Confirmation and retries
Confirm transactions and decide when to resubmit.
Acceptance is not landing
A successful submission acknowledges admission and dispatch, not an on-chain result:
| Submission | Acknowledgment means |
|---|---|
| Hosted single transaction | SWQoS queued a write to at least one leader or engine path, or suppressed a duplicate it already sent. |
| Hosted bundle | SWQoS queued at least one engine leg. The engine's later acceptance or rejection is asynchronous. |
| Local agent | A regional or direct path took the transaction, under the agent's acceptance rules. |
| QUIC datagram, unidirectional stream or IPC without a reply | No acknowledgment exists. |
None of these proves the signature is valid, the transaction can execute, an engine accepted it, or it landed. A submitted transaction can land successfully, land with an execution error, expire, or belong to a fork your chosen commitment does not retain.
Routing
Single transactions may use leader and block-engine delivery; bundles use block engines only. A response does not identify which path will land.
No periodic resubmission
SWQoS does not periodically resend accepted transactions or bundles. maxRetries is ignored. Your application owns confirmation and later resubmission.
Duplicate suppression
A region may accept a repeated single transaction without sending it again. A concurrent duplicate can instead return rate_limited without a retry delay.
Do not rely on this as global idempotency. Explicit bundle resubmissions are not suppressed, even though they return the same bundle id.
Confirm through your Solana RPC
Keep the first signature of each signed transaction before you send. Poll getSignatureStatuses, or subscribe to signature notifications, on your read RPC provider. Check both the execution error and the commitment. getSlot on SWQoS is a routing clock, not a confirmation check.
For a recent-blockhash transaction, retain the lastValidBlockHeight returned with the blockhash used to sign it. If the chain passes that height and no landing is recorded, the transaction cannot newly execute with that blockhash. Rebuild and sign with a fresh blockhash only after checking the original outcome. A durable nonce has a different lifetime: check the nonce account and original signature before advancing or replacing it.
For a bundle, check every customer signature. SWQoS has no bundle-status API, and its bundle id is not a third-party engine's status id. Do not assume that seeing one member on chain proves which submission path delivered it if you sent members separately.
import { setTimeout as sleep } from 'node:timers/promises'
import { createSolanaRpc, type Signature } from '@solana/kit'
export async function waitForConfirmation(
rpcUrl: string,
signature: Signature,
lastValidBlockHeight: bigint,
): Promise<void> {
const rpc = createSolanaRpc(rpcUrl)
for (;;) {
const { value: [status] } = await rpc
.getSignatureStatuses([signature], { searchTransactionHistory: true })
.send()
if (status?.err) throw new Error(`transaction failed: ${JSON.stringify(status.err)}`)
if (status?.confirmationStatus === 'confirmed' || status?.confirmationStatus === 'finalized') {
return
}
const height = await rpc.getBlockHeight({ commitment: 'confirmed' }).send()
if (!status && height > lastValidBlockHeight) {
throw new Error('blockhash expired with no recorded landing')
}
await sleep(500)
}
}Pass the signature and last valid height from the transaction you actually signed. This example waits for confirmed or finalized and does not resend.
Decide whether to retry
| Situation | Action |
|---|---|
Structured refusal with retryable: true | Resubmit unchanged after retry_after_ms when supplied, while the signed lifetime remains valid. |
Structured refusal with retryable: false | Fix the cause or settle the invoice. A blind retry does not fix the request. |
| Accepted, but not yet confirmed | Check the signature and lifetime. You may resubmit the same signed bytes while valid; a same-region duplicate may be suppressed. |
| Timeout or lost connection before a reply | The request may already have been sent. Check the signature before deciding to resubmit. |
| Local agent rejection | A direct leader write may have happened before the region refused it. Follow the local rejection rules. |
| Expired recent blockhash | Check the original outcome, then rebuild and re-sign if your application still needs the action. |
Resubmissions can consume rate allowance. Solana prevents the same signed transaction from executing twice, but a new blockhash produces a new signature and can repeat the action. For declared tips, increasing the tip on a repeated signature can increase the charge.