feat: implemented wipeToken TCK endpt.#2414
Conversation
Signed-off-by: Adityarya11 <arya050411@gmail.com>
There was a problem hiding this comment.
Pull request overview
This PR adds TCK support for the wipeToken JSON-RPC endpoint, aligning the Python SDK’s TCK module with the TokenWipeTransaction specification.
Changes:
- Added
WipeTokenParamsrequest model and JSON param parsing for the new endpoint. - Added
WipeTokenResponseresponse model. - Implemented the
wipeTokenRPC handler and transaction builder usingTokenWipeTransaction.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| tck/response/token.py | Adds a status-only response dataclass for wipeToken. |
| tck/param/token.py | Adds request params dataclass + JSON parsing for wipeToken. |
| tck/handlers/token.py | Adds wipeToken RPC method and constructs/executes TokenWipeTransaction. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| from __future__ import annotations | ||
|
|
||
| from hiero_sdk_python import TokenWipeTransaction |
| serialNumberList = [int(serial_number) for serial_number in params.serialNumbers] | ||
|
|
||
| transaction.set_serial(serialNumberList) |
| reciept: TransactionReceipt = response.get_receipt(client, validate_status=True) | ||
|
|
||
| return WipeTokenResponse(status=ResponseCode(reciept.status).name) |
| @rpc_method("wipeToken") | ||
| def wipe_token(params: WipeTokenParams) -> WipeTokenResponse: | ||
| """Wipes the provided amount of fungible or non-fungible tokens from the specified Hedera account""" | ||
|
|
||
| client = get_client(params.sessionId) | ||
|
|
||
| transaction = _build_wipe_token_transaction(params) | ||
|
|
||
| if params.commonTransactionParams is not None: | ||
| params.commonTransactionParams.apply_common_params(transaction, client) | ||
|
|
||
| response = transaction.execute(client, wait_for_receipt=False) | ||
| reciept: TransactionReceipt = response.get_receipt(client, validate_status=True) | ||
|
|
||
| return WipeTokenResponse(status=ResponseCode(reciept.status).name) |
WalkthroughAdds the ChangeswipeToken endpoint
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant JSONRPCClient
participant wipe_token
participant TokenWipeTransaction
participant TransactionReceipt
JSONRPCClient->>wipe_token: WipeTokenParams
wipe_token->>TokenWipeTransaction: build transaction
wipe_token->>TokenWipeTransaction: execute
wipe_token->>TransactionReceipt: get_receipt(validate_status=True)
TransactionReceipt-->>wipe_token: receipt.status
wipe_token-->>JSONRPCClient: WipeTokenResponse
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
📋 Issue PlannerBuilt with CodeRabbit's Coding Plans for faster development and fewer bugs. View plan used: ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 3201578c-9494-407f-b06a-7558c2cbc0b2
📒 Files selected for processing (3)
tck/handlers/token.pytck/param/token.pytck/response/token.py
| if params.amount is not None: | ||
| transaction.set_amount(to_int(params.amount)) |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
to_int can return None, causing set_amount(None) to be called silently.
to_int catches ValueError/TypeError and returns None. If a user provides amount: "abc", to_int returns None and set_amount(None) is called instead of raising a validation error. This is a silent failure — the user intended to wipe tokens but the amount is silently discarded. Validate the conversion result before passing it to set_amount.
🐛 Proposed fix
if params.amount is not None:
- transaction.set_amount(to_int(params.amount))
+ amount = to_int(params.amount)
+ if amount is None:
+ raise ValueError("amount must be a valid integer")
+ transaction.set_amount(amount)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if params.amount is not None: | |
| transaction.set_amount(to_int(params.amount)) | |
| if params.amount is not None: | |
| amount = to_int(params.amount) | |
| if amount is None: | |
| raise ValueError("amount must be a valid integer") | |
| transaction.set_amount(amount) |
| if params.serialNumbers is not None: | ||
| serialNumberList = [int(serial_number) for serial_number in params.serialNumbers] | ||
|
|
||
| transaction.set_serial(serialNumberList) |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
int(serial_number) raises raw ValueError for non-numeric strings.
parse_json_params validates that serial number items are strings but not that they are valid integer strings. If a user provides serialNumbers: ["abc"], the int() call at line 501 raises a raw ValueError with an unhelpful message like invalid literal for int() with base 10: 'abc'. While handle_sdk_errors wraps this, a clearer validation error would improve the TCK user experience. Consider validating during parsing or providing a clearer error message here.
| reciept: TransactionReceipt = response.get_receipt(client, validate_status=True) | ||
|
|
||
| return WipeTokenResponse(status=ResponseCode(reciept.status).name) |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value
Fix typo: reciept → receipt.
The local variable reciept is misspelled. It should be receipt for readability and consistency.
✏️ Proposed fix
- reciept: TransactionReceipt = response.get_receipt(client, validate_status=True)
+ receipt: TransactionReceipt = response.get_receipt(client, validate_status=True)
- return WipeTokenResponse(status=ResponseCode(reciept.status).name)
+ return WipeTokenResponse(status=ResponseCode(receipt.status).name)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| reciept: TransactionReceipt = response.get_receipt(client, validate_status=True) | |
| return WipeTokenResponse(status=ResponseCode(reciept.status).name) | |
| receipt: TransactionReceipt = response.get_receipt(client, validate_status=True) | |
| return WipeTokenResponse(status=ResponseCode(receipt.status).name) |
| return cls( | ||
| tokenId=params.get("tokenId"), | ||
| accountId=params.get("accountId"), | ||
| amount=params.get("amount"), | ||
| serialNumbers=serial_numbers, |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Add type validation for tokenId, accountId, and amount.
parse_json_params validates serialNumbers but does not validate that tokenId, accountId, or amount are strings. The allowance endpoint (tck/param/allowance.py:128) validates tokenId with isinstance(token_id, str). Without this validation, non-string values pass through silently and only fail later in the handler with less clear errors from TokenId.from_string() or to_int().
🛡️ Proposed fix
return cls(
- tokenId=params.get("tokenId"),
- accountId=params.get("accountId"),
- amount=params.get("amount"),
+ tokenId=_parse_str_param(params, "tokenId"),
+ accountId=_parse_str_param(params, "accountId"),
+ amount=_parse_str_param(params, "amount"),
serialNumbers=serial_numbers,
sessionId=parse_session_id(params),
commonTransactionParams=parse_common_transaction_params(params),
)Or inline validation:
+ token_id = params.get("tokenId")
+ if token_id is not None and not isinstance(token_id, str):
+ raise ValueError("tokenId must be a string")
+ account_id = params.get("accountId")
+ if account_id is not None and not isinstance(account_id, str):
+ raise ValueError("accountId must be a string")
+ amount = params.get("amount")
+ if amount is not None and not isinstance(amount, str):
+ raise ValueError("amount must be a string")
+
return cls(
- tokenId=params.get("tokenId"),
- accountId=params.get("accountId"),
- amount=params.get("amount"),
+ tokenId=token_id,
+ accountId=account_id,
+ amount=amount,
serialNumbers=serial_numbers,
sessionId=parse_session_id(params),
commonTransactionParams=parse_common_transaction_params(params),
)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| return cls( | |
| tokenId=params.get("tokenId"), | |
| accountId=params.get("accountId"), | |
| amount=params.get("amount"), | |
| serialNumbers=serial_numbers, | |
| token_id = params.get("tokenId") | |
| if token_id is not None and not isinstance(token_id, str): | |
| raise ValueError("tokenId must be a string") | |
| account_id = params.get("accountId") | |
| if account_id is not None and not isinstance(account_id, str): | |
| raise ValueError("accountId must be a string") | |
| amount = params.get("amount") | |
| if amount is not None and not isinstance(amount, str): | |
| raise ValueError("amount must be a string") | |
| return cls( | |
| tokenId=token_id, | |
| accountId=account_id, | |
| amount=amount, | |
| serialNumbers=serial_numbers, |
|
Hi @Adityarya11, Please update the branch and resolve the conflicts |
Description:
This PR introduce the
wipeTokenmethod to tck module.Changes Made:
Related issue(s):
Fixes #2398
Notes for reviewer:
Checklist