The order book is a public object
On Base, the liquidity behind a price is a contract anyone can read. This is a real pool, band by band, and what a swap of your size would eat.
Uniswap v3 · WETH/USDC 0.05%
WaitingreadingReading the pool at the latest block
One column per price band, as tall as the dollars in it. Left of the line is USDC; right is WETH, the side a buy eats.
Waiting for the Quoter
App
Your app
Pay · USDC
ReceiveSim
Reading the pool
Sim
- Price impact
- —
- Pool fee 0.05%
- —
- Price after
- —
Receive, impact and fee are our walk through the pool's live ticks. The swap itself is simulated.
Code
import { createPublicClient, createWalletClient, custom, erc20Abi, http, parseAbi, parseUnits } from 'viem'import { base } from 'viem/chains'const USDC = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913'const WETH = '0x4200000000000000000000000000000000000006'const QUOTER = '0x3d4e44Eb1374240CE5F1B871ab261CD16335B76a' // Uniswap v3 QuoterV2const ROUTER = '0x2626664c2603336E57B271c5C0b26F421741e481' // Uniswap v3 SwapRouter02const quoterAbi = parseAbi([ 'function quoteExactInputSingle((address tokenIn, address tokenOut, uint256 amountIn, uint24 fee, uint160 sqrtPriceLimitX96) params) returns (uint256 amountOut, uint160 sqrtPriceX96After, uint32 initializedTicksCrossed, uint256 gasEstimate)',])const routerAbi = parseAbi([ 'function exactInputSingle((address tokenIn, address tokenOut, uint24 fee, address recipient, uint256 amountIn, uint256 amountOutMinimum, uint160 sqrtPriceLimitX96) params) payable returns (uint256 amountOut)',])// Connect a wallet on Base and pick an amount: 1,000 USDC, which has 6 decimals.const wallet = createWalletClient({ chain: base, transport: custom(window.ethereum!) })const client = createPublicClient({ chain: base, transport: http() })const [account] = await wallet.requestAddresses()const amountIn = parseUnits('1000', 6)// Ask the 0.05% pool what that buys right now. The Quoter simulates the swap; nothing is sent.const { result: [quoted] } = await client.simulateContract({ address: QUOTER, abi: quoterAbi, functionName: 'quoteExactInputSingle', args: [{ tokenIn: USDC, tokenOut: WETH, amountIn, fee: 500, sqrtPriceLimitX96: 0n }],})// Let the router pull the USDC.const approval = await wallet.writeContract({ account, address: USDC, abi: erc20Abi, functionName: 'approve', args: [ROUTER, amountIn],})await client.waitForTransactionReceipt({ hash: approval })// Swap, and refuse to fill for less than 99.5% of the quote.const swap = await wallet.writeContract({ account, address: ROUTER, abi: routerAbi, functionName: 'exactInputSingle', args: [{ tokenIn: USDC, tokenOut: WETH, fee: 500, recipient: account, amountIn, amountOutMinimum: quoted * 9950n / 10000n, sqrtPriceLimitX96: 0n }],})await client.waitForTransactionReceipt({ hash: swap })Review a swap to see the code and the chain
Chain
Uniswap v3 · WETH/USDC 0.05%
WaitingReading the pool at the latest block
Base
WaitingBase block
Waiting
Gas for the pool swap
—
Waiting for the gas price
Review a swap to see the code and the chain
The swap sheet is simulated: nothing is traded and no wallet is involved. The columns, the price and the quote are read from the Uniswap v3 WETH/USDC pool on Base as of the block shown. A quote is not a fill; a real swap sets a minimum it will accept.