SettleMint
ConceptsSettlement

Transaction Queue

The transaction queue lets an integrator submit a blockchain write once and retry it safely, without ever risking a duplicate broadcast to the chain.

Acceptance is not settlement.A submitted write is accepted by the queue, which records intent and deduplicates any retry that reuses the same idempotency key before handing the accepted operation to durable execution. Durable execution broadcasts the transaction and retries it as needed. Only once that work finishes does a terminal settlement verdict report what actually happened. Acceptance happens quickly. Settlement can take longer, and the two are never the same event.Acceptance is not settlement.The same figure as the desktop variant, drawn portrait for phone widths. A submitted write is accepted by the queue, which records intent and deduplicates a retry that reuses the same idempotency key. The queue then hands the accepted operation to durable execution, which broadcasts and retries it. Only once that work finishes does a terminal settlement verdict report what actually happened. Acceptance happens fast. Settlement can take longer, and the two are never the same moment.

The queue's own job is acceptance and deduplication. What settlement means once execution finishes belongs to the settlement verdict.

The queue deduplicates a transaction request that reaches it with the same idempotency key, sender, chain, and wallet selection within 24 hours. A route may do other work before it reaches the queue, so check that route's replay contract and the original request status before resubmitting. See Idempotent Write for the exact replay rules.

Acceptance answers immediately; settlement is the answer that counts. The queue confirms a submitted write right away, and durable execution broadcasts, confirms, and reports the outcome once the chain settles it, so a fast acceptance is never read as proof the transaction happened.

A stalled or failed transaction is recoverable, and one sender's stuck write never blocks another sender's. Ordering is scoped to a sender, chain, and organization; automatic recovery resolves transient failures, and an operator can force a retry, a failure, a cancellation, or a nonce correction when it cannot.

Why every write needs a queue

Every operation the platform performs against a ledger ends the same way: a signed write broadcast to a blockchain. Issuing supply, freezing a holding, paying a coupon, and settling a trade are all, underneath, one more write to a chain that charges gas whether the write succeeds or fails. A caller that resubmits a write because a connection dropped or a request timed out can turn one intended mint, transfer, or freeze into two. A doubled transfer is not a display bug for a regulated operator. It is a real balance change on chain, with a reconciliation gap behind it.

More than one caller can submit work for the same sender at once. An operator working in the Console, an integrating API client, and a workflow step reacting to an earlier event can all sign against the same wallet, on the same chain, in the same minute. Every write from one sender needs a nonce, the wallet's own increasing sequence number, and two writes that reuse the same nonce from the same sender cannot both land: the chain accepts one and rejects the other. Without one place that serializes that sequence per sender and chain, concurrent callers compete for the same slot instead of queuing behind it.

Every accepted instruction needs a durable record of what was asked, what was attempted, and what the chain answered, plus a path back when a transaction stalls instead of confirming. The rest of this page is that record, that ordering, and that path back.

Why one queue for the whole platform

The alternative is each domain that writes to a chain, asset issuance, custody, trading settlement, and workflow steps among them, building its own retry, nonce, and recovery logic against the chain. Each separate implementation is its own chance to double-broadcast a write or collide two nonces. A defect in one domain's retry logic rarely resembles a defect in another's, so fixing one teaches an operator little about the rest.

The platform instead funnels every on-chain write, from every domain, through this one queue. No other package broadcasts a transaction on its own. An instrument's own servicing operations queue the same way a trading venue's settled trade does; see Asset Lifecycle for the full list. One guarantee against double-broadcast and one ordering rule then applies the same way, no matter which domain asked for the write.

Acceptance is not settlement

Submitting a write to the platform gets a fast answer, but that answer is acceptance, not proof the transaction happened. The queue's job is to record the intent, make sure a retried request never turns into a second broadcast, and hand the accepted work to durable execution. What actually happened, confirmed, failed, or something in between, is reported separately once execution finishes; see Settlement Verdict for what that terminal report means.

Deduplication is the queue's other half of the promise. Once a write reaches the queue, a matching submission with the same key, sender, chain, and wallet selection within 24 hours resolves against the existing transaction request. While the work is in flight, the queue attaches to it; once it has completed, the queue reads back its recorded result. Against a transaction that failed, dead-lettered, or was cancelled, the queue refuses the duplicate key rather than replaying it. This rule does not cover work an API route performs before queue admission. Check the original outcome and transaction references before starting a new attempt.

What an operator sees, and one name not to confuse it with

