feat: add token-id related queries for stellar its#1346
Conversation
There was a problem hiding this comment.
Pull request overview
Adds new Stellar ITS CLI queries to retrieve different token-id derivations, making it easier to inspect/derive token IDs from on-chain data.
Changes:
- Add contract query handlers for
canonical_interchain_token_id,interchain_token_id, andlinked_token_id. - Wire the new handlers into the
stellar/its.jsCommander CLI ascanonical-interchain-token-id,interchain-token-id, andlinked-token-id.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const operation = contract.call('interchain_token_id', addressToScVal(deployer), hexToScVal(saltBytes32)); | ||
| const returnValue = await broadcast(operation, wallet, chain, 'Get interchain token id', options); | ||
| const tokenId = serializeValue(returnValue.value()); | ||
|
|
||
| printInfo('Interchain Token ID', tokenId); | ||
|
|
There was a problem hiding this comment.
serializeValue produces a non-0x-prefixed hex string for the token id. Since other commands consume token ids via hexToScVal (which relies on ethers.utils.arrayify), the printed/returned value here may not be directly reusable. Consider prefixing with 0x (or standardizing token id formatting in one place).
| const operation = contract.call('linked_token_id', addressToScVal(deployer), hexToScVal(saltBytes32)); | ||
| const returnValue = await broadcast(operation, wallet, chain, 'Get linked token id', options); | ||
| const tokenId = serializeValue(returnValue.value()); | ||
|
|
||
| printInfo('Linked Token ID', tokenId); | ||
|
|
There was a problem hiding this comment.
Same formatting concern as above: the linked token id is serialized as bare hex without 0x, which may not be directly accepted by other commands expecting a hex string parsable by ethers.utils.arrayify. Consider printing/returning 0x-prefixed hex for easier copy/paste.
| const [deployer, salt] = args; | ||
| const saltBytes32 = saltToBytes32(salt); | ||
|
|
||
| validateParameters({ | ||
| isValidStellarAddress: { deployer }, | ||
| isNonEmptyString: { salt }, | ||
| }); |
There was a problem hiding this comment.
saltToBytes32(salt) is computed before validating salt. If salt is empty or not a valid hex string/bytes-like input, saltToBytes32 can throw (via keccak256) with a less actionable error. Validate salt (and ideally its expected format) before converting it, then derive saltBytes32.
| const [deployer, salt] = args; | ||
| const saltBytes32 = saltToBytes32(salt); | ||
|
|
||
| validateParameters({ | ||
| isValidStellarAddress: { deployer }, | ||
| isNonEmptyString: { salt }, | ||
| }); |
There was a problem hiding this comment.
Same issue as interchainTokenId: saltToBytes32(salt) runs before salt is validated, so invalid/empty salts can throw from inside saltToBytes32 instead of producing a clean parameter validation error. Move validation ahead of the conversion.
| const operation = contract.call('canonical_interchain_token_id', nativeToScVal(tokenAddress, { type: 'address' })); | ||
| const returnValue = await broadcast(operation, wallet, chain, 'Get canonical interchain token id', options); | ||
| const tokenId = serializeValue(returnValue.value()); | ||
|
|
||
| printInfo('Canonical Interchain Token ID', tokenId); | ||
|
|
There was a problem hiding this comment.
serializeValue returns raw hex for Uint8Array without a 0x prefix, but downstream helpers like hexToScVal use ethers.utils.arrayify, which expects 0x-prefixed hex. Consider returning/printing the token id in 0x... form here so the output can be copy-pasted into other commands that accept <tokenId> without manual editing.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 7707838. Configure here.
| .command('canonical-interchain-token-id <tokenAddress>') | ||
| .description('Get the canonical interchain token id for a token address') | ||
| .action((tokenAddress, options) => { | ||
| mainProcessor(canonicalInterchainTokenId, [tokenAddress], options); |
There was a problem hiding this comment.
Queries exit before completion
High Severity
The new command actions start mainProcessor without returning its promise. Since program.parseAsync() exits after the action returns, these queries can terminate before canonicalInterchainTokenId, interchainTokenId, or linkedTokenId finishes, producing no result and hiding failures.
Additional Locations (2)
Reviewed by Cursor Bugbot for commit 7707838. Configure here.


why
For easier inspection.
how
Note
Low Risk
Low risk: adds read-only CLI queries that call existing contract methods and print results, without changing stateful operations or core transaction flow.
Overview
Adds three new read-only commands to
stellar/its.jsfor easier token inspection:canonical-interchain-token-id,interchain-token-id, andlinked-token-id.Each command validates inputs, computes/prints the derived salt bytes where relevant, calls the corresponding ITS contract method, and prints/returns the serialized token ID.
Reviewed by Cursor Bugbot for commit 7707838. Bugbot is set up for automated code reviews on this repo. Configure here.