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

# Withdrawal

> Withdraw funds from a provider perps account

Withdraw funds from a provider perps account.

<Info>
  The examples on this page use **Hyperliquid** (`provider: 'hyperliquid'`). Withdrawal mechanics (supported assets, destination chains, and processing times) vary by provider.
</Info>

## Overview

`PerpsClient.withdraw()` is a single-call helper that builds the withdrawal payload, authorizes it through the registered provider plugin, and submits the signed action. It dispatches through the same `createAction` → authorize → `executeAction` pipeline documented in [Actions](/sdk/actions), but consumers do not have to compose the steps manually.

<Warning>
  Withdrawal authorization is provider-specific. Hyperliquid withdrawals require the user's wallet. Lighter withdrawals are signed by the provider plugin's SDK-managed Lighter key. Always follow the `ProviderAction.signers` and `signingMethod` metadata instead of assuming one signer for every venue.
</Warning>

<Info>
  **Hyperliquid:** Withdrawal processing typically takes 3–4 minutes. The bridge transfer from Hyperliquid L1 to Arbitrum is asynchronous.
</Info>

## Discovering Withdrawable Balances

Call `getWithdrawableBalances()` before rendering a withdrawal picker. Providers that support the capability return one row per withdrawable `(asset, route)` pair; providers without the optional read return `undefined`, which means the form remains amount-only.

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

for (const row of rows ?? []) {
  console.log(row.asset.displaySymbol, row.route, row.available);
}
```

Each `WithdrawableBalance` contains:

| Field       | Type                | Description                                                                           |
| ----------- | ------------------- | ------------------------------------------------------------------------------------- |
| `asset`     | `Asset`             | Canonical asset metadata, including precision, L1 identity, and `minWithdrawalAmount` |
| `route`     | `'perps' \| 'spot'` | Venue balance route used by the signed withdrawal                                     |
| `available` | `string`            | Withdrawable amount in the asset's own units                                          |

The SDK joins provider rows with `/assets`, drops unknown assets, and filters amounts below each asset's `minWithdrawalAmount`. For a row-based provider, pass the selected `asset.id` and `route` through the withdrawal action params together; never merge balances across routes. The amount remains a human-readable decimal string — the provider signer applies the asset precision.

***

## Using PerpsClient (recommended)

```typescript theme={null}
const { results } = await perps.withdraw({
  provider: 'hyperliquid',
  address: userAddress,
  withdrawal: {
    destination: userAddress, // Address to receive withdrawn funds
    amount: '100.0',
  },
});

const [result] = results;
if (result.success) {
  console.log('Withdrawal submitted successfully');
} else {
  console.error(`Withdrawal failed: ${result.error}`);
}
```

<Warning>
  Withdrawal submission returns `202 Accepted`. Processing is asynchronous — for Hyperliquid, this typically takes 3–4 minutes via the Arbitrum bridge. Poll `getAccount()` to verify the balance change.
</Warning>

## PerpsClient.withdraw

Build, sign with the provider-declared signer, and submit a withdrawal in a single call.

```typescript theme={null}
const response = await perps.withdraw(params);
```

**Parameters:** `WithdrawParams`

| Field        | Type               | Required | Description                           |
| ------------ | ------------------ | -------- | ------------------------------------- |
| `provider`   | `string`           | Yes      | Provider identifier                   |
| `address`    | `string`           | Yes      | User's wallet address (account owner) |
| `withdrawal` | `WithdrawalParams` | Yes      | Withdrawal details                    |

`WithdrawalParams`:

| Field         | Type                | Required | Description                                         |
| ------------- | ------------------- | -------- | --------------------------------------------------- |
| `destination` | `string`            | Yes      | Destination address for the withdrawal              |
| `amount`      | `string`            | Yes      | Human-readable amount in the selected asset's units |
| `assetId`     | `string`            | No       | Provider-native asset id for row-based withdrawals  |
| `route`       | `'perps' \| 'spot'` | No       | Provider balance route paired with `assetId`        |

**Returns:** `ExecuteActionResponse` — `{ results: ActionResult[] }`. The array contains a single result for the `WITHDRAWAL` action:

| Field                     | Type              | Description                                                |
| ------------------------- | ----------------- | ---------------------------------------------------------- |
| `results[i].action`       | `ActionType`      | `ActionType.WITHDRAWAL`                                    |
| `results[i].success`      | `boolean`         | Whether the withdrawal was accepted                        |
| `results[i].txHash`       | `string?`         | Venue transaction hash when known at submission time       |
| `results[i].explorerLink` | `string?`         | Fully resolved explorer link for `txHash`, when configured |
| `results[i].error`        | `string?`         | Error message (failed result only)                         |
| `results[i].errorCode`    | `PerpsErrorCode?` | Structured failure classification, when provided           |

## Using Service Functions (advanced)

For complete control over the create/sign/execute steps — for example, to surface the typed-data payload in a confirmation dialog before requesting the signature — call the lower-level `createAction` / `executeAction` service functions directly. See [Actions](/sdk/actions) for the full create → sign → execute pattern.

```typescript theme={null}
import { createAction, executeAction, ActionType } from '@lifi/perps-sdk';

const { actions } = await createAction(client, {
  provider: 'hyperliquid',
  address: userAddress,
  action: ActionType.WITHDRAWAL,
  params: {
    destination: userAddress,
    amount: '100.0',
  },
});

const signedActions = await Promise.all(
  actions.map(async (a) => ({
    action: a.action,
    typedData: a.typedData,
    signature: await walletClient.signTypedData({ ...a.typedData }),
  })),
);

const { results } = await executeAction(client, {
  provider: 'hyperliquid',
  address: userAddress,
  action: ActionType.WITHDRAWAL,
  actions: signedActions,
});

const [result] = results;
console.log(result.action, result.success ? 'OK' : result.error);
```

**API Reference:** [POST /createAction](/api-reference/actions#post-createaction), [POST /executeAction](/api-reference/actions#post-executeaction)
