Skip to content

Gate balance effects and FIO refresh on engine readiness (wallet cache v2)#6080

Open
j0ntz wants to merge 3 commits into
developfrom
jon/wallet-cache-v2
Open

Gate balance effects and FIO refresh on engine readiness (wallet cache v2)#6080
j0ntz wants to merge 3 commits into
developfrom
jon/wallet-cache-v2

Conversation

@j0ntz

@j0ntz j0ntz commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

CHANGELOG

Does this branch warrant an entry to the CHANGELOG?

  • Yes
  • No

Dependencies

EdgeApp/edge-core-js#733

Requirements

If you have made any visual changes to the GUI. Make sure you have:

  • Tested on iOS device
  • Tested on Android device
  • Tested on small-screen device (iPod Touch)
  • Tested on large-screen device (tablet)

Description

GUI-side patches for wallet cache v2 phase 1 (TDD section 7: pinned, live). With EdgeApp/edge-core-js#733, wallet objects exist before their engines load and waitForAllWallets resolves in that window, so the login-path surfaces that consumed engine state at resolve-time are gated on engine readiness:

  • checkActionEffect.ts (address-balance): reported the effect against balanceMap immediately after awaiting the wallet, which could now evaluate cached, possibly stale balances. It reports not-yet-effective until the engine has fully synced (same conservatism as the loan flow's waitForLoanAccountSync and the existing < 1 treatment in spend paths, TDD 7.4), letting the action queue's normal 15s poll re-check.
  • Services.tsx: the post-waitForAllWallets FIO refreshes (refreshConnectedWallets, refreshAllFioAddresses) call wallet.otherMethods.*, which the core guarantees is {} pre-engine. A new waitForWalletOtherMethods util watches otherMethods until the engine's methods land (10-minute safety-valve timeout, roughly matching how long waitForAllWallets could already take on large accounts before the cache existed).
  • FioService.ts: the periodic expired-domain check calls otherMethods.getFioAddresses the same way. This one was NOT in the TDD's section-7 audit; it was caught live on the simulator (red dev alert wallet.otherMethods.getFioAddresses is not a function seconds after a warm cached login). Being a 30s periodic task, it skips pre-engine wallets and lets the next cycle retry, which also avoids wedging its one-shot expiredChecking latch when no wallet is ready yet.

Remaining otherMethods call sites (FIO scenes, staking, WalletConnect) are user-navigation surfaces audited in the TDD as safe (null-probes, or flows that imply an engine exists) and are unchanged.

Tested on the iOS simulator against the linked core build (edge-funds, 194 wallets): cold login wrote all 194 walletCache.json files; warm relaunch rendered the full wallet list with names and balances from the cache while engines were still loading; no FIO alert through 140s of runtime; drilling into a wallet shows live engine-backed data on the same wallet object. Screenshots attached below.

Phase 2: tap-prioritization

The core now staggers cached wallets' engine startup through a limited-concurrency queue (EdgeApp/edge-core-js#733 phase 2). withWallet wraps every wallet-scoped scene, so opening one calls account.waitForCurrencyWallet(walletId), which moves that wallet's engine startup to the front of the queue. The call is a fire-and-forget hint; a deleted or broken wallet is already handled by the existing goBack effect.

Phase 6: provisional receive address (TDD section 7.5, decision 9.9)

The receive scene (RequestScene.tsx) waited on the engine for every address, so a rotating-address chain showed a loading state until the engine started. It now opts into the core's cached address (getAddresses({ allowCached: true }), EdgeApp/edge-core-js#733 phase 6) and renders it immediately.

  • On a rotating chain (!hasStableAddresses), the cached address is provisional: a static inline affordance sits under the address (a muted circled-i glyph, "Checking for your latest address", and a spinner; informational, not tappable, not a warning color). A 350ms grace timer gates it on, so a warm engine that confirms first never flashes it; the QR is capped to reserve the row's height so toggling never reflows it.
  • The confirmed address swaps in place only if it differs once the engine loads; on engine failure/timeout the row is removed and the cached address stays, with a 30s safety cap so the spinner never hangs.
  • Staleness guards (from review): each refresh takes a token and captures the wallet id, so a slow reconcile from a prior wallet (the withWallet instance is reused across wallet switches) or after unmount is ignored rather than overwriting the current address. A later refresh / addressChanged rotation takes the plain engine-gated path, so it never shows a stale address.

Rotating-chain behavior is provable in-app on a UTXO chain (BTC/LTC) with no plugin change; the stable-chain skip and the core gating are covered by unit tests. Depends on the core allowCached option (EdgeApp/edge-core-js#733) and, for stable chains, the plugin flags (draft EdgeApp/edge-currency-accountbased#1076).

TDD (pinned, live): implementation divergences and the decisions are documented inline in the affected sections.

Asana: https://app.asana.com/1/9976422036640/project/1213843652804305/task/1216673467164267


Note

Medium Risk
Touches login-time FIO refresh, action-queue balance gating, and receive-address display on rotating chains; wrong timing could show stale addresses or delay automation, but guards and conservative "not effective" behavior limit exposure.

Overview
Adapts the GUI for wallet cache v2, where wallet objects appear before their engines load.

Receive (RequestScene) shows a cached address immediately on warm login for rotating chains (!hasStableAddresses), using getAddresses({ allowCached: true }) and reconciling against the engine-confirmed address. A fixed-height "Checking for your latest address" row (with spinner) appears only after a 350ms grace period if the engine has not confirmed; staleness tokens prevent races across wallet switches and unmount.

Engine readiness gates: action-queue address-balance effects defer until syncStatus reaches the done threshold so cached balances are not evaluated early. Post-login FIO work in Services.tsx waits on a new waitForWalletOtherMethods helper before refreshConnectedWallets / refreshAllFioAddresses; FioService skips FIO wallets whose otherMethods are not ready and fixes the expired-check latch in a finally block.

Tap prioritization: withWallet calls account.waitForCurrencyWallet(walletId) when opening wallet-scoped scenes so that wallet’s engine is bumped to the front of the post-login queue.

Adds locale string request_provisional_address, a RequestScene unit test for the provisional affordance, and CHANGELOG entries.

Reviewed by Cursor Bugbot for commit 5d1a879. Bugbot is set up for automated code reviews on this repo. Configure here.

@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.

@j0ntz

j0ntz commented Jul 18, 2026

Copy link
Copy Markdown
Contributor Author

📸 Test evidence (iOS sim, edge-funds)

agent proof 1216673467164267 01 cold login wallet list

agent proof 1216673467164267 01 cold login wallet list

agent proof 1216673467164267 02 warm login cached wallet list

agent proof 1216673467164267 02 warm login cached wallet list

agent proof 1216673467164267 03 wallet detail engine loaded

agent proof 1216673467164267 03 wallet detail engine loaded

Captured by the agent's in-app test run (build-and-test).

Comment thread src/components/services/Services.tsx
Comment thread src/components/services/FioService.ts Outdated
Comment thread src/util/waitForWalletOtherMethods.ts
@j0ntz
j0ntz force-pushed the jon/wallet-cache-v2 branch from 00faa89 to 7f1149f Compare July 18, 2026 01:10
Comment thread src/components/services/Services.tsx
@j0ntz

j0ntz commented Jul 18, 2026

Copy link
Copy Markdown
Contributor Author

📸 Test evidence (after review fixes)

agent proof 1216673467164267 04 warm login after review fixes

agent proof 1216673467164267 04 warm login after review fixes

Captured by the agent's in-app test run (build-and-test).

With the core's wallet cache (wallet cache v2 phase 1), wallet objects
exist before their engines load, and waitForAllWallets resolves in that
window. Three login-path surfaces consumed engine state immediately:

- The action queue's address-balance effect read balanceMap right after
  awaiting the wallet, which could evaluate a balance effect against
  cached, possibly stale balances. It now reports not-yet-effective
  until the engine has fully synced, matching the conservatism the loan
  flow already applies.
- The FIO address refresh called otherMethods on pre-engine wallets,
  which is {} in that window. Services now waits for each FIO wallet's
  engine-backed otherMethods (bounded by a generous safety-valve
  timeout) before refreshing.
- FioService's periodic expired-domain check called
  otherMethods.getFioAddresses the same way (caught live on the sim).
  It now skips pre-engine wallets and lets the next 30s cycle retry,
  which also avoids wedging its one-shot expiredChecking latch.
@j0ntz
j0ntz force-pushed the jon/wallet-cache-v2 branch from 7f1149f to 0a089ca Compare July 18, 2026 01:31
Comment thread src/controllers/action-queue/runtime/checkActionEffect.ts
The core's new post-login queue staggers cached wallets' engine
startup. withWallet covers every wallet-scoped scene, so opening one
calls waitForCurrencyWallet, which moves that wallet's engine to the
front of the queue.

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Claude Code Review

Claude Code Review is paused for this repository. To reconnect it, an admin of this repository's GitHub organization (or the account owner, for personal repositories) who can also manage your Claude organization's Code Review settings needs to re-link GitHub in Code Review settings. This is a one-time step.

Tip: disable this comment in your organization's Code Review settings.

Comment thread src/components/services/Services.tsx
Comment thread src/util/waitForWalletOtherMethods.ts
@j0ntz

j0ntz commented Jul 19, 2026

Copy link
Copy Markdown
Contributor Author

📸 Test evidence (phase 2: warm login + tap-prioritization)

agent proof 1216673467164267 05 warm login list

agent proof 1216673467164267 05 warm login list

agent proof 1216673467164267 06 sepolia detail after tap

agent proof 1216673467164267 06 sepolia detail after tap

Captured by the agent's in-app test run (build-and-test).

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Claude Code Review

Claude Code Review is paused for this repository. To reconnect it, an admin of this repository's GitHub organization (or the account owner, for personal repositories) who can also manage your Claude organization's Code Review settings needs to re-link GitHub in Code Review settings. This is a one-time step.

Tip: disable this comment in your organization's Code Review settings.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 8f2ef2f. Configure here.

Comment thread src/components/scenes/RequestScene.tsx
@j0ntz
j0ntz force-pushed the jon/wallet-cache-v2 branch from 8f2ef2f to 0de615b Compare July 23, 2026 11:19
@j0ntz

j0ntz commented Jul 23, 2026

Copy link
Copy Markdown
Contributor Author

📸 Phase 6 test evidence (LTC receive scene, warm login)

agent proof 1216673467164267 p6 01 ltc receive cached

agent proof 1216673467164267 p6 01 ltc receive cached

agent proof 1216673467164267 p6 02 ltc receive warmlogin

agent proof 1216673467164267 p6 02 ltc receive warmlogin

Captured by the agent's in-app test run (build-and-test).

The receive scene waited on the wallet engine for every address, so a
warm login showed a spinner until the engine loaded. It now opts into
the core's cached address (getAddresses allowCached) and renders it at
once. On a rotating-address chain the cached answer is provisional: a
muted inline row with an info glyph, 'Checking for your latest
address', and a spinner sits below the address, the QR is capped to
reserve that row's height so it never reflows, and the confirmed
address swaps in only if it differs once the engine loads. Stable
chains show the cached address full-size with no row.
@j0ntz
j0ntz force-pushed the jon/wallet-cache-v2 branch from 0de615b to 5d1a879 Compare July 23, 2026 12:03
@j0ntz

j0ntz commented Jul 23, 2026

Copy link
Copy Markdown
Contributor Author

📸🩹 Test evidence: provisional receive affordance

🩹 Some screenshots below are HACK-FORCED. The marked frames show a state forced by a temporary uncommitted local edit (the natural trigger could not be reproduced on the sim). The hack is not in this PR's diff; the pixels prove the rendering, not the trigger.

🩹 HACK-FORCED: provisional affordance

🩹 HACK-FORCED: provisional affordance

Captured by the agent's in-app test run (build-and-test).

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.

1 participant