---
title: Getting started
description: Install the SV3 TypeScript SDK, create a client, pin a market snapshot, and quote a buy.
---

> **For AI agents:** the complete documentation index is at [llms.txt](/llms.txt). Append `.md` to any page URL for its markdown version.

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](https://viem.sh) 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.

<Note>
  Quotes, calldata, and broadcasts belong in the SDK. Product HTTP is discovery and history only.
</Note>

## Install

The package is not on npm yet. In this monorepo:

```bash
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](https://viem.sh) clients in, the same way you construct a viem Public Client before calling actions.

<Steps>
  <Step title="Create a viem Public Client">
    Point viem at Anvil (`31337`) or Base (`8453`).

    ```ts
    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.

  </Step>

  <Step title="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.

    ```ts
    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](/developers/create-sv3-client). Where the addresses come from: [Deployments](/protocol/deployments).

  </Step>

  <Step title="Pin market state">
    One block-pinned multicall. After this returns, slider quotes must not hit RPC.

    ```ts
    const context = await sv3.market.getTradeContext(market, account)
    context.snapshot.spotPriceWad
    context.reserveBalance
    context.reserveAllowance
    ```

    Snapshot only: [getQuoteState](/developers/get-quote-state). Snapshot plus wallet balances: [getTradeContext](/developers/get-trade-context). Snapshot plus a position: [getAccountContext](/developers/get-account-context).

  </Step>

  <Step title="Quote locally">
    Math lives in `@repo/contract-client/math`. Amounts are branded bigints — USDC is 6 decimals, AVM is 18.

    ```ts
    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](/developers/math/quote-buy-exact-reserve-in). Units: [parseUsdc](/developers/parse-usdc).

  </Step>

  <Step title="Prepare, check allowance, simulate, send">
    `slippageBps` is required — the SDK has no hidden default. `getRequirements` is a **read**: it never sends `approve`.

    ```ts
    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](/developers/prepare-buy-for-reserve-budget). Exact-input selector: [prepareBuyExactReserveIn](/developers/prepare-buy-exact-reserve-in). Allowance / permit: [getRequirements](/developers/get-requirements). Simulate and send: [executePrepared](/developers/execute-prepared).

  </Step>
</Steps>

## Client shape

`createSv3Client` returns namespaces. You call methods on them — you do not call `readContract` from feature code.

| Namespace           | Use                                                                                                                                                  |
| ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| `sv3.market`        | [getQuoteState](/developers/get-quote-state), [getTradeContext](/developers/get-trade-context), [getAccountContext](/developers/get-account-context) |
| `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](/developers/get-requirements)                                                                                                      |
| `sv3.transactions`  | [executePrepared](/developers/execute-prepared), [wait](/developers/wait), `simulatePrepared` / `sendPrepared`                                       |
| `sv3.floor`         | [quoteNextRaise](/developers/quote-next-raise), [raiseIfEligible](/developers/raise-if-eligible)                                                     |
| `sv3.network`       | `getBalance`, `getTransactionCount`, `getBlock`                                                                                                      |
| `sv3.errors`        | [parse / toError](/developers/errors)                                                                                                                |
| `sv3.math`          | Re-export of `@repo/contract-client/math`                                                                                                            |

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

## What's next

<Columns cols={2}>
  <Card title="createSv3Client" icon="plug" href="/developers/create-sv3-client">
    Parameters, wallet binding, and the deployment object.
  </Card>
  <Card
    title="quoteBuyExactReserveIn"
    icon="function"
    href="/developers/math/quote-buy-exact-reserve-in"
  >
    First math call: exact USDC in, AVM out, fees, impact.
  </Card>
</Columns>
