confirmGaslessRequest
Follow one accepted relay request through to on-chain reality — the opinionated layer above waitForGaslessRequest.
import { confirmGaslessRequest } from "@symmio/trading-core";
const accepted = await relayGrantDelegation(config, { account, delegatedSigner, selectors, expiryTimestamp });
const { request, txHash, receipt } = await confirmGaslessRequest(config, {
requestId: accepted.requestId,
until: "receipt",
});Where the driver reports facts — it resolves with whatever terminal it reaches — this asserts the outcome a caller is waiting for: it resolves only on succeeded, and throws for reverted / failed / rejected with the record attached to the error’s responseData.
With until: "receipt" it then waits for the receipt on this config’s own client. That is not belt-and-braces: the relayer’s succeeded is the relayer’s node’s view, and invalidating cached reads against a node that has not yet seen the block re-reads pre-state — which looks exactly like the stalled UI this whole mechanism exists to prevent.
A receipt-wait timeout is not a failure. The relayer already reported the transaction mined with status = 1; the
receipt wait is a freshness barrier on your RPC, not a source of truth. On timeout this resolves with receipt absent
rather than throwing — turning a succeeded action into an error because a public RPC lagged would be a worse bug than
the one being fixed.
Transient read failures — a 429, a 503, a dropped connection — are absorbed by the status wait underneath rather than reported as failures. Subscribe to onTransportIssue to show “status unavailable” while they last; the relay is unaffected. This never re-submits: a 202 is the point of no return.
React consumers rarely call this directly: every relay hook in @symmio/trading-react confirms by default and invalidates the reads its action changed. See the React gasless guide.
Parameters
requestIdstringrequiredStable service tracking id returned by a gasless submit.
until"terminal" | "receipt"default "terminal"optional"terminal" resolves on succeeded; "receipt" additionally waits for the receipt on this config’s client.
service"operations" | "deposits"default "operations"optionalWhich sub-service stores the request. Deposit settlements are "deposits".
receiptConfirmationsnumberdefault 1optionalConfirmations for the receipt wait. Ignored unless until: "receipt".
timeoutMsnumberdefault 120_000optionalBudget for the terminal wait (GASLESS_WAIT_TIMEOUT_MS).
receiptTimeoutMsnumberdefault 60_000optionalBudget for the receipt wait (GASLESS_RECEIPT_TIMEOUT_MS).
queuedPollMsnumberdefault 1_500optionalPoll cadence while queued.
submittedPollMsnumberdefault 3_000optionalPoll cadence after submitted.
streamSettleMsnumberdefault 1_000optionalHow long to let the status stream settle before the first HTTP read — see
waitForGaslessRequest.
streamStaleMsnumberdefault 15_000optionalHow long a delivering stream may report nothing about the workflow before one HTTP read is taken anyway.
signalAbortSignaloptionalAbort the wait, e.g. on unmount. The request keeps running server-side — an abort means nobody is watching, not that the action failed.
onUpdate(request: GaslessRequest) => voidoptionalObserver invoked with every fetched record, including the final one.
onTransportIssue(error: SymmError) => voidoptionalObserver invoked for every transient read failure the status wait absorbed — see
waitForGaslessRequest. It means
the status is temporarily unreadable, never that the request failed.
chainIdnumberoptionalChain override. Defaults to the config’s defaultChainId.
Returns
Promise<GaslessConfirmedRequest>requestGaslessRequestThe terminal record. Always succeeded — anything else threw.
txHashHashThe broadcast transaction hash.
receiptTransactionReceiptoptionalReceipt from this config’s client. Absent for until: "terminal", and absent when the receipt wait ran out of
budget.
Errors
| Code | When |
|---|---|
GASLESS_RELAY_REJECTED | The worker refused the request before any broadcast. |
GASLESS_RELAY_REVERTED | The relayed transaction mined with status = 0; all charges rolled back. |
GASLESS_RELAY_FAILED | A service or RPC failure before a successful receipt. |
GASLESS_SUCCEEDED_WITHOUT_TX | A succeeded record carried no transaction hash — a service invariant break. |
GASLESS_WAIT_ABORTED | signal aborted. Nobody is watching; the request continues. |
GASLESS_TERMINAL_TIMEOUT | The terminal budget ran out. Keep the requestId and keep watching. |
The first three carry the terminal record on responseData, so the real cause is readable without parsing a message.
Never re-submit on a terminal failure. A 202 is the point of no return — the relayer owns the intent from that
moment, and a second submit can double-execute it.