# `X402.Solana.RPC`
[🔗](https://github.com/cardotrejos/x402/blob/v0.9.0/lib/x402/solana/rpc.ex#L1)

Minimal Solana JSON-RPC calls over an `X402.RPC` endpoint.

Provides exactly the RPC surface the SVM facilitator engine needs —
`getLatestBlockhash`, `simulateTransaction`, `sendTransaction`, and
`getSignatureStatuses` — as thin wrappers around the generic
`X402.RPC.request/3`, unwrapping Solana's `%{"context", "value"}` response
envelope where present. It is not a general-purpose Solana client: there is
no account fetching, no address-lookup-table resolution, and no WebSocket
subscription support.

    {:ok, rpc} =
      X402.RPC.new(
        rpc_url: "https://api.devnet.solana.com",
        finch: MyApp.Finch
      )

    {:ok, %{blockhash: blockhash}} = X402.Solana.RPC.get_latest_blockhash(rpc)

All transport, TLS, and telemetry behaviour is inherited from `X402.RPC`
(events carry the Solana method name as `:method` metadata), and errors are
`t:X402.RPC.error/0` values — node-side failures come back as
`{:error, {:jsonrpc_error, %{code: _, message: _, data: _}}}`.

# `latest_blockhash`

```elixir
@type latest_blockhash() :: %{
  blockhash: String.t(),
  last_valid_block_height: non_neg_integer()
}
```

The unwrapped `getLatestBlockhash` value.

# `signature_status`

```elixir
@type signature_status() ::
  nil | %{confirmation_status: String.t() | nil, err: term() | nil}
```

One `getSignatureStatuses` entry: `nil` for an unknown signature, or the
status with its `confirmationStatus` (`"processed"`, `"confirmed"`,
`"finalized"`, or `nil`) and error term.

# `simulation`

```elixir
@type simulation() :: %{err: term() | nil, logs: [String.t()] | nil}
```

The unwrapped `simulateTransaction` value.

`err` is `nil` when the simulated transaction would succeed; otherwise the
node's error term (a string or a map, passed through as decoded JSON).

# `get_latest_blockhash`
*since 0.6.0* 

```elixir
@spec get_latest_blockhash(
  X402.RPC.t(),
  keyword()
) :: {:ok, latest_blockhash()} | {:error, X402.RPC.error()}
```

Fetches the latest blockhash via `getLatestBlockhash`.

Returns the blockhash (Base58) and the last block height at which a
transaction using it is still valid.

## Options

* `:commitment` (`t:String.t/0`) - The commitment level for the request. The default value is `"confirmed"`.

# `get_signature_statuses`
*since 0.6.0* 

```elixir
@spec get_signature_statuses(X402.RPC.t(), [String.t()]) ::
  {:ok, [signature_status()]} | {:error, X402.RPC.error()}
```

Fetches confirmation statuses for Base58 signatures via
`getSignatureStatuses`.

Returns one entry per requested signature, **in request order**: `nil` for
a signature the node does not know, or a map with its
`confirmation_status` and `err` (non-`nil` when the transaction was
included but failed on chain).

The request is issued with `searchTransactionHistory: true`. The node's
in-memory status cache only retains recent signatures, so pending-store
retries that arrive after a confirmed transaction ages out would otherwise
see `nil` and never observe the successful payment.

# `send_transaction`
*since 0.6.0* 

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

Broadcasts a Base64-encoded wire transaction via `sendTransaction`.

Sends with `skipPreflight: true`, matching the reference facilitators —
verification already simulated, and a preflight failure here would be
indistinguishable from a node-side rejection. Returns the Base58
transaction signature acknowledged by the node.

## Options

* `:commitment` (`t:String.t/0`) - The commitment level for the request. The default value is `"confirmed"`.

# `simulate_transaction`
*since 0.6.0* 

```elixir
@spec simulate_transaction(X402.RPC.t(), String.t(), keyword()) ::
  {:ok, simulation()} | {:error, X402.RPC.error()}
```

Simulates a Base64-encoded wire transaction via `simulateTransaction`.

The simulation runs with `sigVerify: false` and
`replaceRecentBlockhash: false`, matching the reference facilitators: the
fee-payer slot is unsigned until settlement, so required signatures must be
verified locally instead (see `X402.Verify.SVM`), and the embedded
blockhash is part of what is being validated.

Returns the node's simulation verdict — `err: nil` means the transaction
would succeed.

## Options

* `:commitment` (`t:String.t/0`) - The commitment level for the request. The default value is `"confirmed"`.

---

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