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%

Waitingreading
Reading 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
LivePrice from 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
swap.ts
TS33 lines
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%

Waiting

Reading the pool at the latest block

Base

Waiting
Base 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.

Base · Block — · —