A cross-chain swap is complete only when the destination action has succeeded and its result is sufficiently final for your application. If your user sees a source transaction hash but no destination tokens yet, treat the transfer as an asynchronous workflow: track each stage, explain what is known, and avoid reporting success early.
Model a swap with distinct states such as submitted, source_confirmed, in_transit, destination_executed, and complete. A source transaction being accepted proves only that the source chain recorded the request; it does not prove that the destination chain has delivered the expected asset.
Store a durable record for every intent: a stable application request ID, source and destination chain identifiers, sender, recipient, input asset and amount, expected output asset, and each known transaction hash or protocol message ID. Use the request ID as your internal correlation key, since different routes can expose different on-chain identifiers.
For an integration that routes across several chains, define a normalized status API above route-specific adapters. Rango Bridge is a concrete example of a service that can select routes across networks; an integrator should still map the route’s observable events into their own stable status model. Keep the raw route data too, so support and reconciliation can inspect the original evidence.
The route mechanism determines what “in transit” means and which event advances the state. For an IBC transfer, the source chain commits a packet; a relayer submits it to the destination, where the receiving application processes it and writes an acknowledgement. A relayer then returns that acknowledgement to the source. Your adapter should distinguish packet receipt from acknowledgement, since the two are different points in the packet lifecycle.
For an Axelar General Message Passing call, the source contract emits a cross-chain call, validators approve it, and an executor submits it to the destination gateway and application. A source event therefore means the message was dispatched, not that the destination contract ran successfully. Advance to destination execution only after verifying the destination transaction and the application-level outcome.
Put two cases side by side in your implementation: an IBC packet should be reconciled through its packet sequence, destination receipt, and acknowledgement or timeout; an Axelar call should be reconciled through its source call ID and destination execution result. Normalize both to your app’s states, but don’t make one protocol’s evidence stand in for the other’s.
Rango Bridge may return a multi-leg route, so represent each leg separately and mark the overall request complete only when every required leg has settled. A completed intermediate swap is progress, not proof that the final recipient received the destination asset. This distinction matters when a route fails after one leg succeeds and another remains pending.
Mark a transaction confirmed only after the relevant chain includes it, then apply a finality policy suited to that chain and the value at risk. There is no universal confirmation count: chain consensus and reorganization risk determine the wait. Keep “included” and “final” separate if your application acts on high-value transfers or credits balances automatically.
A timeout is a protocol outcome, not a synonym for “slow.” On IBC, a packet can time out when its configured height or timestamp passes without successful receipt, subject to the protocol’s proof requirements. A slow relayer or congested destination may delay a status update without making the packet refundable, so do not invite users to resubmit funds just because a timer has elapsed.
Retries should be idempotent: use a unique request ID and enforce one application-level settlement per request. If your indexer restarts or receives the same event twice, it should update the existing record rather than create a second credit. Reconcile periodically against chain data, and preserve an auditable history of state changes instead of overwriting the evidence.
Keep one short safety check in the user flow: verify the destination recipient and expected asset before treating a route as complete. For Rango Bridge integrations, show users the source transaction and the latest verified destination state, while making clear when the destination result has not yet been observed.
For each state change, record its source: a transaction receipt, packet acknowledgement, timeout proof, or destination execution result. Include the relevant chain and transaction identifiers in your internal logs. When evidence is missing or contradictory, keep the request pending or flag it for review instead of silently upgrading it to complete.