For AI agents: a documentation index is available at the root level at /llms.txt and /llms-full.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Contact SupportDiscordGo to dashboard
HomeDocsAPI ReferenceLiquidity IntegrationChangelog
HomeDocsAPI ReferenceLiquidity IntegrationChangelog
  • Introduction
    • Welcome
    • Supported Chains and Providers
    • Demo Apps
    • FAQ
    • API Issues & Error Codes
    • Need Help?
  • Swap API
    • Introduction
      • Swap Tokens with Swap API
      • Onchain Swaps for Exchanges
      • Build Token Swap App (Next.js)
      • Monetize Your App
      • Troubleshooting
    • FAQ
  • Gasless API
    • Introduction
    • Gasless FAQ
  • Solana Swap API
    • Introduction
    • Gasless FAQ
  • Cross-Chain API
    • Introduction
    • Learn More
  • Trade Analytics API
    • Introduction
    • Transaction Data
    • Trade Analytics FAQ
  • Core Concepts
    • Introduction to 0x
    • 0x Cheat Sheet
    • Contracts
    • Order Types
    • Glossary
    • White Paper
    • Transaction Data
  • Developer Resources
    • Bounties
    • Rate Limits
    • System Status
  • Upgrading
    • Overview
    • Upgrading to Swap v2
    • Upgrading to Gasless v2
  • Need Help?
    • FAQ
    • API Issues & Error Codes
    • Contact Support
    • Contact Sales
LogoLogo
Contact SupportDiscordGo to dashboard
On this page
  • Try it Out
  • What We’re Building
  • Pre-requisites
  • Core Concepts
  • 🌈 RainbowKit
  • What is it?
  • Code
  • Setup WalletConnect projectId in providers.tsx
  • 🏷 PriceView
  • What is it?
  • UX flow
  • Code
  • Fetch Indicative Price
  • Token Allowances & Approvals
  • 💸 QuoteView
  • What is it?
  • UX Flow
  • Code
  • Fetch Firm Quote
  • Submit Transaction
  • 🪙 Token lists
  • What is it?
  • Commonly Used Token List Sources
  • Code
  • Monetize Your Swap Integration
  • Conclusion
Swap APIGuides

Build a Token Swap App (AllowanceHolder)

||View as Markdown|
Was this page helpful?
Edit this page
Previous

Onchain Swaps for Exchanges

Next

Monetize Your App

Built with

This guide walks through building a token swap app in Next.js using the 0x Swap API (AllowanceHolder).

It highlights the core concepts used in production apps like Matcha.xyz and can be adapted to any swap interface.

Try it Out

Code for the demo app used in this tutorial: https://github.com/0xProject/0x-examples/tree/main/swap-v2-allowance-holder-next-app

What We’re Building

This example demonstrates:

  • Fetching indicative prices via /swap/allowance-holder/price
  • Fetching firm executable quotes via /swap/allowance-holder/quote
  • Approving ERC20 allowances for AllowanceHolder
  • Submitting swap transactions on-chain

Video tutorial version here:

Pre-requisites

You should be familiar with:

  • React
  • Next.js
  • wagmi
  • viem
  • Swap API concepts (intro or video)

This demo uses Base, but works on all supported chains.

Core Concepts

You’ll build:

  • 🌈 RainbowKit for wallet connection
  • 🏷 PriceView (indicative pricing)
  • 💸 QuoteView (firm quotes + submit transaction)
  • 🪙 Token list management

These components form the foundation of most swap apps:

Swap v2 App Core Concepts

🌈 RainbowKit

What is it?

RainbowKit is a React library that makes it easy to add wallet connection to your app. We are using their Next.js App Router example in our app.

Check out their installation instructions to understand the configurations. You can configure your desired chains and generate the required connectors.

Code

Setup WalletConnect projectId in providers.tsx

RainbowKit relies on WalletConnect. Obtain a free projectId from WalletConnect Cloud and replace the key in the .env file.

1// Inside /swap-v2-next-app/.env
2# To get a RainbowKit relies on WalletConnect, get a free projectId here:
3# https://cloud.walletconnect.com/app
4NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID="ADD_YOUR_KEY"
1// Inside /app/providers/tsx
2const projectId = process.env.NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID as string; // Uses your free key setup in .env

🏷 PriceView

What is it?

PriceView displays indicative pricing using/swap/allowance-holder/price. Indicative pricing is for users to browse for a price without committing to a trade.

Indicative prices:

  • Do not reserve liquidity
  • Are ideal for browsing or real-time updates
  • Avoid unnecessary /quote calls, which should only be used when the user intends to trade

Firm quotes are fetched later in QuoteView.

UX flow

  1. Select tokens
  2. Enter amount → triggers indicative price fetch
  3. Connect wallet (RainbowKit handles network switching)
  4. Approve allowance for AllowanceHolder
  5. Review trade → proceed to QuoteView