An operator sees this queue in exactly one place: the Console's transaction table, an organisation-wide view across every wallet, not just the caller's own. It shows a transaction's current status, dead letter included, with a secondary line underneath for finer detail. When automatic recovery cannot resolve a stuck or failed row, an operator can step in directly rather than wait on the schedule; the levers available there are the same ones covered in What the operator API adds beyond acceptance.

The Console also has a separate operator work queue, unrelated to this page, for bond maturity, redemption approvals, and KYC review. It shares the word queue with this page's subject and nothing else; the two systems do not overlap, and a runbook about one does not apply to the other.

Ordering, delivery, and what happens when work stalls

Once a write is accepted, two more guarantees apply: where it sits in line, and what happens if it never confirms. The platform serializes execution per sender, per chain, per organisation, so a pending nonce for one sender does not reserve another sender's nonce sequence. Shared network or service capacity can still delay both.

Delivery to the chain is at-least-once, not exactly-once: the same accepted row can be resubmitted more than once over its life. The platform checks the row's state and tracks the sender's nonce to coordinate retries and replacements. Those controls do not make an independently submitted request a safe retry. A transaction can stall with no confirmation, or it can fail in a way execution already knows will not change on retry. Both eventually land on dead letter, but by different routes and on different budgets: requeued repeatedly by a reconciliation sweep that runs on a five-minute cycle in the first case, skipped straight there in the second. The recovery-path figure draws both paths, along with the one way out of dead letter once a row is there.

Transient and terminal failures take different recovery paths.A transaction anywhere in the queue's pipeline, any state before a terminal one, can fail two ways. One that fails deterministically before it ever broadcasts, an invalid request is one case, is classified immediately and dead-letters without spending any retry budget. One that stalls with no confirmation past a state-specific threshold is picked up by a periodic reconciliation sweep. That sweep requeues it if retries remain, or moves it to dead letter once the retry limit is reached. Dead letter is a true terminal state on the queue's own state machine, and the only way out is an operator forcing a retry.Transient and terminal failures take different recovery paths.The same figure as the desktop variant, drawn portrait for phone widths. A transaction anywhere in the queue's pipeline either fails deterministically, an invalid request is one case, and dead-letters immediately with no retry spent. Or it stalls past a threshold and is picked up by a periodic reconciliation sweep, which requeues it while retries remain or moves it to dead letter once they run out. Dead letter is terminal; only an operator's forced retry requeues the row.

Both routes end the same way: an operator's forced retry is the only door out of dead letter, and it treats the row as fresh rather than resuming where it stalled.

What each outcome leaves you

A transaction has four terminal states. Pending is an intermediate state, including after a synchronous wait ends. A still-pending result after your synchronous wait only means the wait budget ran out, not the work; execution continues underneath it. Completed means the chain settled the work with a recorded outcome. Execution rejects a failed transaction outright, and dead letter means recovery gave up, or hit a failure that retrying cannot fix. The two look interchangeable at a glance, but they are not quite the same, as the paragraph after the table explains. Cancellation withdraws a row before execution finishes.

What you seeWhat is still possible
Still pending after your synchronous waitRead back the status URL the response carried, until the transaction reaches a terminal state. The queue deduplicates a matching submission, but repeat the API request only when its route documents replay safety.
CompletedNothing. The row stays closed; the platform blocks a forced retry against it.
FailedAn operator can force a retry. You can submit a fresh attempt yourself under a new idempotency key.
Dead letterThe same two options as failed. The row does not requeue itself.
CancelledThe platform blocks a forced retry. A fresh attempt needs a new idempotency key.

Between force-retry and a fresh attempt, the choice turns on what you have already confirmed. A forced retry keeps the row's identity, its idempotency key included, so it is the right lever when you want the same logical operation to continue under its original name; only an operator can pull it. Before using a new key, read the original terminal state and inspect its transaction references if the chain outcome is uncertain. Do it earlier and the new key broadcasts independently, even if the original request already succeeded: exactly the hazard the FAQ on resubmitting under a new idempotency key walks through.

A forced retry is not a resume. It requeues the row from the start, clears the recorded error, and resets the retry count, so the row gets a full budget again rather than the remainder of a spent one. That is why it is an operator's decision rather than an automatic one: whatever exhausted the first budget is usually still true.

Nothing about any of this rewrites the row's past. The platform appends each forced transition to the row's own history, so the trail shows the state it came from and who moved it, and a reopened transaction stays visibly a reopened transaction.

What the operator API adds beyond acceptance

