Swap tokens

Build a token swap using the OpenSea API and SDK.

Use the OpenSea API to swap tokens across chains, with no manual bridging required. This guide covers getting a quote, executing the swap, and discovering tokens.

Prerequisites

Security Warning: Do not use the SDK in client-side code, since your API key would be exposed. Use it on a backend server and return transaction data to your frontend.

Setup

npm install @opensea/sdk viem
import { createPublicClient, createWalletClient, http } from "viem";
import { base } from "viem/chains";
import { OpenSeaSDK, Chain } from "@opensea/sdk/viem";

const publicClient = createPublicClient({ chain: base, transport: http("https://your-rpc-url") });
const walletClient = createWalletClient({ chain: base, transport: http("https://your-rpc-url"), account: "0x..." });

const sdk = new OpenSeaSDK(
  { publicClient, walletClient },
  { chain: Chain.Base, apiKey: "YOUR_API_KEY" },
);

The examples below use viem. The SDK also supports ethers.js (v6+); see Buy and sell NFTs for the ethers setup. All SDK methods work the same with either library.

Step 1: Discover tokens

Before swapping, you can discover which tokens are available using the trending and top token endpoints.

SDK

// Get trending tokens (ranked by OpenSea's trending score)
const trending = await sdk.api.tokens.getTrendingTokens();
console.log(trending);

// Get top tokens by volume
const top = await sdk.api.tokens.getTopTokens();
console.log(top);

curl

# Trending tokens
curl -X GET "https://api.opensea.io/api/v2/tokens/trending" \
  -H "X-API-KEY: YOUR_API_KEY"

# Top tokens
curl -X GET "https://api.opensea.io/api/v2/tokens/top" \
  -H "X-API-KEY: YOUR_API_KEY"

Step 2: Check your balance

Confirm your wallet holds enough of the source token.

SDK

const balances = await sdk.api.accounts.getAccountTokens("0xYOUR_WALLET_ADDRESS");
console.log(balances);

curl

curl -X GET "https://api.opensea.io/api/v2/account/0xYOUR_WALLET_ADDRESS/tokens" \
  -H "X-API-KEY: YOUR_API_KEY"

Step 3: Get a swap quote

Request a quote to see the price and costs in USD, the price impact, the slippage settings, and the transaction data needed to execute the swap.

Parameters:

ParameterDescription
from_chainSource chain (e.g. base)
from_addressToken contract address to sell (use 0x0000000000000000000000000000000000000000 for native ETH)
to_chainDestination chain (e.g. base, or a different chain for cross-chain)
to_addressToken contract address to buy
quantityAmount to swap in the token's smallest unit, as an integer string (wei for ETH: 20000000000000000 is 0.02 ETH)
addressYour wallet address (the taker)
slippage(Optional) Slippage tolerance from 0.0 to 0.5. Defaults to 0.01
recipient(Optional) Address that receives the bought tokens. Defaults to address

The SDK takes these parameters in camelCase (fromChain, fromAddress, toChain, toAddress). The raw REST endpoint shown in the curl example uses the snake_case names above.

SDK

const quote = await sdk.api.tokens.getSwapQuote({
  fromChain: "base",
  fromAddress: "0x0000000000000000000000000000000000000000", // native ETH
  toChain: "base",
  toAddress: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", // USDC on Base
  quantity: "20000000000000000", // 0.02 ETH in wei
  address: "0xYOUR_WALLET_ADDRESS",
});

console.log("Quote:", quote);
// quote.transactions contains the transaction(s) to execute

curl

curl -X GET "https://api.opensea.io/api/v2/swap/quote?\
from_chain=base&\
from_address=0x0000000000000000000000000000000000000000&\
to_chain=base&\
to_address=0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913&\
quantity=20000000000000000&\
address=0xYOUR_WALLET_ADDRESS" \
  -H "X-API-KEY: YOUR_API_KEY"

The response includes a transactions array. Each transaction contains:

  • chain: the chain to submit the transaction on
  • to: the target contract address (null for Solana transactions, which carry their instructions in svm instead)
  • data: hex-encoded calldata
  • value: native token value to send (if any)

Step 4: Execute the swap

Use the transaction data from the quote response to submit the swap onchain. This example uses viem, so it submits EVM transactions only. A Solana transaction has to: null and carries its instructions in svm, which you submit with a Solana client instead.

import type { Address, Hex } from "viem";

for (const tx of quote.transactions) {
  if (!tx.to) {
    throw new Error(`Transaction on ${tx.chain} is not EVM: submit tx.svm with a Solana client`);
  }

  const hash = await walletClient.sendTransaction({
    to: tx.to as Address,
    data: tx.data as Hex,
    value: tx.value ? BigInt(tx.value) : 0n,
  });

  console.log("Transaction hash:", hash);
  const receipt = await publicClient.waitForTransactionReceipt({ hash });
  console.log("Confirmed in block:", receipt.blockNumber);
}

Cross-chain swaps

Cross-chain swaps work the same way. Specify a different toChain and the API handles bridging automatically.

const crossChainQuote = await sdk.api.tokens.getSwapQuote({
  fromChain: "ethereum",
  fromAddress: "0x0000000000000000000000000000000000000000",
  toChain: "base",
  toAddress: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
  quantity: "100000000000000000", // 0.1 ETH in wei
  address: "0xYOUR_WALLET_ADDRESS",
});

Cross-chain swaps may return multiple transactions (e.g. an approval and a bridge transaction). Execute them in order.

CLI

The OpenSea CLI supports swap quotes directly. Unlike the API, it accepts a decimal --quantity and converts it to the token's smallest unit:

opensea swaps quote \
  --from-chain base \
  --from-address 0x0000000000000000000000000000000000000000 \
  --to-chain base \
  --to-address 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 \
  --quantity 0.02 \
  --address 0xYOUR_WALLET_ADDRESS

Next steps