> ## Documentation Index
> Fetch the complete documentation index at: https://v3.docs.derive.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Process Deposits & Withdrawals

> The request-and-settle flow: shareholders queue signed intents; the curator settles each by minting or burning shares at a quoted price.

You can choose when to process user deposit & withdrawal requests. The protocol intentionally
gives this flexibility to the curator to allow for a wide variety of vault strategies.
For example, a covered call vault may not be able to provide exit liquidity at all times.

However, curators must process withdrawals within a 14 days, failure to do so may put the vault
at the risk of being frozen and delisted.

<Note>All of the steps in this guide can be done through the UX or SDKs.</Note>

<Steps>
  <Step title="Shareholder submits an intent">
    A signed deposit or withdrawal request lands in the vault's queue. Deposits hold the funds on the shareholder's
    source subaccount until settled or cancelled.
  </Step>

  <Step title="Curator quotes and settles">
    You poll the queue, pick a share price, and sign a mint (deposit) or burn (withdrawal) approval bound to that exact
    request.
  </Step>

  <Step title="Protocol executes">
    The sequencer re-verifies your approval, checks your quoted price against the vault's own mark-to-market price,
    mints/burns shares, and moves the funds.
  </Step>
</Steps>

## The shareholder side

You'll want this to test your vault end-to-end, and to build a deposit UI. From a
shareholder's wallet:

<CodeGroup>
  ```typescript TypeScript (SDK) theme={null}
  const mySubaccountId = 5678;

  // The deposit asset must equal the vault's — read it off the vault row
  // instead of hardcoding an address.
  const vault = await client.vaults.getVault(vaultId);

  await client.vaults.shareholder.requestDeposit({
    subaccountId: mySubaccountId, // the funds' source (the intent is signed on it)
    vaultSubaccountId: vaultId,
    depositSpotAsset: vault.protocol.config.deposit_spot_asset,
    amount: '5000',
  });

  await client.vaults.shareholder.requestWithdraw({
    subaccountId: mySubaccountId, // destination for the redeemed funds
    vaultSubaccountId: vaultId,
    sharesToBurn: '1000',
  });
  ```

  ```python Python (SDK) theme={null}
  # Coming soon.
  ```

  ```rust Rust (SDK) theme={null}
  // Coming soon.
  ```

  ```bash cURL theme={null}
  # Body nonce/signature: EIP-712 action signing (see /action-signing).
  # X-Derive* headers: session auth (see /json-rpc).
  curl -X POST https://api.derive.xyz/v3/private/request_vault_deposit \
    -H "Content-Type: application/json" \
    -H "X-DeriveWallet: $WALLET_ADDRESS" \
    -H "X-DeriveTimestamp: $TS" \
    -H "X-DeriveSignature: $SIG" \
    -d '{
      "subaccount_id": 5678,
      "nonce": "1751558400000900000",
      "signature_expiry_sec": 1751559000,
      "signer": "0xHOLDER…",
      "signature": "0x…",
      "vault_subaccount_id": 42,
      "deposit_spot_asset": "0xUSDC…",
      "amount": "5000"
    }'

  curl -X POST https://api.derive.xyz/v3/private/request_vault_withdraw \
    -H "Content-Type: application/json" \
    -H "X-DeriveWallet: $WALLET_ADDRESS" \
    -H "X-DeriveTimestamp: $TS" \
    -H "X-DeriveSignature: $SIG" \
    -d '{
      "subaccount_id": 5678,
      "nonce": "1751558400000950000",
      "signature_expiry_sec": 1751559000,
      "signer": "0xHOLDER…",
      "signature": "0x…",
      "vault_subaccount_id": 42,
      "shares_to_burn": "1000"
    }'
  ```
</CodeGroup>

