> ## 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.

# Genie SDK reference

> FIRE and Genie for component-based contracts on the GVM — computational model, design principles, and API reference.

**FIRE** is a development framework that helps you harness The Grid's computational model to design scalable, bottleneck-free systems.

**Genie** is the Rust SDK for The Grid. It helps you structure contract logic using FIRE principles — one `#[contract]` codebase, multiple installable component roles — and handles deployment, installation, access control, and type-safe calls within and across entities.

> Genie is an early preview. The API surface will evolve.

> **Prerequisite.** This reference assumes you are familiar with how The Grid structures execution and state. If entities, components, and activations are new, read these first:
>
> * [Entities and accounts](/user-guide/concepts/entities-and-accounts) — what an entity is and how it holds components
> * [Components](/user-guide/concepts/components) — installable logic and storage, same-entity vs cross-entity interaction
> * [Activations](/user-guide/concepts/activations) — how work is submitted, queued, and routed to components

## Contracts and the entity model

The entity and component model describes how code and state are **structured** on The Grid.

* **Entity** — an addressable container and the unit of sequential execution. Activations arrive at an entity, enter its queue, and are processed one at a time; each is routed to a component inside the entity. See [Entities and accounts](/user-guide/concepts/entities-and-accounts).
* **Component** — immutable logic and independent state **installed inside** an entity. Each component owns its storage; many components can coexist on one entity. See [Components](/user-guide/concepts/components).
* **Logic immutability** — Installing a component into an entity does not let the entity owner tamper with it. The instance runs only its verified on-chain code and responds through its published ABI; every activation is handled according to that logic and its access rules, not at the installer's discretion.
* **Contract** — one verified codebase that defines one or more component types (for example root, issuer, holder). Deploy creates the root instance; install creates other component types on an entity.
* **Co-location boundary** — components on the **same entity** can call each other synchronously within a single activation on that entity's queue. Components on **different entities** do not share storage; they interact only by sending activations between entities.

In Genie, `#[deploy]` instantiates the root component on an entity; `#[install]` adds non-root types. The manifest's `component_type_index` identifies each type when you push and install from the CLI.

## Actor model

In FIRE, the actor model is the foundation for distributing execution and state. On The Grid, the **entity is the actor**: it owns the activation queue and processes work sequentially. **Components** are the immutable logic and independent state modules that live inside an entity and run when an activation reaches them.

### Core principles

* **Message passing and sequential handling** — Entities communicate asynchronously by sending activations to one another. Each entity maintains its own queue and processes incoming activations **one at a time**, in order, dispatching each to the targeted component inside it.
* **Independent execution units** — Each entity runs on its own queue. Work on one entity does not block unrelated entities elsewhere in the system.
* **Immediate state commit** — When an activation completes on an entity, the affected components' state changes commit immediately. Local state stays consistent without waiting for cross-entity consensus.
* **State isolation** — Each component maintains its own storage. During an activation, a component may update its own state and trigger new activations to other entities; it never directly mutates another component's storage.

### Operational considerations

Distributing state and execution trades synchronous, all-or-nothing transactions for parallel throughput. The async consequences are familiar from other actor and message-passing systems. Two show up most often:

* **No transactional revert** — Each activation is its own commit boundary. A failure downstream does not roll back work already committed upstream; coordinate across steps explicitly instead of assuming one global transaction.
* **Stale reads and interleaving** — As in ordinary async code, state can change between sending a request and handling the response. Design multi-step flows with continuations and idempotent handlers where retries are possible.

## Key FIRE concepts

FIRE is how you scale safely on The Grid. **Scale requires asynchrony** — throughput comes from distributed execution across entities, not from serializing the whole network. **Mitigate async complexity** with developer-defined guarantees and explicit design patterns rather than assuming one global transaction. **Unlock parallel scalability** by structuring work so independent entities and components run concurrently without a single hot spot. The principles below spell that out and map each one to Genie:

