TopicCreateTransaction - Test specification
Description:
This test specification for TopicCreateTransaction 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 TopicCreateTransaction. 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 TopicInfoQuery
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/consensus-service/create-a-topic
TopicCreate protobufs:
https://github.com/hashgraph/hedera-protobufs/blob/main/services/consensus_create_topic.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
createTopic
Input Parameters
Parameter Name | Type | Required/Optional | Description/Notes |
---|---|---|---|
memo | string | optional | Short publicly visible memo about the topic. No guarantee of uniqueness. (UTF-8 encoding max 100 bytes) |
adminKey | string | optional | Access control for update/delete of the topic. DER-encoded hex string representation for private or public keys. Keylists and threshold keys are the hex of the serialized protobuf bytes. |
submitKey | string | optional | Access control for submit message. DER-encoded hex string representation for private or public keys. Keylists and threshold keys are the hex of the serialized protobuf bytes. |
autoRenewPeriod | string | required | The amount of time to attempt to extend the topic's lifetime by automatically at the topic's expirationTime. Units of seconds. Min: 6999999 (≈30 days), Max: 8000001 (≈92 days) |
autoRenewAccount | string | optional | Optional account to be used at the topic's expirationTime to extend the life of the topic. Must sign transaction if specified. |
feeScheduleKey | string | optional | A key that controls updates and deletions of topic fees. DER-encoded hex string representation for private or public keys. Keylists and threshold keys are the hex of the serialized protobuf bytes. |
feeExemptKeys | string[] | optional | A list of keys that, if used to sign a message submission, allow the sender to bypass fees. DER-encoded hex string representation for private or public keys. |
customFees | list<json object> | optional | A fee structure applied to message submissions for revenue generation. |
commonTransactionParams | json object | optional |
Output Parameters
Parameter Name | Type | Description/Notes |
---|---|---|
topicId | string | The ID of the created topic. |
status | string | The status of the submitted TopicCreateTransaction (from a TransactionReceipt ). |
Property Tests
Memo:
- Short publicly visible memo about the topic.
Test no | Name | Input | Expected response | Implemented (Y/N) |
---|---|---|---|---|
1 | Creates a topic with valid memo | memo="Test topic memo" | The topic creation succeeds and the topic has the specified memo. | Y |
2 | Creates a topic with empty memo | memo="" | The topic creation succeeds and the topic has no memo. | Y |
3 | Creates a topic with memo at maximum length (100 bytes) | memo=<100_BYTE_STRING> | The topic creation succeeds and the topic has the specified memo. | Y |
4 | Creates a topic with memo exceeding maximum length | memo=<101_BYTE_STRING> | The topic creation fails with MEMO_TOO_LONG . | Y |
5 | Creates a topic with memo containing null byte | memo="Test\0memo" | The topic creation fails with INVALID_ZERO_BYTE_IN_STRING . | Y |
6 | Creates a topic with memo containing only whitespace | memo=" " | The topic creation succeeds and the topic has the whitespace memo. | Y |
7 | Creates a topic with memo containing special characters | memo="!@#$%^&*()_+-=[]{};':",./<>?" | The topic creation succeeds and the topic has the special character memo. | Y |
8 | Creates a topic with memo containing unicode characters | memo="测试主题备注 🚀" | The topic creation succeeds and the topic has the unicode memo. | Y |
AdminKey:
- Access control for update/delete operations on the topic.
Test no | Name | Input | Expected response | Implemented (Y/N) |
---|---|---|---|---|
1 | Creates a topic with valid ED25519 admin key | adminKey=<VALID_ED25519_PUBLIC_KEY> | The topic creation succeeds and the topic has the ED25519 admin key. | Y |
2 | Creates a topic with valid ECDSAsecp256k1 admin key | adminKey=<VALID_ECDSA_SECP256K1_PUBLIC_KEY> | The topic creation succeeds and the topic has the ECDSAsecp256k1 admin key. | Y |
3 | Creates a topic with valid ED25519 private key as admin key | adminKey=<VALID_ED25519_PRIVATE_KEY> | The topic creation succeeds and the topic has the ED25519 private key as its admin key. | Y |
4 | Creates a topic with valid ECDSAsecp256k1 private key as admin key | adminKey=<VALID_ECDSA_SECP256K1_PRIVATE_KEY> | The topic creation succeeds and the topic has the ECDSAsecp256k1 private key as its admin key. | Y |
5 | Creates a topic with valid KeyList as admin key | adminKey=<VALID_KEYLIST> | The topic creation succeeds and the topic has the KeyList as its admin key. | Y |
6 | Creates a topic with valid ThresholdKey as admin key | adminKey=<VALID_THRESHOLD_KEY> | The topic creation succeeds and the topic has the ThresholdKey as its admin key. | Y |
7 | Creates a topic with no admin key | (adminKey not provided) | The topic creation succeeds and the topic has no admin key (immutable except for expiration extension). | Y |
8 | Creates a topic with invalid admin key | adminKey=<INVALID_KEY> | The topic creation fails with an SDK internal error. | Y |
SubmitKey:
- Access control for message submissions to the topic.
Test no | Name | Input | Expected response | Implemented (Y/N) |
---|---|---|---|---|
1 | Creates a topic with valid ED25519 submit key | submitKey=<VALID_ED25519_PUBLIC_KEY> | The topic creation succeeds and the topic has the ED25519 submit key. | Y |
2 | Creates a topic with valid ECDSAsecp256k1 submit key | submitKey=<VALID_ECDSA_SECP256K1_PUBLIC_KEY> | The topic creation succeeds and the topic has the ECDSAsecp256k1 submit key. | Y |
3 | Creates a topic with valid ED25519 private key as submit key | submitKey=<VALID_ED25519_PRIVATE_KEY> | The topic creation succeeds and the topic has the ED25519 private key as its submit key. | Y |
4 | Creates a topic with valid ECDSAsecp256k1 private key as submit key | submitKey=<VALID_ECDSA_SECP256K1_PRIVATE_KEY> | The topic creation succeeds and the topic has the ECDSAsecp256k1 private key as its submit key. | Y |
5 | Creates a topic with valid KeyList as submit key | submitKey=<VALID_KEYLIST> | The topic creation succeeds and the topic has the KeyList as its submit key. | Y |
6 | Creates a topic with valid ThresholdKey as submit key | submitKey=<VALID_THRESHOLD_KEY> | The topic creation succeeds and the topic has the ThresholdKey as its submit key. | Y |
7 | Creates a topic with no submit key | (submitKey not provided) | The topic creation succeeds and the topic has no submit key (open for all message submissions). | Y |
8 | Creates a topic with invalid submit key | submitKey=<INVALID_KEY> | The topic creation fails with an SDK internal error. | Y |
AutoRenewPeriod:
- The amount of time to attempt to extend the topic's lifetime automatically.
Test no | Name | Input | Expected response | Implemented (Y/N) |
---|---|---|---|---|
1 | Creates a topic with valid auto renew period | autoRenewPeriod="7000000" | The topic creation succeeds and the topic has the specified auto renew period. | Y |
2 | Creates a topic with minimum auto renew period | autoRenewPeriod="6999999" | The topic creation succeeds and the topic has the minimum auto renew period. | Y |
3 | Creates a topic with maximum auto renew period | autoRenewPeriod="8000001" | The topic creation succeeds and the topic has the maximum auto renew period. | Y |
4 | Creates a topic with auto renew period below minimum | autoRenewPeriod="2591000" | The topic creation fails with AUTORENEW_DURATION_NOT_IN_RANGE . | Y |
5 | Creates a topic with auto renew period above maximum | autoRenewPeriod="9000000" | The topic creation fails with AUTORENEW_DURATION_NOT_IN_RANGE . | Y |
6 | Creates a topic with auto renew period of zero | autoRenewPeriod="0" | The topic creation fails with AUTORENEW_DURATION_NOT_IN_RANGE . | Y |
7 | Creates a topic with negative auto renew period | autoRenewPeriod="-1" | The topic creation fails with AUTORENEW_DURATION_NOT_IN_RANGE . | Y |
8 | Creates a topic with auto renew period of 9,223,372,036,854,775,807 (int64 max) seconds | autoRenewPeriod="9223372036854775807" | The topic creation fails with AUTORENEW_DURATION_NOT_IN_RANGE . | Y |
9 | Creates a topic with auto renew period of -9,223,372,036,854,775,808 (int64 min) seconds | autoRenewPeriod="-9223372036854775808" | The topic creation fails with AUTORENEW_DURATION_NOT_IN_RANGE . | Y |
10 | Creates a topic without auto renew period | (autoRenewPeriod not provided) | The topic creation succeeds and the SDK sets default value for the auto renew period of 7776000 seconds . | Y |
AutoRenewAccount:
- Optional account to be used at the topic's expirationTime to extend the life of the topic.
Test no | Name | Input | Expected response | Implemented (Y/N) |
---|---|---|---|---|
1 | Creates a topic with valid auto renew account | autoRenewAccount=<VALID_ACCOUNT_ID>, adminKey=<VALID_ADMIN_KEY> | The topic creation succeeds and the topic has the specified auto renew account. | Y |
2 | Creates a topic with non-existent auto renew account | autoRenewAccount="0.0.999999", adminKey=<VALID_ADMIN_KEY> | The topic creation fails with INVALID_AUTORENEW_ACCOUNT . | Y |
3 | Creates a topic with deleted auto renew account | autoRenewAccount=<DELETED_ACCOUNT_ID>, adminKey=<VALID_ADMIN_KEY> | The topic creation fails with INVALID_SIGNATURE . | Y |
4 | Creates a topic with auto renew account but no admin key | autoRenewAccount=<VALID_ACCOUNT_ID> | The topic creation succeeds (newer consensus nodes allow this). | Y |
5 | Creates a topic with no auto renew account | (autoRenewAccount not provided) | the SDK will automatically default to using the transaction fee payer account ID. | Y |
6 | Creates a topic with invalid auto renew account format | autoRenewAccount="invalid", adminKey=<VALID_ADMIN_KEY> | The topic creation fails with an SDK internal error. | Y |
FeeScheduleKey:
- A key that controls updates and deletions of topic fees.
Test no | Name | Input | Expected response | Implemented (Y/N) |
---|---|---|---|---|
1 | Creates a topic with valid ED25519 fee schedule key | feeScheduleKey=<VALID_ED25519_PUBLIC_KEY> | The topic creation succeeds and the topic has the ED25519 fee schedule key. | Y |
2 | Creates a topic with valid ECDSAsecp256k1 fee schedule key | feeScheduleKey=<VALID_ECDSA_SECP256K1_PUBLIC_KEY> | The topic creation succeeds and the topic has the ECDSAsecp256k1 fee schedule key. | Y |
3 | Creates a topic with valid KeyList as fee schedule key | feeScheduleKey=<VALID_KEYLIST> | The topic creation succeeds and the topic has the KeyList as its fee schedule key. | Y |
4 | Creates a topic with valid ThresholdKey as fee schedule key | feeScheduleKey=<VALID_THRESHOLD_KEY> | The topic creation succeeds and the topic has the ThresholdKey as its fee schedule key. | Y |
5 | Creates a topic with no fee schedule key | (feeScheduleKey not provided) | The topic creation succeeds and the topic has no fee schedule key. | Y |
6 | Creates a topic with invalid fee schedule key | feeScheduleKey=<INVALID_KEY> | The topic creation fails with an SDK internal error. | Y |
FeeExemptKeys:
- A list of keys that allow the sender to bypass fees when submitting messages.
Test no | Name | Input | Expected response | Implemented (Y/N) |
---|---|---|---|---|
1 | Creates a topic with single fee exempt key | feeExemptKeys=[<VALID_ED25519_PUBLIC_KEY>] | The topic creation succeeds and the topic has the specified fee exempt key. | Y |
2 | Creates a topic with multiple fee exempt keys | feeExemptKeys=[<VALID_ED25519_PUBLIC_KEY>, <VALID_ECDSA_SECP256K1_PUBLIC_KEY>] | The topic creation succeeds and the topic has all specified fee exempt keys. | Y |
3 | Creates a topic with empty fee exempt keys list | feeExemptKeys=[] | The topic creation succeeds and the topic has no fee exempt keys. | Y |
4 | Creates a topic with no fee exempt keys | (feeExemptKeys not provided) | The topic creation succeeds and the topic has no fee exempt keys. | Y |
5 | Creates a topic with invalid fee exempt key | feeExemptKeys=[<INVALID_KEY>] | The topic creation fails with an SDK internal error. | Y |
CustomFees:
- A fee structure applied to message submissions for revenue generation.
Test no | Name | Input | Expected response | Implemented (Y/N) |
---|---|---|---|---|
1 | Creates a topic with valid HBAR custom fee | customFees=[{feeCollectorAccountId=<VALID_ACCOUNT_ID>, fixedFee.amount="100"}], feeScheduleKey=<VALID_KEY> | The topic creation succeeds and the topic has the specified custom fee. | Y |
2 | Creates a topic with valid token custom fee | customFees=[{feeCollectorAccountId=<VALID_ACCOUNT_ID>, fixedFee.amount="10", fixedFee.denominatingTokenId=<VALID_TOKEN_ID>}], feeScheduleKey=<VALID_KEY> | The topic creation succeeds and the topic has the specified token custom fee. | Y |
3 | Creates a topic with custom fee but no fee schedule key | customFees=[{feeCollectorAccountId=<VALID_ACCOUNT_ID>, fixedFee.amount="100"}] | The topic creation succeeds. | Y |
4 | Creates a topic with multiple custom fees | customFees=[{feeCollectorAccountId=<VALID_ACCOUNT_ID>, fixedFee.amount="100"}, {...}], feeScheduleKey=<VALID_KEY> | The topic creation succeeds and the topic has all specified custom fees. | Y |
5 | Creates a topic with no custom fees | (customFees not provided) | The topic creation succeeds and the topic has no custom fees. | Y |
6 | Creates a topic with invalid custom fee | customFees=[{feeCollectorAccountId="invalid", fixedFee.amount="100"}], feeScheduleKey=<VALID_KEY> | The topic creation fails with an SDK internal error. | Y |
7 | Creates a topic with a fixed fee with an amount of 0 | customFees=[{feeCollectorAccountId=<VALID_ACCOUNT_ID>, fixedFee.amount="0"}], feeScheduleKey=<VALID_KEY> | The topic creation fails with CUSTOM_FEE_MUST_BE_POSITIVE . | Y |
8 | Creates a topic with a fixed fee with an amount of -1 | customFees=[{feeCollectorAccountId=<VALID_ACCOUNT_ID>, fixedFee.amount="-1"}], feeScheduleKey=<VALID_KEY> | The topic creation fails with CUSTOM_FEE_MUST_BE_POSITIVE . | Y |
9 | Creates a topic with a fixed fee with an amount of 9,223,372,036,854,775,807 (int64 max) | customFees=[{feeCollectorAccountId=<VALID_ACCOUNT_ID>, fixedFee.amount="9223372036854775807"}], feeScheduleKey=<VALID_KEY> | The topic creation succeeds and the topic has the custom fixed fee with an amount of 9,223,372,036,854,775,807. | Y |
10 | Creates a topic with a fixed fee with an amount of -9,223,372,036,854,775,808 (int64 min) | customFees=[{feeCollectorAccountId=<VALID_ACCOUNT_ID>, fixedFee.amount="-9223372036854775808"}], feeScheduleKey=<VALID_KEY> | The topic creation fails with CUSTOM_FEE_MUST_BE_POSITIVE . | Y |
11 | Creates a topic with a fixed fee with a fee collector account that doesn't exist | customFees=[{feeCollectorAccountId="123.456.789", fixedFee.amount="100"}], feeScheduleKey=<VALID_KEY> | The topic creation fails with INVALID_CUSTOM_FEE_COLLECTOR . | Y |
12 | Creates a topic with a fixed fee with an empty fee collector account | customFees=[{feeCollectorAccountId="", fixedFee.amount="100"}], feeScheduleKey=<VALID_KEY> | The topic creation fails with an SDK internal error. | Y |
13 | Creates a topic with a fixed fee with a deleted fee collector account | customFees=[{feeCollectorAccountId=<DELETED_ACCOUNT_ID>, fixedFee.amount="100"}], feeScheduleKey=<VALID_KEY> | The topic creation fails with ACCOUNT_DELETED . | Y |
14 | Creates a topic with a fixed fee that is assessed with a token that doesn't exist | customFees=[{feeCollectorAccountId=<VALID_ACCOUNT_ID>, fixedFee.amount="100", fixedFee.denominatingTokenId="123.456.789"}], feeScheduleKey=<VALID_KEY> | The topic creation fails with INVALID_TOKEN_ID_IN_CUSTOM_FEES . | Y |
15 | Creates a topic with a fixed fee that is assessed with a deleted token | customFees=[{feeCollectorAccountId=<VALID_ACCOUNT_ID>, fixedFee.amount="100", fixedFee.denominatingTokenId=<DELETED_TOKEN_ID>}], feeScheduleKey=<VALID_KEY> | The topic creation fails with INVALID_TOKEN_ID_IN_CUSTOM_FEES . | Y |
16 | Creates a topic with fee collectors exempt set to false | customFees=[{feeCollectorAccountId=<VALID_ACCOUNT_ID>, fixedFee.amount="100"}], feeScheduleKey=<VALID_KEY> | The topic creation succeeds and the topic has the custom fee with fee collectors not exempt. | Y |
17 | Creates a topic with more than the maximum amount of fees allowed | customFees=[{feeCollectorAccountId=<VALID_ACCOUNT_ID>, fixedFee.amount="100"} ... (x11)], feeScheduleKey=<VALID_KEY> | The topic creation fails with CUSTOM_FEES_LIST_TOO_LONG . | Y |
18 | Creates a topic with an empty custom fees list | customFees=[], feeScheduleKey=<VALID_KEY> | The topic creation succeeds and the topic has no custom fees. | Y |
JSON Request Example
{
"jsonrpc": "2.0",
"id": 1,
"method": "createTopic",
"params": {
"memo": "Test topic for consensus messages",
"adminKey": "302E020100300506032B657004220420DE6788D0A09F20DED806F446C02FB929D8CD8D17022374AFB3739A1D50BA72C8",
"submitKey": "302E020100300506032B657004220420DE6788D0A09F20DED806F446C02FB929D8CD8D17022374AFB3739A1D50BA72C8",
"autoRenewPeriod": "7000000",
"autoRenewAccount": "0.0.2",
"commonTransactionParams": {
"signers": [
"302E020100300506032B657004220420DE6788D0A09F20DED806F446C02FB929D8CD8D17022374AFB3739A1D50BA72C8"
]
}
}
}
JSON Response Example
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"topicId": "0.0.1234",
"status": "SUCCESS"
}
}