Transaction sent — and the user stares at a Pending status for the next 10 minutes. That's fine for blockchain, but not getting a notification when the transaction is confirmed or fails is not. Tracking transaction status is a real-time task with multiple layers: blockchain polling, WebSocket connection, push notification on final status. Without timely updates, users lose trust, and in high-traffic crypto wallets (e.g., 8000 transactions per day) even a 5-second delay creates a negative experience.
Our engineers with 5+ years of experience in blockchain projects have implemented tracking for 15+ crypto wallets. Apple and Google certified, we have worked with Ethereum, Bitcoin, Solana, and other networks, integrated WebSocket via Alchemy WebSocket API and Infura, and configured push notifications through APNs and FCM. We guarantee stable operation and timely status updates.
What does the transaction lifecycle look like?
An Ethereum transaction goes through states: submitted → pending (mempool) → confirmed (1 confirmation) → finalized (12+ confirmations) → failed (reverted / dropped). Bitcoin: mempool → 1 confirmation → 6 confirmations (finalized). Solana is much faster: slots ~400ms, processed → confirmed → finalized in seconds. On the client, you need to show the current state and number of confirmations.
Blockchain Finalization Times
| Blockchain | Block Time | Confirmations for Finalization | Average Finalization Time |
|---|---|---|---|
| Ethereum | 12-15 sec | 12 (as 0x) or 64 (as 1) | ~3 min (12 blocks) |
| Bitcoin | ~10 min | 6 | ~60 min |
| Solana | ~400 ms | 32 | ~13 sec |
What strategies exist for obtaining status?
| Strategy | Delay | Load on Client | Load on Server |
|---|---|---|---|
| Polling (3-5s) | 3-5s | High (frequent requests) | High (RPC calls) |
| WebSocket | <1s | Low (persistent connection) | Medium (subscriptions) |
| Webhook (Alchemy/Infura) | <1s | Zero (only push) | Low (server receives event) |
Polling every 3–5 seconds with the screen open is fine. In the background — only via silent push or WebSocket API. Infrastructure savings of up to 40% when using WebSocket instead of frequent polling. Typical cost for basic integration starts from $1,500.
Polling via node RPC
// iOS — polling ETH transaction status via JSON-RPC
func pollTransactionStatus(txHash: String) async throws -> TransactionStatus {
let params: [AnyEncodable] = [txHash, false]
let receipt = try await ethClient.call(method: "eth_getTransactionReceipt", params: params)
if receipt == nil {
return .pending // Still in mempool
}
let confirmations = try await getConfirmationsCount(txHash: txHash)
return confirmations >= requiredConfirmations ? .confirmed : .confirmingWith(count: confirmations)
}
Why is WebSocket faster than polling?
WebSocket provides instant data transmission when a new block appears, while polling has a delay of up to 5 seconds. For critical transactions, WebSocket is the preferred choice. We help you choose the optimal option for your budget and requirements.
WebSocket subscription via Alchemy / Infura / QuickNode
// Backend — subscribing to an event via Alchemy WebSocket
const { createAlchemyWeb3 } = require("@alch/alchemy-web3");
const web3 = createAlchemyWeb3(process.env.ALCHEMY_WS_URL);
async function watchTransaction(txHash, userId) {
const subscription = web3.eth.subscribe('newBlockHeaders');
subscription.on('data', async (blockHeader) => {
const receipt = await web3.eth.getTransactionReceipt(txHash);
if (receipt) {
subscription.unsubscribe();
await updateTransactionStatus(txHash, receipt.status ? 'confirmed' : 'failed');
await sendPushNotification(userId, txHash, receipt.status);
}
});
}
How to set up transaction status tracking via WebSocket?
- Set up a WebSocket endpoint on the server, authorized by user token.
- On the client, establish a connection when navigating to the transaction list screen.
- Subscribe to events by
tx_hash— the server sends status updates. - Close the connection when the final status is received.
- Reconnect when the screen is reopened or after an error.
// Android — subscribing to transaction status via WebSocket
class TransactionStatusSocket(
private val token: String,
private val okHttpClient: OkHttpClient
) {
fun subscribe(txHash: String): Flow<TransactionStatus> = callbackFlow {
val ws = okHttpClient.newWebSocket(
Request.Builder()
.url("wss://api.yourwallet.app/ws/tx/$txHash")
.header("Authorization", "Bearer $token")
.build(),
object : WebSocketListener() {
override fun onMessage(webSocket: WebSocket, text: String) {
val status = json.decodeFromString<TransactionStatusUpdate>(text)
trySend(status.status)
if (status.isFinal) close()
}
override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) {
close(t)
}
}
)
awaitClose { ws.close(1000, "Subscription ended") }
}
}
Progress indicator for confirmations
For ETH, we show progress towards 12 confirmations. Use a ProgressView with a gradient from orange to green as the count increases. Transaction design in different statuses:
- pending — animated spinner, yellow accent
- confirming — progress bar with confirmation count
- confirmed — green checkmark, animation
- failed — red, error reason if available (revert reason from receipt)
Push notifications on status change
On final status, we send a push to the user:
{
"title": "Transaction confirmed",
"body": "0.05 ETH sent to 0x742d...3B8C",
"data": {
"screen": "transaction_detail",
"tx_hash": "0xabc123...",
"status": "confirmed"
}
}
For failed transactions, a separate template with a reason description (revert reason or dropped from mempool).
How is dropped transaction handling set up?
A transaction may disappear from the mempool if the gas price was too low. After 15–30 minutes without confirmation, the transaction is considered dropped. We need to detect this:
suspend fun checkDroppedTransactions() {
val pendingTxs = transactionDao.getPendingOlderThan(minutes = 20)
pendingTxs.forEach { tx ->
val receipt = ethClient.getTransactionReceipt(tx.hash)
if (receipt == null) {
transactionDao.updateStatus(tx.hash, TransactionStatus.DROPPED)
pushService.notifyUser(tx.userId, "Transaction did not make it into a block", tx.hash)
}
}
}
What's included in the work
Analysis of the current wallet architecture and strategy selection (polling/WebSocket/webhook). Integration with blockchain nodes (Infura, Alchemy, QuickNode) or your own node. Implementation of client-side logic: polling/WebSocket client for iOS and Android. Development of a progress bar to display confirmation count. Configuration of push notifications (APNs, FCM) on final status. Handling of dropped transactions and errors (revert reason, timeout). Testing on testnets (Goerli, Sepolia) and mainnet. Documentation and source code delivery. We also provide access to development environments, training for your team, and post-launch support.
Timelines and cost
Basic implementation of tracking with polling and push notifications takes 6–10 business days. Full cycle with WebSocket, progress bar, dropped transaction handling, and custom push takes from 2 weeks. Cost is calculated individually after project analysis. Typical cost for basic integration starts from $1,500. Contact us for a consultation and accurate estimate.
We guarantee quality and provide post-launch support. Our developers' experience is confirmed by Apple and Google certifications. Get a free consultation on tracking architecture for your crypto wallet.







