From 90c4560262f99aa4994ea803bf0fcbf0e412585b Mon Sep 17 00:00:00 2001 From: Manish Dait Date: Wed, 11 Feb 2026 20:34:58 +0530 Subject: [PATCH 01/25] chore: added some helper method Signed-off-by: Manish Dait --- diff.txt | 0 ...opic_message_submit_chunked_transaction.py | 19 +++++++++++++++---- examples/test.py | 16 ++++++++++++++++ .../topic_message_submit_transaction.py | 15 +++++++++++++++ .../transaction/transaction.py | 12 +++++++++++- .../transaction/transaction_record.py | 1 + 6 files changed, 58 insertions(+), 5 deletions(-) create mode 100644 diff.txt create mode 100644 examples/test.py diff --git a/diff.txt b/diff.txt new file mode 100644 index 000000000..e69de29bb diff --git a/examples/consensus/topic_message_submit_chunked_transaction.py b/examples/consensus/topic_message_submit_chunked_transaction.py index 63d24e8d4..8d1e7ada1 100644 --- a/examples/consensus/topic_message_submit_chunked_transaction.py +++ b/examples/consensus/topic_message_submit_chunked_transaction.py @@ -17,6 +17,7 @@ TopicInfoQuery, TopicMessageSubmitTransaction, ) +from hiero_sdk_python.consensus.topic_id import TopicId BIG_CONTENT = """ @@ -127,10 +128,20 @@ def fetch_topic_info(client, topic_id): def main(): """Create a topic and submit a large multi-chunk message to it.""" client = setup_client() - topic_id = create_topic(client) - fetch_topic_info(client, topic_id) - submit_topic_message_transaction(client, topic_id) - fetch_topic_info(client, topic_id) + # topic_id = create_topic(client) + # fetch_topic_info(client, topic_id) + # submit_topic_message_transaction(client, topic_id) + # fetch_topic_info(client, topic_id) + tx = ( + TopicMessageSubmitTransaction() + .set_topic_id(TopicId.from_string("0.0.7895219")) + .set_message(BIG_CONTENT) + .freeze_with(client) + ) + + print(tx.get_size()) + print(tx.get_body_size()) + print(tx.get_body_size_all_chunks()) if __name__ == "__main__": diff --git a/examples/test.py b/examples/test.py new file mode 100644 index 000000000..8344fa870 --- /dev/null +++ b/examples/test.py @@ -0,0 +1,16 @@ +from hiero_sdk_python.account.account_create_transaction import AccountCreateTransaction +from hiero_sdk_python.client.client import Client +from hiero_sdk_python.crypto.private_key import PrivateKey + + +def main(): + client = Client.from_env() + tx = AccountCreateTransaction().set_key_without_alias(PrivateKey.generate()).freeze_with(client) + + + print(tx.get_size()) + print(tx.get_body_size()) + + +if __name__ == "__main__": + main() diff --git a/src/hiero_sdk_python/consensus/topic_message_submit_transaction.py b/src/hiero_sdk_python/consensus/topic_message_submit_transaction.py index d79c2415f..fb07ff121 100644 --- a/src/hiero_sdk_python/consensus/topic_message_submit_transaction.py +++ b/src/hiero_sdk_python/consensus/topic_message_submit_transaction.py @@ -404,3 +404,18 @@ def sign(self, private_key: PrivateKey): super().sign(private_key) return self + + def get_body_size_all_chunks(self) -> List[int]: + """ + """ + self._require_frozen() + sizes = [] + + original_index = self._current_index + for transaction_id in self._transaction_ids: + self.transaction_id = transaction_id + sizes.append(self.get_body_size()) + + self._current_index = original_index + return sizes + \ No newline at end of file diff --git a/src/hiero_sdk_python/transaction/transaction.py b/src/hiero_sdk_python/transaction/transaction.py index 14691e09a..91b4e51d1 100644 --- a/src/hiero_sdk_python/transaction/transaction.py +++ b/src/hiero_sdk_python/transaction/transaction.py @@ -412,7 +412,7 @@ def is_signed_by(self, public_key): return any(sig_pair.pubKeyPrefix == public_key_bytes for sig_pair in sig_map.sigPair) - def build_transaction_body(self): + def build_transaction_body(self) -> transaction_pb2.Transaction: """ Abstract method to build the transaction body. @@ -921,3 +921,13 @@ def get_required_chunks(self): int: Number of chunks required. """ return 1 + + def get_size(self) -> int: + """Returns the total transaction size in bytes after protobuf encoding""" + self._require_frozen() + return self._make_request().ByteSize() + + def get_body_size(self) -> int: + """Returns just the transaction body size in bytes after encoding""" + self._require_frozen() + return self.build_transaction_body().ByteSize() diff --git a/src/hiero_sdk_python/transaction/transaction_record.py b/src/hiero_sdk_python/transaction/transaction_record.py index 488a4aa77..c39d8fb0a 100644 --- a/src/hiero_sdk_python/transaction/transaction_record.py +++ b/src/hiero_sdk_python/transaction/transaction_record.py @@ -254,6 +254,7 @@ def _from_proto( elif entropy_case == "prng_bytes": prng_bytes = proto.prng_bytes + proto.automatic_token_associations return cls( transaction_id=tx_id, transaction_hash=proto.transactionHash, From 211910342445f1c3a8b0da313f0ce794379c5ade Mon Sep 17 00:00:00 2001 From: Manish Dait Date: Thu, 12 Feb 2026 17:49:54 +0530 Subject: [PATCH 02/25] chore: refactor chunck method for file append tx Signed-off-by: Manish Dait --- ...opic_message_submit_chunked_transaction.py | 18 ++---- examples/test.py | 16 ----- .../topic_message_submit_transaction.py | 5 ++ .../file/file_append_transaction.py | 58 ++++++++++++++----- 4 files changed, 52 insertions(+), 45 deletions(-) delete mode 100644 examples/test.py diff --git a/examples/consensus/topic_message_submit_chunked_transaction.py b/examples/consensus/topic_message_submit_chunked_transaction.py index 8d1e7ada1..0c6a87a2a 100644 --- a/examples/consensus/topic_message_submit_chunked_transaction.py +++ b/examples/consensus/topic_message_submit_chunked_transaction.py @@ -128,20 +128,10 @@ def fetch_topic_info(client, topic_id): def main(): """Create a topic and submit a large multi-chunk message to it.""" client = setup_client() - # topic_id = create_topic(client) - # fetch_topic_info(client, topic_id) - # submit_topic_message_transaction(client, topic_id) - # fetch_topic_info(client, topic_id) - tx = ( - TopicMessageSubmitTransaction() - .set_topic_id(TopicId.from_string("0.0.7895219")) - .set_message(BIG_CONTENT) - .freeze_with(client) - ) - - print(tx.get_size()) - print(tx.get_body_size()) - print(tx.get_body_size_all_chunks()) + topic_id = create_topic(client) + fetch_topic_info(client, topic_id) + submit_topic_message_transaction(client, topic_id) + fetch_topic_info(client, topic_id) if __name__ == "__main__": diff --git a/examples/test.py b/examples/test.py deleted file mode 100644 index 8344fa870..000000000 --- a/examples/test.py +++ /dev/null @@ -1,16 +0,0 @@ -from hiero_sdk_python.account.account_create_transaction import AccountCreateTransaction -from hiero_sdk_python.client.client import Client -from hiero_sdk_python.crypto.private_key import PrivateKey - - -def main(): - client = Client.from_env() - tx = AccountCreateTransaction().set_key_without_alias(PrivateKey.generate()).freeze_with(client) - - - print(tx.get_size()) - print(tx.get_body_size()) - - -if __name__ == "__main__": - main() diff --git a/src/hiero_sdk_python/consensus/topic_message_submit_transaction.py b/src/hiero_sdk_python/consensus/topic_message_submit_transaction.py index fb07ff121..ed0d93930 100644 --- a/src/hiero_sdk_python/consensus/topic_message_submit_transaction.py +++ b/src/hiero_sdk_python/consensus/topic_message_submit_transaction.py @@ -407,6 +407,11 @@ def sign(self, private_key: PrivateKey): def get_body_size_all_chunks(self) -> List[int]: """ + Returns an array of body sizes for transactions with multiple chunks. + + Returns: + List[int]: An array of body sizes, where each element represents the + size in bytes of a chunk's transaction body """ self._require_frozen() sizes = [] diff --git a/src/hiero_sdk_python/file/file_append_transaction.py b/src/hiero_sdk_python/file/file_append_transaction.py index aebb4ad9b..4b48ffcc6 100644 --- a/src/hiero_sdk_python/file/file_append_transaction.py +++ b/src/hiero_sdk_python/file/file_append_transaction.py @@ -31,6 +31,7 @@ from hiero_sdk_python.channels import _Channel from hiero_sdk_python.client import Client from hiero_sdk_python.crypto.private_key import PrivateKey + from hiero_sdk_python.executable import _Method from hiero_sdk_python.transaction.transaction import TransactionReceipt from hiero_sdk_python.transaction.transaction_response import TransactionResponse @@ -290,8 +291,8 @@ def freeze_with(self, client: Client) -> FileAppendTransaction: self.transaction_id = client.generate_transaction_id() # Generate transaction IDs for all chunks - self._transaction_ids = [] - base_timestamp = self.transaction_id.valid_start + if not self._transaction_ids: + base_timestamp = self.transaction_id.valid_start for i in range(self.get_required_chunks()): if i == 0: @@ -307,19 +308,25 @@ def freeze_with(self, client: Client) -> FileAppendTransaction: account_id=self.transaction_id.account_id, valid_start=chunk_valid_start ) self._transaction_ids.append(chunk_transaction_id) - - # We iterate through every node in the client's network - # For each node, set the node_account_id and build the transaction body - # This allows the transaction to be submitted to any node in the network - for node in client.network.nodes: - self.node_account_id = node._account_id - transaction_body = self.build_transaction_body() - self._transaction_body_bytes[node._account_id] = transaction_body.SerializeToString() - - # Set the node account id to the current node in the network - self.node_account_id = client.network.current_node._account_id - - return self + for i in range(self.get_required_chunks()): + if i == 0: + # First chunk uses the original transaction ID + chunk_transaction_id = self.transaction_id + else: + # Subsequent chunks get incremented timestamps + # Add i nanoseconds to space out chunks + chunk_valid_start = timestamp_pb2.Timestamp( + seconds=base_timestamp.seconds, + nanos=base_timestamp.nanos + i + ) + chunk_transaction_id = TransactionId( + account_id=self.transaction_id.account_id, + valid_start=chunk_valid_start + ) + + self._transaction_ids.append(chunk_transaction_id) + + return super().freeze_with(client) @overload def execute( @@ -458,3 +465,24 @@ def sign(self, private_key: PrivateKey) -> FileAppendTransaction: # Call the parent sign method for the current transaction super().sign(private_key) return self + + + def get_body_size_all_chunks(self) -> List[int]: + """ + Returns an array of body sizes for transactions with multiple chunks. + + Returns: + List[int]: An array of body sizes, where each element represents the + size in bytes of a chunk's transaction body + """ + self._require_frozen() + sizes = [] + + original_index = self._current_index + for transaction_id in self._transaction_ids: + self.transaction_id = transaction_id + sizes.append(self.get_body_size()) + + self._current_index = original_index + return sizes + From 36435247e6a6dc8a64eb733eb58c3398601807db Mon Sep 17 00:00:00 2001 From: Manish Dait Date: Thu, 12 Feb 2026 23:34:05 +0530 Subject: [PATCH 03/25] chore: refactor freeze() to work with chunck tx Signed-off-by: Manish Dait --- .../topic_message_submit_transaction.py | 5 +++ .../file/file_append_transaction.py | 9 ++++- .../transaction/transaction.py | 39 +++++++------------ 3 files changed, 26 insertions(+), 27 deletions(-) diff --git a/src/hiero_sdk_python/consensus/topic_message_submit_transaction.py b/src/hiero_sdk_python/consensus/topic_message_submit_transaction.py index ed0d93930..f8e3dce23 100644 --- a/src/hiero_sdk_python/consensus/topic_message_submit_transaction.py +++ b/src/hiero_sdk_python/consensus/topic_message_submit_transaction.py @@ -254,6 +254,11 @@ def freeze_with(self, client: Client) -> TopicMessageSubmitTransaction: return self if self.transaction_id is None: + if client is None: + raise ValueError( + "Transaction ID must be set before freezing. Use freeze_with(client) or set_transaction_id()." + ) + self.transaction_id = client.generate_transaction_id() if not self._transaction_ids: diff --git a/src/hiero_sdk_python/file/file_append_transaction.py b/src/hiero_sdk_python/file/file_append_transaction.py index 4b48ffcc6..ef5ec768f 100644 --- a/src/hiero_sdk_python/file/file_append_transaction.py +++ b/src/hiero_sdk_python/file/file_append_transaction.py @@ -288,6 +288,11 @@ def freeze_with(self, client: Client) -> FileAppendTransaction: return self if self.transaction_id is None: + if client is None: + raise ValueError( + "Transaction ID must be set before freezing. Use freeze_with(client) or set_transaction_id()." + ) + self.transaction_id = client.generate_transaction_id() # Generate transaction IDs for all chunks @@ -478,11 +483,11 @@ def get_body_size_all_chunks(self) -> List[int]: self._require_frozen() sizes = [] - original_index = self._current_index + original_index = self._current_chunk_index for transaction_id in self._transaction_ids: self.transaction_id = transaction_id sizes.append(self.get_body_size()) - self._current_index = original_index + self._current_chunk_index = original_index return sizes diff --git a/src/hiero_sdk_python/transaction/transaction.py b/src/hiero_sdk_python/transaction/transaction.py index 91b4e51d1..3dd4f79ba 100644 --- a/src/hiero_sdk_python/transaction/transaction.py +++ b/src/hiero_sdk_python/transaction/transaction.py @@ -246,31 +246,7 @@ def freeze(self): Raises: ValueError: If transaction_id or node_account_id are not set. """ - if self._transaction_body_bytes: - return self - - if self.transaction_id is None: - raise ValueError( - "Transaction ID must be set before freezing. Use freeze_with(client) or set_transaction_id()." - ) - - if self.node_account_id is None and len(self.node_account_ids) == 0: - raise ValueError( - "Node account ID must be set before freezing. Use freeze_with(client) or manually set node_account_ids." - ) - - # Populate node_account_ids for backward compatibility - if self.node_account_id: - self.set_node_account_id(self.node_account_id) - self._transaction_body_bytes[self.node_account_id] = self.build_transaction_body().SerializeToString() - return self - - # Build the transaction body for the single node - for node_account_id in self.node_account_ids: - self.node_account_id = node_account_id - self._transaction_body_bytes[node_account_id] = self.build_transaction_body().SerializeToString() - - return self + return self.freeze_with(None) def freeze_with(self, client): """ @@ -288,6 +264,19 @@ def freeze_with(self, client): if self._transaction_body_bytes: return self + + # Check transaction_id and node id to be set when using freeze() + if client is None: + if self.transaction_id is None: + raise ValueError( + "Transaction ID must be set before freezing. Use freeze_with(client) or set_transaction_id()." + ) + + if self.node_account_id is None and len(self.node_account_ids) == 0: + raise ValueError( + "Node account ID must be set before freezing. Use freeze_with(client) or manually set node_account_ids." + ) + if self.transaction_id is None: self.transaction_id = client.generate_transaction_id() From bbcbe3a9c7c980fd1376c0fdf6e0d9b5ced2cd14 Mon Sep 17 00:00:00 2001 From: Manish Dait Date: Fri, 13 Feb 2026 13:28:10 +0530 Subject: [PATCH 04/25] chore: added test fro chunk tx manual freeze Signed-off-by: Manish Dait --- ...opic_message_submit_chunked_transaction.py | 1 - .../file_append_transaction_e2e_test.py | 43 +++++++++++++++++++ ...pic_message_submit_transaction_e2e_test.py | 36 ++++++++++++++++ .../topic_message_submit_transaction_test.py | 1 + 4 files changed, 80 insertions(+), 1 deletion(-) diff --git a/examples/consensus/topic_message_submit_chunked_transaction.py b/examples/consensus/topic_message_submit_chunked_transaction.py index 0c6a87a2a..63d24e8d4 100644 --- a/examples/consensus/topic_message_submit_chunked_transaction.py +++ b/examples/consensus/topic_message_submit_chunked_transaction.py @@ -17,7 +17,6 @@ TopicInfoQuery, TopicMessageSubmitTransaction, ) -from hiero_sdk_python.consensus.topic_id import TopicId BIG_CONTENT = """ diff --git a/tests/integration/file_append_transaction_e2e_test.py b/tests/integration/file_append_transaction_e2e_test.py index e44d61e28..b4ee7c4b4 100644 --- a/tests/integration/file_append_transaction_e2e_test.py +++ b/tests/integration/file_append_transaction_e2e_test.py @@ -3,11 +3,17 @@ import pytest from pytest import mark +from hiero_sdk_python.account.account_id import AccountId +from hiero_sdk_python.file.file_create_transaction import FileCreateTransaction from hiero_sdk_python.file.file_append_transaction import FileAppendTransaction from hiero_sdk_python.file.file_contents_query import FileContentsQuery from hiero_sdk_python.file.file_create_transaction import FileCreateTransaction from hiero_sdk_python.response_code import ResponseCode +from hiero_sdk_python.hbar import Hbar +from hiero_sdk_python.exceptions import PrecheckError +from hiero_sdk_python.transaction.transaction_id import TransactionId +from tests.integration.utils import env, IntegrationTestEnv # Generate big contents for chunking tests - similar to JavaScript bigContents BIG_CONTENTS = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " * 250 # ~13,750 characters @@ -283,3 +289,40 @@ def test_integration_file_append_transaction_method_chaining(env): append_receipt = append_tx.execute(env.client) assert append_receipt.status == ResponseCode.SUCCESS + assert append_receipt.status == ResponseCode.SUCCESS + +@pytest.mark.integration +def test_file_append_chuck_transaction_can_execute_with_manual_freeze(env): + """Test file append transaction can execute with manual freeze.""" + create_receipt = ( + FileCreateTransaction() + .set_keys(env.client.operator_private_key.public_key()) + .set_contents(b"") + .execute(env.client) + ) + + assert create_receipt.status == ResponseCode.SUCCESS + file_id = create_receipt.file_id + + file_contents = FileContentsQuery().set_file_id(file_id).execute(env.client) + assert file_contents == b"" + + content = "A" * (4) # content with (1024 * 14) bytes ie 14 chunks + + tx = ( + FileAppendTransaction() + .set_file_id(file_id) + .set_chunk_size(1) + .set_contents(content) + .freeze_with(env.client) + ) + + # tx.sign(env.client.operator_private_key) + + print(tx.get_required_chunks()) + receipt = tx.execute(env.client) + + assert receipt.status == ResponseCode.SUCCESS + + file_contents = FileContentsQuery().set_file_id(file_id).execute(env.client) + assert file_contents == bytes(content, "utf-8") diff --git a/tests/integration/topic_message_submit_transaction_e2e_test.py b/tests/integration/topic_message_submit_transaction_e2e_test.py index 94feceb6a..223ca362d 100644 --- a/tests/integration/topic_message_submit_transaction_e2e_test.py +++ b/tests/integration/topic_message_submit_transaction_e2e_test.py @@ -6,6 +6,7 @@ import pytest +from hiero_sdk_python.account.account_id import AccountId from hiero_sdk_python.consensus.topic_create_transaction import TopicCreateTransaction from hiero_sdk_python.consensus.topic_delete_transaction import TopicDeleteTransaction from hiero_sdk_python.consensus.topic_message_submit_transaction import ( @@ -19,6 +20,7 @@ from hiero_sdk_python.tokens.custom_fixed_fee import CustomFixedFee from hiero_sdk_python.transaction.custom_fee_limit import CustomFeeLimit +from hiero_sdk_python.transaction.transaction_id import TransactionId def create_topic(client, admin_key=None, submit_key=None, custom_fees=None): """Helper transaction for creating a topic.""" @@ -296,3 +298,37 @@ def test_integration_topic_message_submit_transaction_fails_if_required_chunk_gr message_transaction.execute(env.client) delete_topic(env.client, topic_id) + + + +@pytest.mark.integration +def test_topic_message_submit_transaction_can_submit_a_large_message_manual_freeze(env): + """Test topic message submit transaction can submit large message with manual freeze.""" + topic_id = create_topic( + client=env.client, + admin_key=env.operator_key + ) + + info = TopicInfoQuery().set_topic_id(topic_id).execute(env.client) + assert info.sequence_number == 0 + + message = "A" * (1024 * 14) # message with (1024 * 14) bytes ie 14 chunks + + message_tx = ( + TopicMessageSubmitTransaction() + .set_topic_id(topic_id) + .set_message(message) + .set_transaction_id(TransactionId.generate(env.client.operator_account_id)) + .set_node_account_id(AccountId(0,0,3)) + .freeze() + ) + + message_tx.sign(env.client.operator_private_key) + message_receipt = message_tx.execute(env.client) + + assert message_receipt.status == ResponseCode.SUCCESS + + info = TopicInfoQuery().set_topic_id(topic_id).execute(env.client) + assert info.sequence_number == 14 + + delete_topic(env.client, topic_id) diff --git a/tests/unit/topic_message_submit_transaction_test.py b/tests/unit/topic_message_submit_transaction_test.py index b0adf7a69..8afa46b0d 100644 --- a/tests/unit/topic_message_submit_transaction_test.py +++ b/tests/unit/topic_message_submit_transaction_test.py @@ -6,6 +6,7 @@ import pytest +from hiero_sdk_python.account.account_id import AccountId from hiero_sdk_python.consensus.topic_message_submit_transaction import TopicMessageSubmitTransaction from hiero_sdk_python.exceptions import PrecheckError, ReceiptStatusError from hiero_sdk_python.hapi.services import ( From 80b83a39c4c90fb204570d98e4760089e19cfe1f Mon Sep 17 00:00:00 2001 From: Manish Dait Date: Fri, 13 Feb 2026 14:11:20 +0530 Subject: [PATCH 05/25] fix: fix the intendation in file_append tx execute func Signed-off-by: Manish Dait --- diff.txt | 0 tests/integration/file_append_transaction_e2e_test.py | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) delete mode 100644 diff.txt diff --git a/diff.txt b/diff.txt deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/integration/file_append_transaction_e2e_test.py b/tests/integration/file_append_transaction_e2e_test.py index b4ee7c4b4..7396d8b31 100644 --- a/tests/integration/file_append_transaction_e2e_test.py +++ b/tests/integration/file_append_transaction_e2e_test.py @@ -307,12 +307,12 @@ def test_file_append_chuck_transaction_can_execute_with_manual_freeze(env): file_contents = FileContentsQuery().set_file_id(file_id).execute(env.client) assert file_contents == b"" - content = "A" * (4) # content with (1024 * 14) bytes ie 14 chunks + content = "A" * (4000) # content with (1024 * 14) bytes ie 14 chunks tx = ( FileAppendTransaction() .set_file_id(file_id) - .set_chunk_size(1) + .set_chunk_size(1024) .set_contents(content) .freeze_with(env.client) ) From 8f4b861076c227601873f9fcaede12bd7cd4bd72 Mon Sep 17 00:00:00 2001 From: Manish Dait Date: Fri, 13 Feb 2026 14:23:02 +0530 Subject: [PATCH 06/25] chore: fix unused imports and prints Signed-off-by: Manish Dait --- src/hiero_sdk_python/transaction/transaction_record.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/hiero_sdk_python/transaction/transaction_record.py b/src/hiero_sdk_python/transaction/transaction_record.py index c39d8fb0a..488a4aa77 100644 --- a/src/hiero_sdk_python/transaction/transaction_record.py +++ b/src/hiero_sdk_python/transaction/transaction_record.py @@ -254,7 +254,6 @@ def _from_proto( elif entropy_case == "prng_bytes": prng_bytes = proto.prng_bytes - proto.automatic_token_associations return cls( transaction_id=tx_id, transaction_hash=proto.transactionHash, From eab6e6225f7e7047f448369484e6f1595bacacfa Mon Sep 17 00:00:00 2001 From: Manish Dait Date: Fri, 13 Feb 2026 14:44:28 +0530 Subject: [PATCH 07/25] chore: converted method to property Signed-off-by: Manish Dait --- .../consensus/topic_message_submit_transaction.py | 9 +++------ src/hiero_sdk_python/file/file_append_transaction.py | 9 +++------ src/hiero_sdk_python/transaction/transaction.py | 6 ++++-- 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/src/hiero_sdk_python/consensus/topic_message_submit_transaction.py b/src/hiero_sdk_python/consensus/topic_message_submit_transaction.py index f8e3dce23..4b67d57e7 100644 --- a/src/hiero_sdk_python/consensus/topic_message_submit_transaction.py +++ b/src/hiero_sdk_python/consensus/topic_message_submit_transaction.py @@ -410,13 +410,10 @@ def sign(self, private_key: PrivateKey): super().sign(private_key) return self - def get_body_size_all_chunks(self) -> List[int]: + @property + def body_size_all_chunks(self) -> List[int]: """ Returns an array of body sizes for transactions with multiple chunks. - - Returns: - List[int]: An array of body sizes, where each element represents the - size in bytes of a chunk's transaction body """ self._require_frozen() sizes = [] @@ -424,7 +421,7 @@ def get_body_size_all_chunks(self) -> List[int]: original_index = self._current_index for transaction_id in self._transaction_ids: self.transaction_id = transaction_id - sizes.append(self.get_body_size()) + sizes.append(self.body_size) self._current_index = original_index return sizes diff --git a/src/hiero_sdk_python/file/file_append_transaction.py b/src/hiero_sdk_python/file/file_append_transaction.py index ef5ec768f..01f73161a 100644 --- a/src/hiero_sdk_python/file/file_append_transaction.py +++ b/src/hiero_sdk_python/file/file_append_transaction.py @@ -472,13 +472,10 @@ def sign(self, private_key: PrivateKey) -> FileAppendTransaction: return self - def get_body_size_all_chunks(self) -> List[int]: + @property + def body_size_all_chunks(self) -> List[int]: """ Returns an array of body sizes for transactions with multiple chunks. - - Returns: - List[int]: An array of body sizes, where each element represents the - size in bytes of a chunk's transaction body """ self._require_frozen() sizes = [] @@ -486,7 +483,7 @@ def get_body_size_all_chunks(self) -> List[int]: original_index = self._current_chunk_index for transaction_id in self._transaction_ids: self.transaction_id = transaction_id - sizes.append(self.get_body_size()) + sizes.append(self.body_size) self._current_chunk_index = original_index return sizes diff --git a/src/hiero_sdk_python/transaction/transaction.py b/src/hiero_sdk_python/transaction/transaction.py index 3dd4f79ba..df2992be7 100644 --- a/src/hiero_sdk_python/transaction/transaction.py +++ b/src/hiero_sdk_python/transaction/transaction.py @@ -911,12 +911,14 @@ def get_required_chunks(self): """ return 1 - def get_size(self) -> int: + @property + def size(self) -> int: """Returns the total transaction size in bytes after protobuf encoding""" self._require_frozen() return self._make_request().ByteSize() - def get_body_size(self) -> int: + @property + def body_size(self) -> int: """Returns just the transaction body size in bytes after encoding""" self._require_frozen() return self.build_transaction_body().ByteSize() From 436fb88f99e505143bc027050635a8b612e0f99b Mon Sep 17 00:00:00 2001 From: Manish Dait Date: Fri, 13 Feb 2026 15:12:59 +0530 Subject: [PATCH 08/25] chore: formated unit test Signed-off-by: Manish Dait --- tests/unit/transaction_test.py | 207 +++++++++++++++++++++++++++++++++ 1 file changed, 207 insertions(+) diff --git a/tests/unit/transaction_test.py b/tests/unit/transaction_test.py index 5821d9e7a..231dc71a4 100644 --- a/tests/unit/transaction_test.py +++ b/tests/unit/transaction_test.py @@ -26,6 +26,7 @@ pytestmark = pytest.mark.unit + def test_execute_waits_for_receipt_receipt(): """Test execute return TransactionReceipt when wait_for_receipt is True (default).""" ok_response = transaction_response_pb2.TransactionResponse(nodeTransactionPrecheckCode=ResponseCode.OK) @@ -160,3 +161,209 @@ def test_multiple_keys_still_work(): key2.public_key().to_bytes_raw(), } assert pubkey_prefixes == expected_prefixes, "Signatures should match key1 and key2 exactly" +@pytest.fixture +def file_id(): + """Returns a file_is for test.""" + return FileId.from_string("0.0.1") + + +@pytest.fixture +def account_id(): + """Returns an account_id for test.""" + return AccountId.from_string("0.0.9") + + +@pytest.fixture +def transaction_id(): + """Returns a transaction_id for test.""" + return TransactionId.from_string("0.0.9@1770911831.331000137") + + +def test_same_size_for_identical_transactions(transaction_id, account_id): + """Test two identical transactions should have the same size.""" + key = PrivateKey.generate() + + tx1 = ( + AccountCreateTransaction() + .set_key_without_alias(key) + .set_initial_balance(Hbar(2)) + .set_transaction_id(transaction_id) + .set_node_account_id(account_id) + .freeze() + ) + + tx2 = ( + AccountCreateTransaction() + .set_key_without_alias(key) + .set_initial_balance(Hbar(2)) + .set_transaction_id(transaction_id) + .set_node_account_id(account_id) + .freeze() + ) + + assert tx1.size == tx2.size + + +def test_signed_tx_have_larger_size(transaction_id, account_id): + """Test signed Transaction should have larger size.""" + key = PrivateKey.generate() + + tx1 = ( + AccountCreateTransaction() + .set_key_without_alias(key) + .set_initial_balance(Hbar(2)) + .set_transaction_id(transaction_id) + .set_node_account_id(account_id) + .freeze() + .sign(PrivateKey.generate()) + ) + + tx2 = ( + AccountCreateTransaction() + .set_key_without_alias(key) + .set_initial_balance(Hbar(2)) + .set_transaction_id(transaction_id) + .set_node_account_id(account_id) + .freeze() + ) + + assert tx1.size > tx2.size + + +def test_tx_with_larger_content_should_have_larger_tx_body(transaction_id, account_id): + """Test transaction with larger content should have larger transaction body.""" + tx1 = ( + FileCreateTransaction() + .set_contents("smallBody") + .set_transaction_id(transaction_id) + .set_node_account_id(account_id) + .freeze() + ) + + tx2 = ( + FileCreateTransaction() + .set_contents("veryLargeBody") + .set_transaction_id(transaction_id) + .set_node_account_id(account_id) + .freeze() + ) + + assert tx1.body_size < tx2.body_size + + +def test_tx_without_optional_fields_should_have_smaller_tx_body( + transaction_id, account_id +): + """Test transaction with without optional fields should have smaller transaction body.""" + key = PrivateKey.generate() + tx1 = ( + AccountCreateTransaction() + .set_key_without_alias(key) + .set_initial_balance(Hbar(2)) + .set_transaction_id(transaction_id) + .set_node_account_id(account_id) + .freeze() + ) + + tx2 = ( + AccountCreateTransaction() + .set_key_without_alias(key) + .set_initial_balance(Hbar(2)) + .set_transaction_id(transaction_id) + .set_node_account_id(account_id) + .set_transaction_valid_duration(10) + .freeze() + ) + + assert tx1.body_size < tx2.body_size + + +def test_chunk_tx_should_return_list_of_body_sizes(file_id, account_id, transaction_id): + """Test should return array of body sizes for multi-chunk transaction.""" + chunk_size = 1024 + content = "a" * (chunk_size * 3) + + tx = ( + FileAppendTransaction() + .set_file_id(file_id) + .set_chunk_size(chunk_size) + .set_contents(content) + .set_transaction_id(transaction_id) + .set_node_account_id(account_id) + .freeze() + ) + + sizes = tx.body_size_all_chunks + assert isinstance(sizes, list) + assert len(sizes) == 3 + + +def test_single_chunk_tx_return_list_of_len_one(file_id, account_id, transaction_id): + """Test should return array of one size for single-chunk transaction.""" + content = "small_content" + tx = ( + FileAppendTransaction() + .set_file_id(file_id) + .set_contents(content) + .set_transaction_id(transaction_id) + .set_node_account_id(account_id) + .freeze() + ) + + sizes = tx.body_size_all_chunks + assert isinstance(sizes, list) + assert len(sizes) == 1 + + +def test_tx_with_no_content_should_return_single_body_chunk( + file_id, account_id, transaction_id +): + """Test should return single body chunk for transaction with no content.""" + tx = ( + FileAppendTransaction() + .set_file_id(file_id) + .set_contents(" ") + .set_transaction_id(transaction_id) + .set_node_account_id(account_id) + .freeze() + ) + + sizes = tx.body_size_all_chunks + assert isinstance(sizes, list) + assert len(sizes) == 1 + + +def test_chunked_tx_return_proper_sizes(file_id, account_id, transaction_id): + """Test should return proper sizes for FileAppend transactions when chunking occurs.""" + large_content = "a" * 2048 + + large_tx = ( + FileAppendTransaction() + .set_file_id(file_id) + .set_contents(large_content) + .set_transaction_id(transaction_id) + .set_node_account_id(account_id) + .freeze() + ) + + large_size = large_tx.size + + small_content = "a" * 512 + + small_tx = ( + FileAppendTransaction() + .set_file_id(file_id) + .set_contents(small_content) + .set_transaction_id(transaction_id) + .set_node_account_id(account_id) + .freeze() + ) + + small_size = small_tx.size + + # Since large content is 2KB and chunk size is 1KB, this should create 2 chunks + # Size should be greater than single chunk size + large_size > 1024 + + # The larger chunked transaction should be bigger than the small single-chunk transaction + large_size > small_size From 384a5f346dd0e5017e2b28a8f4d7e56adc9a9ad7 Mon Sep 17 00:00:00 2001 From: Manish Dait Date: Fri, 13 Feb 2026 15:14:04 +0530 Subject: [PATCH 09/25] chore: updated changelog Signed-off-by: Manish Dait --- CHANGELOG.md | 1053 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1053 insertions(+) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..c7a40f281 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,1053 @@ +# Changelog + +All notable changes to this project will be documented in this file. +This project adheres to [Semantic Versioning](https://semver.org). +This changelog is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). + +## [Unreleased] + +### Src +- Exposed all missing `TransactionRecord` protobuf fields `consensusTimestamp`, `scheduleRef`, `assessed_custom_fees`, `automatic_token_associations`, `parent_consensus_timestamp`, `alias`, `ethereum_hash`, `paid_staking_rewards`, `evm_address`, `contractCreateResult` with proper `None` handling, PRNG oneof handling with unset values return `None` instead of default values 0 / b"" (#1636) +- Added Transaction size calculation properties `size`, `body_size` and `body_size_all_chunks`. + +### Tests +- Refactor `mock_server` setup for network level TLS handling and added thread safety + + +### Examples + +- Add the missing `setup_client()` docstring in `examples/tokens/token_dissociate_transaction.py` for consistency with the other example functions. (#2058) + +### Docs + + +### .github +- chore: pin pip packages to exact versions in publish.yml to improve supply chain security and reproducibility (#2056) +- chore: update GitHub Actions runners from ubuntu-latest to hl-sdk-py-lin-md (#2021) +- Refactored the Advanced Issue Template to V2 with stricter prerequisites and a focus on architectural design (#2016). +- Refactored the Advanced Issue Template to ensure PR-level quality checklists do not block maintainers during issue creation (#2036) +- Add automated label sync workflow to propagate labels from linked issues to pull requests (#1716) +- chore: update spam list (#2035) + +## [0.2.3] - 2026-03-26 + +### Added +- Add `__repr__` method to `TokenId` class for cleaner debugging output (#1653) + +### Src +- Updated `AccountUpdateTransaction.set_key()` to accept generic `Key` objects (including `KeyList` and threshold keys), rather than strictly requiring a `PublicKey`. +- Fix the TransactionGetReceiptQuery to raise ReceiptStatusError for the non-retryable and non success receipt status +- Refactor `AccountInfo` to use the existing `StakingInfo` wrapper class instead of flattened staking fields. Access is now via `info.staking_info.staked_account_id`, `info.staking_info.staked_node_id`, and `info.staking_info.decline_reward`. The old flat accessors (`info.staked_account_id`, `info.staked_node_id`, `info.decline_staking_reward`) are still available as deprecated properties and will emit a `DeprecationWarning`. (#1366) +- Added abstract `Key` supper class to handle various proto Keys. + + +### Examples + +### Tests +- Added TCK endpoint for the createAccount method +- Renamed `delegate_contract_id.py` to `delegate_contract_id_test.py` (#2004) +- Fix Flaky tests for `mock_server` by enforcing non-tls port and adding a mock_tls certificate +- Implement basic fuzz testing [#1872](https://github.com/hiero-ledger/hiero-sdk-python/issues/1872) + + +### Docs +- Add Chocolatey as a prerequisite in the Windows setup guide (#1961) + + +### .github +- chore: update several ubuntu runners to hl-sdk-py-lin-md (#1480) +- Refactored intermediate issue template with quality standards, testing requirements, breaking change awareness, and protobuf verification guidance to reduce review burden and improve PR quality (#1892) +- fix: prevent CodeRabbit from posting comments on closed issues(#1962) +- chore: update spam list #1988 +- chore: Update `bot-advanced-check.yml`, `bot-gfi-assign-on-comment.yml`, `bot-intermediate-assignment.yml`, `bot-linked-issue-enforcer.yml`, `unassign-on-comment.yml`, `working-on-comment.yml` workflow runner configuration +- Fix build failing in `publish.yml` + + + +## [0.2.2] - 2026-03-17 + +### Added +- Added CodeRabbit review instructions in `.coderabbit.yaml` for account module `src/hiero_sdk_python/account/`. +- Add support for `include_children` to TransactionRecordQuery ([#1512](https://github.com/hiero-ledger/hiero-sdk-python/issues/1512)) + +### Changed +- Changed pytest version to "pytest>=8.3.4,<10" (#1917) +- Update protobuf schema version to v0.72.0-rc.2 in `.coderabbit.yaml` + +### Src +- Updated `generated_proto.py` file to work with new proto version +- fix: Ensure UTF-8 encoding when reading and writing proto files in `generate_proto.py` to prevent encoding issues on Windows (`#1963`) + +### Examples +- Updated the `examples/consensus/topic_create_transaction_revenue_generating.py` example to use `Client.from_env()` for simpler client setup. (#1964) + +- Refactored `examples/consensus/topic_delete_transaction.py` to use Client.from_env() for simplified client initialization, removed manual setup code, and cleaned up unused imports (`os`, `AccountId`, `PrivateKey`). (`#1971`) + +### Tests + +### Docs +- Replaced relative documentation links in `README.md` with absolute GitHub URLs to fix broken PyPI rendering. +- docs: Clarified AI usage in Good First Issues templates. (#1923) +- docs: Moved the Windows setup guide to docs/sdk_developers/ and added missing setup sections. (`#1953`) + + + +### .github +- chore: ensure uv run uses lowest-direct resolution in deps-check workflow (#1919) +- Added PR draft explainer workflow to comment when PRs are converted to draft after changes are requested. (#1723) +- changed `pr-check-test` to run unit matrix first, run integration matrix only after unit success, skip docs/examples/.github-only changes, and parallelize integration tests with xdist (`#1878`) +- archived workflows relating to PR reminders +- chore: switch workflow runner from ubuntu-latest to hl-sdk-py-lin-md for bot-assignment-check.yml workflow +- chore: update concurrency group for GFI assignment workflow to prevent race conditions (`#1910`) +- chore: switch workflow runner from ubuntu-latest to hl-sdk-py-lin-md for bot-beginner-assign-on-comment workflow +- chore: update bot-coderabbit-plan-trigger workflow to use self-hosted runner (`#1925`) +- Require contributors to complete 1 beginner issue before they can be assigned an intermediate issue (#1939) +- Expand spam list (#1933) +- Expand spam list (#1972) +- chore: add ndpvt-web to spam list (#1945) +- chore: update bot-community-calls workflow to use self hosted runner (#1942) +- chore(ci): update bot-inactivity-unassign workflow to use hl-sdk-py-lin-md runner +- chore: update bot-gfi-candidate-notification workflow to use hl-sdk-py-lin-md runner (`#1966`) +## [0.2.1] - 2026-03-05 + +### Added + +- Added unit test and __repr__ for NftId class(#1627). +- Added CodeRabbit review instructions for the nodes module in `.coderabbit.yaml` (#1699) +- Added CodeRabbit review instructions for the transaction module in `.coderabbit.yaml` (#1696) +- Added CodeRabbit review instructions and path mapping for the schedule module (`src/hiero_sdk_python/schedule/`) in `.coderabbit.yaml` (#1698) +- Added advanced code review prompts for the `src/hiero_sdk_python/file` module in `.coderabbit.yaml` to guide reviewers in verifying proper `FileAppendTransaction` chunking constraints and nuances in memo handling for `FileUpdateTransaction` according to Hiero SDK best practices. (#1697) +- Added CodeRabbit review instructions for consensus module `src/hiero_sdk_python/consensus/` with critical focus on protobuf alignment `.coderabbit.yaml`. +- Added CodeRabbit prompt to review the `src/hiero_sdk_python/crypto` module. +- Added `.codacy.yml` configuration to exclude the `tests/` directory from Bandit `assert` analysis. + +### Fixed + +- Fixed duplication in GitHub bot next issue recommendations by parsing actual issue descriptions instead of blind truncation (#1658) + +### Src +- Add `staking_info` field to `ContractInfo` class to expose staking metadata using the `StakingInfo` wrapper. (#1365) +- Fix `TopicInfo.__str__()` to format `expiration_time` in UTC so unit tests pass in non-UTC environments. (#1800) +- Resolve CodeQL `reflected-XSS` warning in TCK JSON-RPC endpoint +- Improve `keccak256` docstring formatting for better readability and consistency (#1624) +- Added `wait_for_receipt` parameter for `Transaction.execute()` to support optional receipt waiting, and `get_receipt_query`, `get_record_query` and `get_record` to `TransactionResponse`. + +### Examples +- Refactor `examples/file/file_create_transaction.py` to remove `os`,`dotenv`,`AccountId`,`PrivateKey`,`Network` imports that are no longer needed and updated setup-client() (#1610) + +- Refactored contract_delete_transaction example to use Client.from_env. (#1823) + +### Docs + +- docs: Improving formatting will make the pull request process clearer. (`#1858`) +- Added Python compatibility badge to README for improved visibility of supported versions (#1830) +- Fixed Test Improvements header formatting in Good First Issue guidelines by adding missing space before parenthetical and removing stray bold marker (#1829) +- Improved Google-style docstring for `compress_point_unchecked` in `crypto_utils.py`. (#1625) +- chore: update office hours and community calls to use direct links (`#1804`) +- docs: create workflow best practices guide (`docs/workflows/03-workflow-best-practices.md`) (`#1743`) +- Fixed broken `MAINTAINERS.md` relative link in `docs/sdk_developers/bug.md` by using the repository-root GitHub URL. (#1666) +- docs(setup): specify unit tests for local setup verification. (#1856) +- docs: Clarify issues need to be assigned in template files. (#1884) +- doc: Fix testnet link in README.md. (#1879) + +### Tests +- Format `tests/unit/endpoint_test.py` using black. (`#1792`) +- Implement TCK JSON-RPC server with request handling and error management + +### .github +- Added triage members max assignment is protected from being a mentor in `.github/scripts/bot-assignment-check.sh`. (#1718) +- Added automated bot to comment on PRs with invalid conventional commit titles, providing guidance on fixing the title format (#1705) +- Revert PythonBot workflow to restore previous stable behavior. (#1825) +- Added GitHub Actions workflow to remind draft PR authors to mark ready for review after pushing changes. (#1722) +- Fixed bot workflow runtime failure caused by strict `FAILED_WORKFLOW_NAME` validation. (`#1690`) +- Reverted PR #1739 checking assignment counts +- chore: update step-security/harden-runner from 2.14.1 to 2.14.2 in a workflow +- Redesigned beginner issue template with readiness self-check, exploration-based task structure, compact workflow reference, and common pitfalls guidance to improve completion rates (#1651) +- Added workflow documentation guide (`docs/github/04_workflow_documentation.md`) with best practices for documenting GitHub workflows and automation scripts (#1745) +- Updated CodeRabbit workflow and script review instructions to nudge higher-quality patterns without imposing rigid rules (`#1799`) +- Added hiero-sdk-js to the next issue recommendation bot (`#1847`) +- feat(bot): warn PR authors that unlinked PRs will be closed (#1886) +- updated spam list users (`#1894`) +- trigger spam list updates every hour (`#1864`) +- close unlinked pull requests after 12 hours rather than 3 days (`#1863`) +- feat(bot): enforce linked issue assignment check for PR authors (`#1889`) +- Bumped `astral-sh/setup-uv` from v7.2.1 to v7.3.1 in workflow files (#1900) + +## [0.2.0] - 2026-11-02 + +### Tests +- Format `tests/unit/crypto_utils_test.py` with black for code style consistency (#1524) +- Standardize formatting of `tests/unit/entity_id_helper_test.py` using Black for consistent code style across the test suite (#1527) + +- Added tests for ProtoBuf Training Example Implementation +- Formatted `tests/unit/get_receipt_query_test.py` with black for code style consistency. (#1537) +- format black `tests/unit/hbar*.py`.(#1538) +- Formatted `tests/unit/conftest.py` with black for code style consistency. (#1522) +- format `black tests/unit/nft_id_test.py` with Black.(#1544) +- Format `tests/unit/executable_test.py` with Black.(#1530) +- Format `tests/unit/hedera_trust_manager_test.py` with Black for consistent code style (#1539) +- Format tests/unit/logger_test.py with black for code style consistency (#1541) +- Format `tests/unit/batch_transaction_test.py` with Black.(`#1520`) +- Style: formatted `tests/unit/prng_transaction_test.py` with black (#1546) +- Formatted contract unit tests with black for consistent style. (#1523) +- Format account test files with Black (#1519) +- Format `tests/unit/node*.py` with Black for consistent code style (#1545) +- Improve unit test coverage for Hbar, including edge cases, validation, comparisons, and hashing. (#1483) +- Standardize formatting of evm_address_test.py using Black for improved consistency and readability (#1529) +- Formatted unit test files using Black. +- Format tests/unit/network_tls_test.py with black for code style consistency (#1543) +- Formatted `ethereum_transaction_test.py` using Black. +- Formatted client_test.py using Black. +- Format tests/unit/query*.py using black (#1547) +- Format `tests/unit/custom_fee_test.py` with black for code style consistency. (#1525) + +### Added +- Implement custom `__repr__` method for `FileId` class that returns constructor-style representation for improved debugging experience (#1628) +- Added foundational guide for GitHub Workflows (#1741) +- Contract-specific CodeRabbit review instructions in `.coderabbit.yaml` for improved automated PR feedback on ABI, gas, ContractId, and protobuf safety. (#1695) +- Added new members to the mentor roster. (#1693) +- Added support for the `includeDuplicates` flag in `TransactionRecordQuery` and `duplicates` field in `TransactionRecord` (#1635) +- Added logging in bot-gfi-assign-on-comment.js to prevent silent skips. (`#1668`) +- Added `AssessedCustomFee` domain model to represent assessed custom fees. (`#1637`) +- Add __repr__ method for ContractId class to improve debugging (#1714) +- Added Protobuf Training guide to enhance developer understanding of proto serialization + and deserialization (#1645) +- Add `__repr__()` method to `TopicId` class for improved debugging with constructor-style representation (#1629) +- Added guide for resolving CHANGELOG.md conflicts using GitHub's web editor (`#1591`) +- Added Windows setup guide for SDK developers (`docs/sdk_developers/training/setup/setup_windows.md`) with PowerShell installation instructions. (#1570) +- Added a beginner assignment guard that requires completion of a Good First Issue. (#1484) +- Added `/unassign` command allowing contributors to remove themselves from assigned issues.(#1472) +- Added advanced CodeRabbit reviewer guidance for `tokens` module changes, with specialized validation rules for token transactions, token classes, and enums. (#1496) +- Advanced-check bot unassigns users from issues if they do not meet the requirements and provides an explanatory message. (#1477) +- Auto-assignment bot for beginner-labeled issues with `/assign` command support and helpful reminders. (#1368) +- Added comprehensive docstring to `FeeAssessmentMethod` enum explaining inclusive vs exclusive fee assessment methods with usage examples. (#1391) +- Added comprehensive docstring to `TokenType` enum explaining fungible vs non-fungible tokens with practical use cases. (#1392) +- Enable dry run support for office hours bot via `workflow_dispatch` trigger for testing without posting comments. (#1426) +- Trigger CodeRabbit plan comment after Good First Issue assignment to provide AI-generated implementation guidance to new contributors. (#1432) + +- Added a notification workflow that alerts the support team when an issue is labeled as a Good First Issue Candidate.[(#1296)] +- Added comprehensive training documentation for the `Query` class, covering execution flow, payments, retries, and building child queries. (#1238) +- Beginner issue documentation and updated GFI and GFIC templates and documentation +- Enable auto assignment to good first issues (#1312), archived good first issue support team notification. Changed templates with new assign instruction. +- Intermediate issue documentation +- Added unit test for 'endpoint.py' to increase coverage. +- Automated assignment guard for `advanced` issues; requires completion of at least one `good first issue` and one `intermediate` issue before assignment (exempts maintainers, committers, and triage members). (#1142) +- Added Hbar object support for TransferTransaction HBAR transfers: +- Methods now accept `Union[int, Hbar]` for amount parameters with immediate normalization to tinybars +- Includes comprehensive unit tests covering various Hbar units (HBAR, MICROBAR, NANOBAR, TINYBAR) and accumulation behavior with mixed `int` and `Hbar` inputs +- Added a module-level docstring to the HBAR allowance approval example to clarify delegated spending behavior and key concepts. [#1202](https://github.com/hiero-ledger/hiero-sdk-python/issues/1202) +- Added a GitHub Actions workflow to validate broken Markdown links in pull requests. +- Added method chaining examples to the developer training guide (`docs/sdk_developers/training/coding_token_transactions.md`) (#1194) +- Added documentation explaining how to pin GitHub Actions to specific commit SHAs (`docs/sdk_developers/how-to-pin-github-actions.md`)(#1211) +- examples/mypy.ini for stricter type checking in example scripts +- Formatted examples/tokens directory using black code formatter for consistent code style +- Added `.github/workflows/bot-coderabbit-plan-trigger.yml` to automatically invoke CodeRabbit's plan feature on intermediate and advanced issues, providing implementation guidance to help contributors assess complexity and understand requirements. (#1289) +- Added a GitHub Actions workflow that reminds contributors to link pull requests to issues. +- Added `__str__` and `__repr__` methods to `AccountInfo` class for improved logging and debugging experience (#1098) +- Added Good First Issue (GFI) management and frequency documentation to clarify maintainer expectations and SDK-level GFI governance. +- Added SDK-level Good First Issue (GFI) guidelines for maintainers to clarify what qualifies as a good first issue. +- Codecov workflow +- Added unit tests for `key_format.py` to improve coverage. +- Fix inactivity bot execution for local dry-run testing. +- Added Good First Issue candidate guidelines documentation (`docs/maintainers/good_first_issue_candidate_guidelines.md`) and Good First Issues guidelines documentation (`docs/maintainers/good_first_issues_guidelines.md`) (#1066) +- Added documentation: "Testing GitHub Actions using Forks" (`docs/sdk_developers/training/testing_forks.md`). +- Documentation: created docs/maintainers/hiero_python_sdk_team.md +- Unified the inactivity-unassign bot into a single script with `DRY_RUN` support, and fixed handling of cross-repo PR references for stale detection. +- Added unit tests for `SubscriptionHandle` class covering cancellation state, thread management, and join operations. +- Refactored `account_create_transaction_create_with_alias.py` example by splitting monolithic function into modular functions: `generate_main_and_alias_keys()`, `create_account_with_ecdsa_alias()`, `fetch_account_info()`, `print_account_summary()` (#1016) +- Added `.github/workflows/bot-pr-auto-draft-on-changes.yml` to automatically convert PRs to draft and notify authors when reviewers request changes. +- Add beginner issue template +- Add relevant examples to the beginner issue template +- Add Github CODEOWNERS +- Modularized `transfer_transaction_fungible` example by introducing `account_balance_query()` & `transfer_transaction()`.Renamed `transfer_tokens()` → `main()` +- Phase 2 of the inactivity-unassign bot: Automatically detects stale open pull requests (no commit activity for 21+ days), comments with a helpful InactivityBot message, closes the stale PR, and unassigns the contributor from the linked issue. +- Added `__str__()` to CustomFixedFee and updated examples and tests accordingly. +- Added unit tests for `crypto_utils` (#993) +- Added a github template for good first issues +- Added `.github/workflows/bot-assignment-check.yml` to limit non-maintainers to 2 concurrent issue assignments. +- Configured coderabbit with a `.coderabbit.yaml` +- Added `.github/workflows/bot-community-calls` and its script to notify issue creators of a community call +- Added all missing fields to `__str__()` method and updated `test_tokem_info.py` +- Add examples/tokens/token_create_transaction_pause_key.py example demonstrating token pause/unpause behavior and pause key usage (#833) +- Added `docs/sdk_developers/training/transaction_lifecycle.md` to explain the typical lifecycle of executing a transaction using the Hedera Python SDK. +- Add inactivity bot workflow to unassign stale issue assignees (#952) +- Made custom fraction fee end to end +- feat: AccountCreateTransaction now supports both PrivateKey and PublicKey [#939](https://github.com/hiero-ledger/hiero-sdk-python/issues/939) +- Added Acceptance Criteria section to Good First Issue template for better contributor guidance (#997) +- Added `__str__()` to CustomRoyaltyFee and updated examples and tests accordingly (#986) +- Restore bug and feature request issue templates (#996)(https://github.com/hiero-ledger/hiero-sdk-python/issues/996) +- Support selecting specific node account ID(s) for queries and transactions and added `Network._get_node()` with updated execution flow (#362) +- Add TLS support with two-stage control (`set_transport_security()` and `set_verify_certificates()`) for encrypted connections to Hedera networks. TLS is enabled by default for hosted networks (mainnet, testnet, previewnet) and disabled for local networks (solo, localhost) (#855) +- Add PR inactivity reminder bot for stale pull requests `.github/workflows/pr-inactivity-reminder-bot.yml` +- Add comprehensive training documentation for \_Executable class `docs/sdk_developers/training/executable.md` +- Added empty `docs/maintainers/good_first_issues.md` file for maintainers to write Good First Issue guidelines (#1034) +- Added new `.github/ISSUE_TEMPLATE/04_good_first_issue_candidate.yml` file (1068)(https://github.com/hiero-ledger/hiero-sdk-python/issues/1068) +- Enhanced `.github/ISSUE_TEMPLATE/01_good_first_issue.yml` with welcoming message and acceptance criteria sections to guide contributors in creating quality GFIs (#1052) +- Add workflow to notify team about P0 issues `bot-p0-issues-notify-team.yml` +- Added Issue Reminder (no-PR) bot, .github/scripts/issue_reminder_no_pr.sh and .github/workflows/bot-issue-reminder-no-pr.yml to automatically detect assigned issues with no linked pull requests for 7+ days and post a gentle ReminderBot comment.(#951) +- Add support for include_children in TransactionGetReceiptQuery (#1100)(https://github.com/hiero-ledger/hiero-sdk-python/issues/1100) +- Add new `.github/ISSUE_TEMPLATE/05_intermediate_issue.yml` file (1072)(https://github.com/hiero-ledger/hiero-sdk-python/issues/1072) +- Add a workflow to notify the team when issues are labeled as “good first issues” or identified as candidates for that label: `bot-gfi-notify-team.yml`(#1115) +- Added **str** and **repr** to AccountBalance +- Added GitHub workflow that makes sure newly added test files follow pytest test files naming conventions (#1054) +- Added advanced issue template +- Added advanced issue template for contributors `.github/ISSUE_TEMPLATE/06_advanced_issue.yml`. +- Add new tests to `tests/unit/topic_info_query_test.py` (#1124) +- Added `coding_token_transactions.md` for a high level overview training on how token transactions are created in the python sdk. +- Added prompt for codeRabbit on how to review /examples ([#1180](https://github.com/hiero-ledger/hiero-sdk-python/issues/1180)) +- Add Linked Issue Enforcer to automatically close PRs without linked issues `.github/workflows/bot-linked-issue-enforcer.yml`. +- Added support for include duplicates in get transaction receipt query (#1166) +- Added `.github/workflows/cron-check-broken-links.yml` workflow to perform scheduled monthly Markdown link validation across the entire repository with automatic issue creation for broken links ([#1210](https://github.com/hiero-ledger/hiero-sdk-python/issues/1210)) +- Added `transfer_transaction_tinybar.py` example demonstrating tinybar transfers with both integer and Hbar object approaches. ([#1249](https://github.com/hiero-ledger/hiero-sdk-python/issues/1249)) +- Added `transfer_transaction_gigabar.py` example demonstrating `GIGABAR` unit usage for large-value transfers. ([#1249](https://github.com/hiero-ledger/hiero-sdk-python/issues/1249)) +- Coderabbit prompt for .github +- Added convenient factory methods to `Hbar` class for easier instantiation: `from_microbars()`, `from_millibars()`, `from_hbars()`, `from_kilobars()`, `from_megabars()`, and `from_gigabars()`. [#1272](https://github.com/hiero-ledger/hiero-sdk-python/issues/1272) +- Added merge conflict bot workflow (`.github/workflows/bot-merge-conflict.yml`) and helper script (`.github/scripts/bot-merge-conflict.js`) to detect and notify about PR merge conflicts, with retry logic for unknown mergeable states, idempotent commenting, and push-to-main recheck logic (#1247) +- Added workflow to prevent assigning intermediate issues to contributors without prior Good First Issue completion (#1143). +- Added `Client.from_env()` and network-specific factory methods (e.g., `Client.for_testnet()`) to simplify client initialization and reduce boilerplate. [[#1251](https://github.com/hiero-ledger/hiero-sdk-python/issues/1251)] +- Improved unit test coverage for `TransactionId` class, covering parsing logic, hashing, and scheduled transactions. +- Add contract_id support for CryptoGetAccountBalanceQuery([#1293](https://github.com/hiero-ledger/hiero-sdk-python/issues/1293)) +- Support for setting `max_query_payment`, `Query.set_max_query_payment()` allows setting a per-query maximum Hbar payment and `Client.set_default_max_query_payment()` sets a client-wide default maximum payment. +- Chained Good First Issue assignment with mentor assignment to bypass GitHub's anti-recursion protection - mentor assignment now occurs immediately after successful user assignment in the same workflow execution. (#1369) +- Add GitHub Actions script and workflow for automatic spam list updates. +- Added technical docstrings and hardening (set -euo pipefail) to the pr-check-test-files.sh script (#1336) +- Added prompt for coderabbit to review `Query` and it's sub-classes. +- Updated the mentor assignment bot welcome message to be more structured. ([#1487](https://github.com/hiero-ledger/hiero-sdk-python/issues/1487)) +- Add StakingInfo class ([1364](https://github.com/hiero-ledger/hiero-sdk-python/issues/1364)) +- Added a visible confirmation comment when a user unassigns themselves from an issue (#1506) +- Added first-class support for EVM address aliases in `AccountId`, including parsing, serialization, Mirror Node population helpers. +- Add automated bot to recommend next issues to contributors after their first PR merge (#1380) +- Added dry-run support and refactored `.github/workflows/bot-workflows.yml` to use dedicated script `.github/scripts/bot-workflows.js` for improved maintainability and testability. (`#1288`) +- Added MirrorNode based population for `ContractId`, including parsing and serialization support. +- Added `/working` command to reset the inactivity timer on issues and PRs. ([#1552](https://github.com/hiero-ledger/hiero-sdk-python/issues/1552)) +- Added `grpc_deadline` support for transaction and query execution. +- Type hints to exception classes (`PrecheckError`, `MaxAttemptsError`, `ReceiptStatusError`) constructors and string methods. +- Added `__eq__` and `__hash__` functions for Key + +### Documentation +- Added `docs/workflows/02-architecture.md`: explains the orchestration (YAML) vs. business logic (JS) separation pattern for GitHub workflows (#1742) +- Fix relative links in `testing.md`, clean up `CONTRIBUTING.md` TOC, and normalize test file naming and paths (`#1706`) +- Added comprehensive docstring to `compress_with_cryptography` function (#1626) +- Replaced the docstring in `entity_id_helper.py` with one that is correct. (#1623) + +### Changed +- Reduced linting errors in `examples/` directory by 80% (952 → 185) by fixing docstring formatting, import ordering, and applying auto-fixes (#1768) +- Improved bot message formatting in LinkBot to display issue linking format as a code block for better clarity (#1762) +- Refactored `setup_client()` in all `examples/query/` files to use `Client.from_env()` for simplified client initialization (#1449) +- Improve the changelog check by posting informative PR comments when entries are missing or placed under a released version. (#1683) +- Updated return of to_bytes function in `src/hiero_sdk_python/transaction/transaction.py`. (#1631) +- Added missing return type `src/hiero_sdk_python/utils/entity_id_helper.py`. (#1622) +- Update `verify_freeze()` to treat only ACCOUNT_FROZEN_FOR_TOKEN as a successful freeze verification (#1515) +- Updated team.md with new triage, committers and maintainer (#1692) +- Removed outdated "Common Issues" section from CONTRIBUTING.md that referenced non-existent docs/common_issues.md (`#1665`) +- Hide the commit verification bot marker in pull request comments. +- Added missing type hints to sign method in Transaction class (#1630) +- Refactored `examples/consensus/topic_create_transaction.py` to use `Client.from_env()` (#1611) +- Updated GitHub Actions setup-node action to v6.2.0. +- chore: format tests/unit/mock_server.py with black (#1542) +- Updated actions/checkout to v6.0.1 and actions/github-script v8.0.0 in bot-next-issue-recommendation workflow (#1586) +- Expanded inactivity bot messages to include `/unassign` command information for contributors (#1555) +- Update the acceptance criteria wording in the issue templates to improve clarity and consistency for contributors (#1491) +- Add return type hint to `AccountId.__repr__` for type consistency. (#1503) +- Good First Issue template to have more guidance and renamed other templates for consistency with upstream +- Added AI usage guidelines to the Good First Issue and Beginner issue templates to guide contributors on responsible AI use. (#1490) +- Refactored `bot-verified-commits.yml` workflow to use modular JavaScript with configurable environment variables, input sanitization, dry-run mode support, and SHA-pinned actions. (#1482) +- Refactored the advanced issue assignment guard to use a single configurable variable for the required number of completed intermediate issues. (#1479) +- Align Good First Issue and Good First Issue — Candidate guidelines with the Hiero C++ SDK for clarity and consistency.(#1421) +- Make the required signed commit command explicit in all issue templates to reduce PR signing errors for contributors (#1489) +- Refactored `file_info_query.py` to use `print(info)` instead of manual formatting (#1451) +- Enable CodeRabbit walkthrough mode by default to improve PR review visibility (#1439) +- Move assignment guards to be directly inside the gfi and beginner auto assign +- Remove the commented out blocks in config.yml (#1435) +- Renamed `.github/scripts/check_advanced_requirement.sh` to `bot-advanced-check.sh` for workflow consistency (#1341) +- Difficulty guidelines to feel more welcoming +- Added global review instructions to CodeRabbit configuration to limit reviews to issue/PR scope and prevent scope creep [#1373] +- Archived unused auto draft GitHub workflow to prevent it from running (#1371) +- Added comprehensive documentation to the PR changelog check script (`.github/scripts/pr-check-changelog.sh`) to clarify behavior, inputs, permissions, and dependencies [(#1337)] +- Refactored `account_create_transaction_without_alias.py` into smaller, modular functions.(#1321) +- Renamed bot-inactivity workflow files to remove "-phase" suffix since the process no longer uses phased execution (#1339) +- Renamed the GitHub notify team script to match its corresponding workflow filename for better maintainability (#1338) +- style: apply black formatting to examples (#1299) +- Update GitHub workflow names in `.github/workflows/bot-workflows.yml` to match correct references [(#1284)] +- Updated set up and workflow documents for improved clarity and organisation +- Renamed templates for improved clarity [(#1265)] +- Updated Good First Issue notifications to trigger only after the first comment is posted, reducing noise on unassigned issues.(#1212) +- Bumped requests from 2.32.3 to 2.32.4 to 2.32.5 +- Moved `docs/sdk_developers/how_to_link_issues.md` to `docs/sdk_developers/training/workflow/how_to_link_issues.md` and updated all references (#1222) +- Moved docs/sdk_developers/project_structure.md to docs/sdk_developers/training/setup/project_structure.md and ensured all previous references are updated [#1223](https://github.com/hiero-ledger/hiero-sdk-python/issues/1223) +- Renamed workflow scripts in `.github/scripts/` to match their corresponding workflow file names for improved consistency and maintainability (#1198) +- Refactored `account_create_transaction_evm_alias.py` to improve readability by splitting the monolithic function into smaller helper functions. [#1017](https://github.com/hiero-ledger/hiero-sdk-python/issues/1017) +- Improved docstring for `account_allowance_approve_transaction_nft.py` with purpose, key concepts and required vs optional steps. +- Updated Codecov coverage thresholds in 'codecov.yml' to require 90% of project coverage and 92% of patch coverage (#1157) +- Reduce office-hours reminder spam by posting only on each user's most recent open PR, grouping by author and sorting by creation time (#1121) +- Reduce office-hours reminder spam by never posting on PRs of maintainers and committers +- Pylint cleanup for token_airdrop_transaction_cancel.py (#1081) [@tiya-15](https://github.com/tiya-15) +- Move `account_allowance_delete_transaction_hbar.py` from `examples/` to `examples/account/` for better organization (#1003) +- Improved consistency of transaction examples (#1120) +- Refactored `account_create_transaction_with_fallback_alias.py` by splitting the monolithic `create_account_with_fallback_alias` function into modular functions: `generate_fallback_key`, `fetch_account_info`, and `print_account_summary`. The existing `setup_client()` function was reused for improved readability and structure (#1018) +- Allow `PublicKey` for batch_key in `Transaction`, enabling both `PrivateKey` and `PublicKey` for batched transactions +- Allow `PublicKey` for `TokenUpdateKeys` in `TokenUpdateTransaction`, enabling non-custodial workflows where operators can build transactions using only public keys (#934). +- Bump protobuf toml to protobuf==6.33.2 +- Improved the contributing section for sdk developers in CONTRIBUTING.md for clarity and including new documentation +- chore: Move account allowance example to correct folder +- Added more tests to the CustomFee class for different functionalities (#991) +- Changed messaged for test failure summaries so it is clearer by extracting test failure names into summary +- Renamed example files to match src naming (#1053) +- Updated bot naming conventions in `.github/workflows` to be consistent (#1042) +- Renamed workflow files for consistent PR check naming: + `examples.yml` → `pr-check-examples.yml`, + `test.yml` → `pr-check-test.yml` (#1043) +- Cleaned up `token_airdrop_claim_auto` example for pylint compliance (no functional changes). (#1079) +- Formatted `examples/query` using black (#1082)(https://github.com/hiero-ledger/hiero-sdk-python/issues/1082) +- Update team notification script and workflow for P0 issues 'p0_issues_notify_team.js' +- Rename test files across the repository to ensure they consistently end with \_test.py (#1055) +- Cleaned up `token_airdrop_claim_signature_required` example for pylint compliance (no functional changes). (#1080) +- Rename the file 'test_token_fee_schedule_update_transaction_e2e.py' to make it ends with \_test.py as all other test files.(#1117) +- Format token examples with Black for consistent code style and improved readability (#1119) +- Transformed `examples/tokens/custom_fee_fixed.py` to be an end-to-end example, that interacts with the Hedera network, rather than a static object demo. +- Format token examples with Black for consistent code style and improved readability (#1119) +- Replaced `ResponseCode.get_name(receipt.status)` with the `ResponseCode(receipt.status).name` across examples and integration tests for consistency. (#1136) +- Moved helpful references to Additional Context section and added clickable links. +- Transformed `examples\tokens\custom_royalty_fee.py` to be an end-to-end example, that interacts with the Hedera network, rather than a static object demo. +- Refactored `examples/tokens/custom_royalty_fee.py` by splitting monolithic function custom_royalty_fee_example() into modular functions create_royalty_fee_object(), create_token_with_fee(), verify_token_fee(), and main() to improve readability, cleaned up setup_client() (#1169) +- Added comprehensive unit tests for Timestamp class (#1158) +- Enhance unit and integration test review instructions for clarity and coverage `.coderabbit.yaml`. +- Issue reminder bot now explicitly mentions assignees (e.g., `@user`) in comments. ([#1232](https://github.com/hiero-ledger/hiero-sdk-python/issues/1232)) +- Updated `transfer_transaction_hbar.py` example to use `Hbar` objects instead of raw integers and added receipt checking with `ResponseCode` validation.([#1249](https://github.com/hiero-ledger/hiero-sdk-python/issues/1249)) +- Renamed `pr-missing-linked-issue.yml` and `pr_missing_linked_issue.js` to `bot-pr-missing-linked-issue.yml` and `bot-pr-missing-linked-issue.js` respectively. Enhanced LinkBot PR comment with clickable hyperlinks to documentation for linking issues and creating issues. (#1264) +- Enhance assignment bot to guard against users with spam PRs `.github/scripts/bot-assignment-check.sh` +- Add CodeRabbit documentation review prompts for docs, sdk_users, and sdk_developers with priorities, philosophy, and edge case checks. ([#1236](https://github.com/hiero-ledger/hiero-sdk-python/issues/1236)) +- Enhance NodeAddress tests with additional coverage for proto conversion `tests/unit/node_address_test.py` +- Replaced deprecated `AccountCreateTransaction.set_key()` usage with `set_key_without_alias()` and `set_key_with_alias()` across examples and tests + +- Updated `pyproject.toml` to enforce stricter Ruff linting rules, including Google-style docstrings (`D`), import sorting (`I`), and modern Python syntax (`UP`). +- Modified and renamed hasIntermediateOrAdvancedLabel() to check if issue label is beginner or higher (#1385) +- Updated `.github/scripts/bot-office-hours.sh` to detect and skip PRs created by bot accounts when posting office hours reminders. (#1384) +- Refactored `examples/account/account_create_transaction_create_with_alias.py` and `examples/account/account_create_transaction_evm_alias.py` to use the native `AccountInfo.__str__` method for printing account details, replacing manual JSON serialization. ([#1263](https://github.com/hiero-ledger/hiero-sdk-python/issues/1263)) +- Enhance TopicInfo `__str__` method and tests with additional coverage, and update the format_key function in `key_format.py` to handle objects with a \_to_proto method. +- Update changelog workflow to trigger automatically on pull requests instead of manual dispatch (#1567) +- Formatted key-related unit test files (`key_utils_test.py`, `test_key_format.py`, `test_key_list.py`) using the black formatter +- Add return type hint to `ContractId.__str__`. (#1654) +- chore: update maintainer guidelines link in MAINTAINERS.md (#1605) +- chore: update merge conflict bot message with web editor tips (#1592) +- chore: update MAINTAINERS.md to include new maintainer Manish Dait and sort maintainers by GitHub ID. (#1691) +- Changed `TransactionResponse.get_receipt()` so now pins receipt queries to the submitting node via `set_node_account_ids()` ([#1686](https://github.com/hiero-ledger/hiero-sdk-python/issues/1686)) +- chore: clarify wording in the bot-assignment-check.sh (#1748) +- Refactored SDK dependencies to use version ranges, moved build-only deps out of runtime, removed unused core deps and added optional extras. + + +### Fixed +- Added a fork guard condition to prevent Codecov upload failures on fork PRs due to missing token. (`#1485`) +- Corrected broken documentation links in SDK developer training files.(#1707) +- Updated Good First Issue recommendations to supported Hiero repositories. (#1689) +- Fix the next-issue recommendation bot to post the correct issue recommendation comment. (#1593) +- Ensured that the GFI assignment bot skips posting `/assign` reminders for repository collaborators to avoid unnecessary notifications.(#1568). +- Reduced notification spam by skipping the entire advanced qualification job for non-advanced issues and irrelevant events (#1517) +- Aligned token freeze example filename references and improved error handling by catching broader exceptions with clearer messages. (#1412) +- Fixed jq syntax in bot-office-hours.sh (#1502) +- Fixed formatting of `/unassign` command in the PR inactivity reminder message so it displays correctly with backticks. (#1582) +- Prevented linkbot from commenting on or auto-closing bot-authored pull requests. (#1516) +- Respect `dry-run` input in `bot-community-calls.yml` workflow (#1425) +- Updated LinkBot regex in the GitHub Actions bot script to support "Closes" and "Resolves" keywords for improved PR body-link detection (#1465) +- Fixed CodeRabbit plan trigger workflow running multiple times when issues are created with multiple labels by switching to labeled event trigger only. (#1427) +- Prevent LinkBot from posting duplicate “missing linked issue” comments on pull requests. (#1475) +- Refined intermediate assignment guard to validate Beginner issue completion with improved logging and GraphQL-based counting. (#1424) +- Improved filename-related error handling with clearer and more descriptive error messages.(#1413) +- Good First Issue bot no longer posts `/assign` reminders for repository collaborators. (#1367) +- GFI workflow casing +- Update `bot-workflows.yml` to trigger only on open PRs with failed workflows; ignore closed PRs and branches without open PRs. +- Fixed step-security/harden-runner action SHA in merge conflict bot workflow (#1278) +- Fixed the README account balance example to use correct SDK APIs and provide a runnable testnet setup. (#1250) +- Fix token association verification in `token_airdrop_transaction.py` to correctly check if tokens are associated by using `token_id in token_balances` instead of incorrectly displaying zero balances which was misleading (#[815]) +- Fixed inactivity bot workflow not checking out repository before running (#964) +- Fixed the topic_message_query integarion test +- good first issue template yaml rendering +- Fixed solo workflow defaulting to zero +- Fix unit test tet_query.py +- TLS Hostname Mismatch & Certificate Verification Failure for Nodes +- Workflow does not contain permissions for `pr-check-test-files` and `pr-check-codecov` +- Fixed `cron-check-broken-links.yml` string parsing issue in context input `dry_run` (#1235) +- Flaky tests by disabling TLS in mock Hedera nodes in `mock_server.py` +- Fixed LinkBot permission issue for fork PRs by changing trigger to pull_request_target and adding proper permissions. +- Fixed token examples to consistently use setup_client without tuple unpacking.(#1397) +- Fixed duplicate comment prevention in issue reminder bot by adding hidden HTML marker for reliable comment detection (.github/scripts/bot-issue-reminder-no-pr.sh) (#1372) +- Fixed bot-pr-missing-linked-issue to skip commenting on pull requests created by automated bots. (#1382) +- Updated `.github/scripts/bot-community-calls.sh` to skip posting reminders on issues created by bot accounts. (#1383) +- Fixed incorrect run instructions and broaden error handling in `token_dissociate_transaction.py` example to improve usability for new users (#1468) +- Update `.github/scripts/bot-advanced-check.sh` to unassign unqualified users. +- Fixed broken project structure link in `CONTRIBUTING.md` (#1664) +- Refactor spam list update logic and remove unused pull request creation step `.github/scripts/update-spam-list.js` `.github/workflows/cron-update-spam-list.yml`. +- Ensure all Query sub-class `execute()` function to correctly propagate the optional `timeout` parameter. +- Refactor assignment time retrieval and open PR check to use GraphQL API instead of REST API `.github/scripts/bot-issue-reminder-no-pr.sh` (#1746) + +### Removed + +- Deleted `examples/utils.py` as its helper functions are no longer needed. ([#1263](https://github.com/hiero-ledger/hiero-sdk-python/issues/1263)) + +### Breaking Change + +- Remove deprecated 'in_tinybars' parameter and update related tests `/src/hiero_sdk_python/hbar.py`, `/tests/unit/hbar_test.py` and `/src/hiero_sdk_python/tokens/custom_fixed_fee.py`. + +## [0.1.10] - 2025-12-03 + +### Added + +- Added docs/sdk_developers/training/workflow: a training for developers to learn the workflow to contribute to the python SDK. +- Added Improved NFT allowance deletion flow with receipt-based status checks and strict `SPENDER_DOES_NOT_HAVE_ALLOWANCE` verification. +- Add `max_automatic_token_associations`, `staked_account_id`, `staked_node_id` and `decline_staking_reward` fields to `AccountUpdateTransaction` (#801) +- Added docs/sdk_developers/training/setup: a training to set up as a developer to the python sdk +- Add example demonstrating usage of `CustomFeeLimit` in `examples/transaction/custom_fee_limit.py` +- Added `.github/workflows/merge-conflict-bot.yml` to automatically detect and notify users of merge conflicts in Pull Requests. +- Added `.github/workflows/bot-office-hours.yml` to automate the Weekly Office Hour Reminder. +- feat: Implement account creation with EVM-style alias transaction example. +- Added validation logic in `.github/workflows/pr-checks.yml` to detect when no new chnagelog entries are added under [Unreleased]. +- Support for message chunking in `TopicSubmitMessageTransaction`. + +### Changed + +- bot workflows to include new changelog entry +- Removed duplicate import of transaction_pb2 in transaction.py +- Refactor `TokenInfo` into an immutable dataclass, remove all setters, and rewrite `_from_proto` as a pure factory for consistent parsing [#800] +- feat: Add string representation method for `CustomFractionalFee` class and update `custom_fractional_fee.py` example. +- Moved query examples to their respective domain folders to improve structure matching. + +### Fixed + +- fixed workflow: changelog check with improved sensitivity to deletions, additions, new releases + +## [0.1.9] - 2025-11-26 + +### Added + +- Add a limit of one comment for PR to the commit verification bot. [#892] +- Removed `actions/checkout@v4` from `bot-verified-commits.yml` +- Add comprehensive documentation for `ReceiptStatusError` in `docs/sdk_developers/training/receipt_status_error.md` +- Add practical example `examples/errors/receipt_status_error.py` demonstrating transaction error handling +- Document error handling patterns and best practices for transaction receipts +- fix `pull_request` to `pull_request_target` in `bot-verified-commits.yml` +- Add more robust receipt checks and removed fallback to `examples/tokens/token_delete_transaction.py` +- Add detail to `token_airdrop.py` and `token_airdrop_cancel.py` +- Add workflow: github bot to respond to unverified PR commits (#750) +- Add workflow: bot workflow which notifies developers of workflow failures in their pull requests. +- Add `examples/token_create_transaction_max_automatic_token_associations_0.py` to demonstrate how `max_automatic_token_associations=0` behaves. +- Add `examples/topic_id.py` to demonstrate `TopicId` opeartions +- Add `examples/topic_message.py` to demonstrate `TopicMessage` and `TopicMessageChunk` with local mock data. +- Added missing validation logic `fee_schedule_key` in integration `token_create_transaction_e2e_test.py` and ``token_update_transaction_e2e_test.py`. +- Add `account_balance_query.py` example to demonstrate how to use the CryptoGetAccountBalanceQuery class. +- Add `examples/token_create_transaction_admin_key.py` demonstrating admin key privileges for token management including token updates, key changes, and deletion (#798) +- Add `examples/token_create_transaction_freeze_key.py` showcasing freeze key behavior, expected failures without the key, and the effect of freezing/unfreezing on transfers. +- Add `examples/account_info.py` to demonstrate `AccountInfo` opeartions +- Added `HbarUnit` class and Extend `Hbar` class to handle floating-point numbers +- Add `examples/topic_info.py` to demonstrate `TopicInfo` operations. +- feat: Allow `PrivateKey` to be used for keys in `TopicCreateTransaction` for consistency. +- EvmAddress class +- `alias`, `staked_account_id`, `staked_node_id` and `decline_staking_reward` fields to AccountCreateTransaction +- `staked_account_id`, `staked_node_id` and `decline_staking_reward` fields to AccountInfo +- Added `examples/token_create_transaction_supply_key.py` to demonstrate token creation with and without a supply key. +- Added `examples/token_create_transaction_kyc_key.py` to demonstrate KYC key functionality, including creating tokens with/without KYC keys, granting/revoking KYC status, and understanding KYC requirements for token transfers. +- Add `set_token_ids`, `_from_proto`, `_validate_checksum` to TokenAssociateTransaction [#795] +- Added BatchTransaction class +- Add support for token metadata (bytes, max 100 bytes) in `TokenCreateTransaction`, including a new `set_metadata` setter, example, and tests. [#799] +- Added `examples/token_create_transaction_token_fee_schedule.py` to demonstrate creating tokens with custom fee schedules and the consequences of not having it. +- Added `examples/token_create_transaction_wipe_key.py` to demonstrate token wiping and the role of the wipe key. +- Added `examples/account_allowance_approve_transaction_hbar.py` and `examples/account_allowance_delete_transaction_hbar.py`, deleted `examples/account_allowance_hbar.py`. [#775] +- Added `docs\sdk_developers\training\receipts.md` as a training guide for users to understand hedera receipts. +- Add `set_token_ids`, `_from_proto`, `_validate_checksum` to TokenAssociateTransaction [#795] +- docs: added `network_and_client.md` with a table of contents, and added external example scripts (`client.py`). + +### Changed + +- Upgraded step-security/harden-runner v2.13.2 +- bumped actions/checkout from 5.0.0 to 6.0.0 +- Limit workflow bot to one message per PR +- Refactored token-related example scripts (`token_delete.py`, `token_dissociate.py`, etc.) for improved readability and modularity. [#370] +- upgrade: step security action upgraded from harden-runner-2.13.1 to harden-runner-2.13.1 +- chore: Split `examples/account_allowance_nft.py` into separate `account_allowance_approve_transaction_nft.py` and `account_allowance_delete_transaction_nft.py` examples. +- chore: bump protobuf from 6.33.0 to 6.33.1 (#796) +- fix: Allow `max_automatic_token_associations` to be set to -1 (unlimited) in `AccountCreateTransaction` and add field to `AccountInfo`. +- Allow `PrivateKey` to be used for keys in `TopicCreateTransaction` for consistency. +- Update github actions checkout from 5.0.0 to 5.0.1 (#814) +- changed to add concurrency to workflow bot +- feat: Refactor `TokenDissociateTransaction` to use set_token_ids method and update transaction fee to Hbar, also update `transaction.py` and expand `examples/token_dissociate.py`, `tests/unit/token_dissociate.py`. + +### Fixed + +- chore: updated solo action to avoid v5 +- chore: fix test.yml workflow to log import errors (#740) +- chore: fixed integration test names without a test prefix or postfix +- Staked node ID id issue in the account_create_transationt_e2e_test +- workflow: verified commits syntax for verfication bot + +## [0.1.8] - 2025-11-07 + +### Added + +- `is_unknown` property added to `src/hiero_sdk_python/response_code.py` +- Example `response_code.py` +- Add `TokenFeeScheduleUpdateTransaction` class to support updating custom fee schedules on tokens (#471). +- Add `examples/token_update_fee_schedule_fungible.py` and `examples/token_update_fee_schedule_nft.py` demonstrating the use of `TokenFeeScheduleUpdateTransaction`. +- Update `docs/sdk_users/running_examples.md` to include `TokenFeeScheduleUpdateTransaction`. +- added FreezeTransaction class +- added FreezeType class +- Added `docs/sdk_developers/pylance.md`, a new guide explaining how to set up and use **Pylance** in VS Code for validating imports, file references, and methods before review. (#713) +- feat: TokenAirdropClaim Transaction, examples (with signing required and not), unit and integration tests (#201) +- docs: Add Google-style docstrings to `TokenId` class and its methods in `token_id.py`. +- added Google-style docstrings to the `TransactionRecord` class including all dataclass fields, `__repr__`, `_from_proto()` & `_to_proto()` methods. +- Standardized docstrings, improved error handling, and updated type hinting (`str | None` to `Optional[str]`) for the `FileId` class (#652). +- Add Google-style docstrings to `AccountInfo` class and its methods in `account_info.py`. +- Added comprehensive Google-style docstrings to the `Logger` class and all utility functions in `src/hiero_sdk_python/logger/logger.py` (#639). +- add AccountRecordsQuery class +- chore: added python 3.13 to test.yml workflow (#510, #449) +- Transaction bytes serialization support: `Transaction.freeze()`, `Transaction.to_bytes()`, and `Transaction.from_bytes()` methods for offline signing and transaction storage +- docs: Add Google-style docstrings to `ContractId` class and methods in `contract_id.py`. +- Added TokenUnpauseTransaction class +- Added expiration_time, auto_renew_period, auto_renew_account, fee_schedule_key, kyc_key in `TokenCreateTransaction`, `TokenUpdateTransaction` classes +- Added comprehensive Google-style docstrings to the `CustomFee` class and its methods in `custom_fee.py`. +- docs: Add `docs/sdk_developers/project_structure.md` to explain repository layout and import paths. + +### Changed +- chore: renamed examples to match src where possible +- Moved examples/ to be inside subfiles to match src structure +- changed example script workflow to run on new subdirectory structure +- chore: bumped solo action from 14.0 to 15.0 (#764) +- chore: replaced hardcoded 'testnet' messages with environment network name +- chore: validate that token airdrop transactions require an available token service on the channel (#632) +- chore: update local environment configuration in env.example (#649) +- chore: Update env.example NETWORK to encourage testnet or local usage (#659) +- chore: updated pyproject.toml with python 3.10 to 3.13 (#510, #449) +- chore: fix type hint for TokenCancelAirdropTransaction pending_airdrops parameter +- chore: Moved documentation file `common_issues.md` from `examples/sdk_developers/` to `docs/sdk_developers/` for unified documentation management (#516). +- chore: Refactored the script of examples/custom_fee.py into modular functions +- fix: Replaced `collections.namedtuple` with `typing.NamedTuple` in `client.py` for improved type checking. +- chore: Refactored examples/custom_fee.py into three separate example files. +- Expanded `docs/sdk_developers/checklist.md` with a self-review guide for all pull request submission requirements (#645). +- Expanded docs/sdk_developers/signing.md to clarify GPG and DCO requirements and add a Table of Contents (#455). +- chore: Standardized client initialization across all examples/ files to promote consistency (#658). +- chore: changed the file names of airdrop examples, classes, unit and integration tests so they are grouped together. (#631) +- Refactor `AbstractTokenTransferTransaction` to unify Token/NFT transfer logic. + +### Fixed + +- Added explicit read permissions to examples.yml (#623) +- Removed deprecated Logger.warn() method and legacy parameter swap logic from get_logger() (#673). +- Improved type hinting in `file_append_transaction.py` to resolve 'mypy --strict` errors. ([#495](https://github.com/hiero-ledger/hiero-sdk-python/issues/495)) +- fix: Resolve `__eq__` type conflict in `CustomFee` class (#627) +- Fixes a type conflict in `token_id.py` where `from_string` could receive `None`, preventing a runtime error by raising a `ValueError` if the input is missing. #630 +- Dependabot alerts (version bumps) +- Fixed incorrect `TokenType` import (protobuf vs. SDK enum) in 18 example files. +- Update `schedule_sign_transaction_e2e_test` to check for key presence instead of relying on index. +- Add `localhost` and `local` as network names + +### Breaking Changes + +- chore: changed the file names airdrop classes (#631) + {pending_airdrop_id.py -> token_airdrop_pending_id.py} + {pending_airdrop_record.py -> token_airdrop_pending_record.py} + {token_cancel_airdrop_transaction.py -> token_airdrop_transaction_cancel.py} + +- In `TokenAirdropTransaction` the parameters of the following methods have been renamed: + - add_nft_transfer(sender → sender_id, receiver → receiver_id) + - add_approved_nft_transfer(sender → sender_id, receiver → receiver_id) + +## [0.1.7] - 2025-10-28 + +### Added + +- Expanded `README.md` with a new "Follow Us" section detailing how to watch, star, and fork the repository (#472). +- Refactored `examples/topic_create.py` into modular functions for better readability and reuse. +- Add Rebasing and Signing section to signing.md with instructions for maintaining commit verification during rebase operations (#556) +- Add `examples/account_id.py` demonstrating AccountId class usage including creating standard AccountIds, parsing from strings, comparing instances, and creating AccountIds with public key aliases +- Added Google-style docstrings to `CustomFractionalFee` class and its methods in `custom_fractional_fee.py`. +- Added `dependabot.yaml` file to enable automated dependency management. +- Common issues guide for SDK developers at `examples/sdk_developers/common_issues.md` +- Added documentation for resolving changelog conflicts in `docs/common_issues.md` +- Added comprehensive changelog entry guide at `docs/sdk_developers/changelog.md` to help contributors create proper changelog entries (#532). +- docs: Added Google-style docstrings to `CustomFixedFee` class and its methods in `custom_fixed_fee.py`. +- docs: Add Google-style docstrings to `CustomRoyaltyFee` class and its methods in `custom_royalty_fee.py`. +- docs: Add Google-style docstrings to `AbstractTokenTransferTransaction` class and its methods in `abstract_token_transfer_transaction.py`. +- docs: Add Google-style docstrings to `TokenRelationship` class and its methods in `token_relationship.py`. +- feat: add initial testing guide structure +- Added `checksum` filed for TopicId, FileId, ContractId, ScheduleId class +- Added workflow for running example scripts. +- docs: workflow.md documenting key steps to creating a pull request (#605) +- chore: fix the examples workflow to log error messages and run on import failure (#738) +- Added `docs/discord.md` explaining how to join and navigate the Hiero community Discord (#614). + +### Changed + +- Added direct links to Python SDK channel in Linux Foundation Decentralized Trust Discord back in +- Updated all occurrences of non-functional Discord invite links throughout the documentation with the new, stable Hyperledger and Hedera invite links (#603). +- Refactored TopicId class to use @dataclass decorator for reducing boilerplate code +- Renamed `examples/nft_allowance.py` to `examples/account_allowance_nft.py` for consistency with account class naming scheme +- Added changelog conflict resolution examples to `docs/common_issues.md` +- Refactored `examples/topic_create.py` to be more modular by splitting functions and renaming `create_topic()` to `main()`. +- Refactored `examples/transfer_hbar.py` to improve modularity by separating transfer and balance query operations into dedicated functions +- Enhanced contributing section in README.md with resource links +- Refactored examples/topic_message_submit.py to be more modular +- Added "One Issue Per Pull Request" section to `examples/sdk_developers/common_issues.md`. +- docs: Improved the contributing section in the README.md file +- Refactored `examples/transfer_nft.py` to be more modular by isolating transfer logic. +- Refactored `examples/file_append.py` into modular functions for better readability, reuse, and consistency across examples. +- Ensured identical runtime behavior and output to the previous version to maintain backward compatibility. +- Renamed `examples/hbar_allowance.py` to `examples/account_allowance_hbar.py` for naming consistency +- Converted monolithic function in `token_create_nft_infinite.py` to multiple modular functions for better structure and ease. +- docs: Use relative paths for internal GitHub links (#560). +- Update pyproject.toml maintainers list. + – docs: Updated README.md/CHANGELOG.md and added blog.md, bud.md and setup.md (#474) +- renamed docs/sdk_developers/changelog.md to docs/sdk_developers/changelog_entry.md for clarity. +- Refactor `query_balance.py` into modular, reusable functions with `setup_client()`, `create_account()`, `get_balance()`, `transfer_hbars()`, and `main()` for improved readability, maintainability, and error handling. +- Unified balance and transfer logging format — both now consistently display values in hbars for clarity. + +### Fixed + +- Add type hints to `setup_client()` and `create_new_account()` functions in `examples/account_create.py` (#418) +- Added explicit read and write permissions to test.yml +- Type hinting for `Topic` related transactions. + +### Removed + +- Remove deprecated camelCase alias support and `_DeprecatedAliasesMixin`; SDK now only exposes snake_case attributes for `NftId`, `TokenInfo`, and `TransactionReceipt`. (Issue #428) + +## [0.1.6] - 2025-10-21 + +### Added + +- Add comprehensive Google-style docstrings to examples/account_create.py +- add revenue generating topic tests/example +- add fee_schedule_key, fee_exempt_keys, custom_fees fields in TopicCreateTransaction, TopicUpdateTransaction, TopicInfo classes +- add CustomFeeLimit class +- TokenNftAllowance class +- TokenAllowance class +- HbarAllowance class +- HbarTransfer class +- AccountAllowanceApproveTransaction class +- AccountAllowanceDeleteTransaction class +- FileAppendTransaction class +- Documentation examples for Allowance Approve Transaction, Allowance Delete Transaction, and File Append Transaction +- Approved transfer support to TransferTransaction +- set_transaction_id() API to Transaction class +- Allowance examples (hbar_allowance.py, token_allowance.py, nft_allowance.py) +- Refactored examples/logging_example.py for better modularity (#478) + +### Changed + +- TransferTransaction refactored to use TokenTransfer and HbarTransfer classes instead of dictionaries +- Added checksum validation for TokenId +- Refactor examples/token_cancel_airdrop +- Refactor token creation examples for modularity and consistency +- Updated `signing.md` to clarify commit signing requirements, including DCO, GPG, and branch-specific guidelines (#459) + +### Changed + +- Rearranged running_examples.md to be alphabetical +- Refactor token_associate.py for better structure, add association verification query (#367) +- Refactored `examples/account_create.py` to improve modularity and readability (#363) +- Replace Hendrik Ebbers with Sophie Bulloch in the MAINTAINERS.md file +- Improved `CONTRIBUTING.md` by explaining the /docs folder structure and fixing broken hyperlinks.(#431) +- Converted class in `token_nft_info.py` to dataclass for simplicity. + +### Fixed + +- Incompatible Types assignment in token_transfer_list.py +- Corrected references to \_require_not_frozen() and removed the surplus \_is_frozen +- Removed duplicate static methods in `TokenInfo` class: +   - `_copy_msg_to_proto` +   - `_copy_key_if_present` +   - `_parse_custom_fees` +   Kept robust versions with proper docstrings and error handling. +- Add strict type hints to `TransactionGetReceiptQuery` (#420) +- Fixed broken documentation links in CONTRIBUTING.md by converting absolute GitHub URLs to relative paths +- Updated all documentation references to use local paths instead of pointing to hiero-sdk project hub + +## [0.1.5] - 2025-09-25 + +### Added + +- ScheduleSignTransaction class +- NodeUpdateTransaction class +- NodeDeleteTransaction class +- ScheduleDeleteTransaction class +- prng_number and prng_bytes properties in TransactionRecord +- PrngTransaction class +- ScheduleInfoQuery class +- ScheduleInfo class +- Exposed node_id property in `TransactionReceipt` +- NodeCreateTransaction class +- ScheduleId() class +- ScheduleCreateTransaction() class +- build_scheduled_body() in every transaction +- ContractDeleteTransaction class +- ContractExecuteTransaction class +- setMessageAndPay() function in StatefulContract +- AccountDeleteTransaction Class +- generate_proto.py +- Bumped Hedera proto version from v0.57.3 to v0.64.3 +- Added `dev` and `lint` dependency groups as default in `pyproject.toml` +- EthereumTransaction class +- AccountId support for ECDSA alias accounts +- ContractId.to_evm_address() method for EVM compatibility +- consumeLargeData() function in StatefulContract +- example script for Token Airdrop +- added variables directly in the example script to reduce the need for users to supply extra environment variables. +- Added new `merge_conflicts.md` with detailed guidance on handling conflicts during rebase. +- Type hinting to /tokens, /transaction, /query, /consensus +- Linting to /tokens, /transaction, /query, /consensus +- Module docstrings in /tokens, /transaction, /query, /consensus +- Function docstrings in /tokens, /transaction, /query, /consensus + +### Changed + +- bump solo version to `v0.14` +- bump protobufs version to `v0.66.0` +- bump solo version to `v0.13` +- Extract \_build_proto_body() from build_transaction_body() in every transaction +- StatefulContract's setMessage() function designed with no access restrictions, allowing calls from any address +- bump solo version to `v0.12` +- Extract Ed25519 byte loading logic into private helper method `_from_bytes_ed25519()` +- Documentation structure updated: contents moved from `/documentation` to `/docs`. +- Switched Mirror Node endpoints used by SDK to secure ones instead of deprecated insecure endpoints (shut down on Aug 20th, see [Hedera blogpost](https://hedera.com/blog/updated-deprecation-of-the-insecure-hedera-consensus-service-hcs-mirror-node-endpoints)) +- Update protobuf dependency from 5.28.1 to 5.29.1 +- Update grpcio dependency from 1.68.1 to 1.71.2 +- Updated `rebasing.md` with clarification on using `git reset --soft HEAD~` where `` specifies the number of commits to rewind. +- Calls in examples for PrivateKey.from_string_ed25519(os.getenv('OPERATOR_KEY')) to PrivateKey.from_string(os.getenv('OPERATOR_KEY')) to enable general key types +- Add CI tests across Python 3.10–3.12. +- kyc_status: Optional[TokenFreezeStatusProto] = None → kyc_status: Optional[TokenKycStatus] = None +- assert relationship.freeze_status == TokenFreezeStatus.FROZEN, f"Expected freeze status to be FROZEN, but got {relationship.freeze_status}" → assert relationship.freeze_status == TokenFreezeStatus.UNFROZEN, f"Expected freeze status to be UNFROZEN, but got {relationship.freeze_status}" + +### Fixed + +- Format account_create_transaction.py and add type hints +- Format account_balance.py and fix pylint issues +- Format account_delete_transaction.py and fix pylint issues +- Format account_id.py and fix pylint issues +- Format account_info.py and fix pylint issues +- Format account_update_transaction.py and fix pylint issues +- Unit test compatibility issues when running with UV package manager +- Type annotations in TokenRelationship class (kyc_status and freeze_status) +- Test assertions in test_executable.py using pytest match parameter +- Moved and renamed README_upstream.md to docs/sdk_developers/rebasing.md +- Invalid DRE Hex representation in examples/keys_private_ecdsa.py +- Windows malformed path using uv run generate_proto.py using as_posix() +- Changed README MIT license to Apache +- deprecated CamelCase instances in /examples such as TokenId and totalSupply to snake_case +- Invalid HEX representation and signature validation in keys_public_ecdsa.py +- Invalid signature verification for examples/keys_public_der.py +- Duplicate validation function in TokenCreate + +### Removed + +- Removed the old `/documentation` folder. +- Rebase command in README_upstream changed to just -S +- generate_proto.sh +- pkg_resources dependency in generate_proto.py + +### Breaking API changes + +- We have some changed imports and returns to maintain compatability in the proto bump + +transaction_body_pb2.TransactionBody -> transaction_pb2.TransactionBody +contract_call_local_pb2.ContractFunctionResult -> contract_types_pb2.ContractFunctionResult +contract_call_local_pb2.ContractLoginfo -> contract_types_pb2.ContractLoginfo + +- Removed init.py content in /tokens + +**Changed imports** + +- src/hiero_sdk_python/consensus/topic_message.py: from hiero_sdk_python import Timestamp → from hiero_sdk_python.timestamp import Timestamp +- src/hiero_sdk_python/query/topic_message_query.py: from hiero_sdk_python import Client → from hiero_sdk_python.client.client import Client +- src/hiero_sdk_python/tokens/**init**.py: content removed. +- src/hiero_sdk_python/tokens/token_info.py: from hiero_sdk_python.hapi.services.token_get_info_pb2 import TokenInfo as proto_TokenInfo → from hiero_sdk_python.hapi.services import token_get_info_pb2 +- src/hiero_sdk_python/tokens/token_key_validation.py: from hiero_sdk_python.hapi.services → import basic_types_pb2 +- src/hiero_sdk_python/tokens/token_kyc_status.py: from hiero_sdk_python.hapi.services.basic_types_pb2 import TokenKycStatus as proto_TokenKycStatus → from hiero_sdk_python.hapi.services import basic_types_pb2 +- src/hiero_sdk_python/tokens/token_pause_status.py: from hiero_sdk_python.hapi.services.basic_types_pb2 import (TokenPauseStatus as proto_TokenPauseStatus,) → from hiero_sdk_python.hapi.services import basic_types_pb2 +- src/hiero_sdk_python/tokens/token_pause_transaction.py: from hiero_sdk_python.hapi.services.token_pause_pb2 import TokenPauseTransactionBody → from hiero_sdk_python.hapi.services import token_pause_pb2, transaction_pb2 +- from hiero_sdk_python.hapi.services.token_revoke_kyc_pb2 import TokenRevokeKycTransactionBody → from hiero_sdk_python.hapi.services import token_revoke_kyc_pb2, transaction_pb2 +- src/hiero_sdk_python/tokens/token_update_nfts_transaction.py: from hiero_sdk_python.hapi.services.token_update_nfts_pb2 import TokenUpdateNftsTransactionBody → from hiero_sdk_python.hapi.services import token_update_nfts_pb2,transaction_pb2 +- src/hiero_sdk_python/tokens/token_wipe_transaction.py: from hiero_sdk_python.hapi.services.token_wipe_account_pb2 import TokenWipeAccountTransactionBody → from hiero_sdk_python.hapi.services import token_wipe_account_pb2, transaction_pb2 + +## [0.1.4] - 2025-08-19 + +### Added + +- CONTRIBUTING.md: expanded documentation detailing various contribution processes in a step-by-step way. Includes new sections: blog posts and support. +- README_upstream.md: documentation explaining how to rebase to main. + +### Added + +- Legacy ECDSA DER parse support +- documented private key from_string method behavior +- ContractInfo class +- ContractInfoQuery class +- ContractID check in PublicKey.\_from_proto() method +- PendingAirdropId Class +- PendingAirdropRecord Class +- TokenCancelAirdropTransaction Class +- AccountUpdateTransaction class +- ContractBytecodeQuery class +- SimpleStorage.bin-runtime +- Support for both .bin and .bin-runtime contract bytecode extensions in contract_utils.py +- ContractUpdateTransaction class + +### Fixed + +- missing ECDSA support in query.py and contract_create_transaction.py (was only creating ED25519 keys) +- Applied linting and code formatting across the consensus module +- fixed pip install hiero_sdk_python -> pip install hiero-sdk-python in README.md + +### Breaking API changes + +**We have several camelCase uses that will be deprecated → snake_case** Original aliases will continue to function, with a warning, until the following release. + +#### In `token_info.py` + +- tokenId → token_id +- totalSupply → total_supply +- isDeleted → is_deleted +- tokenType → token_type +- maxSupply → max_supply +- adminKey → admin_key +- kycKey → kyc_key +- freezeKey → freeze_key +- wipeKey → wipe_key +- supplyKey → supply_key +- defaultFreezeStatus → default_freeze_status +- defaultKycStatus → default_kyc_status +- autoRenewAccount → auto_renew_account +- autoRenewPeriod → auto_renew_period +- pauseStatus → pause_status +- supplyType → supply_type + +#### In `nft_id.py` + +- tokenId → token_id +- serialNumber → serial_number + +#### In `transaction_receipt.py` + +- tokenId → token_id +- topicId → topic_id +- accountId → account_id +- fileId → file_id + +### Deprecated Additions + +- logger.warn will be deprecated in v0.1.4. Please use logger.warning instead. +- get_logger method passing (name, level) will be deprecated in v0.1.4 for (level, name). + +## [0.1.3] - 2025-07-03 + +### Added + +- TokenType Class +- MAINTAINERS.md file +- Duration Class +- NFTTokenCreateTransaction Class +- TokenUnfreezeTransaction +- Executable Abstraction +- Logger +- Node Implementation +- Integration Tests across the board +- TokenWipeTransaction Class +- TokenNFTInfoQuery Class +- TokenInfo Class +- TokenRejectTransaction Class +- TokenUpdateNftsTransaction Class +- TokenInfoQuery Class +- TokenPauseTransaction Class +- TokenBurnTransaction Class +- TokenGrantKycTransaction Class +- TokenUpdateTransaction Class +- added Type hinting and initial methods to several modules +- TokenRevoceKycTransaction Class +- [Types Guide](hiero/hedera_sdk_python/documentation/sdk_developers/types.md) + +- TransactionRecordQuery Class +- AccountInfoQuery Class + +### Changed + +- replace datetime.utcnow() with datetime.now(timezone.utc) for Python 3.10 +- updated pr-checks.yml +- added add_require_frozen() to Transaction Base Class +- added NFT Transfer in TransferTransaction +- bumped solo-actions to latest release +- updated to/from_proto method to be protected +- Example scripts updated to be easily run form root +- README updated +- added PublicKey.from_proto to PublicKey class +- changed Query Class to have method get_cost +- SimpleContract and StatefulContract constructors to be payable +- added new_pending_airdrops to TransactionRecord Class +- Reorganized SDK developer documentation: +   - Renamed and moved `README_linting.md` to `linting.md` +   - Renamed and moved `README_types.md` to `types.md` +   - Renamed and moved `Commit_Signing.md` to `signing.md` +- Created `sdk_users` docs folder and renamed `examples/README.md` to `running_examples.md` +- Updated references and links accordingly + +### Fixed + +- fixed INVALID_NODE_ACCOUNT during node switching +- fixed ed25519 key ambiguity (PrivateKey.from_string -> PrivateKey.from_string_ed25519 in examples) + +### Removed + +- Redundant test.py file + +## [0.1.2] - 2025-03-12 + +### Added + +- NFTId Class + +### Changed + +- use SEC1 ECPrivateKey instead of PKCS#8 + +### Fixed + +- PR checks +- misnamed parameter (ECDSASecp256k1=pub_bytes -> ECDSA_secp256k1=pub_bytes) + +### Removed + +- .DS_store file + +## [0.1.1] – 2025-02-25 + +### Added + +- RELEASE.md +- CONTRIBUTING.md + +### Changed + +- README now split into root README for project overview and /examples README for transaction types and syntax. +- Python version incremented from 3.9 to 3.10 + +### Removed + +- pdm.lock & uv.lock file + +## [0.1.0] - 2025-02-19 + +### Added + +- Initial release of the Python SDK core functionality. +- Basic documentation on how to install and use the SDK. +- Example scripts illustrating setup and usage. + +### Changed + +- N/A + +### Fixed + +- N/A + +### Removed + +- N/A + + +# [0.1.0] - 2025-02-19 From af8b99952146474bdd7fe2c759c5b34c36abb0f3 Mon Sep 17 00:00:00 2001 From: Manish Dait Date: Mon, 16 Feb 2026 14:38:13 +0530 Subject: [PATCH 10/25] chore: fix the unit test Signed-off-by: Manish Dait --- tests/unit/transaction_test.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/unit/transaction_test.py b/tests/unit/transaction_test.py index 231dc71a4..34a46f5bf 100644 --- a/tests/unit/transaction_test.py +++ b/tests/unit/transaction_test.py @@ -271,6 +271,7 @@ def test_tx_without_optional_fields_should_have_smaller_tx_body( .set_initial_balance(Hbar(2)) .set_transaction_id(transaction_id) .set_node_account_id(account_id) + .set_alias(PrivateKey.generate_ecdsa().public_key().to_evm_address()) .set_transaction_valid_duration(10) .freeze() ) @@ -361,9 +362,8 @@ def test_chunked_tx_return_proper_sizes(file_id, account_id, transaction_id): small_size = small_tx.size - # Since large content is 2KB and chunk size is 1KB, this should create 2 chunks # Size should be greater than single chunk size - large_size > 1024 + assert large_size > 1024 - # The larger chunked transaction should be bigger than the small single-chunk transaction - large_size > small_size + # The larger chunked transaction should be bigger than the single-chunk transaction + assert large_size > small_size From a223cbe81dbaf4b7ddd9003c1f4ffbfd77c5f0a0 Mon Sep 17 00:00:00 2001 From: Manish Dait Date: Sat, 21 Mar 2026 00:31:32 +0530 Subject: [PATCH 11/25] chore: fix rebase Signed-off-by: Manish Dait --- tests/unit/transaction_test.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/unit/transaction_test.py b/tests/unit/transaction_test.py index 34a46f5bf..5b1519b61 100644 --- a/tests/unit/transaction_test.py +++ b/tests/unit/transaction_test.py @@ -6,6 +6,9 @@ from hiero_sdk_python.account.account_id import AccountId from hiero_sdk_python.crypto.private_key import PrivateKey from hiero_sdk_python.exceptions import ReceiptStatusError +from hiero_sdk_python.file.file_append_transaction import FileAppendTransaction +from hiero_sdk_python.file.file_create_transaction import FileCreateTransaction +from hiero_sdk_python.file.file_id import FileId from hiero_sdk_python.hapi.services import ( basic_types_pb2, response_header_pb2, @@ -14,10 +17,12 @@ transaction_receipt_pb2, transaction_response_pb2, ) +from hiero_sdk_python.hbar import Hbar from hiero_sdk_python.response_code import ResponseCode from hiero_sdk_python.tokens.token_id import TokenId from hiero_sdk_python.tokens.token_mint_transaction import TokenMintTransaction from hiero_sdk_python.transaction.transaction_id import TransactionId +from hiero_sdk_python.transaction.transaction_id import TransactionId from hiero_sdk_python.transaction.transaction_receipt import TransactionReceipt from hiero_sdk_python.transaction.transaction_response import TransactionResponse from tests.unit.mock_server import mock_hedera_servers @@ -26,6 +31,23 @@ pytestmark = pytest.mark.unit +@pytest.fixture +def file_id(): + """Returns a file_is for test.""" + return FileId.from_string("0.0.1") + + +@pytest.fixture +def account_id(): + """Returns an account_id for test.""" + return AccountId.from_string("0.0.9") + + +@pytest.fixture +def transaction_id(): + """Returns a transaction_id for test.""" + return TransactionId.from_string("0.0.9@1770911831.331000137") + def test_execute_waits_for_receipt_receipt(): """Test execute return TransactionReceipt when wait_for_receipt is True (default).""" From 7f3a4f39deb4079fab5b4bd008ff501b7c02d2fe Mon Sep 17 00:00:00 2001 From: Manish Dait Date: Sun, 22 Mar 2026 13:23:11 +0530 Subject: [PATCH 12/25] chore: added test for topic message submit tx Signed-off-by: Manish Dait --- .../topic_message_submit_transaction_test.py | 11 +++++ tests/unit/transaction_test.py | 49 +++++++++++++++++-- 2 files changed, 55 insertions(+), 5 deletions(-) diff --git a/tests/unit/topic_message_submit_transaction_test.py b/tests/unit/topic_message_submit_transaction_test.py index 8afa46b0d..f2761f0cc 100644 --- a/tests/unit/topic_message_submit_transaction_test.py +++ b/tests/unit/topic_message_submit_transaction_test.py @@ -504,3 +504,14 @@ def test_topic_submit_execute_returns_failed_receipt_by_default(topic_id): receipt = tx.execute(client) assert receipt.status == ResponseCode.INVALID_SIGNATURE + +def test_topic_submit_message_raises_error_on_freeze(topic_id): + """Test transaction raises error on freeze when the transaction_id and node_id not set""" + tx = ( + TopicMessageSubmitTransaction() + .set_topic_id(topic_id) + .set_message("Hello Hiero") + ) + + with pytest.raises(ValueError): + tx.freeze() diff --git a/tests/unit/transaction_test.py b/tests/unit/transaction_test.py index 5b1519b61..a60847f37 100644 --- a/tests/unit/transaction_test.py +++ b/tests/unit/transaction_test.py @@ -4,6 +4,8 @@ from hiero_sdk_python.account.account_create_transaction import AccountCreateTransaction from hiero_sdk_python.account.account_id import AccountId +from hiero_sdk_python.consensus.topic_id import TopicId +from hiero_sdk_python.consensus.topic_message_submit_transaction import TopicMessageSubmitTransaction from hiero_sdk_python.crypto.private_key import PrivateKey from hiero_sdk_python.exceptions import ReceiptStatusError from hiero_sdk_python.file.file_append_transaction import FileAppendTransaction @@ -33,7 +35,7 @@ @pytest.fixture def file_id(): - """Returns a file_is for test.""" + """Returns a file_id for test.""" return FileId.from_string("0.0.1") @@ -301,8 +303,8 @@ def test_tx_without_optional_fields_should_have_smaller_tx_body( assert tx1.body_size < tx2.body_size -def test_chunk_tx_should_return_list_of_body_sizes(file_id, account_id, transaction_id): - """Test should return array of body sizes for multi-chunk transaction.""" +def test_file_append_chunk_tx_should_return_list_of_body_sizes(file_id, account_id, transaction_id): + """Test file append tx should return array of body sizes for multi-chunk transaction.""" chunk_size = 1024 content = "a" * (chunk_size * 3) @@ -321,8 +323,8 @@ def test_chunk_tx_should_return_list_of_body_sizes(file_id, account_id, transact assert len(sizes) == 3 -def test_single_chunk_tx_return_list_of_len_one(file_id, account_id, transaction_id): - """Test should return array of one size for single-chunk transaction.""" +def test_file_append_single_chunk_tx_return_list_of_len_one(file_id, account_id, transaction_id): + """Test file append tx should return array of one size for single-chunk transaction.""" content = "small_content" tx = ( FileAppendTransaction() @@ -338,6 +340,43 @@ def test_single_chunk_tx_return_list_of_len_one(file_id, account_id, transaction assert len(sizes) == 1 +def test_message_submit_chunk_tx_should_return_list_of_body_sizes(topic_id, account_id, transaction_id): + """Test topic message submit tx should return array of body sizes for multi-chunk transaction.""" + chunk_size = 1024 + message= "a" * (chunk_size * 3) + + tx = ( + TopicMessageSubmitTransaction() + .set_topic_id(topic_id) + .set_chunk_size(chunk_size) + .set_message(message) + .set_transaction_id(transaction_id) + .set_node_account_id(account_id) + .freeze() + ) + + sizes = tx.body_size_all_chunks + assert isinstance(sizes, list) + assert len(sizes) == 3 + + +def test_message_submit_single_chunk_tx_return_list_of_len_one(topic_id, account_id, transaction_id): + """Test topic message submit tx should return array of one size for single-chunk transaction.""" + message = "small_content" + tx = ( + TopicMessageSubmitTransaction() + .set_topic_id(topic_id) + .set_message(message) + .set_transaction_id(transaction_id) + .set_node_account_id(account_id) + .freeze() + ) + + sizes = tx.body_size_all_chunks + assert isinstance(sizes, list) + assert len(sizes) == 1 + + def test_tx_with_no_content_should_return_single_body_chunk( file_id, account_id, transaction_id ): From 01c8fee7dd83a03790e5c709de43e4de46be910c Mon Sep 17 00:00:00 2001 From: Manish Dait Date: Tue, 24 Mar 2026 23:48:16 +0530 Subject: [PATCH 13/25] chore: fix the transaction_id to return original one Signed-off-by: Manish Dait --- .../consensus/topic_message_submit_transaction.py | 2 ++ src/hiero_sdk_python/file/file_append_transaction.py | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/hiero_sdk_python/consensus/topic_message_submit_transaction.py b/src/hiero_sdk_python/consensus/topic_message_submit_transaction.py index 4b67d57e7..d80ccd8cd 100644 --- a/src/hiero_sdk_python/consensus/topic_message_submit_transaction.py +++ b/src/hiero_sdk_python/consensus/topic_message_submit_transaction.py @@ -419,10 +419,12 @@ def body_size_all_chunks(self) -> List[int]: sizes = [] original_index = self._current_index + original_transaction_id = self.transaction_id for transaction_id in self._transaction_ids: self.transaction_id = transaction_id sizes.append(self.body_size) self._current_index = original_index + self.transaction_id = original_transaction_id return sizes \ No newline at end of file diff --git a/src/hiero_sdk_python/file/file_append_transaction.py b/src/hiero_sdk_python/file/file_append_transaction.py index 01f73161a..48398b13b 100644 --- a/src/hiero_sdk_python/file/file_append_transaction.py +++ b/src/hiero_sdk_python/file/file_append_transaction.py @@ -481,10 +481,12 @@ def body_size_all_chunks(self) -> List[int]: sizes = [] original_index = self._current_chunk_index + original_transaction_id = self.transaction_id for transaction_id in self._transaction_ids: self.transaction_id = transaction_id sizes.append(self.body_size) self._current_chunk_index = original_index + self.transaction_id = original_transaction_id return sizes From 147aa97a2ee3f3efc95183b7fc4fe2aa63d3c320 Mon Sep 17 00:00:00 2001 From: Manish Dait Date: Tue, 24 Mar 2026 23:48:47 +0530 Subject: [PATCH 14/25] chore: imporve freeze_with to work with the client without operator Signed-off-by: Manish Dait --- .../transaction/transaction.py | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/hiero_sdk_python/transaction/transaction.py b/src/hiero_sdk_python/transaction/transaction.py index df2992be7..1d26364b0 100644 --- a/src/hiero_sdk_python/transaction/transaction.py +++ b/src/hiero_sdk_python/transaction/transaction.py @@ -248,7 +248,7 @@ def freeze(self): """ return self.freeze_with(None) - def freeze_with(self, client): + def freeze_with(self, client: "Client"): """ Freezes the transaction by building the transaction body and setting necessary IDs. @@ -266,20 +266,27 @@ def freeze_with(self, client): # Check transaction_id and node id to be set when using freeze() - if client is None: - if self.transaction_id is None: + if self.transaction_id is None: + if client is not None: + operator_account_id = client.operator_account_id + if operator_account_id is not None: + self.transaction_id = client.generate_transaction_id() + else: + raise ValueError( + "Client must have an operator_account or transactionId must be set." + ) + else: raise ValueError( "Transaction ID must be set before freezing. Use freeze_with(client) or set_transaction_id()." ) - - if self.node_account_id is None and len(self.node_account_ids) == 0: + + + if self.node_account_id is None and len(self.node_account_ids) == 0: + if client is None: raise ValueError( "Node account ID must be set before freezing. Use freeze_with(client) or manually set node_account_ids." ) - if self.transaction_id is None: - self.transaction_id = client.generate_transaction_id() - # We iterate through every node in the client's network # For each node, set the node_account_id and build the transaction body # This allows the transaction to be submitted to any node in the network From 52379e6c9088e03bf918259b0e4ffca560097182 Mon Sep 17 00:00:00 2001 From: Manish Dait Date: Wed, 25 Mar 2026 01:15:19 +0530 Subject: [PATCH 15/25] chore: added some suggesttions Signed-off-by: Manish Dait --- src/hiero_sdk_python/transaction/transaction.py | 2 +- tests/integration/file_append_transaction_e2e_test.py | 7 ++++--- tests/unit/mock_server.py | 4 ++++ 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/hiero_sdk_python/transaction/transaction.py b/src/hiero_sdk_python/transaction/transaction.py index 1d26364b0..50dadb7e9 100644 --- a/src/hiero_sdk_python/transaction/transaction.py +++ b/src/hiero_sdk_python/transaction/transaction.py @@ -408,7 +408,7 @@ def is_signed_by(self, public_key): return any(sig_pair.pubKeyPrefix == public_key_bytes for sig_pair in sig_map.sigPair) - def build_transaction_body(self) -> transaction_pb2.Transaction: + def build_transaction_body(self) -> transaction_pb2.TransactionBody: """ Abstract method to build the transaction body. diff --git a/tests/integration/file_append_transaction_e2e_test.py b/tests/integration/file_append_transaction_e2e_test.py index 7396d8b31..eb05160c3 100644 --- a/tests/integration/file_append_transaction_e2e_test.py +++ b/tests/integration/file_append_transaction_e2e_test.py @@ -314,12 +314,13 @@ def test_file_append_chuck_transaction_can_execute_with_manual_freeze(env): .set_file_id(file_id) .set_chunk_size(1024) .set_contents(content) - .freeze_with(env.client) + .set_transaction_id(TransactionId.generate(env.client.operator_account_id)) + .set_node_account_id(AccountId(0,0,3)) + .freeze() ) - # tx.sign(env.client.operator_private_key) + tx.sign(env.client.operator_private_key) - print(tx.get_required_chunks()) receipt = tx.execute(env.client) assert receipt.status == ResponseCode.SUCCESS diff --git a/tests/unit/mock_server.py b/tests/unit/mock_server.py index 3ee264b4f..59f2b6e4f 100644 --- a/tests/unit/mock_server.py +++ b/tests/unit/mock_server.py @@ -180,6 +180,10 @@ def mock_hedera_servers(response_sequences): node._close() client = Client(network) + + for node in client.network.nodes: + node._address = node._address._to_insecure() + client.logger.set_level(LogLevel.DISABLED) # Set the operator key = PrivateKey.generate() From 5d646983008d090ab011c8d5c1f70075ceaef4d0 Mon Sep 17 00:00:00 2001 From: Manish Dait Date: Wed, 25 Mar 2026 18:58:09 +0530 Subject: [PATCH 16/25] chore: neat pick Signed-off-by: Manish Dait --- pyproject.toml | 2 + .../topic_message_submit_transaction.py | 8 +--- .../file/file_append_transaction.py | 3 ++ src/hiero_sdk_python/node.py | 2 + .../transaction/transaction.py | 37 ++++++++++++------- .../file_append_transaction_e2e_test.py | 4 +- tests/unit/mock_server.py | 5 ++- 7 files changed, 37 insertions(+), 24 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index a77a6dc02..411aae9d2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,6 +21,8 @@ dependencies = [ "pycryptodome>=3.18.0,<4", "eth-abi>=5.1.0,<6", "python-dotenv>=1.2.1,<3", + "pytest-repeat>=0.9.4", + "pytest-xdist>=3.8.0", ] classifiers = [ "Development Status :: 2 - Pre-Alpha", diff --git a/src/hiero_sdk_python/consensus/topic_message_submit_transaction.py b/src/hiero_sdk_python/consensus/topic_message_submit_transaction.py index d80ccd8cd..4bae2758d 100644 --- a/src/hiero_sdk_python/consensus/topic_message_submit_transaction.py +++ b/src/hiero_sdk_python/consensus/topic_message_submit_transaction.py @@ -253,13 +253,7 @@ def freeze_with(self, client: Client) -> TopicMessageSubmitTransaction: if self._transaction_body_bytes: return self - if self.transaction_id is None: - if client is None: - raise ValueError( - "Transaction ID must be set before freezing. Use freeze_with(client) or set_transaction_id()." - ) - - self.transaction_id = client.generate_transaction_id() + self._resolve_transaction_id(client) if not self._transaction_ids: base_timestamp = self.transaction_id.valid_start diff --git a/src/hiero_sdk_python/file/file_append_transaction.py b/src/hiero_sdk_python/file/file_append_transaction.py index 48398b13b..45b6442bd 100644 --- a/src/hiero_sdk_python/file/file_append_transaction.py +++ b/src/hiero_sdk_python/file/file_append_transaction.py @@ -295,6 +295,9 @@ def freeze_with(self, client: Client) -> FileAppendTransaction: self.transaction_id = client.generate_transaction_id() + + self._resolve_transaction_id(client) + # Generate transaction IDs for all chunks if not self._transaction_ids: base_timestamp = self.transaction_id.valid_start diff --git a/src/hiero_sdk_python/node.py b/src/hiero_sdk_python/node.py index 9fba5cf6c..4512fd454 100644 --- a/src/hiero_sdk_python/node.py +++ b/src/hiero_sdk_python/node.py @@ -126,6 +126,8 @@ def _get_channel(self): if self._root_certificates: # Use the certificate that is provided self._node_pem_cert = self._root_certificates + print("node cert ", self._node_pem_cert) + else: # Fetch pem_cert for the node self._node_pem_cert = self._fetch_server_certificate_pem() diff --git a/src/hiero_sdk_python/transaction/transaction.py b/src/hiero_sdk_python/transaction/transaction.py index 50dadb7e9..1df441f02 100644 --- a/src/hiero_sdk_python/transaction/transaction.py +++ b/src/hiero_sdk_python/transaction/transaction.py @@ -226,7 +226,28 @@ def _to_proto(self): signed_transaction = transaction_contents_pb2.SignedTransaction(bodyBytes=body_bytes, sigMap=sig_map) - return transaction_pb2.Transaction(signedTransactionBytes=signed_transaction.SerializeToString()) + + return transaction_pb2.Transaction( + signedTransactionBytes=signed_transaction.SerializeToString() + ) + + def _resolve_transaction_id(self, client: "Client"): + if self.transaction_id is not None: + return + + if client is not None: + operator_account_id = client.operator_account_id + if operator_account_id is not None: + self.transaction_id = client.generate_transaction_id() + else: + raise ValueError( + "Client must have an operator_account or transactionId must be set." + ) + else: + raise ValueError( + "Transaction ID must be set before freezing. Use freeze_with(client) or set_transaction_id()." + ) + def freeze(self): """ @@ -266,19 +287,7 @@ def freeze_with(self, client: "Client"): # Check transaction_id and node id to be set when using freeze() - if self.transaction_id is None: - if client is not None: - operator_account_id = client.operator_account_id - if operator_account_id is not None: - self.transaction_id = client.generate_transaction_id() - else: - raise ValueError( - "Client must have an operator_account or transactionId must be set." - ) - else: - raise ValueError( - "Transaction ID must be set before freezing. Use freeze_with(client) or set_transaction_id()." - ) + self._resolve_transaction_id(client) if self.node_account_id is None and len(self.node_account_ids) == 0: diff --git a/tests/integration/file_append_transaction_e2e_test.py b/tests/integration/file_append_transaction_e2e_test.py index eb05160c3..167931cfe 100644 --- a/tests/integration/file_append_transaction_e2e_test.py +++ b/tests/integration/file_append_transaction_e2e_test.py @@ -292,7 +292,7 @@ def test_integration_file_append_transaction_method_chaining(env): assert append_receipt.status == ResponseCode.SUCCESS @pytest.mark.integration -def test_file_append_chuck_transaction_can_execute_with_manual_freeze(env): +def test_file_append_chunk_transaction_can_execute_with_manual_freeze(env): """Test file append transaction can execute with manual freeze.""" create_receipt = ( FileCreateTransaction() @@ -307,7 +307,7 @@ def test_file_append_chuck_transaction_can_execute_with_manual_freeze(env): file_contents = FileContentsQuery().set_file_id(file_id).execute(env.client) assert file_contents == b"" - content = "A" * (4000) # content with (1024 * 14) bytes ie 14 chunks + content = "A" * (4000) # content with (4000/1024) bytes ie approx 4 chunks tx = ( FileAppendTransaction() diff --git a/tests/unit/mock_server.py b/tests/unit/mock_server.py index 59f2b6e4f..1d4febf20 100644 --- a/tests/unit/mock_server.py +++ b/tests/unit/mock_server.py @@ -181,8 +181,11 @@ def mock_hedera_servers(response_sequences): client = Client(network) + # Force non-tls channel for node in client.network.nodes: - node._address = node._address._to_insecure() + node._address._is_transport_security = lambda: False + node._set_verify_certificates(False) + node._close() client.logger.set_level(LogLevel.DISABLED) # Set the operator From 381fae3493b770ce35762ce4973194838b3593a1 Mon Sep 17 00:00:00 2001 From: Manish Dait Date: Wed, 25 Mar 2026 21:24:26 +0530 Subject: [PATCH 17/25] chore: cyvlometic codacy fix Signed-off-by: Manish Dait --- src/hiero_sdk_python/transaction/transaction.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/hiero_sdk_python/transaction/transaction.py b/src/hiero_sdk_python/transaction/transaction.py index 1df441f02..3389f5404 100644 --- a/src/hiero_sdk_python/transaction/transaction.py +++ b/src/hiero_sdk_python/transaction/transaction.py @@ -247,7 +247,13 @@ def _resolve_transaction_id(self, client: "Client"): raise ValueError( "Transaction ID must be set before freezing. Use freeze_with(client) or set_transaction_id()." ) - + + def _resolve_node_ids(self, client: "Client"): + if self.node_account_id is None and len(self.node_account_ids) == 0: + if client is None: + raise ValueError( + "Node account ID must be set before freezing. Use freeze_with(client) or manually set node_account_ids." + ) def freeze(self): """ @@ -290,12 +296,8 @@ def freeze_with(self, client: "Client"): self._resolve_transaction_id(client) - if self.node_account_id is None and len(self.node_account_ids) == 0: - if client is None: - raise ValueError( - "Node account ID must be set before freezing. Use freeze_with(client) or manually set node_account_ids." - ) - + self._resolve_node_ids(client) + # We iterate through every node in the client's network # For each node, set the node_account_id and build the transaction body # This allows the transaction to be submitted to any node in the network From db49e98d0fe11826d33c543024affb49016bad40 Mon Sep 17 00:00:00 2001 From: Manish Dait Date: Wed, 25 Mar 2026 23:02:25 +0530 Subject: [PATCH 18/25] chore: fix pyptojectoml Signed-off-by: Manish Dait --- pyproject.toml | 2 -- 1 file changed, 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 411aae9d2..a77a6dc02 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,8 +21,6 @@ dependencies = [ "pycryptodome>=3.18.0,<4", "eth-abi>=5.1.0,<6", "python-dotenv>=1.2.1,<3", - "pytest-repeat>=0.9.4", - "pytest-xdist>=3.8.0", ] classifiers = [ "Development Status :: 2 - Pre-Alpha", From 4bc809724f693d55910df976cab98da3af133463 Mon Sep 17 00:00:00 2001 From: Manish Dait Date: Tue, 7 Apr 2026 13:21:00 +0530 Subject: [PATCH 19/25] chore: make some neetpick Signed-off-by: Manish Dait --- .../consensus/topic_message_submit_transaction.py | 7 +++---- src/hiero_sdk_python/file/file_append_transaction.py | 8 ++++---- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/hiero_sdk_python/consensus/topic_message_submit_transaction.py b/src/hiero_sdk_python/consensus/topic_message_submit_transaction.py index 4bae2758d..dcb3c7b93 100644 --- a/src/hiero_sdk_python/consensus/topic_message_submit_transaction.py +++ b/src/hiero_sdk_python/consensus/topic_message_submit_transaction.py @@ -4,6 +4,7 @@ from typing import Literal, overload from hiero_sdk_python.channels import _Channel +from typing import List, Literal, Optional, overload from hiero_sdk_python.client.client import Client from hiero_sdk_python.consensus.topic_id import TopicId from hiero_sdk_python.crypto.private_key import PrivateKey @@ -405,10 +406,8 @@ def sign(self, private_key: PrivateKey): return self @property - def body_size_all_chunks(self) -> List[int]: - """ - Returns an array of body sizes for transactions with multiple chunks. - """ + def body_size_all_chunks(self) -> list[int]: + """Returns an array of body sizes for transactions with multiple chunks.""" self._require_frozen() sizes = [] diff --git a/src/hiero_sdk_python/file/file_append_transaction.py b/src/hiero_sdk_python/file/file_append_transaction.py index 45b6442bd..3ff8a126b 100644 --- a/src/hiero_sdk_python/file/file_append_transaction.py +++ b/src/hiero_sdk_python/file/file_append_transaction.py @@ -16,6 +16,7 @@ import math from typing import TYPE_CHECKING, Any, Literal, overload +from typing import TYPE_CHECKING, Any, List, Literal, Optional, overload from hiero_sdk_python.file.file_id import FileId from hiero_sdk_python.hapi.services import file_append_pb2, timestamp_pb2 from hiero_sdk_python.hapi.services.schedulable_transaction_body_pb2 import ( @@ -32,6 +33,7 @@ from hiero_sdk_python.client import Client from hiero_sdk_python.crypto.private_key import PrivateKey + from hiero_sdk_python.channels import _Channel from hiero_sdk_python.executable import _Method from hiero_sdk_python.transaction.transaction import TransactionReceipt from hiero_sdk_python.transaction.transaction_response import TransactionResponse @@ -476,10 +478,8 @@ def sign(self, private_key: PrivateKey) -> FileAppendTransaction: @property - def body_size_all_chunks(self) -> List[int]: - """ - Returns an array of body sizes for transactions with multiple chunks. - """ + def body_size_all_chunks(self) -> list[int]: + """Returns an array of body sizes for transactions with multiple chunks.""" self._require_frozen() sizes = [] From f2efa73400dce9e2565cf69cea7466eefe85e7be Mon Sep 17 00:00:00 2001 From: Manish Dait Date: Mon, 13 Apr 2026 14:51:37 +0530 Subject: [PATCH 20/25] chore: fix rebase Signed-off-by: Manish Dait --- CHANGELOG.md | 1053 ---------------------------------- src/hiero_sdk_python/node.py | 1 - 2 files changed, 1054 deletions(-) delete mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index c7a40f281..000000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,1053 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file. -This project adheres to [Semantic Versioning](https://semver.org). -This changelog is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). - -## [Unreleased] - -### Src -- Exposed all missing `TransactionRecord` protobuf fields `consensusTimestamp`, `scheduleRef`, `assessed_custom_fees`, `automatic_token_associations`, `parent_consensus_timestamp`, `alias`, `ethereum_hash`, `paid_staking_rewards`, `evm_address`, `contractCreateResult` with proper `None` handling, PRNG oneof handling with unset values return `None` instead of default values 0 / b"" (#1636) -- Added Transaction size calculation properties `size`, `body_size` and `body_size_all_chunks`. - -### Tests -- Refactor `mock_server` setup for network level TLS handling and added thread safety - - -### Examples - -- Add the missing `setup_client()` docstring in `examples/tokens/token_dissociate_transaction.py` for consistency with the other example functions. (#2058) - -### Docs - - -### .github -- chore: pin pip packages to exact versions in publish.yml to improve supply chain security and reproducibility (#2056) -- chore: update GitHub Actions runners from ubuntu-latest to hl-sdk-py-lin-md (#2021) -- Refactored the Advanced Issue Template to V2 with stricter prerequisites and a focus on architectural design (#2016). -- Refactored the Advanced Issue Template to ensure PR-level quality checklists do not block maintainers during issue creation (#2036) -- Add automated label sync workflow to propagate labels from linked issues to pull requests (#1716) -- chore: update spam list (#2035) - -## [0.2.3] - 2026-03-26 - -### Added -- Add `__repr__` method to `TokenId` class for cleaner debugging output (#1653) - -### Src -- Updated `AccountUpdateTransaction.set_key()` to accept generic `Key` objects (including `KeyList` and threshold keys), rather than strictly requiring a `PublicKey`. -- Fix the TransactionGetReceiptQuery to raise ReceiptStatusError for the non-retryable and non success receipt status -- Refactor `AccountInfo` to use the existing `StakingInfo` wrapper class instead of flattened staking fields. Access is now via `info.staking_info.staked_account_id`, `info.staking_info.staked_node_id`, and `info.staking_info.decline_reward`. The old flat accessors (`info.staked_account_id`, `info.staked_node_id`, `info.decline_staking_reward`) are still available as deprecated properties and will emit a `DeprecationWarning`. (#1366) -- Added abstract `Key` supper class to handle various proto Keys. - - -### Examples - -### Tests -- Added TCK endpoint for the createAccount method -- Renamed `delegate_contract_id.py` to `delegate_contract_id_test.py` (#2004) -- Fix Flaky tests for `mock_server` by enforcing non-tls port and adding a mock_tls certificate -- Implement basic fuzz testing [#1872](https://github.com/hiero-ledger/hiero-sdk-python/issues/1872) - - -### Docs -- Add Chocolatey as a prerequisite in the Windows setup guide (#1961) - - -### .github -- chore: update several ubuntu runners to hl-sdk-py-lin-md (#1480) -- Refactored intermediate issue template with quality standards, testing requirements, breaking change awareness, and protobuf verification guidance to reduce review burden and improve PR quality (#1892) -- fix: prevent CodeRabbit from posting comments on closed issues(#1962) -- chore: update spam list #1988 -- chore: Update `bot-advanced-check.yml`, `bot-gfi-assign-on-comment.yml`, `bot-intermediate-assignment.yml`, `bot-linked-issue-enforcer.yml`, `unassign-on-comment.yml`, `working-on-comment.yml` workflow runner configuration -- Fix build failing in `publish.yml` - - - -## [0.2.2] - 2026-03-17 - -### Added -- Added CodeRabbit review instructions in `.coderabbit.yaml` for account module `src/hiero_sdk_python/account/`. -- Add support for `include_children` to TransactionRecordQuery ([#1512](https://github.com/hiero-ledger/hiero-sdk-python/issues/1512)) - -### Changed -- Changed pytest version to "pytest>=8.3.4,<10" (#1917) -- Update protobuf schema version to v0.72.0-rc.2 in `.coderabbit.yaml` - -### Src -- Updated `generated_proto.py` file to work with new proto version -- fix: Ensure UTF-8 encoding when reading and writing proto files in `generate_proto.py` to prevent encoding issues on Windows (`#1963`) - -### Examples -- Updated the `examples/consensus/topic_create_transaction_revenue_generating.py` example to use `Client.from_env()` for simpler client setup. (#1964) - -- Refactored `examples/consensus/topic_delete_transaction.py` to use Client.from_env() for simplified client initialization, removed manual setup code, and cleaned up unused imports (`os`, `AccountId`, `PrivateKey`). (`#1971`) - -### Tests - -### Docs -- Replaced relative documentation links in `README.md` with absolute GitHub URLs to fix broken PyPI rendering. -- docs: Clarified AI usage in Good First Issues templates. (#1923) -- docs: Moved the Windows setup guide to docs/sdk_developers/ and added missing setup sections. (`#1953`) - - - -### .github -- chore: ensure uv run uses lowest-direct resolution in deps-check workflow (#1919) -- Added PR draft explainer workflow to comment when PRs are converted to draft after changes are requested. (#1723) -- changed `pr-check-test` to run unit matrix first, run integration matrix only after unit success, skip docs/examples/.github-only changes, and parallelize integration tests with xdist (`#1878`) -- archived workflows relating to PR reminders -- chore: switch workflow runner from ubuntu-latest to hl-sdk-py-lin-md for bot-assignment-check.yml workflow -- chore: update concurrency group for GFI assignment workflow to prevent race conditions (`#1910`) -- chore: switch workflow runner from ubuntu-latest to hl-sdk-py-lin-md for bot-beginner-assign-on-comment workflow -- chore: update bot-coderabbit-plan-trigger workflow to use self-hosted runner (`#1925`) -- Require contributors to complete 1 beginner issue before they can be assigned an intermediate issue (#1939) -- Expand spam list (#1933) -- Expand spam list (#1972) -- chore: add ndpvt-web to spam list (#1945) -- chore: update bot-community-calls workflow to use self hosted runner (#1942) -- chore(ci): update bot-inactivity-unassign workflow to use hl-sdk-py-lin-md runner -- chore: update bot-gfi-candidate-notification workflow to use hl-sdk-py-lin-md runner (`#1966`) -## [0.2.1] - 2026-03-05 - -### Added - -- Added unit test and __repr__ for NftId class(#1627). -- Added CodeRabbit review instructions for the nodes module in `.coderabbit.yaml` (#1699) -- Added CodeRabbit review instructions for the transaction module in `.coderabbit.yaml` (#1696) -- Added CodeRabbit review instructions and path mapping for the schedule module (`src/hiero_sdk_python/schedule/`) in `.coderabbit.yaml` (#1698) -- Added advanced code review prompts for the `src/hiero_sdk_python/file` module in `.coderabbit.yaml` to guide reviewers in verifying proper `FileAppendTransaction` chunking constraints and nuances in memo handling for `FileUpdateTransaction` according to Hiero SDK best practices. (#1697) -- Added CodeRabbit review instructions for consensus module `src/hiero_sdk_python/consensus/` with critical focus on protobuf alignment `.coderabbit.yaml`. -- Added CodeRabbit prompt to review the `src/hiero_sdk_python/crypto` module. -- Added `.codacy.yml` configuration to exclude the `tests/` directory from Bandit `assert` analysis. - -### Fixed - -- Fixed duplication in GitHub bot next issue recommendations by parsing actual issue descriptions instead of blind truncation (#1658) - -### Src -- Add `staking_info` field to `ContractInfo` class to expose staking metadata using the `StakingInfo` wrapper. (#1365) -- Fix `TopicInfo.__str__()` to format `expiration_time` in UTC so unit tests pass in non-UTC environments. (#1800) -- Resolve CodeQL `reflected-XSS` warning in TCK JSON-RPC endpoint -- Improve `keccak256` docstring formatting for better readability and consistency (#1624) -- Added `wait_for_receipt` parameter for `Transaction.execute()` to support optional receipt waiting, and `get_receipt_query`, `get_record_query` and `get_record` to `TransactionResponse`. - -### Examples -- Refactor `examples/file/file_create_transaction.py` to remove `os`,`dotenv`,`AccountId`,`PrivateKey`,`Network` imports that are no longer needed and updated setup-client() (#1610) - -- Refactored contract_delete_transaction example to use Client.from_env. (#1823) - -### Docs - -- docs: Improving formatting will make the pull request process clearer. (`#1858`) -- Added Python compatibility badge to README for improved visibility of supported versions (#1830) -- Fixed Test Improvements header formatting in Good First Issue guidelines by adding missing space before parenthetical and removing stray bold marker (#1829) -- Improved Google-style docstring for `compress_point_unchecked` in `crypto_utils.py`. (#1625) -- chore: update office hours and community calls to use direct links (`#1804`) -- docs: create workflow best practices guide (`docs/workflows/03-workflow-best-practices.md`) (`#1743`) -- Fixed broken `MAINTAINERS.md` relative link in `docs/sdk_developers/bug.md` by using the repository-root GitHub URL. (#1666) -- docs(setup): specify unit tests for local setup verification. (#1856) -- docs: Clarify issues need to be assigned in template files. (#1884) -- doc: Fix testnet link in README.md. (#1879) - -### Tests -- Format `tests/unit/endpoint_test.py` using black. (`#1792`) -- Implement TCK JSON-RPC server with request handling and error management - -### .github -- Added triage members max assignment is protected from being a mentor in `.github/scripts/bot-assignment-check.sh`. (#1718) -- Added automated bot to comment on PRs with invalid conventional commit titles, providing guidance on fixing the title format (#1705) -- Revert PythonBot workflow to restore previous stable behavior. (#1825) -- Added GitHub Actions workflow to remind draft PR authors to mark ready for review after pushing changes. (#1722) -- Fixed bot workflow runtime failure caused by strict `FAILED_WORKFLOW_NAME` validation. (`#1690`) -- Reverted PR #1739 checking assignment counts -- chore: update step-security/harden-runner from 2.14.1 to 2.14.2 in a workflow -- Redesigned beginner issue template with readiness self-check, exploration-based task structure, compact workflow reference, and common pitfalls guidance to improve completion rates (#1651) -- Added workflow documentation guide (`docs/github/04_workflow_documentation.md`) with best practices for documenting GitHub workflows and automation scripts (#1745) -- Updated CodeRabbit workflow and script review instructions to nudge higher-quality patterns without imposing rigid rules (`#1799`) -- Added hiero-sdk-js to the next issue recommendation bot (`#1847`) -- feat(bot): warn PR authors that unlinked PRs will be closed (#1886) -- updated spam list users (`#1894`) -- trigger spam list updates every hour (`#1864`) -- close unlinked pull requests after 12 hours rather than 3 days (`#1863`) -- feat(bot): enforce linked issue assignment check for PR authors (`#1889`) -- Bumped `astral-sh/setup-uv` from v7.2.1 to v7.3.1 in workflow files (#1900) - -## [0.2.0] - 2026-11-02 - -### Tests -- Format `tests/unit/crypto_utils_test.py` with black for code style consistency (#1524) -- Standardize formatting of `tests/unit/entity_id_helper_test.py` using Black for consistent code style across the test suite (#1527) - -- Added tests for ProtoBuf Training Example Implementation -- Formatted `tests/unit/get_receipt_query_test.py` with black for code style consistency. (#1537) -- format black `tests/unit/hbar*.py`.(#1538) -- Formatted `tests/unit/conftest.py` with black for code style consistency. (#1522) -- format `black tests/unit/nft_id_test.py` with Black.(#1544) -- Format `tests/unit/executable_test.py` with Black.(#1530) -- Format `tests/unit/hedera_trust_manager_test.py` with Black for consistent code style (#1539) -- Format tests/unit/logger_test.py with black for code style consistency (#1541) -- Format `tests/unit/batch_transaction_test.py` with Black.(`#1520`) -- Style: formatted `tests/unit/prng_transaction_test.py` with black (#1546) -- Formatted contract unit tests with black for consistent style. (#1523) -- Format account test files with Black (#1519) -- Format `tests/unit/node*.py` with Black for consistent code style (#1545) -- Improve unit test coverage for Hbar, including edge cases, validation, comparisons, and hashing. (#1483) -- Standardize formatting of evm_address_test.py using Black for improved consistency and readability (#1529) -- Formatted unit test files using Black. -- Format tests/unit/network_tls_test.py with black for code style consistency (#1543) -- Formatted `ethereum_transaction_test.py` using Black. -- Formatted client_test.py using Black. -- Format tests/unit/query*.py using black (#1547) -- Format `tests/unit/custom_fee_test.py` with black for code style consistency. (#1525) - -### Added -- Implement custom `__repr__` method for `FileId` class that returns constructor-style representation for improved debugging experience (#1628) -- Added foundational guide for GitHub Workflows (#1741) -- Contract-specific CodeRabbit review instructions in `.coderabbit.yaml` for improved automated PR feedback on ABI, gas, ContractId, and protobuf safety. (#1695) -- Added new members to the mentor roster. (#1693) -- Added support for the `includeDuplicates` flag in `TransactionRecordQuery` and `duplicates` field in `TransactionRecord` (#1635) -- Added logging in bot-gfi-assign-on-comment.js to prevent silent skips. (`#1668`) -- Added `AssessedCustomFee` domain model to represent assessed custom fees. (`#1637`) -- Add __repr__ method for ContractId class to improve debugging (#1714) -- Added Protobuf Training guide to enhance developer understanding of proto serialization - and deserialization (#1645) -- Add `__repr__()` method to `TopicId` class for improved debugging with constructor-style representation (#1629) -- Added guide for resolving CHANGELOG.md conflicts using GitHub's web editor (`#1591`) -- Added Windows setup guide for SDK developers (`docs/sdk_developers/training/setup/setup_windows.md`) with PowerShell installation instructions. (#1570) -- Added a beginner assignment guard that requires completion of a Good First Issue. (#1484) -- Added `/unassign` command allowing contributors to remove themselves from assigned issues.(#1472) -- Added advanced CodeRabbit reviewer guidance for `tokens` module changes, with specialized validation rules for token transactions, token classes, and enums. (#1496) -- Advanced-check bot unassigns users from issues if they do not meet the requirements and provides an explanatory message. (#1477) -- Auto-assignment bot for beginner-labeled issues with `/assign` command support and helpful reminders. (#1368) -- Added comprehensive docstring to `FeeAssessmentMethod` enum explaining inclusive vs exclusive fee assessment methods with usage examples. (#1391) -- Added comprehensive docstring to `TokenType` enum explaining fungible vs non-fungible tokens with practical use cases. (#1392) -- Enable dry run support for office hours bot via `workflow_dispatch` trigger for testing without posting comments. (#1426) -- Trigger CodeRabbit plan comment after Good First Issue assignment to provide AI-generated implementation guidance to new contributors. (#1432) - -- Added a notification workflow that alerts the support team when an issue is labeled as a Good First Issue Candidate.[(#1296)] -- Added comprehensive training documentation for the `Query` class, covering execution flow, payments, retries, and building child queries. (#1238) -- Beginner issue documentation and updated GFI and GFIC templates and documentation -- Enable auto assignment to good first issues (#1312), archived good first issue support team notification. Changed templates with new assign instruction. -- Intermediate issue documentation -- Added unit test for 'endpoint.py' to increase coverage. -- Automated assignment guard for `advanced` issues; requires completion of at least one `good first issue` and one `intermediate` issue before assignment (exempts maintainers, committers, and triage members). (#1142) -- Added Hbar object support for TransferTransaction HBAR transfers: -- Methods now accept `Union[int, Hbar]` for amount parameters with immediate normalization to tinybars -- Includes comprehensive unit tests covering various Hbar units (HBAR, MICROBAR, NANOBAR, TINYBAR) and accumulation behavior with mixed `int` and `Hbar` inputs -- Added a module-level docstring to the HBAR allowance approval example to clarify delegated spending behavior and key concepts. [#1202](https://github.com/hiero-ledger/hiero-sdk-python/issues/1202) -- Added a GitHub Actions workflow to validate broken Markdown links in pull requests. -- Added method chaining examples to the developer training guide (`docs/sdk_developers/training/coding_token_transactions.md`) (#1194) -- Added documentation explaining how to pin GitHub Actions to specific commit SHAs (`docs/sdk_developers/how-to-pin-github-actions.md`)(#1211) -- examples/mypy.ini for stricter type checking in example scripts -- Formatted examples/tokens directory using black code formatter for consistent code style -- Added `.github/workflows/bot-coderabbit-plan-trigger.yml` to automatically invoke CodeRabbit's plan feature on intermediate and advanced issues, providing implementation guidance to help contributors assess complexity and understand requirements. (#1289) -- Added a GitHub Actions workflow that reminds contributors to link pull requests to issues. -- Added `__str__` and `__repr__` methods to `AccountInfo` class for improved logging and debugging experience (#1098) -- Added Good First Issue (GFI) management and frequency documentation to clarify maintainer expectations and SDK-level GFI governance. -- Added SDK-level Good First Issue (GFI) guidelines for maintainers to clarify what qualifies as a good first issue. -- Codecov workflow -- Added unit tests for `key_format.py` to improve coverage. -- Fix inactivity bot execution for local dry-run testing. -- Added Good First Issue candidate guidelines documentation (`docs/maintainers/good_first_issue_candidate_guidelines.md`) and Good First Issues guidelines documentation (`docs/maintainers/good_first_issues_guidelines.md`) (#1066) -- Added documentation: "Testing GitHub Actions using Forks" (`docs/sdk_developers/training/testing_forks.md`). -- Documentation: created docs/maintainers/hiero_python_sdk_team.md -- Unified the inactivity-unassign bot into a single script with `DRY_RUN` support, and fixed handling of cross-repo PR references for stale detection. -- Added unit tests for `SubscriptionHandle` class covering cancellation state, thread management, and join operations. -- Refactored `account_create_transaction_create_with_alias.py` example by splitting monolithic function into modular functions: `generate_main_and_alias_keys()`, `create_account_with_ecdsa_alias()`, `fetch_account_info()`, `print_account_summary()` (#1016) -- Added `.github/workflows/bot-pr-auto-draft-on-changes.yml` to automatically convert PRs to draft and notify authors when reviewers request changes. -- Add beginner issue template -- Add relevant examples to the beginner issue template -- Add Github CODEOWNERS -- Modularized `transfer_transaction_fungible` example by introducing `account_balance_query()` & `transfer_transaction()`.Renamed `transfer_tokens()` → `main()` -- Phase 2 of the inactivity-unassign bot: Automatically detects stale open pull requests (no commit activity for 21+ days), comments with a helpful InactivityBot message, closes the stale PR, and unassigns the contributor from the linked issue. -- Added `__str__()` to CustomFixedFee and updated examples and tests accordingly. -- Added unit tests for `crypto_utils` (#993) -- Added a github template for good first issues -- Added `.github/workflows/bot-assignment-check.yml` to limit non-maintainers to 2 concurrent issue assignments. -- Configured coderabbit with a `.coderabbit.yaml` -- Added `.github/workflows/bot-community-calls` and its script to notify issue creators of a community call -- Added all missing fields to `__str__()` method and updated `test_tokem_info.py` -- Add examples/tokens/token_create_transaction_pause_key.py example demonstrating token pause/unpause behavior and pause key usage (#833) -- Added `docs/sdk_developers/training/transaction_lifecycle.md` to explain the typical lifecycle of executing a transaction using the Hedera Python SDK. -- Add inactivity bot workflow to unassign stale issue assignees (#952) -- Made custom fraction fee end to end -- feat: AccountCreateTransaction now supports both PrivateKey and PublicKey [#939](https://github.com/hiero-ledger/hiero-sdk-python/issues/939) -- Added Acceptance Criteria section to Good First Issue template for better contributor guidance (#997) -- Added `__str__()` to CustomRoyaltyFee and updated examples and tests accordingly (#986) -- Restore bug and feature request issue templates (#996)(https://github.com/hiero-ledger/hiero-sdk-python/issues/996) -- Support selecting specific node account ID(s) for queries and transactions and added `Network._get_node()` with updated execution flow (#362) -- Add TLS support with two-stage control (`set_transport_security()` and `set_verify_certificates()`) for encrypted connections to Hedera networks. TLS is enabled by default for hosted networks (mainnet, testnet, previewnet) and disabled for local networks (solo, localhost) (#855) -- Add PR inactivity reminder bot for stale pull requests `.github/workflows/pr-inactivity-reminder-bot.yml` -- Add comprehensive training documentation for \_Executable class `docs/sdk_developers/training/executable.md` -- Added empty `docs/maintainers/good_first_issues.md` file for maintainers to write Good First Issue guidelines (#1034) -- Added new `.github/ISSUE_TEMPLATE/04_good_first_issue_candidate.yml` file (1068)(https://github.com/hiero-ledger/hiero-sdk-python/issues/1068) -- Enhanced `.github/ISSUE_TEMPLATE/01_good_first_issue.yml` with welcoming message and acceptance criteria sections to guide contributors in creating quality GFIs (#1052) -- Add workflow to notify team about P0 issues `bot-p0-issues-notify-team.yml` -- Added Issue Reminder (no-PR) bot, .github/scripts/issue_reminder_no_pr.sh and .github/workflows/bot-issue-reminder-no-pr.yml to automatically detect assigned issues with no linked pull requests for 7+ days and post a gentle ReminderBot comment.(#951) -- Add support for include_children in TransactionGetReceiptQuery (#1100)(https://github.com/hiero-ledger/hiero-sdk-python/issues/1100) -- Add new `.github/ISSUE_TEMPLATE/05_intermediate_issue.yml` file (1072)(https://github.com/hiero-ledger/hiero-sdk-python/issues/1072) -- Add a workflow to notify the team when issues are labeled as “good first issues” or identified as candidates for that label: `bot-gfi-notify-team.yml`(#1115) -- Added **str** and **repr** to AccountBalance -- Added GitHub workflow that makes sure newly added test files follow pytest test files naming conventions (#1054) -- Added advanced issue template -- Added advanced issue template for contributors `.github/ISSUE_TEMPLATE/06_advanced_issue.yml`. -- Add new tests to `tests/unit/topic_info_query_test.py` (#1124) -- Added `coding_token_transactions.md` for a high level overview training on how token transactions are created in the python sdk. -- Added prompt for codeRabbit on how to review /examples ([#1180](https://github.com/hiero-ledger/hiero-sdk-python/issues/1180)) -- Add Linked Issue Enforcer to automatically close PRs without linked issues `.github/workflows/bot-linked-issue-enforcer.yml`. -- Added support for include duplicates in get transaction receipt query (#1166) -- Added `.github/workflows/cron-check-broken-links.yml` workflow to perform scheduled monthly Markdown link validation across the entire repository with automatic issue creation for broken links ([#1210](https://github.com/hiero-ledger/hiero-sdk-python/issues/1210)) -- Added `transfer_transaction_tinybar.py` example demonstrating tinybar transfers with both integer and Hbar object approaches. ([#1249](https://github.com/hiero-ledger/hiero-sdk-python/issues/1249)) -- Added `transfer_transaction_gigabar.py` example demonstrating `GIGABAR` unit usage for large-value transfers. ([#1249](https://github.com/hiero-ledger/hiero-sdk-python/issues/1249)) -- Coderabbit prompt for .github -- Added convenient factory methods to `Hbar` class for easier instantiation: `from_microbars()`, `from_millibars()`, `from_hbars()`, `from_kilobars()`, `from_megabars()`, and `from_gigabars()`. [#1272](https://github.com/hiero-ledger/hiero-sdk-python/issues/1272) -- Added merge conflict bot workflow (`.github/workflows/bot-merge-conflict.yml`) and helper script (`.github/scripts/bot-merge-conflict.js`) to detect and notify about PR merge conflicts, with retry logic for unknown mergeable states, idempotent commenting, and push-to-main recheck logic (#1247) -- Added workflow to prevent assigning intermediate issues to contributors without prior Good First Issue completion (#1143). -- Added `Client.from_env()` and network-specific factory methods (e.g., `Client.for_testnet()`) to simplify client initialization and reduce boilerplate. [[#1251](https://github.com/hiero-ledger/hiero-sdk-python/issues/1251)] -- Improved unit test coverage for `TransactionId` class, covering parsing logic, hashing, and scheduled transactions. -- Add contract_id support for CryptoGetAccountBalanceQuery([#1293](https://github.com/hiero-ledger/hiero-sdk-python/issues/1293)) -- Support for setting `max_query_payment`, `Query.set_max_query_payment()` allows setting a per-query maximum Hbar payment and `Client.set_default_max_query_payment()` sets a client-wide default maximum payment. -- Chained Good First Issue assignment with mentor assignment to bypass GitHub's anti-recursion protection - mentor assignment now occurs immediately after successful user assignment in the same workflow execution. (#1369) -- Add GitHub Actions script and workflow for automatic spam list updates. -- Added technical docstrings and hardening (set -euo pipefail) to the pr-check-test-files.sh script (#1336) -- Added prompt for coderabbit to review `Query` and it's sub-classes. -- Updated the mentor assignment bot welcome message to be more structured. ([#1487](https://github.com/hiero-ledger/hiero-sdk-python/issues/1487)) -- Add StakingInfo class ([1364](https://github.com/hiero-ledger/hiero-sdk-python/issues/1364)) -- Added a visible confirmation comment when a user unassigns themselves from an issue (#1506) -- Added first-class support for EVM address aliases in `AccountId`, including parsing, serialization, Mirror Node population helpers. -- Add automated bot to recommend next issues to contributors after their first PR merge (#1380) -- Added dry-run support and refactored `.github/workflows/bot-workflows.yml` to use dedicated script `.github/scripts/bot-workflows.js` for improved maintainability and testability. (`#1288`) -- Added MirrorNode based population for `ContractId`, including parsing and serialization support. -- Added `/working` command to reset the inactivity timer on issues and PRs. ([#1552](https://github.com/hiero-ledger/hiero-sdk-python/issues/1552)) -- Added `grpc_deadline` support for transaction and query execution. -- Type hints to exception classes (`PrecheckError`, `MaxAttemptsError`, `ReceiptStatusError`) constructors and string methods. -- Added `__eq__` and `__hash__` functions for Key - -### Documentation -- Added `docs/workflows/02-architecture.md`: explains the orchestration (YAML) vs. business logic (JS) separation pattern for GitHub workflows (#1742) -- Fix relative links in `testing.md`, clean up `CONTRIBUTING.md` TOC, and normalize test file naming and paths (`#1706`) -- Added comprehensive docstring to `compress_with_cryptography` function (#1626) -- Replaced the docstring in `entity_id_helper.py` with one that is correct. (#1623) - -### Changed -- Reduced linting errors in `examples/` directory by 80% (952 → 185) by fixing docstring formatting, import ordering, and applying auto-fixes (#1768) -- Improved bot message formatting in LinkBot to display issue linking format as a code block for better clarity (#1762) -- Refactored `setup_client()` in all `examples/query/` files to use `Client.from_env()` for simplified client initialization (#1449) -- Improve the changelog check by posting informative PR comments when entries are missing or placed under a released version. (#1683) -- Updated return of to_bytes function in `src/hiero_sdk_python/transaction/transaction.py`. (#1631) -- Added missing return type `src/hiero_sdk_python/utils/entity_id_helper.py`. (#1622) -- Update `verify_freeze()` to treat only ACCOUNT_FROZEN_FOR_TOKEN as a successful freeze verification (#1515) -- Updated team.md with new triage, committers and maintainer (#1692) -- Removed outdated "Common Issues" section from CONTRIBUTING.md that referenced non-existent docs/common_issues.md (`#1665`) -- Hide the commit verification bot marker in pull request comments. -- Added missing type hints to sign method in Transaction class (#1630) -- Refactored `examples/consensus/topic_create_transaction.py` to use `Client.from_env()` (#1611) -- Updated GitHub Actions setup-node action to v6.2.0. -- chore: format tests/unit/mock_server.py with black (#1542) -- Updated actions/checkout to v6.0.1 and actions/github-script v8.0.0 in bot-next-issue-recommendation workflow (#1586) -- Expanded inactivity bot messages to include `/unassign` command information for contributors (#1555) -- Update the acceptance criteria wording in the issue templates to improve clarity and consistency for contributors (#1491) -- Add return type hint to `AccountId.__repr__` for type consistency. (#1503) -- Good First Issue template to have more guidance and renamed other templates for consistency with upstream -- Added AI usage guidelines to the Good First Issue and Beginner issue templates to guide contributors on responsible AI use. (#1490) -- Refactored `bot-verified-commits.yml` workflow to use modular JavaScript with configurable environment variables, input sanitization, dry-run mode support, and SHA-pinned actions. (#1482) -- Refactored the advanced issue assignment guard to use a single configurable variable for the required number of completed intermediate issues. (#1479) -- Align Good First Issue and Good First Issue — Candidate guidelines with the Hiero C++ SDK for clarity and consistency.(#1421) -- Make the required signed commit command explicit in all issue templates to reduce PR signing errors for contributors (#1489) -- Refactored `file_info_query.py` to use `print(info)` instead of manual formatting (#1451) -- Enable CodeRabbit walkthrough mode by default to improve PR review visibility (#1439) -- Move assignment guards to be directly inside the gfi and beginner auto assign -- Remove the commented out blocks in config.yml (#1435) -- Renamed `.github/scripts/check_advanced_requirement.sh` to `bot-advanced-check.sh` for workflow consistency (#1341) -- Difficulty guidelines to feel more welcoming -- Added global review instructions to CodeRabbit configuration to limit reviews to issue/PR scope and prevent scope creep [#1373] -- Archived unused auto draft GitHub workflow to prevent it from running (#1371) -- Added comprehensive documentation to the PR changelog check script (`.github/scripts/pr-check-changelog.sh`) to clarify behavior, inputs, permissions, and dependencies [(#1337)] -- Refactored `account_create_transaction_without_alias.py` into smaller, modular functions.(#1321) -- Renamed bot-inactivity workflow files to remove "-phase" suffix since the process no longer uses phased execution (#1339) -- Renamed the GitHub notify team script to match its corresponding workflow filename for better maintainability (#1338) -- style: apply black formatting to examples (#1299) -- Update GitHub workflow names in `.github/workflows/bot-workflows.yml` to match correct references [(#1284)] -- Updated set up and workflow documents for improved clarity and organisation -- Renamed templates for improved clarity [(#1265)] -- Updated Good First Issue notifications to trigger only after the first comment is posted, reducing noise on unassigned issues.(#1212) -- Bumped requests from 2.32.3 to 2.32.4 to 2.32.5 -- Moved `docs/sdk_developers/how_to_link_issues.md` to `docs/sdk_developers/training/workflow/how_to_link_issues.md` and updated all references (#1222) -- Moved docs/sdk_developers/project_structure.md to docs/sdk_developers/training/setup/project_structure.md and ensured all previous references are updated [#1223](https://github.com/hiero-ledger/hiero-sdk-python/issues/1223) -- Renamed workflow scripts in `.github/scripts/` to match their corresponding workflow file names for improved consistency and maintainability (#1198) -- Refactored `account_create_transaction_evm_alias.py` to improve readability by splitting the monolithic function into smaller helper functions. [#1017](https://github.com/hiero-ledger/hiero-sdk-python/issues/1017) -- Improved docstring for `account_allowance_approve_transaction_nft.py` with purpose, key concepts and required vs optional steps. -- Updated Codecov coverage thresholds in 'codecov.yml' to require 90% of project coverage and 92% of patch coverage (#1157) -- Reduce office-hours reminder spam by posting only on each user's most recent open PR, grouping by author and sorting by creation time (#1121) -- Reduce office-hours reminder spam by never posting on PRs of maintainers and committers -- Pylint cleanup for token_airdrop_transaction_cancel.py (#1081) [@tiya-15](https://github.com/tiya-15) -- Move `account_allowance_delete_transaction_hbar.py` from `examples/` to `examples/account/` for better organization (#1003) -- Improved consistency of transaction examples (#1120) -- Refactored `account_create_transaction_with_fallback_alias.py` by splitting the monolithic `create_account_with_fallback_alias` function into modular functions: `generate_fallback_key`, `fetch_account_info`, and `print_account_summary`. The existing `setup_client()` function was reused for improved readability and structure (#1018) -- Allow `PublicKey` for batch_key in `Transaction`, enabling both `PrivateKey` and `PublicKey` for batched transactions -- Allow `PublicKey` for `TokenUpdateKeys` in `TokenUpdateTransaction`, enabling non-custodial workflows where operators can build transactions using only public keys (#934). -- Bump protobuf toml to protobuf==6.33.2 -- Improved the contributing section for sdk developers in CONTRIBUTING.md for clarity and including new documentation -- chore: Move account allowance example to correct folder -- Added more tests to the CustomFee class for different functionalities (#991) -- Changed messaged for test failure summaries so it is clearer by extracting test failure names into summary -- Renamed example files to match src naming (#1053) -- Updated bot naming conventions in `.github/workflows` to be consistent (#1042) -- Renamed workflow files for consistent PR check naming: - `examples.yml` → `pr-check-examples.yml`, - `test.yml` → `pr-check-test.yml` (#1043) -- Cleaned up `token_airdrop_claim_auto` example for pylint compliance (no functional changes). (#1079) -- Formatted `examples/query` using black (#1082)(https://github.com/hiero-ledger/hiero-sdk-python/issues/1082) -- Update team notification script and workflow for P0 issues 'p0_issues_notify_team.js' -- Rename test files across the repository to ensure they consistently end with \_test.py (#1055) -- Cleaned up `token_airdrop_claim_signature_required` example for pylint compliance (no functional changes). (#1080) -- Rename the file 'test_token_fee_schedule_update_transaction_e2e.py' to make it ends with \_test.py as all other test files.(#1117) -- Format token examples with Black for consistent code style and improved readability (#1119) -- Transformed `examples/tokens/custom_fee_fixed.py` to be an end-to-end example, that interacts with the Hedera network, rather than a static object demo. -- Format token examples with Black for consistent code style and improved readability (#1119) -- Replaced `ResponseCode.get_name(receipt.status)` with the `ResponseCode(receipt.status).name` across examples and integration tests for consistency. (#1136) -- Moved helpful references to Additional Context section and added clickable links. -- Transformed `examples\tokens\custom_royalty_fee.py` to be an end-to-end example, that interacts with the Hedera network, rather than a static object demo. -- Refactored `examples/tokens/custom_royalty_fee.py` by splitting monolithic function custom_royalty_fee_example() into modular functions create_royalty_fee_object(), create_token_with_fee(), verify_token_fee(), and main() to improve readability, cleaned up setup_client() (#1169) -- Added comprehensive unit tests for Timestamp class (#1158) -- Enhance unit and integration test review instructions for clarity and coverage `.coderabbit.yaml`. -- Issue reminder bot now explicitly mentions assignees (e.g., `@user`) in comments. ([#1232](https://github.com/hiero-ledger/hiero-sdk-python/issues/1232)) -- Updated `transfer_transaction_hbar.py` example to use `Hbar` objects instead of raw integers and added receipt checking with `ResponseCode` validation.([#1249](https://github.com/hiero-ledger/hiero-sdk-python/issues/1249)) -- Renamed `pr-missing-linked-issue.yml` and `pr_missing_linked_issue.js` to `bot-pr-missing-linked-issue.yml` and `bot-pr-missing-linked-issue.js` respectively. Enhanced LinkBot PR comment with clickable hyperlinks to documentation for linking issues and creating issues. (#1264) -- Enhance assignment bot to guard against users with spam PRs `.github/scripts/bot-assignment-check.sh` -- Add CodeRabbit documentation review prompts for docs, sdk_users, and sdk_developers with priorities, philosophy, and edge case checks. ([#1236](https://github.com/hiero-ledger/hiero-sdk-python/issues/1236)) -- Enhance NodeAddress tests with additional coverage for proto conversion `tests/unit/node_address_test.py` -- Replaced deprecated `AccountCreateTransaction.set_key()` usage with `set_key_without_alias()` and `set_key_with_alias()` across examples and tests - -- Updated `pyproject.toml` to enforce stricter Ruff linting rules, including Google-style docstrings (`D`), import sorting (`I`), and modern Python syntax (`UP`). -- Modified and renamed hasIntermediateOrAdvancedLabel() to check if issue label is beginner or higher (#1385) -- Updated `.github/scripts/bot-office-hours.sh` to detect and skip PRs created by bot accounts when posting office hours reminders. (#1384) -- Refactored `examples/account/account_create_transaction_create_with_alias.py` and `examples/account/account_create_transaction_evm_alias.py` to use the native `AccountInfo.__str__` method for printing account details, replacing manual JSON serialization. ([#1263](https://github.com/hiero-ledger/hiero-sdk-python/issues/1263)) -- Enhance TopicInfo `__str__` method and tests with additional coverage, and update the format_key function in `key_format.py` to handle objects with a \_to_proto method. -- Update changelog workflow to trigger automatically on pull requests instead of manual dispatch (#1567) -- Formatted key-related unit test files (`key_utils_test.py`, `test_key_format.py`, `test_key_list.py`) using the black formatter -- Add return type hint to `ContractId.__str__`. (#1654) -- chore: update maintainer guidelines link in MAINTAINERS.md (#1605) -- chore: update merge conflict bot message with web editor tips (#1592) -- chore: update MAINTAINERS.md to include new maintainer Manish Dait and sort maintainers by GitHub ID. (#1691) -- Changed `TransactionResponse.get_receipt()` so now pins receipt queries to the submitting node via `set_node_account_ids()` ([#1686](https://github.com/hiero-ledger/hiero-sdk-python/issues/1686)) -- chore: clarify wording in the bot-assignment-check.sh (#1748) -- Refactored SDK dependencies to use version ranges, moved build-only deps out of runtime, removed unused core deps and added optional extras. - - -### Fixed -- Added a fork guard condition to prevent Codecov upload failures on fork PRs due to missing token. (`#1485`) -- Corrected broken documentation links in SDK developer training files.(#1707) -- Updated Good First Issue recommendations to supported Hiero repositories. (#1689) -- Fix the next-issue recommendation bot to post the correct issue recommendation comment. (#1593) -- Ensured that the GFI assignment bot skips posting `/assign` reminders for repository collaborators to avoid unnecessary notifications.(#1568). -- Reduced notification spam by skipping the entire advanced qualification job for non-advanced issues and irrelevant events (#1517) -- Aligned token freeze example filename references and improved error handling by catching broader exceptions with clearer messages. (#1412) -- Fixed jq syntax in bot-office-hours.sh (#1502) -- Fixed formatting of `/unassign` command in the PR inactivity reminder message so it displays correctly with backticks. (#1582) -- Prevented linkbot from commenting on or auto-closing bot-authored pull requests. (#1516) -- Respect `dry-run` input in `bot-community-calls.yml` workflow (#1425) -- Updated LinkBot regex in the GitHub Actions bot script to support "Closes" and "Resolves" keywords for improved PR body-link detection (#1465) -- Fixed CodeRabbit plan trigger workflow running multiple times when issues are created with multiple labels by switching to labeled event trigger only. (#1427) -- Prevent LinkBot from posting duplicate “missing linked issue” comments on pull requests. (#1475) -- Refined intermediate assignment guard to validate Beginner issue completion with improved logging and GraphQL-based counting. (#1424) -- Improved filename-related error handling with clearer and more descriptive error messages.(#1413) -- Good First Issue bot no longer posts `/assign` reminders for repository collaborators. (#1367) -- GFI workflow casing -- Update `bot-workflows.yml` to trigger only on open PRs with failed workflows; ignore closed PRs and branches without open PRs. -- Fixed step-security/harden-runner action SHA in merge conflict bot workflow (#1278) -- Fixed the README account balance example to use correct SDK APIs and provide a runnable testnet setup. (#1250) -- Fix token association verification in `token_airdrop_transaction.py` to correctly check if tokens are associated by using `token_id in token_balances` instead of incorrectly displaying zero balances which was misleading (#[815]) -- Fixed inactivity bot workflow not checking out repository before running (#964) -- Fixed the topic_message_query integarion test -- good first issue template yaml rendering -- Fixed solo workflow defaulting to zero -- Fix unit test tet_query.py -- TLS Hostname Mismatch & Certificate Verification Failure for Nodes -- Workflow does not contain permissions for `pr-check-test-files` and `pr-check-codecov` -- Fixed `cron-check-broken-links.yml` string parsing issue in context input `dry_run` (#1235) -- Flaky tests by disabling TLS in mock Hedera nodes in `mock_server.py` -- Fixed LinkBot permission issue for fork PRs by changing trigger to pull_request_target and adding proper permissions. -- Fixed token examples to consistently use setup_client without tuple unpacking.(#1397) -- Fixed duplicate comment prevention in issue reminder bot by adding hidden HTML marker for reliable comment detection (.github/scripts/bot-issue-reminder-no-pr.sh) (#1372) -- Fixed bot-pr-missing-linked-issue to skip commenting on pull requests created by automated bots. (#1382) -- Updated `.github/scripts/bot-community-calls.sh` to skip posting reminders on issues created by bot accounts. (#1383) -- Fixed incorrect run instructions and broaden error handling in `token_dissociate_transaction.py` example to improve usability for new users (#1468) -- Update `.github/scripts/bot-advanced-check.sh` to unassign unqualified users. -- Fixed broken project structure link in `CONTRIBUTING.md` (#1664) -- Refactor spam list update logic and remove unused pull request creation step `.github/scripts/update-spam-list.js` `.github/workflows/cron-update-spam-list.yml`. -- Ensure all Query sub-class `execute()` function to correctly propagate the optional `timeout` parameter. -- Refactor assignment time retrieval and open PR check to use GraphQL API instead of REST API `.github/scripts/bot-issue-reminder-no-pr.sh` (#1746) - -### Removed - -- Deleted `examples/utils.py` as its helper functions are no longer needed. ([#1263](https://github.com/hiero-ledger/hiero-sdk-python/issues/1263)) - -### Breaking Change - -- Remove deprecated 'in_tinybars' parameter and update related tests `/src/hiero_sdk_python/hbar.py`, `/tests/unit/hbar_test.py` and `/src/hiero_sdk_python/tokens/custom_fixed_fee.py`. - -## [0.1.10] - 2025-12-03 - -### Added - -- Added docs/sdk_developers/training/workflow: a training for developers to learn the workflow to contribute to the python SDK. -- Added Improved NFT allowance deletion flow with receipt-based status checks and strict `SPENDER_DOES_NOT_HAVE_ALLOWANCE` verification. -- Add `max_automatic_token_associations`, `staked_account_id`, `staked_node_id` and `decline_staking_reward` fields to `AccountUpdateTransaction` (#801) -- Added docs/sdk_developers/training/setup: a training to set up as a developer to the python sdk -- Add example demonstrating usage of `CustomFeeLimit` in `examples/transaction/custom_fee_limit.py` -- Added `.github/workflows/merge-conflict-bot.yml` to automatically detect and notify users of merge conflicts in Pull Requests. -- Added `.github/workflows/bot-office-hours.yml` to automate the Weekly Office Hour Reminder. -- feat: Implement account creation with EVM-style alias transaction example. -- Added validation logic in `.github/workflows/pr-checks.yml` to detect when no new chnagelog entries are added under [Unreleased]. -- Support for message chunking in `TopicSubmitMessageTransaction`. - -### Changed - -- bot workflows to include new changelog entry -- Removed duplicate import of transaction_pb2 in transaction.py -- Refactor `TokenInfo` into an immutable dataclass, remove all setters, and rewrite `_from_proto` as a pure factory for consistent parsing [#800] -- feat: Add string representation method for `CustomFractionalFee` class and update `custom_fractional_fee.py` example. -- Moved query examples to their respective domain folders to improve structure matching. - -### Fixed - -- fixed workflow: changelog check with improved sensitivity to deletions, additions, new releases - -## [0.1.9] - 2025-11-26 - -### Added - -- Add a limit of one comment for PR to the commit verification bot. [#892] -- Removed `actions/checkout@v4` from `bot-verified-commits.yml` -- Add comprehensive documentation for `ReceiptStatusError` in `docs/sdk_developers/training/receipt_status_error.md` -- Add practical example `examples/errors/receipt_status_error.py` demonstrating transaction error handling -- Document error handling patterns and best practices for transaction receipts -- fix `pull_request` to `pull_request_target` in `bot-verified-commits.yml` -- Add more robust receipt checks and removed fallback to `examples/tokens/token_delete_transaction.py` -- Add detail to `token_airdrop.py` and `token_airdrop_cancel.py` -- Add workflow: github bot to respond to unverified PR commits (#750) -- Add workflow: bot workflow which notifies developers of workflow failures in their pull requests. -- Add `examples/token_create_transaction_max_automatic_token_associations_0.py` to demonstrate how `max_automatic_token_associations=0` behaves. -- Add `examples/topic_id.py` to demonstrate `TopicId` opeartions -- Add `examples/topic_message.py` to demonstrate `TopicMessage` and `TopicMessageChunk` with local mock data. -- Added missing validation logic `fee_schedule_key` in integration `token_create_transaction_e2e_test.py` and ``token_update_transaction_e2e_test.py`. -- Add `account_balance_query.py` example to demonstrate how to use the CryptoGetAccountBalanceQuery class. -- Add `examples/token_create_transaction_admin_key.py` demonstrating admin key privileges for token management including token updates, key changes, and deletion (#798) -- Add `examples/token_create_transaction_freeze_key.py` showcasing freeze key behavior, expected failures without the key, and the effect of freezing/unfreezing on transfers. -- Add `examples/account_info.py` to demonstrate `AccountInfo` opeartions -- Added `HbarUnit` class and Extend `Hbar` class to handle floating-point numbers -- Add `examples/topic_info.py` to demonstrate `TopicInfo` operations. -- feat: Allow `PrivateKey` to be used for keys in `TopicCreateTransaction` for consistency. -- EvmAddress class -- `alias`, `staked_account_id`, `staked_node_id` and `decline_staking_reward` fields to AccountCreateTransaction -- `staked_account_id`, `staked_node_id` and `decline_staking_reward` fields to AccountInfo -- Added `examples/token_create_transaction_supply_key.py` to demonstrate token creation with and without a supply key. -- Added `examples/token_create_transaction_kyc_key.py` to demonstrate KYC key functionality, including creating tokens with/without KYC keys, granting/revoking KYC status, and understanding KYC requirements for token transfers. -- Add `set_token_ids`, `_from_proto`, `_validate_checksum` to TokenAssociateTransaction [#795] -- Added BatchTransaction class -- Add support for token metadata (bytes, max 100 bytes) in `TokenCreateTransaction`, including a new `set_metadata` setter, example, and tests. [#799] -- Added `examples/token_create_transaction_token_fee_schedule.py` to demonstrate creating tokens with custom fee schedules and the consequences of not having it. -- Added `examples/token_create_transaction_wipe_key.py` to demonstrate token wiping and the role of the wipe key. -- Added `examples/account_allowance_approve_transaction_hbar.py` and `examples/account_allowance_delete_transaction_hbar.py`, deleted `examples/account_allowance_hbar.py`. [#775] -- Added `docs\sdk_developers\training\receipts.md` as a training guide for users to understand hedera receipts. -- Add `set_token_ids`, `_from_proto`, `_validate_checksum` to TokenAssociateTransaction [#795] -- docs: added `network_and_client.md` with a table of contents, and added external example scripts (`client.py`). - -### Changed - -- Upgraded step-security/harden-runner v2.13.2 -- bumped actions/checkout from 5.0.0 to 6.0.0 -- Limit workflow bot to one message per PR -- Refactored token-related example scripts (`token_delete.py`, `token_dissociate.py`, etc.) for improved readability and modularity. [#370] -- upgrade: step security action upgraded from harden-runner-2.13.1 to harden-runner-2.13.1 -- chore: Split `examples/account_allowance_nft.py` into separate `account_allowance_approve_transaction_nft.py` and `account_allowance_delete_transaction_nft.py` examples. -- chore: bump protobuf from 6.33.0 to 6.33.1 (#796) -- fix: Allow `max_automatic_token_associations` to be set to -1 (unlimited) in `AccountCreateTransaction` and add field to `AccountInfo`. -- Allow `PrivateKey` to be used for keys in `TopicCreateTransaction` for consistency. -- Update github actions checkout from 5.0.0 to 5.0.1 (#814) -- changed to add concurrency to workflow bot -- feat: Refactor `TokenDissociateTransaction` to use set_token_ids method and update transaction fee to Hbar, also update `transaction.py` and expand `examples/token_dissociate.py`, `tests/unit/token_dissociate.py`. - -### Fixed - -- chore: updated solo action to avoid v5 -- chore: fix test.yml workflow to log import errors (#740) -- chore: fixed integration test names without a test prefix or postfix -- Staked node ID id issue in the account_create_transationt_e2e_test -- workflow: verified commits syntax for verfication bot - -## [0.1.8] - 2025-11-07 - -### Added - -- `is_unknown` property added to `src/hiero_sdk_python/response_code.py` -- Example `response_code.py` -- Add `TokenFeeScheduleUpdateTransaction` class to support updating custom fee schedules on tokens (#471). -- Add `examples/token_update_fee_schedule_fungible.py` and `examples/token_update_fee_schedule_nft.py` demonstrating the use of `TokenFeeScheduleUpdateTransaction`. -- Update `docs/sdk_users/running_examples.md` to include `TokenFeeScheduleUpdateTransaction`. -- added FreezeTransaction class -- added FreezeType class -- Added `docs/sdk_developers/pylance.md`, a new guide explaining how to set up and use **Pylance** in VS Code for validating imports, file references, and methods before review. (#713) -- feat: TokenAirdropClaim Transaction, examples (with signing required and not), unit and integration tests (#201) -- docs: Add Google-style docstrings to `TokenId` class and its methods in `token_id.py`. -- added Google-style docstrings to the `TransactionRecord` class including all dataclass fields, `__repr__`, `_from_proto()` & `_to_proto()` methods. -- Standardized docstrings, improved error handling, and updated type hinting (`str | None` to `Optional[str]`) for the `FileId` class (#652). -- Add Google-style docstrings to `AccountInfo` class and its methods in `account_info.py`. -- Added comprehensive Google-style docstrings to the `Logger` class and all utility functions in `src/hiero_sdk_python/logger/logger.py` (#639). -- add AccountRecordsQuery class -- chore: added python 3.13 to test.yml workflow (#510, #449) -- Transaction bytes serialization support: `Transaction.freeze()`, `Transaction.to_bytes()`, and `Transaction.from_bytes()` methods for offline signing and transaction storage -- docs: Add Google-style docstrings to `ContractId` class and methods in `contract_id.py`. -- Added TokenUnpauseTransaction class -- Added expiration_time, auto_renew_period, auto_renew_account, fee_schedule_key, kyc_key in `TokenCreateTransaction`, `TokenUpdateTransaction` classes -- Added comprehensive Google-style docstrings to the `CustomFee` class and its methods in `custom_fee.py`. -- docs: Add `docs/sdk_developers/project_structure.md` to explain repository layout and import paths. - -### Changed -- chore: renamed examples to match src where possible -- Moved examples/ to be inside subfiles to match src structure -- changed example script workflow to run on new subdirectory structure -- chore: bumped solo action from 14.0 to 15.0 (#764) -- chore: replaced hardcoded 'testnet' messages with environment network name -- chore: validate that token airdrop transactions require an available token service on the channel (#632) -- chore: update local environment configuration in env.example (#649) -- chore: Update env.example NETWORK to encourage testnet or local usage (#659) -- chore: updated pyproject.toml with python 3.10 to 3.13 (#510, #449) -- chore: fix type hint for TokenCancelAirdropTransaction pending_airdrops parameter -- chore: Moved documentation file `common_issues.md` from `examples/sdk_developers/` to `docs/sdk_developers/` for unified documentation management (#516). -- chore: Refactored the script of examples/custom_fee.py into modular functions -- fix: Replaced `collections.namedtuple` with `typing.NamedTuple` in `client.py` for improved type checking. -- chore: Refactored examples/custom_fee.py into three separate example files. -- Expanded `docs/sdk_developers/checklist.md` with a self-review guide for all pull request submission requirements (#645). -- Expanded docs/sdk_developers/signing.md to clarify GPG and DCO requirements and add a Table of Contents (#455). -- chore: Standardized client initialization across all examples/ files to promote consistency (#658). -- chore: changed the file names of airdrop examples, classes, unit and integration tests so they are grouped together. (#631) -- Refactor `AbstractTokenTransferTransaction` to unify Token/NFT transfer logic. - -### Fixed - -- Added explicit read permissions to examples.yml (#623) -- Removed deprecated Logger.warn() method and legacy parameter swap logic from get_logger() (#673). -- Improved type hinting in `file_append_transaction.py` to resolve 'mypy --strict` errors. ([#495](https://github.com/hiero-ledger/hiero-sdk-python/issues/495)) -- fix: Resolve `__eq__` type conflict in `CustomFee` class (#627) -- Fixes a type conflict in `token_id.py` where `from_string` could receive `None`, preventing a runtime error by raising a `ValueError` if the input is missing. #630 -- Dependabot alerts (version bumps) -- Fixed incorrect `TokenType` import (protobuf vs. SDK enum) in 18 example files. -- Update `schedule_sign_transaction_e2e_test` to check for key presence instead of relying on index. -- Add `localhost` and `local` as network names - -### Breaking Changes - -- chore: changed the file names airdrop classes (#631) - {pending_airdrop_id.py -> token_airdrop_pending_id.py} - {pending_airdrop_record.py -> token_airdrop_pending_record.py} - {token_cancel_airdrop_transaction.py -> token_airdrop_transaction_cancel.py} - -- In `TokenAirdropTransaction` the parameters of the following methods have been renamed: - - add_nft_transfer(sender → sender_id, receiver → receiver_id) - - add_approved_nft_transfer(sender → sender_id, receiver → receiver_id) - -## [0.1.7] - 2025-10-28 - -### Added - -- Expanded `README.md` with a new "Follow Us" section detailing how to watch, star, and fork the repository (#472). -- Refactored `examples/topic_create.py` into modular functions for better readability and reuse. -- Add Rebasing and Signing section to signing.md with instructions for maintaining commit verification during rebase operations (#556) -- Add `examples/account_id.py` demonstrating AccountId class usage including creating standard AccountIds, parsing from strings, comparing instances, and creating AccountIds with public key aliases -- Added Google-style docstrings to `CustomFractionalFee` class and its methods in `custom_fractional_fee.py`. -- Added `dependabot.yaml` file to enable automated dependency management. -- Common issues guide for SDK developers at `examples/sdk_developers/common_issues.md` -- Added documentation for resolving changelog conflicts in `docs/common_issues.md` -- Added comprehensive changelog entry guide at `docs/sdk_developers/changelog.md` to help contributors create proper changelog entries (#532). -- docs: Added Google-style docstrings to `CustomFixedFee` class and its methods in `custom_fixed_fee.py`. -- docs: Add Google-style docstrings to `CustomRoyaltyFee` class and its methods in `custom_royalty_fee.py`. -- docs: Add Google-style docstrings to `AbstractTokenTransferTransaction` class and its methods in `abstract_token_transfer_transaction.py`. -- docs: Add Google-style docstrings to `TokenRelationship` class and its methods in `token_relationship.py`. -- feat: add initial testing guide structure -- Added `checksum` filed for TopicId, FileId, ContractId, ScheduleId class -- Added workflow for running example scripts. -- docs: workflow.md documenting key steps to creating a pull request (#605) -- chore: fix the examples workflow to log error messages and run on import failure (#738) -- Added `docs/discord.md` explaining how to join and navigate the Hiero community Discord (#614). - -### Changed - -- Added direct links to Python SDK channel in Linux Foundation Decentralized Trust Discord back in -- Updated all occurrences of non-functional Discord invite links throughout the documentation with the new, stable Hyperledger and Hedera invite links (#603). -- Refactored TopicId class to use @dataclass decorator for reducing boilerplate code -- Renamed `examples/nft_allowance.py` to `examples/account_allowance_nft.py` for consistency with account class naming scheme -- Added changelog conflict resolution examples to `docs/common_issues.md` -- Refactored `examples/topic_create.py` to be more modular by splitting functions and renaming `create_topic()` to `main()`. -- Refactored `examples/transfer_hbar.py` to improve modularity by separating transfer and balance query operations into dedicated functions -- Enhanced contributing section in README.md with resource links -- Refactored examples/topic_message_submit.py to be more modular -- Added "One Issue Per Pull Request" section to `examples/sdk_developers/common_issues.md`. -- docs: Improved the contributing section in the README.md file -- Refactored `examples/transfer_nft.py` to be more modular by isolating transfer logic. -- Refactored `examples/file_append.py` into modular functions for better readability, reuse, and consistency across examples. -- Ensured identical runtime behavior and output to the previous version to maintain backward compatibility. -- Renamed `examples/hbar_allowance.py` to `examples/account_allowance_hbar.py` for naming consistency -- Converted monolithic function in `token_create_nft_infinite.py` to multiple modular functions for better structure and ease. -- docs: Use relative paths for internal GitHub links (#560). -- Update pyproject.toml maintainers list. - – docs: Updated README.md/CHANGELOG.md and added blog.md, bud.md and setup.md (#474) -- renamed docs/sdk_developers/changelog.md to docs/sdk_developers/changelog_entry.md for clarity. -- Refactor `query_balance.py` into modular, reusable functions with `setup_client()`, `create_account()`, `get_balance()`, `transfer_hbars()`, and `main()` for improved readability, maintainability, and error handling. -- Unified balance and transfer logging format — both now consistently display values in hbars for clarity. - -### Fixed - -- Add type hints to `setup_client()` and `create_new_account()` functions in `examples/account_create.py` (#418) -- Added explicit read and write permissions to test.yml -- Type hinting for `Topic` related transactions. - -### Removed - -- Remove deprecated camelCase alias support and `_DeprecatedAliasesMixin`; SDK now only exposes snake_case attributes for `NftId`, `TokenInfo`, and `TransactionReceipt`. (Issue #428) - -## [0.1.6] - 2025-10-21 - -### Added - -- Add comprehensive Google-style docstrings to examples/account_create.py -- add revenue generating topic tests/example -- add fee_schedule_key, fee_exempt_keys, custom_fees fields in TopicCreateTransaction, TopicUpdateTransaction, TopicInfo classes -- add CustomFeeLimit class -- TokenNftAllowance class -- TokenAllowance class -- HbarAllowance class -- HbarTransfer class -- AccountAllowanceApproveTransaction class -- AccountAllowanceDeleteTransaction class -- FileAppendTransaction class -- Documentation examples for Allowance Approve Transaction, Allowance Delete Transaction, and File Append Transaction -- Approved transfer support to TransferTransaction -- set_transaction_id() API to Transaction class -- Allowance examples (hbar_allowance.py, token_allowance.py, nft_allowance.py) -- Refactored examples/logging_example.py for better modularity (#478) - -### Changed - -- TransferTransaction refactored to use TokenTransfer and HbarTransfer classes instead of dictionaries -- Added checksum validation for TokenId -- Refactor examples/token_cancel_airdrop -- Refactor token creation examples for modularity and consistency -- Updated `signing.md` to clarify commit signing requirements, including DCO, GPG, and branch-specific guidelines (#459) - -### Changed - -- Rearranged running_examples.md to be alphabetical -- Refactor token_associate.py for better structure, add association verification query (#367) -- Refactored `examples/account_create.py` to improve modularity and readability (#363) -- Replace Hendrik Ebbers with Sophie Bulloch in the MAINTAINERS.md file -- Improved `CONTRIBUTING.md` by explaining the /docs folder structure and fixing broken hyperlinks.(#431) -- Converted class in `token_nft_info.py` to dataclass for simplicity. - -### Fixed - -- Incompatible Types assignment in token_transfer_list.py -- Corrected references to \_require_not_frozen() and removed the surplus \_is_frozen -- Removed duplicate static methods in `TokenInfo` class: -   - `_copy_msg_to_proto` -   - `_copy_key_if_present` -   - `_parse_custom_fees` -   Kept robust versions with proper docstrings and error handling. -- Add strict type hints to `TransactionGetReceiptQuery` (#420) -- Fixed broken documentation links in CONTRIBUTING.md by converting absolute GitHub URLs to relative paths -- Updated all documentation references to use local paths instead of pointing to hiero-sdk project hub - -## [0.1.5] - 2025-09-25 - -### Added - -- ScheduleSignTransaction class -- NodeUpdateTransaction class -- NodeDeleteTransaction class -- ScheduleDeleteTransaction class -- prng_number and prng_bytes properties in TransactionRecord -- PrngTransaction class -- ScheduleInfoQuery class -- ScheduleInfo class -- Exposed node_id property in `TransactionReceipt` -- NodeCreateTransaction class -- ScheduleId() class -- ScheduleCreateTransaction() class -- build_scheduled_body() in every transaction -- ContractDeleteTransaction class -- ContractExecuteTransaction class -- setMessageAndPay() function in StatefulContract -- AccountDeleteTransaction Class -- generate_proto.py -- Bumped Hedera proto version from v0.57.3 to v0.64.3 -- Added `dev` and `lint` dependency groups as default in `pyproject.toml` -- EthereumTransaction class -- AccountId support for ECDSA alias accounts -- ContractId.to_evm_address() method for EVM compatibility -- consumeLargeData() function in StatefulContract -- example script for Token Airdrop -- added variables directly in the example script to reduce the need for users to supply extra environment variables. -- Added new `merge_conflicts.md` with detailed guidance on handling conflicts during rebase. -- Type hinting to /tokens, /transaction, /query, /consensus -- Linting to /tokens, /transaction, /query, /consensus -- Module docstrings in /tokens, /transaction, /query, /consensus -- Function docstrings in /tokens, /transaction, /query, /consensus - -### Changed - -- bump solo version to `v0.14` -- bump protobufs version to `v0.66.0` -- bump solo version to `v0.13` -- Extract \_build_proto_body() from build_transaction_body() in every transaction -- StatefulContract's setMessage() function designed with no access restrictions, allowing calls from any address -- bump solo version to `v0.12` -- Extract Ed25519 byte loading logic into private helper method `_from_bytes_ed25519()` -- Documentation structure updated: contents moved from `/documentation` to `/docs`. -- Switched Mirror Node endpoints used by SDK to secure ones instead of deprecated insecure endpoints (shut down on Aug 20th, see [Hedera blogpost](https://hedera.com/blog/updated-deprecation-of-the-insecure-hedera-consensus-service-hcs-mirror-node-endpoints)) -- Update protobuf dependency from 5.28.1 to 5.29.1 -- Update grpcio dependency from 1.68.1 to 1.71.2 -- Updated `rebasing.md` with clarification on using `git reset --soft HEAD~` where `` specifies the number of commits to rewind. -- Calls in examples for PrivateKey.from_string_ed25519(os.getenv('OPERATOR_KEY')) to PrivateKey.from_string(os.getenv('OPERATOR_KEY')) to enable general key types -- Add CI tests across Python 3.10–3.12. -- kyc_status: Optional[TokenFreezeStatusProto] = None → kyc_status: Optional[TokenKycStatus] = None -- assert relationship.freeze_status == TokenFreezeStatus.FROZEN, f"Expected freeze status to be FROZEN, but got {relationship.freeze_status}" → assert relationship.freeze_status == TokenFreezeStatus.UNFROZEN, f"Expected freeze status to be UNFROZEN, but got {relationship.freeze_status}" - -### Fixed - -- Format account_create_transaction.py and add type hints -- Format account_balance.py and fix pylint issues -- Format account_delete_transaction.py and fix pylint issues -- Format account_id.py and fix pylint issues -- Format account_info.py and fix pylint issues -- Format account_update_transaction.py and fix pylint issues -- Unit test compatibility issues when running with UV package manager -- Type annotations in TokenRelationship class (kyc_status and freeze_status) -- Test assertions in test_executable.py using pytest match parameter -- Moved and renamed README_upstream.md to docs/sdk_developers/rebasing.md -- Invalid DRE Hex representation in examples/keys_private_ecdsa.py -- Windows malformed path using uv run generate_proto.py using as_posix() -- Changed README MIT license to Apache -- deprecated CamelCase instances in /examples such as TokenId and totalSupply to snake_case -- Invalid HEX representation and signature validation in keys_public_ecdsa.py -- Invalid signature verification for examples/keys_public_der.py -- Duplicate validation function in TokenCreate - -### Removed - -- Removed the old `/documentation` folder. -- Rebase command in README_upstream changed to just -S -- generate_proto.sh -- pkg_resources dependency in generate_proto.py - -### Breaking API changes - -- We have some changed imports and returns to maintain compatability in the proto bump - -transaction_body_pb2.TransactionBody -> transaction_pb2.TransactionBody -contract_call_local_pb2.ContractFunctionResult -> contract_types_pb2.ContractFunctionResult -contract_call_local_pb2.ContractLoginfo -> contract_types_pb2.ContractLoginfo - -- Removed init.py content in /tokens - -**Changed imports** - -- src/hiero_sdk_python/consensus/topic_message.py: from hiero_sdk_python import Timestamp → from hiero_sdk_python.timestamp import Timestamp -- src/hiero_sdk_python/query/topic_message_query.py: from hiero_sdk_python import Client → from hiero_sdk_python.client.client import Client -- src/hiero_sdk_python/tokens/**init**.py: content removed. -- src/hiero_sdk_python/tokens/token_info.py: from hiero_sdk_python.hapi.services.token_get_info_pb2 import TokenInfo as proto_TokenInfo → from hiero_sdk_python.hapi.services import token_get_info_pb2 -- src/hiero_sdk_python/tokens/token_key_validation.py: from hiero_sdk_python.hapi.services → import basic_types_pb2 -- src/hiero_sdk_python/tokens/token_kyc_status.py: from hiero_sdk_python.hapi.services.basic_types_pb2 import TokenKycStatus as proto_TokenKycStatus → from hiero_sdk_python.hapi.services import basic_types_pb2 -- src/hiero_sdk_python/tokens/token_pause_status.py: from hiero_sdk_python.hapi.services.basic_types_pb2 import (TokenPauseStatus as proto_TokenPauseStatus,) → from hiero_sdk_python.hapi.services import basic_types_pb2 -- src/hiero_sdk_python/tokens/token_pause_transaction.py: from hiero_sdk_python.hapi.services.token_pause_pb2 import TokenPauseTransactionBody → from hiero_sdk_python.hapi.services import token_pause_pb2, transaction_pb2 -- from hiero_sdk_python.hapi.services.token_revoke_kyc_pb2 import TokenRevokeKycTransactionBody → from hiero_sdk_python.hapi.services import token_revoke_kyc_pb2, transaction_pb2 -- src/hiero_sdk_python/tokens/token_update_nfts_transaction.py: from hiero_sdk_python.hapi.services.token_update_nfts_pb2 import TokenUpdateNftsTransactionBody → from hiero_sdk_python.hapi.services import token_update_nfts_pb2,transaction_pb2 -- src/hiero_sdk_python/tokens/token_wipe_transaction.py: from hiero_sdk_python.hapi.services.token_wipe_account_pb2 import TokenWipeAccountTransactionBody → from hiero_sdk_python.hapi.services import token_wipe_account_pb2, transaction_pb2 - -## [0.1.4] - 2025-08-19 - -### Added - -- CONTRIBUTING.md: expanded documentation detailing various contribution processes in a step-by-step way. Includes new sections: blog posts and support. -- README_upstream.md: documentation explaining how to rebase to main. - -### Added - -- Legacy ECDSA DER parse support -- documented private key from_string method behavior -- ContractInfo class -- ContractInfoQuery class -- ContractID check in PublicKey.\_from_proto() method -- PendingAirdropId Class -- PendingAirdropRecord Class -- TokenCancelAirdropTransaction Class -- AccountUpdateTransaction class -- ContractBytecodeQuery class -- SimpleStorage.bin-runtime -- Support for both .bin and .bin-runtime contract bytecode extensions in contract_utils.py -- ContractUpdateTransaction class - -### Fixed - -- missing ECDSA support in query.py and contract_create_transaction.py (was only creating ED25519 keys) -- Applied linting and code formatting across the consensus module -- fixed pip install hiero_sdk_python -> pip install hiero-sdk-python in README.md - -### Breaking API changes - -**We have several camelCase uses that will be deprecated → snake_case** Original aliases will continue to function, with a warning, until the following release. - -#### In `token_info.py` - -- tokenId → token_id -- totalSupply → total_supply -- isDeleted → is_deleted -- tokenType → token_type -- maxSupply → max_supply -- adminKey → admin_key -- kycKey → kyc_key -- freezeKey → freeze_key -- wipeKey → wipe_key -- supplyKey → supply_key -- defaultFreezeStatus → default_freeze_status -- defaultKycStatus → default_kyc_status -- autoRenewAccount → auto_renew_account -- autoRenewPeriod → auto_renew_period -- pauseStatus → pause_status -- supplyType → supply_type - -#### In `nft_id.py` - -- tokenId → token_id -- serialNumber → serial_number - -#### In `transaction_receipt.py` - -- tokenId → token_id -- topicId → topic_id -- accountId → account_id -- fileId → file_id - -### Deprecated Additions - -- logger.warn will be deprecated in v0.1.4. Please use logger.warning instead. -- get_logger method passing (name, level) will be deprecated in v0.1.4 for (level, name). - -## [0.1.3] - 2025-07-03 - -### Added - -- TokenType Class -- MAINTAINERS.md file -- Duration Class -- NFTTokenCreateTransaction Class -- TokenUnfreezeTransaction -- Executable Abstraction -- Logger -- Node Implementation -- Integration Tests across the board -- TokenWipeTransaction Class -- TokenNFTInfoQuery Class -- TokenInfo Class -- TokenRejectTransaction Class -- TokenUpdateNftsTransaction Class -- TokenInfoQuery Class -- TokenPauseTransaction Class -- TokenBurnTransaction Class -- TokenGrantKycTransaction Class -- TokenUpdateTransaction Class -- added Type hinting and initial methods to several modules -- TokenRevoceKycTransaction Class -- [Types Guide](hiero/hedera_sdk_python/documentation/sdk_developers/types.md) - -- TransactionRecordQuery Class -- AccountInfoQuery Class - -### Changed - -- replace datetime.utcnow() with datetime.now(timezone.utc) for Python 3.10 -- updated pr-checks.yml -- added add_require_frozen() to Transaction Base Class -- added NFT Transfer in TransferTransaction -- bumped solo-actions to latest release -- updated to/from_proto method to be protected -- Example scripts updated to be easily run form root -- README updated -- added PublicKey.from_proto to PublicKey class -- changed Query Class to have method get_cost -- SimpleContract and StatefulContract constructors to be payable -- added new_pending_airdrops to TransactionRecord Class -- Reorganized SDK developer documentation: -   - Renamed and moved `README_linting.md` to `linting.md` -   - Renamed and moved `README_types.md` to `types.md` -   - Renamed and moved `Commit_Signing.md` to `signing.md` -- Created `sdk_users` docs folder and renamed `examples/README.md` to `running_examples.md` -- Updated references and links accordingly - -### Fixed - -- fixed INVALID_NODE_ACCOUNT during node switching -- fixed ed25519 key ambiguity (PrivateKey.from_string -> PrivateKey.from_string_ed25519 in examples) - -### Removed - -- Redundant test.py file - -## [0.1.2] - 2025-03-12 - -### Added - -- NFTId Class - -### Changed - -- use SEC1 ECPrivateKey instead of PKCS#8 - -### Fixed - -- PR checks -- misnamed parameter (ECDSASecp256k1=pub_bytes -> ECDSA_secp256k1=pub_bytes) - -### Removed - -- .DS_store file - -## [0.1.1] – 2025-02-25 - -### Added - -- RELEASE.md -- CONTRIBUTING.md - -### Changed - -- README now split into root README for project overview and /examples README for transaction types and syntax. -- Python version incremented from 3.9 to 3.10 - -### Removed - -- pdm.lock & uv.lock file - -## [0.1.0] - 2025-02-19 - -### Added - -- Initial release of the Python SDK core functionality. -- Basic documentation on how to install and use the SDK. -- Example scripts illustrating setup and usage. - -### Changed - -- N/A - -### Fixed - -- N/A - -### Removed - -- N/A - - -# [0.1.0] - 2025-02-19 diff --git a/src/hiero_sdk_python/node.py b/src/hiero_sdk_python/node.py index 4512fd454..ef5936b84 100644 --- a/src/hiero_sdk_python/node.py +++ b/src/hiero_sdk_python/node.py @@ -126,7 +126,6 @@ def _get_channel(self): if self._root_certificates: # Use the certificate that is provided self._node_pem_cert = self._root_certificates - print("node cert ", self._node_pem_cert) else: # Fetch pem_cert for the node From 11192dcfab83d2fa31be340b495e4dc7de468fd2 Mon Sep 17 00:00:00 2001 From: Manish Dait Date: Thu, 16 Apr 2026 14:32:47 +0530 Subject: [PATCH 21/25] chore: fix rebase Signed-off-by: Manish Dait --- .../topic_message_submit_transaction.py | 6 +-- .../file/file_append_transaction.py | 38 ++----------------- src/hiero_sdk_python/node.py | 2 +- .../transaction/transaction.py | 34 +++++++---------- .../file_append_transaction_e2e_test.py | 15 +++----- ...pic_message_submit_transaction_e2e_test.py | 14 +++---- tests/unit/mock_server.py | 6 --- .../topic_message_submit_transaction_test.py | 8 +--- tests/unit/transaction_test.py | 11 ++---- 9 files changed, 36 insertions(+), 98 deletions(-) diff --git a/src/hiero_sdk_python/consensus/topic_message_submit_transaction.py b/src/hiero_sdk_python/consensus/topic_message_submit_transaction.py index dcb3c7b93..a76c056d1 100644 --- a/src/hiero_sdk_python/consensus/topic_message_submit_transaction.py +++ b/src/hiero_sdk_python/consensus/topic_message_submit_transaction.py @@ -4,7 +4,6 @@ from typing import Literal, overload from hiero_sdk_python.channels import _Channel -from typing import List, Literal, Optional, overload from hiero_sdk_python.client.client import Client from hiero_sdk_python.consensus.topic_id import TopicId from hiero_sdk_python.crypto.private_key import PrivateKey @@ -404,7 +403,7 @@ def sign(self, private_key: PrivateKey): super().sign(private_key) return self - + @property def body_size_all_chunks(self) -> list[int]: """Returns an array of body sizes for transactions with multiple chunks.""" @@ -416,8 +415,7 @@ def body_size_all_chunks(self) -> list[int]: for transaction_id in self._transaction_ids: self.transaction_id = transaction_id sizes.append(self.body_size) - + self._current_index = original_index self.transaction_id = original_transaction_id return sizes - \ No newline at end of file diff --git a/src/hiero_sdk_python/file/file_append_transaction.py b/src/hiero_sdk_python/file/file_append_transaction.py index 3ff8a126b..1e43f2674 100644 --- a/src/hiero_sdk_python/file/file_append_transaction.py +++ b/src/hiero_sdk_python/file/file_append_transaction.py @@ -16,7 +16,6 @@ import math from typing import TYPE_CHECKING, Any, Literal, overload -from typing import TYPE_CHECKING, Any, List, Literal, Optional, overload from hiero_sdk_python.file.file_id import FileId from hiero_sdk_python.hapi.services import file_append_pb2, timestamp_pb2 from hiero_sdk_python.hapi.services.schedulable_transaction_body_pb2 import ( @@ -30,10 +29,8 @@ # Use TYPE_CHECKING to avoid circular import errors if TYPE_CHECKING: from hiero_sdk_python.channels import _Channel - from hiero_sdk_python.client import Client + from hiero_sdk_python.client.client import Client from hiero_sdk_python.crypto.private_key import PrivateKey - - from hiero_sdk_python.channels import _Channel from hiero_sdk_python.executable import _Method from hiero_sdk_python.transaction.transaction import TransactionReceipt from hiero_sdk_python.transaction.transaction_response import TransactionResponse @@ -289,35 +286,12 @@ def freeze_with(self, client: Client) -> FileAppendTransaction: if self._transaction_body_bytes: return self - if self.transaction_id is None: - if client is None: - raise ValueError( - "Transaction ID must be set before freezing. Use freeze_with(client) or set_transaction_id()." - ) - - self.transaction_id = client.generate_transaction_id() - - self._resolve_transaction_id(client) # Generate transaction IDs for all chunks if not self._transaction_ids: base_timestamp = self.transaction_id.valid_start - for i in range(self.get_required_chunks()): - if i == 0: - # First chunk uses the original transaction ID - chunk_transaction_id = self.transaction_id - else: - # Subsequent chunks get incremented timestamps - # Add i nanoseconds to space out chunks - chunk_valid_start = timestamp_pb2.Timestamp( - seconds=base_timestamp.seconds, nanos=base_timestamp.nanos + i - ) - chunk_transaction_id = TransactionId( - account_id=self.transaction_id.account_id, valid_start=chunk_valid_start - ) - self._transaction_ids.append(chunk_transaction_id) for i in range(self.get_required_chunks()): if i == 0: # First chunk uses the original transaction ID @@ -326,12 +300,10 @@ def freeze_with(self, client: Client) -> FileAppendTransaction: # Subsequent chunks get incremented timestamps # Add i nanoseconds to space out chunks chunk_valid_start = timestamp_pb2.Timestamp( - seconds=base_timestamp.seconds, - nanos=base_timestamp.nanos + i + seconds=base_timestamp.seconds, nanos=base_timestamp.nanos + i ) chunk_transaction_id = TransactionId( - account_id=self.transaction_id.account_id, - valid_start=chunk_valid_start + account_id=self.transaction_id.account_id, valid_start=chunk_valid_start ) self._transaction_ids.append(chunk_transaction_id) @@ -476,7 +448,6 @@ def sign(self, private_key: PrivateKey) -> FileAppendTransaction: super().sign(private_key) return self - @property def body_size_all_chunks(self) -> list[int]: """Returns an array of body sizes for transactions with multiple chunks.""" @@ -488,8 +459,7 @@ def body_size_all_chunks(self) -> list[int]: for transaction_id in self._transaction_ids: self.transaction_id = transaction_id sizes.append(self.body_size) - + self._current_chunk_index = original_index self.transaction_id = original_transaction_id return sizes - diff --git a/src/hiero_sdk_python/node.py b/src/hiero_sdk_python/node.py index ef5936b84..2a0ecde91 100644 --- a/src/hiero_sdk_python/node.py +++ b/src/hiero_sdk_python/node.py @@ -126,7 +126,7 @@ def _get_channel(self): if self._root_certificates: # Use the certificate that is provided self._node_pem_cert = self._root_certificates - + else: # Fetch pem_cert for the node self._node_pem_cert = self._fetch_server_certificate_pem() diff --git a/src/hiero_sdk_python/transaction/transaction.py b/src/hiero_sdk_python/transaction/transaction.py index 3389f5404..acf7b1278 100644 --- a/src/hiero_sdk_python/transaction/transaction.py +++ b/src/hiero_sdk_python/transaction/transaction.py @@ -226,34 +226,28 @@ def _to_proto(self): signed_transaction = transaction_contents_pb2.SignedTransaction(bodyBytes=body_bytes, sigMap=sig_map) + return transaction_pb2.Transaction(signedTransactionBytes=signed_transaction.SerializeToString()) - return transaction_pb2.Transaction( - signedTransactionBytes=signed_transaction.SerializeToString() - ) - - def _resolve_transaction_id(self, client: "Client"): + def _resolve_transaction_id(self, client: Client): if self.transaction_id is not None: return - + if client is not None: operator_account_id = client.operator_account_id if operator_account_id is not None: self.transaction_id = client.generate_transaction_id() else: - raise ValueError( - "Client must have an operator_account or transactionId must be set." - ) + raise ValueError("Client must have an operator_account or transactionId must be set.") else: raise ValueError( "Transaction ID must be set before freezing. Use freeze_with(client) or set_transaction_id()." ) - - def _resolve_node_ids(self, client: "Client"): - if self.node_account_id is None and len(self.node_account_ids) == 0: - if client is None: - raise ValueError( - "Node account ID must be set before freezing. Use freeze_with(client) or manually set node_account_ids." - ) + + def _resolve_node_ids(self, client: Client): + if self.node_account_id is None and len(self.node_account_ids) == 0 and client is None: + raise ValueError( + "Node account ID must be set before freezing. Use freeze_with(client) or manually set node_account_ids." + ) def freeze(self): """ @@ -275,7 +269,7 @@ def freeze(self): """ return self.freeze_with(None) - def freeze_with(self, client: "Client"): + def freeze_with(self, client: Client): """ Freezes the transaction by building the transaction body and setting necessary IDs. @@ -291,13 +285,11 @@ def freeze_with(self, client: "Client"): if self._transaction_body_bytes: return self - # Check transaction_id and node id to be set when using freeze() self._resolve_transaction_id(client) - self._resolve_node_ids(client) - + # We iterate through every node in the client's network # For each node, set the node_account_id and build the transaction body # This allows the transaction to be submitted to any node in the network @@ -934,7 +926,7 @@ def size(self) -> int: """Returns the total transaction size in bytes after protobuf encoding""" self._require_frozen() return self._make_request().ByteSize() - + @property def body_size(self) -> int: """Returns just the transaction body size in bytes after encoding""" diff --git a/tests/integration/file_append_transaction_e2e_test.py b/tests/integration/file_append_transaction_e2e_test.py index 167931cfe..ace6d0acb 100644 --- a/tests/integration/file_append_transaction_e2e_test.py +++ b/tests/integration/file_append_transaction_e2e_test.py @@ -4,16 +4,12 @@ from pytest import mark from hiero_sdk_python.account.account_id import AccountId -from hiero_sdk_python.file.file_create_transaction import FileCreateTransaction from hiero_sdk_python.file.file_append_transaction import FileAppendTransaction from hiero_sdk_python.file.file_contents_query import FileContentsQuery from hiero_sdk_python.file.file_create_transaction import FileCreateTransaction from hiero_sdk_python.response_code import ResponseCode - -from hiero_sdk_python.hbar import Hbar -from hiero_sdk_python.exceptions import PrecheckError from hiero_sdk_python.transaction.transaction_id import TransactionId -from tests.integration.utils import env, IntegrationTestEnv + # Generate big contents for chunking tests - similar to JavaScript bigContents BIG_CONTENTS = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " * 250 # ~13,750 characters @@ -289,7 +285,8 @@ def test_integration_file_append_transaction_method_chaining(env): append_receipt = append_tx.execute(env.client) assert append_receipt.status == ResponseCode.SUCCESS - assert append_receipt.status == ResponseCode.SUCCESS + assert append_receipt.status == ResponseCode.SUCCESS + @pytest.mark.integration def test_file_append_chunk_transaction_can_execute_with_manual_freeze(env): @@ -307,7 +304,7 @@ def test_file_append_chunk_transaction_can_execute_with_manual_freeze(env): file_contents = FileContentsQuery().set_file_id(file_id).execute(env.client) assert file_contents == b"" - content = "A" * (4000) # content with (4000/1024) bytes ie approx 4 chunks + content = "A" * (4000) # content with (4000/1024) bytes ie approx 4 chunks tx = ( FileAppendTransaction() @@ -315,14 +312,14 @@ def test_file_append_chunk_transaction_can_execute_with_manual_freeze(env): .set_chunk_size(1024) .set_contents(content) .set_transaction_id(TransactionId.generate(env.client.operator_account_id)) - .set_node_account_id(AccountId(0,0,3)) + .set_node_account_id(AccountId(0, 0, 3)) .freeze() ) tx.sign(env.client.operator_private_key) receipt = tx.execute(env.client) - + assert receipt.status == ResponseCode.SUCCESS file_contents = FileContentsQuery().set_file_id(file_id).execute(env.client) diff --git a/tests/integration/topic_message_submit_transaction_e2e_test.py b/tests/integration/topic_message_submit_transaction_e2e_test.py index 223ca362d..23393e150 100644 --- a/tests/integration/topic_message_submit_transaction_e2e_test.py +++ b/tests/integration/topic_message_submit_transaction_e2e_test.py @@ -19,9 +19,9 @@ from hiero_sdk_python.response_code import ResponseCode from hiero_sdk_python.tokens.custom_fixed_fee import CustomFixedFee from hiero_sdk_python.transaction.custom_fee_limit import CustomFeeLimit - from hiero_sdk_python.transaction.transaction_id import TransactionId + def create_topic(client, admin_key=None, submit_key=None, custom_fees=None): """Helper transaction for creating a topic.""" tx = TopicCreateTransaction(memo="Python SDK topic") @@ -300,32 +300,28 @@ def test_integration_topic_message_submit_transaction_fails_if_required_chunk_gr delete_topic(env.client, topic_id) - @pytest.mark.integration def test_topic_message_submit_transaction_can_submit_a_large_message_manual_freeze(env): """Test topic message submit transaction can submit large message with manual freeze.""" - topic_id = create_topic( - client=env.client, - admin_key=env.operator_key - ) + topic_id = create_topic(client=env.client, admin_key=env.operator_key) info = TopicInfoQuery().set_topic_id(topic_id).execute(env.client) assert info.sequence_number == 0 - message = "A" * (1024 * 14) # message with (1024 * 14) bytes ie 14 chunks + message = "A" * (1024 * 14) # message with (1024 * 14) bytes ie 14 chunks message_tx = ( TopicMessageSubmitTransaction() .set_topic_id(topic_id) .set_message(message) .set_transaction_id(TransactionId.generate(env.client.operator_account_id)) - .set_node_account_id(AccountId(0,0,3)) + .set_node_account_id(AccountId(0, 0, 3)) .freeze() ) message_tx.sign(env.client.operator_private_key) message_receipt = message_tx.execute(env.client) - + assert message_receipt.status == ResponseCode.SUCCESS info = TopicInfoQuery().set_topic_id(topic_id).execute(env.client) diff --git a/tests/unit/mock_server.py b/tests/unit/mock_server.py index 1d4febf20..cdb5f848f 100644 --- a/tests/unit/mock_server.py +++ b/tests/unit/mock_server.py @@ -181,12 +181,6 @@ def mock_hedera_servers(response_sequences): client = Client(network) - # Force non-tls channel - for node in client.network.nodes: - node._address._is_transport_security = lambda: False - node._set_verify_certificates(False) - node._close() - client.logger.set_level(LogLevel.DISABLED) # Set the operator key = PrivateKey.generate() diff --git a/tests/unit/topic_message_submit_transaction_test.py b/tests/unit/topic_message_submit_transaction_test.py index f2761f0cc..6fb5a68ed 100644 --- a/tests/unit/topic_message_submit_transaction_test.py +++ b/tests/unit/topic_message_submit_transaction_test.py @@ -6,7 +6,6 @@ import pytest -from hiero_sdk_python.account.account_id import AccountId from hiero_sdk_python.consensus.topic_message_submit_transaction import TopicMessageSubmitTransaction from hiero_sdk_python.exceptions import PrecheckError, ReceiptStatusError from hiero_sdk_python.hapi.services import ( @@ -505,13 +504,10 @@ def test_topic_submit_execute_returns_failed_receipt_by_default(topic_id): assert receipt.status == ResponseCode.INVALID_SIGNATURE + def test_topic_submit_message_raises_error_on_freeze(topic_id): """Test transaction raises error on freeze when the transaction_id and node_id not set""" - tx = ( - TopicMessageSubmitTransaction() - .set_topic_id(topic_id) - .set_message("Hello Hiero") - ) + tx = TopicMessageSubmitTransaction().set_topic_id(topic_id).set_message("Hello Hiero") with pytest.raises(ValueError): tx.freeze() diff --git a/tests/unit/transaction_test.py b/tests/unit/transaction_test.py index a60847f37..345a84b7a 100644 --- a/tests/unit/transaction_test.py +++ b/tests/unit/transaction_test.py @@ -4,7 +4,6 @@ from hiero_sdk_python.account.account_create_transaction import AccountCreateTransaction from hiero_sdk_python.account.account_id import AccountId -from hiero_sdk_python.consensus.topic_id import TopicId from hiero_sdk_python.consensus.topic_message_submit_transaction import TopicMessageSubmitTransaction from hiero_sdk_python.crypto.private_key import PrivateKey from hiero_sdk_python.exceptions import ReceiptStatusError @@ -275,9 +274,7 @@ def test_tx_with_larger_content_should_have_larger_tx_body(transaction_id, accou assert tx1.body_size < tx2.body_size -def test_tx_without_optional_fields_should_have_smaller_tx_body( - transaction_id, account_id -): +def test_tx_without_optional_fields_should_have_smaller_tx_body(transaction_id, account_id): """Test transaction with without optional fields should have smaller transaction body.""" key = PrivateKey.generate() tx1 = ( @@ -343,7 +340,7 @@ def test_file_append_single_chunk_tx_return_list_of_len_one(file_id, account_id, def test_message_submit_chunk_tx_should_return_list_of_body_sizes(topic_id, account_id, transaction_id): """Test topic message submit tx should return array of body sizes for multi-chunk transaction.""" chunk_size = 1024 - message= "a" * (chunk_size * 3) + message = "a" * (chunk_size * 3) tx = ( TopicMessageSubmitTransaction() @@ -377,9 +374,7 @@ def test_message_submit_single_chunk_tx_return_list_of_len_one(topic_id, account assert len(sizes) == 1 -def test_tx_with_no_content_should_return_single_body_chunk( - file_id, account_id, transaction_id -): +def test_tx_with_no_content_should_return_single_body_chunk(file_id, account_id, transaction_id): """Test should return single body chunk for transaction with no content.""" tx = ( FileAppendTransaction() From 1c0d56b97086fa3c2538b09ab7a33bd81d348d78 Mon Sep 17 00:00:00 2001 From: Manish Dait Date: Tue, 21 Apr 2026 12:59:12 +0530 Subject: [PATCH 22/25] chore: added suggestion Signed-off-by: Manish Dait --- examples/test.py | 32 +++++++++++++++++++ .../topic_message_submit_transaction.py | 19 +++++++---- .../file/file_append_transaction.py | 19 +++++++---- tests/unit/transaction_test.py | 3 ++ 4 files changed, 61 insertions(+), 12 deletions(-) create mode 100644 examples/test.py diff --git a/examples/test.py b/examples/test.py new file mode 100644 index 000000000..f29f9ec27 --- /dev/null +++ b/examples/test.py @@ -0,0 +1,32 @@ +from hiero_sdk_python.account.account_create_transaction import AccountCreateTransaction +from hiero_sdk_python.account.account_id import AccountId +from hiero_sdk_python.client.client import Client +from hiero_sdk_python.consensus.topic_id import TopicId +from hiero_sdk_python.consensus.topic_message_submit_transaction import TopicMessageSubmitTransaction +from hiero_sdk_python.crypto.private_key import PrivateKey + + +def main() -> None: + client = Client.from_env() + tx = ( + AccountCreateTransaction() + .set_key(PrivateKey.generate()) + .set_node_account_id(AccountId(0, 0, 3)) + .freeze_with(client) + ) + print(tx.size) + print(tx.body_size) + + tx2 = ( + TopicMessageSubmitTransaction() + .set_topic_id(TopicId.from_string("0.0.23")) + .set_message("A" * 1300) + .freeze_with(client) + ) + print(tx2.size) + print(tx2.body_size) + print(tx2.body_size_all_chunks) + + +if __name__ == "__main__": + main() diff --git a/src/hiero_sdk_python/consensus/topic_message_submit_transaction.py b/src/hiero_sdk_python/consensus/topic_message_submit_transaction.py index a76c056d1..5e2c4ff3d 100644 --- a/src/hiero_sdk_python/consensus/topic_message_submit_transaction.py +++ b/src/hiero_sdk_python/consensus/topic_message_submit_transaction.py @@ -265,8 +265,10 @@ def freeze_with(self, client: Client) -> TopicMessageSubmitTransaction: chunk_transaction_id = self.transaction_id else: + next_nanos = base_timestamp.nanos + i + chunk_valid_start = timestamp_pb2.Timestamp( - seconds=base_timestamp.seconds, nanos=base_timestamp.nanos + i + seconds=base_timestamp.seconds + next_nanos // 1_000_000_000, nanos=next_nanos % 1_000_000_000 ) chunk_transaction_id = TransactionId( account_id=self.transaction_id.account_id, valid_start=chunk_valid_start @@ -412,10 +414,15 @@ def body_size_all_chunks(self) -> list[int]: original_index = self._current_index original_transaction_id = self.transaction_id - for transaction_id in self._transaction_ids: - self.transaction_id = transaction_id - sizes.append(self.body_size) - self._current_index = original_index - self.transaction_id = original_transaction_id + try: + for i, transaction_id in enumerate(self._transaction_ids): + self._current_index = i + self.transaction_id = transaction_id + + sizes.append(self.body_size) + finally: + self._current_index = original_index + self.transaction_id = original_transaction_id + return sizes diff --git a/src/hiero_sdk_python/file/file_append_transaction.py b/src/hiero_sdk_python/file/file_append_transaction.py index 1e43f2674..3019296a5 100644 --- a/src/hiero_sdk_python/file/file_append_transaction.py +++ b/src/hiero_sdk_python/file/file_append_transaction.py @@ -299,8 +299,10 @@ def freeze_with(self, client: Client) -> FileAppendTransaction: else: # Subsequent chunks get incremented timestamps # Add i nanoseconds to space out chunks + next_nanos = base_timestamp.nanos + i + chunk_valid_start = timestamp_pb2.Timestamp( - seconds=base_timestamp.seconds, nanos=base_timestamp.nanos + i + seconds=base_timestamp.seconds + next_nanos // 1_000_000_000, nanos=next_nanos % 1_000_000_000 ) chunk_transaction_id = TransactionId( account_id=self.transaction_id.account_id, valid_start=chunk_valid_start @@ -456,10 +458,15 @@ def body_size_all_chunks(self) -> list[int]: original_index = self._current_chunk_index original_transaction_id = self.transaction_id - for transaction_id in self._transaction_ids: - self.transaction_id = transaction_id - sizes.append(self.body_size) - self._current_chunk_index = original_index - self.transaction_id = original_transaction_id + try: + for i, transaction_id in enumerate(self._transaction_ids): + self._current_chunk_index = i + self.transaction_id = transaction_id + + sizes.append(self.body_size) + finally: + self._current_chunk_index = original_index + self.transaction_id = original_transaction_id + return sizes diff --git a/tests/unit/transaction_test.py b/tests/unit/transaction_test.py index 345a84b7a..465d4d44e 100644 --- a/tests/unit/transaction_test.py +++ b/tests/unit/transaction_test.py @@ -423,3 +423,6 @@ def test_chunked_tx_return_proper_sizes(file_id, account_id, transaction_id): # The larger chunked transaction should be bigger than the single-chunk transaction assert large_size > small_size + + # Check for chuck index reset reset + assert large_tx._current_chunk_index == 0 From 765b8bad918e861dc2c0d89be647a299b0ee09bd Mon Sep 17 00:00:00 2001 From: Manish Dait Date: Tue, 21 Apr 2026 13:15:58 +0530 Subject: [PATCH 23/25] chore: add test for validating changes Signed-off-by: Manish Dait --- tests/unit/file_append_transaction_test.py | 29 ++++++++++++++++++ .../topic_message_submit_transaction_test.py | 30 +++++++++++++++++++ tests/unit/transaction_test.py | 25 ++++++++++++++-- 3 files changed, 81 insertions(+), 3 deletions(-) diff --git a/tests/unit/file_append_transaction_test.py b/tests/unit/file_append_transaction_test.py index 479acefd5..4b832c43e 100644 --- a/tests/unit/file_append_transaction_test.py +++ b/tests/unit/file_append_transaction_test.py @@ -4,12 +4,14 @@ import pytest +from hiero_sdk_python.account.account_id import AccountId from hiero_sdk_python.exceptions import PrecheckError, ReceiptStatusError from hiero_sdk_python.file.file_append_transaction import FileAppendTransaction from hiero_sdk_python.file.file_id import FileId from hiero_sdk_python.hapi.services import ( response_header_pb2, response_pb2, + timestamp_pb2, transaction_get_receipt_pb2, transaction_receipt_pb2, transaction_response_pb2, @@ -372,3 +374,30 @@ def test_file_append_execute_all_returns_receipt_without_validation(file_id): receipts = tx.execute_all(client) assert receipts[0].status == ResponseCode.INVALID_FILE_ID + + +def test_chunk_transaction_id_nanosecond_overflow(file_id): + """Test that multi-chunk transaction IDs handle nanosecond overflow correctly.""" + base_seconds = 1770911831 + base_nanos = 999_999_999 + + start_timestamp = timestamp_pb2.Timestamp(seconds=base_seconds, nanos=base_nanos) + tx_id = TransactionId(account_id=AccountId(0, 0, 2), valid_start=start_timestamp) + + tx = ( + FileAppendTransaction() + .set_file_id(file_id) + .set_contents("a" * 20) + .set_chunk_size(10) + .set_transaction_id(tx_id) + .set_node_account_id(AccountId(0, 0, 3)) + .freeze() + ) + + # First chunk is exactly equal initial ID + assert tx._transaction_ids[0].valid_start.seconds == base_seconds + assert tx._transaction_ids[0].valid_start.nanos == base_nanos + + # Second chunk seconds=base_seconds + 1, nanos=0 + assert tx._transaction_ids[1].valid_start.seconds == base_seconds + 1 + assert tx._transaction_ids[1].valid_start.nanos == 0 diff --git a/tests/unit/topic_message_submit_transaction_test.py b/tests/unit/topic_message_submit_transaction_test.py index 6fb5a68ed..b4efcaf38 100644 --- a/tests/unit/topic_message_submit_transaction_test.py +++ b/tests/unit/topic_message_submit_transaction_test.py @@ -6,11 +6,13 @@ import pytest +from hiero_sdk_python.account.account_id import AccountId from hiero_sdk_python.consensus.topic_message_submit_transaction import TopicMessageSubmitTransaction from hiero_sdk_python.exceptions import PrecheckError, ReceiptStatusError from hiero_sdk_python.hapi.services import ( response_header_pb2, response_pb2, + timestamp_pb2, transaction_get_receipt_pb2, transaction_receipt_pb2, transaction_response_pb2, @@ -20,6 +22,7 @@ ) from hiero_sdk_python.response_code import ResponseCode from hiero_sdk_python.transaction.custom_fee_limit import CustomFeeLimit +from hiero_sdk_python.transaction.transaction_id import TransactionId from hiero_sdk_python.transaction.transaction_receipt import TransactionReceipt from hiero_sdk_python.transaction.transaction_response import TransactionResponse from tests.unit.mock_server import mock_hedera_servers @@ -511,3 +514,30 @@ def test_topic_submit_message_raises_error_on_freeze(topic_id): with pytest.raises(ValueError): tx.freeze() + + +def test_chunk_transaction_id_nanosecond_overflow(topic_id): + """Test that multi-chunk transaction IDs handle nanosecond overflow correctly.""" + base_seconds = 1770911831 + base_nanos = 999_999_999 + + start_timestamp = timestamp_pb2.Timestamp(seconds=base_seconds, nanos=base_nanos) + tx_id = TransactionId(account_id=AccountId(0, 0, 2), valid_start=start_timestamp) + + tx = ( + TopicMessageSubmitTransaction() + .set_topic_id(topic_id) + .set_message("a" * 20) + .set_chunk_size(10) + .set_transaction_id(tx_id) + .set_node_account_id(AccountId(0, 0, 3)) + .freeze() + ) + + # First chunk is exactly equal initial ID + assert tx._transaction_ids[0].valid_start.seconds == base_seconds + assert tx._transaction_ids[0].valid_start.nanos == base_nanos + + # Second chunk seconds=base_seconds + 1, nanos=0 + assert tx._transaction_ids[1].valid_start.seconds == base_seconds + 1 + assert tx._transaction_ids[1].valid_start.nanos == 0 diff --git a/tests/unit/transaction_test.py b/tests/unit/transaction_test.py index 465d4d44e..3a9865771 100644 --- a/tests/unit/transaction_test.py +++ b/tests/unit/transaction_test.py @@ -355,6 +355,7 @@ def test_message_submit_chunk_tx_should_return_list_of_body_sizes(topic_id, acco sizes = tx.body_size_all_chunks assert isinstance(sizes, list) assert len(sizes) == 3 + assert tx._current_index == 0 def test_message_submit_single_chunk_tx_return_list_of_len_one(topic_id, account_id, transaction_id): @@ -420,9 +421,27 @@ def test_chunked_tx_return_proper_sizes(file_id, account_id, transaction_id): # Size should be greater than single chunk size assert large_size > 1024 - # The larger chunked transaction should be bigger than the single-chunk transaction assert large_size > small_size - - # Check for chuck index reset reset assert large_tx._current_chunk_index == 0 + + +def test_chunked_tx_differ_size_if_chunk_are_not_equal(topic_id, account_id, transaction_id): + """Test that the last chunk's size is different from the full chunks if the chunk size is not even.""" + chunk_size = 1024 + message = "a" * (chunk_size + 512) + + tx = ( + TopicMessageSubmitTransaction() + .set_topic_id(topic_id) + .set_chunk_size(chunk_size) + .set_message(message) + .set_transaction_id(transaction_id) + .set_node_account_id(account_id) + .freeze() + ) + + sizes = tx.body_size_all_chunks + assert len(sizes) == 2 + # The first chunk should be larger than the second because it carries more message data + assert sizes[0] > sizes[1] From e759b2e2dd9c9467bd3da0818164db21d10b0163 Mon Sep 17 00:00:00 2001 From: Manish Dait Date: Tue, 21 Apr 2026 13:24:55 +0530 Subject: [PATCH 24/25] chore: remove test.py Signed-off-by: Manish Dait --- examples/test.py | 32 -------------------------------- 1 file changed, 32 deletions(-) delete mode 100644 examples/test.py diff --git a/examples/test.py b/examples/test.py deleted file mode 100644 index f29f9ec27..000000000 --- a/examples/test.py +++ /dev/null @@ -1,32 +0,0 @@ -from hiero_sdk_python.account.account_create_transaction import AccountCreateTransaction -from hiero_sdk_python.account.account_id import AccountId -from hiero_sdk_python.client.client import Client -from hiero_sdk_python.consensus.topic_id import TopicId -from hiero_sdk_python.consensus.topic_message_submit_transaction import TopicMessageSubmitTransaction -from hiero_sdk_python.crypto.private_key import PrivateKey - - -def main() -> None: - client = Client.from_env() - tx = ( - AccountCreateTransaction() - .set_key(PrivateKey.generate()) - .set_node_account_id(AccountId(0, 0, 3)) - .freeze_with(client) - ) - print(tx.size) - print(tx.body_size) - - tx2 = ( - TopicMessageSubmitTransaction() - .set_topic_id(TopicId.from_string("0.0.23")) - .set_message("A" * 1300) - .freeze_with(client) - ) - print(tx2.size) - print(tx2.body_size) - print(tx2.body_size_all_chunks) - - -if __name__ == "__main__": - main() From 26d08b46ddfb2e9d67ffde7f42573b3303e9a24e Mon Sep 17 00:00:00 2001 From: Manish Dait Date: Sat, 9 May 2026 23:38:24 +0530 Subject: [PATCH 25/25] chore: rebase fix Signed-off-by: Manish Dait --- .../topic_message_submit_transaction.py | 6 +++--- .../transaction/transaction.py | 2 +- tests/unit/transaction_test.py | 19 +------------------ 3 files changed, 5 insertions(+), 22 deletions(-) diff --git a/src/hiero_sdk_python/consensus/topic_message_submit_transaction.py b/src/hiero_sdk_python/consensus/topic_message_submit_transaction.py index 5e2c4ff3d..0cc9529d5 100644 --- a/src/hiero_sdk_python/consensus/topic_message_submit_transaction.py +++ b/src/hiero_sdk_python/consensus/topic_message_submit_transaction.py @@ -412,17 +412,17 @@ def body_size_all_chunks(self) -> list[int]: self._require_frozen() sizes = [] - original_index = self._current_index + original_index = self._current_chunk_index original_transaction_id = self.transaction_id try: for i, transaction_id in enumerate(self._transaction_ids): - self._current_index = i + self._current_chunk_index = i self.transaction_id = transaction_id sizes.append(self.body_size) finally: - self._current_index = original_index + self._current_chunk_index = original_index self.transaction_id = original_transaction_id return sizes diff --git a/src/hiero_sdk_python/transaction/transaction.py b/src/hiero_sdk_python/transaction/transaction.py index acf7b1278..9d2f1ebff 100644 --- a/src/hiero_sdk_python/transaction/transaction.py +++ b/src/hiero_sdk_python/transaction/transaction.py @@ -920,7 +920,7 @@ def get_required_chunks(self): int: Number of chunks required. """ return 1 - + @property def size(self) -> int: """Returns the total transaction size in bytes after protobuf encoding""" diff --git a/tests/unit/transaction_test.py b/tests/unit/transaction_test.py index 3a9865771..6ffa36549 100644 --- a/tests/unit/transaction_test.py +++ b/tests/unit/transaction_test.py @@ -23,7 +23,6 @@ from hiero_sdk_python.tokens.token_id import TokenId from hiero_sdk_python.tokens.token_mint_transaction import TokenMintTransaction from hiero_sdk_python.transaction.transaction_id import TransactionId -from hiero_sdk_python.transaction.transaction_id import TransactionId from hiero_sdk_python.transaction.transaction_receipt import TransactionReceipt from hiero_sdk_python.transaction.transaction_response import TransactionResponse from tests.unit.mock_server import mock_hedera_servers @@ -184,22 +183,6 @@ def test_multiple_keys_still_work(): key2.public_key().to_bytes_raw(), } assert pubkey_prefixes == expected_prefixes, "Signatures should match key1 and key2 exactly" -@pytest.fixture -def file_id(): - """Returns a file_is for test.""" - return FileId.from_string("0.0.1") - - -@pytest.fixture -def account_id(): - """Returns an account_id for test.""" - return AccountId.from_string("0.0.9") - - -@pytest.fixture -def transaction_id(): - """Returns a transaction_id for test.""" - return TransactionId.from_string("0.0.9@1770911831.331000137") def test_same_size_for_identical_transactions(transaction_id, account_id): @@ -355,7 +338,7 @@ def test_message_submit_chunk_tx_should_return_list_of_body_sizes(topic_id, acco sizes = tx.body_size_all_chunks assert isinstance(sizes, list) assert len(sizes) == 3 - assert tx._current_index == 0 + assert tx._current_chunk_index == 0 def test_message_submit_single_chunk_tx_return_list_of_len_one(topic_id, account_id, transaction_id):