# `Onchain.Contract`
[🔗](https://github.com/ZenHive/onchain-stack/blob/onchain-v0.14.0/packages/onchain/lib/onchain/contract.ex#L1)

Generic contract call: ABI encode → eth_call → ABI decode in one function.

Eliminates the 3-step `with` chain every consumer writes for contract reads.
Takes a contract address, function signature, params, and return type — returns
decoded values.

## Error Format

Errors pass through from the underlying module that failed:

| Source | Error Shape |
|--------|-------------|
| `Onchain.Address.validate/1` | `{:error, {:invalid_address, input}}` |
| `Onchain.ABI.encode_call/2` | `{:error, {:encode_error, reason}}` |
| `Onchain.RPC.eth_call/3` | `{:error, {:rpc_error, map}}` — on execution revert, `map` may include `:data` (0x hex) and `:revert` (bytes) for `Onchain.ABI.decode_error/3` |
| `Onchain.ABI.decode_response/3` | `{:error, {:decode_error, reason}}` — including `{:strict_violation, detail}` when `opts` contains `strict: true` |

## Functions

| Function | Purpose |
|----------|---------|
| `call/5` | Generic contract read → decoded values list |
| `call!/5` | Same, raises on error |

## API Functions
| Function | Arity | Description | Param Kinds |
| --- | --- | --- | --- |
| `call!` | 5 | Execute a read-only contract call. Raises on error. | `address: value`, `signature: value`, `params: value`, `return_type: value`, `opts: value` |
| `call` | 5 | Execute a read-only contract call: encode → eth_call → decode. | `address: value`, `signature: value`, `params: value`, `return_type: value`, `opts: value` |

# `call`

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

Execute a read-only contract call: encode → eth_call → decode.

## Parameters

  * `address` - Contract address as 0x hex string or 20-byte binary (value)
  * `signature` - Function signature, e.g. "balanceOf(address)" (value)
  * `params` - List of parameter values matching the signature (value)
  * `return_type` - Tuple type signature for decoding, e.g. "(uint256)" or "(uint256,bool)" (value)
  * `opts` - RPC options (:rpc_url, :timeout, :block) plus decode opts forwarded to Onchain.ABI.decode_response/3 (`strict: true`, `decode_structs: true`) (default: `[]`, value)

## Returns

List of decoded return values from the contract call (`{:ok, [decoded_values]} | {:error, term()}`)

```elixir
# descripex:contract
%{
  params: %{
    opts: %{
      default: [],
      description: "RPC options (:rpc_url, :timeout, :block) plus decode opts forwarded to Onchain.ABI.decode_response/3 (`strict: true`, `decode_structs: true`)",
      kind: :value
    },
    address: %{
      description: "Contract address as 0x hex string or 20-byte binary",
      kind: :value
    },
    signature: %{
      description: "Function signature, e.g. \"balanceOf(address)\"",
      kind: :value
    },
    params: %{
      description: "List of parameter values matching the signature",
      kind: :value
    },
    return_type: %{
      description: "Tuple type signature for decoding, e.g. \"(uint256)\" or \"(uint256,bool)\"",
      kind: :value
    }
  },
  returns: %{
    type: "{:ok, [decoded_values]} | {:error, term()}",
    description: "List of decoded return values from the contract call",
    example: "{:ok, [1000000]}"
  }
}
```

# `call!`

```elixir
@spec call!(String.t() | binary(), String.t(), list(), String.t(), keyword()) ::
  list() | map()
```

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

## Parameters

  * `address` - Contract address as 0x hex string or 20-byte binary (value)
  * `signature` - Function signature, e.g. "balanceOf(address)" (value)
  * `params` - List of parameter values matching the signature (value)
  * `return_type` - Tuple type signature for decoding, e.g. "(uint256)" (value)
  * `opts` - RPC options (:rpc_url, :timeout, :block) plus decode opts forwarded to Onchain.ABI.decode_response/3 (`strict: true`, `decode_structs: true`) (default: `[]`, value)

## Returns

List of decoded return values from the contract call (`[decoded_values]`)

```elixir
# descripex:contract
%{
  params: %{
    opts: %{
      default: [],
      description: "RPC options (:rpc_url, :timeout, :block) plus decode opts forwarded to Onchain.ABI.decode_response/3 (`strict: true`, `decode_structs: true`)",
      kind: :value
    },
    address: %{
      description: "Contract address as 0x hex string or 20-byte binary",
      kind: :value
    },
    signature: %{
      description: "Function signature, e.g. \"balanceOf(address)\"",
      kind: :value
    },
    params: %{
      description: "List of parameter values matching the signature",
      kind: :value
    },
    return_type: %{
      description: "Tuple type signature for decoding, e.g. \"(uint256)\"",
      kind: :value
    }
  },
  returns: %{
    type: "[decoded_values]",
    description: "List of decoded return values from the contract call"
  }
}
```

---

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