SV3 logo

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.

1
Create a viem Public Client

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.

2
Create an SV3 client

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.

3
Pin market state

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.reserveAllowance

Snapshot only: getQuoteState. Snapshot plus wallet balances: getTradeContext. Snapshot plus a position: getAccountContext.

4
Quote locally

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.totalPriceImpactWad

Every math function has its own page, starting with quoteBuyExactReserveIn. Units: parseUsdc.

5
Prepare, check allowance, simulate, send

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.

NamespaceUse
sv3.marketgetQuoteState, getTradeContext, getAccountContext
sv3.quoteSame math as /math, but loads chain state if you pass a market address
sv3.tradeprepare* — encodes calldata, does not send
sv3.authorizationgetRequirements
sv3.transactionsexecutePrepared, wait, simulatePrepared / sendPrepared
sv3.floorquoteNextRaise, raiseIfEligible
sv3.networkgetBalance, getTransactionCount, getBlock
sv3.errorsparse / toError
sv3.mathRe-export of @repo/contract-client/math

Bind a wallet later with sv3.withWalletClient(walletClient).withAccount(address).

What's next

createSv3Client

Parameters, wallet binding, and the deployment object.

quoteBuyExactReserveIn

First math call: exact USDC in, AVM out, fees, impact.