Skip to main content
The SDK exposes two complementary ways to track progress:
  • status(...) — returns a non-blocking snapshot of where an operation is.
  • wait(..., { for })blocks/polls until a specified checkpoint is reached.
Both apply to deposits and withdrawals. Use 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: a WithdrawalWaitable (e.g., from create) or the L2 tx hash Hex.
Phases 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 null immediately.
  • Default polling: 5500 ms (override via pollMs).
  • timeoutMs returns null on deadline.
withdrawals-wait.ts
Building a UI? Use status(...) to paint current phase and enable/disable the Finalize button when phase is READY_TO_FINALIZE.

Deposits

deposits.status(h | l1TxHash): Promise<DepositStatus>

Input
  • h: DepositWaitable (from create) or L1 tx hash Hex.
Phases
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 ZKsyncError of kind RPC.
  • Internal decode issue ⇒ throws ZKsyncError of kind INTERNAL.
Prefer no-throw variants if you want explicit flow control:
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_FINALIZE can take a while. Use status(...) to keep the UI responsive and wait(..., { for: 'finalized' }) only where blocking makes sense.
  • Retries: If a wait returns null due to timeoutMs, you can safely call status(...) to decide whether to keep waiting or surface guidance to the user.