Problem Statement / Feature Objective
Soroban transactions submitted from the dashboard require sequential nonce management per source account. When multiple UI components (tariff updater, meter snapshot scheduler, resource transfer panel) submit transactions concurrently, they risk nonce collisions or sequence gaps that cause contract execution failures. An asynchronous nonce manager must maintain a per-account nonce pool with pre-fetching, lock leasing, and automatic retry with incremented nonce on failure due to sequence mismatch. The manager must also handle account switching (when the operator swaps wallets) by flushing the pending nonce queue.
Technical Invariants & Bounds
- Nonce pre-fetch window: 20 nonces per account, obtained via Server.getAccount(accountId).sequenceNumber + sequential increment.
- Lock leasing: each pending transaction acquires a nonce lease; lease timeout is 120 seconds. Expired leases release the nonce back to the pool.
- Maximum pending transactions per account: 50 (limited by Soroban transaction queue depth recommendation).
- Conflict resolution: if a submission fails with error code tx_bad_seq, the manager releases all pre-fetched nonces for that account, re-fetches the current on-chain sequence, and retries up to 3 times.
- Account switch handler: on wallet change event, cancel all pending leases, flush the queue, and dispatch a RECONCILE_NONCE action to reset.
Codebase Navigation Guide
- src/services/nonceManager.ts - Core nonce manager singleton: pre-fetch, lease acquire/release, retry logic.
- src/services/soroban.ts - Transaction submission; must be updated to acquire nonce from manager before building the transaction envelope.
- src/hooks/useNonceManager.ts - React hook exposing acquireNonce(accountId), releaseNonce(leaseId), and pending count.
- src/store/slices/nonceSlice.ts - Redux slice tracking nonce state per account: current base, pool size, pending count, last error.
- src/hooks/useWallet.ts - Wallet connection hook; on account change, triggers nonce manager flush.
- src/types/soroban.ts - Type definitions for NonceLease, NoncePool, SequenceNumber.
Implementation Blueprint
- In src/services/nonceManager.ts, implement a class NonceManager with: initialize(accountId) fetches current sequence and pre-fetches 20 nonces into a pool. acquireLease(accountId) pops the next available nonce from the pool and creates a lease entry with a 120-second setTimeout. releaseLease(leaseId) returns the nonce to the pool if unused. submitWithNonce(args) wraps soroban.submitTransaction, catches tx_bad_seq errors, and triggers a re-fetch + retry cycle (max 3 attempts).
- In soroban.ts, add a submitWithNonce wrapper that takes the transaction XDR and the lease, invokes the Soroban RPC call, and on success marks the lease as consumed.
- Create useNonceManager hook that returns { status, pendingCount, poolSize }. Components like MeterSnapshotScheduler call acquireLease before building their transaction, then pass the lease to submitWithNonce.
- nonceSlice stores: accounts[accountId] = { baseSequence, poolSize, pendingCount, lastError }. Actions: NONCE_POOL_UPDATED, NONCE_LEASE_ACQUIRED, NONCE_LEASE_RELEASED, NONCE_POOL_EXHAUSTED, NONCE_FLUSHED.
- In useWallet, on account change event, call nonceManager.flushAccount(oldAccountId) which cancels all leases and dispatches NONCE_FLUSHED. Then call initialize on the new account.
- Write integration test in src/tests/nonceManager.test.ts: simulate concurrent submission of 5 transactions, verify that each gets a unique nonce, and that a tx_bad_seq error triggers a full re-fetch and retry.
Problem Statement / Feature Objective
Soroban transactions submitted from the dashboard require sequential nonce management per source account. When multiple UI components (tariff updater, meter snapshot scheduler, resource transfer panel) submit transactions concurrently, they risk nonce collisions or sequence gaps that cause contract execution failures. An asynchronous nonce manager must maintain a per-account nonce pool with pre-fetching, lock leasing, and automatic retry with incremented nonce on failure due to sequence mismatch. The manager must also handle account switching (when the operator swaps wallets) by flushing the pending nonce queue.
Technical Invariants & Bounds
Codebase Navigation Guide
Implementation Blueprint