Problem
UnlockModal.tsx calls unlockAssets from src/lib/soroban.ts and awaits a TransactionResult. The underlying SorobanService.unlockAssets method submits the transaction and is expected to poll rpcServer.getTransaction(hash) for the final status, but the polling loop is not yet implemented — it returns immediately after sendTransaction.
A transaction can remain in the PENDING or NOT_FOUND state for up to 30 seconds on a loaded network. During this window the UI has no feedback and the user may close the modal or click again, causing a double submission.
Expected Behaviour
After sendTransaction the frontend polls getTransaction(hash) with exponential back-off until SUCCESS, FAILED, or a configurable timeout (30 s). The UnlockModal shows the transaction hash as a clickable Stellar Expert link and a polling spinner during the wait.
Acceptance Criteria
Relevant Files
src/lib/soroban.ts — unlockAssets, add pollTransactionStatus
src/components/UnlockModal/UnlockModal.tsx — multi-step UI state
Problem
UnlockModal.tsxcallsunlockAssetsfromsrc/lib/soroban.tsand awaits aTransactionResult. The underlyingSorobanService.unlockAssetsmethod submits the transaction and is expected to pollrpcServer.getTransaction(hash)for the final status, but the polling loop is not yet implemented — it returns immediately aftersendTransaction.A transaction can remain in the
PENDINGorNOT_FOUNDstate for up to 30 seconds on a loaded network. During this window the UI has no feedback and the user may close the modal or click again, causing a double submission.Expected Behaviour
After
sendTransactionthe frontend pollsgetTransaction(hash)with exponential back-off untilSUCCESS,FAILED, or a configurable timeout (30 s). The UnlockModal shows the transaction hash as a clickable Stellar Expert link and a polling spinner during the wait.Acceptance Criteria
SorobanServicegains apollTransactionStatus(hash, timeoutMs = 30000)private method implementing exponential back-off starting at 1 s, doubling each attempt, capped at 5 s{ status: 'SUCCESS' | 'FAILED' | 'TIMEOUT'; resultXdr?: string; errorCode?: string }unlockAssets(and the futurelockAssets) callpollTransactionStatusbefore resolvingUnlockModaldisplays three distinct states: Signing → Submitting → Confirming (hash link) → Success / ErrorFAILED, the contract error code extracted from the result XDR is decoded (e.g.Error::Locked = 1→ "Assets are still locked") and shown to the userTIMEOUT, the modal shows the hash and invites the user to check Stellar Expert manuallygetTransactionreturningNOT_FOUNDtwice thenSUCCESSand verifies the result isSUCCESSafter 3 callsRelevant Files
src/lib/soroban.ts—unlockAssets, addpollTransactionStatussrc/components/UnlockModal/UnlockModal.tsx— multi-step UI state