| Principle                          | What it means                                                                                        | In Genie                                                                                                    |
| ---------------------------------- | ---------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| **Distribute state and execution** | Segregate state across components and execution across entities to maximize throughput.              | Struct fields and `Storage::*` are scoped to one component; each entity runs on its own activation queue.   |
| **Manage component relations**     | Use developer-defined guarantees to ensure distribution safety.                                      | `#[installation_request]`, `#[owner]` / `#[private]`, install ownership, delegated access grants.           |
| **Prioritize composability**       | Build from reusable, interface-defined components while keeping state isolated.                      | Multi-module `#[contract]`, installers, `GvmContract` handles, generated typed clients.                     |
| **Co-locate for atomicity**        | Group cooperating components on the same entity when one activation must see consistent local state. | Same-entity `local` calls; root plus helper components installed together when they must update atomically. |

Used together, these principles are how applications built with FIRE are planned for scalability: independent entities and components handle work in parallel — cross-entity `remote` calls and async continuations where work should be distributed, flow control and error handling shaped by component relations, and entity-level atomicity through co-location when a step must stay local.

## Feature snapshot

| Area                    | Capabilities                                                                               |
| ----------------------- | ------------------------------------------------------------------------------------------ |
| **Contract definition** | `#[contract]`, component modules                                                           |
| **Lifecycle**           | `#[deploy]`, `#[install]`, `#[installation_request]`                                       |
| **Access control**      | `#[owner]`, `#[public]`, `#[private]`, `#[view]`                                           |
| **Storage**             | Struct member fields, `Storage::save` / `load` / `load_guarded`, keyed storage             |
| **Communication**       | Generated clients and installers, `.local` / `.remote`                                     |
| **Runtime**             | Remote `.await`, `genie::spawn()`, spawn callbacks (`on_error`, `on_success`, `on_result`) |
| **Error handling**      | `#[error_type]`, `ensure!`, `try_as()` for cross-call errors                               |
| **Generated code**      | Clients, installers, role refs, `Self::root_client()`                                      |

## Common types

| Type               | Purpose                                                                                          |
| ------------------ | ------------------------------------------------------------------------------------------------ |
| `EntityId`         | Identifies an account or entity                                                                  |
| `AmountInSubunits` | Token amounts; supports `checked_add`, `checked_sub`, `checked_mul`, `checked_div`               |
| `GvmContract`      | Handle to a deployed contract instance; pass to `install()` when composing with another contract |
| `GvmComponentId`   | Handle to a specific component instance                                                          |

## Quick start

```toml theme={null}
[dependencies]
genie = { git = "https://github.com/gen-bc/gen-framework-preview", tag = "v0.15.0" }
```

### Define a contract

Contract crates target RISC-V and use `#![no_std]` instead of the full standard library. If the contract uses heap types (`String`, `Vec`, and so on), also add `extern crate alloc` at the top of `src/lib.rs`:

```rust theme={null}
#![no_std]
extern crate alloc;

use genie::contract;

#[contract]
pub mod simple_counter_contract {
    /// Root component for counter metadata
    pub mod root {
        use genie::{Result, deploy, installation_request, view};

        /// Component struct with member fields for automatic storage management.
        /// Fields are loaded before method execution and saved after mutable methods.
        pub struct CounterRoot {
            count: u64,
        }

        impl CounterRoot {
            /// Runs once when this contract is instantiated. Initializes the root and returns Self.
            /// Fields are automatically saved to storage after deployment.
            #[deploy]
            pub async fn deploy() -> Result<Self> {
                Ok(Self { count: 0 })
            }

            /// Validates installation requests for counter components.
            #[installation_request]
            pub async fn installation_request(
                &mut self,
                _component_type: SimpleCounterContractComponents,
            ) -> Result<()> {
                Ok(())
            }

            #[view]
            pub fn get_count(&self) -> Result<u64> {
                Ok(self.count)
            }
        }
    }

    /// Controller component for counter operations
    pub mod controller {
        use genie::{Result, install, owner};

        pub struct CounterController {
            count: u64,
        }

        impl CounterController {
            /// Install receives the return value from installation_request.
            /// Initialize all struct fields and return Self.
            #[install]
            pub async fn install(
                _installation_return_value: (),
            ) -> Result<Self> {
                Ok(Self { count: 0 })
            }

            #[owner]
            pub fn increment(&mut self) -> Result<()> {
                self.count += 1;
                Ok(())
            }
        }
    }
}
```

### Use the component

```rust theme={null}
use genie::{Component, Result};

// Use generated client for type-safe calls
let client = SimpleCounterContractClient::new(component_id);

// Local calls (same entity), synchronous
client.controller.local.increment()?;
let count = client.root.local.get_count()?;

// Remote calls (cross-entity), asynchronous
client.controller.remote.increment().await?;
let count = client.root.remote.get_count().await?;

// Install components using generated installer
let installer = SimpleCounterContractClient::installer();
let controller_id = installer.controller.install(contract_id).await?;
```

## Macro reference

Genie uses procedural macros to define component boundaries, roles, and communication patterns. Entry-point attributes (`#[view]`, `#[owner]`, `#[public]`, `#[private]`) also generate async variants for remote client calls.

### Contract definition

| Macro         | Purpose                                                  |
| ------------- | -------------------------------------------------------- |
| `#[contract]` | Defines a contract module containing multiple components |
| `mod X`       | Declares a component module within a contract            |

### Component lifecycle

| Macro                     | Purpose                                                                                                                            | Example                                                                                                                           |
| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| `#[deploy]`               | Instantiates the contract by deploying the root component; one root deployment = one contract instance (must be async)             | `#[deploy] pub async fn deploy() -> Result<Self>`                                                                                 |
| `#[install]`              | Internal component method called during component installation (must be async)                                                     | `#[install] pub async fn install(data) -> Result<Self>`                                                                           |
| `#[installation_request]` | Root gatekeeper called before each install; may return install data passed to `#[install]` (`BorshSerialize` / `BorshDeserialize`) | `#[installation_request] pub async fn installation_request(&mut self, component_type: ContractComponents) -> Result<InstallData>` |

### Access control

| Macro        | Purpose                                                | Example                                         |
| ------------ | ------------------------------------------------------ | ----------------------------------------------- |
| `#[owner]`   | Restricts access only to the component owner           | `#[owner] fn mint() -> Result<()>`              |
| `#[public]`  | Public entry point callable by any caller              | `#[public] fn transfer() -> Result<()>`         |
| `#[private]` | Callable only by other components in the same contract | `#[private] fn internal_update() -> Result<()>` |

### Read-only methods

| Macro     | Purpose                                         | Example                                   |
| --------- | ----------------------------------------------- | ----------------------------------------- |
| `#[view]` | Read-only public entry point (no state changes) | `#[view] fn get_balance() -> Result<u64>` |

### Attribute usage patterns

#### Read-only versus mutable methods

```rust theme={null}
// View methods: public read-only
#[view]
fn get_balance() -> Result<u64> {
    Storage::load::<u64>()
}

// Public access for any caller
#[public]
fn update_metadata(new_name: String) -> Result<()> {
    Storage::save(new_name)?;
    Ok(())
}
```

## Storage API

**`StorageKey`** — a byte key for keyed storage (`StorageKey::from(...)`). Keyed methods namespace values by type plus key, so you can store multiple values of the same type.

**`StorageGuard<T>`** — a load–modify–save wrapper returned by `load_guarded`. Mutate through it like a reference; changes persist when it is dropped. Do not hold it across `.await`.

| Function                                 | Purpose                                                  |
| ---------------------------------------- | -------------------------------------------------------- |
| `Storage::save<T>(value)`                | Persist value using type-derived key                     |
| `Storage::save_by_key<T>(key, value)`    | Persist with explicit `StorageKey`                       |
| `Storage::load<T>()`                     | Load owned copy of stored value                          |
| `Storage::load_by_key<T>(key)`           | Load with explicit `StorageKey`                          |
| `Storage::load_zero_copy<T>()`           | Load by shared reference (`Rc`) without cloning payload  |
| `Storage::load_zero_copy_by_key<T>(key)` | Zero-copy load with explicit `StorageKey`                |
| `Storage::load_guarded<T>()`             | Returns `StorageGuard<T>` that auto-saves on drop        |
| `Storage::load_guarded_by_key<T>(key)`   | Keyed `StorageGuard<T>` variant                          |
| `Storage::delete<T>()`                   | Remove value by type                                     |
| `Storage::delete_by_key<T>(key)`         | Remove by explicit `StorageKey`                          |
| `Storage::exists<T>()`                   | Check existence by type                                  |
| `Storage::exists_by_key<T>(key)`         | Check existence by `StorageKey`                          |
| `Storage::save_self<T>(&object)`         | Persist entire component struct (used by generated code) |
| `Storage::load_self<T>()`                | Load entire component struct (used by generated code)    |

### Member storage (automatic field persistence)

Components can define struct fields that are automatically persisted to storage. When a component struct has fields:

1. **On load.** The entire struct is loaded from storage using `Storage::load_self<T>()`.
2. **On save.** After mutable method execution, the entire struct is saved using `Storage::save_self<T>(&object)`.

This whole-struct storage approach is more efficient than field-by-field storage, reducing the number of storage operations and ensuring atomic state updates. It is also convenient: state lives on the component struct and is used naturally through `&self`, `&mut self`, and field access, like ordinary Rust.

```rust theme={null}
pub struct FungibleTokenHolder {
    /// Tracks the holder's token balance, automatically persisted.
    token_store: TokenStore,
    /// Stores metadata received during installation, automatically persisted.
    holder_metadata: HolderMetaData,
}

impl FungibleTokenHolder {
    /// Install returns Self with initialized fields.
    /// The framework automatically saves all fields after installation.
    #[install]
    pub async fn install(metadata: Metadata) -> Result<Self> {
        Ok(Self {
            token_store: TokenStore::new(),
            holder_metadata: HolderMetaData::new(metadata),
        })
    }

    /// Read-only access via `&self`; fields are loaded before the method runs.
    #[view]
    pub fn balance(&self) -> Result<AmountInSubunits> {
        Ok(self.token_store.balance())
    }

    /// Mutable access via `&mut self`; fields are saved after this method returns.
    #[private]
    pub fn receive(&mut self, amount: AmountInSubunits) -> Result<()> {
        self.token_store.credit(amount);
        Ok(())
    }
}
```

## Runtime and communication API

| Function                                             | Purpose                                                                                                                  |
| ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| `genie::spawn(future)`                               | Queue a remote `ComponentCallFuture`; activation is sent when this execution yields (optional callbacks)                 |
| `SpawnHandle::on_result` / `on_error` / `on_success` | Attach callbacks to a spawned call                                                                                       |
| `Self::context()`                                    | Caller identity (`from`) and executing component (`to`); use `*Self::context().from.entity_id()` for the caller's entity |
| `Component::get_owner()`                             | Owner of the current component, if any                                                                                   |
| `Component::is_same_entity(&component_id)`           | Whether another component is on the same entity                                                                          |
| `Component::ensure_same_contract(&component_id)`     | Verify another component belongs to the same contract                                                                    |

### Remote activation patterns

Remote calls from generated clients return a `ComponentCallFuture`. Three ways to run them:

#### Await

Wait for the result in the same method. The execution yields until the remote call completes.

```rust theme={null}
let client = ContractClient::new(target_component);

match client.holder.remote.transfer(amount, recipient).await {
    Ok(()) => { /* success */ }
    Err(err) => { /* handle error */ }
}
```

The calling method must be `async`.

#### Spawn

Queue the call with `genie::spawn` and continue local work. All queued spawns are sent as activations when execution yields.

```rust theme={null}
genie::spawn(client.holder.remote.transfer(amount, recipient));

self.balance = self.balance.checked_sub(amount).ok_or(/* ... */)?;

// All queued spawns are sent as activations to their destinations only when
// this function returns and execution yields.
Ok(())
```

#### Spawn with callbacks

Attach a `#[private]` handler. The runtime invokes it in a later activation when the call completes or fails.

```rust theme={null}
genie::spawn(client.holder.remote.transfer(amount, recipient))
    .on_error(Self::callbacks().on_transfer_error);

#[private]
pub async fn on_transfer_error(&mut self, err: GvmError) -> Result<()> {
    // handle failure
    Ok(())
}
```

Use `.on_success` or `.on_result` for other callback shapes.

## Component communication patterns

### Local versus remote calls

Generated clients expose `.local` and `.remote` routers on each component role.

```rust theme={null}
let client = ContractClient::new(target_component);

// Local (same entity): synchronous — no async
client.holder.local.balance()?;
client.holder.local.send_same_entity(recipient, amount)?;

// Remote (cross-entity): returns a ComponentCallFuture — await, spawn, or spawn with callbacks (see above)
client.holder.remote.send(recipient, amount).await?;
```

### Typed role references

Method parameters can use generated refs instead of raw `GvmComponentId`. Import from `super::self_refs`:

```rust theme={null}
use super::self_refs::Holder;

pub async fn mint(&mut self, dest: Holder, amount: AmountInSubunits) -> Result<()> {
    // The holder owns its balance; the issuer cannot mutate it directly.
    // Mint credits tokens by activating the destination holder's receive method.
    dest.remote.receive(amount).await?;
    Ok(())
}
```

When you have a `GvmComponentId` and need a typed ref (or the reverse), use `.try_into()?`.

### Calling root from a non-root component

Non-root components call root methods via `Self::root_client()`:

```rust theme={null}
Self::root_client()
    .remote
    .execute_swap_a_to_b(amount, self.holder_b)
    .await?;
```

### Error handling

Fallible component methods return `genie::Result<T>` (alias for `Result<T, GenieError>`). Returning `Err` reports failure to the caller; it does **not** revert storage already written in the same activation.

#### Validation

Use `ensure!` for early returns — with a message string or a typed error that implements `Into<GenieError>`.

```rust theme={null}
ensure!(amount > 0, "Amount must be greater than zero");
ensure!(self.is_open, ContractClosed);
```

#### Component errors

Define one error enum per component with `#[error_type]`. Return typed errors via `.into()`.

```rust theme={null}
use genie::{ensure, error_type, AmountInSubunits, Result};

#[error_type]
pub enum TokenError {
    #[error("Insufficient balance: {balance}, required: {required}")]
    InsufficientBalance { balance: AmountInSubunits, required: AmountInSubunits },
    #[error("Amount must be greater than zero")]
    ZeroAmount,
}

#[owner]
pub fn transfer(&mut self, amount: AmountInSubunits) -> Result<()> {
    ensure!(amount > AmountInSubunits::from(0u64), TokenError::ZeroAmount);

    self.balance = self
        .balance
        .checked_sub(amount)
        .ok_or(TokenError::InsufficientBalance {
            balance: self.balance,
            required: amount,
        })?;
    Ok(())
}
```

#### Rollback on failed remote calls

Remote calls can fail after local state has already changed. Update local state first, then revert manually if the remote leg fails:

```rust theme={null}
self.balance = self.balance.checked_sub(amount).ok_or(/* ... */)?;
if let Err(e) = to.remote.receive(amount).await {
    self.balance = self.balance.checked_add(amount).ok_or(/* ... */)?;
    return Err(e.into());
}
Ok(())
```

#### Cross-contract errors

Use `try_as()` to match a callee's typed error after a failed remote call.

