Transaction lifecycle
From signing through submission, confirmation and finality — and how status reaches you.
Transaction lifecycle
Transaction lifecycle
Track a prepared operation from signing through submission, confirmation, and finality.
Prepare once, sign what the rail asks for, then follow the operation id to a terminal state.
operationId is the stable correlation key: it is what submit takes, what GET /transaction/{id} reads, and what to keep in your own records. userOperationHash is returned only on the UserOperation rail, and transactionHash is the current outer transaction hash, which can change during replacement or recovery.
Submit is idempotent. If it times out before a response, it is safe to send the same signed payload again for the same operationId — and on the self-funded rail the same signed transaction bytes resolve to the operation they already booked. Do not prepare and sign a replacement while an operation is still active; keep polling the original operationId.
- 01
Prepare
Prepare the operation and read its rail. Keep the returned operationId — it is the stable identifier for every later call. A prepared operation is held server-side for a limited time; if it expires before submit, prepare again.
- 02
Sign what the rail returns
Sign the userOperationHash, the EIP-712 signingPayload, or the whole transaction, depending on the rail. Attach an EIP-7702 authorization only when the prepare response set authorizationRequired.
- 03
Submit and track
Submit the signature, then poll GET /transaction/{id} with the operationId. The transactionHash identifies the current outer transaction and can change when that transaction is replaced; replacementCount counts how often it has.
- 04
Confirm and finalize
Treat confirmed as mined and finalized as reorg-safe. Keep polling the same operationId if a reorg returns the operation to submitted.
Status updates
Status updates
Poll by operation id and process mirrored lifecycle fields idempotently; public webhook subscriptions are not currently available.
Use polling as the public integration contract and tolerate retried synchronization.
| Status | Meaning | Client action |
|---|---|---|
unknown | No lifecycle record has been established for this operation yet. | Keep polling by operationId before preparing a replacement operation. |
received | The operation is recorded and waiting to enter the submission queue. | Keep polling by operationId; do not create a replacement while it remains active. |
queued | The operation is queued for submission. | Keep polling by operationId; do not create a replacement while it remains active. |
submitted | The operation has a current outer transactionHash and is awaiting a mined receipt. | Keep polling by operationId because the current transactionHash can change during replacement. On the self-funded rail a reason of SPEED_UP_REQUIRED with canRetry means the account must re-sign the same nonce at a higher fee. |
confirmed | The operation was mined but has not yet reached the network's reorg-safe depth. | Do not retry; continue tracking until finalized if reorg safety matters. |
finalized | The mined operation reached the network's configured reorg-safe confirmation depth. | Do not retry; this is the successful reorg-safe state. |
failed | Execution was decided by the chain and reverted, so the operation will not advance. | Inspect the reported reason, correct the cause, then prepare and sign a new operation. |
dropped | The transaction was written off as never taken by the chain. Unlike failed, this is our verdict rather than the chain's, so it can be revised if the same bytes later land. | Prepare and sign a new operation if the action is still required. |
{
"operationId": "op_a1b2c3d4e5f6",
"status": "confirmed",
"transactionHash": "0xdef...",
"userOperationHash": "0xabc...",
"networkId": "137",
"replacementCount": 0,
"reason": null
}