Date: 2026-08-17 (research) · mirrored 2026-08-21
Type: Technical research — Production wallet analysis
Status: ✅ Confirmed + Implemented (Aug 17-21)
Phase: 0 → 1 transition (Production readiness)
Full research: asgaya/knowledge/research/RS083_transaction_broadcast_ui_patterns.md (private knowledge base)
Observation: Asgaya’s covenant funding/refund/abort operations suffered from “stuck sending…” UI bugs where transactions succeed but the UI never updates.
Key findings from studying production wallets (Selene, Paytaca):
lifecycleScope is wrong for broadcasts — it cancels coroutines on activity destruction, losing callbacks even when the tx succeedsRecommendation (adopted): navigate on success, persist transactions, rebroadcast on resume, use viewModelScope.
ReviewSendActivity.sendTransaction() ran in lifecycleScope.launchObserved: transaction succeeded on-chain (TXID e9254e7e...) but UI showed failure/timeout.
SendViewModel using viewModelScope — survives activity destructionpending_transactions table (Room DB) — status BROADCAST → MEMPOOL → CONFIRMEDviewModelScope coroutine polls Electrum (60s, up to 1h), updates DBonResume() checks non-confirmed txs, rebroadcasts if droppedDispatchers.MainArchitecture: viewModelScope + Room pending_transactions + CovenantBuildService (v0.2 hybrid) for network ops.
RS083 is the state-management layer; the v0.2 hybrid is the network-reliability layer. Together:
build() + Kotlin broadcast (network) — eliminates the WebSocket hang class entirelyThe hybrid made broadcast reliable at the network level; RS083 made it reliable at the state level. Both are required and now both are implemented.
pending_transactions schema + SendViewModelStatus: ✅ Confirmed + Implemented (Aug 17-21, 2026)
Evidence: Multi-device testing passing after v0.2 hybrid; transactions persist and confirm in background