Cancel a pending withdrawal order to recover locked vault shares. Only the original order owner (verified on-chain viaDocumentation Index
Fetch the complete documentation index at: https://developers.paxoslabs.com/llms.txt
Use this file to discover all available pages before exploring further.
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
orderIndexof the pending withdrawal order
Step 1: Find the Order Index
QueryGET /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"
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
| Parameter | Type | Required | Description |
|---|---|---|---|
vaultAddress | string | Yes | BoringVault contract address (0x + 40 hex chars) |
orderIndex | string | Yes | Index of the withdrawal order to cancel (decimal string from withdrawalRequests response) |
chainId | number | Yes | EVM chain ID |
responseFormat | string | No | encoded (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 viamsg.sender.
After confirmation, the locked vault shares are returned to the user’s wallet.
Complete Examples
- Node.js
- Python
- Go
- Java
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);
import os
import requests
from web3 import Web3
API_KEY = os.environ["AMPLIFY_API_KEY"]
PRIVATE_KEY = os.environ["PRIVATE_KEY"]
BASE = "https://api.paxoslabs.com"
HEADERS = {"x-api-key": API_KEY}
VAULT_ADDRESS = "0xbbbb000000000000000000000000000000000001"
CHAIN_ID = 1
w3 = Web3(Web3.HTTPProvider("https://eth.llamarpc.com"))
account = w3.eth.account.from_key(PRIVATE_KEY)
# Step 1: Find pending withdrawal orders
print("Fetching pending withdrawal orders...")
status_resp = requests.get(f"{BASE}/v2/amplify/withdrawalRequests", headers=HEADERS, params={
"filter": f"userAddress={account.address} AND vaultAddress={VAULT_ADDRESS} AND status=PENDING",
}).json()
orders = status_resp["withdrawalRequests"]
if not orders:
print("No pending orders to cancel.")
exit()
order_index = orders[0]["orderIndex"]
print(f"Cancelling order index: {order_index}")
# Step 2: Get cancel calldata
cancel_resp = requests.get(f"{BASE}/v2/amplify/withdraw/cancel", headers=HEADERS, params={
"vaultAddress": VAULT_ADDRESS,
"orderIndex": order_index,
"chainId": CHAIN_ID,
}).json()
tx = cancel_resp["transaction"]
# Step 3: Sign and submit
print("Submitting cancellation...")
cancel_tx = {
"to": Web3.to_checksum_address(tx["to"]),
"data": tx["data"],
"value": int(tx["value"]),
"gas": 200_000,
"nonce": w3.eth.get_transaction_count(account.address),
"chainId": CHAIN_ID,
}
signed = account.sign_transaction(cancel_tx)
tx_hash = w3.eth.send_raw_transaction(signed.raw_transaction)
receipt = w3.eth.wait_for_transaction_receipt(tx_hash)
print(f"Cancellation confirmed in block {receipt['blockNumber']}: {tx_hash.hex()}")
package main
import (
"context"
"encoding/json"
"fmt"
"io"
"math/big"
"net/http"
"net/url"
"os"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethclient"
)
const (
baseURL = "https://api.paxoslabs.com"
vaultAddress = "0xbbbb000000000000000000000000000000000001"
chainID = 1
)
func apiGet(path string, params url.Values) (map[string]interface{}, error) {
u := fmt.Sprintf("%s%s?%s", baseURL, path, params.Encode())
req, _ := http.NewRequest("GET", u, nil)
req.Header.Set("x-api-key", os.Getenv("AMPLIFY_API_KEY"))
resp, err := http.DefaultClient.Do(req)
if err != nil { return nil, err }
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
var result map[string]interface{}
json.Unmarshal(body, &result)
return result, nil
}
func main() {
pk, _ := crypto.HexToECDSA(os.Getenv("PRIVATE_KEY"))
fromAddr := crypto.PubkeyToAddress(pk.PublicKey)
client, _ := ethclient.Dial("https://eth.llamarpc.com")
ctx := context.Background()
signer := types.NewEIP155Signer(big.NewInt(chainID))
// Step 1: Find pending withdrawal orders
fmt.Println("Fetching pending withdrawal orders...")
statusResp, _ := apiGet("/v2/amplify/withdrawalRequests", url.Values{
"filter": {fmt.Sprintf("userAddress=%s AND vaultAddress=%s AND status=PENDING",
fromAddr.Hex(), vaultAddress)},
})
orders := statusResp["withdrawalRequests"].([]interface{})
if len(orders) == 0 {
fmt.Println("No pending orders to cancel.")
return
}
order := orders[0].(map[string]interface{})
orderIndex := order["orderIndex"].(string)
fmt.Printf("Cancelling order index: %s\n", orderIndex)
// Step 2: Get cancel calldata
fmt.Println("Fetching cancel calldata...")
cancelResp, _ := apiGet("/v2/amplify/withdraw/cancel", url.Values{
"vaultAddress": {vaultAddress},
"orderIndex": {orderIndex},
"chainId": {fmt.Sprint(chainID)},
})
txData := cancelResp["transaction"].(map[string]interface{})
// Step 3: Sign and submit
fmt.Println("Submitting cancellation...")
nonce, _ := client.PendingNonceAt(ctx, fromAddr)
gasPrice, _ := client.SuggestGasPrice(ctx)
cancelTx := types.NewTransaction(nonce,
common.HexToAddress(txData["to"].(string)),
big.NewInt(0), 200000, gasPrice,
common.FromHex(txData["data"].(string)))
signedCancel, _ := types.SignTx(cancelTx, signer, pk)
client.SendTransaction(ctx, signedCancel)
fmt.Printf("Cancellation submitted: %s\n", signedCancel.Hash().Hex())
}
import org.web3j.crypto.Credentials;
import org.web3j.crypto.RawTransaction;
import org.web3j.crypto.TransactionEncoder;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.http.HttpService;
import org.web3j.utils.Numeric;
import java.math.BigInteger;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
public class AmplifyCancelWithdraw {
static final String BASE = "https://api.paxoslabs.com";
static final String API_KEY = System.getenv("AMPLIFY_API_KEY");
static final String VAULT_ADDRESS = "0xbbbb000000000000000000000000000000000001";
static final int CHAIN_ID = 1;
static HttpClient httpClient = HttpClient.newHttpClient();
static JsonObject apiGet(String path) throws Exception {
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create(BASE + path))
.header("x-api-key", API_KEY)
.GET().build();
HttpResponse<String> resp = httpClient.send(req,
HttpResponse.BodyHandlers.ofString());
return JsonParser.parseString(resp.body()).getAsJsonObject();
}
public static void main(String[] args) throws Exception {
Credentials credentials = Credentials.create(System.getenv("PRIVATE_KEY"));
String userAddress = credentials.getAddress();
Web3j web3 = Web3j.build(new HttpService("https://eth.llamarpc.com"));
// Step 1: Find pending withdrawal orders
System.out.println("Fetching pending withdrawal orders...");
String filter = String.format(
"userAddress=%s AND vaultAddress=%s AND status=PENDING",
userAddress, VAULT_ADDRESS);
String statusPath = "/v2/amplify/withdrawalRequests?filter=" +
java.net.URLEncoder.encode(filter, "UTF-8");
JsonObject statusResp = apiGet(statusPath);
JsonArray orders = statusResp.getAsJsonArray("withdrawalRequests");
if (orders.size() == 0) {
System.out.println("No pending orders to cancel.");
return;
}
String orderIndex = orders.get(0).getAsJsonObject()
.get("orderIndex").getAsString();
System.out.println("Cancelling order index: " + orderIndex);
// Step 2: Get cancel calldata
System.out.println("Fetching cancel calldata...");
String cancelPath = String.format(
"/v2/amplify/withdraw/cancel?vaultAddress=%s&orderIndex=%s&chainId=%d",
VAULT_ADDRESS, orderIndex, CHAIN_ID);
JsonObject cancelResp = apiGet(cancelPath);
JsonObject tx = cancelResp.getAsJsonObject("transaction");
// Step 3: Sign and submit
System.out.println("Submitting cancellation...");
BigInteger nonce = web3.ethGetTransactionCount(userAddress,
org.web3j.protocol.core.DefaultBlockParameterName.PENDING)
.send().getTransactionCount();
BigInteger gasPrice = web3.ethGasPrice().send().getGasPrice();
RawTransaction cancelTx = RawTransaction.createTransaction(
nonce, gasPrice, BigInteger.valueOf(200000),
tx.get("to").getAsString(), BigInteger.ZERO,
tx.get("data").getAsString());
byte[] signedCancel = TransactionEncoder.signMessage(
cancelTx, CHAIN_ID, credentials);
String txHash = web3.ethSendRawTransaction(
Numeric.toHexString(signedCancel)).send().getTransactionHash();
System.out.println("Cancellation submitted: " + txHash);
}
}
Error Responses
| Status | Meaning |
|---|---|
| 400 | Invalid parameters (bad address, missing orderIndex, etc.) |
| 404 | No account found for the given vaultAddress + chainId |