<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Cradicle Explorer</title>
    <link href="/css/bootstrap/bootstrap.min.css" rel="stylesheet">
    <style>
      .form-control-dark::placeholder {
          color: #aaa;
          opacity: 1;
      }
    </style>
    <link rel="stylesheet" href="/assets/fontawesome/css/all.min.css">
    <link rel="icon" type="image/png" href="/favicon.png">


                <link href="/css/dashboard.css" rel="stylesheet">
                </head>
                <body>
                <header class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0 shadow">
                  <a class="navbar-brand col-md-3 col-lg-2 me-0 px-3 fs-6" href="/">Cradicle Explorer</a>
                  <button class="navbar-toggler position-absolute d-md-none collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#sidebarMenu" aria-controls="sidebarMenu" aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                  </button>
                  <form method="get" action="/cgi-bin/main" style="width:100%;"><input class="form-control form-control-dark w-100 rounded-0 border-0" type="text" name="q" placeholder="Search repos" aria-label="Search"></form>
                  <div class="navbar-nav flex-row">
                    <div class="nav-item text-nowrap">
                      <a class="nav-link px-3 active" href="/cgi-bin/repo?id=z2PkjFcLVQnSggTYAV8Z8kEgQWz8z">gleeth</a>
                    </div>
                  </div>
                </header>
                <div class="container-fluid">
                  <div class="row">
                    <nav id="sidebarMenu" class="col-md-3 col-lg-2 d-md-block bg-dark sidebar collapse">
                      <div class="position-sticky pt-3 sidebar-sticky">
                        <ul class="nav flex-column">
                          <li class="nav-item">
                            <a class="nav-link active" href="/cgi-bin/repo?id=z2PkjFcLVQnSggTYAV8Z8kEgQWz8z">
                              <i class="align-text-bottom fa-solid fa-info"></i>
                              Info
                            </a>
                          </li>
                          <li class="nav-item">
                            <a class="nav-link" href="/cgi-bin/repo?id=z2PkjFcLVQnSggTYAV8Z8kEgQWz8z&issue=list">
                              <i class="align-text-bottom fa-solid fa-layer-group"></i>
                              Issues
                            </a>
                          </li>
                          <li class="nav-item">
                            <a class="nav-link" href="/cgi-bin/repo?id=z2PkjFcLVQnSggTYAV8Z8kEgQWz8z&patch=list">
                              <i class="align-text-bottom fa-solid fa-vest-patches"></i>
                              Patches
                            </a>
                          </li>
                          <li class="nav-item">
                            <a class="nav-link" href="/cgi-bin/repo?id=z2PkjFcLVQnSggTYAV8Z8kEgQWz8z&wallet=list">
                              <i class="align-text-bottom fa-solid fa-wallet"></i>
                              Wallets
                            </a>
                          </li>
                          <li class="nav-item">
                            <a class="nav-link" href="/cgi-bin/repo?id=z2PkjFcLVQnSggTYAV8Z8kEgQWz8z&source=.">
                              <i class="align-text-bottom fa-solid fa-code"></i>
                              Source
                            </a>
                          </li>
                        <h6 class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1 text-muted text-uppercase">
                          <span></span>
                        </h6>
                        <ul class="nav flex-column mb-2">
                        
                        </ul>
                      </div>
                    </nav>
                <main class="col-md-9 ms-sm-auto col-lg-10">
                  <div class="container px-1 py-3">
        

    <div class="list-group">
    <div class="list-group-item">
    <div style="font-size:1.3rem;">gleeth</div>
    <div class="repo-item">Gleam library for interacting with Ethereum</div>
    <div>rad:z2PkjFcLVQnSggTYAV8Z8kEgQWz8z</div>
    </div>
    <div class="list-group-item">
    <div>Visibility</div>
    <div class="repo-item">public</div>
    </div>
    <div class="list-group-item">
    <div>Delegates</div><div class="repo-item">did:key:z6MkvcDD5aFqTKtYYpAwhoZT3Z5WU5bHLpoxgEzQBLVLsNd9</div>
    </div>
    <div class="list-group-item">
    <div>Default branch</div>
    <div><span class="repo-item">main &#8594 d4eef4da887e505042177158137efce6911579fc</span> (Tue Apr 21 15:51:26 2026)</div>
    </div>
    <div class="list-group-item">
    <div>Threshold</div>
    <div class="repo-item">1</div>
    </div>
    </div>
    
        <div class="list-group mt-3">
        <div class="list-group-item">
        <div class="mb-2" style="font-weight:bold;"><i class="fa-solid fa-book"></i> README.md</div>
        <pre style="margin:0; font-size:0.85rem; overflow-x:auto; color:#fafafa;"># gleeth

