status(...)— returns a non-blocking snapshot of where an operation is.wait(..., { for })— blocks/polls until a specified checkpoint is reached.
status(...) for UI refreshes; use wait(...) when you need to gate logic on inclusion/finality.
You can pass either a handle returned from
create(...) or a raw transaction hash.Withdrawals
withdrawals.status(h | l2TxHash): Promise<WithdrawalStatus>
Input
h: aWithdrawalWaitable(e.g., fromcreate) or the L2 tx hashHex.
Notes
- No L2 receipt ⇒
L2_PENDING. - Finalization key derivable but not ready ⇒
PENDING. - Already finalized ⇒
FINALIZED.
withdrawals-status.ts
withdrawals.wait(h | l2TxHash, { for, pollMs?, timeoutMs? })
Targets
Behavior
- If the handle has no L2 hash, returns
nullimmediately. - Default polling: 5500 ms (override via
pollMs). timeoutMsreturnsnullon deadline.
withdrawals-wait.ts
Deposits
deposits.status(h | l1TxHash): Promise<DepositStatus>
Input
h:DepositWaitable(fromcreate) or L1 tx hashHex.
deposits-status.ts
deposits.wait(h | l1TxHash, { for: 'l1' | 'l2' })
Targets
deposits-wait.ts
wait(..., { for: 'l2' }) waits for both L1 inclusion and canonical L2 execution.Practical patterns
Pick the right tool
- Use
status(...)for poll-less UI refreshes (e.g., on page focus or interval timers you control). - Use
wait(...)for workflow gating (scripts, jobs, “continue when X happens”).
Timeouts & polling
polling.ts
Error handling
- Network hiccup while fetching receipts ⇒ throws
ZKsyncErrorof kindRPC. - Internal decode issue ⇒ throws
ZKsyncErrorof kindINTERNAL.
no-throw.ts
Tips & edge cases
- Handles vs hashes: Passing a handle without the relevant hash yields
UNKNOWN/null. If you already have a hash, pass the hash directly. - Finalization windows: For withdrawals,
READY_TO_FINALIZEcan take a while. Usestatus(...)to keep the UI responsive andwait(..., { for: 'finalized' })only where blocking makes sense. - Retries: If a wait returns
nulldue totimeoutMs, you can safely callstatus(...)to decide whether to keep waiting or surface guidance to the user.