Skip to main content
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:
  1. CreatecreateWithdrawal() builds the EIP-712 typed data payload
  2. Sign — User signs the typedData with their wallet
  3. SubmitsubmitWithdrawal() 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.

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:
FieldTypeRequiredDescription
dexstringYesDEX identifier
addressstringYesUser’s wallet address (account owner)
withdrawalWithdrawalInputYesWithdrawal details
WithdrawalInput:
FieldTypeRequiredDescription
destinationstringYesDestination address for the withdrawal
amountstringYesAmount to withdraw (e.g., "100.0")
Returns: { action: WithdrawalAction }
FieldTypeDescription
action.actionstringAction type ("Withdraw")
action.descriptionstringHuman-readable description
action.typedDataobjectEIP-712 typed data to sign

submitWithdrawal

Submit a signed withdrawal.
const response = await perps.submitWithdrawal(params);
Parameters:
FieldTypeRequiredDescription
dexstringYesDEX identifier
addressstringYesUser’s wallet address (account owner)
actionSignedWithdrawalYesSigned withdrawal payload
SignedWithdrawal:
FieldTypeRequiredDescription
actionstringYesAction type from buildWithdrawal
typedDataobjectYesOriginal typedData from buildWithdrawal
signaturestringYesUser’s signature of the typedData
Returns: { result: WithdrawalResult }
FieldTypeDescription
result.actionstringAction type
result.successbooleanWhether the withdrawal was accepted
result.errorstringError message (if failed)
API Reference: POST /createWithdrawal, POST /withdrawal