Quickstart
This guide walks you from zero to a working contract interaction in under 5 minutes.
1. Install the package
pnpm add @oaknetwork/contracts
You can also use
npm install @oaknetwork/contractsoryarn add @oaknetwork/contracts.
2. Create a client
import { createOakContractsClient, CHAIN_IDS } from '@oaknetwork/contracts';
const oak = createOakContractsClient({
chainId: CHAIN_IDS.CELO_TESTNET_SEPOLIA,
rpcUrl: 'https://forno.celo-sepolia.celo-testnet.org',
privateKey: '0x...',
});
createOakContractsClient sets up a viem PublicClient for reads and a WalletClient for writes. Pass a contract address to any entity factory to start interacting with it.
Need testnet tokens?
Get free Celo Sepolia tokens from the Celo faucet to cover gas fees on testnet.
3. Read from a contract
const GLOBAL_PARAMS_ADDRESS = '0x...'; // deployed GlobalParams address
const gp = oak.globalParams(GLOBAL_PARAMS_ADDRESS);
const admin = await gp.getProtocolAdminAddress();
const fee = await gp.getProtocolFeePercent();
console.log('Protocol admin:', admin);
console.log('Protocol fee (bps):', fee); // e.g. 100n = 1%
Save steps 2 and 3 together in a file (e.g. index.ts) and run it:
npx tsx index.ts
4. Write to a contract
Write methods return a transaction hash (Hex). Use oak.waitForReceipt() to wait for confirmation.
import { keccak256, toHex } from '@oaknetwork/contracts';
const PLATFORM_HASH = keccak256(toHex('my-platform'));
const txHash = await gp.enlistPlatform(
PLATFORM_HASH,
'0x...adminAddress',
200n, // 2% fee in basis points
'0x...adapterAddress',
);
const receipt = await oak.waitForReceipt(txHash);
console.log('Mined in block:', receipt.blockNumber);
5. Create a campaign
import {
keccak256,
toHex,
getCurrentTimestamp,
addDays,
} from '@oaknetwork/contracts';
const factory = oak.campaignInfoFactory('0x...factoryAddress');
const identifierHash = keccak256(toHex('my-campaign-slug'));
const PLATFORM_HASH = keccak256(toHex('my-platform'));
const CURRENCY = toHex('USD', { size: 32 });
const now = getCurrentTimestamp();
const txHash = await factory.createCampaign({
creator: '0x...creatorAddress',
identifierHash,
selectedPlatformHash: [PLATFORM_HASH],
campaignData: {
launchTime: now + 3_600n, // 1 hour from now
deadline: addDays(now, 30), // 30 days from now
goalAmount: 1_000_000n,
currency: CURRENCY,
},
nftName: 'My Campaign NFT',
nftSymbol: 'MCN',
nftImageURI: 'https://example.com/nft.png',
contractURI: 'https://example.com/contract.json',
});
const receipt = await oak.waitForReceipt(txHash);
const campaignAddress = await factory.identifierToCampaignInfo(identifierHash);
console.log('Campaign deployed at:', campaignAddress);
6. Handle errors
Contract reverts can be decoded into typed errors with recovery hints:
import { parseContractError, getRevertData } from '@oaknetwork/contracts';
try {
await factory.createCampaign({ ... });
} catch (err) {
const revertData = getRevertData(err);
if (revertData) {
const parsed = parseContractError(revertData);
if (parsed) {
console.error('Reverted:', parsed.name);
console.error('Hint:', parsed.recoveryHint);
return;
}
}
console.error('Unknown error:', err);
}
For the full error reference, see Error Handling.
What to read next
- Client Configuration — all setup patterns, per-entity and per-call signers, resolution order, and browser wallets
- GlobalParams — protocol-wide configuration reads and writes
- CampaignInfoFactory — deploying new campaigns
- Error Handling — typed error decoding and recovery hints
- Utilities — hashing, encoding, time helpers, and constants