Skip to main content
CDP Wallets provide a convenient way to execute swaps. This feature combines the core Trade APIs (which handle price discovery and quote creation) with the CDP Wallet’s ability to sign and broadcast transactions.

Any ERC-20 Pair

Swap between any supported tokens using contract addresses

Price Discovery

Get indicative prices with fee and slippage estimates before executing

Smart Account Support

Works with both EOAs and ERC-4337 Smart Accounts

Gas Sponsorship

Built-in Paymaster support for gasless Smart Account swaps
Swaps are EVM only and supported on mainnet networks: Base, Ethereum, Arbitrum, Optimism, and Polygon. Testnet is not supported.

Get a price

Fetch a non-binding price estimate before executing. Check the issues field to surface problems like insufficient balance or missing token allowance before the user confirms.

User authentication

import { useGetSwapPrice } from "@coinbase/cdp-hooks";

const { data, status } = useGetSwapPrice({
  network: "base",
  fromToken: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", // USDC
  toToken: "0x4200000000000000000000000000000000000006",   // WETH
  fromAmount: "1000000", // 1 USDC in atomic units (6 decimals)
  slippageBps: 100,      // 1% max slippage
});

if (data?.liquidityAvailable) {
  console.log("Expected output:", data.toAmount);
  console.log("Minimum after slippage:", data.minToAmount);
  console.log("Network fee:", data.totalNetworkFee);
}

API key authentication

See Trade API: Price discovery for how to get a quote using CDP EVM accounts.

Execute a swap

User authentication

useSwap tracks the full lifecycle through on-chain confirmation. For EOA accounts it waits for a transaction receipt; for Smart Accounts it polls the user operation until completion.
import { useSwap } from "@coinbase/cdp-hooks";

function ExecuteSwap() {
  const { swap, status, data, error } = useSwap();

  const handleSwap = async () => {
    await swap({
      network: "base",
      fromToken: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
      toToken: "0x4200000000000000000000000000000000000006",
      fromAmount: "1000000",
      slippageBps: 100,
    });
  };

  return (
    <div>
      <button onClick={handleSwap} disabled={status === "pending"}>
        {status === "pending" ? "Swapping..." : "Swap"}
      </button>
      {status === "success" && data && (
        <p>Swap confirmed. Received: {data.toAmount}</p>
      )}
      {error && <p>Swap failed: {error.message}</p>}
    </div>
  );
}
The result is a discriminated union based on account type: "evm-eoa" results include a transactionHash, while "evm-smart" results include a userOpHash. Both include the resolved token addresses, amounts, fees, and network fee estimate. See ExecuteSwapResult for the full type.
When using the useSwap hook, the data object is enriched with confirmation details: receipt for EOA transactions, and transactionHash / receipts / userOperation for Smart Accounts. These values are populated once the operation completes on-chain.

API key authentication

CDP EVM accounts support two approaches:
  1. All-in-one swap (recommended): submit a swap in a single call.
  2. Quote, then swap (advanced): create a quote first, then execute. Useful for inspecting swap details or applying custom logic before committing.
See the Trade API quickstart for code examples:

Token approvals

Swaps use Permit2 for token transfers. The CDP Swap API signs the per-swap Permit2 permit automatically, but the fromToken must have an ERC-20 approval to the Permit2 contract.
Use getSwapPrice / useGetSwapPrice to check before executing. If issues.allowance is non-null, the taker needs to approve issues.allowance.spender (the Permit2 contract) for at least fromAmount. Approving a larger amount avoids re-approving on every swap.

Gas sponsorship

For Smart Account users, pass useCdpPaymaster: true to enable gasless swaps on Base, or provide a custom paymasterUrl for any ERC-7677-compatible paymaster. These options are ignored for EOA accounts.
useCdpPaymaster is only supported on Base. For other chains, use paymasterUrl. You cannot specify both.

Account selection

By default, the SDK auto-selects the taker account:
ConfigurationResult
1 Smart Account + 1 EOAPrefers the Smart Account
1 EOA onlyUses the EOA
Multiple accountsError: must specify account explicitly

Error handling

Swap failures throw a SwapError with a typed code:
import { executeSwap, SwapError } from "@coinbase/cdp-core";

try {
  await executeSwap({ /* ... */ });
} catch (err) {
  if (err instanceof SwapError) {
    switch (err.code) {
      case "INSUFFICIENT_BALANCE":
        console.log("Not enough tokens to swap");
        break;
      case "INSUFFICIENT_LIQUIDITY":
        console.log("No route available. Try a different pair or amount.");
        break;
      default:
        console.log("Swap error:", err.message);
    }
  }
}
When using useSwap, check the returned error value instead of a try/catch.

FAQ

Tokens are identified by their 0x-prefixed ERC-20 contract address on the target network. The same token (e.g., USDC) has different addresses on different networks. You can find contract addresses on block explorers like Basescan or Etherscan.
fromAmount must be a positive integer string in atomic units (the smallest denomination of the token). For example, USDC has 6 decimals, so 1 USDC = "1000000". WETH has 18 decimals, so 0.1 WETH = "100000000000000000".
slippageBps sets the maximum acceptable price impact in basis points (1 bps = 0.01%). The default is 100 (1%), applied by the API when omitted. If the price moves beyond this threshold between the quote and execution, the transaction will revert to protect the user.
Swaps are currently available on mainnet networks only (Base, Ethereum, Arbitrum, Optimism, Polygon). Testnet support is not yet available.
Yes. Use the sentinel address 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE as fromToken or toToken to represent the chain’s native token (ETH on Ethereum/Base/Arbitrum/Optimism, POL on Polygon). No Permit2 approval is needed for native tokens.
The CDP Swap API handles the per-swap Permit2 signature automatically. However, the fromToken must have an ERC-20 approval to the Permit2 contract. See Token approvals for details.
executeSwap (core) returns a Promise that resolves with the swap result (transaction hash or user op hash) as soon as it’s submitted. useSwap (hooks) additionally tracks on-chain confirmation: status stays "pending" until the transaction receipt (EOA) or user operation (Smart Account) is confirmed, then moves to "success".

Reference

@coinbase/cdp-core

ResourceDescription
getSwapPriceGet an indicative price
executeSwapExecute a swap
GetSwapPriceOptionsParameters for price requests
GetSwapPriceResultPrice response when liquidity is available
SwapUnavailableResultPrice response when no route exists
ExecuteSwapOptionsParameters for swap execution
ExecuteSwapResultSwap result type (EOA / Smart Account)
SwapErrorTyped error class for swap failures

@coinbase/cdp-hooks

ResourceDescription
useGetSwapPriceReactive price fetching
useSwapExecute and track a swap
UseGetSwapPriceOptionsOptions for useGetSwapPrice
UseGetSwapPriceReturnTypeReturn type of useGetSwapPrice
UseSwapReturnTypeReturn type of useSwap
SwapTransactionDataHook swap result (EOA / Smart Account)