Page MenuHomePhabricator

[Cashtab] Improve wallet state management to properly deal with websocket-triggered state changes
ClosedPublic

Authored by bytesofman on Aug 19 2025, 00:06.

Details

Summary

T3826

Cashtab does not have fine-grained tx update ability. When we need to update one tx, we need to update the whole state of the app.

This issue should be fixed (i.e. we should have more specific db queries), but that will require sqlite across platforms and a migration to sqlite on web and extension.

Cashtab's key-value storage needs async updating. We update the whole state when we update a utxo or a tx in history. When Cashtab was originally designed, this was acceptable, because we did not even have websockets (let alone strongly typed utxos and other libs). But now websockets can and should drive the state of the app. With the android app launching soon, we should also begin optimizing storage and app speed using a database to enhance caching and updates.

In this diff we do what we can to optimize state updates without changing the key-value storage.

  • We introduce useRef instead of passing state vars as params. Have avoided this for a long time because useRef is a complication, and the alternative of passing params was acceptable when we only had to worry about the price updating every 90s. But now that cashtabState can change on every tx, it does not make sense at all to re-initialize websockets every time there is a state change. This has been true for some time but we were getting away with it by accepting poor performance in tx updating. We need to useRef so functions have access to the current state, and not the state that existed when the function was first initialized (this is a quirk of React that was previously handled by passing params and re-initializing functions with useEffect).
  • Queue async methods that are triggered by ws msgs (we can have race conditions with multiple onMessage calls trying to update the same state with different inputs)
  • Batch finalized updates. This is esp important now as tx finalization only occurs with postconsensus, so the user often has many txs finalize at the same time. Async queueing alone may not fully resolve some finalizing txs being missed as we cannot await react state changes.
Test Plan

npm test, try it out at cashtab.io, send and receive txs and watch them finalize correctly

this diff is deployed at cashtab.io with debug logging for receiving finalized txs

Diff Detail

Repository
rABC Bitcoin ABC
Branch
queue-cashtab-actions
Lint
Lint Passed
Unit
No Test Coverage
Build Status
Buildable 34187
Build 67842: Build Diffcashtab-tests
Build 67841: arc lint + arc unit

Event Timeline

stop passing cashtabState as a param to update

bytesofman edited the test plan for this revision. (Show Details)
bytesofman edited the summary of this revision. (Show Details)
Fabien added a subscriber: Fabien.
Fabien added inline comments.
cashtab/src/wallet/useWallet.ts
230

Can be done in another diff but this can be batched the same as finalization

347

It's probably just fine to increase this value a bit. Nobody will see the difference between a 10ms delay and e.g. a 100ms delay while otoh the refresh itself will likely take more than 10ms causing blink effects

This revision is now accepted and ready to land.Aug 19 2025, 07:17
cashtab/src/wallet/useWallet.ts
347

will use 10ms for now but watch for this kind of impact. goal is to minimize this value so that we do not un-necessarily pad avalanche finality.