PAXG Swap Integration
This guide walks through integrating the PAXG swap REST API into your application.
Currently only available via REST API.
Prerequisites
- A Paxos Labs API key
- An Ethereum mainnet RPC endpoint
- A wallet library (viem, ethers, wagmi, etc.)
Supported Token Pairs
PAXG must be either the offerAsset (sell) or wantAsset (buy) in every swap request. Supported stablecoins for the other side of the trade:
| Token | Address |
|---|
| USDC | 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 |
| USDT | 0xdAC17F958D2ee523a2206206994597C13D831ec7 |
| PYUSD | 0x6c3ea9036406852006290770BEdFcAbA0e23A0e8 |
| USDG | 0xe343167631d89B6Ffc58B88d6b7fB0228795491D |
Getting a Swap Quote
Request a quote by calling the /v1/paxg/swapQuotes endpoint:
const response = await fetch(
'https://api.paxoslabs.com/v1/paxg/swapQuotes?' + new URLSearchParams({
chainId: '1',
offerAsset: '0x45804880De22913dAFE09f4980848ECE6EcbAf78', // PAXG
wantAsset: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC
offerAmount: '1000000000000000000', // 1 PAXG in wei
userAddress: '0x...', // User's wallet address
}),
{
headers: {
'x-api-key': 'pxl_<public_id>_<secret>',
},
}
);
const quote = await response.json();
Response Structure
The quote response includes:
interface SwapQuoteResponse {
transaction: {
to: string; // Contract to send the transaction to
data: string; // Encoded swap calldata
value: string; // ETH value (usually "0" for token swaps)
gas: string; // Estimated gas limit
gasPrice: string; // Suggested gas price
};
buyAmount: string; // Expected output amount
minBuyAmount: string; // Minimum output (with slippage)
allowanceTarget: string; // Address to approve tokens to
currentAllowance?: string; // User's current allowance (if any)
}
Handling Token Approvals
Before executing the swap, ensure the user has approved sufficient tokens:
import { erc20Abi } from 'viem';
// Check if approval is needed
const needsApproval = BigInt(quote.currentAllowance ?? '0') < BigInt(offerAmount);
if (needsApproval) {
// Request approval
const approveTx = await walletClient.writeContract({
address: offerAsset,
abi: erc20Abi,
functionName: 'approve',
args: [quote.allowanceTarget, offerAmount],
});
// Wait for approval confirmation
await publicClient.waitForTransactionReceipt({ hash: approveTx });
}
Executing the Swap
Once approved, execute the swap using the provided calldata:
const swapTx = await walletClient.sendTransaction({
to: quote.transaction.to,
data: quote.transaction.data,
value: BigInt(quote.transaction.value),
gas: BigInt(quote.transaction.gas),
});
const receipt = await publicClient.waitForTransactionReceipt({ hash: swapTx });
Using Permit2 Authorization
For gasless approvals, use the permit2 auth method:
const response = await fetch(
'https://api.paxoslabs.com/v1/paxg/swapQuotes?' + new URLSearchParams({
chainId: '1',
offerAsset: '0x45804880De22913dAFE09f4980848ECE6EcbAf78',
wantAsset: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
offerAmount: '1000000000000000000',
userAddress: '0x...',
authMethod: 'permit2', // Use Permit2
}),
{
headers: {
'x-api-key': 'pxl_<public_id>_<secret>',
},
}
);
const quote = await response.json();
// The response includes EIP-712 typed data for signing
if (quote.permit2) {
const signature = await walletClient.signTypedData({
domain: quote.permit2.eip712.domain,
types: quote.permit2.eip712.types,
primaryType: quote.permit2.eip712.primaryType,
message: quote.permit2.eip712.message,
});
// Include signature when executing the swap
// (implementation depends on your setup)
}
Error Handling
The API returns standard HTTP error codes:
| Status | Description |
|---|
| 400 | Invalid parameters or insufficient liquidity |
| 503 | DEX aggregator temporarily unavailable |
Example error response:
{
"error": {
"code": 400,
"message": "No liquidity available for this swap. Try a smaller amount or different token pair.",
"status": "INVALID_ARGUMENT"
}
}
Always validate the minBuyAmount before executing to protect against slippage. Consider showing users the expected output and allowing them to set slippage tolerance.