Tracking Status
The server derives the recipe status from on-chain evidence at the SRA: deposits seen, bridges sent, executions settled. The server does not assert a status. The status stays correct when funds arrive late or when a retry occurs.
Lifecycle
PENDING → BRIDGING → EXECUTING → COMPLETED
→ FAILED
PENDING (no funds within 1h) → ABANDONEDtype RecipeState =
| "PENDING" // quote issued, SRA not yet funded
| "BRIDGING" // funds received, bridge in flight (cross-chain only)
| "EXECUTING" // destination action in progress
| "COMPLETED"
| "FAILED" // carries failureReason
| "ABANDONED"; // the SRA received no funds within 1 hour after the quoteAn ABANDONED recipe is not locked. Funds that arrive late still execute. A new watchStatus call picks the recipe up again from live evidence.
watchStatus
The SDK polls the server, with backoff. Polling stops on a terminal state (COMPLETED / FAILED / ABANDONED).
const watcher = sr.watchStatus(quote.sra, {
interval: 4000, // ms; default 4000
timeout: 600_000, // total watch bound, default 10 min; 0 = poll indefinitely
maxRetries: 5, // consecutive poll failures tolerated; default 5
onStatusChange: (s) => console.log(s.state),
onError: (e) => console.error(e), // persistent poll failure or timeout
});
await watcher.done; // resolves on terminal state / unsubscribe, rejects on persistent failure
watcher.stop(); // or call watcher() - unsubscribegetStatus
Use getStatus for one read of the same data:
const status = await sr.getStatus(sra);
// status.state - RecipeState
// status.deposits - per-deposit evidence: deposit tx, bridge tx, execution tx
// status.failureReason - the first deposit error when state === 'FAILED'Recovering funds
There is no on-chain refund fallback. When the destination action reverts, the funds stay in the SRA. The SRA is non-custodial. Only the owner can recover the funds. getWithdrawCalls returns the recovery calls for the owner to sign:
const { data, receiver } = await sr.getWithdrawCalls({
sra,
tokens: [{ chainId: 42161, token: "0xTOKEN" }],
});
for (const { chainId, calls } of data) {
for (const call of calls) {
await wallet.sendTransaction({ ...call, chainId, value: BigInt(call.value) });
}
}Other SRA reads
sr.getSraInfo({ sra }) // the stored routing config: owner, actions, src tokens, slippage
sr.getSraFeeEstimates({ sra }) // per-chain bridge fee estimates (incl. sponsored entries)
sr.getDepositStatus({ sra, owner, destChainId, vaultId })
// deposit phase (pending/bridging/deposited/failed) + vault balance