Transaction Status
V2 writes return a SubmittedTransaction. A queued swap acknowledgement has
mode === 'queued', result === undefined, its request transactionId when
provided, and a durable uniqueKey. It proves acceptance into the queue, not
execution. Liquidity writes remain executed gateway writes whose confirmation
re-reads the affected position. There is no PendingTransaction, bundle ID, or
.wait() API. To watch committed swaps and liquidity changes as they happen, use the
realtime stream.
const tx = await gSwap.swaps.swap('GALA', 'GUSDC', 3000, { exactIn: '10' });
console.log('Correlation key:', tx.uniqueKey);
console.log('Request mode:', tx.mode);
console.log('Request transaction ID:', tx.transactionId ?? '(not reported)');
const applied = await tx.confirm();
console.log('Applied trade:', applied);
For a queued swap, confirm() polls:
GET {dexBackend}/v1/chain/apply-results/{uniqueKey}?channel=asset&contract=dex-contract
The confirmation policy treats these responses as follows:
| Response | Meaning and client action |
|---|---|
200, Status: 1 | Terminal success; return the AppliedTrade from Data. |
200, Status: 0 | Terminal chain rejection; throw CHAIN_REJECTED with params.errorKey = ErrorKey and params.serverMessage = Message. |
404 | Outcome unresolved (or the result expired after 7 days); keep polling until the deadline. |
429 | Outcome unresolved; honor retry-after and keep polling. |
5xx | Upstream trouble; keep polling until the deadline. |
400 (any other 4xx except 404 and 429) | Terminal: throw CONFIRMATION_FAILED with params.status. The outcome is unknown (the write may still apply); do not treat it as a rejection. |
200 with a body that is not an apply result, or one for another key | CONFIRMATION_MALFORMED / CONFIRMATION_KEY_MISMATCH: unknown outcome. |
ConfirmOptions has timeoutMs default 60_000, pollIntervalMs default
2_000 with a minimum of 500, and initialDelayMs default 3_000 for a
queued swap (0 for liquidity writes). Poll backoff is jittered and capped at
8 seconds. CONFIRMATION_TIMEOUT means the outcome is unknown: the trade may
still apply, so confirm the same uniqueKey again later; results are retained
for 7 days. Do not resubmit.
Pass signal (an AbortSignal) to cancel a wait or an in-flight read; the
confirmation then throws CONFIRMATION_ABORTED, which also leaves the outcome
unknown. A queued swap's errors are AppliedTradeErrors (a GSwapSDKError
subclass); see App and Wallet Integration for the
standalone confirmAppliedTrade.
Persist the uniqueKey. Any time you no longer hold the SubmittedTransaction
(a timeout you gave up on, a process restart, a 409 replay conflict), resolve
the outcome from the key alone:
const applied = await gSwap.swaps.confirmSwap(uniqueKey, { timeoutMs: 30_000 });
confirmSwap() reads the same apply-results record, starts immediately, and
resolves the AppliedTrade or throws the chain's rejection.
Liquidity writes use the same SubmittedTransaction abstraction, but confirm
by re-reading the affected position because position writes may not have an
apply-result row. Use the canonical position identity:
token0, token1, fee, owner, tickLower, and tickUpper. A re-read that
fails is the write's failure, never the read's (the write may be applied): a
terminal HTTP status is CONFIRMATION_FAILED, an unusable position answer
CONFIRMATION_MALFORMED, and anything else (no answer, a 5xx, 404, 408, 429) is
read again until the deadline, then CONFIRMATION_TIMEOUT with the last read
error as cause. Each carries the write's uniqueKey: confirm again, never
resubmit.
The submit request can time out with SUBMISSION_OUTCOME_UNKNOWN; confirm the
original uniqueKey before taking any action. A 409 replay conflict with
CHAIN_DISPATCH_FAILED means that key was already consumed; confirm the
original key and do not retry with a new one.