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.
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 })).
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.
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
Client properties
Once created, the client exposes these read-only properties:Waiting for receipts
Write methods return a transaction hash (Hex). Use waitForReceipt() to poll until the transaction is mined.