feat: Swap token carry and stock-tag search fix (OK-55190, OK-60609) - #12932
feat: Swap token carry and stock-tag search fix (OK-55190, OK-60609)#12932zhaono1 wants to merge 12 commits into
Conversation
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
@codex review |
|
@codex security review |
|
You have reached your Codex usage limits for security reviews. Please try again later. |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
@cursoragent review |
PR #12932 代码审查报告审查概要
评分
PR 评论分析
评论误报分析
发现的问题[🔴 高] [🔵 High] Swap marker 在所有 tab 的选币路径上都会被置位 {Cross-validated ✅}文件: 复现:Swap → Stock 改支付币 → 回 Swap(STOCK 提前 return,不消费,并 restore Auto-fix: - set(swapUserSelectedTokensAtom(), true);
+ if (
+ swapTypeSwitchValue === ESwapTabSwitchType.SWAP ||
+ swapTypeSwitchValue === ESwapTabSwitchType.BRIDGE
+ ) {
+ set(swapUserSelectedTokensAtom(), true);
+ }
[🔴 高] [🔵 High] Pro marker 只在 LIMIT→SWAP 被消费,其它离开 Pro 的路径会残留 {Cross-validated ✅}文件: 旁路:
复现:Pro 手选 token → action button 跳 Swap(并写入金额)→ 之后任意一次 Pro→Swap,陈旧 marker 让 修复建议: 在 [🔴 高] [🔵 High] Limit→Swap carry 用 Pro 网络当 Swap 上下文 {Cross-validated ✅}文件:
结果:跨链判断和 native-default guard 按错误网络比较;该切账户网络时不切。同一份 Auto-fix: - const swapContextNetworkId = fromToken?.networkId ?? accountNetworkId;
+ const swapContextNetworkId = accountNetworkId ?? fromToken?.networkId;调用侧改传 [🟡 中] [🔵 High] tab 切换被 stable-coin 请求阻塞最长 2s {Cross-validated ✅}文件:
Auto-fix: - await carrySwapTokenToPro();
- }
- void swapTypeSwitchAction(newType, networkId);
+ void carrySwapTokenToPro();
+ }
+ void swapTypeSwitchAction(newType, networkId); const list = Array.from(
candidates
.reduce((map, token) => {
...
map.set(token.networkId, addresses);
return map;
}, new Map<string, string[]>())
.entries(),
- ).map(([networkId, contractAddressList]) => ({
- networkId,
- contractAddressList,
- }));
+ )
+ .filter(([, contractAddressList]) => contractAddressList.length > 0)
+ .map(([networkId, contractAddressList]) => ({
+ networkId,
+ contractAddressList,
+ }));
+ if (list.length === 0) return new Set<string>();修改清单
测试建议
GH 评论操作以下问题已在本回合直接发为 inline / reply:
OK-60609 一侧(服务端关键字结果作为匹配权威、fuse 只做高亮、balance merge 保留 |
originalix
left a comment
There was a problem hiding this comment.
Automated code review found blocking issues
Reviewed commit ca96d0bcdb7b.
- P1 · Tab switching clears pending carry markers during network cold start
originalix
left a comment
There was a problem hiding this comment.
Automated code review found blocking issues
Reviewed commit 9f6a7d4c543c.
- P1 · Tab switching clears pending carry markers during network cold start
originalix
left a comment
There was a problem hiding this comment.
Automated code review found blocking issues
Reviewed commit fdd3a88686e5.
- P2 · Market entry reuses a stale Pro carry marker
| if ( | ||
| !isAllNetworkSelected && | ||
| proCarry?.targetNetworkId && | ||
| proCarry.targetNetworkId !== selectedAccountNetworkId | ||
| ) { | ||
| await updateSelectedAccountNetworkAction(proCarry.targetNetworkId); | ||
| } else if ( | ||
| !isAllNetworkSelected && |
There was a problem hiding this comment.
🟠 P1 新增的「跳过冗余切换」让主路径掉进 else if,把账户网络切到被丢弃的旧链
问题
本次新增的 proCarry.targetNetworkId !== selectedAccountNetworkId 与 resolveSwapContextNetworkId 里新写的注释("Pro keeps the account selector aligned with its own target network while active")互相矛盾。useSwapProAccount(useSwapPro.ts:342-366)在 Pro 活跃时会把账户网络同步成 swapProSelectToken.networkId;而 claimProTokenCarry(actions.ts:805)要求 swapProUserSelectedToken === swapProSelectToken === sourceProToken 才返回 true,所以能成功 carry 的 proCarry.targetNetworkId 恒等于 selectedAccountNetworkId。新条件因此在真实 native Pro 退出路径上恒为 false,第一分支变成死代码。
问题在于这是 if / else if 链:第一分支被跳过后立刻进入第二分支 fromToken.networkId !== selectedAccountNetworkId,而此时 fromToken 正是要被丢弃的普通 Swap 旧链 token(swapTypeSwitchAction 在 native 进 LIMIT 时于 actions.ts:3577 提前 return,from/to atom 原样保留)。于是本该「保持在目标网络」的场景,反而 await updateSelectedAccountNetworkAction(fromToken.networkId) 切到了旧链。
影响
跨链 carry 主场景(账户已同步到 sol--101,普通 Swap FromToken 在 evm--1,Pro 标的 sol--101):账户网络被切到 evm--1 → swapTypeSwitchAction(SWAP, 'sol--101') 恢复 lastNonLimit 的 evm--1 组合 → apply() 再写成 from = SOL native / to = JUP。最终 token 对是对的,但账户选择器停在 evm--1,与交易对不一致。
更糟的是这次切换发生在 swapTypeSwitchAtom 仍为 LIMIT 时,useSwapProAccount 的同步 effect 会检测到 currentNetworkId('evm--1') !== targetNetworkId('sol--101') 而反向切回,形成 ping-pong;最终落在哪个网络取决于 Pro 组件卸载与该 effect 的先后,是不确定的。此外这个多余的 await 还拉长了 proCarry.claim() 之前的窗口,正是代码注释里担心的「account-network update in flight」竞态。
本轮新增的单测只断言 hook 侧 plan.targetNetworkId === 'sol--101',而 SwapHeaderContainer 没有任何测试,恰好把「hook 产出正确、消费端丢弃」这条缝隙漏掉了。
建议
不要用 else if 承接被跳过的第一分支,先算出唯一的目标网络再统一去重:
const nextAccountNetworkId =
proCarry?.targetNetworkId ?? fromToken?.networkId;
if (
!isAllNetworkSelected &&
nextAccountNetworkId &&
nextAccountNetworkId !== selectedAccountNetworkId
) {
await updateSelectedAccountNetworkAction(nextAccountNetworkId);
}顺带:swapContextNetworkId 改成 FromToken-first 之后,第 346 行的 fromToken?.networkId || swapContextNetworkId || networkId 里 swapContextNetworkId 已经只可能在 fromToken 缺失时生效并等于 selectedAccountNetworkId,这段回退链可以一并收敛。建议补一个覆盖 handleSwapTypeChange 分支的用例,否则消费端的回归还会重复出现。
Generated by Claude Code
Automated code review found blocking issuesReviewed commit Review summaryThe native Swap state boundary now records one-shot manual token selections so Swap and Swap Pro can transfer compatible tokens across tab changes, including cross-network native-token setup and amount resets. The change also makes server keyword results authoritative while preserving alias arrays and attaching local Fuse metadata only for highlighting. The carry flow stays within the existing kit/shared boundaries and does not touch signing or secret-handling paths, but stable-token classification must preserve address casing on case-sensitive networks before this behavior is safe to merge. What needs attention: Verify that stable-token classification uses network-aware address normalization, especially for Solana, Tron, Aptos, Sui, and other case-sensitive networks. Issues to address
Validation gaps
|
|
Superseded by #12961. |
Pull request was closed


OK-55190 OK-60609
Summary
subtitles: string[]contract while retaining the legacy string shape during rollout.Intent & Context
subtitleswhile decorating all-network results with balances.Design Decisions
OK-55190
usePromiseResult. Timeout or request failure falls back to non-stable for that result only; no foreground module cache persists a failure asfalse. Focus and reconnect revalidation remain enabled.OK-60609
subtitlesaliases.Risk Assessment
Test plan
usePromiseResultfocus/reconnect/key lifecycle suite: 32 tests passedyarn agent:check --profile commitgit diff --checkIssues