eth.zig

Transactions

Building, signing, and sending Ethereum transactions with eth.zig.

eth.zig supports all Ethereum transaction types -- Legacy, EIP-2930 (access lists), EIP-1559 (priority fees), and EIP-4844 (blob transactions).

Sending a Transaction

The Wallet handles the full lifecycle: auto-filling nonce, gas, and chain ID from the provider, then signing and broadcasting.

const eth = @import("eth");

var transport = eth.http_transport.HttpTransport.init(allocator, "https://rpc.example.com");
defer transport.deinit();
var provider = eth.provider.Provider.init(allocator, &transport);

const private_key = try eth.hex.hexToBytesFixed(32, "your_private_key_hex");
var wallet = eth.wallet.Wallet.init(allocator, private_key, &provider);

// Send 1 ETH -- nonce, gas, and chain_id are auto-filled
const tx_hash = try wallet.sendTransaction(.{
    .to = recipient_address,
    .value = eth.units.parseEther(1.0),
});

SendTransactionOpts

All fields in SendTransactionOpts are optional with sensible defaults. Fields like nonce, gas_limit, and fee parameters are auto-filled from the provider when not specified:

FieldTypeDefault
to?[20]u8null
valueu2560
data[]const u8&.{}
gas_limit?u64Auto (estimateGas)
max_fee_per_gas?u256Auto (getGasPrice)
max_priority_fee_per_gas?u256Auto (getMaxPriorityFeePerGas)
nonce?u64Auto (getTransactionCount)

Transaction Types

Legacy (Type 0)

Pre-EIP-1559 transactions with a single gas_price:

const tx = eth.transaction.Transaction{ .legacy = .{
    .nonce = 0,
    .gas_price = 20_000_000_000, // 20 Gwei
    .gas_limit = 21_000,
    .to = recipient,
    .value = eth.units.parseEther(1.0),
    .data = &.{},
    .chain_id = 1,
}};

EIP-1559 (Type 2)

Modern transactions with base fee + priority fee:

const tx = eth.transaction.Transaction{ .eip1559 = .{
    .chain_id = 1,
    .nonce = 0,
    .max_priority_fee_per_gas = 1_000_000_000, // 1 Gwei tip
    .max_fee_per_gas = 30_000_000_000, // 30 Gwei max
    .gas_limit = 21_000,
    .to = recipient,
    .value = eth.units.parseEther(1.0),
    .data = &.{},
    .access_list = &.{},
}};

EIP-4844 (Type 3)

Blob transactions for L2 data availability:

const tx = eth.transaction.Transaction{ .eip4844 = .{
    .chain_id = 1,
    .nonce = 0,
    .max_priority_fee_per_gas = 1_000_000_000,
    .max_fee_per_gas = 30_000_000_000,
    .gas_limit = 21_000,
    .to = recipient,
    .value = 0,
    .data = &.{},
    .access_list = &.{},
    .max_fee_per_blob_gas = 1_000_000_000,
    .blob_versioned_hashes = &.{blob_hash},
}};

Serialization

Serialize transactions for signing or broadcasting:

// Serialize for signing (produces the sighash payload)
const serialized = try eth.transaction.serializeForSigning(allocator, tx);
defer allocator.free(serialized);

// Hash the serialized transaction
const sighash = eth.keccak.keccak256(serialized);

Unit Conversions

const eth_mod = @import("eth");

const one_ether = eth_mod.units.parseEther(1.0);    // 1000000000000000000
const one_gwei = eth_mod.units.parseGwei(1.0);       // 1000000000