Source: Full executable TypeScript in contract/src/examples/06-advanced-patterns/. This page summarizes the flow — read the source for complete per-step code.
The Story
ArtFund has grown. They now manage dozens of active campaigns, multiple treasury contracts, and a growing catalog of physical products that need to be tracked on-chain. Their engineering team needs to optimize for performance and handle complex operational requirements:- Performance — Loading a dashboard that reads data from 10+ contracts should not require 10+ separate RPC calls. They need to batch reads into a single network round-trip.
- Multi-role operations — Some operations on the same contract require different signers. For example, the protocol admin disburses fees, but the campaign creator withdraws funds.
- Physical product tracking — Campaigns that ship physical goods need to register item metadata (dimensions, weight, category) in the ItemRegistry so logistics and customs can be automated.
- Protocol configuration — The platform needs to read global and platform-scoped protocol parameters like buffer times, payment expirations, and campaign duration minimums.
Steps
Step 1: Multicall — Batch Reads
Instead of making N separate RPC calls, batch them into one round-trip usingoak.multicall(). Each read is wrapped in a lazy function so they execute together.
Step 2: Per-Entity Signer
In a browser dApp, the signer is resolved after the user connects their wallet. Pass it when creating the entity — all writes on that entity automatically use it.Step 3: Per-Call Signer
Different operations on the same contract require different signers. Pass the signer as the last argument on each call.Step 4: Item Registry
For campaigns that ship physical products, register item metadata (dimensions, weight, category) on-chain. Supports single and batch registration.Step 5: Registry Keys — Protocol Configuration
The protocol stores configuration values (buffer times, payment expirations, minimum campaign duration) in a data registry. Values can be global or scoped to a specific platform.Step 6: Non-Blocking Receipt Lookup
oak.getReceipt(txHash) fetches the receipt for an already-mined transaction without blocking. Unlike waitForReceipt (which polls until inclusion), getReceipt returns immediately with the receipt or null if not yet mined. Useful for webhooks, indexers, and resuming past sessions.
Step 7: Browser Wallet (MetaMask / Injected)
For frontend applications using MetaMask, Coinbase Wallet, or any browser extension that injectswindow.ethereum, the SDK provides createBrowserProvider and getSigner. Two usage patterns:
Pattern A — Full configuration — provider and signer passed to the client up front, so every entity inherits the wallet.
Step 8: Privy Wallet
Privy embedded wallets expose an EIP-1193 provider. Pass it to viem’scustom transport for both createPublicClient and createWalletClient, then pass chain, provider, and signer into createOakContractsClient — the same full-config pattern as the browser wallet example.