Reconcile a cross-chain transfer by tracking its source transaction, bridge message, and destination effects as separate states. A successful source receipt proves only that the source-chain transaction executed; it does not prove that the intended asset reached the intended recipient. For an integration handling team transfers, the useful question is therefore which observable condition changes the transfer from pending to complete. Bungee Bridge routes can help users compare ways to move assets across chains, while your application owns the completion rule it reports to its users.
Model completion as a state machine.
A transfer is complete only when its required destination outcome is verified. Keep transaction inclusion, bridge delivery, and any destination swap or call as distinct states; collapsing them into one boolean makes delayed execution and partial success hard to represent.
- Create a transfer record before submission. Assign an internal idempotency key and persist the source chain ID, destination chain ID, sender, recipient, input token contract, requested amount, and expected output token. Record the selected route’s bridge and any planned destination action, since a route may deliver an intermediate asset before a swap.
- Keep identifiers scoped to their chain. Use (chain ID, transaction hash) as the transaction key; a hash alone does not identify the network. Add the bridge’s message or transfer identifier when available, and preserve each destination transaction hash separately. Do not assume every bridge exposes the same message fields.
For integrations built around Socket’s routing stack, distinguish the user’s source transaction from subsequent route execution. The Socket API exposes bridge-status endpoints, and Bungee Exchange is another name you may encounter in Socket’s product context; neither should replace your own durable transfer record. Treat any aggregator status as a useful observation, then verify the outcome against the relevant chain.
Verify the source transaction before tracking delivery.
First establish whether the source transaction is pending, reverted, or included successfully. Ethereum JSON-RPC defines eth_getTransactionReceipt: a pending transaction can return null, while a receipt’s status is 0x1 for success or 0x0 for failure.
- Poll by the saved source hash. A practical starting schedule is 2 seconds, then 4, 8, and 16 seconds, capped around 30 seconds between checks; these are example intervals, not chain guarantees. Use jitter and respect your RPC provider’s rate limits. Once a receipt appears, persist its block number and block hash alongside its status.
- Wait for the finality policy your product requires. “Receipt found” and “safe to treat as settled” are different thresholds. Use the chain’s safe or finalized block tags where supported, or a chain-specific confirmation policy; a fixed count such as 12 blocks is an application choice, not a universal cross-chain standard.
Handle a reorg explicitly: if the recorded receipt disappears or its block is no longer canonical, return the source leg to pending and resume observation. Never interpret an RPC timeout or a missing receipt as a failed transaction; query again, ideally through a second provider when reliability warrants it.
Match the destination outcome to the user’s intent.
Destination completion means the intended recipient received the intended asset, or the promised destination action succeeded. A bridge message marked delivered may be insufficient if the route also performs a swap, deposit, or contract call.
- Verify the destination event or balance change. Check the destination-chain receipt and relevant token transfer logs, matching the recipient and token contract rather than relying on a symbol. For an output swap, compare the amount received with the quoted minimum or other committed condition, accounting for token decimals.
- Represent partial success honestly. For example, a team treasury transfer from Base to Optimism may deliver USDC to an intermediate address while a later swap into the treasury’s target asset reverts. Record “bridge delivered, destination swap failed,” retain the destination transaction hash, and surface the asset actually held so an operator can choose a recovery action.
Keep the identifiers needed to audit that decision together:
- Source and destination chain IDs.
- Source transaction hash and receipt status.
- Bridge message or transfer ID, when available.
- Destination transaction hash, recipient, token contract, and amount observed.
Make retries idempotent and recovery explicit.
Retry observation freely, but do not resubmit the transfer merely because destination delivery is slow. A timeout says that your observer lacks a result; it does not establish that the bridge failed or that funds are recoverable.
- Separate read retries from write retries. Use bounded exponential backoff for RPC and status queries. Submit a new source transaction only after determining that the original did not execute, or after an explicit recovery procedure establishes the safe next action.
- Escalate stalled records with evidence. After a route-specific deadline, retain the source receipt, bridge identifier, last observed status, and destination queries for investigation. Deadlines should reflect the route’s verification and settlement design; an optimistic L2 withdrawal can involve a challenge period measured in days, while other routes have different mechanisms.
The Ethereum JSON-RPC specification defines receipt observations, and Socket Data Layer’s status API documentation illustrates why message delivery and destination execution can be separate states. In practice, I mark a transfer complete only when the final destination condition is verified on-chain; otherwise I keep the most specific partial state available.