fix(sdk-core): keep intent tokenName for token-wallet TSS signing - #9884
Draft
ralph-bitgo[bot] wants to merge 2 commits into
Draft
ralph-bitgo[bot] wants to merge 2 commits into
ralph-bitgo[bot] wants to merge 2 commits into
Conversation
Contributor
Contributor
|
|
What changed: - resolveEffectiveTxParams no longer drops amount.symbol as tokenName when it equals chainName: a statics-registered chainName that is itself a token (sol:usdt, sol:usdc, ...) proves the wallet is a token wallet, so the intent symbol always identifies a token transfer. Native wallets keep the strict symbol !== chainName behavior, and chain names absent from statics (dynamic/AMS tokens) are left unchanged to avoid guessing. Why: Signing a SOL:USDT/SOL:USDC withdrawal or consolidation from a token wallet in the UI failed with 'Tx outputs does not match with expected txParams recipients', leaving every request stuck pendingDelivery and blocking the customer (WCI-1723). populateIntent stores amount.symbol = baseCoin.getChain() because sendMany on a token wallet carries no tokenName, so at signing time the symbol matched chainName, the tokenName fallback was skipped, and verifyTransaction could not derive the recipient's associated token account to compare outputs. Ticket: WCI-1723 Session-Id: b7c7cfa9-c342-4d89-a7e4-8dae52576077 Task-Id: 43b26db5-5b57-41d7-94f3-5a3ffb828801
ralph-bitgo
Bot
force-pushed
the
WCI-1723-sol-tss-recipient-verify
branch
from
October 3, 2026 12:04
2ae815e to
f5eb879
Compare
What changed: - isTokenChainName doc and the unregistered-name test comment no longer claim dynamic/AMS tokens resolve to false: GlobalCoinFactory.registerToken inserts runtime tokens into the same statics coin map that isTokenChainName queries, so registered AMS tokens are detected as tokens; only names registered nowhere stay false. Also aligned the resolveTssVerifyTransactionOptions chainName doc with the token-wallet reality (chain name is the token name itself for token wallets). Why: The comments shipped with the WCI-1723 fix described the registry incorrectly and could mislead a future maintainer into thinking AMS token wallets are unsupported by the fix when they are in fact covered. Ticket: WCI-1723 Session-Id: b7c7cfa9-c342-4d89-a7e4-8dae52576077 Task-Id: 43b26db5-5b57-41d7-94f3-5a3ffb828801
This branch has not been deployed
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Description
SOL:USDT / SOL:USDC withdrawals and SOL consolidations from the affected SOL TSS
hot wallet failed UI signing with
Tx outputs does not match with expected txParams recipients, leaving every txRequest stuck inpendingDelivery,unsigned, with no txid (customer blocked; Case376984).
Root cause (token withdrawals). On a token wallet,
baseCoin.getChain()returns the token name itself (e.g.
sol:usdt).populateIntentthereforepersists
amount.symbol = 'sol:usdt'(sendMany on a token wallet carries norecipient
tokenName), but at signing timeresolveEffectiveTxParamstreated asymbol equal to
chainNameas a native transfer and dropped thetokenNamefallback.
Sol.verifyTransactionthen had no mint to derive the recipient'sassociated token account from, and rejected the transaction.
Fix.
resolveEffectiveTxParams(
modules/sdk-core/src/bitgo/utils/tss/recipientUtils.ts) now keepsamount.symbolastokenNamewhenchainNameis itself a statics-registeredtoken — i.e. the wallet is a token wallet. Native wallets keep the strict
symbol !== chainNamerule; names registered nowhere (neither statics nor theruntime/AMS registry that GlobalCoinFactory feeds into it) are left unchanged
rather than guessed, so the fail-closed posture is preserved.
Consolidations were already fixed on master by WCN-2952 (sweep-to-base-address
verification); this PR closes the remaining token-withdrawal path.
Pending requests. The six listed txRequests carry valid intents and unsigned
transactions, and verification runs at signing time in the SDK — so once the UI
runs a SDK build containing this fix (plus WCN-2952 for the consolidations), they
can be signed as-is and do not need to be rejected and recreated.
Issue Number
Ticket: WCI-1723
Type of change
How Has This Been Tested?
modules/sdk-core/test/unit/bitgo/utils/tss/recipientUtils.ts: token wallet(
sol:usdt/tsol:usdcwithchainName = symbol) keepstokenName;native transfer (
symbol === chainName === 'tsol') still drops it; chainname not in statics still drops it; all RED against the pre-fix code, GREEN
after.
modules/sdk-coin-sol/test/unit/sol.ts: a mainnetsol:usdtwithdrawal resolved throughresolveTssVerifyTransactionOptionswith a production-shaped intent (symbol = token chain, no
tokenData) passesverifyTransaction; a tampered intent recipient is still rejected with theexact production error.
sdk-coin-sol790 passing;sdk-core890 passing;bitgotssUtilssubsets match the master baseline (11 pre-existing failures: missing native
sodium functions and pre-existing assertions, identical on master).
sdk-coin-solandsdk-coreclean builds (tsc) green; eslint clean;commitlint passes.
Checklist:
Ticket: WCI-1723