-
Notifications
You must be signed in to change notification settings - Fork 287
feat: implement endpoint for createTopic method
#2215
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
exploreriii
merged 11 commits into
hiero-ledger:main
from
MonaaEid:test/2207-createTopic-tck
May 15, 2026
Merged
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
376553e
feat: implement createTopic functionality and related parameters in T…
MonaaEid 86e567c
feat: implement createTopic functionality and related parameters in T…
MonaaEid d7211e4
feat: implement createTopic functionality and related parameters in T…
MonaaEid 1e8aa1d
feat: implement createTopic functionality and related parameters in T…
MonaaEid 3fb9d77
Merge branch 'main' into test/2207-createTopic-tck
MonaaEid 8d3938e
feat: implement createTopic functionality and related parameters in T…
MonaaEid 76e2d4a
Merge branch 'main' into test/2207-createTopic-tck
MonaaEid a621641
feat: implement createTopic functionality and related parameters in T…
MonaaEid d5b30c8
Merge branch 'main' into test/2207-createTopic-tck
MonaaEid 0132448
Merge branch 'main' into test/2207-createTopic-tck
MonaaEid 56c7fed
Merge branch 'main' into test/2207-createTopic-tck
MonaaEid File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,89 @@ | ||
| from __future__ import annotations | ||
|
|
||
| from hiero_sdk_python.account.account_id import AccountId | ||
| from hiero_sdk_python.consensus.topic_create_transaction import TopicCreateTransaction | ||
| 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_receipt import TransactionReceipt | ||
| from tck.handlers.registry import rpc_method | ||
| from tck.param.topic import CreateTopicCustomFeeParams, CreateTopicParams | ||
| from tck.response.topic import CreateTopicResponse | ||
| from tck.util.client_utils import get_client | ||
| from tck.util.constants import DEFAULT_GRPC_TIMEOUT | ||
| from tck.util.key_utils import get_key_from_string | ||
|
|
||
|
|
||
| def _build_custom_fee(custom_fee_params: CreateTopicCustomFeeParams) -> CustomFixedFee: | ||
| custom_fee = CustomFixedFee() | ||
|
|
||
| if custom_fee_params.feeCollectorAccountId == "": | ||
| # Keep TCK behavior: explicitly empty collector should surface as internal error. | ||
| raise ValueError("feeCollectorAccountId cannot be empty") | ||
|
|
||
| if custom_fee_params.feeCollectorAccountId is not None: | ||
| custom_fee.set_fee_collector_account_id(AccountId.from_string(custom_fee_params.feeCollectorAccountId)) | ||
|
|
||
| if custom_fee_params.feeCollectorsExempt: | ||
| custom_fee.set_all_collectors_are_exempt(custom_fee_params.feeCollectorsExempt) | ||
|
|
||
| if custom_fee_params.fixedFee is not None: | ||
| if custom_fee_params.fixedFee.amount is not None: | ||
| custom_fee.amount = custom_fee_params.fixedFee.amount | ||
|
|
||
| if custom_fee_params.fixedFee.denominatingTokenId: | ||
| custom_fee.set_denominating_token_id(TokenId.from_string(custom_fee_params.fixedFee.denominatingTokenId)) | ||
|
|
||
| return custom_fee | ||
|
|
||
|
|
||
| def _build_create_topic_transaction(params: CreateTopicParams) -> TopicCreateTransaction: | ||
| transaction = TopicCreateTransaction().set_grpc_deadline(DEFAULT_GRPC_TIMEOUT) | ||
|
|
||
| if params.memo is not None: | ||
| transaction.set_memo(params.memo) | ||
|
|
||
| if params.adminKey is not None: | ||
| transaction.set_admin_key(get_key_from_string(params.adminKey)) | ||
|
|
||
| if params.submitKey is not None: | ||
| transaction.set_submit_key(get_key_from_string(params.submitKey)) | ||
|
|
||
| if params.autoRenewPeriod is not None: | ||
| transaction.set_auto_renew_period(params.autoRenewPeriod) | ||
|
|
||
| if params.autoRenewAccountId is not None: | ||
| transaction.set_auto_renew_account(AccountId.from_string(params.autoRenewAccountId)) | ||
|
|
||
| if params.feeScheduleKey is not None: | ||
| transaction.set_fee_schedule_key(get_key_from_string(params.feeScheduleKey)) | ||
|
|
||
| if params.feeExemptKeys is not None: | ||
| transaction.set_fee_exempt_keys([get_key_from_string(key) for key in params.feeExemptKeys]) | ||
|
|
||
| if params.customFees is not None: | ||
| transaction.set_custom_fees([_build_custom_fee(custom_fee_params) for custom_fee_params in params.customFees]) | ||
|
|
||
| return transaction | ||
|
MonaaEid marked this conversation as resolved.
|
||
|
|
||
|
|
||
| @rpc_method("createTopic") | ||
| def create_topic(params: CreateTopicParams) -> CreateTopicResponse: | ||
| client = get_client(params.sessionId) | ||
|
|
||
| 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) | ||
|
MonaaEid marked this conversation as resolved.
|
||
|
|
||
| response = transaction.execute(client, wait_for_receipt=False) | ||
| receipt: TransactionReceipt = response.get_receipt(client, validate_status=True) | ||
|
|
||
| topic_id = "" | ||
| if receipt.status == ResponseCode.SUCCESS and receipt.topic_id is not None: | ||
| topic_id = str(receipt.topic_id) | ||
|
|
||
| return CreateTopicResponse(topic_id, ResponseCode(receipt.status).name) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,93 @@ | ||
| from __future__ import annotations | ||
|
|
||
| from dataclasses import dataclass | ||
|
|
||
| from tck.param.base import BaseTransactionParams | ||
| from tck.util.param_utils import ( | ||
| non_empty_string_list, | ||
| non_empty_string_or_none, | ||
| parse_common_transaction_params, | ||
| parse_session_id, | ||
| to_bool, | ||
| to_int, | ||
| ) | ||
|
|
||
|
|
||
| @dataclass | ||
| class CreateTopicFixedFeeParams: | ||
| """Parameters for a fixed fee custom fee in topic creation.""" | ||
|
|
||
| amount: int | None = None | ||
| denominatingTokenId: str | None = None | ||
|
|
||
| @classmethod | ||
| def parse_json_params(cls, params: dict) -> CreateTopicFixedFeeParams: | ||
| return cls( | ||
| amount=to_int(params.get("amount")), | ||
| denominatingTokenId=non_empty_string_or_none(params.get("denominatingTokenId")), | ||
| ) | ||
|
MonaaEid marked this conversation as resolved.
|
||
|
|
||
|
|
||
| @dataclass | ||
| class CreateTopicCustomFeeParams: | ||
| """Parameters for a custom fee in topic creation.""" | ||
|
|
||
| feeCollectorAccountId: str | None = None | ||
| feeCollectorsExempt: bool | None = None | ||
| fixedFee: CreateTopicFixedFeeParams | None = None | ||
|
|
||
| @classmethod | ||
| def parse_json_params(cls, params: dict) -> CreateTopicCustomFeeParams: | ||
| fixed_fee = params.get("fixedFee") | ||
|
|
||
| fee_collector_account_id = params.get("feeCollectorAccountId") | ||
| if isinstance(fee_collector_account_id, str): | ||
| fee_collector_account_id = fee_collector_account_id.strip() | ||
|
|
||
| return cls( | ||
| feeCollectorAccountId=fee_collector_account_id, | ||
| feeCollectorsExempt=to_bool(params.get("feeCollectorsExempt")), | ||
| fixedFee=(CreateTopicFixedFeeParams.parse_json_params(fixed_fee) if isinstance(fixed_fee, dict) else None), | ||
| ) | ||
|
|
||
|
|
||
| @dataclass | ||
| class CreateTopicParams(BaseTransactionParams): | ||
| """Parameters for creating a topic. Extends BaseTransactionParams to include common transaction parameters.""" | ||
|
|
||
| memo: str | None = None | ||
| adminKey: str | None = None | ||
| submitKey: str | None = None | ||
| autoRenewPeriod: int | None = None | ||
| autoRenewAccountId: str | None = None | ||
| feeScheduleKey: str | None = None | ||
| feeExemptKeys: list[str] | None = None | ||
| customFees: list[CreateTopicCustomFeeParams] | None = None | ||
|
|
||
| @classmethod | ||
| def parse_json_params(cls, params: dict) -> CreateTopicParams: | ||
| fee_exempt_keys = params.get("feeExemptKeys") | ||
| if fee_exempt_keys is not None and not isinstance(fee_exempt_keys, list): | ||
| raise ValueError("feeExemptKeys must be a list") | ||
|
|
||
| custom_fees = params.get("customFees") | ||
| if custom_fees is not None and not isinstance(custom_fees, list): | ||
| raise ValueError("customFees must be a list") | ||
| if custom_fees is not None and any(not isinstance(custom_fee, dict) for custom_fee in custom_fees): | ||
| raise ValueError("each customFees item must be an object") | ||
| return cls( | ||
| memo=params.get("memo"), | ||
| adminKey=non_empty_string_or_none(params.get("adminKey")), | ||
| submitKey=non_empty_string_or_none(params.get("submitKey")), | ||
| autoRenewPeriod=to_int(params.get("autoRenewPeriod")), | ||
| autoRenewAccountId=non_empty_string_or_none(params.get("autoRenewAccountId")), | ||
| feeScheduleKey=non_empty_string_or_none(params.get("feeScheduleKey")), | ||
| feeExemptKeys=non_empty_string_list(fee_exempt_keys), | ||
| customFees=( | ||
| [CreateTopicCustomFeeParams.parse_json_params(custom_fee) for custom_fee in custom_fees] | ||
| if custom_fees is not None | ||
| else None | ||
| ), | ||
| sessionId=parse_session_id(params), | ||
| commonTransactionParams=parse_common_transaction_params(params), | ||
| ) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| from __future__ import annotations | ||
|
|
||
| from dataclasses import dataclass | ||
|
|
||
|
|
||
| @dataclass | ||
| class CreateTopicResponse: | ||
| topicId: str | None = None | ||
| status: str | None = None |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.