TopicMessageSubmitTransaction - Test specification
Description:
This test specification for TopicMessageSubmitTransaction is to be one of many for testing the functionality of the Hiero 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 TopicMessageSubmitTransaction. 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 (message submissions, 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/submit-a-message
TopicMessageSubmit protobufs:
https://github.com/hashgraph/hedera-protobufs/blob/main/services/consensus_submit_message.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
submitTopicMessage
Input Parameters
| Parameter Name | Type | Required/Optional | Description/Notes |
|---|---|---|---|
| topicId | string | optional | The ID of the topic to submit the message to. |
| message | string | optional | The message content to submit. UTF-8 encoding. Will be automatically chunked if the message exceeds the chunk size. |
| maxChunks | int64 | optional | The maximum number of chunks the message can be split into. Default: 20. Used when message size exceeds chunk size. |
| chunkSize | int64 | optional | The size of each chunk in bytes. Default: SDK-specific chunk size. Used for splitting large messages. |
| customFeeLimits | list<json object> | optional | The maximum custom fees the user is willing to pay for message submission. |
| commonTransactionParams | json object | optional |
Output Parameters
| Parameter Name | Type | Description/Notes |
|---|---|---|
| status | string | The status of the submitted TopicMessageSubmitTransaction (from a TransactionReceipt). |
Additional Notes
The tests contained in this specification will assume that valid topics were already successfully created. Any <CREATED_PUBLIC_TOPIC_ID> tag will be the ID of a public topic (no submit key) that allows message submissions from any account. Any <CREATED_PRIVATE_TOPIC_ID> tag will be the ID of a private topic (with submit key) that requires submit key signature for message submissions.
Property Tests
TopicId:
- The ID of the topic to submit the message to.
| Test no | Name | Input | Expected response | Implemented (Y/N) |
|---|---|---|---|---|
| 1 | Submits a message to a valid public topic | topicId="<CREATED_PUBLIC_TOPIC_ID>", message="Test message" | The message submission succeeds. | Y |
| 2 | Submits a message to a non-existent topic | topicId="0.0.999999", message="Test message" | The message submission fails with INVALID_TOPIC_ID. | Y |
| 3 | Submits a message with invalid topic ID format | topicId="invalid", message="Test message" | The message submission fails with an SDK internal error. | Y |
| 4 | Submits a message without topic ID | message="Test message" | The message submission fails with INVALID_TOPIC_ID. | Y |
| 5 | Submits a message to a deleted topic | topicId="<DELETED_TOPIC_ID>", message="Test message" | The message submission fails with INVALID_TOPIC_ID. | Y |
| 6 | Submits a message to a valid private topic | topicId="<CREATED_PRIVATE_TOPIC_ID>", message="Test message", commonTransactionParams.signers=[<SUBMIT_KEY>] | The message submission succeeds. | Y |
| 7 | Submits a message to a valid private topic without submit key signature | topicId="<CREATED_PRIVATE_TOPIC_ID>", message="Test message" | The message submission fails with INVALID_SIGNATURE. | Y |
Message:
- The message content to submit to the topic.
| Test no | Name | Input | Expected response | Implemented (Y/N) |
|---|---|---|---|---|
| 1 | Submits a valid text message to a public topic | topicId="<CREATED_PUBLIC_TOPIC_ID>", message="Hello, world!" | The message submission succeeds and the message is published to the topic. | Y |
| 2 | Submits an empty message to a public topic | topicId="<CREATED_PUBLIC_TOPIC_ID>", message="" | The message submission fails with an SDK internal error. | Y |
| 3 | Submits a message with special characters to a public topic | topicId="<CREATED_PUBLIC_TOPIC_ID>", message="!@#$%^&*()_+-=[]{};':",./<>?" | The message submission succeeds and the message with special characters is published. | Y |
| 4 | Submits a message with unicode characters to a public topic | topicId="<CREATED_PUBLIC_TOPIC_ID>", message="测试消息 🚀" | The message submission succeeds and the unicode message is published to the topic. | Y |
| 5 | Submits a message at maximum single chunk size to a public topic | topicId="<CREATED_PUBLIC_TOPIC_ID>", message=<MAX_CHUNK_SIZE_MESSAGE> | The message submission succeeds and the message is published as a single chunk. | Y |
| 6 | Submits a message that requires chunking to a public topic | topicId="<CREATED_PUBLIC_TOPIC_ID>", message=<LARGE_MESSAGE> | The message submission succeeds and the message is published as multiple chunks. | Y |
| 7 | Submits a message without message content to a public topic | topicId="<CREATED_PUBLIC_TOPIC_ID>" | The message submission fails with an INVALID_TOPIC_MESSAGE | Y |
| 8 | Submits a message with null bytes to a public topic | topicId="<CREATED_PUBLIC_TOPIC_ID>", message="Test\0message" | The message submission succeeds and the message with null bytes is published. | Y |
| 9 | Submits a message with only whitespace to a public topic | topicId="<CREATED_PUBLIC_TOPIC_ID>", message=" " | The message submission succeeds and the whitespace message is published. | Y |
MaxChunks:
- Maximum number of chunks allowed for this transaction.
| Test no | Name | Input | Expected response | Implemented (Y/N) |
|---|---|---|---|---|
| 1 | Submits to a public topic with default max chunks (20) | topicId="<CREATED_PUBLIC_TOPIC_ID>", message="Test", maxChunks=20 | The message submission succeeds. | Y |
| 2 | Submits to a public topic with custom max chunks | topicId="<CREATED_PUBLIC_TOPIC_ID>", message="Test", maxChunks=10 | The message submission succeeds. | Y |
| 3 | Submits to a public topic with max chunks set to 1 | topicId="<CREATED_PUBLIC_TOPIC_ID>", message="Test", maxChunks=1 | The message submission succeeds for small content. | Y |
| 4 | Submits to a public topic with max chunks set to 0 | topicId="<CREATED_PUBLIC_TOPIC_ID>", message="Test", maxChunks=0 | The message submission fails with an SDK internal error. | Y |
| 5 | Submits to a public topic with max chunks set to negative value | topicId="<CREATED_PUBLIC_TOPIC_ID>", message="Test", maxChunks=-1 | The message submission fails with an SDK internal error. | Y |
| 6 | Submits to a public topic content requiring more chunks than maxChunks | topicId="<CREATED_PUBLIC_TOPIC_ID>", maxChunks=1, message=<LARGE_CONTENT_REQUIRING_MORE_CHUNKS>, chunkSize=1000 | The message submission fails with an SDK internal error. | Y |
ChunkSize:
- Size of each chunk in bytes.
| Test no | Name | Input | Expected response | Implemented (Y/N) |
|---|---|---|---|---|
| 1 | Submits to a public topic with default chunk size | topicId="<CREATED_PUBLIC_TOPIC_ID>", message="Test" | The message submission succeeds. | Y |
| 2 | Submits to a public topic with custom chunk size | topicId="<CREATED_PUBLIC_TOPIC_ID>", message="Test", chunkSize=1024 | The message submission succeeds. | Y |
| 3 | Submits to a public topic with chunk size set to 1 | topicId="<CREATED_PUBLIC_TOPIC_ID>", message="Test", chunkSize=1 | The message submission succeeds. | Y |
| 4 | Submits to a public topic with chunk size set to 0 | topicId="<CREATED_PUBLIC_TOPIC_ID>", message="Test", chunkSize=0 | The message submission fails with an SDK internal error. | Y |
| 5 | Submits to a public topic with chunk size set to negative value | topicId="<CREATED_PUBLIC_TOPIC_ID>", message="Test", chunkSize=-1 | The message submission fails with an SDK internal error. | Y |
| 6 | Submits to a public topic with chunk size larger than content | topicId="<CREATED_PUBLIC_TOPIC_ID>", chunkSize=10000, message="small content" | The message submission succeeds with single chunk. | Y |
CustomFeeLimits:
- The maximum custom fees the user is willing to pay for message submission.
| Test no | Name | Input | Expected response | Implemented (Y/N) |
|---|---|---|---|---|
| 1 | Submits a message to a public topic with Hbar custom fee and sufficient custom fee limit | topicId="<CREATED_PUBLIC_TOPIC_WITH_HBAR_FEE_ID>", message="Test", customFeeLimits=[{maxAmount="100"}] | The message submission succeeds and the account is debited the custom fixed fee amount of Hbar. | Y |
| 2 | Submits a message to a public topic with Hbar custom fee without specifying custom fee limit | topicId="<CREATED_PUBLIC_TOPIC_WITH_HBAR_FEE_ID>", message="Test" | The message submission succeeds and the account is debited the custom fixed fee amount of Hbar. | Y |
| 3 | Submits a message to a public topic with token custom fee and sufficient custom fee limit | topicId="<CREATED_PUBLIC_TOPIC_WITH_TOKEN_FEE_ID>", message="Test", customFeeLimits=[{feeTokenId=<VALID_TOKEN_ID>, maxAmount="50"}] | The message submission succeeds and the account is debited the custom fixed fee amount of the token. | Y |
| 4 | Submits a message to a public topic with token custom fee without specifying custom fee limit | topicId="<CREATED_PUBLIC_TOPIC_WITH_TOKEN_FEE_ID>", message="Test" | The message submission succeeds and the account is debited the custom fixed fee amount of the token. | Y |
| 5 | Submits a message to a public topic with Hbar custom fee when account key is fee exempt | topicId="<CREATED_PUBLIC_TOPIC_WITH_HBAR_FEE_AND_FEE_EXEMPT_KEY_ID>", message="Test", commonTransactionParams.signers=[<FEE_EXEMPT_KEY>] | The message submission succeeds and the account is not debited the custom fixed fee amount of Hbar. | Y |
| 6 | Submits a message to a public topic with token custom fee when account key is fee exempt | topicId="<CREATED_PUBLIC_TOPIC_WITH_TOKEN_FEE_AND_FEE_EXEMPT_KEY_ID>", message="Test", commonTransactionParams.signers=[<FEE_EXEMPT_KEY>] | The message submission succeeds and the account is not debited the custom fixed fee amount of the token. | Y |
| 7 | Submits a message to a public topic with Hbar custom fee and insufficient custom fee limit | topicId="<CREATED_PUBLIC_TOPIC_WITH_HBAR_FEE_ID>", message="Test", customFeeLimits=[{maxAmount="1"}] | The message submission fails with MAX_CUSTOM_FEE_LIMIT_EXCEEDED. | Y |
| 8 | Submits a message to a public topic with token custom fee and insufficient custom fee limit | topicId="<CREATED_PUBLIC_TOPIC_WITH_TOKEN_FEE_ID>", message="Test", customFeeLimits=[{feeTokenId=<VALID_TOKEN_ID>, maxAmount="1"}] | The message submission fails with MAX_CUSTOM_FEE_LIMIT_EXCEEDED. | Y |
| 9 | Submits a message to a public topic with token custom fee and invalid token ID in custom fee limit | topicId="<CREATED_PUBLIC_TOPIC_WITH_TOKEN_FEE_ID>", message="Test", customFeeLimits=[{feeTokenId="0.0.999999", maxAmount="100"}] | The message submission fails with NO_VALID_MAX_CUSTOM_FEE. | Y |
| 10 | Submits a message to a public topic with duplicate denominations in custom fee limits | topicId="<CREATED_PUBLIC_TOPIC_WITH_TOKEN_FEE_ID>", message="Test", customFeeLimits=[{feeTokenId=<VALID_TOKEN_ID>, maxAmount="100"}, {feeTokenId=<VALID_TOKEN_ID>, maxAmount="200"}] | The message submission fails with DUPLICATE_DENOMINATION_IN_MAX_CUSTOM_FEE_LIST. | Y |
| 11 | Submits a message to a public topic with multiple custom fee limits | topicId="<CREATED_PUBLIC_TOPIC_WITH_MULTIPLE_FEES_ID>", message="Test", customFeeLimits=[{maxAmount="100"}, {feeTokenId=<VALID_TOKEN_ID>, maxAmount="50"}] | The message submission succeeds. | Y |
| 12 | Submits a message to a public topic with empty custom fee limits | topicId="<CREATED_PUBLIC_TOPIC_WITH_FEES_ID>", message="Test", customFeeLimits=[] | The message submission succeeds if no custom fees are required. | Y |
| 13 | Submits a message to a public topic with invalid token ID in custom fee limit | topicId="<CREATED_PUBLIC_TOPIC_WITH_FEES_ID>", message="Test", customFeeLimits=[{feeTokenId="invalid", maxAmount="100"}] | The message submission fails with an SDK internal error. | Y |
| 14 | Submits a message to a public topic with negative custom fee limit amount | topicId="<CREATED_PUBLIC_TOPIC_WITH_FEES_ID>", message="Test", customFeeLimits=[{feeTokenId=<VALID_TOKEN_ID>, maxAmount="-1"}] | The message submission fails with INVALID_MAX_CUSTOM_FEES | Y |
JSON Request Example
{
"jsonrpc": "2.0",
"id": 1,
"method": "submitTopicMessage",
"params": {
"topicId": "0.0.1234",
"message": "Hello World",
"maxChunks": 20,
"chunkSize": 1024,
"commonTransactionParams": {
"signers": [
"302E020100300506032B657004220420DE6788D0A09F20DED806F446C02FB929D8CD8D17022374AFB3739A1D50BA72C8"
]
}
}
}
JSON Response Example
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"status": "SUCCESS",
"topicSequenceNumber": "42",
"topicRunningHash": "0x1234567890abcdef..."
}
}