Skip to main content
Cancel a pending withdrawal order to recover locked vault shares. Only the original order owner (verified on-chain via msg.sender) can cancel.
Only orders with status PENDING can be cancelled. Orders that have already been processed (COMPLETE) or are mid-refund (PENDING_REFUND, REFUNDED) cannot be cancelled.

Prerequisites

  • A Paxos Labs API key
  • An EVM-compatible signer (the same address that submitted the original withdrawal order)
  • The orderIndex of the pending withdrawal order

Step 1: Find the Order Index

Query GET /v2/amplify/withdrawalRequests to find the orderIndex of the order you want to cancel:
curl "https://api.paxoslabs.com/v2/amplify/withdrawalRequests?\
filter=userAddress%3D0x1234567890abcdef1234567890abcdef12345678%20AND%20\
vaultAddress%3D0xbbbb000000000000000000000000000000000001%20AND%20\
status%3DPENDING" \
  -H "x-api-key: pxl_your_key"
Each item in the response includes an orderIndex field:
{
  "withdrawalRequests": [
    {
      "id": "wr_abc123",
      "orderIndex": "42",
      "status": "PENDING",
      "vaultAddress": "0xbbbb...",
      "chainId": 1,
      "userAddress": "0x1234...",
      "orderAmount": "1000000000000000000",
      "wantAssetAddress": "0xA0b8..."
    }
  ],
  "nextPageToken": null
}

Step 2: Prepare Cancel Calldata

GET /v2/amplify/withdraw/cancel returns the transaction to cancel a pending withdrawal order.

Parameters

ParameterTypeRequiredDescription
vaultAddressstringYesBoringVault contract address (0x + 40 hex chars)
orderIndexstringYesIndex of the withdrawal order to cancel (decimal string from withdrawalRequests response)
chainIdnumberYesEVM chain ID
responseFormatstringNoencoded (default), full, or structured

Response

{
  "transaction": {
    "to": "0xdddd000000000000000000000000000000000001",
    "data": "0x5c975abb...",
    "value": "0",
    "abi": [{"type": "function", "name": "cancelOrder", "inputs": [...]}],
    "functionName": "cancelOrder",
    "args": ["42"]
  }
}

Step 3: Sign and Submit

Broadcast the cancellation transaction. The transaction must be sent from the same address that originally submitted the withdrawal order — ownership is enforced on-chain via msg.sender. After confirmation, the locked vault shares are returned to the user’s wallet.

Complete Examples

import { createWalletClient, createPublicClient, http } from "viem";
import { mainnet } from "viem/chains";
import { privateKeyToAccount } from "viem/accounts";

const API_KEY = process.env.AMPLIFY_API_KEY!;
const PRIVATE_KEY = process.env.PRIVATE_KEY as `0x${string}`;
const BASE = "https://api.paxoslabs.com";
const HEADERS = { "x-api-key": API_KEY };

const VAULT_ADDRESS = "0xbbbb000000000000000000000000000000000001";
const CHAIN_ID = 1;

async function main() {
  const account = privateKeyToAccount(PRIVATE_KEY);
  const walletClient = createWalletClient({
    account,
    chain: mainnet,
    transport: http(),
  });
  const publicClient = createPublicClient({
    chain: mainnet,
    transport: http(),
  });

  // Step 1: Find pending withdrawal orders
  console.log("Fetching pending withdrawal orders...");
  const statusUrl = new URL(`${BASE}/v2/amplify/withdrawalRequests`);
  statusUrl.searchParams.set(
    "filter",
    `userAddress=${account.address} AND vaultAddress=${VAULT_ADDRESS} AND status=PENDING`
  );
  const statusResp = await fetch(statusUrl, { headers: HEADERS }).then(
    (r) => r.json()
  );
  const orders = statusResp.withdrawalRequests;
  if (orders.length === 0) {
    console.log("No pending orders to cancel.");
    return;
  }
  const orderIndex = orders[0].orderIndex;
  console.log(`Cancelling order index: ${orderIndex}`);

  // Step 2: Get cancel calldata
  const cancelUrl = new URL(`${BASE}/v2/amplify/withdraw/cancel`);
  cancelUrl.searchParams.set("vaultAddress", VAULT_ADDRESS);
  cancelUrl.searchParams.set("orderIndex", orderIndex);
  cancelUrl.searchParams.set("chainId", String(CHAIN_ID));

  const cancelResp = await fetch(cancelUrl, { headers: HEADERS }).then(
    (r) => r.json()
  );
  const tx = cancelResp.transaction;

  // Step 3: Sign and submit
  console.log("Submitting cancellation...");
  const hash = await walletClient.sendTransaction({
    to: tx.to as `0x${string}`,
    data: tx.data as `0x${string}`,
    value: BigInt(tx.value),
    chain: mainnet,
    account,
  });
  const receipt = await publicClient.waitForTransactionReceipt({ hash });
  console.log(
    `Cancellation confirmed in block ${receipt.blockNumber}: ${hash}`
  );
}

main().catch(console.error);

Error Responses

StatusMeaning
400Invalid parameters (bad address, missing orderIndex, etc.)
404No account found for the given vaultAddress + chainId