Withdraw funds from a DEX perps account. The withdrawal flow follows the same two-step create-then-submit pattern as authorization and trading.
The examples on this page use Hyperliquid (dex: 'hyperliquid'). Withdrawal mechanics (supported assets, destination chains, and processing times) vary by DEX.
Overview
The withdrawal flow has three steps:
- Create —
createWithdrawal() builds the EIP-712 typed data payload
- Sign — User signs the
typedData with their wallet
- Submit —
submitWithdrawal() sends the signed payload
Withdrawals are user-signed only. Agents cannot initiate withdrawals — this is a security feature. The withdrawal typed data requires the user’s wallet signature regardless of signing mode.
Hyperliquid: Withdrawal processing typically takes 3–4 minutes. The bridge transfer from Hyperliquid L1 to Arbitrum is asynchronous.
Using PerpsClient (recommended)
Step 1: Build withdrawal payload
const { action } = await perps.buildWithdrawal({
dex: 'hyperliquid',
address: userAddress,
withdrawal: {
destination: userAddress, // Address to receive withdrawn funds
amount: '100.0',
},
});
Step 2: Sign the action
const signedAction = {
action: action.action,
typedData: action.typedData,
// Using viem walletClient:
signature: await walletClient.signTypedData({ ...action.typedData }),
// Or using a raw EIP-1193 provider:
// signature: await provider.request({
// method: 'eth_signTypedData_v4',
// params: [address, JSON.stringify(action.typedData)],
// }),
};
Step 3: Submit signed withdrawal
const { result } = await perps.submitWithdrawal({
dex: 'hyperliquid',
address: userAddress,
action: signedAction,
});
if (result.success) {
console.log('Withdrawal submitted successfully');
} else {
console.error(`Withdrawal failed: ${result.error}`);
}
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.
Using Service Functions (advanced)
For more control, use the low-level service functions directly:
import { createWithdrawal, submitWithdrawal } from '@lifi/perps-sdk';
// Build payload
const { action } = await createWithdrawal(client, {
dex: 'hyperliquid',
address: userAddress,
withdrawal: {
destination: userAddress,
amount: '100.0',
},
});
// Sign the action
const signedAction = {
action: action.action,
typedData: action.typedData,
signature: await walletClient.signTypedData({ ...action.typedData }),
};
// Submit
const { result } = await submitWithdrawal(client, {
dex: 'hyperliquid',
address: userAddress,
action: signedAction,
});
console.log(result.action, result.success ? 'OK' : result.error);
PerpsClient Methods
buildWithdrawal
Build a withdrawal payload for the user to sign.
const response = await perps.buildWithdrawal(params);
Parameters:
| Field | Type | Required | Description |
|---|
dex | string | Yes | DEX identifier |
address | string | Yes | User’s wallet address (account owner) |
withdrawal | WithdrawalInput | Yes | Withdrawal details |
WithdrawalInput:
| Field | Type | Required | Description |
|---|
destination | string | Yes | Destination address for the withdrawal |
amount | string | Yes | Amount to withdraw (e.g., "100.0") |
Returns: { action: WithdrawalAction }
| Field | Type | Description |
|---|
action.action | string | Action type ("Withdraw") |
action.description | string | Human-readable description |
action.typedData | object | EIP-712 typed data to sign |
submitWithdrawal
Submit a signed withdrawal.
const response = await perps.submitWithdrawal(params);
Parameters:
| Field | Type | Required | Description |
|---|
dex | string | Yes | DEX identifier |
address | string | Yes | User’s wallet address (account owner) |
action | SignedWithdrawal | Yes | Signed withdrawal payload |
SignedWithdrawal:
| Field | Type | Required | Description |
|---|
action | string | Yes | Action type from buildWithdrawal |
typedData | object | Yes | Original typedData from buildWithdrawal |
signature | string | Yes | User’s signature of the typedData |
Returns: { result: WithdrawalResult }
| Field | Type | Description |
|---|
result.action | string | Action type |
result.success | boolean | Whether the withdrawal was accepted |
result.error | string | Error message (if failed) |
API Reference: POST /createWithdrawal, POST /withdrawal