Stablecoin Swap API: Convert USDC, USDT, and DAI
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.
| Chain | Chain ID | USDC Address | Decimals |
|---|---|---|---|
| Ethereum | 1 | 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 | 6 |
| Arbitrum | 42161 | 0xaf88d065e77c8cC2239327C5EDb3A432268e5831 | 6 |
| Base | 8453 | 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 | 6 |
| Optimism | 10 | 0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85 | 6 |
| Polygon | 137 | 0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359 | 6 |
| BSC | 56 | 0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d | 18 |
| Avalanche | 43114 | 0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E | 6 |
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.
| Chain | Chain ID | USDT Address | Decimals |
|---|---|---|---|
| Ethereum | 1 | 0xdAC17F958D2ee523a2206206994597C13D831ec7 | 6 |
| Arbitrum | 42161 | 0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9 | 6 |
| Base | 8453 | 0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2 | 6 |
| Optimism | 10 | 0x94b008aA00579c1307B0EF2c499aD98a8ce58e58 | 6 |
| Polygon | 137 | 0xc2132D05D31c914a87C6611C10748AEb04B58e8F | 6 |
| BSC | 56 | 0x55d398326f99059fF775485246999027B3197955 | 18 |
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.
| Chain | Chain ID | DAI Address | Decimals |
|---|---|---|---|
| Ethereum | 1 | 0x6B175474E89094C44Da98b954EedeAC495271d0F | 18 |
| Arbitrum | 42161 | 0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1 | 18 |
| Base | 8453 | 0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb | 18 |
| Optimism | 10 | 0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1 | 18 |
| Polygon | 137 | 0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063 | 18 |
| BSC | 56 | 0x1AF3F329e8BE154074D8769D1FFa4eE058B1DBc3 | 18 |
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"
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.
