Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions src/hiero_sdk_python/consensus/topic_create_transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

from __future__ import annotations

from typing import TYPE_CHECKING

from hiero_sdk_python.account.account_id import AccountId
from hiero_sdk_python.channels import _Channel
from hiero_sdk_python.crypto.key import Key
Expand All @@ -23,6 +25,10 @@
from hiero_sdk_python.utils.key_utils import key_to_proto


if TYPE_CHECKING:
from hiero_sdk_python.client.client import Client


class TopicCreateTransaction(Transaction):
"""
Represents a transaction to create a new topic in the Hedera
Expand Down Expand Up @@ -187,6 +193,27 @@ def set_fee_exempt_keys(self, keys: list[Key]) -> TopicCreateTransaction:
self.fee_exempt_keys = keys
return self

def freeze_with(self, client: Client) -> TopicCreateTransaction:
"""
Freeze the transaction with the given client.

If `auto_renew_account` was not explicitly set, automatically assigns it:
- If `transaction_id` is already set, use its `account_id`.
- Otherwise, fall back to the client's `operator_account_id`.

Args:
client (Client): The client instance to use for setting defaults.

Returns:
TopicCreateTransaction: The current transaction instance for method chaining.
"""
if client is not None and client.operator_account_id is not None and self.auto_renew_account is None:
self.auto_renew_account = (
self.transaction_id.account_id if self.transaction_id is not None else client.operator_account_id
)

return super().freeze_with(client)
Comment on lines +210 to +215
Comment on lines +210 to +215

def _to_proto_key(self, key: Key | None):
"""
Backwards-compatible wrapper around `key_to_proto` for converting SDK keys
Expand Down
3 changes: 0 additions & 3 deletions tck/handlers/topic.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,6 @@ def create_topic(params: CreateTopicParams) -> CreateTopicResponse:

transaction = _build_create_topic_transaction(params)

if params.autoRenewAccountId is None and client is not None and client.operator_account_id is not None:
transaction.set_auto_renew_account(client.operator_account_id)

if params.commonTransactionParams is not None:
params.commonTransactionParams.apply_common_params(transaction, client)

Expand Down
67 changes: 67 additions & 0 deletions tests/unit/topic_create_transaction_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from hiero_sdk_python.response_code import ResponseCode
from hiero_sdk_python.tokens.custom_fixed_fee import CustomFixedFee
from hiero_sdk_python.tokens.token_id import TokenId
from hiero_sdk_python.transaction.transaction_id import TransactionId
from tests.unit.mock_server import mock_hedera_servers


Expand Down Expand Up @@ -574,3 +575,69 @@ def test_mixed_key_types_in_constructor(mock_account_ids):
assert transaction_body.consensusCreateTopic.submitKey.ed25519 == ed25519_public.to_bytes_raw()
assert transaction_body.consensusCreateTopic.fee_schedule_key.HasField("ECDSA_secp256k1")
assert len(transaction_body.consensusCreateTopic.fee_exempt_key_list) == 2


def _generate_transaction_id(account_id):
"""Generate a unique transaction ID based on the account ID and the current timestamp."""
import time
Comment on lines +580 to +582

from hiero_sdk_python.hapi.services import timestamp_pb2

current_time = time.time()
timestamp_seconds = int(current_time)
timestamp_nanos = int((current_time - timestamp_seconds) * 1e9)

tx_timestamp = timestamp_pb2.Timestamp(seconds=timestamp_seconds, nanos=timestamp_nanos)
return TransactionId(valid_start=tx_timestamp, account_id=account_id)
Comment on lines +586 to +591


def test_freeze_with_defaults_auto_renew_account_to_operator(mock_client):
"""Test that freeze_with sets auto_renew_account to operator when not explicitly set."""
tx = TopicCreateTransaction(memo="test topic")
frozen_tx = tx.freeze_with(mock_client)
body = frozen_tx.build_transaction_body()

assert body.consensusCreateTopic.autoRenewAccount == mock_client.operator_account_id._to_proto()


def test_freeze_with_preserves_explicit_auto_renew_account(mock_client):
"""Test that freeze_with does not override an explicitly set auto_renew_account."""
explicit_account = AccountId(0, 0, 9999)
tx = TopicCreateTransaction(memo="test topic", auto_renew_account=explicit_account)
frozen_tx = tx.freeze_with(mock_client)
body = frozen_tx.build_transaction_body()

assert body.consensusCreateTopic.autoRenewAccount == explicit_account._to_proto()


def test_freeze_with_uses_transaction_id_account_when_set(mock_client):
"""Test that freeze_with uses transaction_id.account_id when transaction_id is set."""
tx_account = AccountId(0, 0, 5555)
tx = TopicCreateTransaction(memo="test topic")
tx.transaction_id = _generate_transaction_id(tx_account)
frozen_tx = tx.freeze_with(mock_client)
body = frozen_tx.build_transaction_body()

assert body.consensusCreateTopic.autoRenewAccount == tx_account._to_proto()


def test_freeze_with_auto_renew_account_set_via_setter(mock_client):
"""Test that freeze_with preserves auto_renew_account set via set_auto_renew_account."""
explicit_account = AccountId(0, 0, 7777)
tx = TopicCreateTransaction(memo="test topic")
tx.set_auto_renew_account(explicit_account)
frozen_tx = tx.freeze_with(mock_client)
body = frozen_tx.build_transaction_body()

assert body.consensusCreateTopic.autoRenewAccount == explicit_account._to_proto()
Comment thread
coderabbitai[bot] marked this conversation as resolved.


def test_freeze_with_leaves_auto_renew_account_unset_without_operator(mock_client):
"""Test that freeze_with leaves auto_renew_account unset when operator_account_id is None."""
mock_client.operator_account_id = None
tx = TopicCreateTransaction(memo="test topic")
tx.transaction_id = _generate_transaction_id(AccountId(0, 0, 1234))
frozen_tx = tx.freeze_with(mock_client)
body = frozen_tx.build_transaction_body()

assert not body.consensusCreateTopic.HasField("autoRenewAccount")
Loading