Skip to content

Commit dfe2086

Browse files
authored
feat: Support for chunkingInfo in TopicSubmitMessageTransaction (#884)
Signed-off-by: Manish Dait <daitmanish88@gmail.com>
1 parent e533ec8 commit dfe2086

File tree

11 files changed

+928
-173
lines changed

11 files changed

+928
-173
lines changed

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ This changelog is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.
1515
- Added `.github/workflows/merge-conflict-bot.yml` to automatically detect and notify users of merge conflicts in Pull Requests.
1616
- Added `.github/workflows/bot-office-hours.yml` to automate the Weekly Office Hour Reminder.
1717
- feat: Implement account creation with EVM-style alias transaction example.
18-
- Added validation logic in `.github/workflows/pr-checks.yml` to detect when no new chnagelog entries are added under [Unreleased]
18+
- Added validation logic in `.github/workflows/pr-checks.yml` to detect when no new chnagelog entries are added under [Unreleased].
19+
- Support for message chunking in `TopicSubmitMessageTransaction`.
1920

2021
### Changed
2122

@@ -68,6 +69,7 @@ This changelog is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.
6869
- Add `set_token_ids`, `_from_proto`, `_validate_checksum` to TokenAssociateTransaction [#795]
6970
- docs: added `network_and_client.md` with a table of contents, and added external example scripts (`client.py`).
7071

72+
7173
### Changed
7274

7375
- Upgraded step-security/harden-runner v2.13.2

examples/consensus/topic_message.py

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,21 @@ def __init__(self, seconds: int, nanos: int = 0):
2020
self.seconds = seconds
2121
self.nanos = nanos
2222

23+
class MockAccountID:
24+
"""Mocks the protobuf AccountID object."""
25+
def __init__(self, shard, realm, num):
26+
self.shardNum = shard
27+
self.realmNum = realm
28+
self.accountNum = num
29+
self.alias = None
30+
2331
class MockTransactionID:
2432
"""Mocks the protobuf TransactionID object."""
2533
def __init__(self, account_id, seconds, nanos):
2634

27-
self.shardNum = account_id.shard
28-
self.realmNum = account_id.realm
29-
self.accountNum = account_id.num
35+
self.accountID = account_id
3036
self.transactionValidStart = MockTimestamp(seconds, nanos)
37+
self.scheduled = False
3138

3239
class MockChunkInfo:
3340
"""Mocks the protobuf ChunkInfo object."""
@@ -72,13 +79,7 @@ def mock_consensus_response(
7279

7380
chunk_info = None
7481
if is_chunked:
75-
76-
class MockAcct:
77-
shard = 0
78-
realm = 0
79-
num = 10
80-
81-
tx_id = MockTransactionID(MockAcct(), 1736539100, 1) if has_tx_id else None
82+
tx_id = MockTransactionID(MockAccountID(0,0,10), 1736539100, 1) if has_tx_id else None
8283
chunk_info = MockChunkInfo(seq, total_chunks, tx_id)
8384

8485
return MockResponse(message, seq, timestamp, chunk_info)

examples/consensus/topic_message_submit_chunked_transaction.py

Lines changed: 152 additions & 0 deletions
Large diffs are not rendered by default.

src/hiero_sdk_python/client/client.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,10 @@ def _init_mirror_stub(self) -> None:
5353
We now use self.network.get_mirror_address() for a configurable mirror address.
5454
"""
5555
mirror_address = self.network.get_mirror_address()
56-
self.mirror_channel = grpc.secure_channel(mirror_address, grpc.ssl_channel_credentials())
56+
if mirror_address.endswith(':50212') or mirror_address.endswith(':443'):
57+
self.mirror_channel = grpc.secure_channel(mirror_address, grpc.ssl_channel_credentials())
58+
else:
59+
self.mirror_channel = grpc.insecure_channel(mirror_address)
5760
self.mirror_stub = mirror_consensus_grpc.ConsensusServiceStub(self.mirror_channel)
5861

5962
def set_operator(self, account_id: AccountId, private_key: PrivateKey) -> None:

src/hiero_sdk_python/consensus/topic_message.py

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
from hiero_sdk_python.timestamp import Timestamp
1010
from hiero_sdk_python.hapi.mirror import consensus_service_pb2 as mirror_proto
11+
from hiero_sdk_python.transaction.transaction_id import TransactionId
1112

1213

1314
class TopicMessageChunk:
@@ -40,7 +41,7 @@ def __init__(
4041
consensus_timestamp: datetime,
4142
message_data: Dict[str, Union[bytes, int]],
4243
chunks: List[TopicMessageChunk],
43-
transaction_id: Optional[str] = None,
44+
transaction_id: Optional[TransactionId] = None,
4445
) -> None:
4546
"""
4647
Args:
@@ -52,14 +53,14 @@ def __init__(
5253
"sequence_number": int
5354
}
5455
chunks (List[TopicMessageChunk]): All individual chunks that form this message.
55-
transaction_id (Optional[str]): The transaction ID string if available.
56+
transaction_id (Optional[Transaction]): The transaction ID if available.
5657
"""
5758
self.consensus_timestamp: datetime = consensus_timestamp
5859
self.contents: Union[bytes, int] = message_data["contents"]
5960
self.running_hash: Union[bytes, int] = message_data["running_hash"]
6061
self.sequence_number: Union[bytes, int] = message_data["sequence_number"]
6162
self.chunks: List[TopicMessageChunk] = chunks
62-
self.transaction_id: Optional[str] = transaction_id
63+
self.transaction_id: Optional[TransactionId] = transaction_id
6364

6465
@classmethod
6566
def of_single(cls, response: mirror_proto.ConsensusTopicResponse) -> "TopicMessage": # type: ignore
@@ -72,13 +73,9 @@ def of_single(cls, response: mirror_proto.ConsensusTopicResponse) -> "TopicMessa
7273
running_hash: Union[bytes, int] = response.runningHash
7374
sequence_number: Union[bytes, int] = chunk.sequence_number
7475

75-
transaction_id: Optional[str] = None
76+
transaction_id: Optional[TransactionId] = None
7677
if response.HasField("chunkInfo") and response.chunkInfo.HasField("initialTransactionID"):
77-
tx_id = response.chunkInfo.initialTransactionID
78-
transaction_id = (
79-
f"{tx_id.shardNum}.{tx_id.realmNum}.{tx_id.accountNum}-"
80-
f"{tx_id.transactionValidStart.seconds}.{tx_id.transactionValidStart.nanos}"
81-
)
78+
transaction_id = TransactionId._from_proto(response.chunkInfo.initialTransactionID)
8279

8380
return cls(
8481
consensus_timestamp,
@@ -102,25 +99,24 @@ def of_many(cls, responses: List[mirror_proto.ConsensusTopicResponse]) -> "Topic
10299

103100
chunks: List[TopicMessageChunk] = []
104101
total_size: int = 0
105-
transaction_id: Optional[str] = None
106-
102+
transaction_id: Optional[TransactionId] = None
103+
107104
for r in sorted_responses:
108105
c = TopicMessageChunk(r)
109106
chunks.append(c)
107+
110108
total_size += len(r.message)
109+
111110

112111
if (
113112
transaction_id is None
114113
and r.HasField("chunkInfo")
115114
and r.chunkInfo.HasField("initialTransactionID")
116115
):
117-
tx_id = r.chunkInfo.initialTransactionID
118-
transaction_id = (
119-
f"{tx_id.shardNum}.{tx_id.realmNum}.{tx_id.accountNum}-"
120-
f"{tx_id.transactionValidStart.seconds}.{tx_id.transactionValidStart.nanos}"
121-
)
116+
transaction_id = TransactionId._from_proto(r.chunkInfo.initialTransactionID)
122117

123118
contents = bytearray(total_size)
119+
124120
offset: int = 0
125121
for r in sorted_responses:
126122
end = offset + len(r.message)

0 commit comments

Comments
 (0)