Skip to main content
Get up and running with Stableswapper, the onchain liquidity program that powers instant swaps between USDC and custom stablecoins. This guide walks through swapping USDC for a custom stablecoin on devnet. Learn more about Custom Stablecoins.

Prerequisites

  • Node.js 18+ installed
  • A wallet with a private key for Base Sepolia
  • Base Sepolia ETH for gas fees (get from CDP Faucet)
  • Base Sepolia USDC tokens (get from CDP Faucet)
  • A custom stablecoin to swap with (this guide uses CBTUSD, a test token on Base Sepolia)
  • Basic familiarity with TypeScript
Don’t have a custom stablecoin yet? This quickstart uses CBTUSD, a test custom stablecoin already deployed on Base Sepolia for testing. For production with your own branded stablecoin, contact Coinbase about Custom Stablecoins issuance.

1. Create tsconfig.json

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "CommonJS",
    "esModuleInterop": true,
    "resolveJsonModule": true,
    "skipLibCheck": true,
    "strict": true
  }
}

2. Install dependencies

npm install ethers
npm install --save-dev ts-node typescript @types/node

3. Set environment variables

export PRIVATE_KEY="your-wallet-private-key"
export RPC_URL="https://sepolia.base.org"
Never commit your private key to source control. Use environment variables or a secrets manager. For production, use CDP Server Wallet v2 for secure key management.

4. Create your swap script

Now we’ll create a script that swaps 0.1 USDC for the custom stablecoin (CBTUSD). The script will:
  • Connect to the Stableswapper contract on Base Sepolia
  • Approve the contract to spend your USDC
  • Execute the swap with slippage protection
swap.ts
import { ethers } from "ethers";

// Base Sepolia addresses — see Key Addresses page for details
const STABLESWAPPER_ADDRESS = "0x57AB1E2c6289aCe985Bd5c5571EbF6d98CD41Ab7";
const USDC_ADDRESS          = "0x036CbD53842c5426634e7929541eC2318f3dCF7e";
const CBTUSD_ADDRESS        = "0x57AB1EFE59b1C7b36b1Dc9315B4782bCcBb83721";

// Minimal ABIs for the functions we need
const ERC20_ABI = [
  "function approve(address spender, uint256 amount) returns (bool)",
  "function allowance(address owner, address spender) view returns (uint256)",
  "function balanceOf(address account) view returns (uint256)",
  "function decimals() view returns (uint8)",
];

const STABLESWAPPER_ABI = [
  "function swap(address tokenIn, address tokenOut, uint256 amountIn, uint256 minAmountOut, address recipient) external",
  "function feeBasisPoints() view returns (uint16)",
  "function isTokenListed(address token) view returns (bool)",
  "function isTokenSwappable(address token) view returns (bool)",
  "function isFeatureEnabled(uint8 feature) view returns (bool)",
  "function isAllowlisted(address addr) view returns (bool)",
];

async function swapUsdcForCustomToken() {
  const provider = new ethers.JsonRpcProvider(process.env.RPC_URL);
  const signer = new ethers.Wallet(process.env.PRIVATE_KEY!, provider);

  const stableSwapper = new ethers.Contract(STABLESWAPPER_ADDRESS, STABLESWAPPER_ABI, signer);
  const usdc = new ethers.Contract(USDC_ADDRESS, ERC20_ABI, signer);

  // Swap 0.1 USDC (6 decimals)
  const amountIn = ethers.parseUnits("0.1", 6);
  const minAmountOut = ethers.parseUnits("0.09", 6);

  // Step 1: Approve the Stableswapper to spend your USDC
  const currentAllowance = await usdc.allowance(signer.address, STABLESWAPPER_ADDRESS);
  if (currentAllowance < amountIn) {
    console.log("Approving USDC spend...");
    const approveTx = await usdc.approve(STABLESWAPPER_ADDRESS, amountIn);
    await approveTx.wait();
    console.log("Approval confirmed");
  }

  // Step 2: Execute the swap
  console.log("Executing swap...");
  const swapTx = await stableSwapper.swap(
    USDC_ADDRESS,      // tokenIn
    CBTUSD_ADDRESS,    // tokenOut
    amountIn,          // amountIn
    minAmountOut,      // minAmountOut (slippage protection)
    signer.address     // recipient
  );

  const receipt = await swapTx.wait();
  console.log("Swap successful!");
  console.log("Transaction hash:", receipt.hash);
}

swapUsdcForCustomToken()
  .then(() => process.exit(0))
  .catch((err) => { console.error("Swap failed:", err.message); process.exit(1); });

5. Run your swap

npx ts-node swap.ts
Running into issues? See the Troubleshooting guide for common errors and solutions.

What’s next?

Reference

Swap instruction parameters and accounts

Production Readiness

Helper functions, error handling, and best practices

Key Addresses

Program IDs and deployed addresses

Overview

Learn about Custom Stablecoins and use cases