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

# Withdrawals

> Per-asset and per-route withdrawals from Lighter deployments

Lighter withdrawals are authorized by the provider plugin's `SDK` signer through a WASM blob; the user's wallet is not prompted. The same normalized flow applies to `lighter` and `lighter-rh`, while each instance owns its asset catalogue, collateral, endpoints, and signing configuration.

## Discover valid selections

Call `getWithdrawableBalances()` and render exactly the rows it returns:

```typescript theme={null}
const rows = await perps.getWithdrawableBalances({
  provider: 'lighter',
  address: userAddress,
});

// One row per asset and balance route.
// { asset, route: 'perps' | 'spot', available }
```

The SDK joins the venue's balances with `/assets`, filters zero and sub-minimum rows, and attaches each asset's `decimals`, L1 address, and `minWithdrawalAmount`. Do not sum the same asset across `perps` and `spot`; the selected route is part of the signed transaction.

## Submit the selected row

|                 |                                               |
| --------------- | --------------------------------------------- |
| **Signer**      | `SDK` (provider-owned Lighter key, WASM blob) |
| **Params**      | `{ destination, amount, assetId?, route? }`   |
| **Routes**      | `perps` or `spot`                             |
| **Destination** | Account-owner address only                    |

Pass the selected row's `asset.id` and `route` together. `amount` stays in human-readable asset units; the backend loads the authoritative asset precision and minimum, validates the amount, and the provider signer scales it exactly.

```typescript theme={null}
await client.execute({
  provider: 'lighter',
  address: userAddress,
  action: ActionType.WITHDRAWAL,
  params: {
    destination: userAddress,
    amount: selected.available,
    assetId: selected.asset.id,
    route: selected.route,
  },
});
```

For backward-compatible amount-only requests, `route` defaults to `perps` and the asset defaults to that deployment's quote collateral (`USDC` for `lighter`, `USDG` for `lighter-rh`). New UIs should use discovery rather than rely on those defaults.

## Destination constraint

The backend rejects a destination that differs from the L1 account owner. The destination chain follows the deployment: mainnet Lighter exits through its Ethereum path, while `lighter-rh` uses the Robinhood deployment configuration.

## Standard and fast paths

The backend chooses settlement after it has resolved the selected asset and route:

| Path                               | Settlement                          | Eligibility                                                                                        |
| ---------------------------------- | ----------------------------------- | -------------------------------------------------------------------------------------------------- |
| **Fast** (internally a `TRANSFER`) | Operator-relayed, typically minutes | Deployment quote collateral on the `perps` route, with an available operator and sufficient limits |
| **Standard** (`WITHDRAWAL`)        | Normal rollup withdrawal            | Every supported asset/route; fallback whenever fast withdrawal is unavailable                      |

The optional fast-path probe never blocks withdrawal. An unavailable probe or build failure falls back to the standard step. `TRANSFER` remains internal and is not advertised as a directly callable public action.

The returned successful `ActionResult` can include `txHash` and `explorerLink` when that deployment has a configured explorer.