The queue admits one accepted instruction per sender, chain, and idempotency key. A second submission of the same triple is not an error: it signals that the work already exists, so the queue attaches it to that work rather than broadcasting again, following the exact replay rules in Idempotent Write. Once accepted, asynchronous is the default: the call returns immediately with a handle rather than waiting on anything. A caller can opt into a bounded synchronous wait instead, clamped by whatever time the request has left. Past that budget, or by default, the response degrades to an async-accepted handle, the transaction's identifier and a status URL to read it back with, rather than failing the call. A synchronous caller that hits its budget receives a pending result, not a rejection. The exact wait budget and its limits are in the API reference.

The platform classifies deterministic validation or contract failures separately from temporary faults. A recognized gas, account prefund, or paymaster-deposit shortfall is excluded from terminal classification so the funding flow can pause and retry after a top-up. Recovering a stuck or dead-lettered row outside its automatic recovery is an operator-only step: a force-retry, a force-fail with a recorded reason, a cancel, or a force-nonce correction, each scoped to exactly the failure mode it exists to fix.

What a stalled or failed transaction does not mean

A dead-lettered transaction is not a lost transaction. Its row and its full history persist and stay visible in the operator-facing transaction table until someone acts on it; reaching dead letter does not delete evidence of what the caller attempted. A queue timeout on a synchronous call is not a rejection either; the work continues under durable execution, and the platform hands the caller a handle to check later rather than a definitive failure. Reporting either of these as a hard failure overstates what the platform actually recorded.

The platform scopes a wallet-balance shortfall error to the caller's own resolved executor wallet, never a shared Operator Wallet funded by the platform itself and never another participant's address. That scoping is what keeps a routine gas-shortfall report from becoming an unintended disclosure of a different party's wallet identity.

Frequently asked questions

Does resubmitting under a new idempotency key ever create an unwanted duplicate?

Yes, and that is by design. The queue's protection covers a repeated key against the same sender and chain; the platform treats a new key as a new intent, not a retry, so it broadcasts on its own even if the original request already succeeded. If a caller mints a new key without first reading back the original transaction's status, the platform has no way to recognize the two as the same work, and both proceed.

Does the same idempotency key protect a retry across two different chains?

No. The queue deduplicates on the sender, the chain, and the idempotency key together. The same key on a second chain is a different triple, so it starts an independent accepted instruction there rather than attaching to the first chain's work. A caller retrying one logical operation across more than one chain needs a separate key per chain, matching the way the platform already scopes ordering.

Does forcing a retry give a failed or dead-lettered transaction a new idempotency key?

No. Force-retry initially applies only once a row has reached Failed or Dead letter; a still-stalled row keeps recovering on the automatic schedule instead. If the retry requeued the row but could not start execution, repeating force-retry on that unclaimed Queued row resumes its attempt or starts a new attempt if the earlier run ended. What it does is requeue the same row rather than create a new one, so the row keeps its original sender, chain, and idempotency key. Everything about its execution resets: state, retry count, recorded error, revert and contract or RPC error detail, the signed transaction, hash, confirmation count, and receipt, and the operator's payload overwrites its nonce and gas price. See Idempotent Write for the wallet-selection fingerprint a requeued row still carries forward unchanged.

Why can an operator reopen a failed transaction but not a completed one?

Completion means the chain accepted the work, so reopening a completed row would mean broadcasting a second transaction for something that already happened, which is exactly what the queue's replay rules exist to prevent. A failed or dead-lettered row can be requeued after its cause is resolved. Inspect the recorded transaction and chain receipt first when the actual outcome is uncertain.

  • Asset Lifecycle: The whole working life of a regulated tokenized instrument. Every servicing operation it describes, issuing supply, freezing a holding, paying a coupon, settling a trade, reaches the chain through this same queue.
  • Transaction Lifecycle: The full state vocabulary a queued transaction moves through, from acceptance to a terminal state.
  • Settlement Verdict: The terminal report the queue's accepted work resolves to once execution finishes.
  • XvP Settlement: An on-chain exchange whose legs settle together or not at all; each leg is still a write that queues and dedupes through this same spine.
  • Workflow Engine: The durable engine whose steps submit their on-chain writes through this queue for deduplication and sequencing, since replaying a workflow step does not by itself make an external write happen once.
  • Idempotent Write: The idempotency window, the wallet-selection fingerprint, and the exact replay rules behind that guarantee.
  • Operator Wallet: The platform-funded wallet a gas-shortfall error deliberately never names, as distinct from a caller's own executor wallet.

On this page