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:
| Method | Meaning |
|---|---|
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:
| Field | Address of |
|---|---|
directoryProxy | Directory |
factoryProxy | Factory |
marketBeacon | Upgradeable beacon |
marketImplementation | FloorMarket implementation |
floorPolicyControllerProxy | Floor policy controller |
floorMarketQuoter | View-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
| Error | When |
|---|---|
UnsupportedChainError | chainId is not 8453 or 31337, or it disagrees with publicClient.chain.id |
InvalidSdkConfigError | deployment is missing |
Tips
- The client is cheap to construct. Prefer one instance per chain, then
withAccountper connected wallet. getConfig()is safe to log. It does not include the wallet, RPC URL, or keys.