Skip to content

Release v3.0.2: Atomic data sync, API resilience, progress indicators & fiat currency fix#62

Closed
boldbitcoin wants to merge 53 commits intomainfrom
v3.0.2
Closed

Release v3.0.2: Atomic data sync, API resilience, progress indicators & fiat currency fix#62
boldbitcoin wants to merge 53 commits intomainfrom
v3.0.2

Conversation

@boldbitcoin
Copy link
Contributor

@boldbitcoin boldbitcoin commented Mar 13, 2026

Summary

Merges all v3.0.1 work to main — full SQLite DB-first architecture with atomic sync operations, centralized API queue, rate-limit resilience, and multiple UX improvements.

Core Infrastructure

  • SQLite persistence layer — WAL-mode SQLite as single source of truth; repository pattern for all wallet data (balances, UTXOs, transactions, prices, sync cursors)
  • Central API Queue (ApiQueue) — serializes all logical API operations (balance, price, UTXOs, transactions); drives CacheIndicator status text and progress
  • Atomic sync operations — BalanceSyncer, UtxoSyncer, TransactionSyncer collect all data in memory; only write to DB when every address succeeds; typed error classes (BalanceSyncError, UtxoSyncError, TxSyncError)
  • 429 rate-limit retry — automatic retry with backoff, Retry-After header parsing, inter-address throttling (300ms); shared rateLimitRetry module

UX Improvements

  • Progress indicators — CacheIndicator and RestoringIndexesModal show current/total (e.g. "Fetching balance… 3/5")
  • Descriptive failure toasts — specific messages per sync type ("Could not fetch balance", "Could not fetch UTXOs", etc.) with cached data fallback
  • Balance DB-first floor — prevents transient 0-balance display after device unlock
  • Pre-skeleton DB balance seed — balance visible before loading skeleton appears
  • UtxosScreen redesign — dedicated glassmorphism header, derivation path right-aligned, refresh via UtxoSyncer with 429 retry
  • LoadingScreen version:build — app version displayed at bottom center
  • Mempool Playground — new GET Historical Price endpoint

Bug Fixes

  • Fiat currency reset on cold start — EUR/GBP etc no longer overwritten to USD on restart
  • TransactionSyncer atomicitybreak on !res.ok changed to throw to prevent partial DB writes
  • MobilesPairing modal close — navigates back to previous screen
  • Duplicate fetch race — focus guard checks both reinit and fetch-in-progress refs

Test plan - e2e ok

  • Cold start with EUR selected → verify EUR rate persists after restart
  • Pull-to-refresh on WalletHome → verify CacheIndicator shows operation labels and progress
  • Trigger 429 rate limit → verify retry with backoff and eventual success or descriptive toast
  • Restore wallet → verify RestoringIndexesModal shows progress (e.g. "Syncing balances… 3/5")
  • UtxosScreen → verify summary card styling, derivation path alignment, dark/light mode
  • LoadingScreen → verify version:build visible at bottom
  • MobilesPairing → sign tx, close modal → verify navigation back

bbtc and others added 30 commits March 3, 2026 11:03
Both MpcSendBTCWithUTXOs and NostrMpcSendBTCWithUTXOs were calling
FetchUTXODetails (GET /tx/{txid}) twice per input inside the signing
loop. A single API failure mid-session aborted the entire MPC round.

Changes:
- UTXOWithPath and utxoWithPathJSON now carry a scriptpubkey field (hex)
- Both signing functions build prevOuts from inline scriptpubkey;
  FetchUTXODetails is called only as a fallback when scriptpubkey is empty
  (backward-compatible: old callers without scriptpubkey continue to work)
- WalletService.enrichUtxosWithScriptpubkey() fetches /tx/{txid} per
  unique txid in TypeScript before MPC starts, with per-tx caching to
  avoid duplicate fetches for multi-input transactions
- MobilesPairing and MobileNostrPairing call enrichUtxosWithScriptpubkey
  and include scriptpubkey in the JSON passed to the native bridge
- NostrMpcSendBTCWithUTXOs and MpcSendBTCWithUTXOs now return errors on
  invalid amountSatoshi/estimatedFee strings instead of silently using 0

Made-with: Cursor
… UTXO summary card

- Add MempoolClient: in-memory cache + in-flight dedup + per-endpoint TTL
  (30 s default, 5 min tx, 60 s fees/price) + universal 10 s timeout
- Switch getWalletBalanceAggregate to /api/address/:address (chain_stats +
  mempool_stats); ~50x smaller responses; expose pendingSats in WalletBalance
- WalletHome: shimmer replaces ActivityIndicator; displayFiat via useMemo
  (fixes 0 BTC / non-zero fiat mismatch); amber pending chip for unconfirmed sats
- UtxosScreen: static balance summary card (Total / Confirmed / Pending with
  UTXO counts) pinned above scrollable list
- Fix receive-flow address mismatch: getCurrentReceivePathInfo atomically
  returns {path, index, address}; eliminates QR flicker at index boundary
- TransactionList: migrate axios → mempoolClient; remove manual timeout race
- TransactionDetailsModal: tighten flow-item accent bar style
- Update CHANGELOG.md with all v3.0.0 additions

Made-with: Cursor
…ansport

- pump.go: fix TOCTOU race in processEvent — move the processed-map check
  to AFTER assembly under a single lock acquisition; parallel initial-query
  goroutines can no longer double-dispatch the TSS handler for single-chunk
  messages (root cause of the reported signing failure with multiple relays)
- pump.go: replace fixed 1s retryTicker with exponential backoff (0→500ms→1s)
  for subscription failures and channel-close reconnects; reduces blind-spot
  window for messages arriving during relay reconnection
- session.go: parallelize AwaitPeers initial relay query using sync.WaitGroup;
  a slow/offline relay no longer blocks the others from being scanned within
  the timeout budget (previously sequential)
- session.go: continue publishing ready/complete wraps to all peers even when
  one peer's publish fails; report first error only after all peers attempted
- session.go: replace fixed 1s retryTicker with exponential backoff for
  AwaitPeers subscription setup and channel-close resubscription; eliminates
  duplicated nested retry loop
- config.go: increase ConnectTimeout default from 20s to 45s to give more
  room for mobile networks during peer rendezvous

Made-with: Cursor
bbtc and others added 16 commits March 8, 2026 13:09
Remove trailing newlines flagged by `gofmt -s -l .` in CI.

Made-with: Cursor
… balance consistency fixes

Made-with: Cursor
- Central ApiQueue serializing balance/price/UTXO/tx operations with
  progress reporting (current/total) to CacheIndicator and
  RestoringIndexesModal
- Atomic sync: BalanceSyncer, UtxoSyncer, TransactionSyncer collect all
  data in memory and only write to DB when every address succeeds
- 429 rate-limit retry with backoff, Retry-After header support, and
  inter-address throttling (rateLimitRetry module)
- Descriptive failure toasts per sync type
- Fix: fiat currency (EUR etc) overwritten to USD on every cold start
- Fix: MobilesPairing modal close navigates back
- UtxosScreen dedicated header style, derivation path right-aligned
- LoadingScreen version:build display
- Mempool Playground: GET Historical Price endpoint
- Updated CHANGELOG.md for v3.0.1

Made-with: Cursor
@boldbitcoin boldbitcoin changed the title Release v3.0.1: SQLite DB-first, atomic sync, API queue, 429 retry, UX improvements Release v3.0.2: SQLite DB-first, atomic sync, API queue, 429 retry, UX improvements Mar 13, 2026
@boldbitcoin boldbitcoin changed the title Release v3.0.2: SQLite DB-first, atomic sync, API queue, 429 retry, UX improvements Release v3.0.2: Atomic data sync, API rate-limit resilience, progress indicators & fiat currency fix Mar 13, 2026
@boldbitcoin boldbitcoin changed the title Release v3.0.2: Atomic data sync, API rate-limit resilience, progress indicators & fiat currency fix Release v3.0.2: Atomic data sync, API resilience, progress indicators & fiat currency fix Mar 13, 2026
@boldbitcoin boldbitcoin requested review from HalFinneyIsMyHomeBoy, RaProceed and kar1timmins and removed request for RaProceed March 13, 2026 08:28
- TransactionSyncer: always fetch from /txs first (forward pass) to
  find newly confirmed transactions, then backfill from stored cursor.
  Fixes devices missing transactions confirmed after initial sync.
- WalletService: overlay DB is_confirmed/block_height/block_time onto
  parsed rawJson so the UI reflects confirmed status even when rawJson
  is stale. Fixes "Consolidating" shown for already-confirmed txs.
- SyncCoordinator: periodic HD index re-discovery (24h staleness) to
  converge address ranges across multi-device wallets. Notifies UI
  via onAddressesChanged when new addresses are found.
- Bump build number to 53 (Android versionCode + iOS build).

Made-with: Cursor
@boldbitcoin
Copy link
Contributor Author

Superseded by v3.0.3 release PR.

@boldbitcoin boldbitcoin deleted the v3.0.2 branch March 14, 2026 07:58
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.

3 participants