chore: sync release/v6.5.0 fixes after bundle #7 into hotfix/v6.5.2 - #12935
Conversation
(cherry picked from commit 12a7b65)
(cherry picked from commit 7e00c69)
(cherry picked from commit 6c7cf53)
…0543) (#12918) * fix: keep the perps deeplink target over the cold-start restore A banner or push deeplink writes the coin from a context-less handler, so the switch event it emits lands before the Perp page mounts and is dropped. The page then restores activeTradeInstrumentAtom, whose cold-start cache still holds the previous session's coin, and passes it as preferredInstrument — which outranks the background atoms unconditionally and forces the market back. The first tap after a cold start therefore never switched. The deeplink now records a short-lived intent in ServiceHyperliquid, which the initial symbol select consumes ahead of the restore. The restore keeps winning when no intent is pending, so the pair flip it was added to prevent stays fixed. * perf: collapse the perps initial symbol select into one background hop The claim, deeplink intent, instrument target and trading universe were four sequential proxy calls sitting between the first Perp frame and the symbol it should show. Each is nearly free when the background is idle and around 220ms when it is not, which is the cold start the user actually waits on: one device trace spent 470ms of a 1.3s wait in the last three. They now resolve in a single background method, in the same order. The universe read stays behind the claim flag, so a non-claiming run does no more work than before, and initial_symbol_prepare records the combined hop so the remaining wait can be attributed. * chore: derive the perps deeplink intent type from its actual source * fix: apply the perps deeplink intent only on the claiming run Review catch. The intent was consumed on every initial-select run but also applied on every one, so a notification handled by the already-mounted page stayed live on the background singleton for its whole TTL. Any later blur to focus then forced that coin back over a market the user had picked since — overriding a current, explicit choice on a leveraged screen. A mounted page already switches through the event bus, and the non-claiming run resyncs from the background atoms when the UI and background diverge, so it never needed the intent. Consumption stays unconditional so nothing lingers; only the one claiming run per process acts on it. * fix: survive unlock and cover the perps deeplink intent gate Three review findings on the intent lifecycle. The 30s TTL was wall-clock, but with app lock on the whole unlock flow sits between the tap and the first Perp frame; a failed biometric falling back to a password expires the intent, the persisted restore wins again and the original defect returns with nothing in the log to tell expiry from absence. The bound is now 5 minutes and expiry is marked. The non-claiming resync passed an intent that is undefined by construction, which read as if that branch took deeplinks into account and would revive the override the moment the gate was loosened. The gate itself had no coverage: deleting it left every case green. It now lives in a pure helper with a test that fails when it is dropped. * fix: remember the target market for every context-less perps entry The desktop tray, universal search, the Home perps card, the market banner and the market list all jump into Perps the same way the notification path did: write the background atom, then emit PerpSwitchActiveInstrument. When the Perp tab mounts for the first time in a launch that listener does not exist yet, and the claiming initial-select then restores the coin from the cold-start cache over the one the user asked for. Each now records the intent before the atom write, so that first mount restores the tapped market. The Home card passes its own mode through, since it can open a spot pair. * fix: record the perps intent before navigation and off the tap path Two review findings on the entry points added in the previous commit. Four of the five recorded the intent after switchTab, so closing the window rested on React scheduling the mount effect a macrotask later, and on the market list an await import() of a cold chunk could push it past the claiming run entirely. Each now records before the navigation that mounts the tab, and the market list hoists its import for the same reason, which makes the ordering structural instead of incidental. The write also sat inside the same try as changeActiveAsset. On the Home card that try catches into a return placed before switchTab, so a rejected proxy call — a cold MV3 worker, a bridge timeout — left the tap doing nothing at all; elsewhere it swallowed the switch event too. It is bookkeeping whose absence only costs the first-mount restore, so it now has its own catch. * refactor: make the perps first-mount market a one-shot background value Codex review of the accumulated fix. The behaviour was right but carried four mechanisms where one does the job. The pending market now reuses the existing preferredInstrument slot instead of a parallel deeplinkIntent parameter, so buildInitialTradeInstrumentSwitchParams and its ten tests return to their original state — the restore semantics #12680 established are untouched rather than re-argued. The setter no-ops once the latch is taken. That single line replaces the claimed gate at the call site, the resolveAppliedDeeplinkIntent helper and its tests, and the wall-clock TTL: after the claim the page is live and switches through the event bus, so nothing recorded later could be anything but an override of a market the user picked since. The TTL it replaces had its own defect, discarding the target when app lock kept the user past five minutes. Also isolates the notification setter, which was the one entry left where a rejected bookkeeping call skipped the asset write, the mode write and the event; and moves the Home card's record after its writes, so a bail-out no longer strands a pending pair for the next launch to consume. 334 insertions become 182. * docs: record the perps cold-start market case study Required by the repository's bug-fix case recording rule; pure append. * fix: keep a failed chunk load from swallowing a market tap, and cover the pick Two review findings. Hoisting the lazy backgroundApiProxy import above the try in usePerpsNavigation put it outside any error handling, so a chunk that fails to load — stale deployment, offline, CSP — skipped the tab switch as well and escaped as an unhandled rejection. Before this PR the tab still opened. The import now sits inside the same catch as the record it serves, and the navigation runs either way; only the switch that genuinely needs the proxy is skipped. The pick-versus-restore decision moves into resolveInitialPreferredInstrument so it can be tested, which the repository's self-testing rule requires for a bug fix. Verified by mutation: reversing the precedence fails two of the four cases. buildInitialTradeInstrumentSwitchParams and its ten cases stay untouched, so #12680's restore path is still guarded by its original tests. * fix: read the restored perps instrument at switch time, not before the wait Review catch. Extracting the pick-versus-restore decision moved the read of activeTradeInstrumentRef to right after prepareInitialSymbolSelect, but the claiming run can await a trading-meta fetch between that point and the switch. A pair the user picked during that wait was then overwritten by the one open before it, with force: true clearing the order form — and the surrounding log still read the fresh ref, so logs and behaviour disagreed. The resolution moves back to the call that consumes it, which is where the ref was read before this PR. The pending market is unaffected: it is taken once at the claim and cannot change underneath. * style: format the perps cold-start changes with the pinned prettier CI's oxlint prettier check failed on ten spots across four of the touched files. The local toolchain resolves prettier 2.8.8 while the workspace pins 3.8.1, so neither agent:check nor a local --check could see them. (cherry picked from commit c4b545f)
* fix: sync sidebar theme switching * fix: stabilize theme switching * fix: sync embedded themes after reload OK-54061 (cherry picked from commit 929f05a)
…OK-60300, OK-60303) (#12906) * Feat/protocol tips OK-58972 (#12715) (cherry picked from commit fa9228f) * fix: Earn banner glass bar, shadow clipping and list copy (OK-60299, OK-60300, OK-60303) Signed-off-by: ezailWang <jelly@onekey.so> * fix: lint Signed-off-by: ezailWang <jelly@onekey.so> * fix: dark glass banner bar, rich-text protocol tips and PR review follow-ups Signed-off-by: ezailWang <jelly@onekey.so> * fix: DeFi home swipe, banner tap target and first-load height (OK-60299, OK-60602, OK-60606) Signed-off-by: ezailWang <jelly@onekey.so> --------- Signed-off-by: ezailWang <jelly@onekey.so> (cherry picked from commit 51ace8a)
|
@codex review |
|
@codex security review |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
Security review completed. No security issues were found in this pull request. Reviewed commit: Only the user who started this review can view the report in Codex. ℹ️ About Codex security reviews in GitHubThis is an experimental Codex feature. Security reviews are triggered when:
Once complete, Codex will leave suggestions, or a comment if no findings are found. |
| const balanceActionsReady = isStockBalanceActionReady({ | ||
| authoritativeBalance: stockInputTokenBalance.authoritativeBalance, | ||
| authoritativeStockToken: authoritativeStockInputToken, | ||
| isBuySide, | ||
| }); |
There was a problem hiding this comment.
Max and percentage buttons stop working on the sell side when token details come back empty
Severity: non-severe
The balance shortcuts are treated as unusable (isStockBalanceActionReady at packages/kit/src/views/Swap/hooks/useSwapStockTradeInputs.ts:514-518) whenever the extra token record is missing, even though a balance is already shown, so sell orders lose their Max and percentage buttons.
Impact: A user selling a stock token can see their balance but cannot tap Max or 25/50/75%, and must type the amount by hand.
How a defined balance can coexist with a missing token detail
useStockInputTokenBalance builds its result at packages/kit/src/views/Swap/hooks/useSwapStockTradeInputs.ts:194-204: balance falls back to seededBalance ?? '0' while tokenDetail is markStockUsdPriceCurrency(details?.[0]), which is undefined when fetchSwapTokenDetails returns an empty array. balanceReady (:257) only checks balance !== undefined, so authoritativeBalance is defined while authoritativeTokenDetail stays undefined.
On the sell side authoritativeStockInputToken is resolveStockExecutionTokenMetadata({ token, tokenDetail: undefined }), which returns undefined by its first guard (packages/kit/src/views/Swap/hooks/swapStockChannelUtils.ts:142-151). isStockBalanceActionReady then returns false because isBuySide is false and authoritativeStockToken is missing.
That single flag now gates onBalanceMaxPress, onSelectPercentageStage, enableMaxAmount, showPercentageInput, the iOS InputAccessoryView, and SwapActionsState.onSelectPercentageStage in packages/kit/src/views/Swap/pages/components/SwapStockDesktopContainer.tsx, so all of them stay disabled for the whole session while the balance itself renders normally.
| address_type_tooltip_native_segwit__desc = 'address_type_tooltip_native_segwit__desc', | ||
| address_type_tooltip_nested_segwit__desc = 'address_type_tooltip_nested_segwit__desc', | ||
| address_type_tooltip_taproot__desc = 'address_type_tooltip_taproot__desc', | ||
| alerts_and_updates__action = 'alerts_and_updates__action', |
There was a problem hiding this comment.
Generated translation files are edited, which the repository rules forbid
Severity: non-severe
Auto-generated translation artifacts are changed in this PR (new and edited keys in packages/shared/src/locale/enum/translations.ts:159 and the locale JSON files), which the repository rules explicitly prohibit.
Impact: Hand-carried edits to generated i18n output can be silently reverted or conflict on the next generation run.
Rule text and affected files
CLAUDE.md Core Rules: "Never modify generated translations (translations.ts, locale JSON files)." .cursor/rules/locale-handling.mdc repeats it: "Do not modify the code in @onekeyhq/shared/src/locale/enum/translations.ts as these are automatically generated" and "Do not modify the locale JSON files in @onekeyhq/shared/src/locale/json/*".
The diff adds ~90 enum entries plus matching keys in packages/shared/src/locale/json/en_US.json and packages/shared/src/locale/json/th_TH.json, and also changes existing values (protocol_tips__title in en_US, backup.file_permanently_deleted in th_TH). The PR description states these came from the release branch rather than a hand edit; if that is the accepted workflow the rule text should be updated, otherwise these files should be regenerated via the i18n pull instead of merged.
Syncs the fixes that landed on
release/v6.5.0after bundle #7 intohotfix/v6.5.2.Included PRs (6)
7beb35ffa7880119c9e6f688b9537a9bd95eca97dff362df014763435128Deliberately excluded:
1a75a3823f(#12880,chore: release #7). It only touchesRELEASES.jsonand is release/v6.5.0 bundle bookkeeping. This branch has noRELEASES.jsonat all, so picking it would fabricate a manifest whose singleseq: 7entry points atfd071a7c71— a commit that is not on this branch.Conflicts and resolution
.skillshare/skills/1k-retrospective/references/case-studies.md, where the 3-way merge kept both branches' entries.translations.tsplus 19 locale JSONs). The conflicts are adjacent-insertion artifacts — theHEADside of every hunk is empty — not both branches editing the same key.release/v6.5.0's key set is a strict superset of this branch's: 0 keys unique tohotfix/v6.5.2, 92 keys added by release. Taking release's version of these generated artifacts wholesale is therefore lossless and equivalent to ani18n:pullresult — no generated file was hand-edited, per the repo rule.51ace8a822.Verification
release/v6.5.0. The single exception is the retrospective doc noted above.tsgo --noEmitpasses with exit 0 and zero errors. Compared in the same worktree across the 5-commit and 6-commit states — identical.5cd0dbcf0c, so these fixes originally sat on top of 23 commits this branch lacks. Verified that those 23 are absent by SHA only — their content is already here, folded in by sync release/v6.5.0 to the hotfix/v6.5.2 #12839 and chore: sync published release/v6.5.0 bundle #7 into hotfix/v6.5.2 #12903. Both true semantic ancestors (fix: keep perps cold-start data and trade mode consistent across runtimes #12680, feat: add dex labels to perps market lists #12792) are present.dexmarket.spot,global.max,perp.0_fee) exist on this branch in both the enum anden_US.json— a missing JSON key would be a runtime-only failure that no type check catches.Before merging
JPUSH_KEYrepository secret exists. fix: inject JPUSH_KEY into native bundle builds #12872 adds a hard gate (exit 1when empty) that also governs theworkflow_runandworkflow_dispatchentry points, which bypass the patchedsecrets:blocks. This cannot be verified from git.ENABLE_NATIVE_BACKGROUND_THREAD=truelocally where release does not. OK-60543's state lives on the bg-JSServiceHyperliquidsingleton while all recording call sites are main-JS, and this branch also added an awaited hardware migration to bginitCritical, making the cold-start window the fix optimizes busier.tradingview.onekey.sodeployment — fix: sync sidebar theme switching #12887 removes the remount fallback on those platforms in favour of an injectedchangeThemecall.Note:
LOCAL_DB_VERSIONis 20 on this branch vs 19 on release. This sync does not touch it, but it means v6.5.2 carries a one-way schema bump relative to v6.5.0.