diff --git a/tck/handlers/token.py b/tck/handlers/token.py index ce1f0bb2a..322ae5ea4 100644 --- a/tck/handlers/token.py +++ b/tck/handlers/token.py @@ -21,6 +21,7 @@ from hiero_sdk_python.tokens.token_associate_transaction import TokenAssociateTransaction from hiero_sdk_python.tokens.token_create_transaction import TokenCreateTransaction from hiero_sdk_python.tokens.token_delete_transaction import TokenDeleteTransaction +from hiero_sdk_python.tokens.token_dissociate_transaction import TokenDissociateTransaction from hiero_sdk_python.tokens.token_freeze_status import TokenFreezeStatus from hiero_sdk_python.tokens.token_freeze_transaction import TokenFreezeTransaction from hiero_sdk_python.tokens.token_grant_kyc_transaction import TokenGrantKycTransaction @@ -41,6 +42,7 @@ ClaimTokenParams, CreateTokenParams, DeleteTokenParams, + DissociateTokenParams, FreezeTokenParams, GetTokenInfoParams, GrantTokenKycParams, @@ -55,6 +57,7 @@ CreateTokenResponse, CustomFeeResponse, DeleteTokenResponse, + DissociateTokenResponse, FreezeTokenResponse, GetTokenInfoResponse, GrantTokenKycResponse, @@ -289,6 +292,20 @@ def _build_associate_token_transaction(params: AssociateTokenParams) -> TokenAss return transaction +def _build_dissociate_token_transaction(params: DissociateTokenParams) -> TokenDissociateTransaction: + """Build a TokenDissociateTransaction from TCK params.""" + transaction = TokenDissociateTransaction().set_grpc_deadline(DEFAULT_GRPC_TIMEOUT) + + if params.accountId is not None: + transaction.set_account_id(AccountId.from_string(params.accountId)) + + if params.tokenIds is not None: + token_ids = [TokenId.from_string(tid) for tid in params.tokenIds] + transaction.set_token_ids(token_ids) + + return transaction + + def _build_delete_token_transaction(params: DeleteTokenParams) -> TokenDeleteTransaction: """Build a TokenDeleteTransaction from TCK params.""" transaction = TokenDeleteTransaction().set_grpc_deadline(DEFAULT_GRPC_TIMEOUT) @@ -374,6 +391,22 @@ def delete_token(params: DeleteTokenParams) -> DeleteTokenResponse: return DeleteTokenResponse(status=ResponseCode(receipt.status).name) +@rpc_method("dissociateToken") +def dissociate_token(params: DissociateTokenParams) -> DissociateTokenResponse: + """Dissociate tokens from an account using TCK dissociateToken parameters.""" + client = get_client(params.sessionId) + + transaction = _build_dissociate_token_transaction(params) + + if params.commonTransactionParams is not None: + params.commonTransactionParams.apply_common_params(transaction, client) + + response = transaction.execute(client, wait_for_receipt=False) + receipt: TransactionReceipt = response.get_receipt(client, validate_status=True) + + return DissociateTokenResponse(status=ResponseCode(receipt.status).name) + + @rpc_method("freezeToken") def freeze_token(params: FreezeTokenParams) -> FreezeTokenResponse: """Freeze a token for an account using TCK freezeToken parameters.""" diff --git a/tck/param/token.py b/tck/param/token.py index d5294edf0..ad5cdee88 100644 --- a/tck/param/token.py +++ b/tck/param/token.py @@ -166,6 +166,30 @@ def parse_json_params(cls, params: dict) -> FreezeTokenParams: ) +@dataclass +class DissociateTokenParams(BaseTransactionParams): + """Request parameters for the dissociateToken endpoint.""" + + accountId: str | None = None + tokenIds: list[str] | None = None + + @classmethod + def parse_json_params(cls, params: dict) -> DissociateTokenParams: + """Parse JSON-RPC params into a DissociateTokenParams instance.""" + token_ids = params.get("tokenIds") + if token_ids is not None and not isinstance(token_ids, list): + raise ValueError("tokenIds must be a list") + if token_ids is not None and any(not isinstance(token_id, str) for token_id in token_ids): + raise ValueError("each tokenIds item must be a string") + + return cls( + accountId=params.get("accountId"), + tokenIds=token_ids, + sessionId=parse_session_id(params), + commonTransactionParams=parse_common_transaction_params(params), + ) + + @dataclass class GrantTokenKycParams(BaseTransactionParams): """Request parameters for the grantTokenKyc endpoint.""" diff --git a/tck/response/token.py b/tck/response/token.py index 25a845fa6..ba08efbbc 100644 --- a/tck/response/token.py +++ b/tck/response/token.py @@ -34,6 +34,11 @@ class DeleteTokenResponse(StatusOnlyResponse): """Response payload for deleteToken.""" +@dataclass +class DissociateTokenResponse(StatusOnlyResponse): + """Response payload for dissociateToken.""" + + @dataclass class FreezeTokenResponse(StatusOnlyResponse): """Response payload for freezeToken."""