Getting started
Install the SV3 TypeScript SDK, create a client, pin a market snapshot, and quote a buy.
The SDK is the TypeScript surface for SV3. Use it in a browser wallet app, a Node script, or a keeper. It talks to chain through viem and frozen interface ABIs. It does not ship Solidity or bytecode.
The package in this repo is @repo/contract-client. @sv3-protocol/sdk is the intended public name when it is published — it is not on npm yet.
Quotes, calldata, and broadcasts belong in the SDK. Product HTTP is discovery and history only.
Install
The package is not on npm yet. In this monorepo:
pnpm add @repo/contract-client viem
Depend on workspace:*. viem is already a dependency of @repo/contract-client.
Quick Start
The SDK does not open RPC connections or wallets. You pass viem clients in, the same way you construct a viem Public Client before calling actions.
Point viem at Anvil (31337) or Base (8453).
import { createPublicClient, http } from 'viem'
import { foundry } from 'viem/chains'
const publicClient = createPublicClient({
chain: foundry,
transport: http('http://127.0.0.1:8545'),
})For Base, import base from viem/chains and pass your RPC URL.
Pass the public client, the chain id, and a deployment manifest. Controller and quoter addresses are not on Directory — they must be in this object.
import { createSv3Client } from '@repo/contract-client'
import { ANVIL_CHAIN_ID, ANVIL_DEPLOYMENT_MANIFEST } from '@repo/chain-config'
const sv3 = createSv3Client({
publicClient,
chainId: ANVIL_CHAIN_ID,
deployment: {
...ANVIL_DEPLOYMENT_MANIFEST,
contracts: {
directoryProxy: '0x…',
factoryProxy: '0x…',
marketBeacon: '0x…',
marketImplementation: '0x…',
floorPolicyControllerProxy: '0x…',
floorMarketQuoter: '0x…',
},
},
})Reads and local quotes work with this client. To send, also pass walletClient and account, or call sv3.withWalletClient(walletClient).
Full parameter list: createSv3Client. Where the addresses come from: Deployments.
One block-pinned multicall. After this returns, slider quotes must not hit RPC.
const context = await sv3.market.getTradeContext(market, account)
context.snapshot.spotPriceWad
context.reserveBalance
context.reserveAllowanceSnapshot only: getQuoteState. Snapshot plus wallet balances: getTradeContext. Snapshot plus a position: getAccountContext.
Math lives in @repo/contract-client/math. Amounts are branded bigints — USDC is 6 decimals, AVM is 18.
import { parseUsdc } from '@repo/contract-client'
import { quoteBuyExactReserveIn } from '@repo/contract-client/math'
const quote = quoteBuyExactReserveIn(
context.snapshot,
parseUsdc('1'),
)
quote.avmOut
quote.fees.totalRaw
quote.priceImpact.totalPriceImpactWadEvery math function has its own page, starting with quoteBuyExactReserveIn. Units: parseUsdc.
slippageBps is required — the SDK has no hidden default. getRequirements is a read: it never sends approve.
const prepared = await sv3.trade.prepareBuyForReserveBudget({
market,
amount: parseUsdc('1'),
slippageBps: 100n,
})
const requirements = sv3.authorization.getRequirements(prepared, {
token: context.snapshot.tokens.reserve,
spender: market,
amount: prepared.constraints.maxIn ?? parseUsdc('1'),
allowance: context.reserveAllowance,
nonce: context.reservePermitNonce,
isContractWallet: context.codeSize > 0n,
tokenName: 'USD Coin',
mode: 'auto',
})
const pending = await sv3.transactions.executePrepared(prepared)
const receipt = await pending.wait()Budget helper: prepareBuyForReserveBudget. Exact-input selector: prepareBuyExactReserveIn. Allowance / permit: getRequirements. Simulate and send: executePrepared.
Client shape
createSv3Client returns namespaces. You call methods on them — you do not call readContract from feature code.
| Namespace | Use |
|---|---|
sv3.market | getQuoteState, getTradeContext, getAccountContext |
sv3.quote | Same math as /math, but loads chain state if you pass a market address |
sv3.trade | prepare* — encodes calldata, does not send |
sv3.authorization | getRequirements |
sv3.transactions | executePrepared, wait, simulatePrepared / sendPrepared |
sv3.floor | quoteNextRaise, raiseIfEligible |
sv3.network | getBalance, getTransactionCount, getBlock |
sv3.errors | parse / toError |
sv3.math | Re-export of @repo/contract-client/math |
Bind a wallet later with sv3.withWalletClient(walletClient).withAccount(address).