Skip to main content
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 viem PublicClient 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’s custom 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:
  1. Per-call options.signer — highest priority
  2. Per-entity signer passed to the entity factory (e.g. oak.globalParams(addr, { signer }))
  3. Client-level walletClient from createOakContractsClient (simple or full config with a wallet)
  4. Throws an Error from requireSigner() (message begins with No 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.
The receipt includes: