> ## Documentation Index
> Fetch the complete documentation index at: https://zksync-sdk.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Status vs Wait

> Snapshot progress with `status(...)` or block until a checkpoint with `wait(..., { for })` for deposits and withdrawals.

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.

<Note>
  You can pass **either** a handle returned from `create(...)` **or** a raw transaction hash.
</Note>

## Withdrawals

### `withdrawals.status(h | l2TxHash): Promise<WithdrawalStatus>`

**Input**

* `h`: a `WithdrawalWaitable` (e.g., from `create`) **or** the L2 tx hash `Hex`.

**Phases**

| Phase               | Meaning                                           |
| ------------------- | ------------------------------------------------- |
| `UNKNOWN`           | Handle doesn’t contain an L2 hash yet.            |
| `L2_PENDING`        | L2 tx not yet included.                           |
| `PENDING`           | L2 included, **not** yet ready to finalize on L1. |
| `READY_TO_FINALIZE` | Finalization on L1 would succeed now.             |
| `FINALIZED`         | Finalized on L1; funds released.                  |

**Notes**

* No L2 receipt ⇒ `L2_PENDING`.
* Finalization key derivable but not ready ⇒ `PENDING`.
* Already finalized ⇒ `FINALIZED`.

```ts withdrawals-status.ts theme={null} theme={"theme":{"light":"vitesse-light","dark":"tokyo-night"}}
const s = await sdk.withdrawals.status(handleOrHash);
// s.phase ∈ 'UNKNOWN' | 'L2_PENDING' | 'PENDING' | 'READY_TO_FINALIZE' | 'FINALIZED'
```

### `withdrawals.wait(h | l2TxHash, { for, pollMs?, timeoutMs? })`

**Targets**

| Target                 | Resolves with                                                               |
| ---------------------- | --------------------------------------------------------------------------- |
| `{ for: 'l2' }`        | **L2 receipt** (`TransactionReceipt \| null`)                               |
| `{ for: 'ready' }`     | **`null`** when finalization becomes possible                               |
| `{ for: 'finalized' }` | **L1 receipt** when finalized, or `null` if finalized but receipt not found |

**Behavior**

* If the handle has **no L2 hash**, returns `null` immediately.
* Default polling: **5500 ms** (override via `pollMs`).
* `timeoutMs` returns `null` on deadline.

```ts withdrawals-wait.ts theme={null} theme={"theme":{"light":"vitesse-light","dark":"tokyo-night"}}
// Wait for L2 inclusion → get L2 receipt (augmented with l2ToL1Logs if available)
const l2Rcpt = await sdk.withdrawals.wait(handle, { for: 'l2', pollMs: 5000 });

// Wait until it becomes finalizable (no side effects)
await sdk.withdrawals.wait(handle, { for: 'ready' });

// Wait for L1 finalization → L1 receipt (or null if not retrievable)
const l1Rcpt = await sdk.withdrawals.wait(handle, { for: 'finalized', timeoutMs: 15 * 60_000 });
```

<Tip>
  Building a UI? Use `status(...)` to paint current phase and enable/disable the **Finalize** button
  when phase is `READY_TO_FINALIZE`.
</Tip>

## Deposits

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

**Input**

* `h`: `DepositWaitable` (from `create`) **or** L1 tx hash `Hex`.

**Phases**

| Phase         | Meaning                                           |
| ------------- | ------------------------------------------------- |
| `UNKNOWN`     | No L1 hash present on the handle.                 |
| `L1_PENDING`  | L1 receipt missing.                               |
| `L1_INCLUDED` | L1 included; L2 hash not yet derivable from logs. |
| `L2_PENDING`  | L2 hash known but L2 receipt missing.             |
| `L2_EXECUTED` | L2 receipt present with `status === 1`.           |
| `L2_FAILED`   | L2 receipt present with `status !== 1`.           |

```ts deposits-status.ts theme={null} theme={"theme":{"light":"vitesse-light","dark":"tokyo-night"}}
const s = await sdk.deposits.status(handleOrL1Hash);
// s.phase ∈ 'UNKNOWN' | 'L1_PENDING' | 'L1_INCLUDED' | 'L2_PENDING' | 'L2_EXECUTED' | 'L2_FAILED'
```

### `deposits.wait(h | l1TxHash, { for: 'l1' | 'l2' })`

**Targets**

| Target          | Resolves with                                                       |
| --------------- | ------------------------------------------------------------------- |
| `{ for: 'l1' }` | **L1 receipt** or `null`                                            |
| `{ for: 'l2' }` | **L2 receipt** or `null` (waits L1 inclusion **then** L2 execution) |

```ts deposits-wait.ts theme={null} theme={"theme":{"light":"vitesse-light","dark":"tokyo-night"}}
const l1Rcpt = await sdk.deposits.wait(handle, { for: 'l1' });
const l2Rcpt = await sdk.deposits.wait(handle, { for: 'l2' });
```

<Note>
  `wait(..., { for: 'l2' })` waits for both **L1 inclusion** and **canonical L2 execution**.
</Note>

## 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

```ts polling.ts theme={null} theme={"theme":{"light":"vitesse-light","dark":"tokyo-night"}}
const ready = await sdk.withdrawals.wait(handle, {
  for: 'ready',
  pollMs: 5500, // minimum enforced internally
  timeoutMs: 30 * 60_000, // 30 minutes; returns null on deadline
});
if (ready === null) {
  // timeout or not yet finalizable — decide whether to retry or show a hint
}
```

### 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:

```ts no-throw.ts theme={null} theme={"theme":{"light":"vitesse-light","dark":"tokyo-night"}}
const r = await sdk.withdrawals.tryWait(handle, { for: 'finalized' });
if (!r.ok) {
  console.error('Finalize wait failed:', r.error);
} else {
  console.log('Finalized L1 receipt:', r.value);
}
```

## 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.
