Skip to main content

Stablecoin Swap API: Convert USDC, USDT, and DAI

· 5 min read
swapapi
swapapi Team

TL;DR: Swap USDC, USDT, and DAI across 46 EVM chains with a single GET request. No API key required. Watch out for decimal differences on BSC and Rootstock.

Why Stablecoin Swaps Matter

Stablecoins are the backbone of DeFi trading:

  • Price stability — Minimize exposure to volatile assets
  • Liquidity — Deep pools mean low slippage
  • Cross-chain — Move value between chains efficiently
  • Trading pairs — Most tokens trade against USDC or USDT

With swapapi, you can swap stablecoins programmatically without managing API keys or authentication.

Common Stablecoin Addresses

USDC (USD Coin)

USDC is the most widely used stablecoin in DeFi.

ChainChain IDUSDC AddressDecimals
Ethereum10xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB486
Arbitrum421610xaf88d065e77c8cC2239327C5EDb3A432268e58316
Base84530x833589fCD6eDb6E08f4c7C32D4f71b54bdA029136
Optimism100x0b2C639c533813f4Aa9D7837CAf62653d097Ff856
Polygon1370x3c499c542cEF5E3811e1192ce70d8cC03d5c33596
BSC560x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d18
Avalanche431140xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E6
BSC Decimal Gotcha

USDC on BSC has 18 decimals, not 6 like on other chains. Always verify decimals before constructing transactions.

USDT (Tether)

USDT has the highest trading volume across centralized and decentralized exchanges.

ChainChain IDUSDT AddressDecimals
Ethereum10xdAC17F958D2ee523a2206206994597C13D831ec76
Arbitrum421610xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb96
Base84530xfde4C96c8593536E31F229EA8f37b2ADa2699bb26
Optimism100x94b008aA00579c1307B0EF2c499aD98a8ce58e586
Polygon1370xc2132D05D31c914a87C6611C10748AEb04B58e8F6
BSC560x55d398326f99059fF775485246999027B319795518
BSC USDT Decimals

USDT on BSC also has 18 decimals instead of 6. This is a common source of bugs when building cross-chain applications.

DAI

DAI is a decentralized stablecoin collateralized by crypto assets.

ChainChain IDDAI AddressDecimals
Ethereum10x6B175474E89094C44Da98b954EedeAC495271d0F18
Arbitrum421610xDA10009cBd5D07dd0CeCc66161FC93D7c9000da118
Base84530x50c5725949A6F0c72E6C4a641F24049A917DB0Cb18
Optimism100xDA10009cBd5D07dd0CeCc66161FC93D7c9000da118
Polygon1370x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A06318
BSC560x1AF3F329e8BE154074D8769D1FFa4eE058B1DBc318

The Decimal Gotcha

Always check token decimals. The same token can have different decimals on different chains:

// Wrong on BSC - will send 1,000,000x too much
const amount = 100 * 10**6; // Assumes 6 decimals

// Correct - always fetch decimals dynamically
const decimals = await getDecimals(chainId, tokenAddress);
const amount = 100 * 10**decimals;

Chains with Non-Standard Decimals

  • BSC (56): USDC and USDT use 18 decimals
  • Rootstock (30): USDT uses 18 decimals
  • Boba BNB (56288): USDT uses 18 decimals

Swapping Stablecoins

USDC to USDT on Ethereum

curl "https://api.swapapi.dev/v1/swap/1?\
tokenIn=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48&\
tokenOut=0xdAC17F958D2ee523a2206206994597C13D831ec7&\
amount=100000000&\
sender=0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"

DAI to USDC on Arbitrum

curl "https://api.swapapi.dev/v1/swap/42161?\
tokenIn=0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1&\
tokenOut=0xaf88d065e77c8cC2239327C5EDb3A432268e5831&\
amount=100000000000000000000&\
sender=0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"
tip

