abi-typegen
A Solidity ABI lists the functions your app can call and the events a contract can
emit. abi-typegen turns that list into code for your language, with named
arguments, return types, and helpers for your Ethereum SDK.
It reads Foundry and Hardhat artifacts, runs as one native binary, and can generate several targets at once. Your editor can then point out a wrong argument before you send a transaction.
Install
Install the generator once. Add your chosen Ethereum SDK to the app that uses its output.
You can also download a prebuilt binary or add the CLI to a JavaScript project:
The npm package installs the native executable. Generating code does not require an RPC connection, and the standalone binary needs neither Node nor Python.
See installation for platforms and download verification.
Quick start
Compile your contracts, then point the generator at the files your compiler
created. The default target is viem and the default output is src/generated.
Foundry
Use your existing Foundry project:
Add your preferences to foundry.toml:
[]
= "src/generated"
= "viem"
Keep a watcher running while you work:
It regenerates when artifacts change, so run forge build after editing Solidity.
For a forge typegen shell command, see Forge integration.
Hardhat
The plugin generates bindings when Hardhat compiles your contracts.
For Hardhat 3, add it to hardhat.config.ts:
import { defineConfig } from "hardhat/config";
import abiTypegen from "@0xdoublesharp/hardhat-abi-typegen";
export default defineConfig({
plugins: [abiTypegen],
solidity: "0.8.34",
typegen: {
out: "src/generated",
target: "viem",
contracts: ["Token"],
exclude: ["*Test"],
},
});
Hardhat 2 uses a side-effect import instead of plugins:
import "@0xdoublesharp/hardhat-abi-typegen/hardhat2";
You can also use the CLI directly with abi-typegen generate --hardhat.
Choose your target
Pick the library your app already uses. A target determines the generated API and its runtime dependency; it does not install that dependency for you.
There are 25 CLI targets across 18 languages. Unity uses the csharp target
with an adapter package.
JavaScript and TypeScript
| Target | Framework or SDK | What you get |
|---|---|---|
viem |
viem | Typed contract helpers and ABI |
wagmi |
wagmi | React hooks for reads, writes, and events |
ethers |
ethers v6 | Typed contract interfaces and connection helpers |
ethers5 |
ethers v5 | Typed contract interfaces and connection helpers |
web3js |
web3.js v4 | Typed contract methods |
zod |
Zod 4 | Validation schemas and ABI |
Native languages
| Language | Target | Runtime or SDK | What you get |
|---|---|---|---|
| C | c |
Shared Rust runtime | C11 codecs and client helpers with explicit ownership |
| C++ | cpp |
Shared Rust runtime | C++17 codecs and client helpers with automatic cleanup |
| C# | csharp |
Nethereum | Typed DTOs, contract methods, and deployment |
| Dart | dart |
web3dart | Typed values, codecs, calls, and transactions |
| Elixir | elixir |
Ethers | Transaction data, reads, sends, events, and errors |
| Go | go |
go-ethereum | Typed calls, transactions, deployment, and events |
| Java | java |
web3j | Typed values, codecs, calls, and transactions |
| Kotlin | kotlin |
web3j | Typed values, codecs, calls, and transactions |
| PHP | php |
Brick Math, ethereum-tx, cURL | Codecs, RPC reads, signed legacy transactions, receipts, and logs |
| Python | python |
web3.py | Reads, transaction builders, codecs, events, and errors |
| Ruby | ruby |
eth | Calls, transaction builders, codecs, events, and errors |
| Rust | rust |
Alloy | sol! types, codecs, and contract instances |
| Swift | swift |
web3swift | Typed values, codecs, and contract operations |
Game engines
| Engine | Target | What you get |
|---|---|---|
| Unity | csharp + Unity adapter |
C# bindings with Unity HTTP transport and object lifecycle support |
| Godot | godot |
GDScript bindings and a native extension for codecs and asynchronous RPC |
| Unreal Engine | unreal |
C++ codecs and Blueprint nodes for asynchronous scalar reads |
See engine packages for setup and native bindings for supported features and platforms.
Shell and ABI formats
| Target | Works with | What you get |
|---|---|---|
shell |
Bash and Foundry cast | Sourceable helpers for encoding, reads, sends, deployment, and logs |
solidity |
Solidity | Interfaces, tuple structs, events, and errors |
yaml |
YAML | Readable ABI descriptions |
Zod, Solidity, and YAML describe or validate contracts; they do not submit transactions. See native bindings for SDK versions and configuration for target aliases.
COBOL
| Target | Works with | What you get |
|---|---|---|
cobol |
GnuCOBOL and the shared Rust runtime | Reads taking one address and returning one uint256 🤷 |
Generate for more than one app
Use the same contract artifacts for your frontend, backend, or native app:
Each target gets its own directory:
src/generated/
├── viem/
├── python/
└── rust/
You can save the same selection with target = ["viem", "python", "rust"].
Use the generated code
Import the generated file, connect your SDK, and call the contract through its typed API. You still choose the RPC endpoint, wallet, and transaction settings.
Read with viem
For a generated Token binding, set RPC_URL, TOKEN_ADDRESS, and
ACCOUNT_ADDRESS in your environment:
import { createPublicClient, getAddress, http } from "viem";
import { getTokenContract } from "./generated/Token.viem.js";
const client = createPublicClient({ transport: http(process.env.RPC_URL) });
const token = getTokenContract(getAddress(process.env.TOKEN_ADDRESS!), client);
const owner = getAddress(process.env.ACCOUNT_ADDRESS!);
const balance = await token.read.balanceOf([owner]);
console.log(balance); // bigint
Generated TypeScript imports use .js extensions for ESM. Tuple fields and
function arguments retain their ABI types.
Read or encode with Python
The Python wrapper uses your web3.py connection. Encoding a call works offline:
=
=
=
=
=
Write helpers build transactions for your signing flow. Other targets expose their SDK's transaction or operation types. A submitted transaction hash is not proof of success; check the mined receipt.
Call or sign with PHP
The PHP target generates ABI codecs and a small JSON-RPC client. Install its runtime dependencies, generate the bindings, then pass the RPC URL and signing settings to the generated client:
PHP 8.2 or newer needs the curl, gmp, mbstring, and iconv extensions. The
client signs legacy EIP-155 transactions locally. It does not build EIP-1559
transactions or deploy contracts. Poll for a receipt before treating a returned
transaction hash as success. Event log filters, event decoders, and declared
custom-error decoders are also generated. The upstream signing library emits
ArrayAccess return-type deprecation notices on PHP 8.5.
Read a balance from COBOL
The COBOL target supports read-only functions with one address
input and one uint256 output, such as balanceOf(address):
It emits free-form GnuCOBOL subprograms and a C bridge to the shared Rust runtime. Results use decimal text in a 78-character buffer. Other functions, events, and errors appear as metadata comments. See the COBOL build guide for dependencies and limitations.
Link C or C++
The generated headers describe your contract. A shared Rust library handles ABI encoding and decoding, while your application supplies networking and signing.
Build the runtime from this repository and link abi_typegen_runtime into your
consumer. C emits atg_<Name>.h; C++ also emits atg_<Name>.hpp. Both include
abi_typegen.h. The native guide explains
result ownership, transport callbacks, and deployment bytecode.
Know what the bindings cover
Typed arguments help catch mistakes before a call reaches the chain. They cannot prove that a transaction will succeed or recover data the chain did not include.
Generated wrappers cover contract calls, ABI values, and the SDK integrations listed above. Convenience methods for deployment, receipt handling, event queries, and subscriptions differ by target.
- Java and Kotlin currently cannot encode fixed-array inputs outside lengths 1–32, including arrays nested inside tuples. These inputs fail explicitly.
- Indexed strings, bytes, arrays, and tuples appear in logs as hashes. Their original values cannot be decoded from those topics.
- Anonymous events have no signature topic, so the caller must choose the decoder.
- C/C++ consumers build and link the runtime separately.
See current boundaries for the full list. Regenerate when upgrading, and check the changelog for API or naming changes.
Configure the output
Save your usual settings once. Override them on the command line when you need a different output directory or contract selection.
# foundry.toml
[]
= "src/generated"
= ["viem", "go"]
= true
= ["Token", "Vault"]
= ["*Test", "*Mock"]
= "contracts"
An empty contracts list selects all contracts. package names the Go package or
the Kotlin/Java package. The configuration guide covers
Hardhat settings, glob patterns, aliases, and precedence.
--clean removes stale generated files. --no-wrappers keeps primary ABI metadata
and types while omitting callable wrappers where supported. It keeps Zod schemas
and Solidity interfaces. See generated output for
filenames and target-specific behavior.
Start with an existing contract
You do not need the original Solidity project. Import a local ABI, or fetch one from an explorer that has verified the contract.
# Bare ABI arrays and artifact files containing an "abi" field both work.
For an Etherscan-compatible explorer, set ETHERSCAN_API_KEY in your environment
or a local .env file, then fetch and generate:
The default output includes a saved out/WETH.sol/WETH.json artifact and generated
viem files. Network shortcuts include mainnet, sepolia, base, optimism, and
arbitrum. For another compatible explorer, supply its endpoint:
Keep bindings in sync
When a contract changes, its generated code should change with it. A CI check can catch forgotten updates before they are merged.
For Foundry:
- run: forge build
- run: abi-typegen generate --check
For Hardhat, the plugin regenerates during compilation:
- run: pnpm exec hardhat compile
- run: git diff --exit-code src/generated/
Use --check when CI should verify files without rewriting them. Use diff when
you want to inspect the proposed changes:
Command reference
| Command | Example | What it does |
|---|---|---|
generate |
abi-typegen generate --target viem |
Write bindings from compiled artifacts |
watch |
abi-typegen watch --artifacts out |
Regenerate when artifacts change |
diff |
abi-typegen diff --target viem |
Preview changes without writing files |
json |
abi-typegen json --pretty |
Print the parsed ABI as JSON |
fetch |
abi-typegen fetch --name Token --file Token.abi.json |
Import an ABI and generate bindings |
init |
abi-typegen init |
Add an [abi-typegen] section to foundry.toml |
forge-install |
abi-typegen forge-install --shell zsh |
Print shell integration that enables forge typegen |
help |
abi-typegen help generate |
Show help for the CLI or a command |
Use abi-typegen --version to print the installed version and
abi-typegen help <command> for command help. Global --config PATH selects a
configuration file; --hardhat selects the Hardhat artifact layout.
Common generation options:
| Option | What it does |
|---|---|
--artifacts PATH |
Read compiled artifacts from a directory |
--out PATH |
Choose the output directory |
--target viem,python |
Generate one or more targets |
--contracts Token,Vault |
Select contracts by name |
--exclude '*Test,*Mock' |
Exclude contracts by glob pattern |
--package NAME |
Set the package, namespace, or Unreal module name |
--no-wrappers |
Keep metadata and types without contract wrappers |
--check |
Fail if generated output is stale, without writing |
--clean |
Remove stale generated files from the output directory |
watch reads target and output settings from your configuration.
forge-install supports Bash, Zsh, and Fish; follow the
Forge setup guide to load the printed integration.
See configuration for complete examples and
abi-typegen help <command> for command-specific options.
Docs and support
Start with the guide for the part you are working on. For a bug report, include a small ABI that reproduces the problem, your target, and the relevant SDK version.
The documentation index links the full set of guides.
Contribute
See CONTRIBUTING.md for source builds, tests, code conventions, and pull requests.