Skip to content

chore: sync release/v6.5.0 fixes after bundle #7 into hotfix/v6.5.2 - #12935

Merged
originalix merged 6 commits into
hotfix/v6.5.2from
sync/6.5.0-to-6.5.2-20260819
Aug 19, 2026
Merged

chore: sync release/v6.5.0 fixes after bundle #7 into hotfix/v6.5.2#12935
originalix merged 6 commits into
hotfix/v6.5.2from
sync/6.5.0-to-6.5.2-20260819

Conversation

@originalix

@originalix originalix commented Aug 19, 2026

Copy link
Copy Markdown
Collaborator

Syncs the fixes that landed on release/v6.5.0 after bundle #7 into hotfix/v6.5.2.

Included PRs (6)

Commit PR Description
7beb35ffa7 #12872 inject jpush key into native bundle builds
880119c9e6 #12901 sync stock token metadata for max amount (OK-58721)
f688b9537a #12907 align perp dex source labels (OK-59905)
9bd95eca97 #12918 keep the perps deeplink target over the cold-start restore (OK-60543)
dff362df01 #12887 sync sidebar theme switching
4763435128 #12906 Earn banner glass bar, shadow clipping and list copy (OK-60299/60300/60303)

Deliberately excluded: 1a75a3823f (#12880, chore: release #7). It only touches RELEASES.json and is release/v6.5.0 bundle bookkeeping. This branch has no RELEASES.json at all, so picking it would fabricate a manifest whose single seq: 7 entry points at fd071a7c71 — a commit that is not on this branch.

Conflicts and resolution

  • First 5 commits: zero conflicts. The only auto-merge was .skillshare/skills/1k-retrospective/references/case-studies.md, where the 3-way merge kept both branches' entries.
  • fix: Earn banner glass bar, shadow clipping and list copy (OK-60299, OK-60300, OK-60303) #12906 conflicted in 20 generated i18n files (translations.ts plus 19 locale JSONs). The conflicts are adjacent-insertion artifacts — the HEAD side of every hunk is empty — not both branches editing the same key.
    • Before resolving, I verified that release/v6.5.0's key set is a strict superset of this branch's: 0 keys unique to hotfix/v6.5.2, 92 keys added by release. Taking release's version of these generated artifacts wholesale is therefore lossless and equivalent to an i18n:pull result — no generated file was hand-edited, per the repo rule.
    • Post-resolution check: all 20 files are byte-identical to 51ace8a822.

Verification

Before merging

  1. Confirm the JPUSH_KEY repository secret exists. fix: inject JPUSH_KEY into native bundle builds #12872 adds a hard gate (exit 1 when empty) that also governs the workflow_run and workflow_dispatch entry points, which bypass the patched secrets: blocks. This cannot be verified from git.
  2. Re-test the perps deeplink fix on a native split-bundle build. This branch runs ENABLE_NATIVE_BACKGROUND_THREAD=true locally where release does not. OK-60543's state lives on the bg-JS ServiceHyperliquid singleton while all recording call sites are main-JS, and this branch also added an awaited hardware migration to bg initCritical, making the cold-start window the fix optimizes busier.
  3. Spot-check chart theme switching on desktop and native against the live tradingview.onekey.so deployment — fix: sync sidebar theme switching #12887 removes the remount fallback on those platforms in favour of an injected changeTheme call.

Note: LOCAL_DB_VERSION is 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.

huhuanming and others added 6 commits August 19, 2026 16:30
…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)
@sidmorizon

Copy link
Copy Markdown
Contributor

@codex review

@sidmorizon

Copy link
Copy Markdown
Contributor

@codex security review

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@chatgpt-codex-connector

Copy link
Copy Markdown

Security review completed. No security issues were found in this pull request.

Reviewed commit: 4763435128

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@originalix
originalix merged commit 85e4d59 into hotfix/v6.5.2 Aug 19, 2026
14 checks passed
@originalix
originalix deleted the sync/6.5.0-to-6.5.2-20260819 branch August 19, 2026 08:51
Comment on lines +514 to +518
const balanceActionsReady = isStockBalanceActionReady({
authoritativeBalance: stockInputTokenBalance.authoritativeBalance,
authoritativeStockToken: authoritativeStockInputToken,
isBuySide,
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants