> ## Documentation Index
> Fetch the complete documentation index at: https://docs.genlabs.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Rust SDK

> Typed Rust client for the Grid JSON-RPC API: connect, query, sign, and submit activations from your own service or agent.

The Rust SDK is the canonical client for the Grid. The `gen` CLI uses it under the hood, and so does every Rust integration. This page covers what to install, how to configure a client, and a worked example for the most common job: sending a transfer.

For the full API reference, see the rustdoc on [docs.rs](https://docs.rs/client-sdk) (when published) or build it locally with `cargo doc -p client-sdk --open`.

## Crates

| Crate               | What it is                                                                                                                               |
| ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `gen-rpc-client`    | Low-level JSON-RPC client. Implements every method on the [JSON-RPC API](/reference/rpc/overview).                                       |
| `client-sdk`        | Runtime helpers for `GenClient`, `GenSigner`, shared payload types, account helpers, errors, and test utilities.                         |
| `client-sdk-macros` | `#[generate_component_client]` and `#[generate_contract_client]` macros that generate typed payload clients from ABI or manifest inputs. |
| `dynamic-codecs`    | Dynamic ABI-driven encoding and decoding used by CLI tooling and runtime contract interaction without compile-time types.                |

## Install

The crates are not yet published to crates.io. Pull them from the gen-bc repo by Git tag:

```bash theme={null}
cargo add tokio --features full
cargo add client-sdk client-sdk-macros --git https://github.com/gen-bc/gen --tag v0.1.0 --features http
```

Or pin them in `Cargo.toml` directly:

```toml theme={null}
[dependencies]
client-sdk = { git = "https://github.com/gen-bc/gen", tag = "v0.1.0", features = ["http"] }
client-sdk-macros = { git = "https://github.com/gen-bc/gen", tag = "v0.1.0" }
tokio = { version = "1", features = ["full"] }
```

Replace `v0.1.0` with the tag matching your target [network](/user-guide/network-status).

## Configure a client

`GenClient` owns RPC access, view execution, activation submission, and waiting. Most apps construct one and reuse it.

<Note>
  **DevNet access.** DevNet requires a bearer token. Ask your Gen Labs contact for one and substitute it for `<your-jwt>` in the examples below.
</Note>

```rust theme={null}
use client_sdk::GenClient;

#[tokio::main]
async fn main() -> Result<(), client_sdk::SdkError> {
    let client = GenClient::new_http("https://devnet.genlabs.co/rpc/")?;
    Ok(())
}
```

`new_http_with_rpc_config(...)` accepts a `ClientConfig` if you need custom headers, timeouts, or a different RPC URL per request.

## First call

Probe the validator to confirm connectivity:

```rust theme={null}
let version = client.get_version().await?;
println!("validator {}, rpc protocol {}", version.release_version, version.rpc_protocol_version);
```

That single call rules out the most common setup failures: wrong endpoint, network unreachable, protocol version mismatch.

## Send a transfer

Sending a transfer is a four-step flow: load a signer, build the activation payload, sign and submit it, await the result. The SDK collapses the last two into one call.

```rust theme={null}
use client_sdk::{GenClient, GenSigner};
use client_sdk::faucet::{build_transfer_payload, FaucetTransferOptions};
use client_sdk::types::{AmountInSubunits, GvmAccount};

#[tokio::main]
async fn main() -> Result<(), client_sdk::SdkError> {
    let client = GenClient::new_http("https://devnet.genlabs.co/rpc/")?;

    // 1. Load the sender's signing key.
    let signer = GenSigner::from_private_key_bytes(&[0u8; 32])?; // replace with your key

    // 2. Build the transfer payload.
    let recipient: GvmAccount = "grd@1qyqqqqqj6jdqp...".parse()?;
    let amount = AmountInSubunits::new(1_000);
    let payload = build_transfer_payload(recipient, amount, FaucetTransferOptions::builder().build())?;

    // 3. Sign, submit, and wait for finality.
    let outcome = client
        .sign_and_submit_and_wait_activation(&signer, payload)
        .await?;

    // 4. Inspect the outcome.
    println!("activation_id: {:?}", outcome.terminal_activation().id());
    println!("status: {:?}", outcome.terminal_activation().status());
    Ok(())
}
```

A few notes:

* The example uses `build_transfer_payload` from `client_sdk::faucet`. That helper is the canonical path for moving the GEN token between accounts. To call a custom token contract, generate a typed client with `#[generate_contract_client]` and call its `transfer` method instead.
* `sign_and_submit_and_wait_activation` polls until the activation reaches a terminal state. If you need fire-and-forget semantics use `sign_and_submit_activation` and follow up later with `client.wait(activation_id)`.
* `AmountInSubunits` is the smallest unit of the token. The GEN token uses 18 decimals; convert as needed before passing.

## Loading keys

`GenSigner` accepts raw bytes today. Most production agents will load from a wallet file written by the CLI or from a KMS. The CLI's wallet store lives at `~/.gen/wallets/`. To bridge from there programmatically, use `gen wallet export` (see [`gen wallet`](/reference/cli/wallet)) and feed the result to `GenSigner::from_private_key_bytes`.

Never hard-code a private key in source. The example above uses `[0u8; 32]` only as a placeholder.

## GenClient API surface

Every public method on `GenClient`, in source order. For full signatures and documentation, see the rustdoc.

| Method                                                  | Kind  | Description                                                                      |
| ------------------------------------------------------- | ----- | -------------------------------------------------------------------------------- |
| `new(...)`                                              | sync  |                                                                                  |
| `new_json_rpc(...)`                                     | sync  | Creates a new `GenClient` connected to the given JSON-RPC endpoint URL.          |
| `new_json_rpc_with_rpc_config(...)`                     | sync  | Creates a new `GenClient` using a caller-provided transport configuration.       |
| `new_grpc(...)`                                         | sync  | Creates a new `GenClient` connected to the given gRPC RPC endpoint.              |
| `new_grpc_with_rpc_config(...)`                         | sync  |                                                                                  |
| `rpc_transport(...)`                                    | sync  | Returns the normalized RPC transport (JSON-RPC or gRPC).                         |
| `poll_config(...)`                                      | sync  |                                                                                  |
| `wait_strategy(...)`                                    | sync  |                                                                                  |
| `config(...)`                                           | sync  |                                                                                  |
| `get_version(...)`                                      | async | Returns the server's reported artifact release version and RPC protocol version. |
| `get_fresh_valid_until_block(...)`                      | async | Returns the current finalized block plus the SDK's short validity buffer.        |
| `external_activation_header(...)`                       | sync  | Builds an external-activation header from this client's static wire config       |
| `build_signable_activation(...)`                        | async | Builds the canonical unsigned activation that will later be signed,              |
| `build_signable_activation_with_options(...)`           | async | Builds the canonical unsigned activation that will later be signed.              |
| `view(...)`                                             | async | Executes a read-only view call and returns the raw result bytes.                 |
| `simulate_activation(...)`                              | async | Simulates a transaction without submitting it to the network.                    |
| `simulate_activation_with_options(...)`                 | async | Simulates a transaction without submitting it to the network, using              |
| `simulate_signable_activation(...)`                     | async | Simulates a pre-built canonical unsigned activation without submitting it.       |
| `submit_activation(...)`                                | async | Submits a transaction and returns the activation ID.                             |
| `submit_activation_payload(...)`                        | async | Submits an already-encoded activation payload as-is.                             |
| `sign_and_submit_activation(...)`                       | async | Builds, signs, and submits a transaction in one step.                            |
| `sign_and_submit_activation_with_options(...)`          | async | Builds, signs, and submits a transaction in one step, using                      |
| `wait(...)`                                             | async | Polls an already-submitted activation until it reaches a terminal state          |
| `submit_activation_and_wait(...)`                       | async | Submits a transaction and polls until the activation reaches a terminal          |
| `sign_and_submit_and_wait_activation(...)`              | async | Builds, signs, submits, and waits for a transaction in one step.                 |
| `sign_and_submit_and_wait_activation_with_options(...)` | async | Builds, signs, submits, and waits for a transaction in one step, using           |
| `get_activation(...)`                                   | async | Queries the current status of an activation.                                     |
| `get_account(...)`                                      | async | Returns entity information (owner, installed components).                        |
| `get_balance(...)`                                      | async | Returns the default GEN token balance for an account.                            |
| `get_balances(...)`                                     | async | Returns all fungible balances for an account.                                    |
| `get_current_block_index(...)`                          | async | Returns the latest finalized block index.                                        |
| `get_block(...)`                                        | async | Returns an aggregated closed block for a given block index.                      |
| `get_component(...)`                                    | async | Returns component metadata and ABI.                                              |
| `get_storage_at(...)`                                   | async | Returns the raw storage value for a component at a given key.                    |
| `get_contract(...)`                                     | async | Returns contract metadata and all component ABIs.                                |
| `get_abi_by_contract_id(...)`                           | async | Returns contract ABIs by contract ID.                                            |
| `get_abi_by_contract_code_id(...)`                      | async | Returns contract ABIs by contract code ID.                                       |
| `get_trace(...)`                                        | async | Returns trace details by transaction ID.                                         |
| `create_account(...)`                                   | async | Submits a faucet-signed `Account::create_entity_with_id(account)`                |
| `transfer(...)`                                         | async | Submits a `transfer` (or `transfer_with_confirmation` when                       |
| `faucet(...)`                                           | async | Submits a faucet-signed transfer to `account`. Thin wrapper over                 |
| `wait_for_tree_completion(...)`                         | async | Waits for the entire activation tree rooted at `activation_id` to reach          |

## Errors

The SDK returns structured `SdkError` variants. The ones you are likely to handle in production:

| Variant             | When it fires                                                                                 |
| ------------------- | --------------------------------------------------------------------------------------------- |
| `Transport`         | Network error reaching the validator. Retry with backoff.                                     |
| `Server`            | Validator returned a JSON-RPC error. Do not retry without inspecting `code`.                  |
| `ActivationPolling` | Polling for activation status timed out. Re-check via `get_activation`.                       |
| `ActivationResult`  | The activation reached a non-success terminal state. The variant carries the failure reason.  |
| `Encode` / `Decode` | Borsh serialization failure on inputs or outputs. Almost always a type mismatch in your code. |

See the rustdoc for the full enum.

## Next steps

* [JSON-RPC reference](/reference/rpc/overview): every wire-level method the SDK speaks.
* [Send your first transfer (CLI)](/quickstart/index): the same flow at the command line, useful for sanity-checking your setup.
