# `Cartouche.Solana.RPC`
[🔗](https://github.com/zenhive/cartouche/blob/main/lib/cartouche/solana/rpc.ex#L1)

JSON-RPC client for Solana.

Provides typed functions for Solana RPC methods with automatic
Base58 encoding of pubkeys, commitment level options, and response
deserialization.

## Configuration

    config :cartouche,
      solana_node: "https://api.mainnet-beta.solana.com"

## Examples

    {:ok, balance} = Cartouche.Solana.RPC.get_balance(pubkey)
    {:ok, slot} = Cartouche.Solana.RPC.get_slot()
    {:ok, %{blockhash: bh}} = Cartouche.Solana.RPC.get_latest_blockhash()

# `invalid_params_error`

```elixir
@type invalid_params_error() :: {:invalid_params, Exception.t()}
```

Error returned when JSON encoding rejects the outbound request body.

# `rpc_error`

```elixir
@type rpc_error() :: %{code: integer(), message: String.t()}
```

JSON-RPC error envelope returned by a Solana node or by response validation.

# `send_rpc_error`

```elixir
@type send_rpc_error() ::
  rpc_error()
  | invalid_params_error()
  | Finch.Response.t()
  | Jason.DecodeError.t()
  | String.t()
```

All error shapes returned by `send_rpc/3`.

# `get_account_info`

```elixir
@spec get_account_info(
  &lt;&lt;_::256&gt;&gt;,
  keyword()
) :: {:ok, map() | nil} | {:error, term()}
```

Get account info for a pubkey. Returns `nil` if the account doesn't exist.

## Options
- `:commitment` - `:processed`, `:confirmed`, or `:finalized`
- `:encoding` - `:base64` (default), `:base58`, `:"base64+zstd"`, `:json_parsed`

# `get_balance`

```elixir
@spec get_balance(
  &lt;&lt;_::256&gt;&gt;,
  keyword()
) :: {:ok, non_neg_integer()} | {:error, term()}
```

Get the SOL balance (in lamports) for an account.

## Options
- `:commitment` - `:processed`, `:confirmed`, or `:finalized`

# `get_block_height`

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

Get the current block height.

# `get_health`

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

Check node health. Returns `:ok` if healthy, `{:error, ...}` if unhealthy.

# `get_latest_blockhash`

```elixir
@spec get_latest_blockhash(keyword()) ::
  {:ok, %{blockhash: binary(), last_valid_block_height: non_neg_integer()}}
  | {:error, term()}
```

Get the latest blockhash and its last valid block height.

# `get_minimum_balance_for_rent_exemption`

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

Get the minimum balance for rent exemption for a given data size.

# `get_multiple_accounts`

```elixir
@spec get_multiple_accounts(
  [&lt;&lt;_::256&gt;&gt;],
  keyword()
) :: {:ok, [map() | nil]} | {:error, term()}
```

Get account info for multiple pubkeys (max 100).

## Options
- `:commitment`, `:encoding` - same as `get_account_info/2`

# `get_recent_prioritization_fees`

```elixir
@spec get_recent_prioritization_fees(
  [&lt;&lt;_::256&gt;&gt;],
  keyword()
) ::
  {:ok, [%{slot: non_neg_integer(), prioritization_fee: non_neg_integer()}]}
  | {:error, term()}
```

Get recent prioritization fees. Pass account addresses to see fees for
transactions locking those accounts.

# `get_signature_statuses`

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

Get the statuses of transaction signatures (max 256).

## Options
- `:search_transaction_history` - Search beyond recent status cache (default: false)

# `get_slot`

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

Get the current slot.

# `get_token_account_balance`

```elixir
@spec get_token_account_balance(
  &lt;&lt;_::256&gt;&gt;,
  keyword()
) ::
  {:ok,
   %{
     amount: non_neg_integer(),
     decimals: non_neg_integer(),
     ui_amount_string: String.t()
   }}
  | {:error, term()}
```

Get the token balance for an SPL Token account.

Returns the raw integer amount, decimal precision, and `ui_amount_string`
(a human-readable formatted string provided by the RPC node, e.g. `"1.5"`
for 1500000 with 6 decimals).

# `get_token_accounts_by_owner`

```elixir
@spec get_token_accounts_by_owner(&lt;&lt;_::256&gt;&gt;, keyword(), keyword()) ::
  {:ok, [%{pubkey: String.t(), account: map()}]} | {:error, term()}
```

Get all token accounts owned by a wallet.

Requires exactly one filter: `:mint` (specific token) or `:program_id`
(all tokens under a program).

Uses `jsonParsed` encoding by default for structured token account data.

## Examples

    get_token_accounts_by_owner(wallet, mint: usdc_mint)
    get_token_accounts_by_owner(wallet, program_id: Programs.token_program())

# `get_transaction`

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

Get a transaction by its signature.

Returns `nil` if the transaction is not found.

## Options
- `:commitment` - `:confirmed` or `:finalized` (`:processed` is NOT supported)
- `:encoding` - `:json` (default), `:json_parsed`, `:base64`, `:base58`

# `get_version`

```elixir
@spec get_version(keyword()) ::
  {:ok, %{solana_core: String.t(), feature_set: non_neg_integer()}}
  | {:error, term()}
```

Get the node version.

# `request_airdrop`

```elixir
@spec request_airdrop(&lt;&lt;_::256&gt;&gt;, non_neg_integer(), keyword()) ::
  {:ok, String.t()} | {:error, term()}
```

Request an airdrop of SOL (devnet/testnet only).

Returns the airdrop transaction signature.

# `send_and_confirm`

```elixir
@spec send_and_confirm(
  Cartouche.Solana.Transaction.t() | binary(),
  keyword()
) :: {:ok, String.t()} | {:error, term()}
```

Send a transaction and poll for confirmation.

## Options
- `:commitment` - Confirmation level to wait for (default: `:confirmed`)
- `:timeout` - Max time to wait in ms (default: 30_000)
- `:poll_interval` - Poll interval in ms (default: 500)
- All options from `send_transaction/2`

# `send_rpc`

```elixir
@spec send_rpc(binary(), list(), keyword()) ::
  {:ok, term()} | {:error, send_rpc_error()}
```

Send a raw JSON-RPC request to the Solana node.

Options:
- `:solana_node` - Override the node URL
- `:timeout` - Request timeout in ms (default: 30000)
- `:id` - JSON-RPC request ID (default: auto-generated)

## Examples

    iex> Cartouche.Solana.RPC.send_rpc("getSlot", [])
    {:ok, 123456789}

    iex> match?({:error, {:invalid_params, %Jason.EncodeError{}}}, Cartouche.Solana.RPC.send_rpc(<<255>>, []))
    true

    iex> match?({:error, {:invalid_params, %Protocol.UndefinedError{}}}, Cartouche.Solana.RPC.send_rpc("getSlot", [self()]))
    true

# `send_transaction`

```elixir
@spec send_transaction(
  binary() | Cartouche.Solana.Transaction.t(),
  keyword()
) :: {:ok, String.t()} | {:error, term()}
```

Send a signed transaction to the network.

Accepts a `Cartouche.Solana.Transaction` struct or raw serialized bytes.

## Options
- `:encoding` - `:base64` (default) or `:base58`
- `:skip_preflight` - Skip preflight checks (default: false)
- `:preflight_commitment` - Commitment for preflight simulation
- `:max_retries` - Max retries before giving up

Returns the transaction signature (Base58 string).

# `simulate_transaction`

```elixir
@spec simulate_transaction(
  binary() | Cartouche.Solana.Transaction.t(),
  keyword()
) :: {:ok, map()} | {:error, term()}
```

Simulate a transaction without submitting it.

Returns simulation result including logs, compute units consumed, and errors.

---

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