Skip to main content
This quickstart walks you through how to use App Kit’s Swap and Bridge capabilities to swap tokens on the same blockchain. The example in this quickstart swaps USDT for USDC on Ethereum, but you can use other supported tokens or blockchains.
Because the Swap capability is only available on mainnet, this quickstart uses mainnet chains and requires real funds.

Prerequisites

Before you begin, ensure that you’ve:
  • Installed Node.js v22+.
  • Created an Ethereum wallet using a wallet provider such as MetaMask and funded it with USDT and ETH tokens.
  • Obtained a (free) kit key from the Circle Console.

Step 1. Set up the project

This step shows you how to prepare your project and environment.

1.1. Set up your development environment

Create a new directory and install App Kit and its dependencies:
Shell
# Set up your directory and initialize a Node.js project
mkdir app-kit-quickstart-swap
cd app-kit-quickstart-swap
npm init -y

# Install App Kit and tools
npm install @circle-fin/app-kit @circle-fin/adapter-viem-v2 viem typescript tsx
Only need to swap and want a lighter install than the full App Kit? Install the standalone swap package instead: @circle-fin/swap-kit

1.2. Configure TypeScript (optional)

This step is optional. It helps prevent missing types in your IDE or editor.
Create a tsconfig.json file:
Shell
npx tsc --init
Then, update the tsconfig.json file:
Shell
cat <<'EOF' > tsconfig.json
{
  "compilerOptions": {
    "target": "ESNext",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "strict": true,
    "types": ["node"]
  }
}
EOF

1.3. Configure environment variables

Create an .env file in the project directory:
Shell
touch .env
Then, add your credentials. Replace YOUR_PRIVATE_KEY with the private key for your Ethereum wallet and YOUR_KIT_KEY with the kit key from the Circle Console:
.env
PRIVATE_KEY=YOUR_PRIVATE_KEY
KIT_KEY=YOUR_KIT_KEY
Edit .env files in your IDE or editor so credentials are not leaked to your shell history.

Step 2. Perform the swap

This step shows you how to set up your script, execute a swap from USDT to USDC on Ethereum, and check the result.

2.1. Create the script

Create an index.ts file in the project directory and add the following code. This code swaps 1.00 USDT for USDC on Ethereum:
Using other tokens or a different blockchain? Change the tokenIn, tokenOut, and chain values in kit.swap() and use an adapter for that chain.
TypeScript
// Import App Kit and its dependencies
import { AppKit } from "@circle-fin/app-kit";
import { createViemAdapterFromPrivateKey } from "@circle-fin/adapter-viem-v2";
import { inspect } from "util";

// Initialize the SDK
const kit = new AppKit();

const swapUSDTtoUSDC = async (): Promise<void> => {
  try {
    // Initialize the adapter
    const adapter = createViemAdapterFromPrivateKey({
      privateKey: process.env.PRIVATE_KEY as string,
    });

    console.log("---------------Starting Swapping---------------");

    const result = await kit.swap({
      from: { adapter, chain: "Ethereum" }, // Adapter and blockchain for the swap
      tokenIn: "USDT", // Token to swap
      tokenOut: "USDC", // Token to receive
      amountIn: "1.00", // Amount of tokenIn to swap (human-readable)
      config: {
        kitKey: process.env.KIT_KEY as string, // Your kit key from the Circle Console
      },
    });

    console.log("RESULT", inspect(result, false, null, true));
  } catch (err) {
    console.log("ERROR", inspect(err, false, null, true));
  }
};

void swapUSDTtoUSDC();

2.2. Run the script

Save the index.ts file and run the script in your terminal:
Shell
npx tsx --env-file=.env index.ts

2.3. Verify the transaction

After the script finishes, find the returned steps array in the terminal output. Each transaction step includes an explorerUrl. Use that link to verify the amount matches how much USDC was received. The following code is an example of how the result of a successful swap might look in the terminal output. The values are used in this example only and are not a real transaction:
Shell
{
  tokenIn: 'USDT',
  tokenOut: 'USDC',
  chain: {
    type: 'evm',
    chain: 'Ethereum',
    name: 'Ethereum',
    title: 'Ethereum Mainnet',
    nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
    chainId: 1,
    isTestnet: false,
    explorerUrl: 'https://etherscan.io/tx/{hash}',
    rpcEndpoints: [ 'https://eth.merkle.io', 'https://ethereum.publicnode.com' ],
    eurcAddress: '0x1aBaEA1f7C830bD89Acc67eC4af516284b1bC33c',
    usdcAddress: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
    usdtAddress: '0xdac17f958d2ee523a2206206994597c13d831ec7',
    cctp: {
      domain: 0,
      contracts: {
        v1: {
          type: 'split',
          tokenMessenger: '0xbd3fa81b58ba92a82136038b25adec7066af3155',
          messageTransmitter: '0x0a992d191deec32afe36203ad87d7d289a738f81',
          confirmations: 65
        },
        v2: {
          type: 'split',
          tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
          messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
          confirmations: 65,
          fastConfirmations: 2
        }
      }
    },
    kitContracts: {
      bridge: '0xB3FA262d0fB521cc93bE83d87b322b8A23DAf3F0',
      adapter: '0x7FB8c7260b63934d8da38aF902f87ae6e284a845'
    }
  },
  amountIn: '1.00',
  amountOut: '0.99',
  fromAddress: '0x1234123412341234123412341234123412341234',
  toAddress: '0xabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd',
  txHash: '0x78abb6a896e6b166925cae122b6ab2a6abd49ba23cbbd4749c99d5cccf205897',
  explorerUrl: 'https://etherscan.io/tx/0x78abb6a896e6b166925cae122b6ab2a6abd49ba23cbbd4749c99d5cccf205897',
  fees: [ { token: 'USDT', amount: '0.001', type: 'provider' } ],
  config: {
    kitKey: 'KIT_KEY:fdd99fdbdb3c87b9b3f7b29d6cc17b6e:cc8777b4e419eb6dda9f0de932cf0bb8',
  }
}

Next steps