---
title: "Overview"
editUrl: true
head: []
template: "doc"
sidebar: {"order":1,"hidden":false,"attrs":{}}
pagefind: true
draft: false
---

The Arete Rust DSL (Domain Specific Language) is a declarative syntax for defining streaming data pipelines. Using procedural macros, you describe **what** data you want from Solana, not **how** to fetch it.

---

## Overview

Instead of writing complex ETL pipelines with manual account parsing and event handling, the DSL lets you define:

- **Entities** — Structured data objects that project on-chain state
- **Field Mappings** — How data flows from Solana accounts into your entities
- **Aggregations** — Computed metrics that update automatically
- **Resolvers** — External data (like token metadata) enriched automatically
- **Strategies** — How incoming data merges with existing state

The macros transform your Rust code into a JSON-based stack spec (`.stack.json`), which Arete compiles into optimized bytecode for real-time execution.

---

## The DSL in Practice

```rust
#[arete(idl = "my_program.json")]
pub mod my_stream {
    #[entity]
    pub struct Token {
        // Map account fields directly
        #[map(my_program_sdk::accounts::TokenAccount::balance, strategy = LastWrite)]
        pub balance: u64,

        // Aggregate events into metrics
        #[aggregate(from = my_program_sdk::instructions::Trade, field = amount, strategy = Sum)]
        pub total_volume: u64,

        // Derive computed values
        #[computed(balance * price)]
        pub tvl: u64,

        // Enrich with off-chain token metadata (name, symbol, decimals, logo)
        #[resolve(address = "So11111111111111111111111111111111111111112")]
        pub token_metadata: Option<TokenMetadata>,
    }
}
```

:::note
Field paths use the `{name}_sdk::accounts::` and `{name}_sdk::instructions::` prefix, where the name is derived from the IDL's program metadata. For example, an IDL named "my_program" generates `my_program_sdk::accounts::*` and `my_program_sdk::instructions::*`.
:::

---

## Key Concepts

### Module-Level

| Macro      | Purpose                                                                   |
| ---------- | ------------------------------------------------------------------------- |
| `#[arete]` | Entry point — defines the stream and links to data sources (IDL/Protobuf) |

### Entity-Level

| Macro       | Purpose                                              |
| ----------- | ---------------------------------------------------- |
| `#[entity]` | Marks a struct as a data projection                  |
| `#[view]`   | Defines queryable views (list, state) for the entity |

### Field-Level

| Macro                 | Purpose                                     |
| --------------------- | ------------------------------------------- |
| `#[map]`              | Maps fields from Solana account state       |
| `#[from_instruction]` | Extracts data from instruction arguments    |
| `#[aggregate]`        | Computes running values (Sum, Count, etc.)  |
| `#[event]`            | Captures instructions as structured events  |
| `#[snapshot]`         | Captures complete account state             |
| `#[computed]`         | Derives values from other entity fields     |
| `#[derive_from]`      | Populates from instruction metadata         |
| `#[resolve]`          | Fetches off-chain data via a named resolver |

### Resolvers

Resolvers are types that fetch external data server-side and deliver it as part of your entity. You attach them to fields using `#[resolve]`.

| Resolver        | Purpose                                                                                                                                                                                     |
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `TokenMetadata` | Fetches SPL token metadata (name, symbol, decimals, logo) for a mint address via the DAS API. Also exposes `ui_amount` and `raw_amount` helper methods for use in `#[computed]` transforms. |

For example, the ORE stack resolves token metadata for the ORE mint at a known address:

```rust
#[resolve(address = "oreoU2P8bN6jkk3jbaiVxYnG1dCXcYxwhwyK9jSybcp")]
pub ore_metadata: Option<TokenMetadata>,

// The resolved decimals can then be used in transforms:
#[map(ore_sdk::accounts::Round::motherlode, strategy = LastWrite,
      transform = ui_amount(ore_metadata.decimals))]
pub motherlode: Option<f64>,
```

See [Resolvers](./resolvers) for the full reference.

### Cross-Account Resolution

| Syntax                                | Purpose                                              |
| ------------------------------------- | ---------------------------------------------------- |
| `lookup_index(register_from = [...])` | Inline PDA resolution on `#[map]` fields (preferred) |
| `#[resolve_key]`                      | Advanced: custom primary key resolution              |
| `#[register_pda]`                     | Advanced: manual PDA mapping registration            |

---

## Population Strategies

When data arrives, **strategies** determine how it's merged with existing state:

| Strategy      | Behavior              | Example Use              |
| ------------- | --------------------- | ------------------------ |
| `LastWrite`   | Overwrite with latest | Current balances         |
| `SetOnce`     | Write only if empty   | IDs, creation timestamps |
| `Sum`         | Add to existing total | Volume, TVL              |
| `Count`       | Increment by 1        | Trade count              |
| `Append`      | Add to list           | Event history            |
| `Max` / `Min` | Keep extreme value    | Price highs/lows         |

---

## Next Steps

- **[Macro Reference](./macros)** — Complete documentation of every macro and its arguments
- **[Population Strategies](./strategies)** — Deep dive into update strategies and when to use each
- **[Resolvers](./resolvers)** — Enrich entities with token metadata and computed fields