[![Package Version](https://img.shields.io/hexpm/v/gleeth)](https://hex.pm/packages/gleeth)
[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/gleeth/)

An Ethereum library for Gleam, targeting the Erlang (BEAM) runtime. Provides JSON-RPC client, transaction signing, ABI encoding/decoding, and wallet management.

&gt; **Warning**: gleeth has not been audited and is in early development. It is
&gt; recommended for testnet and development use only. Do not use with real funds
&gt; in production without thorough independent review.

## Installation

```sh
gleam add gleeth
```

For a step-by-step walkthrough, see the [ERC-20 tutorial](tutorial.md).

## Quick start

### Read chain state

```gleam
import gleeth/provider
import gleeth/rpc/methods

pub fn main() {
  let assert Ok(p) = provider.new(&quot;http://localhost:8545&quot;)

  // Get the latest block number
  let assert Ok(block_number) = methods.get_block_number(p)

  // Check an address balance
  let assert Ok(balance) = methods.get_balance(
    p,
    &quot;0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045&quot;,
  )
}
```

### Sign and send a transaction (builder API)

The builder API accepts human-readable values - no manual hex conversion needed.

```gleam
import gleeth/crypto/transaction
import gleeth/crypto/wallet
import gleeth/provider
import gleeth/rpc/methods

pub fn main() {
  let assert Ok(p) = provider.new(&quot;http://localhost:8545&quot;)
  let assert Ok(w) = wallet.from_private_key_hex(&quot;0xac09...&quot;)

  // EIP-1559 transaction (recommended - used on all major chains)
  let assert Ok(signed) =
    transaction.build_eip1559()
    |&gt; transaction.eip1559_to(&quot;0x70997970C51812dc3A010C7d01b50e0d17dc79C8&quot;)
    |&gt; transaction.eip1559_value_ether(&quot;1.5&quot;)
    |&gt; transaction.eip1559_gas_limit_int(21_000)
    |&gt; transaction.eip1559_max_fee_gwei(&quot;30.0&quot;)
    |&gt; transaction.eip1559_max_priority_fee_gwei(&quot;2.0&quot;)
    |&gt; transaction.eip1559_nonce_int(0)
    |&gt; transaction.eip1559_chain(1)
    |&gt; transaction.sign_eip1559(w)

  // Broadcast and wait for receipt
  let assert Ok(tx_hash) = methods.send_raw_transaction(p, signed.raw_transaction)
  let assert Ok(receipt) = methods.wait_for_receipt(p, tx_hash)
}
```

Legacy transactions are also supported via `build_legacy()`.

For lower-level control, use `create_eip1559_transaction` or `create_legacy_transaction` with hex strings directly:

```gleam
pub fn main() {
  let assert Ok(p) = provider.new(&quot;http://localhost:8545&quot;)
  let assert Ok(w) = wallet.from_private_key_hex(&quot;0xac09...&quot;)

  // Gas estimation in one call
  let sender = wallet.get_address(w)
  let assert Ok(est) = gas.estimate_legacy(p, sender, &quot;0x7099...&quot;, &quot;0xde0b6b3a7640000&quot;, &quot;0x&quot;)
  let assert Ok(nonce) = methods.get_transaction_count(p, sender, &quot;pending&quot;)

  let assert Ok(tx) = transaction.create_legacy_transaction(
    &quot;0x70997970C51812dc3A010C7d01b50e0d17dc79C8&quot;,
    &quot;0xde0b6b3a7640000&quot;,  // 1 ETH in wei hex
    est.gas_limit,         // from estimation
    est.gas_price,         // from estimation
    nonce,                 // from RPC
    &quot;0x&quot;,                  // no calldata
    1,                     // mainnet
  )

  let assert Ok(signed) = transaction.sign_transaction(tx, w)
  let assert Ok(tx_hash) = methods.send_raw_transaction(p, signed.raw_transaction)
}
```

### Contract interaction

The `contract` module binds a provider, address, and ABI together so you can
call functions by name without manually encoding calldata:

```gleam
import gleeth/contract
import gleeth/crypto/wallet
import gleeth/ethereum/abi/json
import gleeth/provider

pub fn main() {
  let assert Ok(p) = provider.new(&quot;http://localhost:8545&quot;)
  let assert Ok(w) = wallet.from_private_key_hex(&quot;0xac09...&quot;)

  // Parse the ABI and create a contract handle
  let assert Ok(abi) = json.parse_abi(erc20_abi_json)
  let usdc = contract.at(p, &quot;0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48&quot;, abi)

  // Read a balance - just pass strings, types are inferred from the ABI
  let assert Ok(values) = contract.call_raw(usdc, &quot;balanceOf&quot;, [
    &quot;0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045&quot;,
  ])

  // Send a transfer
  let assert Ok(tx_hash) = contract.send_raw(usdc, w, &quot;transfer&quot;, [
    &quot;0x70997970C51812dc3A010C7d01b50e0d17dc79C8&quot;,
    &quot;1000000&quot;,
  ], &quot;0x100000&quot;, 1)
}
```

### Low-level contract call

```gleam
import gleeth/provider
import gleeth/rpc/methods

pub fn main() {
  let assert Ok(p) = provider.new(&quot;http://localhost:8545&quot;)

  // Call balanceOf(address) on an ERC-20 with raw calldata
  let assert Ok(result) = methods.call_contract(
    p,
    &quot;0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48&quot;,  // USDC
    &quot;0x70a08231000000000000000000000000d8dA6BF26964aF9D7eEd9e03E53415D37aA96045&quot;,
  )
}
```

### ABI encoding

```gleam
import gleeth/ethereum/abi/encode
import gleeth/ethereum/abi/types.{Uint, Address, AbiUintValue, AbiAddressValue}

pub fn main() {
  // Encode a function call: transfer(address, uint256)
  let assert Ok(calldata) = encode.encode_call(
    &quot;transfer(address,uint256)&quot;,
    [Uint(256), Address],
    [
      AbiAddressValue(&quot;0x70997970C51812dc3A010C7d01b50e0d17dc79C8&quot;),
      AbiUintValue(1000000),
    ],
  )
}
```

## Features

- **Transaction builder** - pipeline API with human-readable values (`value_ether(&quot;1.5&quot;)`, `gas_price_gwei(&quot;20.0&quot;)`)
- **Transaction signing** - Legacy (Type 0) and EIP-1559 (Type 2) with EIP-155 replay protection
- **Transaction decoding** - decode raw transactions, recover sender address
- **Gas estimation** - `gas.estimate_legacy` and `gas.estimate_eip1559` in a single call
- **Receipt polling** - `wait_for_receipt` with exponential backoff
- **Nonce manager** - local nonce tracking for multi-transaction sequences
- **Wei conversions** - `wei.from_ether(&quot;1.5&quot;)`, `wei.to_gwei(hex)`, `wei.from_int(21000)`
- **JSON-RPC client** - block number, balance, call, code, estimate gas, storage, logs, transactions, receipts, fee history
- **Provider abstraction** - opaque type with URL validation, chain ID caching, and configurable retry
- **ABI system** - full encoding/decoding for all Solidity types, calldata decoding, revert reason decoding, JSON ABI parsing, event log decoding
- **EIP-55 addresses** - `address.checksum` and `address.is_valid_checksum`
- **EIP-191 signing** - `sign_personal_message`, `recover_personal_message`, `verify_personal_message`
- **Wallet management** - key generation, message signing, signature recovery
- **Crypto primitives** - keccak256 (via ex_keccak NIF), secp256k1 (via ex_secp256k1 NIF)
- **EIP-712 signing** - `eip712.sign_typed_data` for permits, order books, meta-transactions
- **Batch JSON-RPC** - multiple RPC calls in a single HTTP request via `batch.new() |&gt; batch.add(...) |&gt; batch.execute_strings(provider)`
- **Contract deployment** - `deploy.deploy` and `deploy.deploy_with_args` handle signing, broadcasting, and receipt polling
- **Retry middleware** - automatic retry with exponential backoff on 429/503 via `provider.with_retry`
- **Contract type** - `contract.at(provider, address, abi)` for automatic ABI encoding/decoding on `call` and `send`, with string-coerced `call_raw`/`send_raw`
- **Event streaming** - `events.get_events` combines getLogs + ABI decoding; `get_events_by_name` filters by event
- **EIP-2612 permits** - `permit.sign` for one-liner permit signing with auto domain/nonce fetch
- **Multicall3** - `multicall.new() |&gt; multicall.add(...) |&gt; multicall.execute(provider)` batches contract reads at the EVM level
- **Block watcher** - `watcher.start(provider)` spawns a BEAM actor that polls for new blocks and sends typed events
- **Event watcher** - `event_watcher.start(provider, address, abi)` streams decoded contract events in real-time
- **ENS resolution** - `ens.resolve(provider, &quot;vitalik.eth&quot;)` and `ens.reverse_resolve(provider, address)` for forward and reverse name resolution
- **Multi-chain registry** - `chain.by_name(&quot;arbitrum&quot;) |&gt; chain.to_provider` with pre-configured mainnet, Sepolia, Arbitrum, Optimism, Polygon, Base
- **RLP encoding/decoding** - per Ethereum Yellow Paper spec

## Requirements

- Gleam &gt;= 1.14.0
- Erlang/OTP &gt;= 27
- Elixir (for ex_keccak and ex_secp256k1 NIF compilation)

Run `mix local.hex --force` before first build if Elixir is freshly installed.

## Development

```sh
gleam build          # Compile
gleam test           # Run all tests
gleam format         # Format code
gleam docs build     # Generate documentation
```

Further documentation can be found at &lt;https://hexdocs.pm/gleeth&gt;.
</pre>
        </div>
        </div>

</div>
</main>
</div>
</div>


</body>
</html>

