createOakContractsClient supports several config and signer patterns. You can mix them: for example, a read-only client with a per-entity signer for one contract, or a keyed client with per-call overrides for specific transactions.
Pattern 1 — Simple (chainId + rpcUrl + privateKey)
Full read/write access using a raw private key. Suitable for backend services and scripts.
| Field | Type | Required | Description |
|---|---|---|---|
chainId | number | Yes | Numeric chain ID (use CHAIN_IDS.* constants) |
rpcUrl | string | Yes | RPC endpoint URL for the chain |
privateKey | `0x${string}` | Yes | 0x-prefixed private key for the signer |
options | Partial<OakContractsClientOptions> | No | Client-level overrides |
Pattern 2 — Read-only (chainId + rpcUrl, no privateKey)
No private key required. All read methods work normally; write and simulate methods throw immediately — no RPC call is made. The error is thrown by requireSigner(); the message starts with No signer configured. and explains how to pass a client key, full-config signer, or per-entity signer (for example oak.globalParams(address, { signer })).
| Field | Type | Required | Description |
|---|---|---|---|
chainId | number | Yes | Numeric chain ID (use CHAIN_IDS.* constants) |
rpcUrl | string | Yes | RPC endpoint URL for the chain |
options | Partial<OakContractsClientOptions> | No | Client-level overrides |
Pattern 3 — Per-entity signer override
Pass a signer when creating an entity. Every write and simulate call on that entity uses the provided signer — you do not pass it again on each call. Use this when the signer is resolved after the client is created (browser wallets, Privy, etc.).Pattern 4 — Per-call signer override
The entity has no fixed signer. Pass a different signer for a single write or simulate call as the last optional argument. Use this when different operations on the same contract need different signers (multi-sig flows, role switching).Pattern 5 — Full (bring your own clients)
Pass pre-built viemPublicClient and WalletClient directly. Use this for custom transports, account abstraction, or when you already manage viem clients elsewhere.
| Field | Type | Required | Description |
|---|---|---|---|
chain | number | Chain | Yes | Numeric chain ID or viem Chain object |
provider | PublicClient | Yes | Viem PublicClient for on-chain reads |
signer | WalletClient | Yes | Viem WalletClient with an attached account |
options | Partial<OakContractsClientOptions> | No | Client-level overrides |
Browser wallet with full configuration
If you prefer to construct the client with provider and signer up front (instead of Pattern 3 on a read-only or minimal client):Privy wallet with full configuration
Privy embedded wallets expose an EIP-1193 provider. Pass that provider to viem’scustom transport for both createPublicClient and createWalletClient, then pass chain, provider, and signer into createOakContractsClient—the same pattern as Browser wallet with full configuration above.
The snippet uses the useWallets hook from @privy-io/react-auth to pick a wallet; replace that with whatever wallet selection logic your app uses.
Unsupported chainsIf Privy does not include your chain in its default networks, register it in the Privy provider. See Configuring EVM networks in the Privy documentation.
Signer resolution priority
When a write or simulate method runs, the signer is resolved in this order:- Per-call
options.signer— highest priority - Per-entity
signerpassed to the entity factory (e.g.oak.globalParams(addr, { signer })) - Client-level
walletClientfromcreateOakContractsClient(simple or full config with a wallet) - Throws an
ErrorfromrequireSigner()(message begins withNo signer configured.) if none of the above is set
Client options
| Option | Type | Default | Description |
|---|---|---|---|
timeout | number | 30000 | Timeout in milliseconds for transport calls and waitForTransactionReceipt |
Client properties
Once created, the client exposes these read-only properties:| Property | Type | Description |
|---|---|---|
config | PublicOakContractsClientConfig | Public chain configuration (no secrets) |
options | OakContractsClientOptions | Resolved client options |
publicClient | PublicClient | Viem PublicClient for custom reads |
walletClient | WalletClient | null | Viem WalletClient for custom writes (null for read-only clients) |
Waiting for receipts
Write methods return a transaction hash (Hex). Use waitForReceipt() to poll until the transaction is mined.
| Field | Type | Description |
|---|---|---|
blockNumber | bigint | Block in which the transaction was mined |
gasUsed | bigint | Total gas consumed |
logs | readonly { topics, data }[] | Raw log entries from the transaction |