---
title: thru-client
description: High-level Rust gRPC client for Thru with ergonomic helpers for
  accounts, transactions, streaming confirmations, proofs, and node status.
source_url:
  html: https://thru.org/docs/sdks/rust-packages/thru-client/
  md: https://thru.org/docs/sdks/rust-packages/thru-client.md
---

# thru-client

Use `thru-client` when you want an ergonomic Rust RPC client instead of assembling channels, metadata, and request types on top of the raw generated bindings.

## Install

```bash
cargo add thru-client thru-base url
cargo add tokio --features macros,rt-multi-thread
```

## When to use it

Choose this crate when you want to:

- Query accounts, balances, transactions, block heights, chain info, and node status with typed helper methods.
- Submit signed transactions and wait for execution with `execute_transaction`, or fire-and-forget with `send_transaction` and `batch_send_transactions`.
- Track many in-flight transactions over one connection with `stream_confirmations`.
- Generate state proofs and prepare account decompression without touching proto types.

## Choose another crate when

- You need keys, transaction builders, address parsing, or proof helpers: use `thru-base`. `thru-client` submits already-signed wire bytes; it does not build or sign transactions.
- You want to stay close to the wire format or call the generated services directly: use `thru-grpc-client`.

## Client construction

Build a `Client` with `ClientBuilder` (also reachable as `Client::builder()`):

```rust
use std::time::Duration;
use thru_client::{Client, ClientBuilder};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client: Client = ClientBuilder::new()
        .http_endpoint(url::Url::parse("http://127.0.0.1:8472")?)
        .timeout(Duration::from_secs(30))
        .build()?;

    let height = client.get_block_height().await?;
    println!("finalized height: {}", height.finalized_height);
    Ok(())
}
```

| Builder method | What it configures |
| - | - |
| `http_endpoint(url::Url)` | The node’s gRPC endpoint. Defaults to `http://127.0.0.1:8472`. An `https://` URL enables TLS, configured when `build` runs, so the builder methods are order-independent. |
| `timeout(Duration)` | Per-request timeout. Defaults to 30 seconds. |
| `auth_token(Option<String>)` | Optional bearer token sent as the `authorization` metadata header on every request. |
| `insecure(bool)` | Skip TLS certificate verification for `https://` endpoints, for nodes presenting self-signed or otherwise untrusted certificates. Disables peer authentication, so only use it against endpoints you trust by other means. No effect on plaintext endpoints. |
| `announce_pending_signature(bool)` | Print each pending transaction signature to stderr just before submission. Off by default. |
| `build()` | Produce the `Client`. The connection itself is established lazily on first use. |

## Main request helpers

All helpers are `async` and return `thru_client::Result<T>` (`Result<T, ClientError>`).

| Task | Main entrypoints |
| - | - |
| Read accounts | `get_account_info`, `get_balance`, `get_account_at_slot` |
| Read transactions | `get_transaction`, `list_transactions_for_account`, `track_transaction_polling` |
| Submit transactions | `execute_transaction`, `send_transaction`, `batch_send_transactions` |
| Stream confirmations | `stream_confirmations` returning a `ConfirmationStream` |
| Node and chain info | `get_version`, `get_chain_info`, `get_health`, `get_block_height`, `get_node_status` |
| State and metrics | `get_state_roots`, `get_state_hashes`, `get_slot_metrics`, `list_slot_metrics` |
| Proofs and decompression | `make_state_proof`, `prepare_account_decompression` |
| Debugging | `debug_re_execute` |

`get_account_info` and `get_transaction` return `Ok(None)` when the node reports `NOT_FOUND` instead of surfacing an error.

## Submitting transactions

Build and sign the transaction with `thru-base`, then hand the wire bytes to the client:

- `execute_transaction(transaction, timeout)` submits and waits for execution over a server-side tracking stream, then fetches full `TransactionDetails` (consumed compute, memory, and state units, execution and VM error codes, events, accounts, and header fields). If tracking times out or fails in a way that leaves the submission outcome unknown, it falls back to polling for the transaction by signature.
- `send_transaction(transaction)` submits without waiting and returns the 64-byte signature.
- `batch_send_transactions(transactions, num_retries)` submits many pre-signed transactions in one request and returns `(signature, accepted)` per transaction, in order. Use `stream_confirmations` to observe when accepted transactions land on-chain.

```rust
use std::time::Duration;

let details = client
    .execute_transaction(&wire_bytes, Duration::from_secs(30))
    .await?;
assert_eq!(details.execution_result, 0);
assert_eq!(details.vm_error, 0);
```

## Streaming confirmations

`stream_confirmations(fee_payer)` opens a live server stream of confirmations for transactions paid for by `fee_payer`, letting one connection track many in-flight transactions:

```rust
let mut stream = client.stream_confirmations(&fee_payer).await?;
while let Some(confirmation) = stream.next(Duration::from_secs(10)).await? {
    println!(
        "slot {}: vm_error={} execution_result={}",
        confirmation.slot, confirmation.vm_error, confirmation.execution_result
    );
}
```

`ConfirmationStream::next` returns `Ok(Some(Confirmation))` when a transaction is confirmed with an execution result, `Ok(None)` when the timeout elapses first, and `Err(_)` when the stream ends or errors. Drop the stream to unsubscribe.

## Errors

Fallible calls return `ClientError`, whose variants distinguish `Rpc`, `Transport`, `Validation`, `TransactionSubmission`, `TransactionVerification`, `AccountNotFound`, and `Generic` failures. `get_balance` returns `AccountNotFound` for missing accounts.

## Notes for agents

- The crate re-exports the generated proto modules as `thru_client::proto`, so response types that are passed through unconverted (for example from `debug_re_execute`) resolve without adding a direct `thru-grpc-client` dependency.
- Helper methods take `thru_base::tn_tools::Pubkey` and `Signature` wrapper types, not raw byte arrays; `signature_from_wire` extracts the trailing 64-byte fee-payer signature from signed wire bytes.
- In this repository, `rpc/thru-client` layers these helpers on top of `thru-grpc-client`; the Thru CLI is its main in-tree consumer.
