AccountUpdateTransaction - Test specification
Description:
This test specification for AccountUpdateTransaction is to be one of many for testing the functionality of the Hedera SDKs. The SDK under test will use the language specific JSON-RPC server return responses back to the test driver.
Design:
Each test within the test specification is linked to one of the properties within AccountUpdateTransaction. Each property is tested with a mix of boundaries. The inputs for each test are a range of valid, minimum, maximum, negative and invalid values for the method. The expected response of a passed test can be a correct error response code or seen as the result of node queries. A successful transaction (the transaction reached consensus and was applied to state) can be determined by getting a TransactionReceipt
or TransactionRecord
, or can be determined by using queries such as AccountInfoQuery
or AccountBalanceQuery
and investigating for the required changes (creations, updates, etc.). The mirror node can also be used to determine if a transaction was successful via its rest API. Error codes are obtained from the response code proto files.
Transaction properties:
https://docs.hedera.com/hedera/sdks-and-apis/sdks/accounts-and-hbar/update-an-account
CryptoUpdate protobufs:
https://github.com/hashgraph/hedera-protobufs/blob/main/services/crypto_update.proto
Response codes:
https://github.com/hashgraph/hedera-protobufs/blob/main/services/response_code.proto
Mirror Node APIs:
https://docs.hedera.com/hedera/sdks-and-apis/rest-api
JSON-RPC API Endpoint Documentation
Method Name
updateAccount
Input Parameters
Parameter Name | Type | Required/Optional | Description/Notes |
---|---|---|---|
accountId | string | optional | The ID of the account to update. |
key | string | optional | DER-encoded hex string representation for private or public keys. KeyLists and ThresholdKeys are the hex of the serialized protobuf bytes. |
autoRenewPeriod | string | optional | Units of seconds |
expirationTime | string | optional | Epoch time in seconds |
receiverSignatureRequired | bool | optional | |
memo | string | optional | |
maxAutoTokenAssociations | int32 | optional | |
stakedAccountId | string | optional | |
stakedNodeId | string | optional | |
declineStakingReward | bool | optional | |
commonTransactionParams | json object | optional |
Output Parameters
Parameter Name | Type | Description/Notes |
---|---|---|
status | string | The status of the submitted AccountUpdateTransaction (from a TransactionReceipt ). |
Additional Notes
The tests contained in this specification will assume that a valid account was already successfully created. Assume that the account was created with default values, unless specified otherwise. Any <CREATED_ACCOUNT_ID>
tag will be the account ID of this created account. Any <PRIVATE_KEY_OF_CREATED_ACCOUNT>
is the DER-encoded hex string of the private key of the account.
Property Tests
Account ID:
- The ID of the account to update.
Test no | Name | Input | Expected response | Implemented (Y/N) |
---|---|---|---|---|
1 | Updates an account with no updates | accountId=<CREATED_ACCOUNT_ID>, commonTransactionParams.signers=[<PRIVATE_KEY_OF_CREATED_ACCOUNT>] | The account update succeeds. | Y |
2 | Updates an account with no updates without signing with the account's private key | accountId=<CREATED_ACCOUNT_ID> | The account update fails with an INVALID_SIGNATURE response code from the network. | Y |
3 | Updates an account with no account ID | The account update fails with an ACCOUNT_ID_DOES_NOT_EXIST response code from the network. | Y |
JSON Request Example
{
"jsonrpc": "2.0",
"id": 541,
"method": "updateAccount",
"params": {
"accountId": "0.0.15432"
}
}
JSON Response Example
{
"jsonrpc": "2.0",
"id": 541,
"result": {
"status": "SUCCESS"
}
}
Key:
- The desired new key of the account.
Test no | Name | Input | Expected response | Implemented (Y/N) |
---|---|---|---|---|
1 | Updates the key of an account to a new valid ED25519 public key | accountId=<CREATED_ACCOUNT_ID>, key=<VALID_ED25519_PUBLIC_KEY>, commonTransactionParams.signers=[<PRIVATE_KEY_OF_CREATED_ACCOUNT>, <CORRESPONDING_VALID_ED25519_PRIVATE_KEY>] | The account update succeeds and the account has the new ED25519 key. | Y |
2 | Updates the key of an account to a new valid ECDSAsecp256k1 public key | accountId=<CREATED_ACCOUNT_ID>, key=<VALID_ECDSA_SECP256K1_PUBLIC_KEY>, commonTransactionParams.signers=[<PRIVATE_KEY_OF_CREATED_ACCOUNT>, <CORRESPONDING_VALID_ECDSA_SECP256K1_PRIVATE_KEY>] | The account update succeeds and the account has the new ECDSAsecp256k1 key. | Y |
3 | Updates the key of an account to a new valid ED25519 private key | accountId=<CREATED_ACCOUNT_ID>, key=<VALID_ED25519_PRIVATE_KEY>, commonTransactionParams.signers=[<PRIVATE_KEY_OF_CREATED_ACCOUNT>, <VALID_ED25519_PRIVATE_KEY>] | The account update succeeds and the account has the new ED25519 key. | Y |
4 | Updates the key of an account to a new valid ECDSAsecp256k1 private key | accountId=<CREATED_ACCOUNT_ID>, key=<VALID_ECDSA_SECP256K1_PRIVATE_KEY>, commonTransactionParams.signers=[<PRIVATE_KEY_OF_CREATED_ACCOUNT>, <VALID_ECDSA_SECP256K1_PRIVATE_KEY>] | The account update succeeds and the account has the new ECDSAsecp256k1 key. | Y |
5 | Updates the key of an account to a new valid valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys | accountId=<CREATED_ACCOUNT_ID>, key=<VALID_KEYLIST>, commonTransactionParams.signers=[<PRIVATE_KEY_OF_CREATED_ACCOUNT>, <VALID_KEYLIST>] | The account update succeeds and the account has the new KeyList. | Y |
6 | Updates the key of an account to a new valid KeyList of nested KeyLists (three levels) | accountId=<CREATED_ACCOUNT_ID>, key=<VALID_NESTED_KEYLIST>, commonTransactionParams.signers=[<PRIVATE_KEY_OF_CREATED_ACCOUNT>, <VALID_NESTED_KEYLIST>] | The account update succeeds and the account has the new nested KeyList. | Y |
7 | Updates the key of an account to a new valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys | accountId=<CREATED_ACCOUNT_ID>, key=<VALID_THRESHOLD_KEY>, commonTransactionParams.signers=[<PRIVATE_KEY_OF_CREATED_ACCOUNT>, <VALID_THRESHOLD_KEY>] | The account update succeeds and the account has the new ThresholdKey. | Y |
8 | Updates the key of an account to a new valid key without signing with the new key | accountId=<CREATED_ACCOUNT_ID>, key=<VALID_KEY>, commonTransactionParams.signers=[<PRIVATE_KEY_OF_CREATED_ACCOUNT>] | The account update fails with a INVALID_SIGNATURE response code from the network. | Y |
9 | Updates the key of an account to a new valid public key and signs with an incorrect private key | accountId=<CREATED_ACCOUNT_ID>, key=<VALID_PUBLIC_KEY>, commonTransactionParams.signers=[<PRIVATE_KEY_OF_CREATED_ACCOUNT>, <DIFFERENT_VALID_PRIVATE_KEY>] | The account update fails with response code INVALID_SIGNATURE | Y |
JSON Request Example
{
"jsonrpc": "2.0",
"id": 538,
"method": "updateAccount",
"params": {
"accountId": "0.0.768",
"key": "302A300506032B6570032100EA746B07CFA75F9273BDC3F2495A43DE15720719DA6ED70AEC2D829ACC6A4ECD",
"commonTransactionParams": {
"signers": [
"302E020100300506032B657004220420DE6788D0A09F20DED806F446C02FB929D8CD8D17022374AFB3739A1D50BA72C8",
"302E020100300506032B657004220420C212D124233D70BA8F6F07BF01A44E98418799E3F8ABD2B42C69EC03B53A4E1B"
]
}
}
}
JSON Response Example
{
"jsonrpc": "2.0",
"id": 538,
"result": {
"status": "SUCCESS"
}
}
Auto Renew Period:
- The desired new auto-renew period for the account. The account is charged to extend its expiration date every ‘this many’ seconds. If it doesn't have enough balance, it extends as long as possible. If it is empty when it expires, then it is deleted.
Test no | Name | Input | Expected response | Implemented (Y/N) |
---|---|---|---|---|
1 | Updates the auto-renew period of an account to 60 days (5,184,000 seconds) | accountId=<CREATED_ACCOUNT_ID>, autoRenewPeriod="5184000", commonTransactionParams.signers=[<PRIVATE_KEY_OF_CREATED_ACCOUNT>] | The account update succeeds and the account's auto renew period should equal 5,184,000 seconds. | Y |
2 | Updates the auto-renew period of an account to -1 seconds | accountId=<CREATED_ACCOUNT_ID>, autoRenewPeriod="-1", commonTransactionParams.signers=[<PRIVATE_KEY_OF_CREATED_ACCOUNT>] | The account update fails with an INVALID_RENEWAL_PERIOD response code from the network. | Y |
3 | Updates the auto-renew period of an account to the minimum period of 30 days (2,592,000 seconds) | accountId=<CREATED_ACCOUNT_ID>, autoRenewPeriod="2592000", commonTransactionParams.signers=[<PRIVATE_KEY_OF_CREATED_ACCOUNT>] | The account update succeeds and the account's auto renew period should equal 2,592,000 seconds. | Y |
4 | Updates the auto-renew period of an account to the minimum period of 30 days minus one second (2,591,999 seconds) | accountId=<CREATED_ACCOUNT_ID>, autoRenewPeriod="2591999", commonTransactionParams.signers=[<PRIVATE_KEY_OF_CREATED_ACCOUNT>] | The account update fails with an AUTORENEW_DURATION_NOT_IN_RANGE response code from the network. | Y |
5 | Updates the auto-renew period of an account to the maximum period of 8,000,001 seconds | accountId=<CREATED_ACCOUNT_ID>, autoRenewPeriod="8000001", commonTransactionParams.signers=[<PRIVATE_KEY_OF_CREATED_ACCOUNT>] | The account update succeeds and the account's auto renew period should equal 8,000,001 seconds. | Y |
6 | Updates the auto-renew period of an account to the maximum period plus one second (8,000,002 seconds) | accountId=<CREATED_ACCOUNT_ID>, autoRenewPeriod="8000002", commonTransactionParams.signers=[<PRIVATE_KEY_OF_CREATED_ACCOUNT>] | The account update fails with an AUTORENEW_DURATION_NOT_IN_RANGE response code from the network. | Y |
JSON Request Example
{
"jsonrpc": "2.0",
"id": 6412,
"method": "updateAccount",
"params": {
"accountId": "0.0.32511",
"autoRenewPeriod": "5184000",
"commonTransactionParams": {
"signers": [
"302E020100300506032B657004220420DE6788D0A09F20DED806F446C02FB929D8CD8D17022374AFB3739A1D50BA72C8"
]
}
}
}
JSON Response Example
{
"jsonrpc": "2.0",
"id": 6412,
"result": {
"status": "SUCCESS"
}
}
Expiration Time:
- The desired new expiration time of the account. This is the time at which the account will expire and attempt to extend its expiration date.
Test no | Name | Input | Expected response | Implemented (Y/N) |
---|---|---|---|---|
1 | Updates the expiration time of an account to 8,000,001 seconds from the current time | accountId=<CREATED_ACCOUNT_ID>, expirationTime="<CURRENT_TIME> + 8000001", commonTransactionParams.signers=[<PRIVATE_KEY_OF_CREATED_ACCOUNT>] | The account update succeeds and the account's expiration time should equal 8,000,001 seconds from the current time. | Y |
2 | Updates the expiration time of an account to -1 seconds | accountId=<CREATED_ACCOUNT_ID>, expirationTime="-1", commonTransactionParams.signers=[<PRIVATE_KEY_OF_CREATED_ACCOUNT>] | The account update fails with an INVALID_EXPIRATION_TIME response code from the network. | Y |
3 | Updates the expiration time of an account to 1 second less than its current expiration time | accountId=<CREATED_ACCOUNT_ID>, expirationTime="<CURRENT_EXPIRATION_TIME> - 1", commonTransactionParams.signers=[<PRIVATE_KEY_OF_CREATED_ACCOUNT>] | The account update fails with an EXPIRATION_REDUCTION_NOT_ALLOWED response code from the network. | Y |
4 | Updates the expiration time of an account to 8,000,002 seconds from the current time | accountId=<CREATED_ACCOUNT_ID>, expirationTime="<CURRENT_TIME> + 8000002", commonTransactionParams.signers=[<PRIVATE_KEY_OF_CREATED_ACCOUNT>] | The account update fails with an INVALID_EXPIRATION_TIME response code from the network. | Y |
JSON Request Example
{
"jsonrpc": "2.0",
"id": 12137,
"method": "updateAccount",
"params": {
"accountId": "0.0.8993",
"expirationTime": "5184000",
"commonTransactionParams": {
"signers": [
"302E020100300506032B657004220420C212D124233D70BA8F6F07BF01A44E98418799E3F8ABD2B42C69EC03B53A4E1B"
]
}
}
}
JSON Response Example
{
"jsonrpc": "2.0",
"id": 12137,
"result": {
"status": "SUCCESS"
}
}
Receiver Signature Required:
- The desired new receiver signature required policy for the account. If true, this account's key must sign any transaction depositing into this account (in addition to all withdrawals).
Test no | Name | Input | Expected response | Implemented (Y/N) |
---|---|---|---|---|
1 | Updates the receiver signature required policy of an account to require a receiving signature | accountId=<CREATED_ACCOUNT_ID>, receiverSignatureRequired=true, commonTransactionParams.signers=[<PRIVATE_KEY_OF_CREATED_ACCOUNT>] | The account update succeeds and the account requires a receiving signature. | Y |
2 | Updates the receiver signature required policy of an account to not require a receiving signature | accountId=<CREATED_ACCOUNT_ID>, receiverSignatureRequired=false, commonTransactionParams.signers=[<PRIVATE_KEY_OF_CREATED_ACCOUNT>] | The account update succeeds and the account doesn't require a receiving signature. | Y |
JSON Request Example
{
"jsonrpc": "2.0",
"id": 7546,
"method": "updateAccount",
"params": {
"accountId": "0.0.5483",
"receiverSignatureRequired": true,
"commonTransactionParams": {
"signers": [
"302e020100300506032b65700422042031f8eb3e77a04ebe599c51570976053009e619414f26bdd39676a5d3b2782a1d"
]
}
}
}
JSON Response Example
{
"jsonrpc": "2.0",
"id": 7546,
"result": {
"status": "SUCCESS"
}
}
Memo:
- The desired new memo of the account (UTF-8 encoding max 100 bytes).
Test no | Name | Input | Expected response | Implemented (Y/N) |
---|---|---|---|---|
1 | Updates the memo of an account to a memo that is a valid length | accountId=<CREATED_ACCOUNT_ID>, memo="testmemo", commonTransactionParams.signers=[<PRIVATE_KEY_OF_CREATED_ACCOUNT>] | The account update succeeds and the account's memo equals “testmemo”. | Y |
2 | Updates the memo of an account to a memo that is the minimum length | accountId=<CREATED_ACCOUNT_ID>, memo="", commonTransactionParams.signers=[<PRIVATE_KEY_OF_CREATED_ACCOUNT>] | The account update succeeds and the account's memo is empty. | Y |
3 | Updates the memo of an account to a memo that is the maximum length | accountId=<CREATED_ACCOUNT_ID>, memo="This is a really long memo but it is still valid because it is 100 characters exactly on the money!!", commonTransactionParams.signers=[<PRIVATE_KEY_OF_CREATED_ACCOUNT>] | The account update succeeds and the account's memo equals "This is a really long memo but it is still valid because it is 100 characters exactly on the money!!". | Y |
4 | Updates the memo of an account to a memo that exceeds the maximum length | accountId=<CREATED_ACCOUNT_ID>, memo="This is a long memo that is not valid because it exceeds 100 characters and it should fail the test!!", commonTransactionParams.signers=[<PRIVATE_KEY_OF_CREATED_ACCOUNT>] | The account update fails with a MEMO_TOO_LONG response code from the network. | Y |
JSON Request Example
{
"jsonrpc": "2.0",
"id": 5429,
"method": "updateAccount",
"params": {
"accountId": "0.0.553",
"memo": "testmemo",
"commonTransactionParams": {
"signers": [
"302e020100300506032b65700422042031f8eb3e77a04ebe599c51570976053009e619414f26bdd39676a5d3b2782a1d"
]
}
}
}
JSON Response Example
{
"jsonrpc": "2.0",
"id": 5429,
"result": {
"status": "SUCCESS"
}
}
Max Automatic Token Associations:
- The new desired max automatic token associations for the account. The maximum number of tokens with which an account can be implicitly associated. Defaults to 0 and up to a maximum value of 5000.
Test no | Name | Input | Expected response | Implemented (Y/N) |
---|---|---|---|---|
1 | Updates the max automatic token associations of an account to a valid amount | accountId=<CREATED_ACCOUNT_ID>, maxAutoTokenAssociations=100, commonTransactionParams.signers=[<PRIVATE_KEY_OF_CREATED_ACCOUNT>], commonTransactionParams.maxTransactionFee=100000000000 | The account update succeeds and the account has 100 automatic token associations. | Y |
2 | Updates the max automatic token associations of an account to the minimum amount | accountId=<CREATED_ACCOUNT_ID>, maxAutoTokenAssociations=0, commonTransactionParams.signers=[<PRIVATE_KEY_OF_CREATED_ACCOUNT>] | The account update succeeds and the account has 0 automatic token associations. | Y |
3 | Updates the max automatic token associations of an account to the maximum amount | accountId=<CREATED_ACCOUNT_ID>, maxAutoTokenAssociations=5000, commonTransactionParams.signers=[<PRIVATE_KEY_OF_CREATED_ACCOUNT>], commonTransactionParams.maxTransactionFee=100000000000 | The account update succeeds and the account has 5000 automatic token associations. | Y |
4 | Updates the max automatic token associations of an account to an amount that exceeds the maximum amount | accountId=<CREATED_ACCOUNT_ID>, maxAutoTokenAssociations=5001, commonTransactionParams.signers=[<PRIVATE_KEY_OF_CREATED_ACCOUNT>], commonTransactionParams.maxTransactionFee=100000000000 | The account update fails with a REQUESTED_NUM_AUTOMATIC_ASSOCIATIONS_EXCEEDS_ASSOCIATION_LIMIT response code from the network. | Y |
JSON Request Example
{
"jsonrpc": "2.0",
"id": 12116,
"method": "updateAccount",
"params": {
"accountId": "0.0.53671",
"maxAutoTokenAssociations": 100,
"commonTransactionParams": {
"signers": [
"302e020100300506032b65700422042031f8eb3e77a04ebe599c51570976053009e619414f26bdd39676a5d3b2782a1d"
]
}
}
}
JSON Response Example
{
"jsonrpc": "2.0",
"id": 12116,
"result": {
"status": "SUCCESS"
}
}
Staked ID:
- The ID of the new desired account to which the account is staked.
- OR
- The ID of the new desired node to which this account is staked.
Test no | Name | Input | Expected response | Implemented (Y/N) |
---|---|---|---|---|
1 | Updates the staked account ID of an account to the operators account ID | accountId=<CREATED_ACCOUNT_ID>, stakedAccountId=<OPERATOR_ACCOUNT_ID>, commonTransactionParams.signers=[<PRIVATE_KEY_OF_CREATED_ACCOUNT>] | The account update succeeds and the account has a staking account ID equal to the input account ID. | Y |
2 | Updates the staked node ID of an account to a valid node ID | accountId=<CREATED_ACCOUNT_ID>, stakedNodeId=<VALID_NETWORK_NODE_ID>, commonTransactionParams.signers=[<PRIVATE_KEY_OF_CREATED_ACCOUNT>] | The account update succeeds and the account has a staking node ID equal to the input node ID. | Y |
3 | Updates the staked account ID of an account to an account ID that doesn't exist | accountId=<CREATED_ACCOUNT_ID>, stakedAccountId="123.456.789", commonTransactionParams.signers=[<PRIVATE_KEY_OF_CREATED_ACCOUNT>] | The account update fails with an INVALID_STAKING_ID response code from the network. | Y |
4 | Updates the staked account ID of an account to a node ID that doesn't exist | accountId=<CREATED_ACCOUNT_ID>, stakedNodeId="123456789", commonTransactionParams.signers=[<PRIVATE_KEY_OF_CREATED_ACCOUNT>] | The account update fails with an INVALID_STAKING_ID response code from the network. | Y |
5 | Updates the staked account ID of an account to an empty account ID | accountId=<CREATED_ACCOUNT_ID>, stakedAccountId="", commonTransactionParams.signers=[<PRIVATE_KEY_OF_CREATED_ACCOUNT>] | The account update fails with and SDK internal error. | Y |
6 | Updates the staked account ID of an account to an invalid node ID | accountId=<CREATED_ACCOUNT_ID>, stakedNodeId="-100", commonTransactionParams.signers=[<PRIVATE_KEY_OF_CREATED_ACCOUNT>] | The account update fails with an INVALID_STAKING_ID response code from the network. | Y |
JSON Request Examples
{
"jsonrpc": "2.0",
"id": 78190,
"method": "updateAccount",
"params": {
"accountId": "0.0.7388",
"stakedAccountId": "0.0.3",
"commonTransactionParams": {
"signers": [
"302e020100300506032b65700422042031f8eb3e77a04ebe599c51570976053009e619414f26bdd39676a5d3b2782a1d"
]
}
}
}
{
"jsonrpc": "2.0",
"id": 78190,
"method": "updateAccount",
"params": {
"accountId": "0.0.7388",
"stakedNodeId": "10",
"commonTransactionParams": {
"signers": [
"302e020100300506032b65700422042031f8eb3e77a04ebe599c51570976053009e619414f26bdd39676a5d3b2782a1d"
]
}
}
}
JSON Response Example
{
"jsonrpc": "2.0",
"id": 78190,
"result": {
"status": "SUCCESS"
}
}
Decline Reward:
- The new desired decline rewards policy for the account. If true, the account declines receiving a staking reward.
Test no | Name | Input | Expected response | Implemented (Y/N) |
---|---|---|---|---|
1 | Updates the decline reward policy of an account to decline staking rewards | accountId=<CREATED_ACCOUNT_ID>, declineStakingRewards=true, commonTransactionParams.signers=[<PRIVATE_KEY_OF_CREATED_ACCOUNT>] | The account update succeeds and the account declines staking rewards. | Y |
2 | Updates the decline reward policy of an account to not decline staking rewards | accountId=<CREATED_ACCOUNT_ID>, declineStakingRewards=false, commonTransactionParams.signers=[<PRIVATE_KEY_OF_CREATED_ACCOUNT>] | The account update succeeds and the account doesn't decline staking rewards. | Y |
JSON Request Example
{
"jsonrpc": "2.0",
"id": 6539,
"method": "updateAccount",
"params": {
"accountId": "0.0.983",
"declineStakingRewards": true,
"commonTransactionParams": {
"signers": [
"302e020100300506032b65700422042031f8eb3e77a04ebe599c51570976053009e619414f26bdd39676a5d3b2782a1d"
]
}
}
}
JSON Response Example
{
"jsonrpc": "2.0",
"id": 6539,
"result": {
"status": "SUCCESS"
}
}