# `Onchain.RPC`
[🔗](https://github.com/ZenHive/onchain/blob/v0.5.4/lib/onchain/rpc.ex#L1)

Ethereum JSON-RPC wrapper using cartouche's RPC client.

Provides a curated API for common Ethereum RPC methods with consistent
error tuples and option handling. All functions accept `:rpc_url`,
`:timeout`, and `:block` options.

## Error Format

- Address validation: `{:error, {:invalid_address, input}}`
- Data validation: `{:error, {:invalid_data, input}}`
- Block validation: `{:error, {:invalid_block, input}}`
- Tx hash validation: `{:error, {:invalid_tx_hash, input}}` (must be 32 bytes)
- RPC/network errors: `{:error, {:rpc_error, %{code: integer, message: string}}}`

For RPC errors, the map always has at least a `:message` key. JSON-RPC error
responses from the node include `:code`; network/transport errors are wrapped
with `inspect/1` as the message.

## Functions

| Function | Purpose |
|----------|---------|
| `eth_call/3` | Read-only contract call → raw hex response |
| `eth_call!/3` | Same, raises on error |
| `eth_send_raw_transaction/2` | Broadcast signed tx → tx hash |
| `eth_send_raw_transaction!/2` | Same, raises on error |
| `get_balance/2` | Account ETH balance in wei |
| `get_balance!/2` | Same, raises on error |
| `block_number/1` | Current block height |
| `block_number!/1` | Same, raises on error |
| `syncing/1` | Node sync status (`false` or sync-status map) |
| `syncing!/1` | Same, raises on error |
| `get_block_by_number/2` | Fetch block by number or tag |
| `get_block_by_number!/2` | Same, raises on error |
| `chain_id/1` | Network chain ID |
| `chain_id!/1` | Same, raises on error |
| `eth_get_logs/2` | Fetch event logs by filter |
| `eth_get_logs!/2` | Same, raises on error |
| `get_transaction_receipt/2` | Transaction receipt by hash |
| `get_transaction_receipt!/2` | Same, raises on error |
| `get_transaction_count/2` | Account nonce (tx count) |
| `get_transaction_count!/2` | Same, raises on error |
| `eth_get_code/2` | Contract bytecode (or "0x" for EOAs) |
| `eth_get_code!/2` | Same, raises on error |
| `get_transaction_by_hash/2` | Full transaction details by hash |
| `get_transaction_by_hash!/2` | Same, raises on error |
| `call/3` | Generic JSON-RPC passthrough — any method, raw result |
| `call!/3` | Same, raises on error |
| `fee_history/2` | EIP-1559 fee history (`eth_feeHistory`) → `Cartouche.FeeHistory.t()` |
| `fee_history!/2` | Same, raises on error |
| `get_proof/3` | Account + storage Merkle proofs (`eth_getProof`) |
| `get_proof!/3` | Same, raises on error |

## API Functions
| Function | Arity | Description | Param Kinds |
| --- | --- | --- | --- |
| `get_proof!` | 3 | Fetch Merkle proof for an account and storage slots. Raises on error. | `address: value`, `storage_keys: value`, `opts: value` |
| `get_proof` | 3 | Fetch Merkle proof for an account and storage slots (eth_getProof). | `address: value`, `storage_keys: value`, `opts: value` |
| `fee_history!` | 2 | Fetch fee history. Raises on error. | `block_count: value`, `opts: value` |
| `fee_history` | 2 | Fetch base-fee history and per-block priority-fee percentiles (eth_feeHistory). | `block_count: value`, `opts: value` |
| `call!` | 3 | Generic JSON-RPC passthrough. Raises on error. | `method: value`, `params: value`, `opts: value` |
| `call` | 3 | Generic JSON-RPC passthrough — invoke any method not covered by a named wrapper. | `method: value`, `params: value`, `opts: value` |
| `eth_get_logs!` | 2 | Fetch event logs matching a filter. Raises on error. | `filter: value`, `opts: value` |
| `eth_get_logs` | 2 | Fetch event logs matching a filter (eth_getLogs). | `filter: value`, `opts: value` |
| `get_transaction_by_hash!` | 2 | Get full transaction details by hash. Raises on error. | `tx_hash: value`, `opts: value` |
| `get_transaction_by_hash` | 2 | Get full transaction details by hash (eth_getTransactionByHash). | `tx_hash: value`, `opts: value` |
| `eth_get_code!` | 2 | Fetch contract bytecode at an address. Raises on error. | `address: value`, `opts: value` |
| `eth_get_code` | 2 | Fetch contract bytecode at an address (eth_getCode). | `address: value`, `opts: value` |
| `get_transaction_count!` | 2 | Get the transaction count (nonce) of an address. Raises on error. | `address: value`, `opts: value` |
| `get_transaction_count` | 2 | Get the transaction count (nonce) of an address. | `address: value`, `opts: value` |
| `get_transaction_receipt!` | 2 | Get a transaction receipt by hash. Raises on error. | `tx_hash: value`, `opts: value` |
| `get_transaction_receipt` | 2 | Get a transaction receipt by hash (eth_getTransactionReceipt). | `tx_hash: value`, `opts: value` |
| `chain_id!` | 1 | Get the network chain ID. Raises on error. | `opts: value` |
| `chain_id` | 1 | Get the network chain ID. | `opts: value` |
| `get_block_by_number!` | 2 | Fetch a block by number or tag. Raises on error. | `block_id: value`, `opts: value` |
| `get_block_by_number` | 2 | Fetch a block by number or tag (eth_getBlockByNumber). | `block_id: value`, `opts: value` |
| `syncing!` | 1 | Get the node's sync status. Raises on error. | `opts: value` |
| `syncing` | 1 | Get the node's sync status (eth_syncing). | `opts: value` |
| `block_number!` | 1 | Get the current block height. Raises on error. | `opts: value` |
| `block_number` | 1 | Get the current block height. | `opts: value` |
| `get_balance!` | 2 | Get the ETH balance of an address in wei. Raises on error. | `address: value`, `opts: value` |
| `get_balance` | 2 | Get the ETH balance of an address in wei. | `address: value`, `opts: value` |
| `eth_send_raw_transaction!` | 2 | Broadcast a signed transaction. Raises on error. | `data: value`, `opts: value` |
| `eth_send_raw_transaction` | 2 | Broadcast a signed transaction. | `data: value`, `opts: value` |
| `eth_call!` | 3 | Execute a read-only contract call. Raises on error. | `address: value`, `data: value`, `opts: value` |
| `eth_call` | 3 | Execute a read-only contract call (eth_call). | `address: value`, `data: value`, `opts: value` |

# `block_number`

```elixir
@spec block_number(keyword()) :: {:ok, non_neg_integer()} | {:error, term()}
```

Get the current block height.

## Parameters

  * `opts` - Options: :rpc_url, :timeout (default: `[]`, value)

## Returns

Current block number (`{:ok, non_neg_integer} | {:error, term}`)

```elixir
# descripex:contract
%{
  params: %{
    opts: %{
      default: [],
      description: "Options: :rpc_url, :timeout",
      kind: :value
    }
  },
  returns: %{
    type: "{:ok, non_neg_integer} | {:error, term}",
    description: "Current block number"
  }
}
```

# `block_number!`

```elixir
@spec block_number!(keyword()) :: non_neg_integer()
```

Get the current block height. Raises on error.

## Parameters

  * `opts` - Options: :rpc_url, :timeout (default: `[]`, value)

## Returns

Current block number (`non_neg_integer`)

```elixir
# descripex:contract
%{
  params: %{
    opts: %{
      default: [],
      description: "Options: :rpc_url, :timeout",
      kind: :value
    }
  },
  returns: %{type: :non_neg_integer, description: "Current block number"}
}
```

# `call`

```elixir
@spec call(String.t(), [term()], keyword()) :: {:ok, term()} | {:error, term()}
```

Generic JSON-RPC passthrough — invoke any method not covered by a named wrapper.

## Parameters

  * `method` - JSON-RPC method name, e.g. "eth_getStorageAt", "debug_traceTransaction", "trace_call", "eth_feeHistory" (value)
  * `params` - List of params for the method, in the order the JSON-RPC spec requires (value)
  * `opts` - Options: :rpc_url, :timeout (default: `[]`, value)

## Returns

Raw decoded JSON result (no further decoding — caller knows what they asked for) or wrapped error tuple (`{:ok, term} | {:error, term}`)

```elixir
# descripex:contract
%{
  params: %{
    opts: %{
      default: [],
      description: "Options: :rpc_url, :timeout",
      kind: :value
    },
    params: %{
      description: "List of params for the method, in the order the JSON-RPC spec requires",
      kind: :value
    },
    method: %{
      description: "JSON-RPC method name, e.g. \"eth_getStorageAt\", \"debug_traceTransaction\", \"trace_call\", \"eth_feeHistory\"",
      kind: :value
    }
  },
  returns: %{
    type: "{:ok, term} | {:error, term}",
    description: "Raw decoded JSON result (no further decoding — caller knows what they asked for) or wrapped error tuple"
  }
}
```

# `call!`

```elixir
@spec call!(String.t(), [term()], keyword()) :: term()
```

Generic JSON-RPC passthrough. Raises on error.

## Parameters

  * `method` - JSON-RPC method name (value)
  * `params` - List of params for the method (value)
  * `opts` - Options: :rpc_url, :timeout (default: `[]`, value)

## Returns

Raw decoded JSON result (`term`)

```elixir
# descripex:contract
%{
  params: %{
    opts: %{
      default: [],
      description: "Options: :rpc_url, :timeout",
      kind: :value
    },
    params: %{description: "List of params for the method", kind: :value},
    method: %{description: "JSON-RPC method name", kind: :value}
  },
  returns: %{type: :term, description: "Raw decoded JSON result"}
}
```

# `chain_id`

```elixir
@spec chain_id(keyword()) :: {:ok, non_neg_integer()} | {:error, term()}
```

Get the network chain ID.

## Parameters

  * `opts` - Options: :rpc_url, :timeout (default: `[]`, value)

## Returns

Chain ID (1 = mainnet, 11155111 = sepolia, etc.) (`{:ok, non_neg_integer} | {:error, term}`)

```elixir
# descripex:contract
%{
  params: %{
    opts: %{
      default: [],
      description: "Options: :rpc_url, :timeout",
      kind: :value
    }
  },
  returns: %{
    type: "{:ok, non_neg_integer} | {:error, term}",
    description: "Chain ID (1 = mainnet, 11155111 = sepolia, etc.)"
  }
}
```

# `chain_id!`

```elixir
@spec chain_id!(keyword()) :: non_neg_integer()
```

Get the network chain ID. Raises on error.

## Parameters

  * `opts` - Options: :rpc_url, :timeout (default: `[]`, value)

## Returns

Chain ID integer (`non_neg_integer`)

```elixir
# descripex:contract
%{
  params: %{
    opts: %{
      default: [],
      description: "Options: :rpc_url, :timeout",
      kind: :value
    }
  },
  returns: %{type: :non_neg_integer, description: "Chain ID integer"}
}
```

# `eth_call`

```elixir
@spec eth_call(String.t() | binary(), String.t(), keyword()) ::
  {:ok, String.t()} | {:error, term()}
```

Execute a read-only contract call (eth_call).

## Parameters

  * `address` - Contract address as 0x hex string or 20-byte binary (value)
  * `data` - 0x-prefixed hex-encoded calldata (from ABI.encode_call) (value)
  * `opts` - Options: :rpc_url, :timeout, :block (default: `[]`, value)

## Returns

Raw 0x-prefixed hex response from the contract (`{:ok, hex_string} | {:error, term}`)

```elixir
# descripex:contract
%{
  params: %{
    data: %{
      description: "0x-prefixed hex-encoded calldata (from ABI.encode_call)",
      kind: :value
    },
    opts: %{
      default: [],
      description: "Options: :rpc_url, :timeout, :block",
      kind: :value
    },
    address: %{
      description: "Contract address as 0x hex string or 20-byte binary",
      kind: :value
    }
  },
  returns: %{
    type: "{:ok, hex_string} | {:error, term}",
    description: "Raw 0x-prefixed hex response from the contract",
    example: "0x000000000000000000000000000000000000000000000000000000000000002a"
  }
}
```

# `eth_call!`

```elixir
@spec eth_call!(String.t() | binary(), String.t(), keyword()) :: String.t()
```

Execute a read-only contract call. Raises on error.

## Parameters

  * `address` - Contract address as 0x hex string or 20-byte binary (value)
  * `data` - 0x-prefixed hex-encoded calldata (value)
  * `opts` - Options: :rpc_url, :timeout, :block (default: `[]`, value)

## Returns

Raw 0x-prefixed hex response (`string`)

```elixir
# descripex:contract
%{
  params: %{
    data: %{description: "0x-prefixed hex-encoded calldata", kind: :value},
    opts: %{
      default: [],
      description: "Options: :rpc_url, :timeout, :block",
      kind: :value
    },
    address: %{
      description: "Contract address as 0x hex string or 20-byte binary",
      kind: :value
    }
  },
  returns: %{type: :string, description: "Raw 0x-prefixed hex response"}
}
```

# `eth_get_code`

```elixir
@spec eth_get_code(
  String.t() | binary(),
  keyword()
) :: {:ok, String.t()} | {:error, term()}
```

Fetch contract bytecode at an address (eth_getCode).

## Parameters

  * `address` - Account address as 0x hex string or 20-byte binary (value)
  * `opts` - Options: :rpc_url, :timeout, :block (default: `[]`, value)

## Returns

0x-prefixed bytecode hex string, or "0x" for EOA addresses (`{:ok, hex_string} | {:error, term}`)

```elixir
# descripex:contract
%{
  params: %{
    opts: %{
      default: [],
      description: "Options: :rpc_url, :timeout, :block",
      kind: :value
    },
    address: %{
      description: "Account address as 0x hex string or 20-byte binary",
      kind: :value
    }
  },
  returns: %{
    type: "{:ok, hex_string} | {:error, term}",
    description: "0x-prefixed bytecode hex string, or \"0x\" for EOA addresses",
    example: "\"0x\" for EOAs, \"0x6080604052...\" for contracts"
  }
}
```

# `eth_get_code!`

```elixir
@spec eth_get_code!(
  String.t() | binary(),
  keyword()
) :: String.t()
```

Fetch contract bytecode at an address. Raises on error.

## Parameters

  * `address` - Account address as 0x hex string or 20-byte binary (value)
  * `opts` - Options: :rpc_url, :timeout, :block (default: `[]`, value)

## Returns

0x-prefixed bytecode hex string (`string`)

```elixir
# descripex:contract
%{
  params: %{
    opts: %{
      default: [],
      description: "Options: :rpc_url, :timeout, :block",
      kind: :value
    },
    address: %{
      description: "Account address as 0x hex string or 20-byte binary",
      kind: :value
    }
  },
  returns: %{type: :string, description: "0x-prefixed bytecode hex string"}
}
```

# `eth_get_logs`

```elixir
@spec eth_get_logs(
  map(),
  keyword()
) :: {:ok, [map()]} | {:error, term()}
```

Fetch event logs matching a filter (eth_getLogs).

## Parameters

  * `filter` - Filter map. Atom keys: :address (hex string), :topics (list), :from_block (integer or tag), :to_block (integer or tag), :block_hash (32-byte hex). Canonical JSON-RPC camelCase string keys ("fromBlock", "toBlock", "address", "topics", "blockHash") are accepted as aliases. If both an atom key and its camelCase alias are present, the atom key wins (the alias value is silently dropped). :block_hash is mutually exclusive with :from_block / :to_block per EIP-1474. Unknown keys return \{:error, \{:invalid_filter_key, key\}\}. (value)
  * `opts` - Options: :rpc_url, :timeout (default: `[]`, value)

## Returns

List of log maps with keys: address, topics, data, block_number, transaction_hash, log_index, transaction_index, removed. Errors: \{:invalid_filter_key, key\} for unknown filter keys; \{:invalid_filter, \{field, value\}\} for bad values; \{:invalid_filter, \{:block_hash_mutually_exclusive, present\}\} when :block_hash is combined with :from_block / :to_block. (`{:ok, [log_map]} | {:error, term}`)

```elixir
# descripex:contract
%{
  params: %{
    opts: %{
      default: [],
      description: "Options: :rpc_url, :timeout",
      kind: :value
    },
    filter: %{
      description: "Filter map. Atom keys: :address (hex string), :topics (list), :from_block (integer or tag), :to_block (integer or tag), :block_hash (32-byte hex). Canonical JSON-RPC camelCase string keys (\"fromBlock\", \"toBlock\", \"address\", \"topics\", \"blockHash\") are accepted as aliases. If both an atom key and its camelCase alias are present, the atom key wins (the alias value is silently dropped). :block_hash is mutually exclusive with :from_block / :to_block per EIP-1474. Unknown keys return {:error, {:invalid_filter_key, key}}.",
      kind: :value
    }
  },
  returns: %{
    type: "{:ok, [log_map]} | {:error, term}",
    description: "List of log maps with keys: address, topics, data, block_number, transaction_hash, log_index, transaction_index, removed. Errors: {:invalid_filter_key, key} for unknown filter keys; {:invalid_filter, {field, value}} for bad values; {:invalid_filter, {:block_hash_mutually_exclusive, present}} when :block_hash is combined with :from_block / :to_block."
  }
}
```

# `eth_get_logs!`

```elixir
@spec eth_get_logs!(
  map(),
  keyword()
) :: [map()]
```

Fetch event logs matching a filter. Raises on error.

## Parameters

  * `filter` - Filter map (see eth_get_logs/2) (value)
  * `opts` - Options: :rpc_url, :timeout (default: `[]`, value)

## Returns

List of parsed log maps (`[log_map]`)

```elixir
# descripex:contract
%{
  params: %{
    opts: %{
      default: [],
      description: "Options: :rpc_url, :timeout",
      kind: :value
    },
    filter: %{description: "Filter map (see eth_get_logs/2)", kind: :value}
  },
  returns: %{type: "[log_map]", description: "List of parsed log maps"}
}
```

# `eth_send_raw_transaction`

```elixir
@spec eth_send_raw_transaction(
  String.t(),
  keyword()
) :: {:ok, String.t()} | {:error, term()}
```

Broadcast a signed transaction.

## Parameters

  * `data` - 0x-prefixed hex-encoded signed transaction (value)
  * `opts` - Options: :rpc_url, :timeout (default: `[]`, value)

## Returns

Transaction hash as 0x hex string (`{:ok, tx_hash} | {:error, term}`)

```elixir
# descripex:contract
%{
  params: %{
    data: %{
      description: "0x-prefixed hex-encoded signed transaction",
      kind: :value
    },
    opts: %{
      default: [],
      description: "Options: :rpc_url, :timeout",
      kind: :value
    }
  },
  returns: %{
    type: "{:ok, tx_hash} | {:error, term}",
    description: "Transaction hash as 0x hex string",
    example: "0xabc123..."
  }
}
```

# `eth_send_raw_transaction!`

```elixir
@spec eth_send_raw_transaction!(
  String.t(),
  keyword()
) :: String.t()
```

Broadcast a signed transaction. Raises on error.

## Parameters

  * `data` - 0x-prefixed hex-encoded signed transaction (value)
  * `opts` - Options: :rpc_url, :timeout (default: `[]`, value)

## Returns

Transaction hash as 0x hex string (`string`)

```elixir
# descripex:contract
%{
  params: %{
    data: %{
      description: "0x-prefixed hex-encoded signed transaction",
      kind: :value
    },
    opts: %{
      default: [],
      description: "Options: :rpc_url, :timeout",
      kind: :value
    }
  },
  returns: %{type: :string, description: "Transaction hash as 0x hex string"}
}
```

# `fee_history`

```elixir
@spec fee_history(
  pos_integer(),
  keyword()
) :: {:ok, Cartouche.FeeHistory.t()} | {:error, term()}
```

Fetch base-fee history and per-block priority-fee percentiles (eth_feeHistory).

## Parameters

  * `block_count` - Number of recent blocks to query, 1..1024 (EIP-1474 cap) (value)
  * `opts` - Options: :newest_block (default "latest"), :reward_percentiles (default [50] — list of ints 0..100, monotonically non-decreasing), :rpc_url, :timeout (default: `[]`, value)

## Returns

Deserialized fee history struct: oldest_block, base_fee_per_gas (block_count + 1 entries), gas_used_ratio, reward (block_count rows × length(reward_percentiles) cols) (`{:ok, Cartouche.FeeHistory.t()} | {:error, term}`)

```elixir
# descripex:contract
%{
  params: %{
    opts: %{
      default: [],
      description: "Options: :newest_block (default \"latest\"), :reward_percentiles (default [50] — list of ints 0..100, monotonically non-decreasing), :rpc_url, :timeout",
      kind: :value
    },
    block_count: %{
      description: "Number of recent blocks to query, 1..1024 (EIP-1474 cap)",
      kind: :value
    }
  },
  returns: %{
    type: "{:ok, Cartouche.FeeHistory.t()} | {:error, term}",
    description: "Deserialized fee history struct: oldest_block, base_fee_per_gas (block_count + 1 entries), gas_used_ratio, reward (block_count rows × length(reward_percentiles) cols)"
  }
}
```

# `fee_history!`

```elixir
@spec fee_history!(
  pos_integer(),
  keyword()
) :: Cartouche.FeeHistory.t()
```

Fetch fee history. Raises on error.

## Parameters

  * `block_count` - Number of recent blocks to query, 1..1024 (value)
  * `opts` - Options: :newest_block, :reward_percentiles, :rpc_url, :timeout (default: `[]`, value)

## Returns

Deserialized fee history struct (`Cartouche.FeeHistory.t()`)

```elixir
# descripex:contract
%{
  params: %{
    opts: %{
      default: [],
      description: "Options: :newest_block, :reward_percentiles, :rpc_url, :timeout",
      kind: :value
    },
    block_count: %{
      description: "Number of recent blocks to query, 1..1024",
      kind: :value
    }
  },
  returns: %{
    type: "Cartouche.FeeHistory.t()",
    description: "Deserialized fee history struct"
  }
}
```

# `get_balance`

```elixir
@spec get_balance(
  String.t() | binary(),
  keyword()
) :: {:ok, non_neg_integer()} | {:error, term()}
```

Get the ETH balance of an address in wei.

## Parameters

  * `address` - Account address as 0x hex string or 20-byte binary (value)
  * `opts` - Options: :rpc_url, :timeout, :block (default: `[]`, value)

## Returns

Balance in wei (`{:ok, non_neg_integer} | {:error, term}`)

```elixir
# descripex:contract
%{
  params: %{
    opts: %{
      default: [],
      description: "Options: :rpc_url, :timeout, :block",
      kind: :value
    },
    address: %{
      description: "Account address as 0x hex string or 20-byte binary",
      kind: :value
    }
  },
  returns: %{
    type: "{:ok, non_neg_integer} | {:error, term}",
    description: "Balance in wei"
  }
}
```

# `get_balance!`

```elixir
@spec get_balance!(
  String.t() | binary(),
  keyword()
) :: non_neg_integer()
```

Get the ETH balance of an address in wei. Raises on error.

## Parameters

  * `address` - Account address as 0x hex string or 20-byte binary (value)
  * `opts` - Options: :rpc_url, :timeout, :block (default: `[]`, value)

## Returns

Balance in wei (`non_neg_integer`)

```elixir
# descripex:contract
%{
  params: %{
    opts: %{
      default: [],
      description: "Options: :rpc_url, :timeout, :block",
      kind: :value
    },
    address: %{
      description: "Account address as 0x hex string or 20-byte binary",
      kind: :value
    }
  },
  returns: %{type: :non_neg_integer, description: "Balance in wei"}
}
```

# `get_block_by_number`

```elixir
@spec get_block_by_number(
  integer() | String.t(),
  keyword()
) :: {:ok, map()} | {:error, term()}
```

Fetch a block by number or tag (eth_getBlockByNumber).

## Parameters

  * `block_id` - Block number (integer) or tag string ("latest", "finalized", "pending", "earliest", "safe", or "0x..." hex) (value)
  * `opts` - Options: :rpc_url, :timeout (default: `[]`, value)

## Returns

Raw block map with hex-encoded fields from the node (`{:ok, map} | {:error, term}`)

```elixir
# descripex:contract
%{
  params: %{
    opts: %{
      default: [],
      description: "Options: :rpc_url, :timeout",
      kind: :value
    },
    block_id: %{
      description: "Block number (integer) or tag string (\"latest\", \"finalized\", \"pending\", \"earliest\", \"safe\", or \"0x...\" hex)",
      kind: :value
    }
  },
  returns: %{
    type: "{:ok, map} | {:error, term}",
    description: "Raw block map with hex-encoded fields from the node",
    example: "%{\"number\" => \"0x1312d00\", \"timestamp\" => \"0x665ba27f\", ...}"
  }
}
```

# `get_block_by_number!`

```elixir
@spec get_block_by_number!(
  integer() | String.t(),
  keyword()
) :: map()
```

Fetch a block by number or tag. Raises on error.

## Parameters

  * `block_id` - Block number (integer) or tag string (value)
  * `opts` - Options: :rpc_url, :timeout (default: `[]`, value)

## Returns

Raw block map with hex-encoded fields (`map`)

```elixir
# descripex:contract
%{
  params: %{
    opts: %{
      default: [],
      description: "Options: :rpc_url, :timeout",
      kind: :value
    },
    block_id: %{
      description: "Block number (integer) or tag string",
      kind: :value
    }
  },
  returns: %{type: :map, description: "Raw block map with hex-encoded fields"}
}
```

# `get_proof`

```elixir
@spec get_proof(String.t() | binary(), [String.t()], keyword()) ::
  {:ok, map()} | {:error, term()}
```

Fetch Merkle proof for an account and storage slots (eth_getProof).

## Parameters

  * `address` - Account address as 0x hex string or 20-byte binary (value)
  * `storage_keys` - List of 0x-prefixed 32-byte hex storage slot keys (may be empty for account-only proofs) (value)
  * `opts` - Options: :rpc_url, :timeout, :block (default: `[]`, value)

## Returns

Atom-keyed proof map: address (checksummed), balance (integer wei), nonce (integer), code_hash (0x hex), storage_hash (0x hex), account_proof ([0x hex]), storage_proof ([%\{key, value, proof\}]) (`{:ok, map} | {:error, term}`)

```elixir
# descripex:contract
%{
  params: %{
    opts: %{
      default: [],
      description: "Options: :rpc_url, :timeout, :block",
      kind: :value
    },
    address: %{
      description: "Account address as 0x hex string or 20-byte binary",
      kind: :value
    },
    storage_keys: %{
      description: "List of 0x-prefixed 32-byte hex storage slot keys (may be empty for account-only proofs)",
      kind: :value
    }
  },
  returns: %{
    type: "{:ok, map} | {:error, term}",
    description: "Atom-keyed proof map: address (checksummed), balance (integer wei), nonce (integer), code_hash (0x hex), storage_hash (0x hex), account_proof ([0x hex]), storage_proof ([%{key, value, proof}])"
  }
}
```

# `get_proof!`

```elixir
@spec get_proof!(String.t() | binary(), [String.t()], keyword()) :: map()
```

Fetch Merkle proof for an account and storage slots. Raises on error.

## Parameters

  * `address` - Account address as 0x hex string or 20-byte binary (value)
  * `storage_keys` - List of 0x-prefixed 32-byte hex storage slot keys (may be empty for account-only proofs) (value)
  * `opts` - Options: :rpc_url, :timeout, :block (default: `[]`, value)

## Returns

Atom-keyed proof map (see get_proof/3) (`map`)

```elixir
# descripex:contract
%{
  params: %{
    opts: %{
      default: [],
      description: "Options: :rpc_url, :timeout, :block",
      kind: :value
    },
    address: %{
      description: "Account address as 0x hex string or 20-byte binary",
      kind: :value
    },
    storage_keys: %{
      description: "List of 0x-prefixed 32-byte hex storage slot keys (may be empty for account-only proofs)",
      kind: :value
    }
  },
  returns: %{type: "map", description: "Atom-keyed proof map (see get_proof/3)"}
}
```

# `get_transaction_by_hash`

```elixir
@spec get_transaction_by_hash(
  String.t(),
  keyword()
) :: {:ok, map() | nil} | {:error, term()}
```

Get full transaction details by hash (eth_getTransactionByHash).

## Parameters

  * `tx_hash` - 0x-prefixed hex transaction hash (value)
  * `opts` - Options: :rpc_url, :timeout (default: `[]`, value)

## Returns

Parsed transaction map, or nil if the transaction is unknown (`{:ok, map | nil} | {:error, term}`)

```elixir
# descripex:contract
%{
  params: %{
    opts: %{
      default: [],
      description: "Options: :rpc_url, :timeout",
      kind: :value
    },
    tx_hash: %{description: "0x-prefixed hex transaction hash", kind: :value}
  },
  returns: %{
    type: "{:ok, map | nil} | {:error, term}",
    description: "Parsed transaction map, or nil if the transaction is unknown"
  }
}
```

# `get_transaction_by_hash!`

```elixir
@spec get_transaction_by_hash!(
  String.t(),
  keyword()
) :: map() | nil
```

Get full transaction details by hash. Raises on error.

## Parameters

  * `tx_hash` - 0x-prefixed hex transaction hash (value)
  * `opts` - Options: :rpc_url, :timeout (default: `[]`, value)

## Returns

Parsed transaction map or nil (`map | nil`)

```elixir
# descripex:contract
%{
  params: %{
    opts: %{
      default: [],
      description: "Options: :rpc_url, :timeout",
      kind: :value
    },
    tx_hash: %{description: "0x-prefixed hex transaction hash", kind: :value}
  },
  returns: %{type: "map | nil", description: "Parsed transaction map or nil"}
}
```

# `get_transaction_count`

```elixir
@spec get_transaction_count(
  String.t() | binary(),
  keyword()
) :: {:ok, non_neg_integer()} | {:error, term()}
```

Get the transaction count (nonce) of an address.

## Parameters

  * `address` - Account address as 0x hex string or 20-byte binary (value)
  * `opts` - Options: :rpc_url, :timeout, :block (default: `[]`, value)

## Returns

Transaction count (nonce) (`{:ok, non_neg_integer} | {:error, term}`)

```elixir
# descripex:contract
%{
  params: %{
    opts: %{
      default: [],
      description: "Options: :rpc_url, :timeout, :block",
      kind: :value
    },
    address: %{
      description: "Account address as 0x hex string or 20-byte binary",
      kind: :value
    }
  },
  returns: %{
    type: "{:ok, non_neg_integer} | {:error, term}",
    description: "Transaction count (nonce)"
  }
}
```

# `get_transaction_count!`

```elixir
@spec get_transaction_count!(
  String.t() | binary(),
  keyword()
) :: non_neg_integer()
```

Get the transaction count (nonce) of an address. Raises on error.

## Parameters

  * `address` - Account address as 0x hex string or 20-byte binary (value)
  * `opts` - Options: :rpc_url, :timeout, :block (default: `[]`, value)

## Returns

Transaction count (nonce) (`non_neg_integer`)

```elixir
# descripex:contract
%{
  params: %{
    opts: %{
      default: [],
      description: "Options: :rpc_url, :timeout, :block",
      kind: :value
    },
    address: %{
      description: "Account address as 0x hex string or 20-byte binary",
      kind: :value
    }
  },
  returns: %{type: :non_neg_integer, description: "Transaction count (nonce)"}
}
```

# `get_transaction_receipt`

```elixir
@spec get_transaction_receipt(
  String.t(),
  keyword()
) :: {:ok, map() | nil} | {:error, term()}
```

Get a transaction receipt by hash (eth_getTransactionReceipt).

## Parameters

  * `tx_hash` - 0x-prefixed hex transaction hash (value)
  * `opts` - Options: :rpc_url, :timeout (default: `[]`, value)

## Returns

Parsed receipt map, or nil if the transaction is pending/unknown (`{:ok, map | nil} | {:error, term}`)

```elixir
# descripex:contract
%{
  params: %{
    opts: %{
      default: [],
      description: "Options: :rpc_url, :timeout",
      kind: :value
    },
    tx_hash: %{description: "0x-prefixed hex transaction hash", kind: :value}
  },
  returns: %{
    type: "{:ok, map | nil} | {:error, term}",
    description: "Parsed receipt map, or nil if the transaction is pending/unknown"
  }
}
```

# `get_transaction_receipt!`

```elixir
@spec get_transaction_receipt!(
  String.t(),
  keyword()
) :: map() | nil
```

Get a transaction receipt by hash. Raises on error.

## Parameters

  * `tx_hash` - 0x-prefixed hex transaction hash (value)
  * `opts` - Options: :rpc_url, :timeout (default: `[]`, value)

## Returns

Parsed receipt map or nil (`map | nil`)

```elixir
# descripex:contract
%{
  params: %{
    opts: %{
      default: [],
      description: "Options: :rpc_url, :timeout",
      kind: :value
    },
    tx_hash: %{description: "0x-prefixed hex transaction hash", kind: :value}
  },
  returns: %{type: "map | nil", description: "Parsed receipt map or nil"}
}
```

# `syncing`

```elixir
@spec syncing(keyword()) :: {:ok, false | map()} | {:error, term()}
```

Get the node's sync status (eth_syncing).

## Parameters

  * `opts` - Options: :rpc_url, :timeout (default: `[]`, value)

## Returns

`false` when the node is fully synced; otherwise a raw sync-status map with hex-encoded fields (`startingBlock`, `currentBlock`, `highestBlock`, sometimes snap-sync fields). Field shape varies by client — caller decodes. (`{:ok, false | map} | {:error, term}`)

```elixir
# descripex:contract
%{
  params: %{
    opts: %{
      default: [],
      description: "Options: :rpc_url, :timeout",
      kind: :value
    }
  },
  returns: %{
    type: "{:ok, false | map} | {:error, term}",
    description: "`false` when the node is fully synced; otherwise a raw sync-status map with hex-encoded fields (`startingBlock`, `currentBlock`, `highestBlock`, sometimes snap-sync fields). Field shape varies by client — caller decodes."
  }
}
```

# `syncing!`

```elixir
@spec syncing!(keyword()) :: false | map()
```

Get the node's sync status. Raises on error.

## Parameters

  * `opts` - Options: :rpc_url, :timeout (default: `[]`, value)

## Returns

`false` when synced, sync-status map otherwise (`false | map`)

```elixir
# descripex:contract
%{
  params: %{
    opts: %{
      default: [],
      description: "Options: :rpc_url, :timeout",
      kind: :value
    }
  },
  returns: %{
    type: "false | map",
    description: "`false` when synced, sync-status map otherwise"
  }
}
```

---

*Consult [api-reference.md](api-reference.md) for complete listing*