<CodeGroup>
  ```typescript TypeScript (SDK) theme={null}
  // Intents wait in the queue until the curator settles them; they can be
  // cancelled at any point before that (this drains ALL of the wallet's
  // pending requests for the vault, deposits and withdrawals alike).
  const live = await client.vaults.shareholder.getLiveRequests();
  await client.vaults.shareholder.cancelAllRequests({
    subaccountId: mySubaccountId,
    vaultSubaccountId: vaultId,
  });

  // Share balances only change once the curator settles.
  const holdings = await client.vaults.shareholder.getShares();
  const history = await client.vaults.shareholder.getRequestHistory({
    pageSize: 20,
  });
  ```

  ```python Python (SDK) theme={null}
  # Coming soon.
  ```

  ```rust Rust (SDK) theme={null}
  // Coming soon.
  ```

  ```bash cURL theme={null}
  # Reads are keyed by wallet; every private call carries the same X-Derive* session headers.
  curl -X POST https://api.derive.xyz/v3/private/get_live_vault_requests \
    -H "Content-Type: application/json" \
    -H "X-DeriveWallet: $WALLET_ADDRESS" \
    -H "X-DeriveTimestamp: $TS" \
    -H "X-DeriveSignature: $SIG" \
    -d '{ "wallet": "0xHOLDER…" }'

  # Cancel is a signed action (nonce/signature via /action-signing):
  curl -X POST https://api.derive.xyz/v3/private/cancel_all_vault_requests \
    -H "Content-Type: application/json" \
    -H "X-DeriveWallet: $WALLET_ADDRESS" \
    -H "X-DeriveTimestamp: $TS" \
    -H "X-DeriveSignature: $SIG" \
    -d '{
      "subaccount_id": 5678,
      "nonce": "1751558400000960000",
      "signature_expiry_sec": 1751559000,
      "signer": "0xHOLDER…",
      "signature": "0x…",
      "vault_subaccount_id": 42
    }'

  curl -X POST https://api.derive.xyz/v3/private/get_vault_shares \
    -H "Content-Type: application/json" \
    -H "X-DeriveWallet: $WALLET_ADDRESS" \
    -H "X-DeriveTimestamp: $TS" \
    -H "X-DeriveSignature: $SIG" \
    -d '{ "wallet": "0xHOLDER…" }'

  curl -X POST https://api.derive.xyz/v3/private/get_vault_request_history \
    -H "Content-Type: application/json" \
    -H "X-DeriveWallet: $WALLET_ADDRESS" \
    -H "X-DeriveTimestamp: $TS" \
    -H "X-DeriveSignature: $SIG" \
    -d '{ "wallet": "0xHOLDER…", "page_size": 20 }'
  ```
</CodeGroup>

<Note>
  Withdrawals are blocked until the vault's `cooldownSec` has elapsed since the holder's **last deposit**
  (`vault_cooldown_active`, 18011). Intent signatures default to a 10-minute validity in the SDK — pass
  `signatureExpirySec` to extend it (the API caps it at 30 days out); an intent whose signature lapses before you settle
  it expires.
</Note>

## The settle loop

Queued intents sit in two per-vault FIFO queues. There is **no WebSocket channel** for
them — poll, then settle. A settle approval is bound to one exact request by its
**user-action hash**, so you cannot pair a price with the wrong request.

<Note>
  Your quote is bounded on both sides by the vault's immutable `maxSlippageBps` against the protocol's mtm-derived
  price.
</Note>

<Steps>
  <Step title="Poll the queues">
    `getLiveMintRequests` (pending deposits) and `getLiveBurnRequests` (pending withdrawals) return a FIFO page of
    requests plus the queue's total length. Each request carries a composite `id` and the `user_action_hash` your
    approval commits to.
  </Step>

  <Step title="Pick a share price">
    Read the vault and quote at (or near) `simulated_share_price_usd` — the live price a depositor faces with your fees
    settled. The protocol rejects a quote outside `maxSlippageBps` of its own mtm price.
  </Step>

  <Step title="Settle each request">
    `mintShares` settles a deposit; `burnShares` settles a withdrawal. Both are signed on the vault subaccount and bound
    to the request's hash.
  </Step>
</Steps>

<CodeGroup>
  ```typescript TypeScript (SDK) theme={null}
  const curator = client.vaults.curator;

  const { requests } = await curator.getLiveMintRequests(vaultId);
  for (const request of requests) {
    // Unset means the vault cannot be priced right now — retry later.
    const { simulated_share_price_usd } = await client.vaults.getVault(vaultId);
    if (simulated_share_price_usd == null) break;

    await curator.mintShares({
      vaultSubaccountId: vaultId,
      sharePrice: simulated_share_price_usd,
      depositHash: request.user_action_hash, // binds the approval to this exact request
      requestId: request.id,
    });
  }
  ```

  ```python Python (SDK) theme={null}
  # Coming soon.
  ```

  ```rust Rust (SDK) theme={null}
  // Coming soon.
  ```

  ```bash cURL theme={null}
  curl -X POST https://api.derive.xyz/v3/private/get_live_mint_requests \
    -H "Content-Type: application/json" \
    -H "X-DeriveWallet: $WALLET_ADDRESS" \
    -H "X-DeriveTimestamp: $TS" \
    -H "X-DeriveSignature: $SIG" \
    -d '{ "subaccount_id": 42, "limit": 100 }'

  # Quote from public/get_vault (simulated_share_price_usd), then settle.
  # Body nonce/signature: EIP-712 action signing on the vault subaccount.
  curl -X POST https://api.derive.xyz/v3/private/mint_vault_shares \
    -H "Content-Type: application/json" \
    -H "X-DeriveWallet: $WALLET_ADDRESS" \
    -H "X-DeriveTimestamp: $TS" \
    -H "X-DeriveSignature: $SIG" \
    -d '{
      "subaccount_id": 42,
      "nonce": "1751558411000001000",
      "signature_expiry_sec": 1751558711,
      "signer": "0xCURATOR…",
      "signature": "0x…",
      "share_price": "1.02",
      "deposit_hash": "0xabc123…",
      "request_id": { "vault_subaccount_id": 42, "wallet": "0xHOLDER…", "vault_nonce": "1751558400000900000" }
    }'
  ```