```rust theme={null}
match client.holder.remote.transfer(amount, recipient).await {
    Ok(()) => Ok(()),
    Err(err) => {
        if let Some(HolderError::InsufficientBalance { .. }) = err.try_as() {
            Ok(()) // handle known callee error
        } else {
            Err(err.into())
        }
    }
}
```

## Cross-contract composition

A contract can take `GvmContract` handles to already-deployed contracts, install their components, and call them through generated clients.

### Two-token pool example

A pool that trades token A for token B needs **one holder per token contract** — two holders because there are two different tokens.

**Root** installs **pool holders** on its own entity at `#[deploy]` (the liquidity reserves):

```rust theme={null}
#[deploy]
pub async fn deploy(
    token_a_contract: GvmContract,
    token_b_contract: GvmContract,
) -> Result<Self> {
    let pool_holder_a = SimpleTokenClient::installer()
        .holder
        .install(token_a_contract)
        .await?;
    let pool_holder_b = SimpleTokenClient::installer()
        .holder
        .install(token_b_contract)
        .await?;
    Ok(Self {
        install_data: InstallData {
            pool_holder_a,
            pool_holder_b,
            token_a_contract,
            token_b_contract,
        },
        /* ... */
    })
}
```

**Client** installs **user holders** on the installing entity at `#[install]`. Root passes the token contracts and its pool holder IDs through `InstallData`:

```rust theme={null}
#[install]
pub async fn install(data: super::root::InstallData) -> Result<Self> {
    let holder_a = SimpleTokenClient::installer()
        .holder
        .install(data.token_a_contract)
        .await?;
    let holder_b = SimpleTokenClient::installer()
        .holder
        .install(data.token_b_contract)
        .await?;
    Ok(Self {
        holder_a,
        holder_b,
        pool_holder_a: data.pool_holder_a,
        pool_holder_b: data.pool_holder_b,
    })
}
```

**Calling the other contract** — on root, wrap a stored pool holder ID in a generated client:

```rust theme={null}
use demo_simple_token::simple_token::SimpleTokenClient;

fn pool_b(&self) -> SimpleTokenClient {
    SimpleTokenClient::new(self.install_data.pool_holder_b)
}

// Same entity: read the pool's token-B reserve (synchronous)
let balance = self.pool_b().holder.local.balance()?;

// Cross-entity: send output tokens to a user's holder
self.pool_b()
    .holder
    .remote
    .send(dest.try_into()?, output)
    .await?;
```

## Generated infrastructure

The `#[contract]` macro automatically generates:

1. **Contract client** — `{Contract}Client` with a router per component role (`.local`, `.remote`, `.callbacks`):
   ```rust theme={null}
   let client = SimpleCounterContractClient::new(component_id);

   client.controller.local.increment()?;
   client.controller.remote.increment().await?;
   ```
2. **Installers** — `{Contract}Installer` for installing non-root components:
   ```rust theme={null}
   let installer = SimpleCounterContractClient::installer();
   let controller_id = installer.controller.install(contract_id).await?;
   ```
3. **Components enum** — one variant per non-root role (for example `SimpleCounterContractComponents::Controller`). Passed to the root's `#[installation_request]` handler so it knows which component is being installed:
   ```rust theme={null}
   #[installation_request]
   pub async fn installation_request(
       &mut self,
       component_type: SimpleCounterContractComponents,
   ) -> Result<()> {
       match component_type {
           SimpleCounterContractComponents::Controller => Ok(()),
       }
   }
   ```
4. **Callback router** — typed refs for `#[private]` methods, wired via `Self::callbacks()` in spawn handlers:
   ```rust theme={null}
   genie::spawn(client.root.remote.increment())
       .on_error(Self::callbacks().on_increment_error);
   ```
5. **Role refs** — `super::self_refs::{Holder, Issuer, ...}` for type-safe same-contract method parameters.
6. **`Self::root_client()`** — on non-root components, call root methods without constructing a client manually:
   ```rust theme={null}
   Self::root_client().remote.some_root_method(args).await?;
   ```
