Reduce UI lag: YAOB throttle, debounce, dedup, and balance cache#709
Reduce UI lag: YAOB throttle, debounce, dedup, and balance cache#709paullinator wants to merge 8 commits intomasterfrom
Conversation
Add missing return in fake plugin getBalance for token balance. Improve @ts-expect-error comment and log swap quote close errors.
Improve login performance by caching wallet state on a per account level in unencrypted JSON file and rehydrate before wallets load.
During login, 45% of balance-related YAOB bridge crossings were redundant. The Redux balanceMap started empty despite cached balances being available, treating every cached balance as "new". (A) Initialize balanceMap directly from the wallet cache in the reducer via a new ACCOUNT_CACHED_BALANCES_LOADED action dispatched before wallet creation, so YAOB never observes an empty map. (B) Early-return guard in onTokenBalanceChanged drops callbacks when the balance matches the current Redux state, catching any duplicates the cache initialization missed. Removes the now-redundant initial parent-balance dispatch from the wallet pixie since balanceMap is pre-populated.
At 50ms, YAOB sent up to 20 bridge messages per second per wallet. With 168 wallets, the RN JS thread was overwhelmed with JSON parsing and proxy updates. Increasing to 200ms batches more updates per message and reduces interrupt frequency by 4x.
Every Redux state change triggered the pixie watcher to call update(walletApi), sending a bridge message even when multiple changes arrived within milliseconds. Per-wallet debouncing collapses rapid-fire state mutations into a single bridge crossing. Also adds hasYaobVisibleChange to skip no-op bridge messages caused by Redux reference changes to internal-only fields.
The update queue processed 3 items per 500ms (6/sec), but with 168 wallets filling it, the queue peaked at 227 items and never drained. Slowing individual processing while relying on deduplication keeps the queue shallow.
The onTransactions callback dispatched CURRENCY_ENGINE_CHANGED_TXS unconditionally, even when compare() filtered out all transactions as unchanged. Each dispatch mutated wallet state, triggered the pixie watcher, and sent a YAOB bridge message. Gating the dispatch eliminates no-op bridge crossings. Also guards onNewTokens against empty arrays.
The CURRENCY_ENGINE_CHANGED_BALANCE reducer always created a new Map reference, marking the wallet as dirty and triggering a YAOB bridge message even when the balance was identical. A same-value guard keeps the existing reference, letting the watcher debounce skip the update.
| update(walletApi) | ||
| } | ||
| } | ||
| }, 300) |
There was a problem hiding this comment.
Debounce timer uses stale closure over walletState
Medium Severity
The setTimeout callback on line 476 captures walletState from the enclosing async function's local scope. This value is frozen to whatever state existed when the timer was first created. During the 300ms debounce window, subsequent updates set updatePending = true but the timer still holds the stale walletState. When the timer fires, hasYaobVisibleChange compares the stale snapshot (not the latest state) against lastUpdatedState, and lastUpdatedState is then set to the stale value. This causes lastUpdatedState to diverge from what yaob actually received, which can lead to skipped update(walletApi) calls in subsequent debounce windows. Using the outer-scope lastState variable (which always holds the most recent state) instead of the closure-captured walletState would fix this.
|
Bugbot Autofix prepared fixes for 1 of the 1 bugs found in the latest run.
Or push these changes by commenting: Preview (e705a0120b)diff --git a/src/core/currency/wallet/currency-wallet-pixie.ts b/src/core/currency/wallet/currency-wallet-pixie.ts
--- a/src/core/currency/wallet/currency-wallet-pixie.ts
+++ b/src/core/currency/wallet/currency-wallet-pixie.ts
@@ -473,8 +473,11 @@
updateTimer = undefined
if (updatePending) {
updatePending = false
- if (hasYaobVisibleChange(walletState, lastUpdatedState)) {
- lastUpdatedState = walletState
+ if (
+ lastState != null &&
+ hasYaobVisibleChange(lastState, lastUpdatedState)
+ ) {
+ lastUpdatedState = lastState
update(walletApi)
}
} |



CHANGELOG
Does this branch warrant an entry to the CHANGELOG?
Dependencies
none
Description
Reduces RN JS thread starvation during wallet scene transitions by cutting redundant YAOB bridge crossings and Redux dispatches. Six targeted fixes:
balanceMapfrom cached balances via a newACCOUNT_CACHED_BALANCES_LOADEDaction, eliminating a wave of redundantonTokenBalanceChangedcallbacks on startup. Adds an early-return guard to drop callbacks when the value matches the current Redux state.update(walletApi)to 300ms: Collapses rapid-fire Redux state mutations into a single bridge crossing per wallet. AddshasYaobVisibleChangeto skip no-op updates for internal-only field changes.CURRENCY_ENGINE_CHANGED_TXSdispatch: Only dispatches whencompare()finds actual changed/created transactions.balanceMapreducer: Returns the existingMapreference when the balance value is unchanged, preventing spurious watcher triggers.Note
Medium Risk
Touches login sequencing, wallet/config objects, and disk-backed caching, which can affect startup behavior and wallet visibility if cache data is stale/invalid or delegation/polling misbehaves. Changes also alter update/dispatch timing, so regressions may show up as delayed UI refreshes or missed updates.
Overview
Adds a cache-first login path that loads a per-account
walletCache.jsonto instantly expose lightweightEdgeCurrencyWallet/EdgeCurrencyConfigstubs (with delegation/polling to real engines), and merges these cached wallets intoEdgeAccount.currencyWalletsuntil engines finish loading.Introduces wallet-cache persistence: a throttled
cacheSaverpixie writes tokens/customTokens, wallet metadata, balances, enabled tokens, andotherMethodsnames; cached balances are dispatched via newACCOUNT_CACHED_BALANCES_LOADEDso wallet reducers seedbalanceMapwithout a startup callback storm. Adds extensive end-to-end tests plus deterministic fake-plugin gating for engine load.Reduces UI/bridge churn by increasing
YAOB_THROTTLE_MS(50→200), debouncing walletupdate(walletApi)with a YAOB-visible-field diff, deduping no-op balance/token/tx Redux dispatches, and slowingupdateQueuecadence.Written by Cursor Bugbot for commit 19b037e. This will update automatically on new commits. Configure here.