@foundryprotocol/0gkit-contracts
v1.0.1
Published
Typed contract clients for 0G. Five standard 0G contracts pre-bundled (ERC-20, ERC-721, Multicall3, provider registry, attestation verifier) plus `forge build` → typed TS codegen. Wagmi-style .read.method() / .write.method() / .events.Event(); no hand-wri
Downloads
267
Maintainers
Readme
@foundryprotocol/0gkit-contracts
Typed contract clients for 0G. No hand-written ABIs.
- Five standard 0G contracts pre-bundled — ERC-20, ERC-721, Multicall3, provider registry, attestation verifier.
- Wagmi-style
.read.method()/.write.method()/.events.Event()— full IntelliSense, zeroany. 0g contracts generate --abi <forge-artifact>.json --out <dir>consumes Foundry build output and emits typed.tsclients.
npm i @foundryprotocol/0gkit-contracts viemStandard contracts
import { standardContracts } from "@foundryprotocol/0gkit-contracts";
// Multicall3 is universal — same address on every EVM chain.
const m3 = standardContracts.multicall3({ network: "galileo" });
const block = await m3.read.getBlockNumber();
// ERC-20 needs an address (no per-network singleton).
const usdc = standardContracts.erc20({
address: "0xa0b8...e3c8",
network: "galileo",
signer, // optional; required for .write.*
});
const balance = await usdc.read.balanceOf("0x1234...");
const tx = await usdc.write.transfer("0xabcd...", 100n);
console.log(tx.txHash, tx.blockNumber);| Contract | Network address | Status |
| --------------------- | ------------------------------------ | ---------------------------------------------------------- |
| multicall3 | Universal | Auto-resolved per network |
| erc20 | Per-deployment | Pass { address } |
| erc721 | Per-deployment | Pass { address } |
| registry | Pinned per network when 0G publishes | Throws CONFIG with hint until then; pass { address } now |
| attestationVerifier | Pinned per network when 0G publishes | Throws CONFIG with hint until then; pass { address } now |
Codegen — your own contracts
After forge build, point 0g contracts generate at the artifact:
0g contracts generate \
--abi out/MyContract.sol/MyContract.json \
--out src/contractsEmits one .ts file per contract:
import { MyContract } from "./contracts/MyContract";
const c = MyContract.attach({ address: "0x...", signer });
const value = await c.read.totalSupply(); // typed bigint
const tx = await c.write.transfer(to, amount); // returns Receipt
const events = await c.events.Transfer({ fromBlock: 0n });Generated code passes tsc --strict --noEmit with zero any. Output is byte-deterministic — same artifact in, same TS out — so diffs in PR are obvious.
Programmatic codegen
import { generate } from "@foundryprotocol/0gkit-contracts/codegen";
await generate({
abiPath: "out/MyContract.sol/MyContract.json",
outDir: "src/contracts",
name: "MyContract", // optional override
});Custom contracts via createTypedContract
For one-offs where codegen would be overkill:
import { createTypedContract } from "@foundryprotocol/0gkit-contracts";
import { parseAbi } from "viem";
const c = createTypedContract({
abi: parseAbi(["function ping() view returns (uint256)"]),
address: "0x...",
network: "galileo",
});
const n = await c.read.ping();CLI
0g contracts list # show bundled standard contracts
0g contracts info erc20 # methods + events for one contract
0g contracts generate --abi <p> --out <d> # codegen from Foundry artifactAPI
createTypedContract({ abi, address, signer?, ... })
Returns { read, write, events, address, abi }.
read.<method>(args)— delegates toviem.getContract.write.<method>(args)— submits via the wallet client, awaits the receipt, returns{ txHash, blockNumber, latencyMs }(the0gkit-core.Receiptshape). Requires{ signer }whoseprivateKeyis exposed (thefromPrivateKey/fromFile/fromEnvloaders from0gkit-wallet).events.<EventName>({ fromBlock?, toBlock?, args? })— pull-only log query viaviem.getLogs. SP6 (0gkit-indexer) adds live subscriptions with reorg safety.
Errors
All thrown errors are 0gkit-core.ZeroGError subclasses with a code and a one-line hint:
CONFIG— wrong/missing args, or a non-pinned contract address. Includes a remedy.CHAIN— viem write/read/getLogs failed. Original message preserved.
Estimating & dry-run
const c = createTypedContract({ abi, address, network, signer });
const est = await c.estimate.transfer(recipient, 1_000n);
// { kind: "contract", gas, fee, breakdown: { method: "transfer", gasPrice }, expectedSeconds: 3 }
const dr = await c.write.transfer([recipient, 1_000n], { dryRun: true });
// { dryRun: true, estimate, result: { latencyMs: 0 } }estimate uses viem's estimateContractGas + getGasPrice; write({ dryRun })
also runs simulateContract so EVM revert paths surface before any broadcast
happens. From the CLI:
0g estimate contracts --abi ./out/MyContract.json --address 0x... --method transfer --args '["0x...","1000"]'License
MIT
