# `Onchain.Tempo.RPC`
[🔗](https://github.com/ZenHive/onchain-stack/blob/onchain_tempo-v0.10.0/packages/onchain_tempo/lib/onchain/tempo/rpc.ex#L1)

Tempo-specific JSON-RPC operations — transaction broadcast and receipt fetching.

Provides both async (`eth_sendRawTransaction`) and sync
(`eth_sendRawTransactionSync`) broadcast methods. The sync variant is
Tempo-specific — it waits for block inclusion (~500ms on Tempo) and returns
the receipt inline, eliminating the race condition of separate receipt polling.

## Usage

    {:ok, tx_hash} = Onchain.Tempo.RPC.broadcast_async(signed_hex, rpc_url)

    {:ok, tx_hash, receipt} = Onchain.Tempo.RPC.broadcast_sync(signed_hex, rpc_url)

    {:ok, receipt} = Onchain.Tempo.RPC.fetch_receipt(tx_hash, rpc_url)

## Options

All functions accept an `opts` keyword list with:

  * `:req_options` — keyword list passed to `Req.request/2` (timeouts, adapters, etc.)

# `broadcast_async`

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

Broadcast a signed transaction via async `eth_sendRawTransaction`.

Returns the transaction hash immediately without waiting for block inclusion.

# `broadcast_sync`

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

Broadcast a signed transaction via Tempo's synchronous `eth_sendRawTransactionSync`.

Waits for block inclusion and returns the full receipt inline. Returns
`{:ok, tx_hash, receipt}` on success.

# `fetch_receipt`

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

Fetch a transaction receipt via `eth_getTransactionReceipt`.

# `parse_receipt`

```elixir
@spec parse_receipt(map()) :: map()
```

Parse a raw JSON-RPC receipt map into atom-keyed format.

The output is compatible with `Onchain.Transfer.parse_logs/1` and
`Onchain.Tempo.Transfer.parse_transfer_with_memo_logs/1`.

# `simulate`

```elixir
@spec simulate(String.t(), String.t(), keyword()) ::
  {:ok, :success}
  | {:ok, {:revert, String.t()}}
  | {:ok, :unsupported}
  | {:error, String.t()}
```

Simulate a co-signed Tempo 0x76 transaction via `eth_simulateV1` before
broadcasting, so a fee payer can confirm the transaction would SUCCEED before
paying its gas.

Reconstructs a `TempoTransactionRequest` from the decoded envelope (recovering
the sender for `from` and folding the tail call into `to`/`input`), runs the
simulation against latest state with `validation: false` (no signature checks),
and reports the execution outcome:

  * `{:ok, :success}` — the transaction would succeed (call status `0x1`)
  * `{:ok, {:revert, detail}}` — the transaction would fail on-chain: either the
    call status is `0x0` (revert / out-of-gas, the gas-draining DoS this guards
    against) or the node rejected the transaction as invalid (an `eth_simulateV1`
    execution error such as `-38013` "intrinsic gas too low"). `detail` carries
    the node's error message / revert data. A fail-open caller MUST still reject
    on this result — it means the transaction is bad, not the node.
  * `{:ok, :unsupported}` — the node does not implement `eth_simulateV1`
    (JSON-RPC error `-32601`); the caller decides whether to fail open or closed
  * `{:error, reason}` — the transaction could not be decoded, or the RPC failed
    for an operational reason (transport error, or a non-execution RPC error)

`raw_hex` is an already co-signed 0x76 transaction hex string.

> #### Method note {: .info}
> The Tempo node exposes the EVM-standard `eth_simulateV1` (AA-aware: it accepts
> the 0x76 `type`, `feeToken`, and the folded AA call). `tempo_simulateV1` —
> used by the mpp-rs reference — is not deployed on Tempo mainnet (4217) or
> Moderato testnet (42431); both return `-32601`. Verified empirically against
> both networks.

---

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