gleeth/contract

High-level contract interaction.

Binds a provider, address, and parsed ABI together so you can call contract functions without manually encoding calldata or decoding results.

There are two calling styles: typed and string-coerced. Typed calls use explicit AbiValue constructors; string-coerced calls (call_raw/send_raw) accept plain strings and auto-coerce them based on the ABI.

Typed calls

let assert Ok(abi) = json.parse_abi(erc20_abi_json)
let usdc = contract.at(provider, "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", abi)

// Read-only call with explicit ABI value types
let assert Ok(values) = contract.call(usdc, "balanceOf", [
  types.AddressVal("0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"),
])

// Write call (sends a transaction)
let assert Ok(tx_hash) = contract.send(usdc, wallet, "transfer", [
  types.AddressVal("0x70997970C51812dc3A010C7d01b50e0d17dc79C8"),
  types.UintValue(1_000_000),
], "0x100000", chain_id)

String-coerced calls

The call_raw/send_raw variants accept plain strings and coerce them to the correct ABI types automatically:

let usdc = contract.at(provider, "0xA0b8...eB48", abi)

// Same balanceOf call - just pass the address as a string
let assert Ok(values) = contract.call_raw(usdc, "balanceOf", [
  "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
])

// Same transfer - amounts can be decimal strings or hex
let assert Ok(tx_hash) = contract.send_raw(usdc, wallet, "transfer", [
  "0x70997970C51812dc3A010C7d01b50e0d17dc79C8",
  "1000000",
], "0x100000", 1)

Types

A contract instance bound to a provider, address, and ABI.

pub type Contract {
  Contract(
    provider: provider.Provider,
    address: String,
    abi: List(json.AbiEntry),
  )
}

Constructors

Values

pub fn at(
  provider: provider.Provider,
  address: String,
  abi: List(json.AbiEntry),
) -> Contract

Create a contract instance bound to a provider, address, and parsed ABI.

Examples

let assert Ok(abi) = json.parse_abi(erc20_abi_json)
let usdc = contract.at(provider, "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", abi)
pub fn call(
  contract: Contract,
  function_name: String,
  args: List(types.AbiValue),
) -> Result(List(types.AbiValue), types.GleethError)

Call a read-only function on the contract. Encodes the arguments, calls eth_call, and decodes the return values.

Examples

let assert Ok(abi) = json.parse_abi(erc20_abi_json)
let usdc = contract.at(provider, "0xA0b8...eB48", abi)

// Read the balance for an address
let assert Ok([types.UintValue(balance)]) =
  contract.call(usdc, "balanceOf", [
    types.AddressValue("0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"),
  ])
pub fn call_raw(
  contract: Contract,
  function_name: String,
  args: List(String),
) -> Result(List(types.AbiValue), types.GleethError)

Call a read-only function using string arguments that are auto-coerced to the correct ABI types based on the function’s ABI definition.

Addresses are passed as hex strings, integers as decimal strings or hex, booleans as “true”/“false”.

Examples

// Instead of: contract.call(c, "balanceOf", [AddressVal("0xf39f...")])
contract.call_raw(c, "balanceOf", ["0xf39f..."])

// Multiple args
contract.call_raw(c, "allowance", ["0xf39f...", "0x7099..."])
pub fn send(
  contract: Contract,
  w: wallet.Wallet,
  function_name: String,
  args: List(types.AbiValue),
  gas_limit: String,
  chain_id: Int,
) -> Result(String, types.GleethError)

Send a write transaction to the contract. Encodes the arguments, signs, broadcasts, and returns the transaction hash.

Examples

let assert Ok(abi) = json.parse_abi(erc20_abi_json)
let usdc = contract.at(provider, "0xA0b8...eB48", abi)

// Transfer 1,000,000 units (1 USDC) to another address
let assert Ok(tx_hash) =
  contract.send(usdc, wallet, "transfer", [
    types.AddressValue("0x70997970C51812dc3A010C7d01b50e0d17dc79C8"),
    types.UintValue(1_000_000),
  ], "0x100000", 1)
pub fn send_raw(
  contract: Contract,
  w: wallet.Wallet,
  function_name: String,
  args: List(String),
  gas_limit: String,
  chain_id: Int,
) -> Result(String, types.GleethError)

Send a write transaction using string arguments that are auto-coerced.

Like send, but accepts plain strings instead of typed AbiValue constructors. Addresses are passed as hex strings, integers as decimal strings or hex, booleans as “true”/“false”.

Examples

let usdc = contract.at(provider, "0xA0b8...eB48", abi)

// Transfer 1 USDC - just pass strings
let assert Ok(tx_hash) =
  contract.send_raw(usdc, wallet, "transfer", [
    "0x70997970C51812dc3A010C7d01b50e0d17dc79C8",
    "1000000",
  ], "0x100000", 1)

// Approve a spender for a given amount
let assert Ok(tx_hash) =
  contract.send_raw(usdc, wallet, "approve", [
    "0xSpenderAddress...",
    "5000000",
  ], "0x100000", 1)
Search Document