Withdraw USDC from a margin account to your wallet

Withdraw USDC funds from a specific margin account back to your wallet. The system performs comprehensive risk checks to ensure your account remains healthy after the withdrawal.

Risk Checks and Requirements

Before approving a withdrawal, the system verifies:

  1. Sufficient Equity: Your remaining equity must exceed both:

    • Initial Margin (IM): Required for opening new positions
    • Maintenance Margin (MM): Minimum to avoid liquidation
  2. Account Status:

    • Account must not be flagged for liquidation
    • No pending settlements that would affect equity
  3. Available Balance:

    • Can only withdraw truly "free" collateral
    • System accounts for unrealized losses on open positions

How Withdrawals Work

  1. You sign an EIP-712 message requesting the withdrawal
  2. Risk engine checks your account will remain solvent
  3. System approves and executes the on-chain transfer
  4. USDC arrives in your specified wallet address

Important Considerations

  • Isolated Margins: Each trading pair has separate collateral
  • Mark-to-Market: Unrealized P&L affects available withdrawal amount
  • Gas Costs: On-chain withdrawal incurs network fees (paid by protocol)
  • Processing Time: Usually instant, but may take a few blocks

Common Rejection Reasons

  • "Insufficient equity - mm": Withdrawal would put account below maintenance margin
  • "Insufficient equity - im": Withdrawal would put account below initial margin
  • "Account in liquidation": Account is already flagged for liquidation
  • "Margin account not found": No active account for the specified pair

Best Practices

  1. Check account state before withdrawing to see available balance
  2. Leave buffer above minimum margins to avoid liquidation
  3. Consider market volatility - your equity can change rapidly
  4. Withdraw from accounts with no open positions first

EIP-712 Signature Example (TypeScript)

import { parseUnits } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';

// Domain parameters for EIP-712 signature
const EIP712Domain = {
  chainId: 421614, // Arbitrum Sepolia (use 42161 for Arbitrum One mainnet)
  name: 'Premia',
  verifyingContract: '0x...' // ClearingHouseProxy address from deployment
  version: '1'
};

// Type definitions
const Pair = [
  { name: 'base', type: 'address' },
  { name: 'quote', type: 'address' }
];

const UserWithdraw = [
  { name: 'deadline', type: 'uint256' },
  { name: 'to', type: 'address' },
  { name: 'from', type: 'address' },
  { name: 'amount', type: 'uint256' },
  { name: 'pair', type: 'Pair' }
];

// Example withdrawal data
const withdraw = {
  to: '0xYourWalletAddress',    // Destination EOA wallet address
  from: '0xYourSmartAccount',    // Smart account address
  amount: 500,                   // Amount to withdraw
  pair: {
    base: '0xBaseTokenAddress',  // e.g., WETH address
    quote: '0xQuoteTokenAddress' // e.g., USDC address
  }
};

// Calculate deadline (30 seconds from now)
const deadline = Math.floor(Date.now() / 1000) + 30;

// Setup wallet
const account = privateKeyToAccount('0xYourPrivateKey');

// Sign the typed data
const signature = await account.signTypedData({
  domain: EIP712Domain,
  types: { 
    UserWithdraw,
    Pair
  },
  primaryType: 'UserWithdraw',
  message: {
    deadline,
    to: withdraw.to,
    from: withdraw.from,
    amount: parseUnits(withdraw.amount.toString(), 6),
    pair: withdraw.pair
  }
});

// Final request payload
const requestPayload = {
  ...withdraw,
  signature,
  signature_deadline: deadline
};
Language
Credentials
Header
URL
Click Try It! to start a request and see the response here!