Stablecoin-to-stablecoin swaps typically have very low price impact (<0.01%) due to deep liquidity pools.

TypeScript Example

async function swapStablecoins(
chainId: number,
fromToken: string,
toToken: string,
amount: number,
decimals: number,
sender: string
) {
// Convert human-readable amount to raw
const rawAmount = (amount * 10**decimals).toString();

const res = await fetch(
`https://api.swapapi.dev/v1/swap/${chainId}?` +
`tokenIn=${fromToken}&` +
`tokenOut=${toToken}&` +
`amount=${rawAmount}&` +
`sender=${sender}`
);

const { success, data } = await res.json();

if (!success) throw new Error("Swap failed");
if (data.status !== "Successful") throw new Error("No route found");

// For stablecoin swaps, price impact should be minimal
if (data.priceImpact > 0.001) {
console.warn("High price impact:", data.priceImpact);
}

return data.tx;
}

// Example: Swap 1000 USDC to USDT on Base
const tx = await swapStablecoins(
8453,
"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", // USDC
"0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2", // USDT
1000,
6,
"0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"
);

Best Practices

1. Always Verify Decimals

import { createPublicClient, http, erc20Abi } from 'viem';

const client = createPublicClient({
chain: base,
transport: http(),
});

async function getDecimals(chainId: number, tokenAddress: string) {
const decimals = await client.readContract({
address: tokenAddress as `0x${string}`,
abi: erc20Abi,
functionName: 'decimals',
});
return decimals;
}

2. Check Price Impact

Even stablecoin swaps can have price impact on low-liquidity chains:

if (data.priceImpact > 0.001) {
// 0.1% threshold
throw new Error("Price impact too high for stablecoin swap");
}

3. Handle Different Addresses

Don't hardcode addresses. Use a registry:

const STABLECOINS = {
USDC: {
1: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
42161: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
8453: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
// ...
},
USDT: {
1: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
// ...
}
};

4. Test on Small Amounts First

Always test with $1-10 before executing larger trades.

Stablecoin Swap Strategies

1. Yield Optimization

Move between stablecoins to capture the highest yield:

// If USDC lending APY > USDT lending APY, swap to USDC
if (usdcApy > usdtApy + 0.5) {
await swapStablecoins(chainId, USDT, USDC, amount, 6, sender);
}

2. Arbitrage

Exploit price differences between stablecoins (requires monitoring):

// If USDC trades at $1.001 and DAI at $1.000, buy DAI, sell USDC
if (usdcPrice > daiPrice + threshold) {
await swapStablecoins(chainId, USDC, DAI, amount, 6, sender);
}

3. Rebalancing

Maintain target portfolio weights:

const targetRatio = { USDC: 0.5, USDT: 0.3, DAI: 0.2 };
const currentRatio = await getCurrentRatio();

// Rebalance if drift exceeds threshold
if (Math.abs(currentRatio.USDC - targetRatio.USDC) > 0.05) {
await rebalancePortfolio();
}

Response Example

{
"success": true,
"data": {
"status": "Successful",
"tokenFrom": {
"address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"symbol": "USDC",
"decimals": 6
},
"tokenTo": {
"address": "0xdAC17F958D2ee523a2206206994597C13D831ec7",
"symbol": "USDT",
"decimals": 6
},
"swapPrice": 0.9998,
"priceImpact": 0.0001,
"amountIn": "100000000",
"expectedAmountOut": "99980000",
"tx": {
"to": "0x...",
"data": "0x...",
"value": "0",
"gas": "150000"
}
},
"timestamp": "2026-03-20T00:00:00.000Z"
}

Common Errors

"Insufficient Liquidity"

Some chains have limited stablecoin liquidity. Try a different route or smaller amount.

"High Price Impact"

Large trades on low-liquidity chains can move prices significantly. Split into smaller trades.

"Invalid Token"

Verify the token address is correct for the chain. Many tokens have different addresses on different chains.