</CodeGroup>

<CodeGroup>
  ```typescript TypeScript (SDK) theme={null}
  const burns = await curator.getLiveBurnRequests(vaultId);
  for (const request of burns.requests) {
    const { simulated_share_price_usd } = await client.vaults.getVault(vaultId);
    if (simulated_share_price_usd == null) break;

    await curator.burnShares({
      vaultSubaccountId: vaultId,
      sharePrice: simulated_share_price_usd,
      withdrawHash: request.user_action_hash,
      requestId: request.id,
    });
  }
  ```

  ```python Python (SDK) theme={null}
  # Coming soon.
  ```

  ```rust Rust (SDK) theme={null}
  // Coming soon.
  ```

  ```bash cURL theme={null}
  curl -X POST https://api.derive.xyz/v3/private/get_live_burn_requests \
    -H "Content-Type: application/json" \
    -H "X-DeriveWallet: $WALLET_ADDRESS" \
    -H "X-DeriveTimestamp: $TS" \
    -H "X-DeriveSignature: $SIG" \
    -d '{ "subaccount_id": 42, "limit": 100 }'

  curl -X POST https://api.derive.xyz/v3/private/burn_vault_shares \
    -H "Content-Type: application/json" \
    -H "X-DeriveWallet: $WALLET_ADDRESS" \
    -H "X-DeriveTimestamp: $TS" \
    -H "X-DeriveSignature: $SIG" \
    -d '{
      "subaccount_id": 42,
      "nonce": "1751558412000002000",
      "signature_expiry_sec": 1751558712,
      "signer": "0xCURATOR…",
      "signature": "0x…",
      "share_price": "1.02",
      "withdraw_hash": "0xdef456…",
      "request_id": { "vault_subaccount_id": 42, "wallet": "0xHOLDER…", "vault_nonce": "1751558400000950000" }
    }'
  ```
</CodeGroup>

<Warning>
  Before a burn settles, make sure the vault subaccount holds enough of the deposit asset to pay the redemption — you
  may need to [unwind positions](/vaults/trade) first. The redemption moves funds out of the vault subaccount at settle
  time.
</Warning>

<Tip>
  Don't want a deposit? `curator.rejectDepositRequest(request.id, 'reason')` pops it off the queue and releases the
  holder's funds with no on-chain settle. The reason is optional and capped at 20 characters.
</Tip>

## Request lifecycle

Every request moves through these statuses:

| Status              | Meaning                                                             |
| ------------------- | ------------------------------------------------------------------- |
| `enqueued`          | Waiting in the FIFO queue for the curator.                          |
| `sequencer_applied` | Settled — the mint/burn executed.                                   |
| `user_cancel`       | The shareholder cancelled it (`cancelAllRequests`).                 |
| `curator_reject`    | You rejected the deposit (`rejectDepositRequest`).                  |
| `protocol_reject`   | The settle failed a protocol check (slippage, margin, cooldown, …). |
| `expired`           | The intent's signature expiry passed before it was settled.         |

Shareholders see the full status trail via `getRequestHistory`; the settled events are
public in `getActionHistory`.

## Reading vault state

All unauthenticated and read-only, on `client.vaults`:

| Method                  | Returns                                                                                                                   |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| `getVault`              | Full row for one vault: on-chain state, config, live `nav_usd`, `simulated_share_price_usd`, `curator_shares`, benchmark. |
| `listVaults`            | Every vault, paginated.                                                                                                   |
| `getActionHistory`      | Settled deposit / withdrawal / fee-accrual / cancel events with the fee-share split.                                      |
| `getPerformanceHistory` | Sampled NAV / share-price / HWM time series (`1h`, `8h`, `24h`, `1wk`).                                                   |

`getVault` is the one you poll while settling — `simulated_share_price_usd` is your
quote anchor, and `nav_usd` is negative if the vault is insolvent.

<CardGroup cols={2}>
  <Card title="Trade" icon="chart-line" href="/vaults/trade">
    Keep enough of the deposit asset liquid to pay redemptions.
  </Card>

  <Card title="Fees" icon="percent" href="/vaults/fees">
    Every settle here is also when your fees are minted.
  </Card>
</CardGroup>


## Related topics

- [Create a Vault](/vaults/create-a-vault.md)
- [Trade](/vaults/trade.md)
- [Fees](/vaults/fees.md)
