Skip to content

Creating Specs

Hyperstack uses a declarative Rust DSL (Domain Specific Language) to define how on-chain Solana data should be transformed, aggregated, and streamed to your application. Instead of writing complex ETL pipelines, you simply declare the final state you want, and Hyperstack handles the rest.


Building data pipelines for Solana typically involves manual account parsing, complex event handling, and managing state synchronization. Hyperstack replaces this imperative approach with a declarative model:

Imperative Approach (Traditional)Declarative Approach (Hyperstack)
Write custom decoding logic for every accountUse #[map] to link IDL fields to your state
Manually track and sum event valuesUse #[aggregate(strategy = Sum)]
Manage WebSocket connections and state diffsDefine entities and let Hyperstack stream updates
Build custom backend services for dataDeploy a spec and use generated SDKs

A Hyperstack spec is a Rust module annotated with #[hyperstack]. Inside this module, you define Entities—the structured data objects your application will consume.

use hyperstack_macros::{hyperstack, Stream};
#[hyperstack(idl = "path/to/idl.json")]
pub mod my_stream {
#[entity(name = "Token")]
#[derive(Stream)]
pub struct Token {
/// The primary key (mint address)
#[from_instruction(Create::mint, primary_key)]
pub mint: String,
/// Real-time reserves mapped from account state
#[map(BondingCurve::reserves)]
pub reserves: u64,
/// Total volume aggregated from individual trade events
#[aggregate(from = Trade, field = amount, strategy = Sum)]
pub total_volume: u64,
/// Computed field derived from existing fields
#[computed(reserves * price)]
pub tvl: u64,
}
}
  1. #[hyperstack] Module: The container for your specification. It links to your data sources (IDL or Protobuf files).
  2. #[entity] Struct: Defines a projection of on-chain data. Each entity represents a collection of related data that will be streamed as a single unit.
  3. Primary Key: Every entity must have a primary key (usually a Pubkey or String). This is how Hyperstack tracks individual instances of an entity.
  4. Field Mappings: Attributes on struct fields that define where the data comes from and how it’s processed.

Hyperstack provides several mapping attributes to populate your entity fields:

AttributeSourceDescription
#[map]Account StateTracks fields within a Solana account. Updates whenever the account changes.
#[from_instruction]InstructionsExtracts arguments or account keys from a specific instruction.
#[aggregate]Events/InstructionsComputes running values (Sum, Count, etc.) from a stream of events.
#[event]EventsCaptures specific instructions as a log of events within the entity.
#[snapshot]Account StateCaptures the entire state of an account at a specific point in time.
#[computed]Local FieldsDerives a new value by performing calculations on other fields in the same entity.
#[derive_from]InstructionsPopulates fields by deriving data from instruction context.

When data arrives, Strategies determine how the field value is updated. This is particularly powerful for aggregations.

StrategyBehavior
LastWrite(Default) Overwrites the field with the latest value.
SetOnceSets the value once and ignores subsequent updates (perfect for IDs).
SumAdds the incoming value to the existing total.
CountIncrements the total by 1 for every matching event.
AppendAdds the incoming value to a list (creating an event log).
Max / MinKeeps only the highest or lowest value seen.

When you build your Rust project containing a Hyperstack spec, the macros perform several steps:

  1. Validation: The macro verifies that your mappings match the provided IDL or Protobuf definitions.
  2. AST Generation: It generates a JSON-based Abstract Syntax Tree (AST) representing your data pipeline.
  3. Bytecode Compilation: When you deploy your spec (hyperstack up), Hyperstack Cloud compiles this AST into optimized bytecode.
  4. Execution: The Hyperstack VM executes this bytecode in real-time against the Solana transaction firehose, updating your entity state and streaming diffs to your clients.