Code

  • Component: /app/components/price.tsx
  • Rendered when user has not clicked “Review Trade” (controlled here in page.tsx)
  • Price requests are routed through /app/api/price/route.ts to avoid exposing your API key

Fetch Indicative Price

  • Triggered via useEffect in /app/components/price.tsx whenever tokens, amounts, or chain changes
  • Price requests are routed through /app/api/price/route.ts to avoid exposing your API key

Token Allowances & Approvals

Important: Read Before Using 0x API

  • NEVER set an allowance on the Settler contract. Doing so may result in unintended consequences, including potential loss of tokens or exposure to security risks. The Settler contract does not support or require token allowances for its operation. Setting an allowance on the Settler contract will lead to misuse by other parties.

  • ONLY set allowances on AllowanceHolder or Permit2 contracts, as indicated by the API responses.

  • The correct allowance target is returned in issues.allowance.spender or allowanceTarget.

Before placing a trade on the PageView, users must set allowances on all tokens involved. A token allowance lets a third party move funds on your behalf. Essentially, you permit them to move your tokens.

In our case, we want to approve an allowance for AllowanceHolder contract to trade our ERC20 tokens for us. To do this, we need to approve a specific allowance, allowing this contract to move a certain amount of our ERC20 tokens on our behalf. Read more about token allowances.

token allowance ui

The logic to check if the user has approved a token allowance the selected sell token is setup in /app/components/price.ts.

  1. Read existing allowance with useReadContract
  2. If insufficient → simulate + write approval (useSimulateContract, useWriteContract)
  3. Wait for confirmation using useWaitForTransactionReceipt

Be aware that approvals cost gas. Looking for a gasless approach? Check out Gasless API.

Need to quickly revoke an allowance while testing? To revoke an allowance, you can set the allowance to 0. This can be done programmatically or through a UI such as https://revoke.cash/ .

💸 QuoteView

What is it?

QuoteView displays a firm, executable quote returned from /swap/allowance-holder/quote.

Firm quotes:

  • Reserve liquidity from market makers
  • Contain a fully executable order

swap demo quoteview

UX Flow

  • Shows final sell and buy amounts
  • Metadata (symbols, decimals) comes from the token list
  • User clicks “Place Order” to sign and broadcast the transaction

Code

  • Component: /app/components/quote.tsx
  • Rendered after:
    1. Allowance approval
    2. Clicking Review Trade

Fetch Firm Quote

  • Triggered via useEffect in /app/components/quote.tsx whenever tokens, amounts, or chain changes
  • Price requests are routed through /app/api/quote/route.ts to avoid exposing your API key

Submit Transaction

The last step is to submit the transaction with all the required parameters using your preferred web3 library (e.g. wagmi, viem, ethers.js, web3.js). In this example, we use wagmi’s useSendTransaction.

Pass the required params we get from the quote response to sendTransaction. Code here.

1sendTransaction({
2 account: walletClient?.account.address,
3 gas: !!quote?.transaction.gas ? BigInt(quote?.transaction.gas) : undefined,
4 to: quote?.transaction.to,
5 data: quote?.transaction.data,
6 chainId: chainId,
7});

🪙 Token lists

What is it?

Token Lists provide curated sets of ERC20 tokens—along with their associated metadata—that applications can use when enabling asset selection (e.g., choosing tokens to swap). These lists typically include:

  • Name (e.g., Wrapped Ether)
  • Symbol (e.g., ETH)
  • Contract address
  • logoURI

Developers can either consume an existing list in full or create a customized list derived from one or more established sources.

Commonly Used Token List Sources

  • QuickNode Token API: https://www.quicknode.com/token-api

  • Trust Wallet Assets: https://github.com/trustwallet/assets/tree/master/blockchains

  • Polygon Token Assets: https://github.com/maticnetwork/polygon-token-assets/tree/main/assets/tokenAssets

  • TokenLists Registry: https://tokenlists.org/

  • CoinGecko Token List: https://tokenlists.org/token-list?url=https://tokens.coingecko.com/uniswap/all.json

Code

The demo uses a curated a token list in /src/constants.ts. In production level apps, it’s common practice to maintain a token list since some apps don’t support all available tokens.

Monetize Your Swap Integration

Swap API provides two built-in ways to monetize your swap integration—available on both free and paid plan:

  • Affiliate fees: Earn a commission on each trade (demonstrated in this example app).
  • Trade surplus: trade surplus (i.e. positive slippage) 1

For implementation details and pricing considerations, see the how to monetize your app using 0x Swap API.

1 Trade surplus is available only to select integrators on a custom plan. Contact support for access.

Conclusion

By following the best practices outlined in this blog post, you can create a user-friendly and effective app that enables trustless token swapping on our supported chains.

You now have a fully functional swap workflow that demonstrates:

  • Indicative pricing
  • Firm quotes
  • Setting token allowances
  • Submitting transactions on-chain

This pattern works across all supported chains..

Happy swapping!