SV3 logo

createSv3Client

Create the SV3 TypeScript client from a viem Public Client and a deployment manifest.

Creates a sv3Client. This is the only supported way to talk to SV3 from TypeScript.

The client does not connect a wallet, choose an RPC, or import React. You pass a viem Public Client (and optionally a Wallet Client), the same pattern as createPublicClient / createWalletClient.

Import

import { createSv3Client, createReadOnlySv3Client } from "@repo/contract-client";

createFloorSdk / createReadOnlyFloorSdk are deprecated aliases.

Usage

import { createPublicClient, http } from "viem";
import { foundry } from "viem/chains";
import { createSv3Client } from "@repo/contract-client";
import { ANVIL_CHAIN_ID, ANVIL_DEPLOYMENT_MANIFEST } from "@repo/chain-config";

const publicClient = createPublicClient({
  chain: foundry,
  transport: http("http://127.0.0.1:8545"),
});

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…",
    },
  },
});

With a wallet, so prepare* and executePrepared can run:

import { createWalletClient, custom } from "viem";

const walletClient = createWalletClient({
  chain: foundry,
  transport: custom(window.ethereum),
});

const [account] = await walletClient.getAddresses();

const sv3 = createSv3Client({
  publicClient,
  walletClient,
  account,
  chainId: ANVIL_CHAIN_ID,
  deployment,
});

Or bind later:

const writable = sv3.withWalletClient(walletClient).withAccount(account);

Read-only (writes throw WalletClientRequiredError):

const sv3 = createReadOnlySv3Client({
  publicClient,
  chainId: ANVIL_CHAIN_ID,
  deployment,
});

Return Value

sv3Client

Namespaces: market, factory, directory, token, quote, trade, position, authorization, transactions, floor, network, events, errors, revenue, metrics, units, math.

Helpers on the client:

MethodMeaning
withWalletClient(walletClient)Returns a new client that can send
withAccount(account)Binds the address that must match prepared transactions
withBlockTag(tag)Pins later reads to this tag
getConfig()Sanitized config (no secrets)
getSdkVersion(){ version }
assertSupportedChain()Throws UnsupportedChainError on mismatch
assertDeployment()Reloads directory pointers
getMarket(address)Identity plus a snapshot

Parameters

publicClient

  • Type: PublicClient

Required. viem public client used for reads, multicall, and simulateContract.

const sv3 = createSv3Client({
  publicClient,
  chainId: ANVIL_CHAIN_ID,
  deployment,
});

chainId

  • Type: 8453 | 31337

Must match publicClient.chain.id when that is set. Any other chain throws UnsupportedChainError.

const sv3 = createSv3Client({
  publicClient,
  chainId: 31337,
  deployment,
});

deployment

  • Type: DeploymentManifest

Proxy addresses and curve metadata for this chain. Spread ANVIL_DEPLOYMENT_MANIFEST or BASE_DEPLOYMENT_MANIFEST from @repo/chain-config, then fill contracts.

Required contract fields for a working client:

FieldAddress of
directoryProxyDirectory
factoryProxyFactory
marketBeaconUpgradeable beacon
marketImplementationFloorMarket implementation
floorPolicyControllerProxyFloor policy controller
floorMarketQuoterView-only quoter

deployment.curveLibrary (kind, revision, sourceHash) gates local math. Unknown revisions throw UnsupportedCurveRevisionError.

See Deployments.

const sv3 = createSv3Client({
  publicClient,
  chainId: ANVIL_CHAIN_ID,
  deployment: {
    ...ANVIL_DEPLOYMENT_MANIFEST,
    contracts: {/* proxies */},
  },
});

walletClient (optional)

  • Type: WalletClient

Needed to send. Reads and local quotes work without it.

const sv3 = createSv3Client({
  publicClient,
  walletClient,
  account,
  chainId: ANVIL_CHAIN_ID,
  deployment,
});

account (optional)

  • Type: Address | Account

The account that must match prepared transactions. Bound later with sv3.withAccount.

const sv3 = createSv3Client({
  publicClient,
  walletClient,
  account: "0x…",
  chainId: ANVIL_CHAIN_ID,
  deployment,
});

defaultDeadlineSeconds (optional)

  • Type: number
  • Default: 300

Attached to prepared writes. Values above maxDeadlineSeconds throw InvalidDeadlineError.

const sv3 = createSv3Client({
  publicClient,
  chainId: ANVIL_CHAIN_ID,
  deployment,
  defaultDeadlineSeconds: 120,
});

maxDeadlineSeconds (optional)

  • Type: number
  • Default: 1800
const sv3 = createSv3Client({
  publicClient,
  chainId: ANVIL_CHAIN_ID,
  deployment,
  maxDeadlineSeconds: 600,
});

defaultConfirmations (optional)

  • Type: number
  • Default: 1

Passed to wait unless overridden.

const sv3 = createSv3Client({
  publicClient,
  chainId: ANVIL_CHAIN_ID,
  deployment,
  defaultConfirmations: 2,
});

multicall (optional)

  • Type: { deployless?: boolean; address?: Address }

Anvil defaults to deployless multicall. Base uses the chain Multicall3 unless you set address.

const sv3 = createSv3Client({
  publicClient,
  chainId: 8453,
  deployment,
  multicall: { address: "0xcA11bde05977b3631167028862bE2a173976CA11" },
});

permitCapability (optional)

  • Type: 'none' | 'eip2612'
  • Default: 'none'

Contract wallets use the allowance route unless this is 'eip2612'. See getRequirements.

const sv3 = createSv3Client({
  publicClient,
  chainId: ANVIL_CHAIN_ID,
  deployment,
  permitCapability: "eip2612",
});

logger (optional)

  • Type: { debug, info, warn, error }

Must not log secrets or authorization headers.

Error

ErrorWhen
UnsupportedChainErrorchainId is not 8453 or 31337, or it disagrees with publicClient.chain.id
InvalidSdkConfigErrordeployment is missing

Tips

  • The client is cheap to construct. Prefer one instance per chain, then withAccount per connected wallet.
  • getConfig() is safe to log. It does not include the wallet, RPC URL, or keys.