ScheduleCreateTransaction - Test specification
Description:
This test specification for ScheduleCreateTransaction 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 ScheduleCreateTransaction. 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 ScheduleInfoQuery
and investigating for the required changes (creations, updates, etc.).
Transaction properties:
https://docs.hedera.com/hedera/sdks-and-apis/sdks/schedule-transaction/create-a-schedule-transaction
ScheduleCreate protobufs:
https://github.com/hashgraph/hedera-protobufs/blob/main/services/schedule_create.proto
Response codes:
https://github.com/hashgraph/hedera-protobufs/blob/main/services/response_code.proto
JSON-RPC API Endpoint Documentation
Method Name
createSchedule
Input Parameters
Parameter Name | Type | Required/Optional | Description/Notes |
---|---|---|---|
scheduledTransaction | json object | optional | The transaction to schedule. |
memo | string | optional | Short description of the schedule (UTF-8 encoding max 100 bytes) |
adminKey | string | optional | DER-encoded hex string representation for private or public keys. Keylists and threshold keys are the hex of the serialized protobuf bytes. |
payerAccountId | string | optional | ID of the account to pay for the scheduled transaction. |
expirationTime | string | optional | The time at which this schedule should expire (in seconds since the epoch) |
waitForExpiry | bool | optional | Should the schedule wait until its expiration time to execute? |
commonTransactionParams | json object | optional |
Output Parameters
Parameter Name | Type | Description/Notes |
---|---|---|
scheduleId | string | The ID of the created schedule. |
transactionId | string | The ID of the scheduled transaction. |
status | string | The status of the submitted ScheduleCreateTransaction (from a TransactionReceipt ). |
Additional Notes
The tests contained in this specification will assume that scheduled transaction is a basic crypto transfer and it will be represented by a <SCHEDULED_TRANSACTION> tag, unless the test specifies otherwise.
Property Tests
Scheduled Transaction:
- The transaction that is to be scheduled.
Test no | Name | Input | Expected response | Implemented (Y/N) |
---|---|---|---|---|
1 | Creates a scheduled crypto transfer transaction | scheduledTransaction=<CRYPTO_TRANSFER_TRANSACTION> | The schedule creation succeeds and the transaction is scheduled. | Y |
2 | Creates a scheduled consensus submit message transaction | scheduledTransaction=<CONSENSUS_SUBMIT_MESSAGE_TRANSACTION> | The schedule creation succeeds and the transaction is scheduled. | Y |
3 | Creates a scheduled token burn transaction | scheduledTransaction=<TOKEN_BURN_TRANSACTION> | The schedule creation succeeds and the transaction is scheduled. | Y |
4 | Creates a scheduled token mint transaction | scheduledTransaction=<TOKEN_MINT_TRANSACTION> | The schedule creation succeeds and the transaction is scheduled. | Y |
5 | Creates a scheduled crypto approve allowance transaction | scheduledTransaction=<CRYPTO_APPROVE_ALLOWANCE_TRANSACTION> | The schedule creation succeeds and the transaction is scheduled. | Y |
6 | Creates a scheduled transaction with no scheduled transaction | The schedule creation fails with an INVALID_TRANSACTION response code from the network. | Y | |
7 | Creates a scheduled transaction that's not a whitelisted transaction | scheduledTransaction=<TOPIC_CREATE_TRANSACTION> | The schedule creation fails with a SCHEDULED_TRANSACTION_NOT_IN_WHITELIST response code from the network. | Y |
Memo:
- A short description of the schedule.
Test no | Name | Input | Expected response | Implemented (Y/N) |
---|---|---|---|---|
1 | Creates a schedule with valid memo | scheduledTransaction=<SCHEDULED_TRANSACTION>, memo="test memo" | The schedule creation succeeds and the file has the specified memo. | Y |
2 | Creates a schedule with memo at maximum length (100 bytes) | scheduledTransaction=<SCHEDULED_TRANSACTION>, memo=<100_BYTE_STRING> | The schedule creation succeeds and the file has the specified memo. | Y |
3 | Creates a schedule with memo exceeding maximum length | scheduledTransaction=<SCHEDULED_TRANSACTION>, memo=<101_BYTE_STRING> | The schedule creation fails with a MEMO_TOO_LONG response code from the network. | Y |
4 | Creates a schedule with invalid memo | scheduledTransaction=<SCHEDULED_TRANSACTION>, memo="Test\0memo" | The schedule creation fails with a INVALID_ZERO_BYTE_IN_STRING response code from the network. | Y |
5 | Creates a schedule with memo containing only whitespace | scheduledTransaction=<SCHEDULED_TRANSACTION>, memo=" " | The schedule creation succeeds and the file has the whitespace memo. | Y |
6 | Creates a schedule with memo containing special characters | scheduledTransaction=<SCHEDULED_TRANSACTION>, memo="!@#$%^&*()_+-=[]{};':",./<>?" | The schedule creation succeeds and the file has the special character memo. | Y |
7 | Creates a schedule with memo containing unicode characters | scheduledTransaction=<SCHEDULED_TRANSACTION>, memo="测试文件备注 🚀" | The schedule creation succeeds and the file has the unicode memo. | Y |
8 | Creates a schedule with memo containing exactly 100 ASCII characters | scheduledTransaction=<SCHEDULED_TRANSACTION>, memo="a".repeat(100) | The schedule creation succeeds and the file has the 100-character memo. | Y |
9 | Creates a schedule with memo containing exactly 100 UTF-8 bytes (fewer characters) | scheduledTransaction=<SCHEDULED_TRANSACTION>, memo="🚀".repeat(25) | The schedule creation succeeds and the file has the 100-byte memo. | Y |
Admin Key:
- The admin key of the schedule.
Test no | Name | Input | Expected response | Implemented (Y/N) |
---|---|---|---|---|
1 | Creates a schedule with a valid ED25519 public key as its admin key | scheduledTransaction=<SCHEDULED_TRANSACTION>, adminKey=<VALID_ED25519_PUBLIC_KEY>, commonTransactionParams.signers=[<CORRESPONDING_ED25519_PRIVATE_KEY>] | The schedule creation succeeds and the schedule has the new ED25519 key as its admin key. | Y |
2 | Creates a schedule with a valid ECDSAsecp256k1 public key as its admin key | scheduledTransaction=<SCHEDULED_TRANSACTION>, adminKey=<VALID_ECDSA_SECP256K1_PUBLIC_KEY>, commonTransactionParams.signers=[<CORRESPONDING_ECDSA_SECP256K1_PRIVATE_KEY>] | The schedule creation succeeds and the schedule has the new ECDSAsecp256k1 key as its admin key. | Y |
3 | Creates a schedule with a valid ED25519 private key as its admin key | scheduledTransaction=<SCHEDULED_TRANSACTION>, adminKey=<VALID_ED25519_PRIVATE_KEY>, commonTransactionParams.signers=[<CORRESPONDING_ED25519_PRIVATE_KEY>] | The schedule creation succeeds and the schedule has the new ED25519 key as its admin key. | Y |
4 | Creates a schedule with a valid ECDSAsecp256k1 private key as its admin key | scheduledTransaction=<SCHEDULED_TRANSACTION>, adminKey=<VALID_ECDSA_SECP256K1_PRIVATE_KEY>, commonTransactionParams.signers=[<CORRESPONDING_ECDSA_SECP256K1_PRIVATE_KEY>] | The schedule creation succeeds and the schedule has the new ECDSAsecp256k1 key as its admin key. | Y |
5 | Creates a schedule with a valid valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its admin key | scheduledTransaction=<SCHEDULED_TRANSACTION>, adminKey=<VALID_KEYLIST>, commonTransactionParams.signers=[<CORRESPONDING_ED25519_PRIVATE_KEY>] | The schedule creation succeeds and the schedule has the new KeyList as its admin key. | Y |
6 | Creates a schedule with a valid KeyList of nested KeyLists (three levels) as its admin key | scheduledTransaction=<SCHEDULED_TRANSACTION>, adminKey=<VALID_NESTED_KEYLIST>, commonTransactionParams.signers=[<CORRESPONDING_ED25519_PRIVATE_KEY>] | The schedule creation succeeds and the schedule has the new nested KeyList as its admin key. | Y |
7 | Creates a schedule with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its admin key | scheduledTransaction=<SCHEDULED_TRANSACTION>, adminKey=<VALID_THRESHOLD_KEY>, commonTransactionParams.signers=[<CORRESPONDING_ED25519_PRIVATE_KEY>] | The schedule creation succeeds and the schedule has the new ThresholdKey as its admin key. | Y |
8 | Creates a schedule with a valid admin key without signing with the new key | scheduledTransaction=<SCHEDULED_TRANSACTION>, adminKey=<VALID_KEY> | The schedule creation fails with an INVALID_SIGNATURE response code from the network. | Y |
9 | Creates a schedule with a valid public key as its admin key and signs with an incorrect private key | scheduledTransaction=<SCHEDULED_TRANSACTION>, adminKey=<VALID_PUBLIC_KEY>, commonTransactionParams.signers=[<CORRESPONDING_ED25519_PRIVATE_KEY>] | The schedule creation fails with an INVALID_SIGNATURE response code from the network. | Y |
Payer Account ID:
- The ID of the account to pay for the scheduled transaction.
Test no | Name | Input | Expected response | Implemented (Y/N) |
---|---|---|---|---|
1 | Creates a schedule with a payer account ID | scheduledTransaction=<SCHEDULED_TRANSACTION>, payerAccountId=<CREATED_ACCOUNT_ID>, commonTransactionParams.signers=[<ACCOUNT_PRIVATE_KEY>] | The schedule creation succeeds and the transaction has the account ID as its payer account ID. | Y |
2 | Creates a schedule with a payer account ID that doesn't exist | scheduledTransaction=<SCHEDULED_TRANSACTION>, payerAccountId="123.456.789" | The schedule creation fails with an ACCOUNT_ID_DOES_NOT_EXIST response code from the network. | Y |
3 | Creates a schedule with an empty payer account ID | scheduledTransaction=<SCHEDULED_TRANSACTION>, payerAccountId="" | The schedule creation fails with an internal SDK error. | Y |
4 | Creates a schedule with a payer account ID that was deleted | scheduledTransaction=<SCHEDULED_TRANSACTION>, payerAccountId=<DELETED_ACCOUNT_ID>, commonTransactionParams.signers=[<DELETED_ACCOUNT_PRIVATE_KEY>] | The schedule creation succeeds and the transaction has the deleted account ID as its payer account ID. | Y |
5 | Creates a schedule with a payer account ID that doesn't sign | scheduledTransaction=<SCHEDULED_TRANSACTION>, payerAccountId=<CREATED_ACCOUNT_ID> | The schedule creation succeeds and the transaction has the account ID as its payer account ID. | Y |
Expiration Time:
- The time at which the schedule should expire.
Test no | Name | Input | Expected response | Implemented (Y/N) |
---|---|---|---|---|
1 | Creates a schedule with valid expiration time | scheduledTransaction=<SCHEDULED_TRANSACTION>, expirationTime=<CURRENT_TIME + 1800> | The schedule creation succeeds and the file has the specified expiration time. | Y |
2 | Creates a schedule with expiration time in the past | scheduledTransaction=<SCHEDULED_TRANSACTION>, expirationTime=<CURRENT_TIME - 7200> | The schedule creation fails with SCHEDULE_EXPIRATION_TIME_MUST_BE_HIGHER_THAN_CONSENSUS_TIME | Y |
3 | Creates a schedule with expiration time equal to current | scheduledTransaction=<SCHEDULED_TRANSACTION>, expirationTime=<CURRENT_TIME> | The schedule creation fails with SCHEDULE_EXPIRATION_TIME_MUST_BE_HIGHER_THAN_CONSENSUS_TIME | Y |
4 | Creates a schedule with too large expiration time | scheduledTransaction=<SCHEDULED_TRANSACTION>, expirationTime=<CURRENT_TIME + 9000000> | The schedule creation fails with SCHEDULE_EXPIRATION_TIME_TOO_FAR_IN_FUTURE | Y |
5 | Creates a schedule with expiration time of 9,223,372,036,854,775,807 (int64 max) seconds | scheduledTransaction=<SCHEDULED_TRANSACTION>, expirationTime="9223372036854775807" | The schedule creation fails with SCHEDULE_EXPIRATION_TIME_TOO_FAR_IN_FUTURE . | Y |
6 | Creates a schedule with expiration time of 9,223,372,036,854,775,806 (int64 max - 1) seconds | scheduledTransaction=<SCHEDULED_TRANSACTION>, expirationTime="9223372036854775806" | The schedule creation fails with SCHEDULE_EXPIRATION_TIME_TOO_FAR_IN_FUTURE . | Y |
7 | Creates a schedule with expiration time of -9,223,372,036,854,775,808 (int64 min) seconds | scheduledTransaction=<SCHEDULED_TRANSACTION>, expirationTime="-9223372036854775808" | The schedule creation fails with SCHEDULE_EXPIRATION_TIME_MUST_BE_HIGHER_THAN_CONSENSUS_TIME . | Y |
8 | Creates a schedule with expiration time of -9,223,372,036,854,775,807 (int64 min + 1) seconds | scheduledTransaction=<SCHEDULED_TRANSACTION>, expirationTime="-9223372036854775807" | The schedule creation fails with SCHEDULE_EXPIRATION_TIME_MUST_BE_HIGHER_THAN_CONSENSUS_TIME . | Y |
9 | Creates a schedule with expiration time of 5,356,800 seconds from the current time | scheduledTransaction=<SCHEDULED_TRANSACTION>, expirationTime=<CURRENT_TIME + 5356800> | The schedule creation succeeds and the file has the specified expiration time. | Y |
10 | Creates a schedule with expiration time of 5,356,803 seconds from the current time | scheduledTransaction=<SCHEDULED_TRANSACTION>, expirationTime=<CURRENT_TIME + 5356803> | The schedule creation fails with SCHEDULE_EXPIRATION_TIME_TOO_FAR_IN_FUTURE . | Y |
Wait for Expiry:
- Should the scheduled transaction wait until the expiration time to execute?
Test no | Name | Input | Expected response | Implemented (Y/N) |
---|---|---|---|---|
1 | Creates a schedule with wait for expiry | scheduledTransaction=<SCHEDULED_TRANSACTION>, expirationTime=<CURRENT_TIME> + 5184000, waitForExpiry=true | The schedule creation succeeds and the transaction will wait until expiration to execute. | Y |
2 | Creates a schedule with expiration time in the past | scheduledTransaction=<SCHEDULED_TRANSACTION>, expirationTime=<CURRENT_TIME> + 5184000, waitForExpiry=false | The schedule creation succeeds and the transaction will not wait until expiration to execute. | Y |
3 | Creates a schedule with wait for expiry but not expiration time | scheduledTransaction=<SCHEDULED_TRANSACTION>, waitForExpiry=true | The schedule creation fails with MISSING_EXPIRY_TIME . | Y |
JSON Request Example
{
"jsonrpc": "2.0",
"id": 1,
"method": "createSchedule",
"params": {
"scheduledTransaction": {
"maxTransactionFee": "1000000000",
"memo": "This is a scheduled transaction!",
"method": "createAccount",
"params": {
"key": "3030020100300706052b8104000a04220420e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b35",
"initialBalance": "1000000000"
}
},
"memo": "This is the scheduling transaction!",
"adminKey": "3030020100300706052b8104000a04220420e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b35",
"payerAccountId": "0.0.3248",
"expirationTime": "17584768480",
"waitForExpiry": true,
"commonTransactionParams": {
"signers": [
"3030020100300706052b8104000a04220420e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b35",
"3030020100300706052b8104000a04220420e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b35"
]
}
}
}
JSON Response Example
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"scheduleId": "0.0.1234",
"status": "SUCCESS"
}
}