# Index

### Introduction to Constellation Network

<table data-view="cards"><thead><tr><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th><th data-hidden data-card-cover data-type="files"></th></tr></thead><tbody><tr><td><strong>Introduction</strong></td><td>Learn what Constellation is and how it works.</td><td><a href="/spaces/pBDtrsB6CTph9ERYvdNO">/spaces/pBDtrsB6CTph9ERYvdNO</a></td><td><a href="/files/U080egKqG0fH4BeKeJVD">/files/U080egKqG0fH4BeKeJVD</a></td></tr><tr><td><strong>Network</strong> <strong>Fundamentals</strong></td><td>Core concepts, Architecture,  and Tokens</td><td><a href="/spaces/1OHICG0ktcwxiTcG2wHO">/spaces/1OHICG0ktcwxiTcG2wHO</a></td><td><a href="/files/78Vg2Hruy0W2ybopNm7y">/files/78Vg2Hruy0W2ybopNm7y</a></td></tr></tbody></table>

### For Developers

<table data-view="cards"><thead><tr><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th><th data-hidden data-card-cover data-type="files"></th></tr></thead><tbody><tr><td><strong>Metagraph Development</strong></td><td>Create and launch your own metagraph.</td><td><a href="/spaces/xrXzGdpjkF8q1pQcgabg">/spaces/xrXzGdpjkF8q1pQcgabg</a></td><td><a href="/files/BdxNUK1s36ghvvQ7l0Nu">/files/BdxNUK1s36ghvvQ7l0Nu</a></td></tr><tr><td><strong>Network APIs</strong></td><td>Use APIs to interact with the network</td><td><a href="/spaces/lzDyHxpeesNyOR3WIEd4">/spaces/lzDyHxpeesNyOR3WIEd4</a></td><td><a href="/files/Sgp0BweHkW5idBWptQI7">/files/Sgp0BweHkW5idBWptQI7</a></td></tr><tr><td><strong>Integrate Stargazer Wallet</strong></td><td>Add wallet support to your app.</td><td><a href="/spaces/AUvaNviXuvMQPGFFlTu0">/spaces/AUvaNviXuvMQPGFFlTu0</a></td><td><a href="/files/EA3TzioJZfMjEblnWEzJ">/files/EA3TzioJZfMjEblnWEzJ</a></td></tr></tbody></table>

### For Node Operators

<table data-view="cards"><thead><tr><th></th><th></th><th data-hidden data-card-cover data-type="files"></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>Run a node Validator</strong></td><td>Set up and manage a validator node.</td><td><a href="/files/EyUFuqD0omomMlK4cWYO">/files/EyUFuqD0omomMlK4cWYO</a></td><td><a href="/spaces/ZrtHSqcmP0ydsdSnYXRM">/spaces/ZrtHSqcmP0ydsdSnYXRM</a></td></tr><tr><td><strong>Setup Delegated Staking</strong></td><td>Setup your node to accept delegated staking requests from the $DAG community.</td><td><a href="/files/aRp7OhpIgjptyLUOEHIQ">/files/aRp7OhpIgjptyLUOEHIQ</a></td><td><a href="/spaces/ZrtHSqcmP0ydsdSnYXRM/pages/tXikAINIYVssYPQLgBKb">/spaces/ZrtHSqcmP0ydsdSnYXRM/pages/tXikAINIYVssYPQLgBKb</a></td></tr></tbody></table>


# Intro to Constellation Network

Constellation Network is a feeless, scalable blockchain ecosystem where projects can build their own custom blockchains (metagraphs). It has everything you’d expect from a blockchain—tokens, decentralized applications and wallets—but with a unique architecture that makes it faster, more efficient, and highly flexible.

## **How It Works**

* Any projects, company or even person can build on Constellation by creating their own metagraphs—custom blockchains tailored to their needs.
* Users interact with these projects using websites, decentralized applications, crypto wallets and tokens.
* The network itself does not impose fees to users, meaning each project can decide if any fees are charged to their users
* It’s flexible scalable and interoperable, metagraphs can be as simple a token or evolve to complex enterprise usecases, on Constellation there are virtually no limits for what can be built.

## **Core Components**

<figure><img src="/files/wRJbe4XjrdRUwZz2NoG3" alt="" width="563"><figcaption><p>Network architecture overview.<br></p></figcaption></figure>

To understand how Constellation works, here are the key building blocks of the network:

### **Metagraphs (Custom Blockchains)**

Metagraphs are independent blockchains built on Constellation. They can be simple (like a single token) or complex (powering enterprise applications). Each metagraph has full control over its rules, data, and fee structure.

### **Hypergraph (Global L0)**

The **Hypergraph** is the foundation of Constellation. It acts as a secure, scalable, and interoperable layer that connects all metagraphs, allowing them to communicate with each other and external blockchains.

### **DAG Token**

DAG is the native currency of Constellation Network. It powers the ecosystem by enabling:

* **Feeless peer-to-peer transactions**
* **Rewards for node validators** who secure the network
* **Collateral for running nodes**, ensuring network integrity
* **Interaction with decentralized applications (dApps)** and metagraphs

DAG is the backbone of Constellation, fueling both network operations and user interactions

### **Wallets & Applications**

Users can store and manage tokens, interact with metagraphs, and access decentralized applications through crypto wallets that support Constellation Network.

## **Why Constellation?**

* **No Gas Fees** – The network itself doesn’t charge fees; projects set their own rules.
* **Unlimited Scalability** – The system grows with demand, ensuring speed and efficiency.
* **True Flexibility** – From simple tokens to enterprise-grade applications, anything can be built.
* **Interoperability** – Projects on Constellation can seamlessly interact with each other and external blockchains.

## **Bringing It All Together**

Constellation Network is a feeless, scalable, and highly flexible blockchain ecosystem where anyone—from individual developers to enterprises—can build and interact with decentralized applications, custom blockchains (metagraphs), and digital assets.

With its unique architecture, interoperability, and limitless scalability, Constellation provides a powerful foundation for innovation. Whether you're looking to launch a token, build a complex application, or explore new blockchain use cases, Constellation gives you the tools to do it.

All the details about the network’s components, technology, and how to build on it are covered in detail  in the rest of this Documentation. Dive in to learn more! 🚀


# What is a metagraph?

Metagraphs: Custom Blockchains on Constellation

Blockchains are powerful, but they often force developers to play by someone else’s rules. What if you could build a blockchain designed specifically for your application, with its own logic, scalability, and data processing?

That’s exactly what metagraphs offer.

A metagraph is a custom, application-specific blockchain built on Constellation Network. Unlike traditional blockchains, where multiple projects share the same infrastructure, each metagraph operates independently. This gives developers full control over rules, data processing, and scalability—allowing them to create networks optimized for real-world applications.

Metagraphs function as decentralized backends, supporting a wide range of use cases, from AI training and data verification to decentralized identity and finance.

<figure><img src="/files/6Mp71gTPvAT8eldvKQPL" alt="" width="563"><figcaption></figcaption></figure>

## **How Metagraphs Differ from Traditional Blockchains**

Most blockchains rely on **smart contracts** for application functionality, but these come with limitations:

* **Rigid constraints** – Smart contracts must follow the rules of the blockchain they run on.
* **Reliance on third-party oracles** – They require external data sources to process real-world information.
* **Scalability bottlenecks** – High network usage impacts all applications equally.

Metagraphs remove these restrictions by offering:

* **Custom execution environments** – Developers define their own consensus, fee structure, and logic.
* **Native real-world data integration** – No need for external oracles to verify information.
* **Independent scalability** – Each metagraph runs on its own infrastructure, ensuring **consistent performance** without network congestion.

Instead of competing for resources on a shared blockchain, metagraphs act as tailored, decentralized networks built for real-world applications.

## **Metagraph Flexibility**

Metagraphs can be designed to fit the exact needs of a project, from small-scale applications to enterprise-grade solutions.

{% embed url="<https://www.youtube.com/watch?index=3&list=PL1iI5n3l2OKB8AaU3-LTnKaJVLU5QAZs3&v=W2T-W4kNKXs>" %}

### **Simple Metagraph (Small Project or Token)**

* 3+ validator nodes
* A single token for transactions
* Minimal computational needs
* Ideal for basic token economies and P2P transactions

### **Advanced Metagraph (Enterprise & Data-Heavy Use Cases)**

* Multiple validators for decentralization and scalability
* Custom processing pipelines for AI, finance, healthcare, or IoT
* Cross-chain interoperability for seamless metagraph and blockchain integration
* Ideal for data verification, decentralized AI, identity solutions, and large-scale apps

Metagraphs are not just for tokens—they can handle data tagging, trust scoring, predictive analytics, and more.

## **Metagraph Tokens & Customization**

Each metagraph can issue its own token, which powers transactions within its network, incentivizes validators to process and secure data, and assigns value to verified data streams. Since metagraphs have full control over their tokenomics, projects can customize how their token is distributed, used, and governed to fit their specific needs.

## **Why Build a Metagraph?**

Metagraphs unlock a new level of blockchain customization, allowing developers to create scalable, decentralized networks optimized for real-world applications. With a metagraph, developers can:

* Build a blockchain tailored to their exact needs without the limitations of a shared network.
* Process and verify real-world data natively, eliminating reliance on external oracles.
* Scale independently, avoiding congestion from other applications.
* Create new use cases beyond tokens and DeFi, enabling innovation in AI, supply chain, identity, and more.

Metagraphs provide the flexibility, efficiency, and control needed to bring groundbreaking blockchain applications to life.

<table data-card-size="large" data-view="cards" data-full-width="false"><thead><tr><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th><th data-hidden data-card-cover data-type="files"></th></tr></thead><tbody><tr><td><strong>Metagraph Architecture</strong></td><td>Learn more about how metagraphs work!</td><td><a href="/spaces/1OHICG0ktcwxiTcG2wHO/pages/FcQmCays53rnCb3jk50Z">/spaces/1OHICG0ktcwxiTcG2wHO/pages/FcQmCays53rnCb3jk50Z</a></td><td><a href="/files/6Mp71gTPvAT8eldvKQPL">/files/6Mp71gTPvAT8eldvKQPL</a></td></tr><tr><td><strong>Build a metagraph</strong></td><td>Build your own metagraph using the Euclid SDK</td><td><a href="/spaces/xrXzGdpjkF8q1pQcgabg/pages/Siygr6nKK9vuEvhGHaY2">/spaces/xrXzGdpjkF8q1pQcgabg/pages/Siygr6nKK9vuEvhGHaY2</a></td><td><a href="/files/wgkWMak9WZi44CnBojpc">/files/wgkWMak9WZi44CnBojpc</a></td></tr></tbody></table>


# What is DAG?

DAG is the native utility token of Constellation Network, serving as the foundation for its feeless, scalable, and decentralized ecosystem. Unlike traditional cryptocurrencies that act solely as a store of value or payment method, $DAG is designed to:

* **Secure the network** by incentivizing validators and delegators.
* **Power** [**metagraphs** ](/network-intro/what-is-a-metagraph)by covering snapshot fees for validation and storage.
* **Support ecosystem growth** through funding, development grants, and incentives.

As the economic engine of Constellation, $DAG ensures network security, sustainability, and long-term adoption.

***

### **How DAG is Used**

#### **Powering the Network – Snapshot Fees**

Transactions on the Constellation Hypergraph do not rely on traditional gas fees. Instead, metagraphs pay snapshot fees in $DAG to validate and store data, enabling a scalable and feeless user experience.

{% hint style="info" %}
Learn more about how snapshot fees work with our paper [Network Fees on the Hypergraph](/network-intro/white-papers/network-fees-on-the-hypergraph)
{% endhint %}

**Securing the Ecosystem – Validators & Delegators**

Validators stake 250,000 $DAG per node to participate in securing the network and processing transactions. Non-technical users can delegate their $DAG to validators, earning passive rewards while contributing to network decentralization.

#### **Driving Ecosystem Growth – Grants & Incentives**

$DAG fuels ecosystem expansion by funding developer grants, open-source tools, marketing initiatives, and community rewards. This ensures continued innovation and adoption of metagraphs.

#### **Enabling Trading & Liquidity – Exchanges & DeFi**

$DAG is actively traded on 15+ centralized and decentralized exchanges, including PacaSwap DEX, where it powers token swaps, liquidity pools, and DeFi applications within the Constellation ecosystem.

***

### **Sustainable Tokenomics: The Adaptive Supply Model**

<figure><img src="/files/jwuA06TI5ltZRRtK64Ql" alt="" width="563"><figcaption><p>Summary of DAG tokenomics</p></figcaption></figure>

Unlike fixed-supply blockchains that can struggle with long-term sustainability, Constellation follows a **flexible supply model (Metanomics)** designed to:

* Continuously reward validators and delegators.
* Fund ongoing network expansion and innovation.
* Maintain decentralization and economic stability.

#### **Balancing Inflation & Deflation**

To ensure a sustainable ecosystem:

* **New $DAG is minted** at a controlled rate to reward network participants.
* **Snapshot fees paid by metagraphs are burned**, gradually reducing inflation.

This dynamic supply model incentivizes participation while keeping the token economy balanced.

{% hint style="info" %}
Learn more about how snapshot fees work with our paper [Metanomics](/network-intro/white-papers/metanomics)
{% endhint %}

***

### **Feeless Transactions**

Most blockchains rely on gas fees, which can be costly and unpredictable. Constellation eliminates this issue by allowing:

* **Zero transaction fees for users.** Sending $DAG or interacting with metagraphs is completely feeless.
* **Custom fee structures for projects.** Metagraphs cover network costs, allowing developers to set their own pricing models.

This lowers barriers to entry for new users and businesses, making blockchain adoption more accessible and scalable.

***

### **How to Get Involved**

You can participate in the Constellation ecosystem today:

* **Delegate or run a validator node** – Help secure the network and earn rewards.
* **Hold, trade or use DAG** – Swap tokens, provide liquidity, and engage with DeFi applications.
* **Build with metagraphs** – Create scalable, decentralized applications using Constellation’s technology.


# Get started with DAG

## **Get Started with a Wallet**

* Download [**Stargazer Wallet**](https://constellationnetwork.io/stargazer-wallet/) to store, buy, swap and send DAG and other tokens.
* Supports iOS, Android and Chrome.

***

### **Get DAG**

* Buy from 15+ supported exchanges (e.g., KuCoin, Gate.io).
* Purchase directly in Stargazer Wallet with a credit card.
* Buy DAG on the BASE network.

{% hint style="info" %}
Find the best options to get DAG at <https://constellationnetwork.io/buy/>
{% endhint %}

***

### **Stake & Delegate for Rewards**

* Stake **250,000 DAG** to run a validator node.

{% content-ref url="/pages/xncztgEfgfZq9pSFvYXe" %}
[Node validators](/network-intro/node-validators)
{% endcontent-ref %}

* Delegate DAG to validators or metagraph nodes and earn DAG incentives at the [DAG Explorer](https://mainnet.dagexplorer.io/).

{% content-ref url="/pages/qecmlCSCqjKdWu6VsVcM" %}
[DAG Delegation](/network-intro/dag-delegation)
{% endcontent-ref %}

***

### **Trade & Swap**

* Trade on centralized exchanges or PacaSwap DEX (coming soon).
* Use DAG for liquidity pools and DeFi applications.


# DAG Delegation

Delegated staking on Constellation Network allows any DAG holder to participate in network security and validation by staking their tokens with validators—without needing to run a node. This enables more users to contribute to decentralization and governance while earning staking incentives.

By choosing a validator, you help secure the network, support metagraph projects, and receive DAG incentives for your participation. Some metagraph validators even offer additional L0 token rewards, increasing your potential incentives.

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th data-hidden data-card-cover data-type="files"></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td>Delegated Staking on DAG Explorer</td><td><a href="/files/HrJfYqzSlGfqJ2kOtYwR">/files/HrJfYqzSlGfqJ2kOtYwR</a></td><td><a href="https://mainnet.dagexplorer.io/staking">https://mainnet.dagexplorer.io/staking</a></td></tr></tbody></table>

## **Why Delegate Your DAG?**

<div data-full-width="true"><figure><img src="/files/ZvNAmh5WeXXwGrAef1AL" alt=""><figcaption></figcaption></figure></div>

* **Earn Network Incentives** – Receive a fixed 3% APR, plus a share of 45% of inflation emissions and potential extra rewards from metagraphs.
* **No Technical Setup Needed** – Stake without running a validator node.
* **Support Projects You Believe In** – Choose validators aligned with your interests or metagraphs that offer additional rewards.
* **Flexible & Transparent** – Easily switch validators, track performance, and adjust your strategy at any time.

### How Delegated Staking Works

1. Connect your Stargazer Wallet to the [DAG Explorer ](https://mainnet.dagexplorer.io/staking)
2. Choose from available validators based on fees, performance, or project alignment
3. Delegate your DAG tokens (no minimum requirement)
4. Monitor your delegations through the dashboard

{% embed url="<https://docs.constellationnetwork.io/network-intro/dag-delegation/getting-started>" %}

### Key Features

* **Transparent Fees:** Validators (the individuals or metagraphs you delegate too) charge between 5-10% of rewards
* **No Lock-up Period:** Change validators without waiting periods
* **21-Day Unwinding**: When fully withdrawing a delegation position there’s a 21-day unwinding phase. During this time, tokens are temporarily locked as the network processes the withdrawal, ensuring a smooth transition without sudden shifts in liquidity
* **Multiple Delegations –** You can open up to 10 delegated positions per wallet, each requiring a minimum of 5,000 DAG.

<br>


# Getting started

Getting Started with DAG Delegation

Delegating your DAG tokens allows you to earn rewards by supporting network validators without running a node yourself. Follow this step-by-step guide to begin delegating your DAG tokens on the Constellation Network.

***

### **Step 1: Prepare Your Wallet**

#### **1.1 Install a Compatible Wallet**

To delegate DAG, you need a compatible wallet that supports Constellation Network, such as Stargazer Wallet.

* If you don’t have Stargazer Wallet, [download and install it here](https://stargazerwallet.com/).
* Follow the instructions to set up a new wallet or import an existing one.

**1.2 Fund Your Wallet with DAG**

{% hint style="warning" %}
**If you're testing delegated staking on Integrationnet, make sure to:**

1. Open your Stargazer Wallet and switch the network to integrationne&#x74;**.**
2. Get some test DAG by using the integrationnet faucet:\
   <https://faucet.constellationnetwork.io/testnet/faucet/>**{your DAG wallet address}**

Just replace `{your DAG wallet address}` with your actual wallet address,&#x20;

3. Go to <https://integrationnet.dagexplorer.io/>

Once you’ve got some test DAG, you’re ready to stake and explore!
{% endhint %}

Ensure your wallet has enough DAG tokens for delegation.

* If you need DAG, check all the available options at  ["How to get DAG"](https://constellationnetwork.io/buy/).
* Confirm that your DAG balance appears correctly in your wallet.

***

### **Step 2: Access the DAG Explorer**

#### **2.1 Open DAG Explorer**

* Visit [DAG Explorer](https://mainnet.dagexplorer.io/) in your browser.
* Click on "[Delegated Staking](https://mainnet.dagexplorer.io/staking)" from the top menu.

<figure><img src="/files/mQTWHY99T7qvuVT975sC" alt="" width="375"><figcaption><p>DAG Explorer Landing Page</p></figcaption></figure>

#### **2.2 Connect Your Wallet**

* Click "Connect Wallet" at the top right corner.
* Select Stargazer Wallet and approve the connection.
* Your DAG balance and any previous delegations will now be visible.

***

### **Step 3: Choose a Validator**

#### **3.1 Browse Available Validators**

* Scroll through the list of validators.
* Use filters to find a validator by name, performance, or delegation fees.
* Click on a validator’s name to view details like total delegated DAG, commission rate, and validator description.

<figure><img src="/files/l2CDXjwxJz8CWKjtxsaQ" alt="" width="375"><figcaption><p>List of available validators</p></figcaption></figure>

#### **3.2 Select a Validator**

* Pick a validator that aligns with your preferences.
* Consider factors such as:
  * Validator Commission Rate (5%–10%) - This is the percentage the validator you selected will receive from your delegation rewards. Your initial delegated amount remains the same and is not affect by this comission&#x20;
  * Total Delegated DAG&#x20;
  * Metagraph (if delegating to a project validator)

***

### **Step 4: Delegate Your DAG**

#### **4.1 Initiate Delegation**

* Click the "Stake DAG" button on your chosen validator.
* A pop-up window will appear to enter your delegation amount.

<figure><img src="/files/A5zMLZrTJIIx4Ocu05Z1" alt="" width="375"><figcaption><p>Staking DAG to a Validator</p></figcaption></figure>

**4.2 Enter the Amount to Delegate**

* Type the amount of DAG you want to delegate.
* You can also use quick selection buttons (50%, Max) to allocate your DAG.
* Confirm that your available balance is sufficient.

#### **4.3 Confirm & Approve Transaction**

* Delegating DAG requires two transactions on the network
  * Lock DAG
  * Delegate to Validator
* Click "Lock DAG" to initiate delegation.
* Approve the transaction in your wallet.
* After the transaction is confirmed click "Delegate DAG"
* Wait for confirmation; your delegation will be recorded on the network.

<figure><img src="/files/Uoj31Sc7xS0BLAJBHyNF" alt="" width="375"><figcaption><p>Success modal for delegated staking</p></figcaption></figure>

Delegating DAG is a simple way to earn rewards and support the Constellation Network. By following this guide, you can securely delegate your DAG to any available node validator.\
\
Keep following this guide to learn how to monitor your rewards and manage your delegated positions efficiently!


# Managing delegated positions

You can easily track and manage your delegated DAG directly through the DAG Explorer. Here's how:

1. Go to <https://mainnet.dagexplorer.io/>
2. Connect your Stargazer Wallet.
3. Click your wallet address in the top-right corner.
4. Select **"My Delegations"** from the dropdown menu.

You’ll be taken to the My Delegations page, where you can view:

* Total DAG delegated
* Active delegation positions
* Unlocking (unstaking) positions
* Accrued rewards for each delegation position

This dashboard helps you stay informed about your staking activity and make informed decisions around delegated position management.

<figure><img src="/files/ZfzTLdRtfSx3B8IewE4t" alt="" width="375"><figcaption><p>Your delegated positions</p></figcaption></figure>


# Add DAG to a delegation

You can add more DAG to any active delegated position at any point in time. This will keep your accrued rewards and add to the total delegated.

**6.3 Stake more DAG to a validator**

* To stake more DAG on a validator:
  * Click "Stake DAG" next to your current delegation.
  * Choose  the ammount of DAG you want to add and confirm the transaction.
  * Your DAG will be added immediately to that postion, without any downtime.


# Withdraw/Unstake a delegation

If you decide to stop delegating or take a break from staking, you can initiate the unstaking process at any time. Unstaking begins a 21-day unbonding period, after which your staked DAG — along with any accrued rewards — is automatically returned to your wallet with no fees.

**1. Unstake DAG**

* Go to **"My Delegations"** in your wallet or staking dashboard.

<figure><img src="/files/LzBKKEpEYCgzTfD7wiUQ" alt="" width="563"><figcaption></figcaption></figure>

* Select the validator you wish to unstake from.
* Click **"Unstake"** and confirm the transaction.

<figure><img src="/files/gprrPZCjWsXMwnISxxqq" alt=""><figcaption></figcaption></figure>

**2. Unbonding period**

<figure><img src="/files/syJHkU2My0BJobIMfZRB" alt="" width="375"><figcaption></figcaption></figure>

* Once confirmed, your position enters a 21-day unbonding period.
* During this time, the tokens remain locked and cannot be used or restaked.

<figure><img src="/files/fwlrxBbe3S4YaB8shliK" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
**On integrationnet, for testing purposes, the unbonding period is 1 day only**
{% endhint %}

**3. Automatic return to wallet**

* After 21 days, your initial stake and any accrued rewards will be automatically returned to your wallet.
* There are no fees for unstaking or receiving your tokens.


# Change validators on a position

If you’re looking to switch to a different validator—whether for better performance, higher rewards, or to support a specific metagraph—you can do so instantly without having to unstake and wait 21 days. This feature lets you reallocate your stake in real time, ensuring your DAG remains active and continuously earning.

**1. Change validators instantly**

* Go to **"My delegations"** and find the validator you’re currently staking with.
* Click **"Change validator"** next to the active delegation under the actions column.

<figure><img src="/files/8dlyQpklHjseT1vUGItj" alt="" width="563"><figcaption></figcaption></figure>

**2. Select new validator**

* Browse the list of available validators.
* Choose your preferred validator and confirm the transaction.

<figure><img src="/files/qGUz72Wh4AMon9feww2U" alt="" width="375"><figcaption></figcaption></figure>

**3. Immediate reallocation**

* Your staked DAG is reallocated immediately, with no downtime or unbonding delay.
* Rewards continue to accumulate based on the new validator’s parameters.


# Delegation rewards

By participating in the network through delegation, you support validator operations and contribute to metagraph projects. In return, the protocol provides DAG-based incentives to encourage active participation.

### **How rewards are distributed**

* Incentives are automatically added to your delegated balance, increasing your stake over time.
* These incentives accumulate in your delegation position and are not directly claimable.
* To access your delegated tokens and the associated incentives, you must undelegate and wait for the 21-day unbonding period to complete.

{% hint style="warning" %}
**On integrationnet, for testing purposes, the unbonding period is 1 day only**
{% endhint %}

### **Incentive sources**

Delegators receive incentives through the following components:

1. **Fixed incentive rate (3% annualized)**
   * All delegated DAG receives a consistent 3% annual incentive, providing a stable baseline for participation.
2. **Variable emissions (45% of protocol-level emissions)**
   * 45% of all newly minted tokens are allocated to delegators.
   * This share adjusts based on the overall network delegation rate, offering greater incentives when less than 60% of the total DAG supply is delegated
3. **Validator commission**
   * Validators  apply a commission fee to the total incentives earned by their delegators.
   * This commission supports validator operations and is deducted before rewards are distributed to delegators.
   * The commission rate varies by validator and is displayed when choosing where to delegate.


# How validators & metagraphs attract delegators

Validators play a critical role in securing the Constellation Network and processing transactions. While some validators operate as part of metagraphs, individual node validators can also attract delegators and grow their stake by offering incentives, transparency, and reliability.

For those looking to run a single validator node or form a small group of validators, there are several strategies to attract delegation and maximize participation.

{% hint style="success" %}
If you are running a node validator learn more on how to set your node up for delegated staking at:\
\
<https://docs.constellationnetwork.io/run-a-node/delegated-staking>
{% endhint %}

## **Single Node Validators**

As a single validator, your goal is to build trust, demonstrate reliability, and offer incentives to attract DAG delegators. Here’s how:

### **Set Competitive Fees**

* Validators charge a 5-10% fee on delegator incentives.
* Lower fees can attract more delegators, while higher fees may allow for additional rewards.

### **Demonstrate Reliability**

* Validators with high uptime and consistent performance are more likely to attract delegators.

### **Maintain Transparency**

* Share performance metrics, validator status, and updates with the community.
* Keep an open communication channel through social platforms and forums.

### **Engage with the Community**

* Active participation in Telegram, Twitter, and community discussions builds credibility.
* Validators who engage with the DAG ecosystem often gain more delegation support.

### **Offer Incentive Programs**

Validators can differentiate themselves by providing extra incentives:

* **Loyalty Bonuses** – Additional rewards for long-term delegators.
* **Referral Programs** – Encourage new delegators with incentives for both parties.
* **Bonus Periods** – Temporary boosts in rewards to attract new delegations.
* **Milestone Rewards** – Additional incentives for delegators who stake for a set duration.
* **Network Growth Rewards** – Validators increase rewards as the overall delegation network expands.

## **Validator Tribes: The First Step to a Metagraph**

A Validator Tribe is a small group of trusted nodes (3+ validators) that work together as an early-stage metagraph. While most metagraphs are built for specific applications, a Validator Tribe may initially exist just to validate transactions without additional on-chain functionality.

### **Forming a Validator Tribe**

1️- Three or more validators come together to create a metagraph.\
2️- The metagraph can issue a native L0 token (optional) to reward delegators.\
3️- Validators within the metagraph coordinate how to attract delegators and distribute incentives.

### **DAG Holders Creating a Metagraph**

DAG holders can launch a Validator Tribe metagraph by securing three node slots on the mainnet.

* This provides an early entry point into metagraph validation.
* Participants can issue a metagraph token to reward delegators and expand their staking network.

## **Metagraphs**

Validators operating within a metagraph have additional ways to attract and reward delegators:

### **Exclusive Features & Services**

* Some metagraphs offer governance rights, premium features, or exclusive access to delegators.

### **Additional Token Rewards**

* Metagraphs can distribute native L0 tokens to delegators, enhancing total incentives.

### **Redistribution of Delegation Fees**

* A portion of delegation fees can be shared with delegators, increasing returns.

### **Using Fees for DEX Liquidity**

* Metagraphs can commit delegation fees to liquidity pools on PacaSwap DEX, benefiting both traders and stakers.
* More liquidity = reduced slippage, making it easier to trade tokens.
* Metagraphs can earn a share of DEX transaction fees, which can be redistributed to delegators.

🚀 Explore validator opportunities and grow your delegation network today!


# FAQ

Frequently Asked Questions

#### **Q1: How long does it take to start earning rewards?**

Rewards start accruing immediately after delegation and are automatically compounded into your delegated position.

#### **Q2: Can I delegate to multiple validators?**

Yes! You can split your DAG across different validators to diversify your staking positions.

#### **Q3: What happens if the validator goes offline?**

If a validator experiences downtime, you still receive your rewards.&#x20;

#### **Q4: Is there a minimum amount of DAG required to delegate?**

There is a minimum requirement of 5,000.0000.00 DAG to create a delegated position.

#### **Q5: Can I change validators without unstaking?**

Yes! The “Change Validator” feature allows you to reallocate your delegation instantly without waiting for the 21-day unbonding period.

#### **Q6: What is the unbonding period when unstaking DAG?**

Once you unstake, your DAG enters a 21-day unbonding period. After that, the full amount and its accrued incentives return to your wallet automatically, with no fees.

#### **Q7: Are there any fees for staking or unstaking?**

The protocol does not charge staking or unstaking fees. However, validators may apply a commission on the incentives they distribute.

#### **Q8: What is validator commission?**

Validators apply a commission to the incentives earned by their delegators. This supports their operational costs. The commission rate is displayed when you choose a validator.

#### **Q9:Can I add more DAG to an existing stake?**

No. Currently adding more DAG to an existing position is not possible. You can work around this by using a different wallet and delegating to the same validator.

#### **Q10: Where can I monitor my delegated positions?**

Visit [mainnet.dagexplorer.io](https://mainnet.dagexplorer.io), connect your Stargazer wallet, and click your address to access the "My Delegations" dashboard.

#### **Q11: What are fixed vs. variable incentives?**

Fixed incentives provide a stable 3% annualized rate on delegated DAG. Variable incentives come from 45% of protocol emissions.

#### **Q12: Why should I delegate my DAG instead of just holding it?**

Delegating supports network metagraphs and validators. Non-delegated DAG does not participate in incentive distribution, which may result in relative dilution over time.

#### **Q13: How do validator incentives align with network growth?**

The system is designed to balance rewards based on participation. When total DAG delegated is below 60% of total DAG supply, incentives increase to encourage more engagement.

#### **Q14: Can validators offer additional incentives beyond protocol rewards?**

Yes. Validators and metagraphs can create custom incentive programs such as loyalty bonuses, referral campaigns, and token airdrops tied to their delegated communities.

#### **Q15: How many delegated positions can I have?**

Currently each wallet address can have a maximum of 10 delegated positions. To work around this you can always use a new wallet to create extra delegated positions.

**Q16: Are rewards being compounded into my delegated position?**

Yes! Rewards autocompound in your delegated position, meaning the more rewards you accrue the bigger the compound effect!

**Q17: Can I create a delegation position on mobile?**

For now staking is only available on DAG Explorer using your desktop. Mobile support will be added later.


# Node validators

Node validators are the backbone of Constellation Network. They run the infrastructure that processes transactions, secures the network, and validates data, ensuring that Constellation remains scalable, decentralized, and trustless.

Validators don’t mine blocks like in traditional blockchains. Instead, they reach agreement (consensus) on the network’s state by validating snapshots—bundles of transactions and data—before storing them on the Hypergraph.

In return for their work, validators earn DAG rewards based on their contributions to the network.

## **What Do Node Validators Do?**

### **Process Transactions & Secure the Network**

Validators ensure that all transactions and data submitted to the network are valid and trustworthy before they are permanently recorded.

### **Earn Rewards in DAG**

<div data-full-width="true"><figure><img src="/files/ij9sCNLRjb9lwPqeHmhD" alt=""><figcaption></figcaption></figure></div>

Validators are compensated in DAG for their role in securing the network and processing transactions. Rewards are distributed from network emissions and in the future from metagraph fees.

Validators can also get extra rewards through delegation fees from delegated DAG to their node.

{% hint style="info" %}
Learn more about how validators can earn more DAG through [Delegating Staking](#delegators-and-validators-how-they-work-together).
{% endhint %}

## **Types of Validators in Constellation Network**

Validators operate at different levels, depending on their role in the ecosystem:

| **Validator Type**         | **Role**                                                                      |
| -------------------------- | ----------------------------------------------------------------------------- |
| **Global L0 Validator**    | Secures the Hypergraph, processes snapshots, and maintains network consensus. |
| **Metagraph L0 Validator** | Validates and submits metagraph-specific snapshots to the Global L0.          |
| **Metagraph L1 Validator** | Processes transactions and data within a specific metagraph.                  |

A single node can participate in multiple layers, earning rewards from both the Global L0 and individual metagraphs.

## **Delegators & Validators: How They Work Together**

Not everyone needs to run their own validator to participate!

Users who hold DAG can delegate their tokens to a validator to:

* Support network security.
* Earn incentives.
* Help determine which validators receive more network emissions.

Validators, in turn, earn a percentage of the rewards from their delegators, creating an incentive for them to operate efficiently and attract delegations.

## **Why Become a Validator?**

* Earn DAG.
* Play a key role in securing a decentralized network.
* Support metagraphs and innovation on Constellation.

Whether you want to run your own node or delegate your DAG, validators are critical to the success of Constellation Network.


# White Papers


# The HGTP Economy

Implementing Generative Tokenomics in the Hypergraph for Validator Nodes and Metagraphs at Scale

### Introduction[​](https://docs.constellationnetwork.io/learn/tools-resources/tokenomics-litepaper#introduction) <a href="#introduction" id="introduction"></a>

This document is a high-level overview and framing of Constellation’s Hypergraph Network (HGTP): A decentralized network economy where consensus is run on the Global L0 (Hypergraph) and L1 Metagraphs (previously referred to as “state channels”). The intention of this paper is to educate individuals on the fundamentals of HGTP with an explanation of the metrics used across the Hypergraph network to yield an incentivization structure for key stakeholders in the economy: Validator Nodes and Metagraphs. Additionally, the aim of this overview is for individuals and businesses to gain a better understanding of how to navigate the Constellation Ecosystem with the goal of attracting them to join one or both of these stakeholder groups.

The Hypergraph’s current economic model is a fixed incentivization token emission schedule, denominated in the Hypergraph’s native currency DAG, rewarded to node operators for securing and maintaining the decentralized infrastructure. In 2018, this model was established, along with zero transaction fees, as a placeholder to promote adoption of our mission while creating a low barrier to entry.

The intention is that less complex transactions, like sending/receiving DAG and one-off snapshots sent by Metagraphs (subnetworks built on top of the Hypergraph), would remain feeless. Since the validation of these types of transactions would never clog our network, these use cases should not be limited, even if there is immediate value exchange between users and node operators of the Hypergraph. However, if the frequency of low-complexity transactions becomes too large, a fee will be instituted to prevent spamming or DDoS-type attacks on the network. Fees incentivize security and proper up-time for a network, but these costs still need to be manageable for Metagraph businesses. Keeping a healthy balance will be a primary focus as the team continues iterating to measure the network fees for a more complete tokenomics model for the Hypergraph.

This overview will cover how the Hypergraph Economy operates with Metagraphs, using the network for validation services, and the fundamental baseline formula measuring scalable economics around the DAG and Metagraph networks.

### Hypergraph[​](https://docs.constellationnetwork.io/learn/tools-resources/tokenomics-litepaper#hypergraph) <a href="#hypergraph" id="hypergraph"></a>

Hypergraph Transfer Protocol (HGTP) is the decentralized network developed by Constellation Network, Inc. and governed by the community. HGTP consists of the Hypergraph, a global layer zero network with Validator Nodes that maintains and secures the network, orchestrated by the Proof of Reputable Observations (PRO) consensus mechanism, and Metagraphs, or subnetworks that make up HGTP, that include networks, applications, and businesses.

HGTP is a decentralized protocol composed of multiple independent networks, known as Metagraphs. Each Metagraph is flexible and customizable to validate and process data according to its user-defined business logic. Furthermore, each Metagraph leverages custom consensus mechanisms to validate data before submitting its “state” as snapshots to the Hypergraph. The Hypergraph performs final validation and then adds the Metagraph snapshot to the ledger. This approach is how microservice state isolation is used in traditional digital and web2 environments where microservices cross-communicate with one another. Metagraphs are like traditional microservice development environments where the state of data is managed by exclusive logical service boundaries. By cryptographically securing any data type in its entirety, our vision is to make web3 tooling composable with the digital world of web2.

<figure><img src="/files/lb6QPQhnDCVOFrB8cmeP" alt="" width="563"><figcaption></figcaption></figure>

**Figure 1.** HGTP architecture overview.<br>

This structure enables multiple states of data to exist, some with custom consensus, others leveraging global consensus, and other Metagraphs doing the validation themselves. Furthermore, with custom consensus, companies can deploy their own blockchain that orchestrates Validator Nodes to validate custom logic and the state of data while being able to create dependencies and incentives for validating a transaction. Individuals and entities will come to rely on the Hypergraph for the speed of validating data in realtime, assigning an incentive to the validator for validating under their customized consensus, and the security of knowing that the data was not tampered with.

This paper will break down how to measure network fees to further align stakeholders, validator nodes, and Metagraphs for the scalability of our ecosystem. Using metrics like the number of “workAmount” a transaction requires, how many resources are available to process a transaction, the frequency of transactions being sent, latency, staked DAG, and peer validation weight will be used to determine DAG fees. DAG fees will align both users of the Hypergraph Network: Validator Nodes and Metagraphs.

### Validator Nodes[​](https://docs.constellationnetwork.io/learn/tools-resources/tokenomics-litepaper#validator-nodes) <a href="#validator-nodes" id="validator-nodes"></a>

Validator Nodes are the backbone of the Hypergraph’s decentralized network as they provide the resources to validate and confirm transactions. The Proof of Reputable Observation (PRO) consensus mechanism organizes the Validator Node operators and secures the network. This combination of a healthy network of nodes and PRO Consensus provide security, throughput, and uptime for application developers.

Validator Nodes will have limited resources tied to their node and can choose to support the Global L0 and one or more Metagraph Networks based on computing resources.

<figure><img src="/files/S76Dg7slq4ZtX1xeA1mq" alt=""><figcaption></figcaption></figure>

**Figure 2:** Metagraph L1 does the initial validation and bundles the transaction into blocks. The blocks are sent to the Metagraph L0 layer to be bundled into Metagraph snapshots to the Global L0. All metagraphs must have an L0 layer composed of 1 or more nodes (almost always more). Those L0 metagraph nodes must be hybrid nodes that are running both the Global L0 process and the Metagraph L0 process on the same node/server.

### Metagraphs[​](https://docs.constellationnetwork.io/learn/tools-resources/tokenomics-litepaper#metagraphs) <a href="#metagraphs" id="metagraphs"></a>

Metagraph L0 nodes, which are responsible for submitting snapshots to the Global L0, must all be run as hybrid nodes, supporting both Global L0 and their Metagraph L0 processes on the same node. Thus, Metagraphs can recruit from the existing pool of Global L0 validators to run their Metagraph processes, or recruit new ones. Since Metagraph networks with greater total staked DAG within their L0 network pay lower snapshot fees, they are incentivized to set DAG staking requirements as a prerequisite to joining their network. It is conceivable that DAG staking incentivized by Metagraph networks would allow for a reduction in Global L0 collateral requirements while maintaining high levels of locked value on the network. This opens the network for node participation with less than 250k DAG collateral requirement.

Beyond attracting Hypergraph validators with staked DAG, Metagraphs must incentivize participation in their own networks. Validator Node operators will choose which Metagraph processes to run with their node’s limited resources. Metagraphs with more attractive rewards for validators relative to their resource requirements will draw the most nodes to their network. Ultimately, Metagraphs will compete with each other to offer the greatest incentives to recruit the nodes needed to support their network or application.

Our goal is to make Metagraph deployment cost-competitive with web2 legacy services, while creating further utility demand around the DAG token. Furthermore, enabling Metagraphs to incentivize Validator Nodes to stake additional DAG to their network use case, further increases the potential for total value locked (TVL) on the network. These are the following ways that Metagraphs can leverage the Hypergraph:

#### Snapshot to Hypergraph[​](https://docs.constellationnetwork.io/learn/tools-resources/tokenomics-litepaper#snapshot-to-hypergraph) <a href="#snapshot-to-hypergraph" id="snapshot-to-hypergraph"></a>

All Metagraphs will send snapshots to the Hypergraph, which include associated fees. Each snapshot is capable of containing many individual transactions. Currently, snapshots sent to the Hypergraph are capped at 50kb; these snapshots can include Metagraph Token transactions and other raw data points. Metagraphs may choose to pass the incurred snapshot fees to their users within their own tokenomics (like a gas fee to use their Metagraphs network) or to pay them through other means. As mentioned earlier, other factors, such as the computational power needed to validate the transaction and attached priority fees, will determine the total cost.

<figure><img src="/files/sadrKe1YXWt3yRXxknPx" alt=""><figcaption></figcaption></figure>

**Figure 3:** Lifecycle of a Metagraph token transaction from creation to finality.

#### Deflationary Effects[​](https://docs.constellationnetwork.io/learn/tools-resources/tokenomics-litepaper#deflationary-effects) <a href="#deflationary-effects" id="deflationary-effects"></a>

Metagraphs pay fees for data validated on the Hypergraph, which could create a deflationary effect on the ecosystem. Because these fees are irrecoverable, if incurred fees are greater than or equal to any value distributed to Validator Nodes, the ecosystem will experience a balanced (or even deflationary) token economy.

#### Metagraph Tokens[​](https://docs.constellationnetwork.io/learn/tools-resources/tokenomics-litepaper#metagraph-tokens) <a href="#metagraph-tokens" id="metagraph-tokens"></a>

It is equally important to point out that Metagraphs can issue their own Metagraph tokens as rewards for Validator Nodes that support their network. The majority of excess node rewards can be generated by these Metagraph tokens while maintaining DAG emissions to provide security and maintain the global state.

### Metagraph: Network Fees[​](https://docs.constellationnetwork.io/learn/tools-resources/tokenomics-litepaper#metagraph-network-fees) <a href="#metagraph-network-fees" id="metagraph-network-fees"></a>

In order to use the Hypergraph, Metagraphs must contribute fees to the network for each snapshot of state submitted. Metagraphs have the option of passing these fees on to their users or not, giving them the flexibility to organize their networks to meet the needs of diverse use cases. Snapshot fees are submitted to the Hypergraph in DAG, and these fees are irrecoverable. This mechanism could create a deflationary pressure on the network that will counteract rewards distributions to Validator Nodes. The first Metagraphs launching at the end of the Hercules era and the beginning of the Gemini era will pay no fees to the network and be limited to a snapshot size of 50kb or less. In this early stage, Metagraph snapshots without fees will trigger on-demand global snapshots, allowing high throughput for Metagraph data.

During the Gemini era, a snapshot prioritization function will be released that will introduce a fee mechanism for Metagraphs on the network. Snapshots without fees will still be accepted but they will be limited to one Metagraph snapshot per global snapshot. Feeless snapshots will not trigger on-demand consensus once the prioritization function is released which will effectively rate limit free snapshots to a rate of one every few seconds. Snapshots with fees will be processed on-demand and will allow for significantly higher snapshot throughput.

Fees will be calculated based on the amount of work required by the network to validate the data contained in each snapshot. The work amount is then adjusted with a multiplier that takes into account two additional metrics: staked DAG on the metagraph and PRO score. The multiplier discounts fees for Metagraphs also provide valuable attributes to the network outside of fees, such as incentivizing users to stake DAG in order to create a stable and secure network measured through PRO score.

**The following formula will be used to determine the required fees:**

**Please note:**

As features roll out there will be a need to adjust the weights to ensure optimization.

```
workAmount = byteSize x computationalCost
```

Copy

```
multiplier = 1 / (stakedDAG x stakingWeight) + (averageProScore x proWeight)
```

Copy

```
fee = (baseFee * workAmount * workMultiplier) + optionalTip
```

Copy

The fee structure outlined above and the 50kb snapshot size limitation will increase with the rollout of future development releases in future eras, allowing for more complex data types validated by the Hypergraph, and additional value for Validator Nodes.

Below are the description of the inputs (outside of the limitless potential inputs of PRO score):

#### Work Amount[​](https://docs.constellationnetwork.io/learn/tools-resources/tokenomics-litepaper#work-amount) <a href="#work-amount" id="work-amount"></a>

Work amount is a measure of the amount of work the Hypergraph must perform to validate a transaction. This is composed of the byteSize which is the size of the data being validated, and computationalCost which is the time and resources required to run the validation function. The combination of these two factors estimates the actual effort required of the network to validate a transaction.

#### Computational Cost[​](https://docs.constellationnetwork.io/learn/tools-resources/tokenomics-litepaper#computational-cost) <a href="#computational-cost" id="computational-cost"></a>

This is the time and effort it takes to run the validation function. Computational cost will be the combined measure of time and memory (RAM) resources required to run a validation function for a given transaction. A validation function that takes 100ms and 1GB of RAM is less costly to the network than a function that takes 2s and 8GB of RAM. This measures that time and resource cost. A simple transaction, like sending DAG to a peer, does not take as much time or resources compared to something complex like a cross-chain swap or Metagraph-to-Metagraph transaction (which may include multiple variables and Metagraphs deciphering different data types).

#### Multiplier[​](https://docs.constellationnetwork.io/learn/tools-resources/tokenomics-litepaper#multiplier) <a href="#multiplier" id="multiplier"></a>

The multiplier functions to calibrate the transaction cost of a Metagraph in relation to its valuable contributions to the overarching Hypergraph. This adjustment takes into account two primary factors:

1. **stakedDAG:** The total amount of staked DAG within the Metagraph, which represents locked value helping create a stable and secure network.
2. **averagePROScore:** The mean PRO score of the Validator Nodes present in the Metagraph, which is indicative of the trust and security of the network.

By incentivizing a higher PRO score, the multiplier aims to enhance the overall trustworthiness and security of the Hypergraph.

#### Staked DAG[​](https://docs.constellationnetwork.io/learn/tools-resources/tokenomics-litepaper#staked-dag) <a href="#staked-dag" id="staked-dag"></a>

Staked DAG will be defined as the combined DAG staked by all nodes that sign a given metagraph snapshot. That could result in variable fees depending on the signers but fees could be controlled by metagraph networks enforcing DAG staking requirements on their networks. Metagraphs will need to set minimum DAG staked amounts to prevent their fees from varying too much.

#### Base Fees and Optional Tip[​](https://docs.constellationnetwork.io/learn/tools-resources/tokenomics-litepaper#base-fees-and-optional-tip) <a href="#base-fees-and-optional-tip" id="base-fees-and-optional-tip"></a>

The base fee is a constant that adjusts the overall cost of fees on the network. It is not a dynamic value but could be changed over time to optimize the overall fees burned by the network.

To enhance snapshot prioritization beyond the mandatory validation fees, an optional tip value can be appended to the snapshot fees. This additional value augments the snapshot’s priority compared to those without a tip. Tips prove advantageous in congested networks, facilitating prompt processing for Metagraphs that require swifter finality times, ensuring their snapshots receive precedence over others in the network.

### Summary[​](https://docs.constellationnetwork.io/learn/tools-resources/tokenomics-litepaper#summary) <a href="#summary" id="summary"></a>

HGTP is an evolution of blockchain technology that brings the immutability and transparency of Web3 technology into Web2 digital infrastructure. The goal of this litepaper is to gain a better understanding of the fundamentals of our economics and the key stakeholders of the Hypergraph. With Metagraphs, businesses and individuals can leverage the Hypergraph, the Euclid SDK, and Validator Nodes to bridge conventional business logic with Web3 incentives and immutability.

HGTP will provide the infrastructure to build Metagraphs while creating an economy that keeps peer-to-peer transactions feeless while including proper incentives to attract both Validator Nodes and Metagraphs. Beyond peer-to-peer transaction fees, we can begin to calculate fees on our network by looking at these parameters: workAmount, computational cost, multipliers, stakedDAG, and tips/base fees. Using these metrics, we can create a calculator to predict the cost of deploying a Metagraph and the cost associated with sending snapshots.

Metagraphs will be required to create incentives for their own network while also placing DAG staking and resource requirements to attract Validator Nodes. It is conceivable that in a future release, variable rewards could be emitted based on the workload, thus reducing (or increasing) staking requirements to the network. As PRO scoring is released, new inputs will be added in the Network Fees calculator which will further incentivize active node management and network participation. This paves the way for the Hypergraph to usher in more use cases into the web3 industry at large.

For Metagraphs, entities can create their own network with tokenomics that correlate real-time data validation from existing legacy technology with Metagraph tokens. By having baseline network fees and requirements, and flexible development environments for Metagraphs, Metagraphs can build networks and incentivization structures that meet their industry’s needs while simultaneously connecting commerce to create data-driven insights that correlate to needs in the real world (vs. solely creating a web3 business that doesn’t impact the gross national product). The outcome of this design approach provides composable web3 technology with web2 infrastructure and economics enabling applications to drive exponential adoption of products and services outside of the web3 market.

### Glossary[​](https://docs.constellationnetwork.io/learn/tools-resources/tokenomics-litepaper#glossary) <a href="#glossary" id="glossary"></a>

#### Proof of Reputable Observation (PRO)[​](https://docs.constellationnetwork.io/learn/tools-resources/tokenomics-litepaper#proof-of-reputable-observation-pro) <a href="#proof-of-reputable-observation-pro" id="proof-of-reputable-observation-pro"></a>

Hypergraph’s unique consensus algorithm that enables more flexible application development, high transaction speeds, and throughput capacity by measuring each node’s reputation. A node's reputation or PRO Score can be based on a combination of factors like past performance, DAG staked, up-time, etc.

#### byteSize[​](https://docs.constellationnetwork.io/learn/tools-resources/tokenomics-litepaper#bytesize) <a href="#bytesize" id="bytesize"></a>

The size of the code that's being run to validate the transaction/data type.

#### computationalCost[​](https://docs.constellationnetwork.io/learn/tools-resources/tokenomics-litepaper#computationalcost) <a href="#computationalcost" id="computationalcost"></a>

This is the time and effort it takes to run the validation function. You can imagine that a validation function that takes 100ms and 1GB of RAM is less costly to the network than a function that takes 2s and 8GB of RAM. This measures that time/resource cost.

#### workAmount[​](https://docs.constellationnetwork.io/learn/tools-resources/tokenomics-litepaper#workamount) <a href="#workamount" id="workamount"></a>

The size of the code being run and the amount of time/effort it takes to run combined. This is the actual amount of work the network is doing to validate the data.

#### unitMultiplier[​](https://docs.constellationnetwork.io/learn/tools-resources/tokenomics-litepaper#unitmultiplier) <a href="#unitmultiplier" id="unitmultiplier"></a>

This adjusts the cost of the work up or down depending on the metagraph's other contributions to the network (staked DAG and trust/stability score-PRO). Higher staked DAG + PRO score results in a lower multiplier which means that fees are cheaper for the same amount of work performed.

#### stakedDAG[​](https://docs.constellationnetwork.io/learn/tools-resources/tokenomics-litepaper#stakeddag) <a href="#stakeddag" id="stakeddag"></a>

Defined as the combined DAG associated with all nodes that sign a given state channel snapshot. That could result in variable fees depending on the signers but fees could be controlled by metagraph networks enforcing DAG staking requirements on their networks. Metagraphs will need to set minimum DAG staked amounts to prevent their fees from varying too much.

#### baseFee[​](https://docs.constellationnetwork.io/learn/tools-resources/tokenomics-litepaper#basefee) <a href="#basefee" id="basefee"></a>

We need some DAG value in the equation to make the result a DAG price. This could be 1 datum or higher depending on what we want the final fee to come out to. This is not meant to be a dynamic value but a constant that we set when we implement this.

#### optionalTip[​](https://docs.constellationnetwork.io/learn/tools-resources/tokenomics-litepaper#optionaltip) <a href="#optionaltip" id="optionaltip"></a>

This is the same thing as the priority fee or the DAG fee that we currently have. Snapshots with a tip have higher priority over snapshots without a tip.


# Network Fees on the Hypergraph

A Generative Approach to the Implementation of Fees for Scalability and Security

### Introduction[​](https://docs.constellationnetwork.io/learn/tools-resources/network-fees-litepaper#introduction) <a href="#introduction" id="introduction"></a>

This document seeks to further the discussion on Constellation Network's economic model by introducing specific metrics and frameworks for the implementation of fees within the network. It draws connections between the network's commitment to free peer-to-peer transactions and the broader trend towards "pay as you go" systems in cloud computing. Furthermore, it explores the tokenomics of the network in relation to these fees, presenting a revitalized vision for leveraging Constellation Network's unique incentive and reward mechanisms to cultivate self-sustaining, generative economies.

We introduce a framework for snapshot fees that is integral to the economic model, underpinning the network's ability to incentivize positive activity, support scalability at various stages, and ensure network security. This framework involves a strategic introduction of fees to benefit the entire network, motivate positive activities, and bolster the network's capacity to scale.

By introducing fees in a way that stimulates efficient network utilization, fortifies against potential security threats, and generates a utility marketplace, this paper discusses the creation of a robust platform that encourages innovation without sacrificing security or scalability. In the following sections, we present a comprehensive approach to maintaining a vibrant ecosystem that benefits all stakeholders—underscoring our commitment to accessibility, sustainability, and collective prosperity within the Constellation Network.

### Network Fees[​](https://docs.constellationnetwork.io/learn/tools-resources/network-fees-litepaper#network-fees) <a href="#network-fees" id="network-fees"></a>

Constellation Network adheres to the core principle that most network actions should be feeless, fostering a low-fee environment to support the diverse use cases it aims to nurture. While we clarify that low-fee does not mean no-fee, the careful application of network fees, denominated in DAG, is crucial for network scalability and security. These fees play a pivotal role in the decentralized tokenomics of the network, not only by determining the cost of actions and incentivizing certain behaviors but also by deterring malicious attacks. Striking a careful balance between fees and rewards is vital for the network to attract diverse economic models for our metagraph layer, and to scale and accommodate innovation over the years, while simultaneously supporting robust network security.

Moreover, it's important to note that our approach to low or zero fees functions as a subsidy to stimulate network participation and growth. By minimizing fees, Constellation Network aims to lower barriers to entry, making it more accessible for users and encouraging broader adoption of both DAG as a utility token and metagraphs as a platform for development. This strategy is designed to support the network's expansion by fostering an environment that is attractive to new users and developers, ultimately contributing to a self-sustaining and growing ecosystem.

Fees are utilized on the network for the following purposes:

* **Securing the network against attacks:** by making certain patterns of behavior more expensive, such as DDoS or spam attacks, the economic viability of attacking network vulnerabilities is reduced.
* **Efficient resource utilization:** introducing cost mechanisms encourages users towards more resource-efficient behaviors, optimizing network resource usage without imposing limitations. An illustration of this principle is the implementation of metagraph snapshot fees, which attach a tangible cost to data storage on the Hypergraph. This incentivizes metagraph teams to innovate, such as by storing only data notarizations (hashes) on-chain rather than the full data sets, leading to more efficient network space utilization.
* **Creating a utility marketplace:** network fees serve to facilitate a transaction space where users compensate resource providers for their services, effectively creating a marketplace for the exchange of utility. For example, metagraphs pay snapshot fees for the utility of validation, consensus, and storage on the ledger while validator nodes generate rewards for their work validating transactions, reaching consensus, and providing access to on-chain data.

Furthermore, fees fall broadly into two categories:

* **Required**: A minimum fee is necessary for certain actions to proceed, particularly for essential network operations or those involving tangible costs, like snapshot processing and storage. These mandatory fees ensure that critical functions are supported and maintained across the network. Without meeting this fee requirement, the specified actions will not be executed.
* **Optional**: a dynamic or market-rate fee that allows actions to be performed with enhanced priority or speed. Such fees act as incentives for transaction prioritization and overcoming network-imposed limitations, like transaction rate limits. This approach resembles a "tip" to validators, rewarding them for expedited processing of blocks or metagraph snapshots.

Next, we examine the use of fees in two critical areas of the network: peer to peer transactions and metagraph snapshots.

#### Peer to Peer Transactions[​](https://docs.constellationnetwork.io/learn/tools-resources/network-fees-litepaper#peer-to-peer-transactions) <a href="#peer-to-peer-transactions" id="peer-to-peer-transactions"></a>

As the native utility token of the Constellation Network, DAG is used as a method of exchanging value between users through peer to peer transactions on the network. While primarily a feeless currency, DAG has always had the concept of *optional* fees which can be used to prioritize a transaction over others. For the vast majority of network users, there is no need for prioritization, effectively allowing them to operate within a free usage tier while senders with specific throughput or latency requirements pay a small fee for their usage of the network.

For example, an optional fee can be provided to a DAG transaction as a way to prioritize it over other transactions within the mempool and trigger on-demand consensus on the network. This significantly increases transaction throughput for individual wallets and is useful in bulk sending use cases, such as airdrops or distributing to many wallets at once. The optional nature of DAG fees allows those fees to act as a rate limiting mechanism, forcing heavy users of the network to pay for the relatively greater impact of their actions on network resources.

In the coming months, Constellation will be rolling out a small number of limited restrictions for DAG transactions in order to enhance security and scalability of the currency. Like with the optional priority fee, these restrictions can be overridden with a small fee. Each fee targets a specific vulnerability in order to enhance security by making these vulnerabilities too slow or too expensive to exploit. An example of such a fee is enumerated below.

**Low Balance Rate Limit**[**​**](https://docs.constellationnetwork.io/learn/tools-resources/network-fees-litepaper#low-balance-rate-limit)

DAG wallets will be rate limited by the network based on their DAG balance in order to prevent spamming or address splitting attacks which seek to create many low balance wallets quickly to overwhelm network state storage and memory resources.

The rate limiting formula is as follows:

```mathematica
rateLimit = 1 hr / (DAG wallet balance / 20)
```

For example, if a wallet has 5,000 DAG (\~$250 at time of writing) it would be able to send a transaction every 1/(5000 / 20) of an hour, or every 14 seconds.

A wallet with a 1 DAG balance (\~$0.05 at time of writing) would be able to send 1/(1/20) hours, or once every 20 hours.

The above rate limit can be overridden, in much the way that DAG transactions can be prioritized, by providing a 0.002 DAG fee (\~$0.0001 at time of writing) or higher.

This rate limiting mechanism effectively deters spam attacks by making it impractical to execute large volumes of transactions from low-balance wallets without incurring significant costs. This mechanism also ensures that the average user will rarely, if ever, encounter these rate limits unless they are attempting to use accounts with very low balances while sending a large volume of transactions. It's worth mentioning that this approach is not unique to Constellation Network but is a convention established in several other feeless network implementations. This strategy has been adopted as a practical solution to maintain network integrity and prevent abuse while ensuring accessibility for genuine users.

#### Metagraph Snapshot Fees[​](https://docs.constellationnetwork.io/learn/tools-resources/network-fees-litepaper#metagraph-snapshot-fees) <a href="#metagraph-snapshot-fees" id="metagraph-snapshot-fees"></a>

In Constellation’s economic model, metagraph snapshot fees are the primary point of fee collection and the only current source of *required* fees. This structure pushes the responsibility of fee payment to metagraphs rather than users, as is the case in most other decentralized networks. Metagraphs are able to individually design their own economic models that pass these fees on to their users, or pay the fees through other means such as community grants or node rewards. We believe this fee structure creates an ecosystem optimized for novelty and flexibility at the metagraph layer.

Metagraph snapshot fees set the expenses associated with operating on the network which in turn influences the economic viability of individual metagraphs and the sustainability of the network as a whole. By directly linking fees to the operational throughput of metagraphs, the system ensures that the economic burden is proportionate to the usage and benefits derived from the network. This approach fosters a scalable and self-regulating ecosystem, where the cost structure is transparent and aligned with the growth and development of metagraphs.

**Objectives**[**​**](https://docs.constellationnetwork.io/learn/tools-resources/network-fees-litepaper#objectives)

The fee structure for metagraph snapshots was crafted with several key objectives in mind:

* **Limited Fees**: Ensuring that the costs associated with using the network remains low and manageable for projects of all sizes.
* **Flexibility for Metagraphs**: Fees are imposed only for data submitted to the Global L0, allowing metagraphs freedom to determine the fee structure for their users, if any.
* **Staking for Reduced Fees**: Staking encourages long term network participation and commitment, and as such is rewarded with reduced snapshot fees.
* **Fixed Fees**: Required fees have a fixed cost that does not fluctuate due to network activity, allowing for accurate cost projections for metagraph projects.
* **Slow Network Inflation**: In the current era, fees are irrecoverable, effectively working to slow DAG inflation.
* **Inflation Replacing**: Once DAG max supply is reached, future fees will be redistributed as validator rewards.

**Formula**[**​**](https://docs.constellationnetwork.io/learn/tools-resources/network-fees-litepaper#formula)

Snapshot fees are set based on the following formula:

```
Fee = (baseFee × WorkAmount × workMultiplier) + optionalTip
```

The elements of the formula are calculated in the following way:

```
workAmount = kbyteSize x computationalCost

workMultiplier = 1 / (1 + (stakedDAG x stakingWeight) + (proScore x proWeight)

```

The formula relies on the following inputs:

* **kByteSize**: The size of the data submitted in the snapshot represented in kilobytes. The size of the snapshot itself influences the cost of long term storage by validators and archive nodes.
* **stakedDAG**: The amount of DAG that the metagraph has in their designated staking wallet.
* **proScore**: The PRO score of the metagraph, to be rolled out in future eras.
* **optionalTip**: An optional addition to snapshot fees to prioritize snapshots over others in a congested network.

The formula also includes the following constants:

* **baseFee**
  * **Description**: The foundational fee unit of the network represented in datum. This represents the cost of validation and storage for 1 kb of data.
  * **Value**: 100,000 datum
* **computationalCost**
  * **Description**: The computational cost of validating snapshot contents is determined by the required actions, with operations demanding more resources incurring a higher computational cost. It is important to note here that this only applies to operations run during Global L0 validation, and to storage of metagraph snapshots. Metagraphs can implement operations of arbitrary complexity internally, which would only incur a fee if re-validation was required during Global L0 processing of the snapshot, effectively making full validation an opt-in process.
  * **Value**: 1 for custom data snapshots and for L0 token transactions within snapshots.
* **stakingWeight**
  * **Description:** A constant influencing the amount by which `stakedDAG` reduces required fees.
  * **Value**: 0.0000002
* **proWeight**
  * **Description**: A constant influencing the amount by which `proScore` reduces required fees. Initially set to zero until PRO score is live on the network.
  * **Value**: 0

**Fee and Staking Wallets**[**​**](https://docs.constellationnetwork.io/learn/tools-resources/network-fees-litepaper#fee-and-staking-wallets)

In order to facilitate collection of snapshot fees, metagraphs will be required to designate a wallet for their fees to be deducted from. A wallet can be designated by signing a message to prove ownership of the wallet, having that message additionally signed by a majority of metagraph L0 nodes, and then submitting that message to the network. Fee wallets can be changed at any time by signing a new message in the same way.

Fees are denominated in DAG and will be automatically deducted from the fee wallet as a metagraph snapshot successfully undergoes consensus on the Hypergraph. A record of this balance change is stored on the metagraph snapshot itself.

Similarly, a staking wallet can be designated by a metagraph utilizing a similar process to the fee wallet. A message must be signed by the staking wallet and a majority of metagraph L0 nodes, then sent to the network. Staking wallets must be globally unique among metagraphs which ensures that staked DAG is not counted for a metagraph more than once.

It is important to note, the collateral that metagraphs must provide to run their Hypergraph nodes on the network is not counted as staked. Only the balance in the staking wallet at the time of snapshot processing will be considered for the calculation.

**Staking**[**​**](https://docs.constellationnetwork.io/learn/tools-resources/network-fees-litepaper#staking)

Staking benefits the network by reducing circulating supply and thereby increasing the demand for in circulation tokens. Staking also enhances network security, as participants have a vested interest in the integrity and performance of the network, discouraging malicious activities. Metagraphs that stake significant sums of DAG are rewarded by the network with reduced snapshot fees, providing them bandwidth at a lower per-snapshot cost.

<figure><img src="/files/iq5hoh4ySGQxRRvSuRWp" alt=""><figcaption></figcaption></figure>

In the fee calculation, `workMultiplier` is a hyperbolic decay function which approaches zero at high values of `stakedDAG` but never reaches it. In practice, this means that staking can only reduce snapshot fees but never fully eliminate them. This design ensures that while staking significantly incentivizes participation and investment in the network, it also maintains a minimal level of fee generation crucial for the network's sustainability and security.

**Examples**[**​**](https://docs.constellationnetwork.io/learn/tools-resources/network-fees-litepaper#examples)

Here we will look at two examples to illustrate the application of snapshot fees on different metagraph use cases. The first, the Dor metagraph, illustrates data usage by the network’s first MainNet metagraph, and uses data based on real usage trends. The second, the Ethereum Blockchain is presented to describe the hypothetical fees a project could expect to pay to host a metagraph duplicating Ethereum blockchain data on the Hypergraph.

All examples assume a DAG price of $0.10 USD for USD calculations. Outcomes show fees both with and without staked DAG.

**Dor Metagraph**[**​**](https://docs.constellationnetwork.io/learn/tools-resources/network-fees-litepaper#dor-metagraph)

The Dor metagraph validates foot traffic data from a network of IoT sensor devices. Sensors send their data or “check in” with the metagraph once per hour. At the time of writing, there are over 800 sensor devices active on the metagraph.

Sensor data is received by the metagraph in a custom binary format, formatted into internal data schemas, and enriched by data from external sources, namely the Dor REST API. A primary goal in the design of the metagraph data structure was to maintain a low on-chain footprint in order to allow the metagraph to scale to support many thousands of devices. As such, the contents of each check in is hashed, and this notarized value is stored on-chain which significantly reduces the data needs of the metagraph compared to storing full data on-chain.

The metagraph also hosts an L0 token, DOR, which is used to incentivize users to maintain the network of sensors. In testing, the largest snapshot sizes were logged when bulk batches of L0 transactions were validated, with a maximum observed snapshot size of 35kb. Snapshots had a minimum size of 5kb, with an overall mean of 10kb.

Inputs:

| Avg Snapshot Size (kb) | Snapshots/mo |
| ---------------------- | ------------ |
| 10                     | 400,000      |

Outputs:

| DAG Staked | Per-snapshot fee (DAG) | Per-snapshot fee (USD) | Snapshot fees/mo (DAG) | Snapshot fees/mo (USD) |
| ---------- | ---------------------- | ---------------------- | ---------------------- | ---------------------- |
| 0          | 0.01                   | 0.001                  | 4,000.00               | 400.00                 |
| 250,000    | 0.00952380             | 0.00095238             | 3809.52                | 380.95                 |
| 1,000,000  | 0.00083333             | 0.00833333             | 3,333.33               | 333.33                 |
| 10,000,000 | 0.00333333             | 0.00033333             | 1,333.33               | 133.33                 |

**Ethereum Blockchain Metagraph**[**​**](https://docs.constellationnetwork.io/learn/tools-resources/network-fees-litepaper#ethereum-blockchain-metagraph)

To illustrate the costs associated with a metagraph with greater data throughput and an interesting future metagraph use case, we examine a hypothetical metagraph that stores Ethereum block data on the Hypergraph.

For the purposes of this example, the average snapshot size is set to 180kb. This takes into account the recent average of Ethereum block sizes at the time of writing (170kb) and a 10kb overhead for the snapshot schema (5kb) and additional metadata stored along with the blocks (5kb). We assume one snapshot per block and a rate of 213,000 blocks per month.

Inputs:

| Avg Snapshot Size (kb) | Snapshots/mo |
| ---------------------- | ------------ |
| 180                    | 213,000      |

Outputs:

| DAG Staked | Per-snapshot fee (DAG) | Per-snapshot fee (USD) | Snapshot fees/mo (DAG) | Snapshot fees/mo (USD) |
| ---------- | ---------------------- | ---------------------- | ---------------------- | ---------------------- |
| 0          | 0.18                   | 0.018                  | 38,340.00              | 3,834.00               |
| 250,000    | 0.17142857             | 0.01714285             | 36,514.28              | 3,651.43               |
| 1,000,000  | 0.15                   | 0.015                  | 31,950.00              | 3,195.00               |
| 10,000,000 | 0.06                   | 0.006                  | 12,780.00              | 1,278.00               |

To extend the comparison, we can calculate the total number of L0 token transactions that would fit in the same snapshot size (180kb) which is roughly 257 transactions per snapshot, resulting in a monthly total of 54,741,000 transactions. This is, of course, not a directly fair comparison but still serves to illustrate the stark difference in fee structure between Constellation Network and Ethereum.

The table below compares the cost of 54,741,000 transactions on each network. Estimated Hedera and Solana fees are included for reference.

| Network       | Per-transaction cost (USD) | Monthly Cost (USD) |
| ------------- | -------------------------- | ------------------ |
| Constellation | 0.00006994                 | 3,834.00           |
| Ethereum      | 0.93                       | 50,909,130.00      |
| Hedera        | 0.0001                     | 5,474.10           |
| Solana        | 0.000127                   | 6,952.11           |

**Calculator**[**​**](https://docs.constellationnetwork.io/learn/tools-resources/network-fees-litepaper#calculator)

We make available an interactive calculator designed to help you explore the impact of different values on snapshot fees. This tool allows you to dynamically adjust parameters such as `kByteSize` and `stakedDAG` to understand how these parameters impact snapshot fees and to visualize the economic and operational impact of different combinations of metagraph throughput and DAG staked.

[Snapshot Fee Calculator](https://constellationnetwork.io/snapshot-fee-calculator)

### Tokenomic Impacts[​](https://docs.constellationnetwork.io/learn/tools-resources/network-fees-litepaper#tokenomic-impacts) <a href="#tokenomic-impacts" id="tokenomic-impacts"></a>

In 2018, Constellation Network launched the Hypergraph with an economic model based on a fixed token emission schedule for its native currency, DAG. Tokens are distributed to validator node operators for their work maintaining the underlying infrastructure of the network, and other pools that support network activity. Rewards are distributed by the network at a distribution rate based on a preset schedule of epochs, each lasting for roughly two and a half years, depending on the real rate of snapshot creation on the network. In each new epoch, the rewards are cut in half compared to the previous epoch. After the final epoch ends, at a total token supply of less than 3.69 billion DAG, the network will cease to create new rewards entirely. In this way, network rewards are distributed rapidly in early epochs, and then more slowly as the ecosystem matures to limit total supply.

**Epochs and Monthly DAG emissions**

<figure><img src="/files/n0qXC0LIL6PYfMT9eURp" alt=""><figcaption></figcaption></figure>

Reward distributions are an inflationary force, increasing the circulating supply of tokens with each snapshot of network activity towards a capped total supply. This inflationary force supports the maintenance and infrastructure costs of the network by introducing new tokens into the supply at a regular rate. Once the final rewards are distributed and the total supply stabilizes, new mechanisms will be needed to compensate validators and support network infrastructure and development.

#### Fee Distribution[​](https://docs.constellationnetwork.io/learn/tools-resources/network-fees-litepaper#fee-distribution) <a href="#fee-distribution" id="fee-distribution"></a>

Up until now, the collection of fees on the Hypergraph has been minimal, having little overall impact on the network's tokenomics. With the introduction of metagraph snapshot fees, along with additional DAG fees, fee collection will greatly increase and have the opportunity to impact network tokenomics in more significant ways.

In order to benefit the network as a whole, fees are irrevocable, removing them from circulating supply as each metagraph snapshot is processed. In this way, they will become a deflationary countermeasure to the network inflation that the current rewards structure relies on. Their impact will slow the rate of inflation in each epoch and ultimately reduce total supply after the final epoch ends.

After the last snapshot of the final epoch, inflationary rewards will end and a new source of value will need to be unlocked to support node validators and other network infrastructure in a fixed supply environment. At this point, any new fees collected will remain in circulation and be redistributed to the validators and other network rewards pools. As the network matures towards this stage, snapshot fees are likely to grow to become a significant source of value, meeting or exceeding the rewards distribution rate of the final epoch. We believe this transfer of value from resource users to resource providers in the form of rewards will create a self-sustaining network without the need for an ongoing inflationary supply.

### Generative Economics[​](https://docs.constellationnetwork.io/learn/tools-resources/network-fees-litepaper#generative-economics) <a href="#generative-economics" id="generative-economics"></a>

The foundational goal of Constellation Network’s technical and economic model is to foster dynamic systems with a built-in tendency towards social equity, sustainability, and mutually beneficial economic outcomes for all participants. This foundation is influenced by the concept of [generative economics](https://www.opendemocracy.net/en/opendemocracyuk/toward-generative-economy/), which focuses on creating economic systems that inherently produce positive results for society, the environment, and the global economy.

In our model, we focus on interactions between the various stakeholders of our platform: metagraph networks, validator nodes, users of the platform, and community members. The following sections highlight examples of applied generative economic theory within the network.

#### Metagraphs as Producers and Consumers[​](https://docs.constellationnetwork.io/learn/tools-resources/network-fees-litepaper#metagraphs-as-producers-and-consumers) <a href="#metagraphs-as-producers-and-consumers" id="metagraphs-as-producers-and-consumers"></a>

A crucial mechanism built into the network’s fee structure is the requirement that metagraph L0 nodes are run as hybrid Global L0 nodes. In the current era, each metagraph is granted 3 slots on the global network seedlist in order to run their Global L0 nodes. These nodes generate network rewards by validating snapshots for the host metagraph, as well as snapshots from other metagraphs and blocks from the DAG L1. With this mechanism, each metagraph is both a producer of utility on the Hypergraph through their work in network validation and consensus, and a consumer of utility through their submission of data to other network nodes.

For metagraphs with low throughput, the DAG earned from snapshot fees will be greater than the DAG spent on snapshot fees. Conversely, metagraphs with higher throughput will spend more DAG on snapshot fees than they earn in network rewards from their work as a validator.

<figure><img src="/files/fdQ5BYlgFRPvgUEOZosS" alt=""><figcaption></figcaption></figure>

Monthly reward output of 3 Global L0 validator nodes in epoch 2 compared to snapshot fees assuming 100 kb average snapshot size and a computational cost of 1.

To the left of the intersection of the two lines in the graphic above, validator rewards outpace snapshot fees - effectively creating a free usage tier. This provides an economic onramp for metagraph projects to validate their idea and reach scale before having to allocate capital to snapshot fees. It also allows them time to mature their own internal economic model to generate fees from their users if they choose to finance their network fees in that way. We believe this mechanism significantly lowers barriers to entry for the ecosystem while encouraging healthy growth and experimentation with novel economic structures.

#### Heterogeneous Validator Configurations[​](https://docs.constellationnetwork.io/learn/tools-resources/network-fees-litepaper#heterogeneous-validator-configurations) <a href="#heterogeneous-validator-configurations" id="heterogeneous-validator-configurations"></a>

Initially, validator nodes in the Constellation Network were uniformly structured to run both the Global L0 and DAG L1 layers. This configuration was essential for bootstrapping the network and ensuring it could handle real-time transaction loads effectively. However, uniform configuration is suboptimal, primarily because the two layers have distinct resource requirements— notably, L0 processes demand significantly more RAM than L1—and they achieve consensus through different mechanisms. L1 layers can reach consensus in parallel within clusters of three nodes, whereas the L0 layer requires unanimous consensus across all participating nodes.

With the introduction of metagraphs, the network now has the need for additional layers to operate either in conjunction with or independently from the Global L0 and DAG L1 layers. For example, a metagraph built using the Currency Framework and utilizing custom data as a Data Application has 3 additional layers: Metagraph L0, Currency L1, and Data L1.

<figure><img src="/files/pNOouJllMba3lSrLrOW9" alt=""><figcaption></figcaption></figure>

A minimal Currency Framework metagraph running the Global L0, Metagraph L0, Currency L1, and Data L1 layers in parallel on three individual nodes.

Each layer, whether metagraph-specific or global, can scale horizontally in similar fashion to a microservice. This means they can expand in capacity and efficiency to match network demands and data processing needs and thereby achieve optimal performance. Specifically, the scaling of metagraphs predominantly occurs on the L1 layers, which utilize a directed acyclic graph architecture and can facilitate parallel consensus operations at significant rates of throughput. Just as microservices can be independently scaled to meet the needs of different applications, metagraphs can adjust their capacity based on their unique use cases and workload.

The ability of a metagraph to scale each layer independently offers opportunities for community members to actively participate in running nodes as metagraphs expand to match the needs of their specific use cases. For metagraph L1 layers, there is no requirement that nodes must also run validation for the Global L0 layer which means a broader base of the community can participate as node operators, surpassing previous limitations. Nodes run by a diverse group of participants distribute control and reduce central points of failure, making the metagraph more resilient against attacks and manipulation.

Future protocol updates, namely enabling validator reward distribution to L1 nodes, will allow the DAG L1 to scale independently of the Global L0 layer by introducing an independent reward structure on that layer. The DAG L1 can be scaled down significantly while still handling many multiples of the current transaction workload. We believe the current optimal cluster size to be in the range of 12 to 24 nodes. In practice, this would mean that most Global L0 node operators could reduce their infrastructure costs by scaling down their instances to support just the Global L0 layer, without compromising security or scalability on the network, and while continuing to earn rewards.

<figure><img src="/files/68HoZkLLrTr7Z3LjN6Ez" alt=""><figcaption></figcaption></figure>

Homogeneous node configurations transitioning to heterogeneous configurations to support independent scaling of the Global L0 and DAG L1, as well as metagraph layers.

As the network evolves to further support independent scaling of network layers, it paves the way for a more sustainable economic model with new opportunities to contribute as a node operator. This model not only rewards participants fairly but also ensures that the network remains robust against external threats and scalable in the face of growing demand. Node operators will have the flexibility to serve as validators in independent global network layers and metagraph layers, either individually or as hybrid nodes that validate for multiple layers simultaneously. This flexibility will significantly expand the pool of node operators, thereby enhancing the network's overall strength.

#### Incentivizing Builders[​](https://docs.constellationnetwork.io/learn/tools-resources/network-fees-litepaper#incentivizing-builders) <a href="#incentivizing-builders" id="incentivizing-builders"></a>

In order to support a thriving ecosystem, Constellation Network relies on the active engagement and contributions of many network participants. We believe the network will function optimally with higher levels of participation rather than lower. This mindset of abundance is core to the idea of an efficiently functioning Hypergraph; that more interconnected metagraphs and more data throughput will result in a more efficient ecosystem for all participants. As such, there is a need to incentivize network participation in general, and specifically to lower barriers to entry for metagraph project teams to be first movers within the ecosystem, given that they occupy such a critical role in the architecture.

Metagraph project teams need various kinds of support to be able to effectively launch and contribute to the Hypergraph. As a platform with a relatively high learning curve for new developers, resources need to be made available to encourage development teams to choose Constellation Network for their project, and to make them successful once they begin building. These resources come in many forms including developer tools, documentation, and direct support from core developers to answer questions and debug issues. Creating an effective onboarding strategy for these teams is an essential task.

Also critical, is the task of lowering barriers to entry for these projects. Barriers to entry are often economic in nature, and as such require economic solutions such as grants and subsidy agreements to reduce initial costs as projects attempt to scale. Two primary sources of financing exist for project teams interested in building on the Hypergraph: Stardust Collective and the Data Pool.

The Stardust Collective was launched at network genesis as a community group, primarily made up of node operators, with a shared vision to catalyze the network’s growth through proactive community engagement and to spearhead its widespread adoption. Central to their ability to be effective is the Stardust Tax, a 10% tax on all network rewards which is diverted to a holding wallet for use by the collective. Recently, Stardust Collective has legally formalized their organization which has enabled them to channel resources into pivotal projects, from providing loans that boost metagraph project viability to investing in the education of HGTP-centric developers. The Stardust Collective is a powerful force in pushing the network forward.

The Data Pool, launched in early 2023 to support early metagraph builders on the network through a pool of network rewards set aside for distribution through Lattice. This pool initially helped to support the Dor metagraph, the first metagraph to launch on the network. At the time, Dor was already a fully mature company with an existing customer base and a core focus on data analytics. By open sourcing their codebase along with supportive tooling, Dor significantly contributed to the ecosystem, encouraging the development of additional metagraph projects. As the next cohort of metagraph projects prepare to launch, the Data Pool is being made available to project teams to bootstrap their efforts on the Hypergraph.

In a partnership between the core team and Stardust Collective, the following kinds of support from the Data Pool can be made available on a case-by-case basis:

* Node collateral for launching MainNet nodes
* Funds to offset snapshot fees for project scaling
* Project development funds

Through this partnership, we aim to incentivize positive participation in the network, expand open source contributions to critical tooling, and to provide a catalyst for the launch of metagraph projects with strong utility. By actively lowering barriers to entry and providing strong support mechanisms for builders, these programs encourage innovation and sustainable growth within the Hypergraph ecosystem.

### Conclusion[​](https://docs.constellationnetwork.io/learn/tools-resources/network-fees-litepaper#conclusion) <a href="#conclusion" id="conclusion"></a>

Constellation Network’s vision continues to drive a mission of bringing web3 tools to web2 development and businesses. Through metagraphs, we have introduced extensible frameworks that enable more customization through data integrations with incentives and complete subnetwork orchestration. In this paper, we have described a network fee structure that will benefit the network as a whole through enhanced security, scalability, and sustainability. Furthermore, this fee structure expands our vision of web2 composability through its compatibility with existing cloud computing models. This strategy, enhanced by the versatility of metagraph architecture, showcases that the Hypergraph will persist as a supportive platform for projects of varying sizes to flourish. Moreover, the methodologies discussed in this paper regarding fee implementation, resource distribution, and incentivization are set to foster a self-reliant network that advantages all involved parties in the long run.

At the heart of our strategy is a pledge to maintain Constellation Network as an open and dynamic ecosystem for every stakeholder - metagraphs, validator node operators, developers, and the community. The introduction of fees aims to promote efficient use of the network, enhance security against attacks, and foster a vibrant utility marketplace, establishing a foundation where innovation thrives alongside robust security and scalability. These fees serve not just as a mechanism for resource management but as a testament to our commitment to a model that encourages active contribution, rewards engagement, and supports the overall health of the ecosystem.

Each feature and mechanism, articulated in this paper, unlocks the potential for future development and elasticity of the network. For example, dynamic staking can evolve to allow community driven participation to reduce costs on metagraphs, or the ability for nodes to delegate resources to other metagraphs that provide certain attractive economic models. Through both technological and economic lenses, applications will be empowered to create alternative treasury strategies to complement their consumer facing experience. They will not have to compromise their technical vision for broken web3 economic models, but instead will be able to marry web3 architecture and financial strategies to introduce programmatic transparency, accountability, and accretive financial models.


# Metanomics

## Introduction[​](https://docs.constellationnetwork.io/learn/tools-resources/metanomics-litepaper#introduction) <a href="#introduction" id="introduction"></a>

As Constellation Network evolves to meet the dynamic needs of a growing ecosystem, we are excited to introduce Metanomics—the next generation of our tokenomic model. The current framework has successfully driven data incentivization, supported node validators, and nurtured the early stages of metagraph development. However, with the network expanding and more metagraph projects coming online, a decisive shift is necessary. Metanomics is designed to be a sustainable and adaptable supply model that aligns with our vision for long-term decentralization, offering robust rewards and incentives for all stakeholders within the ecosystem.

In cryptocurrency, a capped supply model is often ideal for store-of-value tokens, as it can enhance scarcity and, by extension, value retention. However, DAG is fundamentally a utility token designed to foster the growth and functionality of the Constellation Network. A strictly capped supply can hinder the network's ability to adapt and scale effectively, restricting its capacity to reward validators, support protocol development, and incentivize all participants within the ecosystem.

Currently, Constellation Network supports the development of its public protocol through a combination of public and private funding sources. While this approach has allowed for significant growth, it also presents challenges in aligning resources with the broader needs of the network. As the ecosystem evolves, it's becoming increasingly important to establish a dedicated focus on core protocol development and network tooling to ensure the continued expansion and innovation of the public network. Metanomics offers a clear path forward by providing a sustainable funding model that reduces reliance on private subsidies and aligns incentives across all participants, ensuring Constellation Network can continue to deliver robust solutions for its users.

This litepaper introduces the next evolution of DAG tokenomics with a flexible supply model. This model ensures predictable incentives for node validators, participants, and protocol development while preserving the network’s economic integrity. It also establishes a transparent and sustainable mechanism for funding both ongoing and future initiatives.

## The New Model[​](https://docs.constellationnetwork.io/learn/tools-resources/metanomics-litepaper#the-new-model) <a href="#the-new-model" id="the-new-model"></a>

### Immediate Changes[​](https://docs.constellationnetwork.io/learn/tools-resources/metanomics-litepaper#immediate-changes) <a href="#immediate-changes" id="immediate-changes"></a>

#### **Rebuild Treasury**[**​**](https://docs.constellationnetwork.io/learn/tools-resources/metanomics-litepaper#rebuild-treasury)

As we navigate the evolving market, with its increasing competition and new opportunities for adoption, it is essential to refocus on open-source development, core team support, and ecosystem growth.

To support these efforts, we are making a strategic move to significantly enhance the Constellation Network treasury, comparable to leading protocols. This initiative is crucial for providing robust support for both ongoing and future projects, ensuring that our network remains competitive and continues to thrive.

As part of this strategy, we will unlock and repurpose 450 million DAG tokens. These tokens were originally locked by the founders as a commitment to the long-term success of the network and to demonstrate their confidence in the long term success of the Constellation ecosystem. Now, with the network entering a new phase of growth, these tokens will be strategically allocated to accelerate development and expansion.

The repurposed tokens will be allocated as follows:

* **Scaling Operations:** 50M DAG
* **Community Incentives (grants, general incentives):** 50M DAG
* **Marketing & Network adoption (development support, documentation, content creation):** 50M DAG
* **Employee Incentives:** 50M DAG (18-month vesting)
* **Public goods (Tessellation, Stargazer, Dag Explorer, Lattice, Euclid SDK, dag4js), Development, Engineering, R\\\&D:** 250M DAG

To ensure transparency and maintain the trust of all network participants, we will provide bi-annual updates on the impact and allocation of these funds across the various categories. Furthermore, to protect the DAG market from unnecessary volatility, any token sales for funding will be limited to 5% of the average daily trade volume.

Reallocating these tokens ensures that Constellation Network is ready to compete and thrive in the rapidly changing Web3 landscape. This investment in community incentives, marketing, network adoption, employee incentives, and product development will strengthen our foundation and drive substantial growth in the years to come.

#### **Winding down the data pool**[**​**](https://docs.constellationnetwork.io/learn/tools-resources/metanomics-litepaper#winding-down-the-data-pool)

As we transition to the Metanomics model, the Data Pool will remain active until the official go-live date at the end of Q1 2025. However, in the lead-up to this transition, we are adjusting the overall distribution of tokens within the Data Pool to better align with the network’s future state.

#### **New distribution**[**​**](https://docs.constellationnetwork.io/learn/tools-resources/metanomics-litepaper#new-distribution)

The overall distribution will change as follows:

* **Data pool bounties:** decrease from 55% to 42%
* **Stardust tax:** decrease from 10% to 7%
* **Mainnet validator incentives:** increase from 17% to 24%
* **Integrationnet validator incentives:** increase from 15% to 20%
* **Testnet validator incentives:** increase from 3% to 7%

#### **DTM Bounties**[**​**](https://docs.constellationnetwork.io/learn/tools-resources/metanomics-litepaper#dtm-bounties)

In line with these changes, the DTM baseline bounty will be discontinued, as the primary focus now shifts to data collection with Dor's metagraph fully operational. To meet the expectations of Foundation DTM buyers, we will remove the caps on commercial and installation bounties. Of the 5,991,186.99 DAG allocated for this purpose, 2,710,298.88 DAG will be distributed monthly, with 35% designated for commercial bounties and 65% for installation bounties until the new tokenomics are implemented.

The remaining DAG will be reserved for distribution after the new tokenomics model is in place ensuring that DTM bounties remain available for 18 months after the Data Pool changes. This provides a smooth transition as we move into the Metanomics era.

<figure><img src="/files/DoriusZBzJVYPcnUkSKd" alt=""><figcaption><p>data-pool-redistribution.png</p></figcaption></figure>

### Metanomics[​](https://docs.constellationnetwork.io/learn/tools-resources/metanomics-litepaper#metanomics-1) <a href="#metanomics-1" id="metanomics-1"></a>

#### **Introducing Metanomics**[**​**](https://docs.constellationnetwork.io/learn/tools-resources/metanomics-litepaper#introducing-metanomics)

As Constellation Network continues to grow and evolve, so too must its tokenomics. Metanomics represents the next significant step in the evolution of DAG tokenomics, designed to meet the network’s future needs while building on the strong foundation already in place.

Under the old model, rewards were distributed according to a fixed schedule of epochs, each lasting approximately two and a half years, depending on the actual rate of snapshot creation on the network. In each new epoch, the rewards were halved, with the final epoch concluding once the total token supply reached just under 3.69 billion DAG. At that point, no new rewards would be created, effectively capping the total supply and distributing rewards rapidly in the early stages and more gradually as the ecosystem matured.

However, as the network expands and more participants join the ecosystem, a more flexible and sustainable model is needed. Beginning in the first quarter of 2025, DAG will transition to a flexible supply token under the Metanomics model. This new structure introduces a dynamic inflation rate, starting at 6% and gradually decreasing until it stabilizes at 0.5%.

A key innovation in this model is integrating DAG's market price into the emission formula. As network participants incur fixed costs—such as hardware, opportunity costs, and the expenses related to core protocol development—the inflation rate will adjust accordingly. When the token price is higher, less inflation is required to cover these costs, thereby maintaining economic stability within the Constellation ecosystem. This approach ensures sustainable growth, preventing both excessive inflation and deflation, and enhances the utility of DAG as a mechanism for securing the long-term sustainability of the network.

By shifting to a flexible supply model, Metanomics ensures that Constellation Network can dynamically adapt to the needs of its growing ecosystem. Unlike the capped supply of the past, this approach allows for a balanced distribution of rewards that scales with network demand. The flexibility in supply enables the network to provide consistent incentives for validators and participants, maintain economic stability, and support ongoing development—all while ensuring that the network can evolve in step with its expanding user base and technological advancements.

#### **Emission Formula**[**​**](https://docs.constellationnetwork.io/learn/tools-resources/metanomics-litepaper#emission-formula)

**Key aspects**[**​**](https://docs.constellationnetwork.io/learn/tools-resources/metanomics-litepaper#key-aspects)

* Economic Stability: The flexible supply adjusts to market conditions, maintaining network health.
* Incentive Alignment: Ensures continuous incentives for protocol, stardust collective, validators, and delegators.
* Transparency: A clear and predictable inflation rate allows all participants to adjust and plan accordingly.

<figure><img src="/files/K6HMoXvN8mCP6rkBmDsC" alt=""><figcaption><p>inflation-formula.png</p></figcaption></figure>

#### **Network Emission Distribution**[**​**](https://docs.constellationnetwork.io/learn/tools-resources/metanomics-litepaper#network-emission-distribution)

The distribution of inflation emissions among network stakeholders is structured as follows:

<figure><img src="/files/Mp20cPxmqjKSz1Vtki5G" alt=""><figcaption><p>diagram-emission-distribution.png</p></figcaption></figure>

#### **Variable emissions**[**​**](https://docs.constellationnetwork.io/learn/tools-resources/metanomics-litepaper#variable-emissions)

* Protocol receives 30%
* Stardust Collective (Foundation) receives 5%
* Validators receive 20%
* Delegators receive 45%

#### **Fixed emissions**[**​**](https://docs.constellationnetwork.io/learn/tools-resources/metanomics-litepaper#fixed-emissions)

* Delegators receive a fixed 3% on delegated DAG

The protocol starts with an initial rate of 0%, increasing by 6% each quarter until it reaches a maximum of 30%. During this ramp-up period, the foundation receives the remaining funds.

<figure><img src="/files/Pv3fvjsyjxZXpnguPf5S" alt=""><figcaption><p>chart-emissions-split-over-time.png</p></figcaption></figure>

This allocation ensures robust incentives for all groups to actively participate and operate within the network, providing a sustainable, predictable, and transparent incentive framework.

### **Introducing Delegators**[**​**](https://docs.constellationnetwork.io/learn/tools-resources/metanomics-litepaper#introducing-delegators)

Delegators are key participants within the Constellation Network who hold DAG tokens and choose to delegate them to one or more validators on the network. In return for their delegation, they receive incentives, with a portion deducted as a validator fee.

Anyone that holds DAG in a wallet can participate in the delegation process. Token holders simply choose a validator on the network to delegate to - this could be regular validators, metagraph-operated validators, or any other validator node on the network. After delegation, rewards are distributed to the delegator based on the amount delegated, with a portion of rewards redirected to the validator based on their validator fee.

This delegation process allows anyone to participate actively in the network by directing token emissions to their chosen validators. Delegators thus play a crucial role in shaping the distribution of network incentives, making them active participants in the growth and governance of Constellation Network.

The Protocol/core treasury is prohibited from being used in Delegation.

### **Delegator incentives**

[**​**](https://docs.constellationnetwork.io/learn/tools-resources/metanomics-litepaper#delegator-incentives)

<figure><img src="/files/Zgmr6265nphKDciHXLW5" alt=""><figcaption><p>diagram-delegator-and-validator-incentives.png</p></figcaption></figure>

Delegators receive incentives from two sources:

* **Fixed Emissions:** A fixed 3% APR on all delegated DAG.
* **Variable Emissions:** 45% of all inflationary emissions allocated to the network.

A key factor in this model is the idea that in order to have a functional delegation system, delegator rewards should outpace network inflation whenever possible. The variable rewards structure creates a dynamic within the network where an equilibrium in incentive distribution is achieved when 60% of the total DAG supply is delegated. This 60% threshold is optimal as it maintains network liquidity while encouraging active participation.

When the total supply delegated is below 60%, DAG holders have a clear incentive to delegate, as their returns will exceed the inflation rate. The fixed 3% APR further ensures that delegator incentives are consistently above the inflation rate, making delegation a compelling option for all DAG holders.

This structure creates a precise opportunity cost for keeping DAG idle, as the tokens would be diluted over time, creating a powerful incentive for all network participants to engage in the existing opportunities within the network.

#### **Unwinding a Delegated Position**[**​**](https://docs.constellationnetwork.io/learn/tools-resources/metanomics-litepaper#unwinding-a-delegated-position)

If a delegator decides to withdraw their DAG tokens from delegation, there is a 30-day unwinding period during which the tokens remain locked, and no rewards are earned. This unwinding period helps maintain network stability and prevents sudden large withdrawals that could disrupt the system. However, delegators can re-delegate their tokens to another validator without undergoing this unwinding period.

#### **Validator Fees**[**​**](https://docs.constellationnetwork.io/learn/tools-resources/metanomics-litepaper#validator-fees)

Validators can set a fee, ranging from 5% to 10%, on the incentives distributed to Delegators. This fee structure incentivizes validators to operate efficiently and attract delegations by offering competitive terms. Delegators have the freedom to choose validators based on performance, alignment with specific projects, or contributions to the network, creating a competitive environment where validators strive to maintain high standards. For instance, entities like the Stardust Collective (Foundation), the Protocol, or DOR may have dedicated validators where delegators can delegate their tokens, effectively directing support to these areas of the network.

#### **Active incentive governance**[**​**](https://docs.constellationnetwork.io/learn/tools-resources/metanomics-litepaper#active-incentive-governance)

The introduction of delegators adds a new layer of active incentive governance within the Constellation Network. By selecting specific validators, delegators directly influence the distribution of 5% to 10% of the total delegate emissions. This participatory model creates a competitive environment wherein node validators are incentivized to compete and find means to attract delegations.

Delegators can choose validators based on their performance, alignment with specific projects, or contribution to the network. This choice encourages validators to maintain high standards and actively contribute to the network's health and growth.

All aspects of the incentive governance model are designed to be transparent. The mechanisms for delegation, collecting validator fees, and emission distribution will be automated and on-chain, allowing all participants to understand and predict outcomes.

#### **Metagraph Projects**[**​**](https://docs.constellationnetwork.io/learn/tools-resources/metanomics-litepaper#metagraph-projects)

Metagraph projects can strategically leverage this governance structure to secure funding and project growth. By attracting delegated DAG, metagraph projects can finance their development, marketing, and community engagement initiatives. Providing L0 tokens or exclusive project features as incentives to delegators aligns the interests of these projects with those of the network participants.\
It will be up to the project to decide the best way to attract delegated DAG by leveraging what their project offers.

#### **Stardust Collective**[**​**](https://docs.constellationnetwork.io/learn/tools-resources/metanomics-litepaper#stardust-collective)

The Stardust Collective, tasked with promoting community growth and network awareness, benefits from this incentive governance model as a funding opportunity. Delegators who value the Collective's contributions can delegate their DAG to the Collective’s validators, thereby supporting its initiatives.

#### **Node validators**[**​**](https://docs.constellationnetwork.io/learn/tools-resources/metanomics-litepaper#node-validators)

Regular node validators can leverage this dynamic to accrue extra DAG incentives.\
Known node validators in the community can leverage their following to attract delegations. They can do this by giving special perks to those who decide to delegate to their validator.\
Other node validators can simply delegate their DAG to their own validator. This will guarantee them net incentives, as they receive the full delegation amount plus the validator fee.

#### **Protocol**[**​**](https://docs.constellationnetwork.io/learn/tools-resources/metanomics-litepaper#protocol)

Although protocol/core treasury cannot participate in delegation, delegators can opt to delegate to the protocol nodes, this will help fund development and the overall work the protocol does for the network.

#### Snapshot Fees[​](https://docs.constellationnetwork.io/learn/tools-resources/metanomics-litepaper#snapshot-fees) <a href="#snapshot-fees" id="snapshot-fees"></a>

Snapshot fees play a critical role in the Constellation Network's economic model, particularly within the framework of Metanomics. These fees are paid by metagraphs based on their activity levels on the network and are designed to be a counterbalance to the inflationary aspects of the tokenomics model.

As metagraphs generate activity on the network, they incur snapshot fees that are consumed, and irrevocably removed from circulation. This removal of fees serves to offset the inflationary emissions generated through rewards, ensuring that the overall token supply remains balanced.

In this way, snapshot fees act as a buffer against potential oversupply, creating stability for DAG and contributing to the network's health. Their role is particularly important after the transition to the flexible supply model, where they help to maintain the delicate balance between inflation and deflation.

If the network requires additional support, a governance vote could authorize reallocating a portion of the snapshot fees to validator incentives. This flexibility ensures that the network remains adaptable and capable of sustaining growth while preserving its core economic principles.

#### Key dates[​](https://docs.constellationnetwork.io/learn/tools-resources/metanomics-litepaper#key-dates) <a href="#key-dates" id="key-dates"></a>

* Unlock of the original 450M DAG founder’s tokens: August 9th, 2024
* Data pool changes: August 2024
* Go live of Metanomics: End of Q1 2025

## Model Summary[​](https://docs.constellationnetwork.io/learn/tools-resources/metanomics-litepaper#model-summary) <a href="#model-summary" id="model-summary"></a>

#### Key Features[​](https://docs.constellationnetwork.io/learn/tools-resources/metanomics-litepaper#key-features) <a href="#key-features" id="key-features"></a>

* **Flexible Supply Model:** The supply of DAG will adjust based on market conditions, with an initial inflation rate of 6% decreasing to a target rate of 0.5%.
* **Emission Distribution:** Inflation emissions are allocated among protocol development (30%), Stardust Collective (5%), validators (20%), and delegators (45% of emissions plus a fixed 3%).
* **Delegators:** New way for DAG holders to participate in the network as a mechanism of active incentive governance

<figure><img src="/files/CZfpWwLgpxdnIOVchgUj" alt=""><figcaption><p>diagram-dag-supply.png</p></figcaption></figure>

#### Effect of market conditions on the inflation rate[​](https://docs.constellationnetwork.io/learn/tools-resources/metanomics-litepaper#effect-of-market-conditions-on-the-inflation-rate) <a href="#effect-of-market-conditions-on-the-inflation-rate" id="effect-of-market-conditions-on-the-inflation-rate"></a>

<figure><img src="/files/cD0BN1ZFuqAUmP1blSQi" alt=""><figcaption><p>chart-market-conditions-on-inflation-rate.png</p></figcaption></figure>

This chart shows how the inflation rate in the model reacts over time under four different market conditions (stable, decreasing, increasing, and up and down), with all other inputs being equal.

The Metanomics model is designed to ensure that, regardless of market conditions, the inflation rate gradually decreases over time until it reaches a target rate of 0.5%. This built-in adaptability allows for effective management of the DAG token supply, supports network growth, and maintains economic stability even in fluctuating market environments.

#### Relation between Network adoption and DAG supply[​](https://docs.constellationnetwork.io/learn/tools-resources/metanomics-litepaper#relation-between-network-adoption-and-dag-supply) <a href="#relation-between-network-adoption-and-dag-supply" id="relation-between-network-adoption-and-dag-supply"></a>

<figure><img src="/files/jwKLl2PHjtEcvSDfB4ww" alt=""><figcaption><p>chart-network-adoption-and-dag-supply.png</p></figcaption></figure>

This chart illustrates how the model responds to a consistent increase in network activity by mitigating the effects of inflation on the token supply.

The controlled increase in total supply, along with a decreasing inflation rate and growing metagraph adoption, demonstrates the model’s capacity to provide necessary incentives while avoiding unchecked supply growth. This balance ensures the network remains appealing to new participants and continues to expand sustainably.

## Conclusion[​](https://docs.constellationnetwork.io/learn/tools-resources/metanomics-litepaper#conclusion) <a href="#conclusion" id="conclusion"></a>

The introduction of the Metanomics model represents a crucial evolution in Constellation Network's approach to tokenomics, aligning our economic framework with the growing needs of our ecosystem. By embracing a dynamic supply model with a controlled and decreasing inflation rate, Metanomics ensures that the network can sustain growth while maintaining economic stability.

This new model enhances our ability to not only open the network to more participants but also to incentivize them to participate effectively, ensuring that the ecosystem remains appealing to both existing members and newcomers. Integrating delegators into the governance process further empowers our community, creating a more engaged and participatory network where token emissions and rewards are directly influenced by those who contribute to the network's health and success.

As metagraphs continue to drive increased activity on the network, the role of snapshot fees becomes increasingly vital. These fees, integrated into the dynamic supply model, help moderate inflation in line with network activity, ensuring overall balance within the ecosystem. Along with a strong network treasury and developer outreach strategy, the proliferation of metagraph projects will form a generative economic landscape that will support the network as a whole.

By managing supply and demand through a well-structured tokenomic framework, Metanomics positions Constellation Network to thrive in the face of evolving market conditions. This forward-looking approach lays the foundation for sustained success, ensuring that Constellation Network continues to lead in the decentralized technology space for years to come.


# Wallets

Wallets are applications that manage private keys and provide a convenient way to interact with addresses on the network.

### Stargazer Wallet[​](https://docs.constellationnetwork.io/learn/tools-resources/wallets#stargazer-wallet) <a href="#stargazer-wallet" id="stargazer-wallet"></a>

Stargazer Wallet is a multichain wallet that supports Constellation and Ethereum chains. It's available as a Chrome extension and on mobile for iOS and Android.

<table data-view="cards" data-full-width="true"><thead><tr><th></th><th data-hidden data-card-target data-type="content-ref"></th><th data-hidden data-card-cover data-type="files"></th></tr></thead><tbody><tr><td><strong>Download Chrome Extension</strong></td><td><a href="https://chromewebstore.google.com/detail/stargazer-wallet/pgiaagfkgcbnmiiolekcfmljdagdhlcm?hl=en-US">https://chromewebstore.google.com/detail/stargazer-wallet/pgiaagfkgcbnmiiolekcfmljdagdhlcm?hl=en-US</a></td><td><a href="/files/GyEt31tjwQkO3FDhs7dY">/files/GyEt31tjwQkO3FDhs7dY</a></td></tr><tr><td><strong>Download on IOS</strong></td><td><a href="https://apps.apple.com/us/app/stargazer-wallet/id1612326452">https://apps.apple.com/us/app/stargazer-wallet/id1612326452</a></td><td><a href="/files/icFCieQqP5nDE9JZx13B">/files/icFCieQqP5nDE9JZx13B</a></td></tr><tr><td><strong>Download on Android</strong></td><td><a href="https://play.google.com/store/apps/details?id=com.stargazer">https://play.google.com/store/apps/details?id=com.stargazer</a></td><td><a href="/files/xPqZ02S8bRVyMnloJ4Vf">/files/xPqZ02S8bRVyMnloJ4Vf</a></td></tr></tbody></table>


# DAG Explorer

The DAG Explorer is an open source tool available for the Constellation community to monitor transaction statuses and other important information about the network. The tool supports MainNet and all t

<table data-view="cards" data-full-width="true"><thead><tr><th></th><th data-hidden data-card-cover data-type="files"></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>Mainnet</strong> </td><td><a href="/files/HrJfYqzSlGfqJ2kOtYwR">/files/HrJfYqzSlGfqJ2kOtYwR</a></td><td><a href="https://mainnet.dagexplorer.io/">https://mainnet.dagexplorer.io/</a></td></tr><tr><td><strong>Integrationnet</strong></td><td><a href="/files/g2j10BQYg3KUsgAsgZ1f">/files/g2j10BQYg3KUsgAsgZ1f</a></td><td><a href="https://integrationnet.dagexplorer.io/">https://integrationnet.dagexplorer.io/</a></td></tr><tr><td><strong>Testnet</strong></td><td><a href="/files/sCNYLUjmpcQufpNwvk7t">/files/sCNYLUjmpcQufpNwvk7t</a></td><td><a href="https://testnet.dagexplorer.io/">https://testnet.dagexplorer.io/</a></td></tr></tbody></table>


# Overview

<table data-card-size="large" data-view="cards" data-full-width="true"><thead><tr><th></th><th></th><th data-hidden data-card-cover data-type="files"></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>Explore Projects</strong></td><td>Explore projects building on Constellation Network</td><td><a href="/files/EcM4fttMVGeCYNt3IVYz">/files/EcM4fttMVGeCYNt3IVYz</a></td><td><a href="https://constellationnetwork.io/projects/">https://constellationnetwork.io/projects/</a></td></tr><tr><td><strong>Ecosystem Partners</strong></td><td>View our growing list of trusted partners</td><td><a href="/files/1EaZy0b5TpiD6wj1zyxi">/files/1EaZy0b5TpiD6wj1zyxi</a></td><td><a href="https://constellationnetwork.io/community/">https://constellationnetwork.io/community/</a></td></tr></tbody></table>


# Introduction

This section introduces the foundational concepts that underpin the Constellation Network. It covers the network's layered architecture, consensus model, token standards, fee structures, and the role of metagraphs within the broader ecosystem. Whether you're building a decentralized application, running a validator, or integrating with the network, these articles will help you understand how the core components fit together.

For guidance on building and deploying metagraphs, see therapid development resources available in the [Euclid SDK](/metagraph-development#euclid-sdk).

Developer support is available on [Discord](https://discord.gg/9PhXJKeAWC).


# Architecture

## Overview

Constellation Network uses a modular, horizontally scalable architecture designed to support high-throughput applications, verifiable data, and decentralized value transfer. At the heart of the network is the Global Layer 0 (gL0)—known as the Hypergraph—which acts as the final consensus layer and source of truth for all activity across the network.

The Hypergraph aggregates data from multiple sources, including the DAG L1, where native DAG token transactions are validated and structured into blocks using a directed acyclic graph (DAG) model. Once validated, these blocks are submitted to the global L0 for final inclusion in the network’s canonical ledger.

Constellation also supports modular application layers called metagraphs—independent subnets that define their own logic, tokens, and data structures. Each metagraph includes:

* **Currency L1**: Validates transactions involving its native L0 token.
* **Data L1**: Validates domain-specific custom data updates.
* **Metagraph L0**: Packages validated L1 transactions into metagraph snapshots, which represent the metagraph’s finalized state.

Metagraph snapshots are submitted to the Global L0 (Hypergraph) alongside DAG L1 blocks. After undergoing a final round of validation, all accepted data is recorded into a global snapshot, which serves as the immutable, globally recognized record of network state.

This layered architecture allows Constellation to maintain global consistency while supporting decentralized, scalable execution across a diverse set of applications. By anchoring all activity to the Hypergraph, the network ensures both flexibility at the edge and strong consensus at the core.

<figure><img src="/files/deGHwSRUPFobYS7mOfAD" alt=""><figcaption></figcaption></figure>

## Metagraph Architecture[​](https://docs.constellationnetwork.io/metagraphs/concepts/architecture#metagraph-layers) <a href="#metagraph-layers" id="metagraph-layers"></a>

Metagraphs are modular, application-specific components of the Constellation Network. Each metagraph is composed of a Layer 0 (L0) and one or more Layer 1 (L1) layers. Together, these layers manage the ingestion, validation, consensus, and finalization of application data and token transactions within the metagraph.

### Core Concepts

* **L1 Layers** are responsible for ingesting data or transactions, performing initial validation, and reaching consensus using a DAG-based consensus algorithm.
* **L0 Layer** performs final validation, runs majority-based consensus, and packages validated blocks from L1 layers into metagraph snapshots—the core unit of state on a metagraph.
* **Snapshots** are submitted from the metagraph L0 to the Global L0 (Hypergraph) for inclusion in the global snapshot chain.

Each layer consists of a cluster of 3 or more nodes. Nodes within a layer communicate over secure HTTP APIs with source-signed messages. Cross-layer communication (e.g., L1 to L0) also uses HTTP with additional security measures to ensure integrity and authentication.

![Euclid SDK](https://docs.constellationnetwork.io/assets/images/metagraph-architecture-e7488eedaaca28f19109dd2f88d4e2f3.svg)

### Layer Definitions

#### Metagraph L0

Also referred to as the Currency L0 layer, this is the final consensus and validation layer of the metagraph. It:

* Aggregates blocks from L1 layers
* Forms the metagraph snapshot chain
* Submits finalized snapshots to the Global L0 (Hypergraph)

The metagraph’s L0 snapshot chain is independent of the global snapshot chain but is periodically synchronized with it through snapshot submission.

***

#### Currency L1

A DAG-based L1 layer dedicated to L0 token transactions. It:

* Validates transactions (signatures, balances, sender addresses)
* Applies any custom logic defined by the metagraph
* Forms blocks from valid transactions
* Runs graph-based consensus over blocks
* Submits finalized blocks to the metagraph L0 layer

***

#### Data L1

A DAG-based L1 layer for domain-specific custom data updates. It:

* Validates and decodes application-specific data
* Verifies signatures and runs custom validation logic
* Forms blocks of valid data
* Runs DAG-based consensus
* Submits finalized blocks to the metagraph L0 layer

***

#### Global L0 (Hypergraph)

The Hypergraph is the network-wide Layer 0 consensus layer. It:

* Validates and finalizes metagraph snapshots
* Validates and finalizes DAG L1 blocks
* Aggregates them into global snapshots
* Maintains the canonical record of all activity across DAG L1 and metagraphs

Once a metagraph snapshot is accepted into a global snapshot, it is considered finalized and recorded on-chain.

***

### Scaling Considerations

Constellation’s metagraph architecture is optimized for both **horizontal** and **vertical** scaling:

| Layer     | Scaling Method | Description                                                                                                                                                                       |
| --------- | -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| L1 Layers | Horizontal     | Adding more nodes increases throughput and parallel consensus capabilities                                                                                                        |
| L0 Layer  | Vertical       | Throughput is limited by node resources; scaling requires more powerful nodes. Adding more L0 nodes improves fault tolerance, decentralization,  and security, but not throughput |

L1 layers benefit from distributed consensus and can scale out as needed to support high data volumes. L0 layers must reach majority consensus and require synchronized participation, so their performance scales vertically rather than horizontally.

## Summary

Constellation’s architecture combines localized processing with global consensus to support secure, scalable, and application-specific blockchain infrastructure. Metagraphs operate independently with their own validation and consensus layers, while the Hypergraph serves as the unifying Layer 0 that finalizes state across the entire network. By coordinating all finalized activity into global snapshots, Constellation ensures a consistent, tamper-proof ledger—while enabling parallel execution and innovation at the edge of the network.


# Accounts and Keys

The basics of Constellation accounts and keys

## Overview

Constellation Network accounts are identified by cryptographic addresses that serve as public identifiers for transactions on the network. These addresses are used across both the Hypergraph (DAG) and metagraphs (L0 tokens), ensuring a unified identity model across the entire ecosystem.

Each account is secured through asymmetric cryptography, relying on a **Key Trio** consisting of a **private key**, **public key**, and **address**.

## The Key Trio[​](https://docs.constellationnetwork.io/metagraphs/accounts#the-key-trio)

In the Constellation Network, accounts are composed of a key trio consisting of the private key, public key, and an address.

* **Private key:** The private key is a highly confidential piece of information that plays a crucial role in authenticating an address to the network. With the private key, you can execute sensitive actions like signing messages or sending transactions.
* **Public key:** The public key serves as a unique identifier for nodes on the network and is derived from the private key. It is crucial for establishing trust relationships between nodes, enabling secure communication, and verifying digital signatures.
* **Address:** The address is the public-facing component of the Key Trio and represents a public wallet address for receiving payments or other digital transactions. It can be derived from either the private or public key and is widely used for peer-to-peer transactions. Sharing your address with others enables them to send you payments while keeping your private key confidential.

## Address Format[​](https://docs.constellationnetwork.io/metagraphs/accounts#address-format) <a href="#address-format" id="address-format"></a>

{% hint style="warning" %}
Constellation Network addresses are case sensitive!
{% endhint %}

Addresses consist of 40 characters divided into three parts.

* **Prefix:** the characters “DAG”.
* **Check digit:** A single decimal calculated from the digits in the Hash.
* **Hash:** The [base58 encoded](https://en.bitcoin.it/Base58Check_encoding) hash of the first 36 characters of an account public key.

The **Check Digit** is computed by taking the sum of all digit characters in the **Hash**. If the sum is greater than 9, the sum is reduced to a single digit by taking the remainder of the sum divided by 9.

#### Example Calculation

In the address `DAG5poQ31KFjikEgLoqnf9CQR2KVYv3pfxV5NQZY` the **Check Digit** can be calculated in the following way:

```
3+1+9+2+3+5 = 23
23 % 9 = 5
```

Thus, the **Check Digit** is 5.

## Deriving an Address from a Public Key

The **Hash** can be derived from the public key in hex format in the following way:

```typescript
const PKCS_PREFIX = '3056301006072a8648ce3d020106052b8104000a03420004';

function deriveHash (publicKeyHex: string) {
  const prefixed = PKCS_PREFIX + publicKeyHex;

  const sha256String = sha256(publicKeyHex);
  const hash = bs58.encode(sha256String);
  
  return hash.slice(hash.length - 36, hash.length);
}

function deriveAddress(publicKeyHex: string) {
  const hash = deriveHash(publicKeyHex);
  const checkDigit = hash.match(/\d/g).reduce((sum, digit) => sum + parseInt(digit, 10), 0) % 9;
  
  return `DAG${checkDigit}${hash}`;
}
```

The address is constructed of the three components concatenated together:

```javascript
address = "DAG" + checkDigit + hash
```

## Signing Messages[​](https://docs.constellationnetwork.io/metagraphs/accounts#signing-messages) <a href="#signing-messages" id="signing-messages"></a>

Constellation Network supports ECDSA signatures on secp256k1.

To sign messages, a sha512 hash of the message is signed with the private key.

```javascript
function sign (privateKey: string, msg: string) {
  const sha512Hash = sha512(msg);
  
  const signature = secp.sign(sha512Hash, privateKey);

  return Buffer.from(signature).toString('hex'); 
}

```


# Snapshots and Network State

## Overview

On the Hypergraph, **snapshots** serve as the core unit of state progression, replacing the traditional blockchain model of sequential blocks. Instead of processing transactions individually within a single chain, the network allows multiple **L1 layers**—such as DAG L1 and Currency L1—to create blocks independently in parallel. These blocks are then submitted to the **L0 layer** (Hypergraph/metagraph L0), where they are validated and aggregated into snapshots. Each snapshot finalizes a set of blocks, creating a cohesive and secure record of network activity.

This snapshot-based approach enables high throughput by allowing concurrent execution of L1 blocks while maintaining strong security guarantees through the Hypergraph’s global finalization process. Snapshots provide a scalable way to track and verify state changes across both the Hypergraph and metagraphs.

## The Role of Snapshots on the Network

A snapshot in Constellation Network serves a function similar to blocks in other blockchains, but with key differences. Rather than containing individual transactions, a snapshot finalizes a collection of **validated L1 blocks**. These snapshots form a cryptographically linked chain that represents the history of the network’s state.

Each **Global Snapshot** records the Merkle root of all finalized transactions, along with references to previous snapshots to maintain continuity. It also includes any metagraph snapshots that have been submitted to the Hypergraph, ensuring that metagraph state is secured at the L0 level. Once finalized, a snapshot is immutable and verifiable, creating a reliable source of truth for all network participants.

## The Snapshot Lifecycle

The process of snapshot creation follows a structured lifecycle, starting with **L1 block formation**, progressing through **L0 validation and aggregation**, and concluding with **finalization and inclusion in the snapshot chain**.

At the L1 level, multiple independent layers operate in parallel, each producing blocks that contain transactions relevant to their domain. For example, DAG L1 processes standard network transactions, while Currency L1 handles token-based operations. Validators in each L1 execute transactions, package them into blocks, and submit them to the L0 layer.

Once L1 blocks reach the L0 layer, they undergo validation to ensure correctness and consensus agreement. The Hypergraph’s L0 nodes verify the integrity of these blocks, confirm their inclusion criteria, and aggregate them into a snapshot. Each snapshot contains a finalized record of all validated L1 blocks within that period, along with a Merkle root summarizing the network state.

After validation, the snapshot is proposed to the network for consensus. Once finalized, it is added to the snapshot chain, permanently recording all included transactions and metagraph state updates. This process repeats continuously, allowing the network to progress efficiently without relying on a rigid sequential block structure.

## Snapshot Triggers

Snapshot creation can be triggered in two ways: **on-demand** or at **timed intervals**.

**On-demand snapshots** are triggered whenever new L1 blocks are received by the L0 layer. As soon as enough data is available, the network initiates a round of consensus, ensuring that transactions are processed as quickly as possible. This mechanism allows for rapid state updates and fast transaction finality times.

**Timed snapshots**, on the other hand, are produced at **regular intervals of approximately one minute**, regardless of whether new blocks have been submitted. These timed snapshots serve an additional purpose beyond finalizing transactions—they increment the `epochProgress` value, providing a rough measure of time within the network. This concept of network time is crucial for operations that depend on periodic updates, such as validator reward distribution. Unlike on-demand snapshots, which are created as needed, timed snapshots ensure that certain protocol mechanisms execute at predictable intervals.

## Metagraph Snapshot Lifecycle

Each metagraph follows a similar process to the Hypergraph for state progression. Metagraphs operate their own L1 layers, where transactions specific to that metagraph are processed and finalized into blocks. These blocks are validated by the metagraph’s L0 layer and aggregated into metagraph snapshots.

To ensure security and finality, metagraph snapshots are periodically submitted to the Hypergraph. Once included in a Global Snapshot, they become part of the immutable network history, securing metagraph state alongside Hypergraph state. This hierarchical model allows metagraphs to maintain autonomy while still benefiting from the Hypergraph’s global validation and consensus.


# Network Fees

Constellation Network is designed to support high-throughput, low-cost applications without sacrificing decentralization or security. At the heart of this design is a flexible, modular fee system that allows most users to interact with the network for free while still supporting essential network operations, encouraging responsible usage, and enabling a scalable token economy.

Constellation’s approach to fees is guided by two core principles:

* **Feeless by default**, to reduce friction and support accessibility
* **Fees where needed**, to support network sustainability, security, and performance

This section provides an overview of how network fees function across different layers of the network, including peer-to-peer DAG transactions and metagraph activity.

***

## Why Fees Exist&#x20;

Unlike traditional blockchains that apply flat fees to every transaction, Constellation applies fees only when necessary. Fees serve several critical functions:

* **Security**: They deter abuse by making spam attacks, resource hoarding, or denial-of-service attempts economically unfeasible.
* **Prioritization**: Fees can be optionally included to increase the priority of certain actions, ensuring timely processing in high-demand scenarios.
* **Resource Allocation**: Fees are used to manage storage, computation, and bandwidth in a way that incentivizes efficient use of network resources.
* **Economic Incentives**: Validators and infrastructure providers are rewarded through the redistribution of fees, creating a sustainable incentive model.
* **Network Subsidy**: Low or zero fees act as an intentional subsidy to stimulate adoption and experimentation, particularly in the early phases of network growth.

This model creates a flexible fee economy where light users can interact freely, and heavy users or high-performance applications help fund the system.

***

## L0 Token Transaction Fees&#x20;

DAG and metagraph-hosted L0 tokens support peer-to-peer transactions between wallets on the DAG or Metagraph Currency L1 layer. These transactions are **feeless by default**, meaning users can send and receive tokens without paying a fee in most cases.

However, optional fees can be included in a transaction to:

* Prioritize it for inclusion in the next snapshot
* Trigger parallel consensus
* Bypass rate limits that apply to high-volume or low-balance accounts

This tiered system enables different levels of service based on user needs and prevents network abuse without excluding legitimate use.

#### Example Use Case

If a wallet needs to send hundreds of transactions quickly (e.g., for an airdrop), it can attach a small fee (e.g., 1 datum or more) to each transaction. This ensures priority processing and higher throughput, while ordinary users sending occasional transactions continue to operate for free.

#### Low Balance Rate Limits

To mitigate spam from wallets with negligible balances, a dynamic rate limit is applied to accounts with low DAG holdings. This limit can be bypassed by attaching a small fee (0.002 DAG) to a transaction.

This strategy ensures that wallet spam becomes prohibitively expensive, protecting network performance without disrupting typical usage patterns.

### Custom Metagraph Transaction Fees&#x20;

Each metagraph has the flexibility to define its own **internal fee logic** for transactions and services within its domain. This allows metagraphs to implement business models, incentives, and cost structures tailored to their specific use case—all while staying interoperable with the rest of the network.

#### Data Update Fees

Metagraphs can associate L0 token payments directly with data submissions using the `FeeTransaction` type. This creates a native mechanism for pay-per-use functionality, where users pay for access to specific services, datasets, or on-chain actions.

Key characteristics:

* `FeeTransaction` is cryptographically linked to a data submission but does not include the data itself—preserving user privacy.
* It allows metagraphs to monetize access to data, trigger logic only when payment is received, or implement rate-limiting based on fee volume.
* Transactions can be submitted atomically alongside their associated data updates, ensuring consistency between payment and action.

#### Custom L0 Token Fees

Metagraphs using the Euclid SDK Currency Layer can enforce minimum fee requirements on L0 token transfers. These rules can be based on custom business logic, such as:

* Fixed minimum transfer fees per transaction
* Tiered fees based on token amount or user role
* Dynamic fees based on network activity or metagraph load
* Governance-controlled fee schedules

Because metagraphs control their own business logic, they can determine when and how to charge users for token transfers, staking, or in-app utility—without requiring changes to the global protocol.

***

## Snapshot Fees

While peer-to-peer usage is largely feeless, metagraphs interact with the network in more complex ways. These interactions are subject to required snapshot fees, which are currently the only mandatory fees on the network.

#### Who Pays

Snapshot fees are paid by metagraph operators, not end users. This allows each metagraph to determine how or whether to pass costs along to its users. Projects can cover fees themselves, subsidize usage through staking rewards or grants, or introduce custom fee models at the application level.

#### What Fees Pay For

Snapshot fees support:

* Global consensus validation of metagraph data
* Secure data storage by archive nodes
* Proof-of-record for any data or token activity committed to the Hypergraph

These fees are denominated in DAG and deducted from a designated metagraph fee wallet.

***

### How Snapshot Fees Are Calculated

Snapshot fees are determined by the following formula:

```
Fee = (baseFee × WorkAmount × workMultiplier) + optionalTip
```

#### Key Inputs:

* **WorkAmount**: Reflects both the size (in KB) and computational complexity of the submitted data.
* **WorkMultiplier**: A reduction factor based on the amount of staked DAG and the metagraph’s PRO Score.
* **Optional Tip**: An extra fee a metagraph can include to prioritize its snapshot during network congestion.

Snapshot fees are *fixed*, not market-driven, which ensures predictability and easier budgeting for metagraph projects.

***

### Fee Wallets and Staking

Each metagraph must designate a fee wallet to pay for snapshots and a staking wallet to qualify for reduced fees. Only DAG in the staking wallet counts toward fee reductions—collateral or DAG stored in other wallets does not.

**Staking DAG:**

* Reduces snapshot fees through the `workMultiplier`
* Signals long-term commitment to the network
* Contributes to network security by removing tokens from circulation

Fees can never be reduced to zero, but large staked balances significantly lower operational costs for active metagraphs.

***

## Summary

Constellation Network’s fee model is designed for scale, flexibility, and fairness. Most everyday usage is free or extremely low-cost, while higher-intensity or system-critical operations are funded through proportional fees.

This structure:

* Encourages innovation and accessibility
* Protects the network from misuse
* Supports validator incentives and long-term sustainability
* Enables developers to launch metagraphs with flexible economic models

As the network evolves, fees will remain an essential tool—not just for paying for resources, but for shaping user behavior, securing infrastructure, and growing a healthy, decentralized economy.

{% hint style="info" %}
For more information on network fees and their implementation, see [Network Fees on the Hypergraph](/network-intro/white-papers/network-fees-on-the-hypergraph).&#x20;
{% endhint %}


# Consensus

Constellation Network uses a multi-layer consensus model to securely validate transactions and data across a scalable, modular network. This approach separates local consensus—where transactions are validated at the application or token level—from global consensus, which finalizes those updates and anchors them to the network's canonical state.

Consensus happens in two major phases:

1. **Layer 1 (L1) Consensus** – Validates transactions at the edge (e.g., DAG transfers, metagraph activity)
2. **Layer 0 (L0) Consensus** – Finalizes and records state across the entire network (via metagraph L0 or the Hypergraph)

This layered design enables horizontal scalability, data composability, and robust finality, while still maintaining a unified and trusted ledger.

***

### Layer 1 (L1) Consensus

L1 consensus is the first stage of validation for transactions and data submitted to the network. It takes place independently across three environments:

* **DAG L1** – Validates transactions involving the native DAG token.
* **Metagraph Currency L1** – Validates L0 token transactions received by individual metagraphs.
* **Metagraph Data L1** – Validates application-specific data update transactions.

Each L1 environment is composed of a cluster of validator nodes. These nodes reach consensus on the validity of transactions using a DAG-based graph structure, where each node confirms and references others’ blocks. Consensus at this layer ensures that:

* Transactions are properly formed
* Signatures are valid
* Basic checks (e.g. balance, parent references) pass

Once a sufficient number of nodes agree on a set of validated data, that data is aggregated into a block or snapshot candidate and passed on to the next phase of consensus.

Consensus on L1 layers is parallelized and horizontally scalable, with rounds of consensus taking place across small groups of nodes (e.g., 3 nodes), providing rapid processing and validation of incoming transactions.

***

### Layer 0 (L0) Consensus

L0 consensus is where final agreement and ledger inclusion happen. It exists at two levels:

* **Metagraph L0** – Each metagraph has its own Layer 0 that collects validated L1 transactions into a metagraph snapshot, performs final local checks, and submits it to the global network.
* **Global L0 (Hypergraph)** – This is the shared consensus layer that assembles snapshots from all metagraphs and the DAG L1 into a single global snapshot, which becomes part of the immutable ledger.

Each snapshot submitted to L0 is verified and either accepted or rejected. This final round of validation includes:

* Integrity of the snapshot structure and signatures
* Conformance with snapshot fee requirements
* Final checks on balances and transaction consistency
* Prevention of double spends and other malicious actions

Once approved, snapshots are added to the global snapshot and anchored to the network history.

***

### Validator Participation and Security

Consensus at the global Layer 0 (Hypergraph) is maintained by a set of validator nodes, each of which must stake DAG collateral to participate. This forms the basis of Constellation’s modified proof-of-stake model, where validators are incentivized to behave honestly and maintain network integrity.

Validators participate in consensus by:

* Reviewing proposed snapshots
* Validating their contents
* Signing them for inclusion in the global snapshot

To protect against dishonest behavior:

* Nodes that sign invalid or conflicting data can be slashed, forfeiting their stake
* Validators that fail to meet performance or security standards can be removed from the active set

This staking and slashing model ensures that global consensus remains trust-minimized, economically secure, and decentralized.

***

### PRO Score: Layered Trust and Reputation

In addition to stake-based participation, Constellation uses a reputation system called the **PRO Score** (Proof of Reputable Observation). This system introduces a trust layer on top of the consensus process by tracking and evaluating node behavior over time.

PRO Scores influence how nodes perceive and prioritize the signatures of their peers, especially in situations like:

* Minor forks or network splits
* Competing snapshots or state updates
* Peer selection and gossip propagation

Nodes with higher PRO Scores are considered more reputable and are more likely to be trusted during snapshot formation and conflict resolution. In future releases, PRO Scores will also influence rewards, validator rotation, and staking incentives.

***

### Summary

Consensus in Constellation is layered, with different validation responsibilities assigned to different parts of the network.

| Layer            | Role in Consensus                                                     |
| ---------------- | --------------------------------------------------------------------- |
| **DAG L1**       | Validates native DAG token transactions                               |
| **Metagraph L1** | Validates custom token and data transactions within metagraphs        |
| **Metagraph L0** | Packages L1-validated data into snapshots for global submission       |
| **Global L0**    | Validates and finalizes all snapshots across the network (Hypergraph) |

This layered approach allows for secure and scalable consensus while supporting a wide range of token models, data systems, and applications.


# L0 Token Standard

The L0 Token Standard, also referred to as the Metagraph Token Standard, is Constellation Network’s specification for currency tokens across its modular, multi-layered architecture. It defines a shared interface and core functionality for all value-transferring tokens on the network—spanning both DAG, the native asset of the protocol, and L0 tokens, which are custom tokens issued by metagraphs.

At its core, the L0 Token Standard provides the structural and transactional foundation for interoperability between metagraphs, as well as with external systems such as wallets, exchanges, and APIs. Whether a user is transacting in DAG or an L0 token issued by a metagraph, the experience and underlying mechanics are consistent and composable, allowing for straightforward integration across the ecosystem.

### Key Features

The L0 Token Standard supports a growing set of advanced transaction types, which as of the Tessellation V3 release include:

* **Currency transfers**: Basic send and receive operations between wallets.
* **Delegated spending** (`AllowSpend` and `SpendTransaction`): A two-step authorization model that allows metagraphs or users to act on behalf of another wallet under controlled, pre-approved conditions.
* **Token locking** (`TokenLock`): Mechanisms to temporarily restrict the movement of tokens for staking, governance, or collateral purposes—without transferring custody.
* **Data-associated transactions** (`FeeTransaction`): Transactions that are cryptographically tied to on-chain data updates, supporting pay-per-use models, e-commerce, and auditability.

These capabilities allow tokens to act not just as units of value, but as programmable instruments in dynamic applications, DAOs, and cross-metagraph systems.

### DAG and L0 Token Equivalence

While DAG is the native token of the network and used to pay snapshot fees (the cost to include a transaction in the consensus snapshot), it adheres to the same standard as metagraph-issued L0 tokens. This creates parity between DAG and custom tokens from a functional standpoint, ensuring that tools like wallets and explorers can treat them uniformly while maintaining DAG’s special utility role at the protocol level.

### Automatic Adoption via Euclid SDK

Any metagraph that implements the Euclid SDK’s currency layer automatically inherits the full capabilities of the L0 Token Standard. This ensures that developers building on Constellation don’t have to reimplement token logic or manage interoperability on their own—these features are built into the framework.

The L0 Token Standard is the connective tissue of Constellation Network’s currency layer, enabling composability, utility, and programmability across an evolving ecosystem of interoperable metagraphs.


# Advanced Token Functionality

Constellation Network’s token model goes beyond simple value transfer by enabling a set of advanced token features that support staking, delegation, fee logic, and smart interactions between wallets, metagraphs, and the Hypergraph. These capabilities are available to both the native DAG token and any L0 token implemented using the Euclid SDK’s Currency L1 module.

### Delegated Spending

One of the most powerful tools in Constellation’s token system is the **delegated spending mechanism**, made possible through the `AllowSpend` and `SpendTransaction` types. These allow a wallet to pre-authorize another entity—such as a metagraph or another user—to spend a specific amount of tokens on its behalf, under certain conditions.

AllowSpends are **single-use and time-limited**, providing a safe and controlled alternative to open-ended token approvals common in other ecosystems. This enables use cases such as:

* Atomic token swaps between parties or metagraphs
* Auction or bidding systems
* Metagraph-managed multi-sig wallets
* E-commerce workflows with conditional payment fulfillment

SpendTransactions are submitted by the delegate (typically a metagraph) once the specified conditions are met, consuming the AllowSpend and triggering the associated transfer.

### Token Locking

The network supports **locking tokens** via `TokenLock` transactions, which remove funds from a wallet’s spendable balance for a defined duration or until a specific unlocking condition is met. Locked tokens remain tied to the wallet and cannot be transferred, adding security without moving tokens into a third-party contract.

Token locking is used for:

* Node collateral staking
* Delegated staking participation
* Governance requirements
* Time-based vesting or escrow models

Locks can be unlocked automatically based on duration or manually by the metagraph or Hypergraph when conditions are met. All unlocks are recorded on-chain via `TokenUnlock` system transactions.

### FeeTransactions

FeeTransactions are a special transaction type used to associate a payment with a piece of custom data submitted to a metagraph. When a user sends an application-specific DataUpdate (such as a document, event, or sensor reading), they include a FeeTransaction alongside it. This transaction contains:

* A payment amount in the metagraph’s L0 token
* A hash reference to the associated data
* A signature from the sender’s wallet

This structure allows metagraphs to enforce pay-per-update models while maintaining data privacy and minimizing on-chain storage. FeeTransactions are essential for use cases where data ingestion, validation, or storage is tied to verifiable utility and compensation.

### Custom Transfer Fees

Metagraphs can also define **custom fee logic for L0 token transfers** on their Currency L1 layer. Unlike FeeTransactions, which pair with data, these fees apply to standard token transfers and can be customized to fit a metagraph’s specific business model.

Using the Euclid SDK, developers can implement:

* Flat or percentage-based transfer fees
* Fee exemptions for specific addresses
* Dynamic fees based on transfer size or other logic

This gives each metagraph the flexibility to define how value flows through their ecosystem, enabling sustainable and purposeful token economies that align with the goals of the project.

***

These advanced features allow developers to design flexible, expressive token economies without deploying external smart contracts or exposing users to unnecessary risk. Together, they form the foundation for secure, utility-driven systems that can scale across use cases—from DeFi to enterprise operations and beyond.


# Transaction Type Reference

{% hint style="info" %}
For more information on how to send transactions, see the network [API docs](/network-apis).&#x20;
{% endhint %}

The following global transaction types are supported across the network.&#x20;

***

## **Transaction Types**

### **DAG Transaction**

A **standard currency transaction** that transfers **DAG tokens** between two addresses.

| Property            | Value         |
| ------------------- | ------------- |
| **Receiving Layer** | DAG L1        |
| **Signed By**       | Source wallet |
| **Fee**             | Paid in DAG   |

#### **Transaction Fields**

| Field           | Description                                                                                                                                         |
| --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| **source**      | The wallet address initiating the transaction.                                                                                                      |
| **destination** | The wallet address receiving DAG.                                                                                                                   |
| **amount**      | The number of DAG tokens being transferred.                                                                                                         |
| **fee**         | The transaction fee in DAG.                                                                                                                         |
| **salt**        | A random value to guarantee uniqueness on the network.                                                                                              |
| **parent**      | A reference to the previous transaction hash and network accepted ordinal. Creates a transaction chain for each address, preventing replay attacks. |

#### **Example**

```json
{
  "value": {
    "source": "DAG1xyz...",
    "destination": "DAG1abc...",
    "amount": 10050000000,
    "fee": 0.01,
    "salt": 465498,
    "parent": {
      "ordinal": 12345,
      "hash": "fbff1127273..."
    }
  }
  "proofs": [{
    "id": "f27242529710fd8...",
    "signature": "f0sdfa32f2f2..."
  }
}
```

***

### **L0 Token Transaction**

A **standard transaction** for transferring **L0 tokens** within a **metagraph’s currency layer**.

| Property            | Value                 |
| ------------------- | --------------------- |
| **Receiving Layer** | Metagraph Currency L1 |
| **Signed By**       | Source wallet         |
| **Fee**             | Paid in L0 Token      |

#### **Transaction Fields**

Same as **DAG Transaction**, but **amount and fee are denominated in L0 tokens**.

***

### **AllowSpend**

A **delegation transaction** that **pre-approves spending** on behalf of the sender.

| Property            | Value                                              |
| ------------------- | -------------------------------------------------- |
| **Receiving Layer** | DAG L1 or Metagraph Currency L1                    |
| **Signed By**       | Source wallet                                      |
| **Fee**             | Paid in DAG or L0 Token (based on receiving layer) |
| **Expiration**      | Maximum **1 hour (83 epochs)**                     |

#### **Transaction Fields**

| Field                      | Description                                                                                                                                                 |
| -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **source**                 | The address granting permission to spend up to the amount.                                                                                                  |
| **destination**            | The wallet address receiving the funds.                                                                                                                     |
| **currency**               | The metagraph ID for an L0 token or null for DAG.                                                                                                           |
| **amount**                 | Maximum amount that can be spent with an associated `SpendTransaction` in datum.                                                                            |
| **fee**                    | Optional fee for the transaction.                                                                                                                           |
| **lastValidEpochProgress** | The expiration of the `AllowSpend` in terms of network epochProgress value.                                                                                 |
| **approvers**              | A list of addresses that must approve the transaction in order to issue an `AllowSpend` against it. Currently limited to a single approver per transaction. |
| **parent**                 | A reference to the previous `AllowSpend` hash and network accepted ordinal for the source address. Prevents replay attacks.                                 |

#### **Example**

```json
{
  "value": {
    "source": "DAG1xyz...",
    "destination": "DAG1abc...",
    "currency": "DAGzzz123...",
    "amount": 5000000000,
    "fee": 0,
    "lastValidEpochProgress": 999,
    "approvers": ["DAG1abc..."]
    "parent": {
      "ordinal": 123,
      "hash": "fbff112..."
    }
  },
  "proofs": [{
    "id": "f27242529710fd8...",
    "signature": "f0sdfa32f2f2..."
  }]
}
```

***

### **SpendTransaction**

A **metagraph-generated transaction** that either:

1. Uses an **AllowSpend** to execute a transfer, or
2. Moves funds from a **metagraph-owned wallet**.

If an AllowSpend is referenced, the SpendTransaction can spend up to the `amount` of the AllowSpend, or less. Once an AllowSpend is referenced in an accepted SpendTransaction, the AllowSpend lock is released and the transaction cannot be used again for a future SpendTransaction.&#x20;

| Property            | Value                                         |
| ------------------- | --------------------------------------------- |
| **Receiving Layer** | Submitted by metagraph to Global L0           |
| **Signed By**       | Included in **metagraph's currency snapshot** |
| **Fee**             | None                                          |

#### **Transaction Fields**

| Field             | Description                                                        |
| ----------------- | ------------------------------------------------------------------ |
| **allowSpendRef** | (Optional) The hash of the `AllowSpend` being used.                |
| **source**        | The executing wallet matching `AllowSpend` source or metagraph ID. |
| **destination**   | The destination wallet for the funds.                              |
| **currency**      | The metagraph ID for an L0 token or null for DAG.                  |
| **amount**        | The amount being transferred.                                      |

#### **Example**

```json
{
  "value": {
    "allowSpendRef": "f2n2390l232...",  // or null for metagraph wallet txns
    "source": "DAG1xyz...", 
    "destination": "DAG1abc..."
    "currency": "DAGzzz123...",
    "amount": 3000000000
  },
  "proofs": [{
    "id": "f27242529710fd8...",
    "signature": "f0sdfa32f2f2..."
  }]
}
```

***

### **FeeTransaction**

A **transaction associated with submitting data** to a metagraph’s Data L1.

| Property            | Value                                                                 |
| ------------------- | --------------------------------------------------------------------- |
| **Receiving Layer** | Metagraph Data L1                                                     |
| **Signed By**       | Source wallet                                                         |
| **Fee**             | There is no fee for the transaction since it represents a fee itself. |

#### **Transaction Fields**

| Field             | Description                                                                        |
| ----------------- | ---------------------------------------------------------------------------------- |
| **source**        | The wallet address initiating the transaction.                                     |
| **destination**   | The wallet address receiving the transaction.                                      |
| **amount**        | The amount of the transaction, denoted in the L0 token of the receiving metagraph. |
| **dataUpdateRef** | The hash of the associated data update.                                            |

#### **Example**

```json
{
  "data": {
    // metagraph-defined custom data type
  },
  "fee":{
    "value": {
      "source": "DAG1xyz...", 
      "destination": "DAG1abc..."
      "amount": 10,
      "dataUpdateRef": "0227488ede0..."
    },
    "proofs": [{
      "id": "f27242529710fd8...",
      "signature": "f0sdfa32f2f2..."
    }]
  }
}
```

***

### **TokenLock**

Locks funds for a specified duration or indefinitely. Locked funds are deducted from a wallet's balance for the duration of the lock but are never transferred from the wallet.&#x20;

| Property      | Value                           |
| ------------- | ------------------------------- |
| **Layer**     | DAG L1 or Metagraph Currency L1 |
| **Signed By** | Source wallet                   |
| **Fee**       | Paid in DAG or L0 Token         |

#### **Transaction Fields**

| Field           | Description                                                                                                                |
| --------------- | -------------------------------------------------------------------------------------------------------------------------- |
| **source**      | The wallet address initiating the transaction                                                                              |
| **amount**      | The balance to lock                                                                                                        |
| **fee**         | Optional fee for the transaction.                                                                                          |
| **currencyId**  | The metagraph ID for an L0 token or null for DAG.                                                                          |
| **unlockEpoch** | The global epochProgress value that this lock will be released by the network. This field is null for indefinite locks.    |
| **parent**      | A reference to the previous `TokenLock` hash and network accepted ordinal for the source address. Prevents replay attacks. |

#### **Example**

```json
{
  "value": {
    "source": "DAG1xyz...", 
    "amount": 10,
    "fee": 0:,
    "currencyId": "DAGzzz123..."
    "unlockEpoch": 999232,
    "parent": {
      "ordinal": 123,
      "hash": "fbff112..."
    }
  },
  "proofs": [{
    "id": "f27242529710fd8...",
    "signature": "f0sdfa32f2f2..."
  }]
}
```

***

### **TokenUnlock**

A **system-generated transaction** that **unlocks previously locked tokens**. **TokenUnlock** transactions can be created by metagraphs (L0 tokens) and the global L0 (DAG) to unlock a **TokenLock** before its `unlockEpoch`, or to unlock a **TokenLock** with no `unlockEpoch`. This transaction type is also emitted when a TokenLock has reached its `unlockEpoch`.&#x20;

| Property            | Value                                                                         |
| ------------------- | ----------------------------------------------------------------------------- |
| **Receiving Layer** | Global L0 or Metagraph L0                                                     |
| **Signed By**       | Included in a signed metagraph snapshot (L0 tokens) or global snapshot (DAG). |
| **Fee**             | None                                                                          |

#### **Transaction Fields**

| Field          | Description                                       |
| -------------- | ------------------------------------------------- |
| **source**     | The wallet address initiating the transaction     |
| **amount**     | The balance to lock                               |
| **currencyId** | The metagraph ID for an L0 token or null for DAG. |

#### **Example**

```json
{
  "value": {
    "source": "fbff112...", 
    "amount": 10,
    "currencyId": "DAGzzz123..."
  },
  "proofs": [{
    "id": "f27242529710fd8...",
    "signature": "f0sdfa32f2f2..."
  }]
}
```

***

### **AllowSpendExpiration**

A **system-generated transaction** that marks an **expired AllowSpend**.

| Property            | Value                                                                  |
| ------------------- | ---------------------------------------------------------------------- |
| **Receiving Layer** | Global L0 or Metagraph L0                                              |
| **Signed By**       | Included in a metagraph snapshot (L0 tokens) or global snapshot (DAG). |
| **Fee**             | None                                                                   |

#### **Transaction Fields**

| Field             | Description                           |
| ----------------- | ------------------------------------- |
| **allowSpendRef** | The hash of the associated AllowSpend |

#### **Example**

```json
{
  "value": {
    "allowSpendRef": "fbff112..."
  },
  "proofs": [{
    "id": "f27242529710fd8...",
    "signature": "f0sdfa32f2f2..."
  }]
}
```

***

### UpdateDelegatedStake

A user-generated transaction to create or update a delegated stake position. A delegated staking position is comprised of two parts:

* A TokenLock with an indefinite expiration
* An UpdateDelegatedStake transaction referencing the TokenLock

This transaction can be used to update an existing delegated stake position without requiring a withdrawal first. The updated delegated stake transaction will have all the same details as the original, except with a different nodeId referenced.&#x20;

| Property      | Value         |
| ------------- | ------------- |
| **Layer**     | Global L0     |
| **Signed By** | Source wallet |
| **Fee**       | Paid in DAG   |

#### Transaction Fields

| Field            | Description                                                                                                                           |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| **nodeID**       | The node ID (pub key) of the node to delegate to.                                                                                     |
| **amount**       | The amount to delegate. This must match the `TokenLock` amount.                                                                       |
| **fee**          | An optional fee for the transaction.                                                                                                  |
| **tokenLockRef** | The hash of the `TokenLock` transaction that is being delegated.                                                                      |
| **parent**       | A reference to the previous `UpdateDelegatedStake` hash and network accepted ordinal for the source address. Prevents replay attacks. |

#### **Example**

```json
{
  "value": {
    "nodeId": "e7d04c888...",
    "amount": 90000,
    "fee": 0,
    "tokenLockRef": "0fzz0f23...",
    "parent": {
      "ordinal": 123,
      "hash": "fbff112..."
    }
  },
  "proofs": [{
    "id": "f27242529710fd8...",
    "signature": "f0sdfa32f2f2..."
  }]
}
```

***

### WithdrawDelegatedStake

A user-generated transaction to unwind a delegated staking position. After the WithdrawDelegatedStake transaction is accepted, the associated TokenLock will be unlocked by the network after 21 days (measured by epochProgress).&#x20;

| Property      | Value         |
| ------------- | ------------- |
| **Layer**     | Global L0     |
| **Signed By** | Source wallet |
| **Fee**       | None          |

#### Transaction Fields

| Field        | Description                                                   |
| ------------ | ------------------------------------------------------------- |
| **stakeRef** | The hash of the `UpdateDelegatedStake` transaction to unlock. |

#### **Example**

```json
{
  "value": {
    "stakeRef": "0fzz0f23..."
  },
  "proofs": [{
    "id": "f27242529710fd8...",
    "signature": "f0sdfa32f2f2..."
  }]
}
```

***

### UpdateNodeCollateral

A user-generated transaction to create a node collateral position. A node collateral position is comprised of two parts:

* A TokenLock with an indefinite expiration
* An UpdateNodeCollateral transaction referencing the TokenLock

This transaction can be used to update an existing delegated stake position without requiring a withdrawal first. The updated delegated stake transaction will have all the same details as the original, except with a different nodeId referenced.&#x20;

| Property      | Value         |
| ------------- | ------------- |
| **Layer**     | Global L0     |
| **Signed By** | Source wallet |
| **Fee**       | Paid in DAG   |

#### Transaction Fields

| Field            | Description                                                                                                           |
| ---------------- | --------------------------------------------------------------------------------------------------------------------- |
| **nodeID**       | The node ID (pub key) of the node to delegate to.                                                                     |
| **amount**       | The amount to delegate. This must match the `TokenLock` amount.                                                       |
| **fee**          | An optional fee for the transaction.                                                                                  |
| **tokenLockRef** | The hash of the `TokenLock` transaction that is being delegated.                                                      |
| **parent**       | A reference to the previous Update hash and network accepted ordinal for the source address. Prevents replay attacks. |

#### **Example**

```json
{
  "value": {
    "nodeId": "e7d04c888...",
    "amount": 90000,
    "fee": 0,
    "tokenLockRef": "0fzz0f23...",
    "parent": {
      "ordinal": 123,
      "hash": "fbff112..."
    }
  },
  "proofs": [{
    "id": "f27242529710fd8...",
    "signature": "f0sdfa32f2f2..."
  }]
}
```

***

### WithdrawNodeCollateral

A user-generated transaction to unwind a node collateral position. After the WithdrawNodeCollateral transaction is accepted, the associated TokenLock will be unlocked by the network after 21 days (measured by epochProgress).&#x20;

| Property      | Value         |
| ------------- | ------------- |
| **Layer**     | Global L0     |
| **Signed By** | Source wallet |
| **Fee**       | None          |

#### Transaction Fields

| Field             | Description                                                   |
| ----------------- | ------------------------------------------------------------- |
| **collateralRef** | The hash of the `UpdateNodeCollateral` transaction to unlock. |

#### **Example**

```json
{
  "value": {
    "collateralRef": "0fzz0f23..."
  },
  "proofs": [{
    "id": "f27242529710fd8...",
    "signature": "f0sdfa32f2f2..."
  }]
}
```


# Introduction

Metagraphs are modular, application-specific components of the Constellation Network. Each metagraph operates as an independent subnet with its own state, logic, and validation rules, while anchoring final results to the Hypergraph—the network’s global Layer 0 consensus layer. Metagraphs allow developers to build and deploy their own infrastructure on top of the Constellation protocol, leveraging its consensus and security model while maintaining control over application-level behavior.

A metagraph is composed of one or more **Layer 1 (L1)** components and a single **Layer 0 (L0)** component. Each layer forms a cluster of validator nodes that run consensus and communicate with other layers via signed HTTP requests. The internal architecture of a metagraph determines how it processes transactions and data, how its native token is used, and how it contributes to the global state of the network.

### Use Cases and Applications

Metagraphs are designed to support application-specific logic and infrastructure, making them suitable for a wide variety of use cases that require trusted data processing, verifiable value transfer, or domain-specific rules. Because metagraphs define their own transaction types, token logic, and data validation models, they can be tailored to meet the operational, regulatory, and business needs of specific sectors.

Some common categories of metagraph use include:

* **Digital Asset Infrastructure**: Metagraphs can host their own L0 tokens with custom economic models, fee logic, and staking mechanisms. Projects use metagraphs to issue tokens that support in-app economies, network access rights, or incentivization schemes. Built-in support for features like delegated spending and token locks make them useful for secure, auditable token operations.
* **Verifiable Data Pipelines**: Metagraphs with Data L1 layers can ingest, validate, and notarize structured or semi-structured data. This is particularly useful for use cases that involve compliance, audit trails, or timestamped records—such as law enforcement logs, financial data submissions, healthcare attestations, or supply chain documentation.
* **Public Sector and Critical Infrastructure**: Some metagraphs are built to ingest mission-critical data from public safety or emergency response systems. For example, a metagraph might notarize data streams from field devices, vehicles, or sensors, ensuring that the resulting records are tamper-proof and can be referenced in legal or operational audits.
* **Cross-Network Coordination**: Because all metagraphs anchor their state to the global L0 (Hypergraph), they can coordinate with one another through globally ordered state updates. This makes it possible to build workflows that span multiple metagraphs—for example, a token swap between two projects or a verification system that combines identity credentials with asset ownership data.
* **Enterprise Data Services**: Organizations can use metagraphs to enforce internal rules on how business data is validated, stored, and accessed. This allows enterprises to build blockchain-based backends for analytics, reporting, or service metering—without exposing their full infrastructure to the public network.

Ultimately, metagraphs provide a framework for building verifiable systems where each application defines its own boundaries and logic, while still benefiting from a shared network for consensus and security. As more use cases emerge, metagraph design patterns continue to evolve—ranging from lightweight validators for narrow use cases to complex multi-layered systems with rich token economies and data coordination mechanisms.

### Developing a Metagraph

Developers build metagraphs using the [Euclid SDK](/metagraph-development), a modular framework for defining metagraph behavior. The SDK provides tools for:

* Creating custom token types
* Defining transaction and data validation logic
* Managing metagraph state and snapshot production
* Signing and submitting snapshots to the Hypergraph

Metagraphs are written in Scala and deployed as services that run continuously and participate in consensus. Developers implement one or more node types—L1 L0 nodes—and define the application’s structure through configuration and SDK extension points. Most projects begin by extending the SDK’s base `CurrencyL1App` and `CurrencyL0App` classes and integrating with the provided APIs.

In addition to the core services, metagraph developers often implement external APIs, indexing layers, or front-end applications that interact with the metagraph’s state or trigger transactions.

### Deploying and Running a Metagraph

After development, metagraphs are deployed as independent clusters of validator nodes, typically with three or more nodes per layer. These nodes handle transaction ingestion, consensus, snapshot creation, and submission to the Hypergraph. Developers provision the infrastructure, configure networking and keys, and maintain uptime across the L1 and L0 layers.

Metagraph developers are responsible for managing their network, including:

* Launching and configuring validator clusters
* Monitoring node health and snapshot progress
* Upgrading logic as application needs evolve

The [Euclid SDK](/metagraph-development) provides built-in tools for initializing clusters, coordinating cross-layer communication, and handling common maintenance tasks.

Metagraphs support decentralized opperation by recruiting community node operators. This improves throughput, resilience, and trust by distributing control of the network layers. Token-based incentives or staking models can be used to encourage participation.

As application logic changes over time, developers can deploy new versions of their metagraph software to update token rules, data validation, or fee behavior. These upgrades are handled directly by the metagraph team and don’t require global network coordination.

Overall, metagraphs offer flexible deployment options—from fully internal systems to open, community-driven networks—while maintaining interoperability through the Hypergraph.


# Application-Specific Data

Metagraphs support the ingestion, validation, and on-chain storage of application-specific data types. This data is submitted to the metagraph as **DataUpdates**, which are defined by the metagraph itself. These updates can represent any structured or semi-structured real-world data—from IoT sensor readings and business events to legal records, logs, analytics, or anything else meaningful to the domain the metagraph serves.

Each DataUpdate is a locally-defined transaction submitted to the metagraph’s Data L1 layer. This layer is responsible for parsing and validating the incoming data, enforcing application-specific logic, and participating in graph-based consensus rounds that produce blocks. Once a Data L1 block is finalized, it is sent to the Metagraph L0, where a second layer of validation and finalization takes place. The L0 layer aggregates blocks into a metagraph snapshot, which is the authoritative unit of state for the metagraph and is submitted to the Global L0 (Hypergraph) for final consensus and inclusion in a global snapshot.

### Defining Custom Data Behavior

Metagraph developers define their custom data schema and logic by extending DataApplication in the Metagraph Framework. This allows developers to specify:

* How incoming data should be decoded
* What signature or authentication rules should apply
* Any domain-specific validation logic that determines whether a DataUpdate is accepted or rejected
* How updates should be grouped into blocks
* What data should be added to local, working memory (Calculated State)
* Whether and how data is stored on-chain (e.g., full payloads vs. notarized hashes)

These capabilities make metagraphs highly adaptable to a wide range of use cases. For example:

* A metagraph used in public safety might ingest vehicle telemetry and timestamped incident logs, notarizing them for legal verification.
* A supply chain metagraph might process signed delivery confirmations and proof-of-origin certificates.
* A healthcare metagraph might process encrypted patient records, with selective notarization for audit and compliance.

### Design Considerations and Use Patterns

Because DataUpdates are handled within the metagraph’s own L1 and L0 layers, each metagraph can independently enforce its own trust assumptions, data models, and regulatory constraints—while still anchoring finalized state to the Hypergraph for global ordering and provability.

Developers also have control over how data is stored and queried. Not all data needs to be stored in full on-chain. Many metagraphs choose to store only hashes or references on-chain to preserve privacy or reduce storage costs, while maintaining cryptographic guarantees about the data’s authenticity and timestamp.

Custom data processing on metagraphs can also be linked with **FeeTransactions**, which enable pay-per-update business models. A FeeTransaction contains a cryptographic reference to the data it is associated with, allowing a metagraph to tie utility (data validation and storage) to token-based compensation in a verifiable way.

Metagraphs offer a powerful and flexible environment for building domain-specific data pipelines with on-chain guarantees. The combination of custom logic, horizontal scalability, and Hypergraph anchoring enables developers to build high-integrity, application-specific blockchain systems that are purpose-built for real-world workflows and data integrity requirements.

{% hint style="info" %}
For more detailed information on implementing application-specific data processing on metagraphs, see [Metagraph Framework Data](/metagraph-development/metagraph-framework/data).&#x20;
{% endhint %}


# Tessellation

The [Tessellation project](https://github.com/Constellation-Labs/tessellation) is the core protocol implementation of the Constellation Network. It defines the logic and infrastructure that powers the Hypergraph—the global Layer 0 responsible for consensus, snapshot processing, and coordination across all metagraphs. Tessellation also includes the foundational components needed to build, run, and connect metagraphs to the network.

As the lowest-level implementation of the network, Tessellation acts as the foundation for higher-level tooling, including the [Euclid SDK](/metagraph-development), which simplifies metagraph development. While most developers will interact primarily with Euclid, Tessellation provides the underlying services, protocols, and consensus mechanics that enable scalable, decentralized applications to operate securely on the Constellation Network.


# Scala on Constellation Network

Constellation’s protocol and metagraph development framework are built in **Scala**, a strongly typed, functional-first programming language that provides the precision and modularity needed to build scalable, secure, and reliable decentralized infrastructure.

Scala is used across both the [Tessellation](https://github.com/Constellation-Labs/tessellation) project (which implements the core protocol logic and Layer 0 consensus) and the [Euclid SDK](/metagraph-development) (the developer framework for building metagraphs). This consistent foundation allows developers to reason about code with clarity while leveraging the full power of the underlying platform.

### Why Scala?

Scala offers a unique combination of features that make it particularly well-suited for building a cryptocurrency network:

* **Strong static typing** helps eliminate entire classes of runtime errors and encourages safer, more predictable code.
* **Functional programming constructs**—such as immutability, monads, and pure functions—enable developers to write code that is modular, testable, and easier to reason about in concurrent or distributed environments.
* **Object-oriented capabilities** make it flexible and approachable for teams coming from traditional enterprise backgrounds.
* **Concise, expressive syntax** reduces boilerplate and encourages clean design without sacrificing power or control.

This blend of safety, expressiveness, and functional rigor aligns naturally with the design principles behind Constellation’s architecture: composability, parallelism, and data integrity at scale.

### Ecosystem Interoperability

Scala runs on the **Java Virtual Machine (JVM)** and is fully interoperable with Java and other JVM-based languages. This allows Constellation developers to tap into a mature ecosystem of libraries and tools while writing modern, high-level code. Existing Java libraries can be seamlessly integrated, offering flexibility without compromising on language expressiveness or architectural clarity.

### Further Learning[​](https://docs.constellationnetwork.io/metagraphs/components/tech-stack#further-learning) <a href="#further-learning" id="further-learning"></a>

* [JVM Tutorial - Java Virtual Machine Architecture Explained for Beginners](https://www.freecodecamp.org/news/jvm-tutorial-java-virtual-machine-architecture-explained-for-beginners/)
* [The Scala Programming Language](https://www.scala-lang.org/)
* [Scala Docs](https://docs.scala-lang.org/getting-started/index.html)
* [Scala with Cats](https://typelevel.org/cats/)


# Introduction

The Euclid SDK is a powerful toolkit that provides developers with a comprehensive set of tools to build distributed applications on the Constellation Network.

### Euclid SDK[​](https://docs.constellationnetwork.io/sdk/#euclid-sdk) <a href="#euclid-sdk" id="euclid-sdk"></a>

<figure><img src="/files/oIpKnfzislW9JHhdH9CJ" alt=""><figcaption><p>Euclid SDK</p></figcaption></figure>

Digital ledger technology (DLT) has opened up a world of possibilities for developers who are looking to build decentralized applications. However, building these applications can be a challenging task, and the learning curve can be steep. Additionally, most blockchain development platforms are closed systems that do not allow the introduction of arbitrary code which limits the kind of applications that project teams are able to build.

Euclid offers a more flexible approach to DLT application development that enables application teams to encorporate common libraries into their applications while also allowing for direct customization of the internal processes of their networks. This allows for complete customization of network behavior, including the ability to introduce custom consensus mechanisms, complex arbitrary data types, and associated validation logic. This approach differs significantly from closed systems (ETH, Solana, Hedera) that do not allow this level of customization.

Constellation’s micro-service based architecture allows for highly scalable production applications but also introduces new challenges for local development due to the number of services that need to be developed, deployed, and monitored. This is where the Euclid SDK comes in. It provides developers with a powerful set of tools that simplify the process of building distributed applications on the Constellation Network.

### Purpose[​](https://docs.constellationnetwork.io/sdk/#purpose) <a href="#purpose" id="purpose"></a>

Euclid is designed to simplify Constellation metagraph development. It is currently under active development and provides a set of composable patterns that abstract away the boilerplate code necessary to develop using Tessellation while still allowing developers the freedom to implement their own extensions. This approach allows project teams to get up and running quickly so that they can focus on their own business logic without the restrictions of being locked into a closed development system.

The SDK is designed as an extensible system that supports diverse use cases and allows components to be reused whenever possible. This modular design enables the SDK to support a wide range of use cases, from simple to complex that seamlessly interoperate through the Hypergraph network. It also allows developers to choose which features to include in their metagraph and which to leave out.

### Frameworks[​](https://docs.constellationnetwork.io/sdk/#frameworks) <a href="#frameworks" id="frameworks"></a>

Euclid will include a series of micro-frameworks that are each designed to encapsulate a specific set of functionality for metagraph projects and provide out-of-the-box utility to project teams.

Currently, only a single framework has been released: the Currency Framework. This framework provides developers with a simple way to create and manage a high-throughput digital currency utilizing the Metagraph Token standard. However, Euclid is designed to support a wide range of components that can be used to create complex distributed applications.

Each framework is designed to abstract away the complexity of developing on the Constellation Network while allowing complete customization. This architecture makes it easy for developers to create distributed applications quickly by making use of provided functionality and extending it to fit their individual use cases.

{% hint style="success" %}
**Try our Quick Start Guide**

Ready to start building? Jump ahead to our [Quick Start Guide](/metagraph-development/guides/quick-start).
{% endhint %}


# Toolkit

<table data-view="cards"><thead><tr><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th><th data-hidden data-card-cover data-type="files"></th></tr></thead><tbody><tr><td><strong>Euclid Development Environment</strong></td><td>An upgradable base for launching minimal development environments and developing metagraph projects locally.</td><td><a href="/pages/XkK8quJFy4bxLWjJhXiU">/pages/XkK8quJFy4bxLWjJhXiU</a></td><td></td></tr><tr><td><strong>Hydra CLI</strong></td><td>A powerful command line utility to manage network clusters within the Euclid Development Environment.</td><td><a href="/pages/P4MlMqXgaliJo36S5law">/pages/P4MlMqXgaliJo36S5law</a></td><td></td></tr><tr><td><strong>Developer Dashboard</strong></td><td>A frontend codebase for visual interaction with local development clusters.</td><td><a href="/pages/ijBDM2yTpEUcgfPZf5vK">/pages/ijBDM2yTpEUcgfPZf5vK</a></td><td></td></tr><tr><td><strong>Telemetry Dashboard</strong></td><td>Custom telemetry tooling for monitoring local or deployed metagraph networks.</td><td><a href="/pages/ji1Jyu5fz8rKyzCXSV3z">/pages/ji1Jyu5fz8rKyzCXSV3z</a></td><td></td></tr><tr><td><strong>Metagraph Framework</strong></td><td>A framework for Metagraph development.</td><td><a href="/pages/Ot5HOlokuRUj3dQeoDb2">/pages/Ot5HOlokuRUj3dQeoDb2</a></td><td></td></tr></tbody></table>


# Development Environment

The Euclid Development Environment is an upgradeable project framework to simplify the process of configuring a local development environment for metagraph developers on the Constellation Network.

Getting started with metagraph development can be challenging due to the infrastructure requirements for a minimal development environment. This is a significantly bigger challenge for Constellation Network developers compared to developers on blockchain-based networks due to the inherent complexity of Constellation's microservice-based architecture. The Euclid Development Environment was created to simplify that process as much as possible for metagraph developers, so that developers can focus on building their applications and business logic rather than deploying infrastructure. It includes open source tools that can be used as a starting point for developing more customized tooling specific to your project team’s needs.

## Minimal Development Environment[​](https://docs.constellationnetwork.io/sdk/elements/dev-environment#minimal-development-environment) <a href="#minimal-development-environment" id="minimal-development-environment"></a>

A minimal development environment for the Constellation Network consists of the following components:

* 1 Global L0 node
* 3 Metagraph L0 node
* 3 Metagraph L1 - Currency nodes
* 3 DAG L1 nodes (optional)
* 3 Metagraph L1 - Data nodes (optional)

Note that a cluster of at least three L1 nodes is necessary for the L1 layer to reach consensus (Metagraph L1 - Currency + DAG L1 + Metagraph L1 - Data).

See [Network Architecture](https://docs.constellationnetwork.io/metagraphs/concepts/architecture) for an overview of the role each cluster plays in the Hypergraph.

## System Requirements[​](https://docs.constellationnetwork.io/sdk/elements/dev-environment#system-requirements) <a href="#system-requirements" id="system-requirements"></a>

For local development, it is sufficient to run each necessary node in a Docker container on a single developer machine. The minimal setup requires at least 5 docker containers which can be taxing on system resources. For that reason, we recommend your development machine have a minimum of **16 GB of RAM** with at least **8GB of that RAM allocated to Docker**. We recommend allocating 10GB RAM or more for a smoother development experience if your development machine can support it.

The system requirements for running a Euclid Development Environment project are:

* Linux or macOS operating system
* 16 GB RAM or more
* Docker installed with 8GB RAM allocated to it

## Included Tools[​](https://docs.constellationnetwork.io/sdk/elements/dev-environment#included-tools) <a href="#included-tools" id="included-tools"></a>

The Euclid Development Environment includes the following components:

* The [Hydra CLI](https://docs.constellationnetwork.io/sdk/elements/hydra-cli) tool for building and managing clusters of docker containers for each of the network configurations
* Docker files for building and connecting each of the required local clusters
* A [Telemetry Dashboard](https://docs.constellationnetwork.io/sdk/elements/telemetry-dashboard) consisting of two additional docker containers running Prometheus and Grafana.
* Optionally, run the [Developer Dashboard](/metagraph-development/elements/developer-dashboard), a NextJS frontend javascript app for use during development.

## Install[​](https://docs.constellationnetwork.io/sdk/elements/dev-environment#install) <a href="#install" id="install"></a>

Clone the repo from Github

```
git clone https://github.com/Constellation-Labs/euclid-development-environment.git
cd euclid-development-environment
```

See [Hydra CLI](https://docs.constellationnetwork.io/sdk/elements/hydra-cli) for additional installation and configuration instructions.

## Project Directory Structure[​](https://docs.constellationnetwork.io/sdk/elements/dev-environment#project-directory-structure) <a href="#project-directory-structure" id="project-directory-structure"></a>

The project has the following structure:

```
- infra
- scripts
- source
- euclid.json
```

### Infra[​](https://docs.constellationnetwork.io/sdk/elements/dev-environment#infra) <a href="#infra" id="infra"></a>

This directory contains infrastructure related to the running of Euclid.

* Docker: This directory contains docker configuration, including Dockerfiles, and port, IP, and name configurations for running Euclid locally.
* Ansible: This directory contains Ansible configurations to start your nodes locally and remotely
  * **local**: Used for start and stop the nodes locally.
  * **remote**: Used for configuring and deploying to remote hosts

### Scripts[​](https://docs.constellationnetwork.io/sdk/elements/dev-environment#scripts) <a href="#scripts" id="scripts"></a>

Thats the "home" of hydra script, here you'll find the `hydra` and `hydra-update (deprecated)` scripts.

#### euclid.json[​](https://docs.constellationnetwork.io/sdk/elements/dev-environment#euclidjson) <a href="#euclidjson" id="euclidjson"></a>

Here is the hydra configuration file, there you can set the `p12` file names.

### Source[​](https://docs.constellationnetwork.io/sdk/elements/dev-environment#source) <a href="#source" id="source"></a>

This directory contains your local source code for each project under the `project` directory. These directories will be empty by default, until the project is installed using `hydra install` or `hydra install-template` which will generate these project directories from a template. The files in these directories are automatically included in the metagraph-l0, data-l1, and currency-l1 docker containers when you run `hydra build`.

In this directory inside the `global-l0` subdirectory, you will find the genesis file for your Global L0 network. Updating this file will allow you to attribute DAG token amounts to addresses at the genesis of your network. The source for the Global L0 network is stored in a jar file under `source/docker` since this codebase is not meant to be modified.

Similarly, within the `metagraph-l0` subdirectory, you will find the genesis file for your Currency L0 network. Updating this file will allow you to attribute **metagraph token** amounts to addresses at the genesis of your network.

In the `p12-files` directory, you will find p12 files used in the default node configuration. You may update these files to use your own keys for your nodes. Environment variables in the `euclid.json` file should be updated with the new file aliases and passwords if you do choose to update them.


# Hydra CLI

Hydra CLI is a powerful command line utility designed to manage local development Docker clusters in the Euclid Development Environment. With Hydra CLI, developers can easily create, configure, and manage Constellation Network development clusters for metagraph development.

Hydra CLI is a free and open-source tool that can be easily installed on any operating system that supports bash. Hydra is currently distributed as a part of the [Euclid Development Environment project](https://docs.constellationnetwork.io/sdk/elements/dev-environment) and can be found in the `scripts` directory.

## Install Dependencies[​](https://docs.constellationnetwork.io/sdk/elements/hydra-cli#install-dependencies) <a href="#install-dependencies" id="install-dependencies"></a>

**Argc**

```
cargo install argc
```

Copy

Or you can install the [argc binaries](https://github.com/sigoden/argc/releases) directly.

**Docker**

* [macOS](https://docs.docker.com/desktop/install/mac-install/)
* [linux](https://docs.docker.com/desktop/install/linux-install/)

## Ansible[​](https://docs.constellationnetwork.io/sdk/elements/hydra-cli#ansible) <a href="#ansible" id="ansible"></a>

* Ansible is a configuration tool for configuring and deploying to remote hosts
* [Here](https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html) you can check how to install Ansible

## JQ[​](https://docs.constellationnetwork.io/sdk/elements/hydra-cli#jq) <a href="#jq" id="jq"></a>

* jq is a lightweight and flexible command-line JSON processor. It allows you to manipulate JSON data easily, making it ideal for tasks like querying, filtering, and transforming JSON documents.
* [Here](https://jqlang.github.io/jq/download/) you can check how to install jq

## YQ[​](https://docs.constellationnetwork.io/sdk/elements/hydra-cli#yq) <a href="#yq" id="yq"></a>

* yq is a powerful command-line YAML processor and parser, similar to jq but for YAML data. It allows you to query, filter, and manipulate YAML documents easily from the command line, making it a handy tool for tasks such as extracting specific data, updating YAML files, and formatting output.
* [Here](https://github.com/mikefarah/yq) you can check how to install yq

## Install Project[​](https://docs.constellationnetwork.io/sdk/elements/hydra-cli#install-project) <a href="#install-project" id="install-project"></a>

Run the `install` command which accomplishes two things:

* Creates templated currency starter projects for L0 and L1 Currency apps in the `source/` directory.
* Removes the project's git configuration so that you're free to check your changes into your own repo. Further infrastructure upgrades can be handled through Hydra.

```
scripts/hydra install
```

You can import a metagraph template from custom examples by using the following command:

```
scripts/hydra install-template
```

By default, we use the [Metagraph Examples](https://github.com/Constellation-Labs/metagraph-examples) repository. You should provide the template name when running this command. To list the templates available to install, type:

```
scripts/hydra install-template --list
```

## Build[​](https://docs.constellationnetwork.io/sdk/elements/hydra-cli#build) <a href="#build" id="build"></a>

Build using the Hydra CLI. This will build a minimal development environment for your project using Docker.

```
scripts/hydra build
```

## Usage[​](https://docs.constellationnetwork.io/sdk/elements/hydra-cli#usage) <a href="#usage" id="usage"></a>

The primary purpose of Hydra is to manage local deployment and configuration of development clusters for developing metagraph projects. Running all the necessary network clusters for development can be quite complex to do from scratch, so Hydra aims to simplify that process.

See [Network Architecture](https://docs.constellationnetwork.io/metagraphs/concepts/architecture) for an overview of the role each cluster plays in the Hypergraph.

Hydra uses Docker to launch minimal development clusters for the following supported networks:

* Global L0
* Currency L0
* Currency L1
* DAG L1

It also includes a pair of monitoring containers supporting:

* Prometheus
* Grafana

### Building[​](https://docs.constellationnetwork.io/sdk/elements/hydra-cli#building) <a href="#building" id="building"></a>

Build the default clusters (Global L0, Currency L0, Currency L1, Monitoring)

```
scripts/hydra build
```

To include the DAG L1 network, you can add `dag-l1` to the `layers` field on `euclid.json`. This option is disabled by default because it is not strictly necessary for metagraph development.

### Destroying[​](https://docs.constellationnetwork.io/sdk/elements/hydra-cli#destroying) <a href="#destroying" id="destroying"></a>

Built containers can be destroyed with the `destroy` command

```
scripts/hydra destroy
```

### Starting[​](https://docs.constellationnetwork.io/sdk/elements/hydra-cli#starting) <a href="#starting" id="starting"></a>

Run your built clusters with the `start-genesis` and `start-rollback` commands.

```
scripts/hydra start-genesis
```

```
scripts/hydra start-rollback
```

### Stopping[​](https://docs.constellationnetwork.io/sdk/elements/hydra-cli#stopping) <a href="#stopping" id="stopping"></a>

Stop running containers with the `stop` command.

```
scripts/hydra stop
```

### Check Status[​](https://docs.constellationnetwork.io/sdk/elements/hydra-cli#check-status) <a href="#check-status" id="check-status"></a>

Check the status of all running containers.

```
scripts/hydra status
```

## Deployment[​](https://docs.constellationnetwork.io/sdk/elements/hydra-cli#deployment) <a href="#deployment" id="deployment"></a>

Configuring, deploying, and starting remote node instances is supported through Ansible playbooks. The default settings deploy to three node instances via SSH which host all layers of your metagraph project (gL0, mL0, cL1, dL1). Two hydra methods are available to help with the deployment process: `hydra remote-deploy` and `hydra remote-start`. Prior to running these methods, remote host information must be configured in `infra/ansible/remote/hosts.ansible.yml`.

By default, we use the default directory for the SSH file, which is `~/.ssh/id_rsa`. However, you can change it to your preferred SSH file directory. You can find instructions on how to generate your SSH file [here](https://git-scm.com/book/en/v2/Git-on-the-Server-Generating-Your-SSH-Public-Key).

Ansible functions more effectively with `.pem` key files. If you possess a `.ppk` key file, you can utilize [these instructions](https://tecadmin.net/convert-ppk-to-pem-using-command/) to convert it to `.pem`.

If your file contains a password, you will be prompted to enter it to proceed with remote operations.

### Host Configuration[​](https://docs.constellationnetwork.io/sdk/elements/hydra-cli#host-configuration) <a href="#host-configuration" id="host-configuration"></a>

To run your metagraph remotely, you'll need remote server instances - 3 instances for the default configuration. These hosts should be running either `ubuntu-20.04` or `ubuntu-22.04`. It's recommended that each host meets the following minimum requirements:

* 16GB of RAM
* 8vCPU
* 160GB of storage

You can choose your preferred platform for hosting your instances, such as AWS or DigitalOcean. After creating your hosts, you'll need to provide the following information in the `hosts.ansible.yml` file:

* Host IP
* Host user
* Host SSH key (optional if your default SSH token already has access to the remote host)

### P12 Files[​](https://docs.constellationnetwork.io/sdk/elements/hydra-cli#p12-files) <a href="#p12-files" id="p12-files"></a>

P12 files contain the public/private key pair identifying each node (peerID) and should be located in the `source/p12-files` directory by default. The `file-name`, `key-alias`, and `password` should be specified in the `euclid.json` file under the `p12_files` section. By default, Euclid comes with three example files: `token-key.p12`, `token-key-1.p12`, and `token-key-2.p12`. **NOTE:** Before deploying, be sure to replace these example files with your own, as these files are public and their credentials are shared.

**NOTE:** If deploying to MainNet, ensure that your peerIDs are registered and present on the metagraph seedlist. Otherwise, the metagraph startup will fail because the network will reject the snapshots.

### Network Selection[​](https://docs.constellationnetwork.io/sdk/elements/hydra-cli#network-selection) <a href="#network-selection" id="network-selection"></a>

Currently, there are two networks available for running your metagraph: `IntegrationNet`, and `MainNet`. You need to specify the network on which your metagraph will run in the `euclid.json` file under `deploy -> network -> name`.

### GL0 Node Configuration[​](https://docs.constellationnetwork.io/sdk/elements/hydra-cli#gl0-node-configuration) <a href="#gl0-node-configuration" id="gl0-node-configuration"></a>

The deploy script does not deploy the `gl0` node. It's recommended to use `nodectl` to build your `gl0` node. Information on installing `nodectl` can be found [here](https://docs.constellationnetwork.io/validate/automated/nodectl). `Nodectl` helps manage `gl0` nodes by providing tools such as `auto-upgrade` and `auto-restart` which keep the node online in the case of a disconnection or network upgrade. Using these features is highly recommended for the stability of your metagraph.

**NOTE:** Your GL0 node must be up and running before deploying your metagraph. You can use the same host to run all four layers: `gl0`, `ml0`, `cl1`, and `dl1`.

#### `hydra remote-deploy`[​](https://docs.constellationnetwork.io/sdk/elements/hydra-cli#hydra-remote-deploy) <a href="#hydra-remote-deploy" id="hydra-remote-deploy"></a>

This method configures remote instances with all the necessary dependencies to run a metagraph, including Java, Scala, and required build tools. The Ansible playbook used for this process can be found and edited in `infra/ansible/playbooks/deploy.ansible.yml`. It also creates all required directories on the remote hosts, and creates or updates metagraph files to match your local Euclid environment. Specifically, it creates the following directories:

* `code/global-l0`
* `code/metagraph-l0`
* `code/currency-l1`
* `code/data-l1`

Each directory will be created with `cl-keytool.jar`, `cl-wallet.jar`, and a P12 file for the instance. Additionally, they contain the following:

**In `code/metagraph-l0`:**

* metagraph-l0.jar // The executable for the mL0 layer
* genesis.csv // The initial token balance allocations
* genesis.snapshot // The genesis snapshot created locally
* genesis.address // The metagraph address created in the genesis snapshot

**In `code/currency-l1`:**

* currency-l1.jar // The executable for the cL1 layer

**In `code/data-l1`:**

* data-l1.jar // The executable for the dL1 layer

#### `hydra remote-start`[​](https://docs.constellationnetwork.io/sdk/elements/hydra-cli#hydra-remote-start) <a href="#hydra-remote-start" id="hydra-remote-start"></a>

This method initiates the remote startup of your metagraph in one of the available networks: integrationnet or mainnet. The network should be set in `euclid.json` under `deploy` -> `network`

To begin the remote startup of the metagraph, we utilize the parameters configured in euclid.json (`network`, `gl0_node -> ip`, `gl0_node -> id`, `gl0_node -> public_port`, `ansible -> hosts`, and `ansible -> playbooks -> start`). The startup process unfolds as follows:

1. Termination of any processes currently running on the metagraph ports, which by default are 7000 for ml0, 8000 for cl1, and 9000 for dl1 (you can change on `hosts.ansible.yml`).
2. Relocation of any existing logs to a folder named `archived-logs`, residing within each layer directory: `metagraph-l0`, `currency-l1`, and `data-l1`.
3. Initiation of the `metagraph-l0` layer, with `node-1` designated as the genesis node.
4. Initial startup as `genesis`, transitioning to `rollback` for subsequent executions. To force a genesis startup, utilize the `--force_genesis` flag with the `hydra remote-start` command. This will move the current `data` directory to a folder named `archived-data` and restart the metagraph from the first snapshot.
5. Detection of missing files required for layer execution, such as `:your_file.p12` and `metagraph-l0.jar`, triggering an error and halting execution.
6. Following the initiation of `metagraph-l0`, the l1 layers, namely `currency-l1` and `data-l1`, are started. These layers only started if present in your project.

After the script completes execution, you can verify if your metagraph is generating snapshots by checking the block explorer of the selected network:

* Integrationnet: <https://be-integrationnet.constellationnetwork.io/currency/:your_metagraph_id/snapshots/latest>
* Mainnet: <https://be-mainnet.constellationnetwork.io/currency/:your_metagraph_id/snapshots/latest>

You can verify if the cluster was successfully built by accessing the following URL:

`http://{your_host_ip}:{your_layer_port}/cluster/info`

Replace:

* `{your_host_ip}`: Provide your host's IP address.
* `{your_layer_port}`: Enter the public port you assigned to each layer.

Each layer directory on every node contains a folder named `logs`. You can monitor and track your metagraph logs by running:

`tail -f logs/app.log`

**NOTE:** Don't forget to add your hosts' information, such as host, user, and SSH key file, to your `infra/ansible/remote/hosts.ansible.yml` file.

#### `hydra remote-status`[​](https://docs.constellationnetwork.io/sdk/elements/hydra-cli#hydra-remote-status) <a href="#hydra-remote-status" id="hydra-remote-status"></a>

This method will return the status of your remote hosts. You should see the following:

```
################################## Node 1 ##################################
Metagraph L0
URL: http://:your_node_ip:your_port/node/info
State: :state
Host: :host
Public port: :your_port
P2P port: :your_port
Peer id: :peerId

Currency L1
URL: http://:your_node_ip:your_port/node/info
State: :state
Host: :host
Public port: :your_port
P2P port: :your_port
Peer id: :peerId

Data L1
URL: http://:your_node_ip:your_port/node/info
State: :state
Host: :host
Public port: :your_port
P2P port: :your_port
Peer id: :peerId


################################## Node 2 ##################################
Metagraph L0
URL: http://:your_node_ip:your_port/node/info
State: :state
Host: :host
Public port: :your_port
P2P port: :your_port
Peer id: :peerId

Currency L1
URL: http://:your_node_ip:your_port/node/info
State: :state
Host: :host
Public port: :your_port
P2P port: :your_port
Peer id: :peerId

Data L1
URL: http://:your_node_ip:your_port/node/info
State: :state
Host: :host
Public port: :your_port
P2P port: :your_port
Peer id: :peerId


################################## Node 3 ##################################
Metagraph L0
URL: http://:your_node_ip:your_port/node/info
State: :state
Host: :host
Public port: :your_port
P2P port: :your_port
Peer id: :peerId

Currency L1
URL: http://:your_node_ip:your_port/node/info
State: :state
Host: :host
Public port: :your_port
P2P port: :your_port
Peer id: :peerId

Data L1
URL: http://:your_node_ip:your_port/node/info
State: :state
Host: :host
Public port: :your_port
P2P port: :your_port
Peer id: :peerId
```


# Developer Dashboard

<figure><img src="/files/EBA9uM9vFJ6lUPDiCjmA" alt=""><figcaption><p>Developer Dashboard</p></figcaption></figure>

The Euclid Developer Dashboard is a tool crafted specifically for developers working with the Constellation ecosystem. The dashboard presents a unified view of the status of local and deployed clusters, allowing developers to easily monitor their projects' progress and the flow of data between network layers.

Engineered to seamlessly integrate with the Euclid Development Environment, the dashboard serves as an excellent starting point for constructing bespoke developer tools tailored to the unique requirements of your project. Developed using NextJS and Tailwind CSS, the codebase promotes rapid development, ensuring a smooth and efficient workflow for developers. Regardless of whether you're working on a small-scale project or building a sophisticated application, this dashboard helps you stay informed about your project's status while also laying the groundwork for the creation of additional tools designed to optimize your development process.

## Setup[​](https://docs.constellationnetwork.io/sdk/elements/developer-dashboard#setup) <a href="#setup" id="setup"></a>

Clone the project from Github

```
git clone https://github.com/Constellation-Labs/sdk-developer-dashboard.git
cd sdk-developer-dashboard
```

Install dependencies

```
npm install
```

Run the project

```
npm run dev
```

Open a browser and navigate to

```
http://localhost:8080
```

## Configuration[​](https://docs.constellationnetwork.io/sdk/elements/developer-dashboard#configuration) <a href="#configuration" id="configuration"></a>

The `.env` file in the root of the project contains defaults that work with the Euclid Development Environment out of the box but you can edit the defaults to match your desired configuration.

```
L0_GLOBAL_URL=http://localhost:9000
L0_CURRENCY_URL=http://localhost:9200
L1_CURRENCY_URL=http://localhost:9300
```


# Telemetry Dashboard

<figure><img src="/files/6LiX2OWA8DOUPERucUQK" alt=""><figcaption></figcaption></figure>

The Telemetry Dashboard is an essential tool provided as part of the SDK to allow project teams to monitor network health for metagraph development. It consists of dashboard templates to track global network health (Global L0 and DAG L1) and local metagraph health (Currency L0 and Currency L1). The Telemetry Dashboard is built on a [Grafana](https://docs.constellationnetwork.io/sdk/elements/\[https://grafana.com/]\(https://grafana.com/\)) instance using data collected from the network via [Prometheus](https://docs.constellationnetwork.io/sdk/elements/\[https://prometheus.io/]\(https://prometheus.io/\)).

The dashboard provides a visual representation of network health and helps developers to quickly identify any issues or bottlenecks in the system. By monitoring key metrics such as consensus duration, gossip round frequency, and transaction throughput, developers can make informed decisions about how to optimize their metagraphs networks and improve overall performance.

## Installation[​](https://docs.constellationnetwork.io/sdk/elements/telemetry-dashboard#installation) <a href="#installation" id="installation"></a>

The Telemetry dashboard is included as part of the Euclid Development Environment. Once the framework is installed, it can be started with Hydra. To start the dashboard, ensure that the `start_grafana_container` option is enabled in `euclid.json`:

```
...
  "docker": {
    "start_grafana_container": true
  }
...
```

Then, you can initiate the system from genesis with the following command:

```
scripts/hydra start-genesis
```

Alternatively, to start from a rollback, execute:

```
scripts/hydra start-rollback
```

By default, Grafana runs on port 3000 and can be accessed at the following url

```
http://localhost:3000
```

## Setup[​](https://docs.constellationnetwork.io/sdk/elements/telemetry-dashboard#setup) <a href="#setup" id="setup"></a>

The default username and password both “admin”.

![Grafana Login](https://docs.constellationnetwork.io/assets/images/grafana-login-1fa3cbb50291390e8c21590b6db622de.png)

## Dashboards[​](https://docs.constellationnetwork.io/sdk/elements/telemetry-dashboard#dashboards) <a href="#dashboards" id="dashboards"></a>

You can find the default dashboards in the “Dashboards” section on the left menu.

![Grafana Dashboards](https://docs.constellationnetwork.io/assets/images/grafana-dashboards-94849c832ea4ef378b8579f88855edb6.png)

**By default, the following templates are included:**

* Global Layer dashboard - Information about the Global L0 and DAG L1 networks.
* Currency Layer dashboard - Information about the Currency L0 and Currency L1 networks.


# Metagraph Monitoring Service

We have introduced a monitoring tool in version `v0.10.0` of the [Euclid Development Environment project](/metagraph-development/elements/development-environment) that can assess the health of your metagraph and initiate restarts if necessary.

A healthy metagraph requires a minimum of three nodes per layer: `metagraph-l0`, `currency-l1`, and `data-l1`. The `currency-l1` and `data-l1` layers should be implemented if your metagraph requires these layers, but at least three nodes per layer are necessary for correct operation.

Sometimes, your node can be unhealthy for several reasons, as examples:

* The remote host becoming stuck in a process.
* The remote host shutting down unexpectedly.
* The node experiencing a fork.
* The metagraph sending snapshots to a node that subsequently becomes unhealthy.

Each of these conditions may require attention and, in some cases, intervention, such as a restart.

For example, consider a scenario where your metagraph is operating normally but sends a `MetagraphSnapshot` to a `global-l0` node that has forked on the network. If this node is not part of the main and valid fork, your `MetagraphSnapshot` will never reach the `global-l0` layer. The monitoring service will detect this issue and automatically trigger a metagraph restart.

In another scenario, if the `currency-l1` process stops on one of your nodes, the monitoring service will detect this anomaly and initiate a restart for the affected node on that layer.

### Introduction[​](https://docs.constellationnetwork.io/sdk/elements/monitoring-service#introduction) <a href="#introduction" id="introduction"></a>

The service is developed using `NodeJS`, and all necessary dependencies are installed on your remote instance during deployment.

Running in the background with PM2, the service initiates checks at intervals specified in the configuration under the field: `check_healthy_interval_in_minutes`. It evaluates the health of the metagraph based on predefined and customizable `restart-conditions`, detailed in the [metagraph-monitoring-service](https://github.com/Constellation-Labs/metagraph-monitoring-service) repository. For example, if an unhealthy node is detected, the service triggers a restart.

The service runs health checks on a regular interval and evaluates the metagraph cluster on a set of predefined or developer-created health criteria (restart-conditions). Restart conditions can target the whole cluster, a specific layer, or individual nodes to ensure that the metagraph is operating properly in each case. If an issue is detected, the service uses SSH to access the impacted node(s) and restart their process and rejoin them to the network.

### Installation[​](https://docs.constellationnetwork.io/sdk/elements/monitoring-service#installation) <a href="#installation" id="installation"></a>

This tool does not ship by default with Euclid, so it must be installed before use. To install within a Euclid project, run the following:

`hydra install-monitoring-service`

this command to creates a monitoring project in your source directory, which will be named `metagraph-monitoring-service`

To use this feature, information about the remote hosts to be monitored must be configured in the `infra/ansible/remote/hosts.ansible.yml` file under the monitoring section. The monitoring service must have SSH access to the other nodes with a user with sudo privileges without requiring a password. Refer to [this document](https://gcore.com/learning/how-to-disable-password-for-sudo-command/) to learn how to enable password-less sudo for a user.

### Monitoring Configuration[​](https://docs.constellationnetwork.io/sdk/elements/monitoring-service#monitoring-configuration) <a href="#monitoring-configuration" id="monitoring-configuration"></a>

Before deploying to remote instances, configure your monitoring by editing the `config/config.json` file located in the root of the `metagraph-monitoring-service` directory. After installing the service, when you run the install command, some fields will be automatically populated based on the `euclid.json` file. These fields include:

* `metagraph.id`: The unique identifier for your metagraph.
* `metagraph.name`: The name of your metagraph.
* `metagraph.version`: The version of your metagraph.
* `metagraph.default_restart_conditions`: Specifies conditions under which your metagraph should restart. These conditions are located in `src/jobs/restart/conditions`, including:
* `SnapshotStopped`: Triggers if your metagraph stops producing snapshots.
* `UnhealthyNodes`: Triggers if your metagraph nodes become unhealthy.
* `metagraph.layers`:
* `ignore_layer`: Set to `true` to disable a specific layer.
* `ports`: Specifies public, P2P, and CLI ports.
* `additional_env_variables`: Lists additional environment variables needed upon restart, formatted as `["TEST=MY_VARIABLE, TEST_2=MY_VARIABLE_2"]`.
* `seedlist`: Provides information about the layer seedlist, e.g., `{ base_url: ":your_url", file_name: ":your_file_name"}`.
* `metagraph.nodes`:
* `ip`: IP address of the node.
* `username`: Username for SSH access.
* `privateKeyPath`: Path to the private SSH key, relative to the service's root directory. Example: `config/your_key_file.pem`.
* `key_file`: Details of the `.p12` key file used for node startup, including `name`, `alias`, and `password`.
* `network.name`: The network your metagraph is part of, such as `integrationnet` or `mainnet`.
* `network.nodes`: Information about the GL0s nodes.
* `check_healthy_interval_in_minutes`: The interval, in minutes, for running the health check.

NOTE: You must provide your SSH key file that has access to each node. It is recommended to place this under the `config` directory. Ensure that this file has access to the node and that the user you've provided also has sudo privileges without a password.

### Customize Monitoring[​](https://docs.constellationnetwork.io/sdk/elements/monitoring-service#customize-monitoring) <a href="#customize-monitoring" id="customize-monitoring"></a>

Learn how to customize your monitoring by checking the repositories:

* [metagraph-monitoring-service-package](https://github.com/Constellation-Labs/metagraph-monitoring-service-package): This repository houses the `npm` package that provides core restart functionalities.
* [metagraph-monitoring-service](https://github.com/Constellation-Labs/metagraph-monitoring-service-package): This repository utilizes the aforementioned package to implement a basic restart functionality.

### Deploying Monitoring[​](https://docs.constellationnetwork.io/sdk/elements/monitoring-service#deploying-monitoring) <a href="#deploying-monitoring" id="deploying-monitoring"></a>

Once you've configured your metagraph monitoring, deploy it to the remote host with:

`hydra remote-deploy-monitoring-service`

This command sends your current monitoring service from euclid to your remote instance and downloads all necessary dependencies.

### Starting Monitoring[​](https://docs.constellationnetwork.io/sdk/elements/monitoring-service#starting-monitoring) <a href="#starting-monitoring" id="starting-monitoring"></a>

After deployment, start your monitoring with:

`hydra remote-start-monitoring-service`

To force a complete restart of your metagraph, use:

`hydra remote-start-monitoring-service --force-restart`


# Overview

Euclid's Metagraph Framework is a rapid development framework specifically designed for creating metagraph applications within the Constellation Network ecosystem. Written in Scala, this framework offers a robust and flexible environment for building advanced blockchain solutions. The framework supports two key modules: the Currency Module and the Data Module, enabling developers to create metagraphs with comprehensive L0 token support and custom data processing capabilities.

## Framework Features[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/overview#framework-features) <a href="#framework-features" id="framework-features"></a>

The Metagraph Framework (also known as the Currency Framework) provides a complete blockchain-in-a-box solution for the creation of a layer 1 DLT network. It offers a stable starting point for application developers, while allowing full customization of the codebase to meet specific business or personal application goals.

### Key Benefits[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/overview#key-benefits) <a href="#key-benefits" id="key-benefits"></a>

**Customization and Interoperability**[**​**](https://docs.constellationnetwork.io/sdk/metagraph-framework/overview#customization-and-interoperability)

One of the core strengths of the Metagraph Framework is its complete customization capability. Developers have full control over the metagraph codebase, enabling the addition of custom validation logic, support for various external data types and ingestion formats, and the integration of external Scala or Java packages to accelerate development by leveraging existing libraries and tools.

The framework also facilitates seamless interoperability with other metagraphs, allowing for the effortless adoption of network standards and best practices. This ensures metagraph projects are adaptable and upgradable to make use of future network functionality.

**Scalability and Security**[**​**](https://docs.constellationnetwork.io/sdk/metagraph-framework/overview#scalability-and-security)

The Metagraph Framework promotes best practices that support high levels of scalability and security. The hybrid DAG/linear-chain architecture of HGTP ensures efficient handling of large transaction volumes and complex data processes, making it suitable for high-frequency and data-intensive applications.

**Integrated Development Toolkit**[**​**](https://docs.constellationnetwork.io/sdk/metagraph-framework/overview#integrated-development-toolkit)

The Metagraph Framework works seamlessly with the rest of the Euclid SDK, providing developers with a comprehensive toolkit for local development and testing. This includes tools for remote deployment and cluster monitoring in production environments, ensuring that developers can easily transition from development to production.

### Modules[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/overview#modules) <a href="#modules" id="modules"></a>

**Currency Module**[**​**](https://docs.constellationnetwork.io/sdk/metagraph-framework/overview#currency-module)

The Currency Module adds L0 token support to a metagraph project. Developers get default token functionality out of the box, with the ability to customize key network logic around token minting, distribution, and implementation of fees.

**Data Module**[**​**](https://docs.constellationnetwork.io/sdk/metagraph-framework/overview#data-module)

The Data Module allows developers to define and manage custom data types, validation logic, and data structures for their metagraphs. This capability enables the creation of sophisticated data pipelines and processing mechanisms, while giving developers complete control over data storage and privacy.

## Getting Started[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/overview#getting-started) <a href="#getting-started" id="getting-started"></a>

Explore the following sections to gain an understanding of how Metagraph Framework applications are structured, the core concepts of their development, and how to best leverage their powerful development constructs to create secure, scalable, and decentralized blockchain applications.

By utilizing the Metagraph Framework, developers can rapidly build and deploy metagraph applications that meet the evolving demands of the Web3 ecosystem, ensuring a durable and future-proof foundation for their projects.


# Framework Architecture

This section contains information about the Metagraph Framework and its relation to the deployed architecture of a metagraph.

In order to understand how the framework functions, it is important to understand the multi-layered architecture of a metagraph. Make sure you're familiar with [Metagraph Architecture](https://docs.constellationnetwork.io/metagraphs/concepts/architecture) before continuing.

## Code Structure[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/architecture#code-structure) <a href="#code-structure" id="code-structure"></a>

A new metagraph project generated from the [currency template](https://github.com/Constellation-Labs/currency.g8) will have the following module directory structure:

```
- modules/
- - l0/
- - - Main.scala
- - l1/
- - - Main.scala
- - data_l1/
- - - Main.scala
- - shared_data
- - - Main.scala
```

Let's break down each directory and its function.

**L0**[**​**](https://docs.constellationnetwork.io/sdk/metagraph-framework/architecture#l0)

This directory contains a `Main.scala` file with a Main object instance that extends `CurrencyL0App`. `CurrencyL0App` contains overridable functions that allow for customization of the operation of the metagraph L0 layer including validation, snapshot formation, and management of off chain state. It also contains the `rewards` overridable function that allows for minting of new tokens on the network.

**note**

While the class `CurrencyL0App` has the "Currency" in its name, it defines the L0 layer through which both Currency L1 and Data L1 data flows.

**L1**[**​**](https://docs.constellationnetwork.io/sdk/metagraph-framework/architecture#l1)

This directory contains a `Main.scala` file with a Main object instance that extends `CurrencyL1App`. `CurrencyL1App` contains overridable functions relevant to customizing token validation behavior such as `transactionValidator`.

**L1 Data**[**​**](https://docs.constellationnetwork.io/sdk/metagraph-framework/architecture#l1-data)

This directory also contains a `Main.scala` file, with a Main object instance that extends `CurrencyL1App`. In order to have this L1 behave as a DataApplication, the `dataApplication` method should be overridden with your custom configuration. The metagraph examples repo has implemented examples to reference, for example the [NFT example](https://github.com/Constellation-Labs/metagraph-examples/blob/main/examples/nft/modules/data_l1/src/main/scala/com/my/nft/data_l1/Main.scala).

**Shared Data**[**​**](https://docs.constellationnetwork.io/sdk/metagraph-framework/architecture#shared-data)

This directory contains an empty Main.scala file but is provided as a suggestion for application directory structure. Several of the lifecycle functions are run on both Data L1 and on L0. For example, serializers/deserializers, validators, and data types will likely shared between layers. Organizing them in a separate directory makes their use in multiple layers clear.

See the [Data Application Lifecycle](https://docs.constellationnetwork.io/sdk/metagraph-framework/data/lifecycle-functions) for more information.


# Installation

The Metagraph Framework can be installed in several ways:

* **Euclid** (recommended): Install an empty project in Euclid SDK using the `hydra install` command.
* **Metagraph Examples** (recommended): Explore ready-to-use examples of metagraph codebases in the [metagraph-examples repo](https://github.com/Constellation-Labs/metagraph-examples). These examples can also be installed automatically via the `hydra install-template` command.
* **giter8**: The Metagraph Framework is distributed as a g8 template project that can be customized for your organization. This template can be manually built using [giter8](http://www.foundweekends.org/giter8/). For more details, visit the [project repository](https://github.com/Constellation-Labs/currency.g8).

**Quick Start**

See the Euclid Quick Start guide for a walkthrough of framework installation within the Euclid Development Environment. This is the recommended development environment and installation method for most users.

## Installation Using Giter8[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/installation#installation-using-giter8) <a href="#installation-using-giter8" id="installation-using-giter8"></a>

**note**

Manual installation using giter8 necessitates pre-generated Tessellation dependencies. To generate these dependencies, execute the following commands in the tessellation repository on the desired tag:

```
sbt shared/publishM2 kernel/publishM2 keytool/publishM2 nodeShared/publishM2 dagL1/publishM2 currencyL0/publishM2 currencyL1/publishM2
```

Ensure Scala and giter8 are installed. Install giter8 with:

```
./cs install giter8
```

Then, install the template using the specified tag:

```
# replace v2.8.0 with the version to install
g8 Constellation-Labs/currency --tag "v2.8.0" 
```

### Compiling the Project[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/installation#compiling-the-project) <a href="#compiling-the-project" id="compiling-the-project"></a>

After installing your project and the Tessellation dependencies, compile the project to generate your local JAR files. You can compile as follows:

For metagraph-l0:

```
sbt currencyL0/assembly
```

For currency-l1:

```
sbt currencyL1/assembly
```

For data-l1:

```
sbt dataL1/assembly
```

## Installation Using Metagraph Examples[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/installation#installation-using-metagraph-examples) <a href="#installation-using-metagraph-examples" id="installation-using-metagraph-examples"></a>

Using Euclid, you can execute the following command to list the available examples:

```
hydra install-template --list
```

To install the desired template, execute this command:

```
# replace 'nft' with the name of the desired template
hydra install-template nft
```

### Compiling the Project[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/installation#compiling-the-project-1) <a href="#compiling-the-project-1" id="compiling-the-project-1"></a>

To compile the project using Euclid, you just need to run:

```
hydra build
```


# Currency

The Currency Module provides a fast and customizable way to launch a metagraph with native support for currency (L0 token) transactions. Unlike closed-loop systems such as smart-contract platforms, this framework offers enhanced flexibility by allowing direct modifications of application-level code. It encapsulates functionalities necessary for peer-to-peer token transactions, chain data construction, and more, in an easy-to-use package.

Note that launching a token is not required when developing with the Metagraph Framework, and at present, the Metagraph Framework is also the most efficient way to launch a data-focused application with or without a token associated with it. Extending the framework with the Data module allows developers to build metagraphs with custom data ingestion, validation, and storage logic. See the [Data Application](https://docs.constellationnetwork.io/sdk/metagraph-framework/data/overview) section for more detail.

By basing their metagraphs on this framework, developers gain the advantage of working with a proven set of underlying features and functionality in order to be able to focus on their project's own business logic rather than boilerplate functionality. Example projects are provided in order to speed up development. See [metagraph examples](https://github.com/Constellation-Labs/metagraph-examples) or use the `install-template` method of `hydra`.


# Working with Tokens

This section will cover the use of L0 tokens within a metagraph - how to mint them, how to determine fees for user actions, and different strategies for state management in relation to token distribution.

### Minting Tokens[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/currency/tokens#minting-tokens) <a href="#minting-tokens" id="minting-tokens"></a>

Tokens can be minted in two ways through a metagraph: at genesis through the use of the *genesis file*, or as part of a incremental snapshot using the *rewards* function.

#### Genesis File[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/currency/tokens#genesis-file) <a href="#genesis-file" id="genesis-file"></a>

The genesis file is a file used during the creation of a genesis snapshot, i.e. the first snapshot of the chain, which contains initial wallet balances. Configuring the genesis file sets the initial circulating supply for the network and assigns that supply to specific wallets.

The genesis file is a simple CSV file that can be found in `source/metagraph-l0/genesis/genesis.csv` with the format of

```
<ADDRESS>,<BALANCE>
```

Copy

Euclid comes with a default set of addresses and balances in this file. You can (and should) edit for your own needs however you like.

NOTE: The balances in the genesis file are denominated in datum rather than DAG. 1 DAG is 100,000,000 datum. So for example to set a balance of 25 tokens to a wallet, you would add the following line: `DAG123..., 2500000000`

The genesis file is used only once, during the formation of the genesis snapshot, and as such you only have one chance to set your initial balances. Changing the contents of this file once the snapshot chain has progressed beyond the first snapshot will not have any effect on token balances on your network.

Once the metagraph state has progressed beyond the genesis snapshot (ordinal 1+), any changes to the token balance map must come through either token transactions or new minting of tokens through the rewards function.

#### Rewards Function[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/currency/tokens#rewards-function) <a href="#rewards-function" id="rewards-function"></a>

The rewards function is a function of the `CurrencyL0App` called during the [Metagraph Snapshot Lifecycle](https://docs.constellationnetwork.io/sdk/metagraph-framework/data/lifecycle-functions) which has the ability to create Reward transactions. Reward transactions are special minting transactions on the network which increase the circulating supply of the L0 token and distribute it to an address.

If we examine the function in `modules→l0→Main.scala`, we can see that the function is provided with the following context:

* `Signed[CurrencyIncrementalSnapshot]`
* `SortedMap[Address, Balance]`
* `SortedSet[Signed[Transaction]]`
* `ConsensusTrigger`
* `Set[CurrencySnapshotEvent]`
* `Option[DataCalculatedState]`

The expected output of the rewards function is a SortedSet with reward transactions. Using the context data provided, a number of strategies for token minting are possible.

Supported token minting strategies:

* Continuous minting to reward network participation (ex: rewarding validator nodes that participate in consensus)
* State-triggered minting (ex: minting rewards to wallets based on data fetched on a schedule)
* One-off minting (ex: an airdrop or one-time creation of a wallet).

See the [Reward API metagraph example](https://github.com/Constellation-Labs/metagraph-examples/tree/main/examples/reward-api) repo for an example of how to use the rewards function.

### Setting Metagraph Fees[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/currency/tokens#setting-metagraph-fees) <a href="#setting-metagraph-fees" id="setting-metagraph-fees"></a>

Fees charged by the metagraph fall into two categories: Token transaction fees, and fee transactions charged for custom data updates. These perform similar actions on different kinds of transactions but have unique ways that they need to be configured and managed.

**note**

All fees collected on a metagraph are denominated in the metagraph’s token as the currency. Fees are not collected or managed in DAG.

#### Token Transaction Fees[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/currency/tokens#token-transaction-fees) <a href="#token-transaction-fees" id="token-transaction-fees"></a>

By default, L0 tokens share the fee characteristics of DAG. DAG has zero required fee for transfers, but adding a minimal fee (1+ datum) will prioritize the processing of a transaction above non-fee transactions on the network. Priority processing also allows many more transactions to be processed from the same address in a single snapshot: 100 per snapshot for priority vs 1 per snapshot for non-priority transactions. This default configuration allows senders to pay for increased throughput if needed, for example in airdrop or bulk sending use cases, while otherwise supporting a feeless network.

L0 tokens share these default attributes of DAG but can customize the minimum required fee for a specific transaction (default zero). This behavior can be managed with the `transactionValidator` function on the `CurrencyL1App` object. The `transactionValidator` function can either accept or reject a transaction based on any attributes of transaction, but is most commonly used to reject if the fee below a particular threshold.

\[Tessellation v2.9.0+] An additional function, `transactionEstimator` returns the expected fee for a given transaction. This function is exposed over the `/estimate-fee` Currency L1 endpoint and is used by wallets and other 3rd party integrations to understand the fee required to send a successful transaction.

See the [Custom Transaction Validation](https://github.com/Constellation-Labs/metagraph-examples/tree/main/examples/custom-transaction-validation) repo for an example implementation.

**note**

Fees collected by the network are currently removed from circulation (in other words burned). While custom transaction fee behavior and especially destination wallets will likely be added in the future, it is possible to deposit fees into a specific wallet with current feature through a mint/burn mechanism. The `rewards` function can be used to mint the equivalent of the burned fees into a particular wallet by monitoring transactions in each snapshot.

#### Data Update Fees[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/currency/tokens#data-update-fees) <a href="#data-update-fees" id="data-update-fees"></a>

**V2.9.0+**

FeeTransactions and associated functionality are currently set to be included in Tessellation v2.9.0. The description of functionality below applies only to that future version or later.

Metagraphs have the ability to require custom fees for data payloads submitted through the `/data` endpoint on a DataApplication. These fees allow the application to charge fees for certain actions such as creating or updating resources (minting) or based on the resources required to handle the request. By default, fees are set to zero.

Much like currency transactions, data transaction fees must be explicitly approved and signed by the private key representing the address of the requester. Since data updates are fully custom data types defined within the metagraph codebase, there is no inherently included fee structure or predefined destination wallet for the fee to be transferred to within the data update that can be referenced.

Both the amount and destination wallet of the DataUpdate must be set through a `FeeTransaction` object nested in the DataUpdate request body. This object is signed independently of the DataUpdate and then included in the DataUpdate body, and then the entire DataUpdate body including the FeeTransaction is signed. This format allows the metagraph to validate the signature of the DataUpdate as whole, as well as the FeeTransaction independently. All FeeTransactions must be included in the metagraph on-chain data and shared with the gL0. Requiring a separate signature on the FeeTransaction itself preserves the metagraph developer’s ability to exclude parts or all of the DataUpdate contents from the on-chain data.

FeeTransaction has the following format:

```
// FeeTransaction
{
  value: {
    destination: 'DAG...', // metagraph-defined fee wallet
    amount: 1 // amount of fee in datum
  },
  proofs: [] // signature of only FeeTransaction value
}
```

Copy

FeeTransaction included in an example data update:

```
// CustomDataUpdate
{
  value: {
    customField1: 42,
    customField2: "custom-value",  // any fields of the DataUpdate
    FeeTransaction: {
      value: {
        destination: 'DAG...', // metagraph-defined fee wallet
        amount: 1 // amount of fee in datum
      },
      proofs: [] // signature of only FeeTransaction value
    }
  },
  proofs: [] // signature of CustomDataUpdate value
}
```

Copy

In order to support wallets and other 3rd party services that need to know the cost of processing a DataUpdate before sending it, the `/data/estimate-fee` endpoint is provided. This endpoint accepts an unsigned DataUpdate and returns the expected fee and metagraph destination wallet for the fee.

For example:

```
**Request:**
POST /data/estimate-fee
{
  customField1: 42,
  customField2: "custom-value",  // any fields of the DataUpdate
}

**Response:**
{
  fee: 100,  // minimum required fee
  address: "DAG..." // metagraph-defined fee wallet
}
```


# Data

Data Application Module

The Data Application (or Data API) is a module available to Metagraph Framework developers to ingest and validate custom data types through their metagraphs. It's a set of tools for managing data interactions within the metagraph that is flexible enough to support a wide range of application use cases such as IoT, NFTs, or custom application-specific blockchains.

**Example Code**

Want to jump directly to a code example? A number of examples can be found on Github under the [Metagraph Examples](https://github.com/Constellation-Labs/metagraph-examples/tree/main/examples) repo.

### Basics[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/data/overview#basics) <a href="#basics" id="basics"></a>

The basic function of a Data Application is to accept data through a special endpoint on the Data L1 layer, found at `POST /data`. Receiving a request triggers a series of lifecycle functions for the data update, running it through validation and consensus on both Data L1 and L0, and then eventual inclusion into the custom data portion of the metagraph snapshot.

This process is defined in detail in [Lifecycle Functions](https://docs.constellationnetwork.io/metagraph-development/metagraph-framework/data/lifecycle-functions) but an abbreviated version is provided below as an overview. In order to interact with the framework, developers can tap into these lifecycle events to override the default behavior and introduce their own custom logic.

#### Data Flow[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/data/overview#data-flow) <a href="#data-flow" id="data-flow"></a>

1. Data accepted by the `/data` endpoint
2. Data is parsed (and reformatted if necessary) with `signedDataEntityEncoder`
3. Custom validations are run on Data L1 with `validateUpdate`
4. Data is packaged into blocks, run through L1 consensus and sent to L0
5. Additional custom validations are run w/L0 context available with `validateData`
6. Data is packaged into on-chain (snapshot) and off-chain (calculated state) representations with the `combine` function
7. The snapshot undergoes consensus and is accepted into the chain

See [Lifecycle Functions](https://docs.constellationnetwork.io/metagraph-development/metagraph-framework/data/lifecycle-functions) for more detail.

#### State Management and Storage[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/data/overview#state-management-and-storage) <a href="#state-management-and-storage" id="state-management-and-storage"></a>

State is defined within the Metagraph Framework in two ways: on-chain (snapshot) and off-chain (calculated state). The developer has control over how both kinds of state are created via the `combine` lifecycle function which is called prior to each round of L0 consensus.

On-chain state is stored in the metagraph's snapshot chain and each of these snapshots is submitted to the Global L0 for inclusion in a global snapshot. As such, on chain state incurs fees (See [Network Fees](https://docs.constellationnetwork.io/network-fundamentals/network-fees)) and has a maximum size of 500kb (See [State Scalability](https://docs.constellationnetwork.io/metagraph-development/metagraph-framework/data/state-management#scalability)). This also means that any data stored in on-chain state is made public through the public nature of global snapshots on the Hypergraph. However, the developer has the option to encrypt that state through the `serializeState` lifecycle function, or alternatively, to limit the data that's stored in on-chain state.

Off-chain or "calculated" state is data that is stored off-chain but can be recreated by the accumulation of all snapshots in order from genesis to current. In this way, it's calculated from the chain but not part of the chain data itself. Calculated state is stored in memory by default, and recreated from a file-based cache on bootup, but the relevant lifecycle functions can be used to hook into other data stores such as a local database or an external storage service. Since calculated state is never sent to the Hypergraph, it does not incur any fees and has no limitations on size or structure beyond hardware limits.

See [State Management](https://docs.constellationnetwork.io/metagraph-development/metagraph-framework/data/state-management) for more details.

#### Querying Metagraph Data[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/data/overview#querying-metagraph-data) <a href="#querying-metagraph-data" id="querying-metagraph-data"></a>

Metagraphs support the creation of custom HTTP endpoints on any of the metagraph layers. These endpoints are useful for allowing external access to calculated state or creating views of the chain data for users.

See [Custom Queries](https://docs.constellationnetwork.io/metagraph-development/metagraph-framework/custom-endpoints) for more details.

#### Scheduled Tasks[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/data/overview#scheduled-tasks) <a href="#scheduled-tasks" id="scheduled-tasks"></a>

Scheduled tasks on a metagraph are possible through the concept of daemons, worker processes that run on a timer. These processes allow the metagraph codebase to react to time-based triggers rather than waiting for an incoming transaction or data update to react to. Daemons are especially useful for syncing behavior, such as fetching data from an external source on a regular schedule or pushing internal data externally on a regular basis.

[Edit this page](https://github.com/Constellation-Labs/documentation-hub/edit/main/sdk/metagraph-framework/05-data/01-overview.md)


# State Management

A Data Application manages two distinct types of state: **OnChainState** and **CalculatedState**, each serving unique purposes in the metagraph architecture.

#### OnChain State[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/data/state-management#onchain-state) <a href="#onchain-state" id="onchain-state"></a>

OnChainState contains all the information intended to be permanently stored on the blockchain. This state represents the immutable record of all updates that have been validated and accepted by the network.

It typically includes:

* A history of all data updates
* Transaction records
* Any data that requires blockchain-level immutability and auditability

OnChainState is replicated across all nodes in the network and becomes part of the chain's immutable record via inclusion in a snapshot. It should be designed to be compact and contain only essential information as it contributes to storage requirements and snapshot fees.

#### Calculated State[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/data/state-management#calculated-state) <a href="#calculated-state" id="calculated-state"></a>

CalculatedState can be thought of as a metagraph's working memory, containing essential aggregated information derived from the complete chain of OnChainState. It is not stored on chain itself, but can be reconstructed by traversing the network's chain of snapshots and applying the `combine` function to them.

CalculatedState typically:

* Provides optimized data structures for querying
* Contains aggregated or processed information
* Stores derived data that can be reconstructed from OnChainState if needed

CalculatedState is maintained by each node independently and can be regenerated from the OnChainState if necessary. This makes it ideal for storing derived data, indexes, or sensitive information.

### Creating State Classes[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/data/state-management#creating-state-classes) <a href="#creating-state-classes" id="creating-state-classes"></a>

Each state described above represents functionality from the Data Application. To create these states, you need to implement custom traits provided by the Data Application:

* The OnChainState must extend the `DataOnChainState` trait
* The CalculatedState must extend the `DataCalculatedState` trait

Both traits, `DataOnChainState` and `DataCalculatedState`, can be found in the tessellation repository.

Here's a simple example of state definitions:

```
@derive(decoder, encoder)
case class VoteStateOnChain(updates: List[PollUpdate]) extends DataOnChainState

@derive(decoder, encoder)
case class VoteCalculatedState(polls: Map[String, Poll]) extends DataCalculatedState
```

### Updating State[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/data/state-management#updating-state) <a href="#updating-state" id="updating-state"></a>

The DataAPI includes several lifecycle functions crucial for the proper functioning of the metagraph.

You can review all these functions in the [Lifecycle Functions](/metagraph-development/metagraph-framework/data/lifecycle-functions) section.

In this discussion, we'll focus on the following functions: `combine` and `setCalculatedState`

#### combine[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/data/state-management#combine) <a href="#combine" id="combine"></a>

Is the central function to updating the states. This function processes incoming requests/updates by either increasing or overwriting the existing states. Here is the function's signature:

```
override def combine(
  currentState: DataState[OnChainState, CalculatedState],
  updates: List[Signed[Update]]
): IO[DataState[OnChainState, CalculatedState]]
```

The combine function is invoked after the requests have been validated at both layers (l0 and l1) using the `validateUpdate` and `validateData` functions.

The `combine` function receives the `currentState` and the `updates`

* `currentState`: As indicated by the name, this is the current state of your metagraph since the last update was received.
* `updates`: This is the list of incoming updates. It may be empty if no updates have been provided to the current snapshot.

The output of this function is also a state, reflecting the new state of the metagraph post-update. Therefore, it's crucial to ensure that the function returns the correct updated state.

Returning to the `water and energy usage` example, you can review the implementation of the combine function [here](https://github.com/Constellation-Labs/metagraph-examples/blob/main/examples/water-and-energy-usage/modules/shared_data/src/main/scala/com/my/water_and_energy_usage/shared_data/combiners/Combiners.scala). In this implementation, the function retrieves the current value of water or energy and then increments it based on the amount specified in the incoming request for the `CalculatedState`, while also using the current updates as the `OnChainState`.

#### setCalculatedState[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/data/state-management#setcalculatedstate) <a href="#setcalculatedstate" id="setcalculatedstate"></a>

Following the combine function and after the snapshot has been accepted and consensus reached, we obtain the `majority snapshot`. This becomes the official snapshot for the metagraph. At this point, we invoke the `setCalculatedState` function to update the `CalculatedState`.

This state is typically stored `in memory`, although user preferences may dictate alternative storage methods. You can explore the implementation of storing the `CalculatedState` in memory by checking the [CalculatedState.scala](https://github.com/Constellation-Labs/metagraph-examples/blob/main/examples/water-and-energy-usage/modules/shared_data/src/main/scala/com/my/water_and_energy_usage/shared_data/calculated_state/CalculatedState.scala) and [CalculatedStateService.scala](https://github.com/Constellation-Labs/metagraph-examples/blob/main/examples/water-and-energy-usage/modules/shared_data/src/main/scala/com/my/water_and_energy_usage/shared_data/calculated_state/CalculatedStateService.scala) classes, where we have detailed examples.

In the sections below, we will discuss `serializers` used to serialize the states.

### Serializers/Deserializers[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/data/state-management#serializersdeserializers) <a href="#serializersdeserializers" id="serializersdeserializers"></a>

We also utilize other lifecycle functions for `serialize/deserialize` processes, each designed specifically for different types of states.

For the `OnChainState`, we use the following functions:

```
def serializeState(
  state: OnChainState
): F[Array[Byte]]

def deserializeState(
  bytes: Array[Byte]
): F[Either[Throwable, OnChainState]]
```

For the `CalculatedState` we have:

```
def serializeCalculatedState(
  state: CalculatedState
): F[Array[Byte]] 

def deserializeCalculatedState(
  bytes: Array[Byte]
): F[Either[Throwable, CalculatedState]]
```

The `OnChainState` serializer is employed during the snapshot production phase, prior to consensus, when nodes propose snapshots to become the official one. Once the official snapshot is selected, based on the majority, the `CalculatedState` serializer is used to serialize this state and store the `CalculatedState` on disk.

The deserialization functions are invoked when constructing states from the `snapshots/calculatedStates` stored on disk. For instance, when restarting a metagraph, it's necessary to retrieve the state prior to the restart from the stored information on disk.

In the following section, we will provide a detailed explanation about disk storage.

### Disk Storage[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/data/state-management#disk-storage) <a href="#disk-storage" id="disk-storage"></a>

When operating a Metagraph on layer 0 (ml0), a directory named `data` is created. This directory is organized into the following subfolders:

* `incremental_snapshot`: Contains the Metagraph snapshots.
* `snapshot_info`: Stores information about the snapshots, including internal states like balances.
* `calculated_state`: Holds the Metagraph calculated state.

Focusing on the `calculated_state`, within this folder, files are named after the snapshot ordinal. These files contain the CalculatedState corresponding to that ordinal. We employ a logarithmic cutoff strategy to manage the storage of these states.

This folder is crucial when restarting the Metagraph. It functions as a `checkpoint`: instead of rerunning the entire chain to rebuild the `CalculatedState`, we utilize the files in the `calculated_state` directory. This method allows us to rebuild the state more efficiently, saving significant time.

### Data Privacy[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/data/state-management#data-privacy) <a href="#data-privacy" id="data-privacy"></a>

As previously mentioned, the `CalculatedState` serves a crucial role by allowing the storage of any type of information discreetly, without exposing it to the public. This functionality is particularly useful for safeguarding sensitive data. When you use the `CalculatedState`, you can access your information whenever necessary, but it remains shielded from being recorded on the blockchain.. This method offers an added layer of security, ensuring that sensitive data is not accessible or visible on the decentralized ledger.

By leveraging `CalculatedState`, organizations can manage proprietary or confidential information such as personal user data, trade secrets, or financial details securely within the metagraph architecture. The integrity and privacy of this data are maintained, as it is stored in a secure compartment separated from the public blockchain.

### Scalability[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/data/state-management#scalability) <a href="#scalability" id="scalability"></a>

Metagraphs face a constraint concerning the size of snapshots: `they must not exceed 500kb`. If snapshots surpass this threshold, they will be rejected, which can impose significant limitations on the amount of information that can be recorded on the blockchain.

This is where the CalculatedState becomesparticularly valuable. It allows for the storage of any amount of data, bypassing the size constraints of blockchain snapshots. Moreover, CalculatedState offers flexibility in terms of storage preferences,enabling users to choose how and where their data is stored.

This functionality not only alleviates the burden of blockchain size limitations but also enhances data management strategies. By utilizing CalculatedState, organizations can efficiently manage larger datasets, secure sensitive information off-chain, and optimize their blockchain resources for critical transactional data.

[Edit this page](https://github.com/Constellation-Labs/documentation-hub/edit/main/sdk/metagraph-framework/05-data/02-state-management.md)


# Lifecycle functions

Lifecycle functions are essential to the design and operation of a metagraph within the Euclid SDK. These functions enable developers to hook into various stages of the framework's lifecycle, allowing for the customization and extension of the core functionality of their Data Application. By understanding and implementing these functions, developers can influence how data is processed, validated, and persisted, ultimately defining the behavior of their metagraph.

#### How Lifecycle Functions Fit into the Framework[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/data/lifecycle-functions#how-lifecycle-functions-fit-into-the-framework) <a href="#how-lifecycle-functions-fit-into-the-framework" id="how-lifecycle-functions-fit-into-the-framework"></a>

In the Euclid SDK, lifecycle functions are organized within the L0 (DataApplicationL0Service), Currency L1 (CurrencyL1App), and Data L1 (DataApplicationL1Service) modules. These modules represent different layers of the metagraph architecture:

* **L0 Layer:** This is the base layer responsible for core operations like state management, validation, and consensus. Functions in this layer are critical for maintaining the integrity and consistency of the metagraph as they handle operations both before (`validateData`, `combine`) and after consensus (`setCalculatedState`).
* **Data L1 Layer:** This layer manages initial validations and data transformations through the /data endpoint. It is responsible for filtering and preparing data before it is sent to the L0 layer for further processing.
* **Currency L1 Layer:** This layer handles initial validations and transaction processing through the /transactions endpoint before passing data to the L0 layer. It plays a crucial role in ensuring that only valid and well-formed transactions are forwarded for final processing. Note that currency transactions are handled automatically by the framework and so only a small number of lifecycle events are available to customize currency transaction handling (`transactionValidator`, etc.).

By implementing lifecycle functions in these layers, developers can manage everything from the initialization of state in the `genesis` function to the final serialization of data blocks. Each function serves a specific purpose in the metagraph's lifecycle, whether it’s validating incoming data, updating states, or handling custom logic through routes and decoders.

#### Lifecycle Overview[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/data/lifecycle-functions#lifecycle-overview) <a href="#lifecycle-overview" id="lifecycle-overview"></a>

The diagram below illustrates the flow of data within a metagraph, highlighting how transactions and data updates move from the Currency L1 and Data L1 layers into the L0 layer. The graphic also shows the sequence of lifecycle functions that are invoked at each stage of this process. By following this flow, developers can understand how their custom logic integrates with the framework and how data is processed, validated, and persisted as it progresses through the metagraph.

![Euclid SDK](https://docs.constellationnetwork.io/assets/images/data-update-lifecycle-3d44b4bc3815618d6cf3c83fa5f49313.png)

{% hint style="info" %}
Note that some lifecycle functions are called multiple times and across L1 and L0 layers. It is usually recommended to create a common, shared implementation for these functions.
{% endhint %}

### Functions[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/data/lifecycle-functions#functions) <a href="#functions" id="functions"></a>

#### genesis[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/data/lifecycle-functions#genesis) <a href="#genesis" id="genesis"></a>

Data Applications allow developers to define custom state schemas for their metagraph. Initial states are established in the `genesis` function within the `l0` module's `DataApplicationL0Service`. Use the `OnChainState` and `CalculatedState` methods to define the initial schema and content of the application `state` for the `genesis snapshot`.

For example, you can set up your initial states using map types, as illustrated in the Scala code below:

```
class OnChainState(updates: List[Update]) extends DataOnChainState
class CalculatedState(info: Map[String, String]) extends DataCalculatedState

override def genesis: DataState[OnChainState, CalculatedState] = DataState(OnChainState(List.empty), CalculatedState(Map.empty))
```

In the code above, we set the initial state to be:

* `OnChainState`: Empty list
* `CalculatedState`: Empty Map

#### signedDataEntityDecoder[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/data/lifecycle-functions#signeddataentitydecoder) <a href="#signeddataentitydecoder" id="signeddataentitydecoder"></a>

This method parses custom requests at the `/data` endpoint into the `Signed[Update]` type. It should be implemented in both `Main.scala` files for the `l0` and `data-l1` layers. By default, you can use the `circeEntityDecoder` to parse the JSON:

```
{
  "value": {
    // This type is defined by your application code
  },
  "proofs": [{
    "id": "<public key>",
    "signature": "<signature of data in value key above>"
  }]
}
```

The default implementation is straightforward:

```
def signedDataEntityDecoder[F[_] : Async: Env]: EntityDecoder[F, Signed[Update]] = circeEntityDecoder
```

For custom parsing of the request, refer to the example below:

```
  def signedDataEntityDecoder[F[_] : Async: Env]: EntityDecoder[F, Signed[Update]] = {
    EntityDecoder.decodeBy(MediaType.text.plain) { msg =>
    // Assuming msg.body is a comma-separated string of key-value pairs.
      val dataMap = msg.body.split(",").map { pair =>
        val Array(key, value) = pair.split(":")
        key.trim -> value.trim
      }.toMap

      val update = Update(dataMap.value)
      val hexId = Hex(dataMap.pubKey)
      val hexSignature = Hex(dataMap.signature)
      val signatureProof = SignatureProof(Id(hexId), Signature(hexSignature))
      val proofsSet = SortedSet(signatureProof)

      val proofs = NonEmptySet.fromSetUnsafe(proofsSet)
      Signed(update, proofs)
    }
  }
```

In this custom example, we parse a simple string formatted as a map, extracting the `value`, `pubKey`, and `signature` necessary to construct the `Signed[Update]`. This method allows for efficient handling of incoming data, converting it into a structured form ready for further processing.

#### validateUpdate[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/data/lifecycle-functions#validateupdate) <a href="#validateupdate" id="validateupdate"></a>

This method validates the update on the L1 layer and can return synchronous errors through the `/data` API endpoint. Context information (oldState, etc.) is not available to this method so validations need to be based on the contents of the update only. Validations requiring context should be run in `validateData` instead. It should be implemented in both `Main.scala` files for the `l0` and `data-l1` layers

For example, validate a field is within a positive range:

```
def validateUpdate(update: Update): IO[DataApplicationValidationErrorOr[Unit]] = IO {
  if (update.usage <= 0) {
    DataApplicationValidationError.invalidNec
  } else {
    ().validNec
  }
}
```

The code above rejects any update that has the update value less than or equal to 0.

#### validateData[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/data/lifecycle-functions#validatedata) <a href="#validatedata" id="validatedata"></a>

This method runs on the L0 layer and validates an update (data) that has passed L1 validation and consensus. `validateData` has access to the old or current application state, and a list of updates. Validations that require access to state information should be run here. It should be implemented in both `Main.scala` files for the `l0` and `data-l1` layers

For example, validate that a user has a balance before allowing an action:

```
def validateData(oldState: DataState[OnChainState, CalculatedState], updates: NonEmptyList[Signed[Update]]): IO[DataApplicationValidationErrorOr[Unit]] = IO {
  updates
    .map(_.value)
    .map {
      val currentBalance = acc.balances.getOrElse(update.address, 0)

      if (currentBalance > 0) {
        ().validNec 
      } else {
        DataApplicationValidationError.invalidNec
      }
    }
    .reduce
}
```

The code above rejects any update that the current balance is lower than 0.

#### combine[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/data/lifecycle-functions#combine) <a href="#combine" id="combine"></a>

The `combine` method accepts the current state and a list of validated updates and should return the new state. This is where state is ultimately updated to generate the new snapshot state. It should be implemented in both `Main.scala` files for the `l0` and `data-l1` layers

For example, subtract one from a balance map:

```
def combine(oldState: DataState[OnChainState, CalculatedState], updates: NonEmptyList[Signed[Update]]): IO[State] = IO {
  updates.foldLeft(oldState) { (acc, update) =>
    val currentBalance = acc.balances.getOrElse(update.address, 0)

    acc.focus(_.balances).modify(_.updated(update.address, currentBalance - 1))
  }
}
```

The code above will subtract one for the given address and update the state

#### serializeState and deserializeState[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/data/lifecycle-functions#serializestate-and-deserializestate) <a href="#serializestate-and-deserializestate" id="serializestate-and-deserializestate"></a>

These methods are required to convert the onChain state to and from byte arrays, used in the snapshot, and the OnChainState class defined in the genesis method. It should be implemented in both `Main.scala` files for the `l0` and `data-l1` layers

For example, serialize to/from a State object:

```
  def serializeState(state: OnChainState): IO[Array[Byte]] = IO {
    state.asJson.deepDropNullValues.noSpaces.getBytes(StandardCharsets.UTF_8)
  }

  def deserializeState(bytes: Array[Byte]): IO[Either[Throwable, OnChainState]] = IO {
    parser.parse(new String(bytes, StandardCharsets.UTF_8)).flatMap { json =>
      json.as[OnChainState]
    }
  }
```

The codes above serialize and deserialize using `Json`

#### serializeCalculatedState and deserializeCalculatedState[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/data/lifecycle-functions#serializecalculatedstate-and-deserializecalculatedstate) <a href="#serializecalculatedstate-and-deserializecalculatedstate" id="serializecalculatedstate-and-deserializecalculatedstate"></a>

These methods are essential for converting the CalculatedState to and from byte arrays. Although the `CalculatedState` does not go into the snapshot, it is stored in the `calculated_state` directory under the `data` directory. For more details, refer to the [State Management](https://docs.constellationnetwork.io/sdk/metagraph-framework/data/state-management) section. It should be implemented in both `Main.scala` files for the `l0` and `data-l1` layers

For example, serialize to/from a State object:

```
  def serializeCalculatedState(state: CalculatedState): IO[Array[Byte]] = IO {
    state.asJson.deepDropNullValues.noSpaces.getBytes(StandardCharsets.UTF_8)
  }

  def deserializeCalculatedState(bytes: Array[Byte]): IO[Either[Throwable, CalculatedState]] = IO {
    parser.parse(new String(bytes, StandardCharsets.UTF_8)).flatMap { json =>
      json.as[CalculatedState]
    }
  }
```

The codes above serialize and deserialize using `Json`

#### serializeUpdate and deserializeUpdate[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/data/lifecycle-functions#serializeupdate-and-deserializeupdate) <a href="#serializeupdate-and-deserializeupdate" id="serializeupdate-and-deserializeupdate"></a>

These methods are required to convert updates sent to the `/data` endpoint to and from byte arrays. Signatures are checked against the byte value of the `value` key of the update so these methods give the option to introduce custom logic for how data is signed by the client. It should be implemented in both `Main.scala` files for the `l0` and `data-l1` layers

For example, serialize to/from a JSON update:

```
  def serializeUpdate(update: Update): IO[Array[Byte]] = IO {
    update.asJson.deepDropNullValues.noSpaces.getBytes(StandardCharsets.UTF_8)
  }

  def deserializeUpdate(bytes: Array[Byte]): IO[Either[Throwable, Update]] = IO {
    parser.parse(new String(bytes, StandardCharsets.UTF_8)).flatMap { json =>
      json.as[Update]
    }
  }
```

The codes above serialize and deserialize using `Json`

#### serializeBlock and deserializeBlock[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/data/lifecycle-functions#serializeblock-and-deserializeblock) <a href="#serializeblock-and-deserializeblock" id="serializeblock-and-deserializeblock"></a>

These methods are required to convert the data application blocks to and from byte arrays, used in the snapshot.\
It should be implemented in both `Main.scala` files for the `l0` and `data-l1` layers

For example, serialize to/from a State object:

```
  def serializeBlock(block: Signed[DataApplicationBlock]): IO[Array[Byte]] = IO {
    state.asJson.deepDropNullValues.noSpaces.getBytes(StandardCharsets.UTF_8)
  }

  def deserializeBlock(bytes: Array[Byte]): IO[Either[Throwable, Signed[DataApplicationBlock]]] = IO {
    parser.parse(new String(bytes, StandardCharsets.UTF_8)).flatMap { json =>
      json.as[Signed[DataApplicationBlock]]
    }
  }
```

The codes above serialize and deserialize using `Json`

#### setCalculatedState[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/data/lifecycle-functions#setcalculatedstate) <a href="#setcalculatedstate" id="setcalculatedstate"></a>

This function updates the `calculatedState`. For details on when and why this function is called, refer to the [State Management](https://docs.constellationnetwork.io/sdk/metagraph-framework/data/state-management) section. It should be implemented in both `Main.scala` files for the `l0` and `data-l1` layers

```
  override def setCalculatedState(
    ordinal: SnapshotOrdinal,
    state  : CalculatedState
  )(implicit context: L0NodeContext[IO]): IO[Boolean] = {
      val currentCalculatedState = currentState.state
      val updated = state.devices.foldLeft(currentCalculatedState.devices) {
        case (acc, (address, value)) =>
          acc.updated(address, value)
      }

      CalculatedState(snapshotOrdinal, CalculatedState(updated))
    }.as(true)
        
```

The code above simply replaces the current address with the new value, thereby overwriting it.

#### getCalculatedState[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/data/lifecycle-functions#getcalculatedstate) <a href="#getcalculatedstate" id="getcalculatedstate"></a>

This function retrieves the `calculatedState`. It should be implemented in both `Main.scala` files for the `l0` and `data-l1` layers

```
  override def getCalculatedState(implicit context: L0NodeContext[IO]): IO[(SnapshotOrdinal, CheckInDataCalculatedState)] = 
  currentState.state.map(calculatedState => (calculatedState.ordinal, calculatedState.state))
        
```

The code above is an example of how to implement the retrieval of `calculatedState`.

#### hashCalculatedState[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/data/lifecycle-functions#hashcalculatedstate) <a href="#hashcalculatedstate" id="hashcalculatedstate"></a>

This function hashes the `calculatedState`, which is used for `proofs`. It should be implemented in both `Main.scala` files for the `l0` and `data-l1` layers

```
  override def hashCalculatedState(
    state: CalculatedState
  )(implicit context: L0NodeContext[IO]): IO[Hash] = {
    val jsonState = state.asJson.deepDropNullValues.noSpaces
    Hash.fromBytes(jsonState.getBytes(StandardCharsets.UTF_8))
  }
        
```

The code above is an example of how to implement the hashing of `calculatedState`.

#### dataEncoder and dataDecoder[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/data/lifecycle-functions#dataencoder-and-datadecoder) <a href="#dataencoder-and-datadecoder" id="dataencoder-and-datadecoder"></a>

Custom encoders/decoders for the updates. It should be implemented in both `Main.scala` files for the `l0` and `data-l1` layers

```
def dataEncoder: Encoder[Update] = deriveEncoder
def dataDecoder: Decoder[Update] = deriveDecoder
```

The code above uses the `circe` semiauto deriveEncoder and deriveDecoder

#### calculatedStateEncoder and calculatedStateDecoder[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/data/lifecycle-functions#calculatedstateencoder-and-calculatedstatedecoder) <a href="#calculatedstateencoder-and-calculatedstatedecoder" id="calculatedstateencoder-and-calculatedstatedecoder"></a>

Custom encoders/decoders for the calculatedStates. It should be implemented in both `Main.scala` files for the `l0` and `data-l1` layers

```
def calculatedStateEncoder: Encoder[CalculatedState] = deriveEncoder
def calculatedStateDecoder: Decoder[CalculatedState] = deriveDecoder
```

The code above uses the `circe` semiauto deriveEncoder and deriveDecoder

[Edit this page](https://github.com/Constellation-Labs/documentation-hub/edit/main/sdk/metagraph-framework/05-data/03-lifecycle-functions.md)


# Framework Endpoints

A metagraph functions similarly to a traditional back-end server, interacting with the external world through HTTP endpoints with specific read (GET) and write (POST) functionalities. While a metagraph is decentralized by default and backed by an on-chain data store, it operates much like any other web server. This section outlines the default endpoints available to developers to interact with their metagraph.

See also [Custom Queries](/metagraph-development/metagraph-framework/custom-endpoints) for information on how to create your own metagraph endpoints.

### Endpoints[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/framework-endpoints#framework-endpoints) <a href="#framework-endpoints" id="framework-endpoints"></a>

Below is a list of available endpoints made available by default through the Metagraph Framework. Each endpoint is hosted by a node running either the Metagraph L0, Currency L1, or Data L1.

This is not an exhaustive list of available endpoints, please see [Metagraph APIs](/network-apis/metagraph-apis) for more information and links to the OpenAPI specifications of each API.

#### Universally Available Endpoints[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/framework-endpoints#universally-available-endpoints) <a href="#universally-available-endpoints" id="universally-available-endpoints"></a>

These endpoints are available on all (mL0, cL1, and dL1) APIs and are useful for debugging and monitoring purposes.

| Method | Endpoint      | Description                                                                                                                                                                                                        |
| ------ | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| GET    | /node/info    | Returns info about the health and connectivity state of a particular node. This is useful for understanding if a node is connected to its layer of the network and its ready state.                                |
| GET    | /cluster/info | Returns info about the cluster of nodes connected to the node's layer of the network. This is useful for understanding how many nodes are connected at each layer and diagnosing issues related to cluster health. |

#### Metagraph L0[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/framework-endpoints#metagraph-l0) <a href="#metagraph-l0" id="metagraph-l0"></a>

Endpoints available on metagraph L0 nodes.

| Method | Endpoint                   | Description                                                                                                                                                                                                                                                 |
| ------ | -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| GET    | /snapshots/latest          | Returns the latest incremental snapshot created by the metagraph. Incremental snapshots contain only changes since the previous snapshot. This endpoint also supports returning snapshots at specific ordinals with the format \`GET /snapshots/:ordinal\`. |
| GET    | /snapshots/latest/combined | Returns the latest full snapshot of the metagraph which includes some calculated values. This shows the complete state of the metagraph at that moment in time.                                                                                             |
| GET    | /currency/:address/balance | Returns the balance of a particular address on the metagraph at the current snapshot.                                                                                                                                                                       |
| GET    | /currency/total-supply     | Returns the total number of tokens in circulation at the current snapshot. Note that "total supply" in this case is total supply created currently. It doesn't represent max supply of the token.                                                           |

#### Currency L1[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/framework-endpoints#currency-l1) <a href="#currency-l1" id="currency-l1"></a>

Endpoints available on currency L1 nodes.

| Method | Endpoint                              | Description                                                                                                                                                 |
| ------ | ------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| POST   | /transactions                         | Accepts signed L0 token transactions.                                                                                                                       |
| GET    | /transactions/:hash                   | Returns a single transaction by hash if the transaction is in the node's mempool waiting to be processed. Does not have access to non-pending transactions. |
| GET    | /transactions/last-reference/:address | Returns the lastRef value for the provided address. LastRef is necessary for constructing a new transaction.                                                |
| POST   | /estimate-fee                         | Returns the minimum fee required give the (unsigned) currency transaction.                                                                                  |

#### Data L1[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/framework-endpoints#data-l1) <a href="#data-l1" id="data-l1"></a>

| Method | Endpoint           | Description                                                                                                   |
| ------ | ------------------ | ------------------------------------------------------------------------------------------------------------- |
| POST   | /data              | Accepts custom-defined data updates.                                                                          |
| GET    | /data              | Returns all data updates in mempool waiting to be processed.                                                  |
| POST   | /data/estimate-fee | (v2.9.0+) Returns the minimum fee and destination address to process the given (unsigned) custom data update. |


# Custom Endpoints

Metagraph developers have the ability to define their own endpoints to add additional functionality to their applications. Custom endpoints are supported on each of the layers, with different contextual data and scalability considerations for each. These endpoints can be used to provide custom views into snapshot state, or for any custom handling that the developer wishes to include as part of the application.

### Defining a Route[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/custom-endpoints#defining-a-route) <a href="#defining-a-route" id="defining-a-route"></a>

A route can be defined by overriding the `routes` function available on `DataApplicationL0Service` or `DataApplicationL1Service`, creating endpoints on the metagraph L0 node or data L1 node, respectively. Custom routes are defined as instances of http4s `HttpRoutes`.

Here is a minimal example that shows how to return a map of currency addresses with a balance on the metagraph. The example accesses the `addresses` property of L0 chain context and returns it to the requester.

```
  // modules/l0/.../l0/Main.scala

  override def routes(implicit context: L0NodeContext[IO]): HttpRoutes[IO] = HttpRoutes.of {
    case GET -> Root / "addresses" =>
      OptionT(context.getLastCurrencySnapshot)
        .flatMap(_.dataApplication.toOptionT)
        .flatMapF(da => deserializeState(da.onChainState).map(_.toOption))
        .value
        .flatMap {
          case Some(value) => Ok(value.addresses)
          case None => NotFound()
        }
  }
```

For a slightly more complex example, the code below shows how to return the Data Application's calculated state from an endpoint. It also shows a more common pattern for route definition which moves route definitions to their own file, defined as a case class extending `Http4sDsl[F]`. Note that `calculatedStateService` is not available as part of `L0NodeContext` so it must be passed to the case class.

```
  // modules/l0/.../l0/Main.scala
  override def routes(implicit context: L0NodeContext[IO]): HttpRoutes[IO] = CustomRoutes[IO](calculatedStateService).public

  // modules/l0/.../l0/CustomRoutes.scala
  case class CustomRoutes[F[_] : Async](calculatedStateService: CalculatedStateService[F]) extends Http4sDsl[F] with PublicRoutes[F] {
    @derive(encoder, decoder)
    case class CalculatedStateResponse(
      ordinal        : Long,
      calculatedState: CheckInDataCalculatedState
    )

    private def getLatestCalculatedState: F[Response[F]] = {
      calculatedStateService.getCalculatedState
        .map(state => CalculatedStateResponse(state.ordinal.value.value, state.state))
        .flatMap(Ok(_))
    }

    private val routes: HttpRoutes[F] = HttpRoutes.of[F] {
      case GET -> Root / "calculated-state" / "latest" => getLatestCalculatedState
    }

    val public: HttpRoutes[F] =
      CORS
        .policy
        .withAllowCredentials(false)
        .httpRoutes(routes)

    override protected def prefixPath: InternalUrlPrefix = "/"
  }
```

#### Custom Route Prefix[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/custom-endpoints#custom-route-prefix) <a href="#custom-route-prefix" id="custom-route-prefix"></a>

All custom defined routes exist under a prefix, shown in the example above as `Root`. By default this prefix is `/data-application`, so for example you might define an `addresses` route which would be found at `http://<base-url>:port/data-application/addresses`.

It is possible to override the default prefix to provide your own custom prefix by overriding the `routesPrefix` method.

For example, to use the prefix "/d" instead of "/data-application":

```
  override def routesPrefix: ExternalUrlPrefix = "/d"
```

### Examples[​](https://docs.constellationnetwork.io/sdk/metagraph-framework/custom-endpoints#examples) <a href="#examples" id="examples"></a>

For more complete examples of custom route implementations, see [Example Codebases](/metagraph-development/resources/example-codebases).


# Quick Start

## Quick Start Guide

This guide will walk you through the process of setting up a minimal development environment using the Euclid Development Environment project, installing the Metagraph Framework, and launching clusters. The process should take less than an hour, including installing dependencies.

{% hint style="info" %}
**Windows Support**

Primary development focus for this SDK is based on UNIX-based operating systems like macOS or Linux. With that being said, Windows support is available using the Windows Subsystem for Linux (WSL) to emulate a UNIX environment. The following guide has been tested in that environment and works wells.

See [Install WSL](https://learn.microsoft.com/en-us/windows/wsl/install) for more detail in setting up WSL on your Windows machine.
{% endhint %}

## Install Dependencies[​](https://docs.constellationnetwork.io/sdk/guides/quick-start#install-dependencies) <a href="#install-dependencies" id="install-dependencies"></a>

**Install Basic Dependencies**[**​**](https://docs.constellationnetwork.io/sdk/guides/quick-start#install-basic-dependencies)

Many developers can skip this step because these dependencies are already installed.

* [Node JS](https://nodejs.org/en)
* [Yarn](https://classic.yarnpkg.com/en/docs/install)
* [Docker](https://docs.docker.com/get-docker/)
* [Cargo](https://doc.rust-lang.org/cargo/getting-started/installation.html)
* [Ansible](https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html)
* [Scala 2.13](https://www.scala-lang.org/download/)
* [Jq](https://jqlang.github.io/jq/download/)
* [Yq](https://github.com/mikefarah/yq)

**Install argc**[**​**](https://docs.constellationnetwork.io/sdk/guides/quick-start#install-argc)

```sh
cargo install argc
```

**Install Giter**[**​**](https://docs.constellationnetwork.io/sdk/guides/quick-start#install-giter)

```sh
cs install giter8
```

**Configure Docker**[**​**](https://docs.constellationnetwork.io/sdk/guides/quick-start#configure-docker)

The Euclid Development Environment starts up to 10 individual docker containers to create a minimal development environment which takes some significant system resources. Configure docker to make at least 8GB of RAM available. If you are using Docker Desktop, this setting can be found under Preferences -> Resources.

## Install[​](https://docs.constellationnetwork.io/sdk/guides/quick-start#install) <a href="#install" id="install"></a>

**Clone**[**​**](https://docs.constellationnetwork.io/sdk/guides/quick-start#clone)

Clone the Euclid Development Environment project to your local machine.

```sh
git clone https://github.com/Constellation-Labs/euclid-development-environment
cd euclid-development-environment
```

See the [Development Environment](/metagraph-development/elements/development-environment) section for an overview of the directory structure of the project.

**Configure**[**​**](https://docs.constellationnetwork.io/sdk/guides/quick-start#configure)

Update the `project_name` field to the name of your project.

**Hydra**[**​**](https://docs.constellationnetwork.io/sdk/guides/quick-start#hydra)

Familiarize yourself with the `hydra` CLI. We can use the `hydra` CLI tool to build the necessary docker containers and manage our network clusters.

```sh
scripts/hydra -h

USAGE: hydra <COMMAND>

COMMANDS:
  install                           Installs a local framework and detaches project
  install-template                  Installs a project from templates
  build                             Build containers
  start-genesis                     Start containers from the genesis snapshot (erasing history) [aliases: start_genesis]
  start-rollback                    Start containers from the last snapshot (maintaining history) [aliases: start_rollback]
  stop                              Stop containers
  destroy                           Destroy containers
  purge                             Destroy containers and images
  status                            Check the status of the containers
  remote-deploy                     Remotely deploy to cloud instances using Ansible [aliases: remote_deploy]
  remote-start                      Remotely start the metagraph on cloud instances using Ansible [aliases: remote_start]
  remote-status                     Check the status of the remote nodes
  update                            Update Euclid
  logs                              Get the logs from containers
  install-monitoring-service        Download the metagraph-monitoring-service (https://github.com/Constellation-Labs/metagraph-monitoring-service) [aliases: install_monitoring_service]
  remote-deploy-monitoring-service  Deploy the metagraph-monitoring-service to remote host [aliases: remote_deploy_monitoring_service]
  remote-start-monitoring-service   Start the metagraph-monitoring-service on remote host [aliases: remote_start_monitoring_service]
```

**Install Project**[**​**](https://docs.constellationnetwork.io/sdk/guides/quick-start#install-project)

Running the `install` command will do two things:

* Creates currency-l0 and currency-l1 projects from a g8 template and moves them to the `source/project` directory.
* Detach your project from the source repo.

Detaching your project from the source repo removes its remote git configuration and prepares your project to be included in your own version control. Once detached, your project can be updated with `hydra`.

```sh
scripts/hydra install   
```

You can import a metagraph template from custom examples by using the following command:

```sh
scripts/hydra install-template
```

By default, we use the [Metagraph Examples](https://github.com/Constellation-Labs/metagraph-examples) repository. You should provide the template name when running this command. To list the templates available to install, type:

```sh
scripts/hydra install-template --list
```

## Build[​](https://docs.constellationnetwork.io/sdk/guides/quick-start#build) <a href="#build" id="build"></a>

Build your network clusters with hydra. By default, this builds `metagraph-ubuntu`, `metagraph-base-image`, and `prometheus` + `grafana` monitoring containers. These images will allow deploy the containers with metagraph layers: `global-l0`, `metagraph-l0`, `currency-l1`, and `data-l1`. The `dag-l1` layer is not built by default since it isn't strictly necessary for metagraph development. You can include it on the `euclid.json` file.

Start the build process. This can take a significant amount of time... be patient.

```sh
scripts/hydra build
```

## Run[​](https://docs.constellationnetwork.io/sdk/guides/quick-start#run) <a href="#run" id="run"></a>

After your containers are built, go ahead and start them with the `start-genesis` command. This starts all network components from a fresh genesis snapshot.

```sh
scripts/hydra start-genesis
```

Once the process is complete you should see output like this:

```sh
################################################################
######################### METAGRAPH INFO #########################

Metagraph ID: :your_id


Container metagraph-node-1 URLs
Global L0: http://localhost:9000/node/info
Metagraph L0: http://localhost:9200/node/info
Currency L1: http://localhost:9300/node/info
Data L1: http://localhost:9400/node/info


Container metagraph-node-2 URLs
Metagraph L0: http://localhost:9210/node/info
Currency L1: http://localhost:9310/node/info
Data L1: http://localhost:9410/node/info


Container metagraph-node-3 URLs
Metagraph L0: http://localhost:9220/node/info
Currency L1: http://localhost:9320/node/info
Data L1: http://localhost:9420/node/info


Clusters URLs
Global L0: http://localhost:9000/cluster/info
Metagraph L0: http://localhost:9200/cluster/info
Currency L1: http://localhost:9300/cluster/info
Data L1: http://localhost:9400/cluster/info

####################################################################
```

You can also check the status of your containers with the `status` command.

```sh
scripts/hydra status
```

## Next Steps[​](https://docs.constellationnetwork.io/sdk/guides/quick-start#next-steps) <a href="#next-steps" id="next-steps"></a>

You now have a minimal development environment installed and running 🎉

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th></th></tr></thead><tbody><tr><td><strong>Send your first transaction</strong></td><td>Set up the FE Developer Dashboard and send your hello world metagraph transaction.</td></tr><tr><td><strong>Manual Setup</strong></td><td>Prefer to configure your environment by hand? Explore manual setup.</td></tr></tbody></table>


# Send a Transaction

In this guide, we will explore two of the tools that work together with the Euclid Developer Environment, then use them to send and track our first metagraph token transaction.

We will install the [Developer Dashboard](/metagraph-development/elements/telemetry-dashboard), send a transaction using an included script, and monitor our clusters using the [Telemetry Dashboard](https://docs.constellationnetwork.io/sdk/elements/telemetry-dashboard).

### Before You Start[​](https://docs.constellationnetwork.io/sdk/guides/send-transaction#before-you-start) <a href="#before-you-start" id="before-you-start"></a>

This guide assumes that you have configured your local environment based on the [Quick Start Guide](/metagraph-development/guides/quick-start) and have at least your `global-l0`, `currency-l0`, `currency-l1`, and `monitoring` clusters running.

### Install the SDK Developer Dashboard[​](https://docs.constellationnetwork.io/sdk/guides/send-transaction#install-the-sdk-developer-dashboard) <a href="#install-the-sdk-developer-dashboard" id="install-the-sdk-developer-dashboard"></a>

The Developer Dashboard is a frontend dashboard built with NextJS and Tailwind CSS. It comes with default configuration to work with the Development Environment on install.

### Setup Guide[​](https://docs.constellationnetwork.io/sdk/guides/send-transaction#setup-guide) <a href="#setup-guide" id="setup-guide"></a>

#### Prerequisites[​](https://docs.constellationnetwork.io/sdk/guides/send-transaction#prerequisites) <a href="#prerequisites" id="prerequisites"></a>

* Node.js (`v16` recommended)
* `npm` or `yarn` package manager

#### Installation[​](https://docs.constellationnetwork.io/sdk/guides/send-transaction#installation) <a href="#installation" id="installation"></a>

1. Clone the repository

   ```
   git clone https://github.com/Constellation-Labs/sdk-developer-dashboard.git
   cd sdk-developer-dashboard
   ```
2. Install dependencies

   ```
   # Using yarn (recommended)
   yarn install

   # Or using npm
   npm install
   ```
3. Start the development server

   ```
   # Using yarn
   yarn dev

   # Or using npm
   npm run dev
   ```

### View the Developer Dashboard[​](https://docs.constellationnetwork.io/sdk/guides/send-transaction#view-the-developer-dashboard) <a href="#view-the-developer-dashboard" id="view-the-developer-dashboard"></a>

Open a browser window to `http://localhost:8080`.

Here, you can see both your currency and global clusters at work. You should see the snapshot ordinals for the Global L0 and the Currency L0 increment on your dashboard. Also notice that you can inspect each snapshot to see its contents. Any transactions sent on the network will appear in the tables below - there are separate tables for DAG and Metagraph Token transactions.

The dashboard is designed to work with the Euclid Development Environment default settings out-of-the-box, but if you need to change network settings, they can be found in the `.env` file at the root of the project.

### Send a Transaction[​](https://docs.constellationnetwork.io/sdk/guides/send-transaction#send-a-transaction) <a href="#send-a-transaction" id="send-a-transaction"></a>

The Developer Dashboard comes pre-installed with scripts to send transactions to your running metagraph. The scripts use [dag4.js](https://github.com/StardustCollective/dag4.js) to interact with the network based on the settings in your `.env` file.

**Single Transaction**[**​**](https://docs.constellationnetwork.io/sdk/guides/send-transaction#single-transaction)

Single transactions can be sent on the command line for easy testing. The transaction below should succeed with the default configuration.

```
yarn metagraph-transaction:send --seed="drift doll absurd cost upon magic plate often actor decade obscure smooth" --transaction='{"destination": "DAG4o41NzhfX6DyYBTTXu6sJa6awm36abJpv89jB","amount":99, "fee":0}'
```

**Bulk Transactions**[**​**](https://docs.constellationnetwork.io/sdk/guides/send-transaction#bulk-transactions)

You can send bulk transactions to the network by calling `send-bulk` and providing a path to a json file with transaction configuration. A sample JSON file is provided for you which will work with the default configuration.

```
yarn metagraph-transaction:send-bulk --config="./scripts/send_transactions/batch_transactions.example.json"
```

**View Transactions**[**​**](https://docs.constellationnetwork.io/sdk/guides/send-transaction#view-transactions)

Return to the dashboard and look in the Currency Transactions table. You should see the transactions you just sent. You can also view the contents of the snapshot that the transaction's block was included in.

### Monitoring[​](https://docs.constellationnetwork.io/sdk/guides/send-transaction#monitoring) <a href="#monitoring" id="monitoring"></a>

Now that you have sent a transaction or two we can check on the stability of the network with the [Telemetry Dashboard](https://docs.constellationnetwork.io/sdk/elements/telemetry-dashboard). The Telemetry Dashboard is composed of two containers included as part of the Development Environment: a Prometheus instance and a Grafana instance.

The dashboard is hosted on the Grafana instance which can be accessed at `http://localhost:3000/`.

The initial login and password are:

```
username: admin
password: admin
```

The Grafana instance includes two dashboards which can be found in the menu on the left. One dashboard monitors the Global L0 and DAG L1 (if you have it running). The other monitors the Currency L0 and Currency L1. More information can be found in the [Telemetry Dashboard](https://docs.constellationnetwork.io/sdk/elements/telemetry-dashboard) section.


# Manual Setup

This guide walks through the detailed process of manually creating a minimal development environment using docker containers and manual configuration. Most developers will be more productive using the automatic setup and configuration of the Euclid Development Environment with the Hydra CLI. The following is provided for project teams looking to create their own custom configurations outside the default development environment.

### Generate P12 Files[​](https://docs.constellationnetwork.io/sdk/guides/manual-setup#generate-p12-files) <a href="#generate-p12-files" id="generate-p12-files"></a>

Generate your own `p12` files following the steps below: (java 11 must be installed)

1. Download the cl-keytool file [here](https://github.com/Constellation-Labs/tessellation/releases)
2. We need to generate 3 `p12` files: 1 for Genesis Nodes (Global L0, Currency L0, and Currency L1 - 1), 1 for second node on cluster (Currency L1 - 2), 1 for third node on cluster (Currency L1 - 3).
3. Export the follow variables on your terminal with the values replaced to generate the first `p12` file.

```
export CL_KEYSTORE=":name-of-your-file.p12"
export CL_KEYALIAS=":name-of-your-file"
export CL_PASSWORD=":password"
```

1. Run the following instruction:

```
java -jar cl-keytool.jar generate
```

1. This will generate the first file for you
2. Change the variables CL\_KEYSTORE, CL\_KEYALIAS, and CL\_PASSWORD and repeat the step 2 more times
3. At the end you should have 3 `p12` files

### Common Steps[​](https://docs.constellationnetwork.io/sdk/guides/manual-setup#common-steps) <a href="#common-steps" id="common-steps"></a>

#### Create Containers[​](https://docs.constellationnetwork.io/sdk/guides/manual-setup#create-containers) <a href="#create-containers" id="create-containers"></a>

With Docker installed on your machine run:

```
docker run -e LANG=C.UTF-8 -e LC_ALL=C.UTF-8 -it -p 9000:9000 -p 9001:9001 -p 9002:9002--name :container_name_global_l0 --entrypoint "/bin/bash" ubuntu:20.04
docker run -e LANG=C.UTF-8 -e LC_ALL=C.UTF-8 -it -p 9100:9000 -p 9101:9001 -p 9102:9002--name :container_name_currency_l0 --entrypoint "/bin/bash" ubuntu:20.04
docker run -e LANG=C.UTF-8 -e LC_ALL=C.UTF-8 -it -p 9200:9000 -p 9201:9001 -p 9202:9002--name :container_name_currency_l1_1 --entrypoint "/bin/bash" ubuntu:20.04
docker run -e LANG=C.UTF-8 -e LC_ALL=C.UTF-8 -it -p 9300:9000 -p 9301:9001 -p 9302:9002--name :container_name_currency_l1_2 --entrypoint "/bin/bash" ubuntu:20.04
docker run -e LANG=C.UTF-8 -e LC_ALL=C.UTF-8 -it -p 9400:9000 -p 9401:9001 -p 9402:9002--name :container_name_currency_l1_3 --entrypoint "/bin/bash" ubuntu:20.04
```

*Replace the \`:containername*\` with the name that you want for your container\*

#### Create a Docker Network[​](https://docs.constellationnetwork.io/sdk/guides/manual-setup#create-a-docker-network) <a href="#create-a-docker-network" id="create-a-docker-network"></a>

We need to create a docker custom network by running the following:

```
docker network create custom-network-tokens
```

#### Build the Container Libs[​](https://docs.constellationnetwork.io/sdk/guides/manual-setup#build-the-container-libs) <a href="#build-the-container-libs" id="build-the-container-libs"></a>

In your container run the following instructions:

```
apt-get update

apt install openjdk-11-jdk -y #jdk 11 to run the jars
apt-get install curl -y #install curl
apt-get install wget -y #install wget
apt-get install gnupg -y #used to add sbt repo
apt-get install vim -y #used to edit files, you can use the editor that you want to

echo "deb https://repo.scala-sbt.org/scalasbt/debian all main" | tee /etc/apt/sources.list.d/sbt.list
echo "deb https://repo.scala-sbt.org/scalasbt/debian /" | tee /etc/apt/sources.list.d/sbt_old.list
curl -sL "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x2EE0EA64E40A89B84B2DF73499E82A75642AC823" | apt-key add

apt-get update
apt-get install sbt -y #install sbt
```

The instructions above install the dependencies to run correctly the node.

#### Tessellation repository[​](https://docs.constellationnetwork.io/sdk/guides/manual-setup#tesselation-repository) <a href="#tesselation-repository" id="tesselation-repository"></a>

Clone the repository:

```
git clone https://github.com/Constellation-Labs/tessellation.git
git checkout v2.0.0-alpha.2
```

**warning**

Make sure you're using the latest version of Tessellation. You can find the most recent release in [**here**](https://github.com/Constellation-Labs/tessellation/releases).

Move to the tessellation folder and checkout to branch/version that you want. You can skip the `git checkout :version` if you want to use the develop default branch

```
cd tesselation
git checkout :version
```

### Global L0[​](https://docs.constellationnetwork.io/sdk/guides/manual-setup#global-l0) <a href="#global-l0" id="global-l0"></a>

* Here is the instructions to run specifically Global L0 container.
* Move the `p12` file to container with the instruction:

```
docker cp :directory-of-p12-file container-name:file-name.p12
```

* Inside the docker container make sure that your p12 file exists correctly
* It should be at the root level (same level as the tessellation folder)
* Move to tessellation folder:

```
cd tessellation/
```

* Generate the jars

```
sbt core/assembly wallet/assembly
```

* Check the logs to see which version of global-l0 and wallet was published. It should be something like this:

```
/tessellation/modules/core/target/scala-2.13/tessellation-core-assembly-*.jar
```

* Move these jars to the root folder, like the example below

```
mv codebase/tessellation/modules/core/target/scala-2.13/tessellation-core-assembly-* global-l0.jar
mv codebase/tessellation/modules/wallet/target/scala-2.13/tessellation-wallet-assembly-* cl-wallet.jar
```

* Run the following command to get the clusterId (**store this information**):

```
java -jar cl-wallet.jar show-id
```

* Run the following command to get the clusterAddress (**store this information**):

```
java -jar cl-wallet.jar show-address
```

* Outside the container, run this following command to get your docker container IP

```
docker container inspect :container_name | grep -i IPAddress
```

* Outside the container, we need to join our container to the created network, you can do this with the following command (outside the container)

```
docker network connect custom-network-tokens :container_name  
```

* You can check now your network and see your container there:

```
docker network inspect custom-network
```

* Fill the environment variables necessary to run the container (from your first `p12` file):

```
export CL_KEYSTORE=":name-of-your-file.p12"
export CL_KEYALIAS=":name-of-your-file"
export CL_PASSWORD=":password"
export CL_APP_ENV=dev
export CL_COLLATERAL=0
export CL_ENV=dev
```

* Create one empty genesis file in root directory too (you can add wallets and amounts if you want to):

```
touch genesis.csv
```

* Finally, run the jar:

```
java -jar global-l0.jar run-genesis genesis.csv --ip :ip_of_your_container
```

* Your should see something like this:

```
23:26:53.013 [io-compute-blocker-3] INFO  o.t.s.a.TessellationIOApp - App environment: Dev
23:26:53.052 [io-compute-blocker-3] INFO  o.t.s.a.TessellationIOApp - App version: 2.0.0-alpha.2
[WARNING] Your CPU is probably starving. Consider increasing the granularity
of your delays or adding more cedes. This may also be a sign that you are
unintentionally running blocking I/O operations (such as File or InetAddress)
without the blocking combinator.
[WARNING] Your CPU is probably starving. Consider increasing the granularity
of your delays or adding more cedes. This may also be a sign that you are
unintentionally running blocking I/O operations (such as File or InetAddress)
without the blocking combinator.
23:27:03.051 [io-compute-5] INFO  o.t.s.a.TessellationIOApp - Self peerId: b1cf4d017eedb3e187b4d17cef9bdbcfdb2e57b26e346e9186da3a7a2b9110d73481fedbc6de23db51fb932371c54b02fff3388712dcb1e902870da7fa472f66
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.esotericsoftware.kryo.util.UnsafeUtil (file:/code/global-l0.jar) to constructor java.nio.DirectByteBuffer(long,int,java.lang.Object)
WARNING: Please consider reporting this to the maintainers of com.esotericsoftware.kryo.util.UnsafeUtil
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
23:27:04.670 [io-compute-5] INFO  o.t.s.a.TessellationIOApp - Seedlist disabled.
23:27:18.263 [io-compute-1] INFO  o.h.e.s.EmberServerBuilderCompanionPlatform - Ember-Server service bound to address: 0.0.0.0:9000
23:27:18.270 [io-compute-1] INFO  o.t.s.r.MkHttpServer - HTTP Server name=public started at /0.0.0.0:9000
23:27:18.315 [io-compute-2] INFO  o.h.e.s.EmberServerBuilderCompanionPlatform - Ember-Server service bound to address: 0.0.0.0:9001
23:27:18.316 [io-compute-2] INFO  o.t.s.r.MkHttpServer - HTTP Server name=p2p started at /0.0.0.0:9001
23:27:18.357 [io-compute-1] INFO  o.h.e.s.EmberServerBuilderCompanionPlatform - Ember-Server service bound to address: 127.0.0.1:9002
23:27:18.359 [io-compute-1] INFO  o.t.s.r.MkHttpServer - HTTP Server name=cli started at /127.0.0.1:9002
23:27:20.400 [io-compute-3] INFO  o.t.s.i.c.d.N.$anon - Node state changed to=Ready{}
```

* That's all for the global-l0 container

### Currency L0[​](https://docs.constellationnetwork.io/sdk/guides/manual-setup#currency-l0) <a href="#currency-l0" id="currency-l0"></a>

* Here is the instructions to run specifically Currency L0 container.
* Move the `p12` file to container with the instruction:

```
docker cp :directory-of-p12-file container-name:file-name.p12
```

* Inside the docker container make sure that your p12 file exists correctly
* It should be at the root level (same level as the tessellation folder)
* Move to tessellation folder:

```
cd tessellation/
```

* Generate the jars

```
sbt currencyL0/assembly
```

* Check the logs to see which version of currency-l0 was published. It should be something like this:

```
/tessellation/modules/currency-l0/target/scala-2.13/tessellation-currency-l0-assembly-*.jar
```

* Move this jar to the root folder, like the example below

```
mv codebase/tessellation/modules/core/target/scala-2.13/tessellation-currency-l0-assembly-* currency-l0.jar
```

* Outside the container, run this following command to get your docker container IP

```
docker container inspect :container_name | grep -i IPAddress
```

* Outside the container, we need to join our container to the created network, you can do this with the following command (outside the container)

```
docker network connect custom-network-tokens :container_name  
```

* You can check now your network and see your container there:

```
docker network inspect custom-network
```

* Fill the environment variables necessary to run the container (from your first `p12` file):

```
export CL_KEYSTORE=":name-of-your-file.p12"
export CL_KEYALIAS=":name-of-your-file"
export CL_PASSWORD=":password"
export CL_GLOBAL_L0_PEER_ID=:id_got_of_command_cl_wallet_show_id
export CL_L0_TOKEN_IDENTIFIER=:id_got_of_command_cl_wallet_show_address
export CL_PUBLIC_HTTP_PORT=9000
export CL_P2P_HTTP_PORT=9001
export CL_CLI_HTTP_PORT=9002
export CL_GLOBAL_L0_PEER_HTTP_HOST=:ip-global-l0-container
export CL_GLOBAL_L0_PEER_HTTP_PORT=9000
export CL_APP_ENV=dev
export CL_COLLATERAL=0
```

* Create one genesis file in root directory too (you can add wallets and amounts if you want to):

```
touch genesis.csv
```

* You should edit this `genesis.csv` to add your addresses and amounts. You can use `vim` for that:

```
vim genesis.csv
```

* Example of genesis content:

```
DAG8pkb7EhCkT3yU87B2yPBunSCPnEdmX2Wv24sZ,1000000000000
DAG4o41NzhfX6DyYBTTXu6sJa6awm36abJpv89jB,1000000000000
DAG4Zd2W2JxL1f1gsHQCoaKrRonPSSHLgcqD7osU,1000000000000
```

* Finally, run the jar:

```
java -jar currency-l0.jar run-genesis genesis.csv --ip :ip_of_current_container
```

* Your should see something like this:

```
23:28:33.769 [io-compute-blocker-3] INFO  o.t.s.a.TessellationIOApp - App environment: Dev
23:28:33.829 [io-compute-blocker-3] INFO  o.t.s.a.TessellationIOApp - App version: 2.0.0-alpha.2
23:29:25.489 [io-compute-2] INFO  o.h.e.s.EmberServerBuilderCompanionPlatform - Ember-Server service bound to address: 0.0.0.0:9000
23:29:25.520 [io-compute-2] INFO  o.t.s.r.MkHttpServer - HTTP Server name=public started at /0.0.0.0:9000
23:29:25.606 [io-compute-2] INFO  o.h.e.s.EmberServerBuilderCompanionPlatform - Ember-Server service bound to address: 0.0.0.0:9001
23:29:25.608 [io-compute-2] INFO  o.t.s.r.MkHttpServer - HTTP Server name=p2p started at /0.0.0.0:9001
23:29:25.795 [io-compute-3] INFO  o.h.e.s.EmberServerBuilderCompanionPlatform - Ember-Server service bound to address: 127.0.0.1:9002
23:29:25.796 [io-compute-3] INFO  o.t.s.r.MkHttpServer - HTTP Server name=cli started at /127.0.0.1:9002
23:29:44.671 [io-compute-3] INFO  o.t.c.l.s.s.G.$anon - Genesis binary 3c02294a7a3c7b3a8f2af8c9633a82af46430cda7ffc2de0fc0c6f19afb497e0 and 57a4f918ce8228be1282834ece3e6f69ad87d69b42857dbb227b5e6441b25025 accepted and sent to Global L0
```

* That's all for the currency-l0 container

### Currency L1 - 1[​](https://docs.constellationnetwork.io/sdk/guides/manual-setup#currency-l1---1) <a href="#currency-l1---1" id="currency-l1---1"></a>

* Here is the instructions to run specifically Currency L1 - 1 container.
* Move the `p12` file to container with the instruction:

```
docker cp :directory-of-p12-file container-name:file-name.p12
```

* Inside the docker container make sure that your p12 file exists correctly
* It should be at the root level (same level as the tessellation folder)
* Move to tessellation folder:

```
cd tessellation/
```

* Generate the jars

```
sbt currencyL1/assembly
```

* Check the logs to see which version of currency-l1 was published. It should be something like this:

```
/tessellation/modules/currency-l1/target/scala-2.13/tessellation-currency-l1-assembly-*.jar
```

* Move this jar to the root folder, like the example below

```
mv codebase/tessellation/modules/currency-l1/target/scala-2.13/tessellation-currency-l1-assembly-* currency-l1.jar
```

* Outside the container, run this following command to get your docker container IP

```
docker container inspect :container_name | grep -i IPAddress
```

* Outside the container, we need to join our container to the created network, you can do this with the following command (outside the container)

```
docker network connect custom-network-tokens :container_name  
```

* You can check now your network and see your container there:

```
docker network inspect custom-network
```

* Fill the environment variables necessary to run the container (from your first `p12` file):

```
export CL_KEYSTORE=":name-of-your-file.p12"
export CL_KEYALIAS=":name-of-your-file"
export CL_PASSWORD=":password"
export CL_GLOBAL_L0_PEER_ID=:id_got_of_command_cl_wallet_show_id
export CL_L0_PEER_ID=:id_got_of_command_cl_wallet_show_id
export CL_L0_TOKEN_IDENTIFIER=:id_got_of_command_cl_wallet_show_address
export CL_PUBLIC_HTTP_PORT=9000
export CL_P2P_HTTP_PORT=9001
export CL_CLI_HTTP_PORT=9002
export CL_GLOBAL_L0_PEER_HTTP_HOST=:ip-global-l0-container
export CL_GLOBAL_L0_PEER_HTTP_PORT=9000
export CL_L0_PEER_HTTP_HOST=:ip-currency-l0-container
export CL_L0_PEER_HTTP_PORT=9000
export CL_APP_ENV=dev
export CL_COLLATERAL=0
```

* Finally, run the jar:

```
java -jar currency-l1.jar run-initial-validator  --ip :ip_of_current_container
```

* Your should see something like this:

```
23:31:34.892 [io-compute-blocker-3] INFO  o.t.s.a.TessellationIOApp - App environment: Dev
23:31:34.901 [io-compute-blocker-3] INFO  o.t.s.a.TessellationIOApp - App version: 2.0.0-alpha.2
23:31:38.257 [io-compute-1] INFO  o.t.s.a.TessellationIOApp - Self peerId: b1cf4d017eedb3e187b4d17cef9bdbcfdb2e57b26e346e9186da3a7a2b9110d73481fedbc6de23db51fb932371c54b02fff3388712dcb1e902870da7fa472f66
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.esotericsoftware.kryo.util.UnsafeUtil (file:/code/currency-l1.jar) to constructor java.nio.DirectByteBuffer(long,int,java.lang.Object)
WARNING: Please consider reporting this to the maintainers of com.esotericsoftware.kryo.util.UnsafeUtil
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
23:31:39.054 [io-compute-1] INFO  o.t.s.a.TessellationIOApp - Seedlist disabled.
23:31:49.892 [io-compute-6] INFO  o.h.e.s.EmberServerBuilderCompanionPlatform - Ember-Server service bound to address: 0.0.0.0:9000
23:31:49.895 [io-compute-6] INFO  o.t.s.r.MkHttpServer - HTTP Server name=public started at /0.0.0.0:9000
23:31:49.917 [io-compute-6] INFO  o.h.e.s.EmberServerBuilderCompanionPlatform - Ember-Server service bound to address: 0.0.0.0:9001
23:31:49.918 [io-compute-6] INFO  o.t.s.r.MkHttpServer - HTTP Server name=p2p started at /0.0.0.0:9001
23:31:49.943 [io-compute-3] INFO  o.h.e.s.EmberServerBuilderCompanionPlatform - Ember-Server service bound to address: 127.0.0.1:9002
23:31:49.943 [io-compute-3] INFO  o.t.s.r.MkHttpServer - HTTP Server name=cli started at /127.0.0.1:9002
23:31:52.135 [io-compute-6] INFO  o.t.s.i.c.d.N.$anon - Node state changed to=Ready{}
23:31:57.435 [io-compute-0] DEBUG o.t.d.l.StateChannel - Received block consensus input to process: InspectionTrigger
23:31:57.635 [io-compute-3] DEBUG o.t.d.l.d.c.b.Validator - Cannot start own consensus: Not enough peers, Not enough tips, No transactions
23:32:02.598 [io-compute-1] DEBUG o.t.d.l.d.c.b.Validator - Cannot start own consensus: Not enough peers, Not enough tips, No transactions
23:32:02.658 [io-compute-2] DEBUG o.t.d.l.StateChannel - Received block consensus input to process: InspectionTrigger
23:32:06.858 [io-compute-0] INFO  o.t.d.l.StateChannel - Pulled following global snapshot: SnapshotReference{height=0,subHeight=11,ordinal=SnapshotOrdinal{value=11},lastSnapshotHash=93b341d24ce00f43abe054448afe29a43d6997bc0df6bd38821fe394d69a969f,hash=bc8aade10ab11efac2b180c48e78b060420dda6e72019061faf82ff8a8369fd7,proofsHash=9b869faaa608b3f3b8e2a9a4e548d371c11977ba2f5a498b9062f8d78d5e6676}
23:32:06.959 [io-compute-0] INFO  o.t.d.l.StateChannel - Snapshot processing result: DownloadPerformed{reference=SnapshotReference{height=0,subHeight=11,ordinal=SnapshotOrdinal{value=11},lastSnapshotHash=93b341d24ce00f43abe054448afe29a43d6997bc0df6bd38821fe394d69a969f,hash=bc8aade10ab11efac2b180c48e78b060420dda6e72019061faf82ff8a8369fd7,proofsHash=9b869faaa608b3f3b8e2a9a4e548d371c11977ba2f5a498b9062f8d78d5e6676},addedBlock=Set(),removedObsoleteBlocks=Set()}
23:32:07.172 [io-compute-0] DEBUG o.t.d.l.d.c.b.Validator - Cannot start own consensus: Not enough peers, Not enough tips, No transactions
23:32:07.177 [io-compute-2] DEBUG o.t.d.l.StateChannel - Received block consensus input to process: InspectionTrigger
23:32:12.178 [io-compute-0] DEBUG o.t.d.l.d.c.b.Validator - Cannot start own consensus: Not enough peers, Not enough tips, No transactions
23:32:12.219 [io-compute-0] DEBUG o.t.d.l.StateChannel - Received block consensus input to process: InspectionTrigger

```

* That's all for the currency-l1-1 container

### Currency L1 - 2[​](https://docs.constellationnetwork.io/sdk/guides/manual-setup#currency-l1---2) <a href="#currency-l1---2" id="currency-l1---2"></a>

* Here is the instructions to run specifically Currency L1 - 2 container.
* Move the `p12` file to container with the instruction (second `p12` file):

```
docker cp :directory-of-p12-file-2 container-name:file-name.p12
```

* Inside the docker container make sure that your p12 file exists correctly
* It should be at the root level (same level as the tessellation folder)
* Move to tessellation folder:

```
cd tessellation/
```

* Generate the jars

```
sbt currencyL1/assembly
```

* Check the logs to see which version of currency-l1 was published. It should be something like this:

```
/tessellation/modules/currency-l1/target/scala-2.13/tessellation-currency-l1-assembly-*.jar
```

* Move this jar to the root folder, like the example below

```
mv codebase/tessellation/modules/currency-l1/target/scala-2.13/tessellation-currency-l1-assembly-* currency-l1.jar
```

* Outside the container, run this following command to get your docker container IP

```
docker container inspect :container_name | grep -i IPAddress
```

* Outside the container, we need to join our container to the created network, you can do this with the following command (outside the container)

```
docker network connect custom-network-tokens :container_name  
```

* You can check now your network and see your container there:

```
docker network inspect custom-network
```

* Fill the environment variables necessary to run the container (from your first `p12` file):

```
export CL_KEYSTORE=":name-of-your-second-file.p12"
export CL_KEYALIAS=":name-of-your-second-file"
export CL_PASSWORD=":password"
export CL_GLOBAL_L0_PEER_ID=:id_got_of_command_cl_wallet_show_id
export CL_L0_PEER_ID=:id_got_of_command_cl_wallet_show_id
export CL_L0_TOKEN_IDENTIFIER=:id_got_of_command_cl_wallet_show_address
export CL_PUBLIC_HTTP_PORT=9000
export CL_P2P_HTTP_PORT=9001
export CL_CLI_HTTP_PORT=9002
export CL_GLOBAL_L0_PEER_HTTP_HOST=:ip-global-l0-container
export CL_GLOBAL_L0_PEER_HTTP_PORT=9000
export CL_L0_PEER_HTTP_HOST=:ip-currency-l0-container
export CL_L0_PEER_HTTP_PORT=9000
export CL_APP_ENV=dev
export CL_COLLATERAL=0
```

* Finally, run the jar:

```
java -jar currency-l1.jar run-validator  --ip :ip_of_current_container
```

* Your should see something like this:

```
23:31:34.892 [io-compute-blocker-3] INFO  o.t.s.a.TessellationIOApp - App environment: Dev
23:31:34.901 [io-compute-blocker-3] INFO  o.t.s.a.TessellationIOApp - App version: 2.0.0-alpha.2
23:31:38.257 [io-compute-1] INFO  o.t.s.a.TessellationIOApp - Self peerId: b1cf4d017eedb3e187b4d17cef9bdbcfdb2e57b26e346e9186da3a7a2b9110d73481fedbc6de23db51fb932371c54b02fff3388712dcb1e902870da7fa472f66
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.esotericsoftware.kryo.util.UnsafeUtil (file:/code/currency-l1.jar) to constructor java.nio.DirectByteBuffer(long,int,java.lang.Object)
WARNING: Please consider reporting this to the maintainers of com.esotericsoftware.kryo.util.UnsafeUtil
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
23:31:39.054 [io-compute-1] INFO  o.t.s.a.TessellationIOApp - Seedlist disabled.
23:31:49.892 [io-compute-6] INFO  o.h.e.s.EmberServerBuilderCompanionPlatform - Ember-Server service bound to address: 0.0.0.0:9000
23:31:49.895 [io-compute-6] INFO  o.t.s.r.MkHttpServer - HTTP Server name=public started at /0.0.0.0:9000
23:31:49.917 [io-compute-6] INFO  o.h.e.s.EmberServerBuilderCompanionPlatform - Ember-Server service bound to address: 0.0.0.0:9001
23:31:49.918 [io-compute-6] INFO  o.t.s.r.MkHttpServer - HTTP Server name=p2p started at /0.0.0.0:9001
23:31:49.943 [io-compute-3] INFO  o.h.e.s.EmberServerBuilderCompanionPlatform - Ember-Server service bound to address: 127.0.0.1:9002
23:31:49.943 [io-compute-3] INFO  o.t.s.r.MkHttpServer - HTTP Server name=cli started at /127.0.0.1:9002
23:31:52.135 [io-compute-6] INFO  o.t.s.i.c.d.N.$anon - Node state changed to=Ready{}
23:31:57.435 [io-compute-0] DEBUG o.t.d.l.StateChannel - Received block consensus input to process: InspectionTrigger
23:31:57.635 [io-compute-3] DEBUG o.t.d.l.d.c.b.Validator - Cannot start own consensus: Not enough peers, Not enough tips, No transactions
23:32:02.598 [io-compute-1] DEBUG o.t.d.l.d.c.b.Validator - Cannot start own consensus: Not enough peers, Not enough tips, No transactions
23:32:02.658 [io-compute-2] DEBUG o.t.d.l.StateChannel - Received block consensus input to process: InspectionTrigger
23:32:06.858 [io-compute-0] INFO  o.t.d.l.StateChannel - Pulled following global snapshot: SnapshotReference{height=0,subHeight=11,ordinal=SnapshotOrdinal{value=11},lastSnapshotHash=93b341d24ce00f43abe054448afe29a43d6997bc0df6bd38821fe394d69a969f,hash=bc8aade10ab11efac2b180c48e78b060420dda6e72019061faf82ff8a8369fd7,proofsHash=9b869faaa608b3f3b8e2a9a4e548d371c11977ba2f5a498b9062f8d78d5e6676}
23:32:06.959 [io-compute-0] INFO  o.t.d.l.StateChannel - Snapshot processing result: DownloadPerformed{reference=SnapshotReference{height=0,subHeight=11,ordinal=SnapshotOrdinal{value=11},lastSnapshotHash=93b341d24ce00f43abe054448afe29a43d6997bc0df6bd38821fe394d69a969f,hash=bc8aade10ab11efac2b180c48e78b060420dda6e72019061faf82ff8a8369fd7,proofsHash=9b869faaa608b3f3b8e2a9a4e548d371c11977ba2f5a498b9062f8d78d5e6676},addedBlock=Set(),removedObsoleteBlocks=Set()}
23:32:07.172 [io-compute-0] DEBUG o.t.d.l.d.c.b.Validator - Cannot start own consensus: Not enough peers, Not enough tips, No transactions
23:32:07.177 [io-compute-2] DEBUG o.t.d.l.StateChannel - Received block consensus input to process: InspectionTrigger
23:32:12.178 [io-compute-0] DEBUG o.t.d.l.d.c.b.Validator - Cannot start own consensus: Not enough peers, Not enough tips, No transactions
23:32:12.219 [io-compute-0] DEBUG o.t.d.l.StateChannel - Received block consensus input to process: InspectionTrigger

```

* That's all for the currency-l1-2 container

### Currency L1 - 3[​](https://docs.constellationnetwork.io/sdk/guides/manual-setup#currency-l1---3) <a href="#currency-l1---3" id="currency-l1---3"></a>

* Here is the instructions to run specifically Currency L1 - 2 container.
* Move the `p12` file to container with the instruction (third `p12` file):

```
docker cp :directory-of-p12-file-3 container-name:file-name.p12
```

* Inside the docker container make sure that your p12 file exists correctly
* It should be at the root level (same level as the tessellation folder)
* Move to tessellation folder:

```
cd tessellation/
```

* Generate the jars

```
sbt currencyL1/assembly
```

* Check the logs to see which version of currency-l1 was published. It should be something like this:

```
/tessellation/modules/currency-l1/target/scala-2.13/tessellation-currency-l1-assembly-*.jar
```

* Move this jar to the root folder, like the example below

```
mv codebase/tessellation/modules/currency-l1/target/scala-2.13/tessellation-currency-l1-assembly-* currency-l1.jar
```

* Outside the container, run this following command to get your docker container IP

```
docker container inspect :container_name | grep -i IPAddress
```

* Outside the container, we need to join our container to the created network, you can do this with the following command (outside the container)

```
docker network connect custom-network-tokens :container_name  
```

* You can check now your network and see your container there:

```
docker network inspect custom-network
```

* Fill the environment variables necessary to run the container (from your first `p12` file):

```
export CL_KEYSTORE=":name-of-your-third-file.p12"
export CL_KEYALIAS=":name-of-your-third-file"
export CL_PASSWORD=":password"
export CL_GLOBAL_L0_PEER_ID=:id_got_of_command_cl_wallet_show_id
export CL_L0_PEER_ID=:id_got_of_command_cl_wallet_show_id
export CL_L0_TOKEN_IDENTIFIER=:id_got_of_command_cl_wallet_show_address
export CL_PUBLIC_HTTP_PORT=9000
export CL_P2P_HTTP_PORT=9001
export CL_CLI_HTTP_PORT=9002
export CL_GLOBAL_L0_PEER_HTTP_HOST=:ip-global-l0-container
export CL_GLOBAL_L0_PEER_HTTP_PORT=9000
export CL_L0_PEER_HTTP_HOST=:ip-currency-l0-container
export CL_L0_PEER_HTTP_PORT=9000
export CL_APP_ENV=dev
export CL_COLLATERAL=0
```

* Finally, run the jar:

```
java -jar currency-l1.jar run-validator  --ip :ip_of_current_container
```

* Your should see something like this:

```
23:31:34.892 [io-compute-blocker-3] INFO  o.t.s.a.TessellationIOApp - App environment: Dev
23:31:34.901 [io-compute-blocker-3] INFO  o.t.s.a.TessellationIOApp - App version: 2.0.0-alpha.2
23:31:38.257 [io-compute-1] INFO  o.t.s.a.TessellationIOApp - Self peerId: b1cf4d017eedb3e187b4d17cef9bdbcfdb2e57b26e346e9186da3a7a2b9110d73481fedbc6de23db51fb932371c54b02fff3388712dcb1e902870da7fa472f66
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.esotericsoftware.kryo.util.UnsafeUtil (file:/code/currency-l1.jar) to constructor java.nio.DirectByteBuffer(long,int,java.lang.Object)
WARNING: Please consider reporting this to the maintainers of com.esotericsoftware.kryo.util.UnsafeUtil
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
23:31:39.054 [io-compute-1] INFO  o.t.s.a.TessellationIOApp - Seedlist disabled.
23:31:49.892 [io-compute-6] INFO  o.h.e.s.EmberServerBuilderCompanionPlatform - Ember-Server service bound to address: 0.0.0.0:9000
23:31:49.895 [io-compute-6] INFO  o.t.s.r.MkHttpServer - HTTP Server name=public started at /0.0.0.0:9000
23:31:49.917 [io-compute-6] INFO  o.h.e.s.EmberServerBuilderCompanionPlatform - Ember-Server service bound to address: 0.0.0.0:9001
23:31:49.918 [io-compute-6] INFO  o.t.s.r.MkHttpServer - HTTP Server name=p2p started at /0.0.0.0:9001
23:31:49.943 [io-compute-3] INFO  o.h.e.s.EmberServerBuilderCompanionPlatform - Ember-Server service bound to address: 127.0.0.1:9002
23:31:49.943 [io-compute-3] INFO  o.t.s.r.MkHttpServer - HTTP Server name=cli started at /127.0.0.1:9002
23:31:52.135 [io-compute-6] INFO  o.t.s.i.c.d.N.$anon - Node state changed to=Ready{}
23:31:57.435 [io-compute-0] DEBUG o.t.d.l.StateChannel - Received block consensus input to process: InspectionTrigger
23:31:57.635 [io-compute-3] DEBUG o.t.d.l.d.c.b.Validator - Cannot start own consensus: Not enough peers, Not enough tips, No transactions
23:32:02.598 [io-compute-1] DEBUG o.t.d.l.d.c.b.Validator - Cannot start own consensus: Not enough peers, Not enough tips, No transactions
23:32:02.658 [io-compute-2] DEBUG o.t.d.l.StateChannel - Received block consensus input to process: InspectionTrigger
23:32:06.858 [io-compute-0] INFO  o.t.d.l.StateChannel - Pulled following global snapshot: SnapshotReference{height=0,subHeight=11,ordinal=SnapshotOrdinal{value=11},lastSnapshotHash=93b341d24ce00f43abe054448afe29a43d6997bc0df6bd38821fe394d69a969f,hash=bc8aade10ab11efac2b180c48e78b060420dda6e72019061faf82ff8a8369fd7,proofsHash=9b869faaa608b3f3b8e2a9a4e548d371c11977ba2f5a498b9062f8d78d5e6676}
23:32:06.959 [io-compute-0] INFO  o.t.d.l.StateChannel - Snapshot processing result: DownloadPerformed{reference=SnapshotReference{height=0,subHeight=11,ordinal=SnapshotOrdinal{value=11},lastSnapshotHash=93b341d24ce00f43abe054448afe29a43d6997bc0df6bd38821fe394d69a969f,hash=bc8aade10ab11efac2b180c48e78b060420dda6e72019061faf82ff8a8369fd7,proofsHash=9b869faaa608b3f3b8e2a9a4e548d371c11977ba2f5a498b9062f8d78d5e6676},addedBlock=Set(),removedObsoleteBlocks=Set()}
23:32:07.172 [io-compute-0] DEBUG o.t.d.l.d.c.b.Validator - Cannot start own consensus: Not enough peers, Not enough tips, No transactions
23:32:07.177 [io-compute-2] DEBUG o.t.d.l.StateChannel - Received block consensus input to process: InspectionTrigger
23:32:12.178 [io-compute-0] DEBUG o.t.d.l.d.c.b.Validator - Cannot start own consensus: Not enough peers, Not enough tips, No transactions
23:32:12.219 [io-compute-0] DEBUG o.t.d.l.StateChannel - Received block consensus input to process: InspectionTrigger

```

* That's all for the currency-l1-3 container

### Joining Currency L1 containers to build the cluster[​](https://docs.constellationnetwork.io/sdk/guides/manual-setup#joining-currency-l1-containers-to-build-the-cluster) <a href="#joining-currency-l1-containers-to-build-the-cluster" id="joining-currency-l1-containers-to-build-the-cluster"></a>

* We need to join the 2 and 3 currency L1 container to the first one, to build the cluster.
* For that, we need to open another terminal instance and run

```
docker exec -it :l1-currency-2-container-name /bin/bash
```

* Then we need to call this:

```
curl -v -X POST http://localhost:9002/cluster/join -H \"Content-type: application/json\" -d '{ \"id\":\":id_got_of_command_cl_wallet_show_id\", \"ip\": \":ip_of_currency_l1_1_container\", \"p2pPort\": 9001 }'
```

* Repeat the same with the third Currency L1 container
* You now should have the cluster build, if you access the url: `http://localhost:9200/cluster/info` you should see the nodes

### Next Steps[​](https://docs.constellationnetwork.io/sdk/guides/manual-setup#next-steps) <a href="#next-steps" id="next-steps"></a>

You should now have a minimal development environment installed and running 🎉

{% hint style="success" %}
**Send your first transaction!**

Set up the FE Developer Dashboard and send your hello world metagraph transaction [here](/metagraph-development/guides/send-a-transaction)
{% endhint %}


# Customize Rewards Logic

In this guide, we will walk through two different methods of customizing rewards logic within your metagraph.

### Understanding Rewards[​](https://docs.constellationnetwork.io/sdk/guides/customize-rewards#understanding-rewards) <a href="#understanding-rewards" id="understanding-rewards"></a>

Rewards are emitted on every timed snapshot of the metagraph and increase the circulating supply of the metagraph token beyond the initial balances defined in genesis.csv. These special transaction types can be used to distribute your currency to fund node operators, or create fixed pools of tokens over time.

By default, no rewards are distributed by a metagraph using the Metagraph Framework which results in a static circulating supply. The rewards customizations described below create inflationary currencies - the rate of which can be controlled by the specific logic introduced. Similarly, a maximum token supply can easily be introduced if desired to prevent unlimited inflation.

#### The Rewards Function[​](https://docs.constellationnetwork.io/sdk/guides/customize-rewards#the-rewards-function) <a href="#the-rewards-function" id="the-rewards-function"></a>

The rewards function includes contextual information from the prior incremental update, including any data produced. Additionally, this function can include customized code capable of invoking any library function of your choice, allowing you to support truly custom use cases and advanced tokenomics structures. The following examples serve as a foundation for typical use cases, which you can expand upon and tailor to your project's needs.

### Before You Start[​](https://docs.constellationnetwork.io/sdk/guides/customize-rewards#before-you-start) <a href="#before-you-start" id="before-you-start"></a>

This guide assumes that you have configured your local environment based on the [Quick Start Guide](https://docs.constellationnetwork.io/sdk/guides/quick-start) and have at least your `global-l0`, `currency-l0`, `currency-l1` clusters configured.

We will be updating the code within your project in the L0 module. This can be found in:

```
source/project/<project_name>/modules/l0/src/main/Main.scala
```

Please note, the examples below show all logic within a single file to make copy/pasting the code as simple as possible. In a production application you would most likely want to split the code into multiple files.

### Examples[​](https://docs.constellationnetwork.io/sdk/guides/customize-rewards#examples) <a href="#examples" id="examples"></a>

These examples show different ways that rewards logic can be customized within your metagraph. The concepts displayed can be used independently or combined for further customization based on the business logic of your project.

#### Example: Distribute Rewards to Fixed Addresses[​](https://docs.constellationnetwork.io/sdk/guides/customize-rewards#example-distribute-rewards-to-fixed-addresses) <a href="#example-distribute-rewards-to-fixed-addresses" id="example-distribute-rewards-to-fixed-addresses"></a>

Add the following code to your L0 Main.scala file.

```
package com.my.currency.l0

import cats.effect.{Async, IO}
import org.tessellation.BuildInfo
import org.tessellation.currency.dataApplication.BaseDataApplicationL0Service
import org.tessellation.currency.l0.CurrencyL0App
import org.tessellation.currency.schema.currency.{
  CurrencyBlock,
  CurrencyIncrementalSnapshot,
  CurrencySnapshotStateProof,
  CurrencyTransaction
}
import org.tessellation.schema.address.Address
import org.tessellation.schema.balance.Balance
import org.tessellation.schema.cluster.ClusterId
import org.tessellation.schema.transaction.{
  RewardTransaction,
  TransactionAmount
}
import org.tessellation.sdk.domain.rewards.Rewards
import org.tessellation.sdk.infrastructure.consensus.trigger.ConsensusTrigger
import org.tessellation.security.SecurityProvider
import org.tessellation.security.signature.Signed

import eu.timepit.refined.auto._
import cats.syntax.applicative._

import java.util.UUID
import scala.collection.immutable.{SortedSet, SortedMap}

object RewardsMintForPredefinedAddresses {
  def make[F[_]: Async] =
    new Rewards[
      F,
      CurrencyTransaction,
      CurrencyBlock,
      CurrencySnapshotStateProof,
      CurrencyIncrementalSnapshot
    ] {
      def distribute(
        lastArtifact: Signed[CurrencyIncrementalSnapshot],
        lastBalances: SortedMap[Address, Balance],
        acceptedTransactions: SortedSet[Signed[CurrencyTransaction]],
        trigger: ConsensusTrigger
      ): F[SortedSet[RewardTransaction]] = SortedSet(
        Address("DAG8pkb7EhCkT3yU87B2yPBunSCPnEdmX2Wv24sZ"),
        Address("DAG4o41NzhfX6DyYBTTXu6sJa6awm36abJpv89jB")
      ).map(RewardTransaction(_, TransactionAmount(55_500_0000L))).pure[F]
    }
}

object Main
  extends CurrencyL0App(
    "custom-rewards-l0",
    "custom-rewards L0 node",
    ClusterId(UUID.fromString("517c3a05-9219-471b-a54c-21b7d72f4ae5")),
    version = BuildInfo.version
  ) {

  def dataApplication: Option[BaseDataApplicationL0Service[IO]] = None

  def rewards(implicit sp: SecurityProvider[IO]) = Some(
    RewardsMintForPredefinedAddresses.make[IO]
  )
}
```

The code distributes 5.55 token rewards on each timed snapshot to two hardcoded addresses:

* DAG8pkb7EhCkT3yU87B2yPBunSCPnEdmX2Wv24sZ
* DAG4o41NzhfX6DyYBTTXu6sJa6awm36abJpv89jB

These addresses could represent treasury wallets or manually distributed rewards pools. Update the number of wallets and amounts to match your use-case.

**Rebuild Clusters**[**​**](https://docs.constellationnetwork.io/sdk/guides/customize-rewards#rebuild-clusters)

Run the following commands to rebuild your clusters with the new code:

```
scripts/hydra destroy
scripts/hydra build --no_cache
```

Once built, run hydra start to see your changes take effect.

```
scripts/hydra start-genesis
```

**View Changes**[**​**](https://docs.constellationnetwork.io/sdk/guides/customize-rewards#view-changes)

Using the [Developer Dashboard](https://docs.constellationnetwork.io/sdk/elements/developer-dashboard) you should see the balances of the two wallets above increase by 5.5 tokens after each snapshot.

Inspecting the snapshot body, you should also see an array of "rewards" transactions present.

![Rewards Transactions in Snapshot](https://docs.constellationnetwork.io/assets/images/rewards-snapshot-9172b617bb518907ba185e376d3d96c2.png)

#### Example: Distribute Rewards to Validator Nodes[​](https://docs.constellationnetwork.io/sdk/guides/customize-rewards#example-distribute-rewards-to-validator-nodes) <a href="#example-distribute-rewards-to-validator-nodes" id="example-distribute-rewards-to-validator-nodes"></a>

Add the following code to your L0 Main.scala file.

```
package com.my.currency.l0

import cats.effect.{Async, IO}
import cats.implicits.{toFoldableOps, toFunctorOps, toTraverseOps}
import org.tessellation.BuildInfo
import org.tessellation.currency.dataApplication.BaseDataApplicationL0Service
import org.tessellation.currency.l0.CurrencyL0App
import org.tessellation.currency.schema.currency.{CurrencyBlock, CurrencyIncrementalSnapshot, CurrencySnapshotStateProof, CurrencyTransaction}
import org.tessellation.schema.address.Address
import org.tessellation.schema.balance.Balance
import org.tessellation.schema.cluster.ClusterId
import org.tessellation.schema.transaction.{RewardTransaction, TransactionAmount}
import org.tessellation.sdk.domain.rewards.Rewards
import org.tessellation.security.SecurityProvider
import org.tessellation.security.signature.Signed
import eu.timepit.refined.auto._
import org.tessellation.sdk.infrastructure.consensus.trigger.ConsensusTrigger

import java.util.UUID
import scala.collection.immutable.{SortedMap, SortedSet}

object RewardsMint1ForEachFacilitator {
  def make[F[_]: Async: SecurityProvider] =
    new Rewards[F, CurrencyTransaction, CurrencyBlock, CurrencySnapshotStateProof, CurrencyIncrementalSnapshot] {
      def distribute(
        lastArtifact: Signed[CurrencyIncrementalSnapshot],
        lastBalances: SortedMap[Address, Balance],
        acceptedTransactions: SortedSet[Signed[CurrencyTransaction]],
        trigger: ConsensusTrigger
      ): F[SortedSet[RewardTransaction]] = {
        val facilitatorsToReward = lastArtifact.proofs.map(_.id)
        val addresses = facilitatorsToReward.toList.traverse(_.toAddress)
        val rewardsTransactions = addresses.map(addresses => {
          val addressesAsList = addresses.map(RewardTransaction(_, TransactionAmount(1_000_0000L)))
          collection.immutable.SortedSet.empty[RewardTransaction] ++ addressesAsList
        })

        rewardsTransactions
      }
    }
}

object Main
  extends CurrencyL0App(
    "custom-rewards-l0",
    "custom-rewards L0 node",
    ClusterId(UUID.fromString("517c3a05-9219-471b-a54c-21b7d72f4ae5")),
    version = BuildInfo.version
  ) {

  def dataApplication: Option[BaseDataApplicationL0Service[IO]] = None

  def rewards(implicit sp: SecurityProvider[IO]) = Some(
    RewardsMint1ForEachFacilitator.make[IO]
  )
}
```

The code distributes 1 token reward on each timed snapshot to each validator node that participated in the most recent round of consensus.

**Rebuild Clusters**[**​**](https://docs.constellationnetwork.io/sdk/guides/customize-rewards#rebuild-clusters-1)

Run the following commands to rebuild your clusters with the new code:

```
scripts/hydra destroy
scripts/hydra build --no_cache
```

Once built, run hydra start to see your changes take effect.

```
scripts/hydra start-genesis
```

**View Changes**[**​**](https://docs.constellationnetwork.io/sdk/guides/customize-rewards#view-changes-1)

Using the [Developer Dashboard](https://docs.constellationnetwork.io/sdk/elements/developer-dashboard) you should see the balances of the wallets in each node in your L0 cluster above increase by 1 token after each snapshot.

Inspecting the snapshot body, you should also see an array of "rewards" transactions present.

#### Example: Distribute Rewards Based on API Data[​](https://docs.constellationnetwork.io/sdk/guides/customize-rewards#example-distribute-rewards-based-on-api-data) <a href="#example-distribute-rewards-based-on-api-data" id="example-distribute-rewards-based-on-api-data"></a>

Add the following code to your L0 Main.scala file.

```
package com.my.currency.l0

import cats.data.NonEmptyList
import cats.effect.{Async, IO}
import cats.implicits.catsSyntaxApplicativeId
import derevo.circe.magnolia.{decoder, encoder}
import derevo.derive
import org.tessellation.BuildInfo
import org.tessellation.currency.dataApplication.BaseDataApplicationL0Service
import org.tessellation.currency.l0.CurrencyL0App
import org.tessellation.currency.schema.currency.{CurrencyBlock, CurrencyIncrementalSnapshot, CurrencySnapshotStateProof, CurrencyTransaction}
import org.tessellation.schema.address.Address
import org.tessellation.schema.balance.Balance
import org.tessellation.schema.cluster.ClusterId
import org.tessellation.schema.transaction.{RewardTransaction, TransactionAmount}
import org.tessellation.sdk.domain.rewards.Rewards
import org.tessellation.security.SecurityProvider
import org.tessellation.security.signature.Signed
import eu.timepit.refined.numeric.Positive
import eu.timepit.refined.refineV
import eu.timepit.refined.types.numeric.PosLong
import org.tessellation.sdk.infrastructure.consensus.trigger.ConsensusTrigger
import io.circe.parser.decode

import java.util.UUID
import scala.collection.immutable.{SortedMap, SortedSet}

object RewardsMintForEachAddressOnApi {
  private def getRewardAddresses: List[Address] = {

    @derive(decoder, encoder)
    case class AddressTimeEntry(address: Address, date: String)

    try {
      //Using host.docker.internal as host because we will fetch this from a docker container to a API that is on local machine
      //You should replace to your url
      val response = requests.get("http://host.docker.internal:8000/addresses")
      val body = response.text()

      println("API response" + body)

      decode[List[AddressTimeEntry]](body) match {
        case Left(e) => throw e
        case Right(addressTimeEntries) => addressTimeEntries.map(_.address)
      }
    } catch {
      case x: Exception => {
        println(s"Error when fetching API: ${x.getMessage}")
        List[Address]()
      }
    }
  }

  private def getAmountPerWallet(addressCount: Int): PosLong = {
    val totalAmount: Long = 100_000_0000L
    val amountPerWallet: Either[String, PosLong] = refineV[Positive](totalAmount / addressCount)

    amountPerWallet.toOption match {
      case Some(amount) => amount
      case None =>
        println("Error getting amount per wallet")
        PosLong(1)
    }
  }

  def make[F[_] : Async ] =
    new Rewards[F, CurrencyTransaction, CurrencyBlock, CurrencySnapshotStateProof, CurrencyIncrementalSnapshot] {
      def distribute(
                      lastArtifact: Signed[CurrencyIncrementalSnapshot],
                      lastBalances: SortedMap[Address, Balance],
                      acceptedTransactions: SortedSet[Signed[CurrencyTransaction]],
                      trigger: ConsensusTrigger
                    ): F[SortedSet[RewardTransaction]] = {

        val rewardAddresses = getRewardAddresses
        val foo = NonEmptyList.fromList(rewardAddresses)

        foo match {
          case Some(addresses) =>
            val amountPerWallet = getAmountPerWallet(addresses.size)
            val rewardAddressesAsSortedSet = SortedSet(addresses.toList: _*)

            rewardAddressesAsSortedSet.map(address => {
              val txnAmount = TransactionAmount(amountPerWallet)
              RewardTransaction(address, txnAmount)
            }).pure[F]

          case None =>
            println("Could not find reward addresses")
            val nodes: SortedSet[RewardTransaction] = SortedSet.empty
            nodes.pure[F]
        }
      }
    }
}

object Main
  extends CurrencyL0App(
    "custom-rewards-l0",
    "custom-rewards L0 node",
    ClusterId(UUID.fromString("517c3a05-9219-471b-a54c-21b7d72f4ae5")),
    version = BuildInfo.version
  ) {

  def dataApplication: Option[BaseDataApplicationL0Service[IO]] = None

  def rewards(implicit sp: SecurityProvider[IO]) = Some(
    RewardsMintForEachAddressOnApi.make[IO]
  )
}
```

The code distributes token rewards on each timed snapshot to each address that is returned from a custom API.

On this [Repository](https://github.com/Constellation-Labs/metagraph-examples/) you can take a better look at the template example and the custom API.

In the repository, the code will distribute the amount of 100 tokens between the number of returned wallets (in this case the maximum of 20 latest wallets)

**Rebuild Clusters**[**​**](https://docs.constellationnetwork.io/sdk/guides/customize-rewards#rebuild-clusters-2)

Run the following commands to rebuild your clusters with the new code:

```
scripts/hydra destroy
scripts/hydra build --no_cache
```

Once built, run hydra start to see your changes take effect.

```
scripts/hydra start-genesis
```

**View Changes**[**​**](https://docs.constellationnetwork.io/sdk/guides/customize-rewards#view-changes-2)

Using the [Developer Dashboard](https://docs.constellationnetwork.io/sdk/elements/developer-dashboard) you should see the balances of the wallets in each node in your L0 cluster above increase by ( 100 / :number\_of\_wallets ) tokens after each snapshot.

Inspecting the snapshot body, you should also see an array of "rewards" transactions present.


# Custom Data Validation

In this guide, we will walk through a Data Application and a simple example implementation of an IoT use case. Complete code for this guide can be found in the [metagraph examples repo](https://github.com/Constellation-Labs/metagraph-examples) on Github. See the [Water and Energy Use](https://github.com/Constellation-Labs/metagraph-examples/tree/main/examples/DataApi-Water-And-Energy-Usage) example.

**Want more detail?**

Looking for additional detail on Data Application development? More information is available in [Data Application](/metagraph-development/metagraph-framework/data).

### Before You Start[​](https://docs.constellationnetwork.io/sdk/guides/custom-data#before-you-start) <a href="#before-you-start" id="before-you-start"></a>

In order to get started, install dependencies as described in the [Quick Start Guide](/metagraph-development/guides/quick-start). You will need at least the `global-l0`, `metagraph-l0`, and `metagraph-l1-data` containers enabled in your `euclid.json` file for this guide.

**Example euclid.json values**

```
  "version": "0.9.1",
  "tessellation_version": "2.2.0",
  "project_name": "custom-project",
  "framework": {
    "name": "currency",
    "modules": [
      "data"
    ],
    "version": "v2.2.0",
    "ref_type": "tag"
  },
  "layers": [
    "global-l0",
    "metagraph-l0",
    "currency-l1",
    "data-l1"
  ],
```

**Installing Templates with Hydra**

To initiate a metagraph using a template, we provide several options in our [GitHub repository](https://github.com/Constellation-Labs/metagraph-examples). Follow these steps to utilize a template:

1\.  List Available Templates: First, determine th\`e templates at your disposal by executing the command below:

```
./scripts/hydra install-template --list
```

2\.  Install a Template: After selecting a template, replace `:repo_name` with your chosen repository's name to install it. For instance:

```
./scripts/hydra install-template :repo_name
```

As a practical example, if you wish to install the `water-and-energy-usage` template, your command would look like this:

```
./scripts/hydra install-template water-and-energy-usage
```

This process will set up a metagraph based on the selected template.

Within your Euclid modules directory (source/project/water-and-energy-usage/modules) you will see three module directories: l0 (metagraph l0), l1 (currency l1), and data\_l1 (data l1). Each module has a Main.scala file that defines the application that will run at each corresponding layer.

```
- source
  - project
    - water-and-energy-usage
      - modules
        - l0
        - l1
        - data_1
        - shared_data
      - project
```

### Send Data[​](https://docs.constellationnetwork.io/sdk/guides/custom-data#send-data) <a href="#send-data" id="send-data"></a>

Edit the `send_data_transaction.js` script and fill in the `globalL0Url`, `metagraphL1DataUrl`, and `walletPrivateKey` variables. The private key can be generated with the `dag4.keystore.generatePrivateKey()` method if you don't already have one.

Once the variables are updated, save the file. You can now run `node send_data_transaction.js` to send data to the `/data` endpoint.

#### Check State Updates[​](https://docs.constellationnetwork.io/sdk/guides/custom-data#check-state-updates) <a href="#check-state-updates" id="check-state-updates"></a>

Using the custom endpoint created in the data\_l1 Main.scala `routes` method, we can check the metagraph state as updates are sent.

Using your browser, navigate to `<your L1 base url>/data-application/addresses` to see the complete state including all devices that have sent data. You can also check the state of an individual device using the `<your L1 base url>/data-application/addresses/:address` endpoint.

You should see a response like this:

```
{
    "DAG4bQGdnDJ5okVdsdtvJzBwQoPGjLNzN7HC1CBV": {
        "energy": {
            "usage": 7,
            "timestamp": 1689441998946
        },
        "water": {
            "usage": 7,
            "timestamp": 1689441998946
        }
    }
}
```

### Next Steps[​](https://docs.constellationnetwork.io/sdk/guides/custom-data#next-steps) <a href="#next-steps" id="next-steps"></a>

This brief guide demonstrates the ability to update and view on-chain state based on the Metagraph Framework's Data Application layer. Detailed information about the framework methods used can be found in the [example README file](https://github.com/Constellation-Labs/metagraph-examples/blob/main/examples/DataApi-Water-And-Energy-Usage/README.md) and in comments throughout the code. Also see additional break downs of the application lifecycle methods in the [Data API](/metagraph-development/metagraph-framework/data) section.


# Working with p12 files

### Generating p12 files[​](https://docs.constellationnetwork.io/sdk/guides/working-with-p12-files#generating-p12-files) <a href="#generating-p12-files" id="generating-p12-files"></a>

This guide will walk you through the process of creating your own custom p12 files. We will generate three files to match the original Euclid Development Environment project's configuration.

{% hint style="warning" %}
**Caution**

If using a Euclid Development Environment project, you must update your configuration to use your own custom p12 files. Projects submitted with the default p12 files that come with the project will be rejected.
{% endhint %}

#### Step 1: Download `cl-keytool.jar` Executable[​](https://docs.constellationnetwork.io/sdk/guides/working-with-p12-files#step-1-download-cl-keytooljar-executable) <a href="#step-1-download-cl-keytooljar-executable" id="step-1-download-cl-keytooljar-executable"></a>

Download the `cl-keytool.jar` executable. This is included as an asset with each release of Tessellation.

#### Step 2: Set Up Your Environment Variables[​](https://docs.constellationnetwork.io/sdk/guides/working-with-p12-files#step-2-set-up-your-environment-variables) <a href="#step-2-set-up-your-environment-variables" id="step-2-set-up-your-environment-variables"></a>

Modify the following variables with your custom details and export them to your environment:

```
export CL_KEYSTORE=":your_custom_file_name.p12"
export CL_KEYALIAS=":your_custom_file_alias"
export CL_PASSWORD=":your_custom_file_password"
```

Replace `:your_custom_file_name.p12`, `:your_custom_file_alias`, and `:your_custom_file_password` with your specific file name, alias, and password, respectively.

#### Step 3: Generate Your Custom .p12 File[​](https://docs.constellationnetwork.io/sdk/guides/working-with-p12-files#step-3-generate-your-custom-p12-file) <a href="#step-3-generate-your-custom-p12-file" id="step-3-generate-your-custom-p12-file"></a>

Execute the following command to generate your custom .p12 file:

```
java -jar cl-keytool.jar generate
```

This will create a .p12 file in the directory from which the command was executed.

#### Step 4: Repeat the Process[​](https://docs.constellationnetwork.io/sdk/guides/working-with-p12-files#step-4-repeat-the-process) <a href="#step-4-repeat-the-process" id="step-4-repeat-the-process"></a>

Repeat steps 2 and 3 two more times to create a total of three custom p12 files. Remember to change the file name each time to avoid overwriting any existing files.

### Finding Your Node IDs[​](https://docs.constellationnetwork.io/sdk/guides/working-with-p12-files#finding-your-node-ids) <a href="#finding-your-node-ids" id="finding-your-node-ids"></a>

Your node ID is the public key of your wallet which will be stored as a p12 file.

{% hint style="warning" %}
**Caution**

If using a Euclid Development Environment project, you must update your configuration to use your own custom p12 files. Projects submitted with the default p12 files that come with the project will be rejected.
{% endhint %}

[**How to generate p12 files**](https://docs.constellationnetwork.io/sdk/guides/generating-with-p12-files)

Download the `cl-wallet.jar` executable. This is distributed as an asset with each [release of Tessellation](https://github.com/Constellation-Labs/tessellation/releases).

Editing the details of the following variables and export to your environment.

```
export CL_KEYSTORE=":your_file_name.p12"
export CL_KEYALIAS=":your_file_alias"
export CL_PASSWORD=":your_file_password"
```

Then you can run the following to get your node ID:

```
java -jar cl-wallet.jar show-id
```


# Snapshot Fees

The Hypergraph charges fees for validating and storing metagraph snapshots, ensuring the network's continued functionality. These snapshot fees, along with node collateral requirements, are the only expenses metagraphs must pay in order to interface with the Hypergraph. This fee structure provides metagraphs with significant flexibility, enabling them to decide their own fee structures and data inclusion policies.

Metagraphs have the autonomy to choose whether to charge their end users directly, impose fees for specific data types, or even operate without user fees. They can also control which data is included in their snapshots, managing costs and determining the privacy level of their network.

Fees are calculated based on the size and computational cost of processing snapshots. Currently, all snapshots have a computational cost of 1, which means that snapshot size is the only active factor in determining snapshot fee cost. For detailed information on network fees, refer to the [Network Fees Litepaper](https://docs.constellationnetwork.io/learn/tools-resources/network-fees-litepaper).

### Owner and Staking Wallets[​](https://docs.constellationnetwork.io/sdk/guides/snapshot-fees#owner-and-staking-wallets) <a href="#owner-and-staking-wallets" id="owner-and-staking-wallets"></a>

The Global L0 deducts snapshot fees from an "owner wallet," which is designated by a majority of metagraph validators and registered with the gL0. An additional wallet, known as the "staking wallet," can also be designated to reduce fees based on its balance at the time a snapshot is processed. These two wallets can be the same, but the addresses used for either the owner or staking wallets must be globally unique on the Hypergraph.

The owner and staking wallets are designated by signing a message to prove ownership of each wallet and creating a "Currency Message" for the metagraph. This Currency Message must be signed by a majority of the L0 nodes of the metagraph, then included in a metagraph snapshot to be sent to the gL0 for registration and inclusion in a global snapshot. Owner and staking wallets can be changed at any time using the same process.

**Assigning an owner wallet is required**

Starting in Tessellation v2.7.0, the Hypergraph will reject snapshots sent by metagraphs that do not designate an owner wallet or if the designated wallet does not have sufficient funds to cover the cost of the current snapshot’s fees. For this reason, assigning an owner wallet is required. Assigning a staking wallet is optional.

#### Assigning Metagraph Wallets with Euclid[​](https://docs.constellationnetwork.io/sdk/guides/snapshot-fees#assigning-metagraph-wallets-with-euclid) <a href="#assigning-metagraph-wallets-with-euclid" id="assigning-metagraph-wallets-with-euclid"></a>

Euclid simplifies the process of assigning both the owner and staking wallets with a few simple Hydra commands ([v0.11.0](https://github.com/Constellation-Labs/euclid-development-environment/releases/tag/v0.11.0) or later).

**Local builds**

Snapshot fees are turned off by default for local builds. Owner and staking details only need to be configured when deploying to MainNet or a public testnet (IntegrationNet, etc.).

First, update the `snapshot_fees` key in euclid.json with the name, alias, and password of the p12 file for each of the wallets. The p12 files should be stored in the `source/p12-files` directory and should have a unique name.

For example (replace with your own values):

```
{
  "snapshot_fees": {
    "owner": {
        "name": "metagraph_owner.p12",
        "alias": "metagraph_owner",
        "password": "pass1234" 
    },
    "staking": {
        "name": "metagraph_staking.p12",
        "alias": "metagraph_staking",
        "password": "pass1235" 
    }
  }
}
```

Next, run `hydra remote-deploy` , this will deploy your owner and staking p12 files to the remote nodes.

If running your remote metagraph from genesis, no special configuration is required - owner and (optionally) staking wallet configuration will be automatically set for you if provided in euclid.json. Simply run `hydra remote-start` or `hydra remote-start --force_genesis` to start your metagraph from genesis.

If running an existing metagraph as rollback, run

```
hydra remote-start --force_owner_message --force_staking_message
```

to set or overwrite the fee wallet configuration for the metagraph.

The `--force_staking_message` parameter is optional and can be removed if not using a staking wallet.

To check that your configuration has been successfully updated, run

```
hydra remote-snapshot-fee-config
```

You should see an output like this:

```
OWNER
Owner Address: DAG3Z6oMiqXyi4SKEU4u4fwNiYAMYFyPwR3ttTSd
Owner Parent Ordinal: 0

STAKING
Staking Address: DAG5yuTbZP5Jq55yzdDkAisULFhkhPrW7XRqNY1D
Staking Parent Ordinal: 0
```

If both the Owner and Staking addresses are set then the addresses are properly assigned and the Hypergraph will process snapshot fees based on that configuration.


# Deploy a Metagraph

This tutorial will guide you through the process of deploying your Euclid metagraph project to a cloud provider and connecting to IntegrationNet or MainNet. We focus on AWS specifically but the basic principles would apply to any cloud provider.

**Deploying a Metagraph with Euclid**

{% hint style="warning" %}
Utilize Euclid for deploying metagraphs efficiently. Initiate deployment to your remote hosts, including all necessary files and dependencies, with the following command:

```
./scripts/hydra remote-deploy
```

To start your nodes, execute:

```
./scripts/hydra remote-start
```

For comprehensive guidance on utilizing these commands, consult the README file in the [Euclid repository](https://github.com/Constellation-Labs/euclid-development-environment/blob/main/README.md).

Additionally, we offer a demonstration video showcasing this functionality, available [here](https://twitter.com/codebrandes/status/1765904204600938505).
{% endhint %}

### Architecture[​](https://docs.constellationnetwork.io/sdk/guides/deploy-a-metagraph/overview/#architecture) <a href="#architecture" id="architecture"></a>

There are many kinds of potential deployment architectures possible for production deployments depending on project scaling needs. Here, we will focus on a deployment strategy that uses a minimal set of infrastructure components to simplify deployment and reduce cloud costs. For most projects, this offers a good starting point that can be expanded on later to meet specific project needs.

We will be deploying a [Metagraph Framework](/metagraph-development/metagraph-framework/overview) metagraph using a [Data Application](/metagraph-development/metagraph-framework/data). This type of metagraph consists of 4 layers in total:

* **Global L0:** Hypergraph node on IntegrationNet or MainNet
* **Metagraph L0:** Metagraph consensus layer
* **Currency L1:** Metagraph layer for accepting and validating token transactions
* **Data L1:** Metagraph layer for accepting and validating data updates

In this guide, we will deploy all 4 layers to each of 3 EC2 instances. In other words, we will only use 3 servers but each server will act as a node on each of the 4 layers. This allows all layers to have the minimum cluster size to reach consensus (3), while also being conscious of infrastructure costs by combining each layer onto the same EC2 instances. Each layer will communicate over custom ports which we will configure as part of this process.

**Deployed Architecture:**

![Metagraph Architecture](https://docs.constellationnetwork.io/assets/images/metagraph-deployment-architecture-93f07292331cd1c25b609809e612f7bf.png)

### Requirements[​](https://docs.constellationnetwork.io/sdk/guides/deploy-a-metagraph/overview/#requirements) <a href="#requirements" id="requirements"></a>

* AWS Account
* A metagraph project built and tested locally in Euclid
* At least 3 **`p12`** files. Refer to [this guide](/metagraph-development/guides/working-with-p12-files) on how to generate p12 files.
* Ensure that the ID of all your **`p12`** files is on the appropriate network seedlist (IntegrationNet or MainNet) otherwise, you won't be able to connect to the network. Check the [seedlist](https://constellationlabs-dag.s3.us-west-1.amazonaws.com/integrationnet-seedlist) to verify your IDs are included.

### Guide[​](https://docs.constellationnetwork.io/sdk/guides/deploy-a-metagraph/overview/#guide) <a href="#guide" id="guide"></a>

This guide will walk you through a series of steps to manually configure your nodes via the AWS console. We will configure AWS, build all code on a base instance that we will then convert to an AWS AMI to be used as a template for creating the rest of the nodes. This allows us to build once, and then duplicate it to all of the EC2 instances. Then we will configure each of the nodes with their own P12 file and other details specific to each node.

**We will walk through the following steps:**

* [Configure security groups](/metagraph-development/guides/deploy-a-metagraph/security-groups): Create a security group for the nodes and open the proper network ports for communication.
* [Setup SSH keys](/metagraph-development/guides/deploy-a-metagraph/key-pairs): Create SSH keys to securely connect to the nodes.
* [Create a base instance](/metagraph-development/guides/deploy-a-metagraph/base-instance): Build a server image as an AWS AMI to be reused for each of the nodes.
* [Configure the base instance](/metagraph-development/guides/deploy-a-metagraph/base-instance/connect-to-the-instance): Add all dependencies and upload metagraph project files to the base instance.
* [Generate AMI](/metagraph-development/guides/deploy-a-metagraph/base-instance/generating-ami-image-from-base-instance): Convert the base instance into a reusable AMI.
* [Generate EC2 Instances from AMI](/metagraph-development/guides/deploy-a-metagraph/base-instance/launching-instances-from-ami): Using the AMI created in previous steps as a template, generate all 3 EC2 instances.
* [Configure Layers and Join](/metagraph-development/guides/deploy-a-metagraph/start-metagraph-instances/configuring-p12-files): Configure each of the 4 layers and join to the network.

[Edit this page](https://github.com/Constellation-Labs/documentation-hub/edit/main/sdk/guides/deploy-a-metagraph/01-overview.md)<br>


# Security groups

Security groups act as virtual firewalls that control inbound and outbound traffic to your instances. Our 3 nodes will need to open up connection ports for SSH access, and for each of the 4 network layers to communicate over.

#### Create a Security Group[​](https://docs.constellationnetwork.io/sdk/guides/deploy-a-metagraph/security-groups#create-a-security-group) <a href="#create-a-security-group" id="create-a-security-group"></a>

First, navigate to the **`Security Groups`** section in the Amazon [EC2 console](https://us-west-2.console.aws.amazon.com/ec2/home).

![Menu ec2](https://docs.constellationnetwork.io/assets/images/security-group-1-0364dd14dd16936812e0eda2e47c4639.png)

**Click on `Create Security Group`**[**​**](https://docs.constellationnetwork.io/sdk/guides/deploy-a-metagraph/security-groups#click-on-create-security-group)

Create a new security group and provide a name, for example `MetagraphSecurityGroup`.

**Add Inbound Rules**[**​**](https://docs.constellationnetwork.io/sdk/guides/deploy-a-metagraph/security-groups#add-inbound-rules)

Inbound rules define which ports accept inbound connections on your node. We will need to open up ports for SSH access and for each of the metagraph layers.

Click **`Add Rule`** under the **`Inbound Rules`** section and add the following rules:

| Type       | Protocol | Port Range | Source    | Purpose    |
| ---------- | -------- | ---------- | --------- | ---------- |
| SSH        | TCP      | 22         | 0.0.0.0/0 | SSH access |
| Custom TCP | TCP      | 9000-9002  | 0.0.0.0/0 | gL0 layer  |
| Custom TCP | TCP      | 9100-9102  | 0.0.0.0/0 | mL0 layer  |
| Custom TCP | TCP      | 9200-9202  | 0.0.0.0/0 | cL1 layer  |
| Custom TCP | TCP      | 9300-9302  | 0.0.0.0/0 | dL1 layer  |


# Key pairs

Key pairs are a crucial part of securing your instances. They consist of a public key that AWS stores and a private key file that you store. The private key file is used to SSH into your instances securely.

#### Use the following steps to create a keypair[​](https://docs.constellationnetwork.io/sdk/guides/deploy-a-metagraph/key-pairs#use-the-following-steps-to-create-a-keypair) <a href="#use-the-following-steps-to-create-a-keypair" id="use-the-following-steps-to-create-a-keypair"></a>

Navigate to the **`Key pairs`** page on the Amazon EC2 console.

![Key pair aws](https://docs.constellationnetwork.io/assets/images/key-pair-1-8b538ec60600215ee510173cb9274227.png)

**Click on `Create key pair`**[**​**](https://docs.constellationnetwork.io/sdk/guides/deploy-a-metagraph/key-pairs#click-on-create-key-pair)

Provide a unique name for your key pair, such as: `MetagraphKeyPair`

Your screen should now look similar to this:

![Key pair aws](https://docs.constellationnetwork.io/assets/images/key-pair-2-6fff96c2778fcae5d2f53af67ea1d139.png)

After you click **`Create key pair`**, a new key pair will be generated, and your browser will automatically download a file that contains your private key.

{% hint style="warning" %}
**important**

Safeguard this file as it will be necessary for SSH access to your instances. Do not share this file or expose it publicly as it could compromise the security of your instances.

Store your keypair on your local machine in a secure location. You will need it to connect to your EC2 instances.
{% endhint %}


# Base instance

## Start Here

{% content-ref url="/pages/ZhzWW9o3vAv3mrqejwVu" %}
[Generating base instance](/metagraph-development/guides/deploy-a-metagraph/base-instance/generating-base-instance)
{% endcontent-ref %}


# Generating base instance

In this section, we will create a single EC2 instance that we will use as a template for the other two EC2 instances. This allows us to perform these tasks once and then have the output replicated to all the instances.

#### Create a Base Instance[​](https://docs.constellationnetwork.io/sdk/guides/deploy-a-metagraph/base-instance/generating-base-instance#create-a-base-instance) <a href="#create-a-base-instance" id="create-a-base-instance"></a>

Navigate to the **`Instances`** section on the Amazon EC2 console.

![base instance 01](https://docs.constellationnetwork.io/assets/images/base-intance-01-49a325ca0d7ac7f86fd9ebc64c9f13fd.png)

**Click on `Launch Instances`.**[**​**](https://docs.constellationnetwork.io/sdk/guides/deploy-a-metagraph/base-instance/generating-base-instance#click-on-launch-instances)

Assign a name to your instance. For this guide, we will call it **`Metagraph base image`**.

**Choose an AMI**[**​**](https://docs.constellationnetwork.io/sdk/guides/deploy-a-metagraph/base-instance/generating-base-instance#choose-an-ami)

In the **`Choose an Amazon Machine Image (AMI)`** section, select `Ubuntu` and then `Ubuntu server 20.04`. You should keep `64-bit (x86)`.

<figure><img src="https://docs.constellationnetwork.io/assets/images/base-intance-02-307116115eb0f444a4e882e1cacc5a39.png" alt="" width="563"><figcaption></figcaption></figure>

For the instance type, choose a model with **`4 vCPUs`** and **`16 GiB memory`**. In this case, we'll use the **`t2.xlarge`** instance type.

**Select a Key Pair**[**​**](https://docs.constellationnetwork.io/sdk/guides/deploy-a-metagraph/base-instance/generating-base-instance#select-a-key-pair)

In the **`Configure Instance Details`** step, select the key pair you created earlier in the **`Key pair name`** field.

<figure><img src="https://docs.constellationnetwork.io/assets/images/base-intance-04-c0dea98ebcf98d83f6c091084f80ea80.png" alt=""><figcaption></figcaption></figure>

**Select Security Group**[**​**](https://docs.constellationnetwork.io/sdk/guides/deploy-a-metagraph/base-instance/generating-base-instance#select-security-group)

In the `Network settings` section, you select the security group you created earlier.

<figure><img src="https://docs.constellationnetwork.io/assets/images/base-intance-05-8c2f23e35a5b8f83cb60273ec6e82169.png" alt="" width="563"><figcaption></figcaption></figure>

**Configure Storage**[**​**](https://docs.constellationnetwork.io/sdk/guides/deploy-a-metagraph/base-instance/generating-base-instance#configure-storage)

In the `Configure storage` section, you specify the amount of storage for the instance. For this tutorial, we'll set it to **`160 GiB`**.

<figure><img src="https://docs.constellationnetwork.io/assets/images/base-intance-06-f5ba059a58d87a95fe58cfe35a97ad8d.png" alt="" width="563"><figcaption></figcaption></figure>

**Launch Instance**[**​**](https://docs.constellationnetwork.io/sdk/guides/deploy-a-metagraph/base-instance/generating-base-instance#launch-instance)

Finally, press `Launch instance`. Your base instance should now be running.

You can check the status of your instance in the **`Instances`** section of the Amazon EC2 console.

<figure><img src="https://docs.constellationnetwork.io/assets/images/base-intance-07-911a523035be0cca56de430e3f094d84.png" alt=""><figcaption></figcaption></figure>


# Connect to the instance

From your **`Instances`** page, click on your instance.

Then you should see something like this:

<figure><img src="https://docs.constellationnetwork.io/assets/images/configuring-base-image-01-b6a92d9f1277fb2912b1da049ca07f38.png" alt=""><figcaption></figcaption></figure>

**Click on the `Connect` button at the top of the page.**[**​**](https://docs.constellationnetwork.io/sdk/guides/deploy-a-metagraph/base-instance/configuring-base-instance#click-on-the-connect-button-at-the-top-of-the-page)

There are different ways to access the instance. In this example, we will connect using `ssh` using the file downloaded in the [Key pairs](/metagraph-development/guides/deploy-a-metagraph/key-pairs) step.

**Grant privileges to the SSH key**[**​**](https://docs.constellationnetwork.io/sdk/guides/deploy-a-metagraph/base-instance/configuring-base-instance#grant-privileges-to-the-ssh-key)

```
chmod 400 MyKeypair.pem
```

**Use the `ssh` command to connect to your instance**[**​**](https://docs.constellationnetwork.io/sdk/guides/deploy-a-metagraph/base-instance/configuring-base-instance#use-the-ssh-command-to-connect-to-your-instance)

```
ssh -i "MyKeypair.pem" ubuntu@your_instance.aws-region.compute.amazonaws.com
```

The name/IP of the instance will be different, but you can get the instructions on how to connect via ssh in the **`Connect to your instance`** section of the EC2 Console.

<figure><img src="https://docs.constellationnetwork.io/assets/images/configuring-base-image-02-d46fc8e51d2bb2928d4c022a17e82dad.png" alt="" width="563"><figcaption></figcaption></figure>

If asked to confirm the fingerprint of the instance, type **`yes`**.

Once connected, you should see a screen similar to this:

<figure><img src="https://docs.constellationnetwork.io/assets/images/configuring-base-image-03-2db8329486bb524e62173cb36421b188.png" alt=""><figcaption></figcaption></figure>

### Base instance setup[​](https://docs.constellationnetwork.io/sdk/guides/deploy-a-metagraph/base-instance/configuring-base-instance#base-instance-setup) <a href="#base-instance-setup" id="base-instance-setup"></a>

Now, you can begin setting up your instance.

**Create base directory**[**​**](https://docs.constellationnetwork.io/sdk/guides/deploy-a-metagraph/base-instance/configuring-base-instance#create-base-directory)

Create a directory named **`code`** and navigate into it. This will be the base directory that we will work out of.

```
mkdir code
cd code/
```

**Create layer directories**[**​**](https://docs.constellationnetwork.io/sdk/guides/deploy-a-metagraph/base-instance/configuring-base-instance#create-layer-directories)

Create the following directories: `global-l0`, `metagraph-l0`, `currency-l1`, and `data-l1`. These will be the root directories for each of the layers.

```
mkdir global-l0
mkdir metagraph-l0
mkdir currency-l1
mkdir data-l1
```

**Add Tessellation utilities to each directory**[**​**](https://docs.constellationnetwork.io/sdk/guides/deploy-a-metagraph/base-instance/configuring-base-instance#add-tessellation-utilities-to-each-directory)

Replace "v2.2.0" with the latest version of Tessellation found here: <https://github.com/Constellation-Labs/tessellation/releases>

```
cd global-l0

wget https://github.com/Constellation-Labs/tessellation/releases/download/v2.2.0/cl-node.jar
wget https://github.com/Constellation-Labs/tessellation/releases/download/v2.2.0/cl-wallet.jar
wget https://github.com/Constellation-Labs/tessellation/releases/download/v2.2.0/cl-keytool.jar

cp cl-wallet.jar metagraph-l0/cl-wallet.jar
cp cl-wallet.jar currency-l1/cl-wallet.jar
cp cl-wallet.jar data-l1/cl-wallet.jar

cp cl-keytool.jar metagraph-l0/cl-keytool.jar
cp cl-keytool.jar currency-l1/cl-keytool.jar
cp cl-keytool.jar data-l1/cl-keytool.jar
```

**Install the necessary dependencies:**[**​**](https://docs.constellationnetwork.io/sdk/guides/deploy-a-metagraph/base-instance/configuring-base-instance#install-the-necessary-dependencies)

```
sudo apt-get update
sudo apt install openjdk-11-jdk -y
sudo apt-get install curl -y
sudo apt-get install wget -y
sudo apt-get install gnupg -y
 
sudo echo "deb https://repo.scala-sbt.org/scalasbt/debian all main" | sudo tee /etc/apt/sources.list.d/sbt.list
sudo echo "deb https://repo.scala-sbt.org/scalasbt/debian /" | sudo tee /etc/apt/sources.list.d/sbt_old.list
sudo curl -sL "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x2EE0EA64E40A89B84B2DF73499E82A75642AC823" | sudo apt-key add
 
sudo apt-get update
 
sudo apt-get install sbt -y
```

### Generate Metagraph JAR Files[​](https://docs.constellationnetwork.io/sdk/guides/deploy-a-metagraph/base-instance/configuring-base-instance#generate-metagraph-jar-files) <a href="#generate-metagraph-jar-files" id="generate-metagraph-jar-files"></a>

For each of the metagraph layers, code from your project must be compiled into executable jar files. During local development with Euclid these files are compiled for you and stored within the `infra` directory of your project code. You can move these locally tested JAR files directly onto your base instance for deployment (recommended for this tutorial).

After ensuring that your project is ready for deployment, navigate to the following directory in your local Euclid codebase: `infra -> docker -> shared -> jars`

Within this directory, you will find the following JARs:

```
- `metagraph-l0.jar`
- `metagraph-l1-currency.jar`
- `metagraph-l1-data.jar`
```

Use `scp` to copy the files to your metagraph layer directories:

```
scp -i "MyKeypair.pem" your_jar_directory/metagraph-l0.jar ubuntu@ec2-your-ip.your-region.compute.amazonaws.com:code/metagraph-l0/metagraph-l0.jar
scp -i "MyKeypair.pem" your_jar_directory/metagraph-l1-currency.jar ubuntu@ec2-your-ip.your-region.compute.amazonaws.com:code/currency-l1/currency-l1.jar
scp -i "MyKeypair.pem" your_jar_directory/metagraph-l1-data.jar ubuntu@ec2-your-ip.your-region.compute.amazonaws.com:code/data-l1/data-l1.jar
```

**Alternative Option**[**​**](https://docs.constellationnetwork.io/sdk/guides/deploy-a-metagraph/base-instance/configuring-base-instance#alternative-option)

Alternatively, you could choose to generate the JARs on the base instance itself. If you choose that route, you can follow the steps in the following guide.

[Generating JARs on Base Instance](#generate-metagraph-jar-files)

### Setting up the Genesis File[​](https://docs.constellationnetwork.io/sdk/guides/deploy-a-metagraph/base-instance/configuring-base-instance#setting-up-the-genesis-file) <a href="#setting-up-the-genesis-file" id="setting-up-the-genesis-file"></a>

The genesis file is a configuration file that sets initial token balances on your metagraph at launch, or genesis. This allows your project to start with any configuration of wallet balances you choose, which will only later be updated through token transactions and rewards distributions.

#### Genesis file[​](https://docs.constellationnetwork.io/sdk/guides/deploy-a-metagraph/base-instance/configuring-base-instance#genesis-file) <a href="#genesis-file" id="genesis-file"></a>

If you already have your genesis file used for testing on Euclid, you can upload the file here.

```
scp -i "MyKeypair.pem" your_genesis_file.csv ubuntu@ec2-your-ip.your-region.compute.amazonaws.com:code/metagraph-l0/genesis.csv
```

#### Generating metagraphID[​](https://docs.constellationnetwork.io/sdk/guides/deploy-a-metagraph/base-instance/configuring-base-instance#generating-metagraphid) <a href="#generating-metagraphid" id="generating-metagraphid"></a>

Before connecting your metagraph to the network, we will generate its' ID and save the output locally. This ID is a unique key used by the Global L0 store state about your metagraph.

**info**

When deploying to MainNet, your metagraphID must be added to the metagraph seedlist before you will be able to connect. Provide the metagraphID generated below to the Constellation team to be added to the seedlist.

IntegrationNet does not have a metagraph seedlist so you can connect easily and regenerate your metagraphID if needed during testing.

**Generate your metagraphID**[**​**](https://docs.constellationnetwork.io/sdk/guides/deploy-a-metagraph/base-instance/configuring-base-instance#generate-your-metagraphid)

```
cd ~/code/metagraph-l0

export CL_KEYSTORE=test.p12
export CL_KEYALIAS=test
export CL_PASSWORD=test
export CL_PUBLIC_HTTP_PORT=9100
export CL_P2P_HTTP_PORT=9101
export CL_CLI_HTTP_PORT=9102
export CL_GLOBAL_L0_PEER_HTTP_HOST=localhost
export CL_GLOBAL_L0_PEER_HTTP_PORT=9000
export CL_GLOBAL_L0_PEER_ID=e2f4496e5872682d7a55aa06e507a58e96b5d48a5286bfdff7ed780fa464d9e789b2760ecd840f4cb3ee6e1c1d81b2ee844c88dbebf149b1084b7313eb680714
export CL_APP_ENV=integrationnet

java -jar cl-keytool.jar generate

nohup java -jar metagraph-l0.jar create-genesis genesis.csv > metagraph-l0.log 2>&1 &

rm test.p12
```

**View Genesis Output**[**​**](https://docs.constellationnetwork.io/sdk/guides/deploy-a-metagraph/base-instance/configuring-base-instance#view-genesis-output)

You will find the following files in your directory:

* `genesis.snapshot`
* `genesis.address`

The `genesis.address` file contains your metagraphID, which should resemble a DAG address: `DAG...`. The `genesis.snapshot` file contains snapshot zero of your metagraph which will be used when connecting to the network for the first time.

**Your base instance is now fully configured**[**​**](https://docs.constellationnetwork.io/sdk/guides/deploy-a-metagraph/base-instance/configuring-base-instance#your-base-instance-is-now-fully-configured)

The following sections will cover creating each EC2 instance from this base instance and configuring each individually. You can skip ahead to the [Generating AMI](/metagraph-development/guides/deploy-a-metagraph/base-instance/generating-ami-image-from-base-instance) section.


# Generating AMI (Image) from Base Instance

Now that our base instance is configured, we can generate an AMI (Amazon Machine Image) from the instance. The AMI will allow us to create our other two EC2 instances as exact copies of the one we've already configured.

**Create the Image**

To generate the AMI, select your instance and then actions → Image and templates → Create Image

<figure><img src="https://docs.constellationnetwork.io/assets/images/generating-AMI-from-instance-01-8de4798908bdacbb8c742f2948018eca.png" alt=""><figcaption></figcaption></figure>

We can repeat the same name when configuring the image:

<figure><img src="https://docs.constellationnetwork.io/assets/images/generating-AMI-from-instance-02-ee73cc26846530499a131d3d13197b38.png" alt=""><figcaption></figcaption></figure>

**Press Create Image**

<figure><img src="/files/F96v2A4ooFm7TvE6lwcO" alt=""><figcaption></figcaption></figure>

This step will take some time but you can follow progress on the AMIs page.

**Wait Until the Image is in Available Status**

![Generating AMI](https://docs.constellationnetwork.io/assets/images/generating-AMI-from-instance-04-ed4e6e011a53d939ef05bb813cdeea6b.png)

**Delete Base Instance**

Once the image is ready we can delete the instance used to generate the image. To do this, go back to the instances page, select the instance, and then press&#x20;


# Launching instances from AMI

The AMI created in the previous step can now be used to generate each of our 3 EC2 instances for our metagraph.

**Visit the AMI Page**

Select the AMI we created previously and press the **`Launch instance from AMI`** button.

**Configure Instance**

Name your instance, select the **`Instance Type`** as **`t2.xlarge`**, choose your **`Key pair`**, and select the appropriate **`Security Groups`**.

**Launch Instance**

Press the `Launch Instance` button.

**Repeat**

Perform the above steps 3 times to create 3 EC2 instances from the AMI.

**Connect to Instances**

Find the ip address of each instance in the EC2 dashboard and connect using your previously generated SSH key. You should be able to access all 3 instances and confirm they are properly configured.

```
ssh -i "MyKeypair.pem" ubuntu@ip.of.your.instance
```


# Start Metagraph Instances

## Start Here

{% content-ref url="/pages/Mp9MXvfSsQMefVHpUaOc" %}
[Configuring P12 Files](/metagraph-development/guides/deploy-a-metagraph/start-metagraph-instances/configuring-p12-files)
{% endcontent-ref %}


# Configuring P12 Files

### P12 Files <a href="#p12-files" id="p12-files"></a>

P12 files contain the public/private keypair for your node to connect to the network which is protected by an alias and a password. These files are necessary for all layers to communicate with each other and validate identity of other nodes. In this step, we will move p12 files to each of the 3 nodes so that they are available when starting each layer of the network.

This guide will use just 3 p12 files in total (1 for each server instance) which is the minimal configuration. For production deployments, it is recommended that each layer and instance has its own p12 file rather than sharing between the layers.

**Transfer p12 Files**

Run the following command to transfer a p12 file to each layer's directory for a single EC2 instance.

Replace `:p12_file.p12` and `your_instance_ip` with your actual p12 file and node IP.

```
scp -i "MyKeypair.pem" :p12_file.p12 your_instance_ip:code/global-l0
scp -i "MyKeypair.pem" :p12_file.p12 your_instance_ip:code/metagraph-l0
scp -i "MyKeypair.pem" :p12_file.p12 your_instance_ip:code/currency-l1
scp -i "MyKeypair.pem" :p12_file.p12 your_instance_ip:code/data-l1
```

**Repeat this process for each of your 3 instances.**

Make sure to use a different P12 for instance when repeating the above steps.

Your P12 files will now be available on your nodes and you can move on the starting up each layer.


# Start Global L0 Instances

In the following sections, we will SSH into each of our 3 servers and configure each layer and then join it to the network. Note that both IntegrationNet and MainNet have seedlists for the Global L0 layer. Make sure your node IDs have been added to the seedlist prior to joining, otherwise you will not be allowed to join.

#### Setup Global L0 <a href="#setup-global-l0" id="setup-global-l0"></a>

#### SSH into one of your EC2 instances and move to the `global-l0` directory. <a href="#setup-global-l0" id="setup-global-l0"></a>

```
ssh -i "MyKeypair.pem" ubuntu@your_instance_ip"
cd code/global-l0
```

**Set environment variables**

Export the following environment variables, changing the values to use your p12 file's real name, alias, and password.

```
export CL_KEYSTORE=":p12_file.p12"
export CL_KEYALIAS=":p12_file_alias"
export CL_PASSWORD=":p12_password"
```

**Obtain public IP**

Obtain the public IP of your cluster by using the following command.

```
curl ifconfig.me
```

**Download the latest seedlist**

Download the latest seedlist from either IntegrationNet or MainNet.

For IntegrationNet, the seedlist is kept in an S3 bucket and can be downloaded directly.

```
wget https://constellationlabs-dag.s3.us-west-1.amazonaws.com/integrationnet-seedlist
```

For MainNet, the seedlist is stored in Github as a build asset for each release. Make sure to fill in the latest version below to get the correct seedlist.

```
wget https://github.com/Constellation-Labs/tessellation/releases/download/v2.2.1/mainnet-seedlist
```

**Start your node**

The following command will start your Global L0 node in validator mode.

```
nohup java -jar cl-node.jar run-validator --ip :instance_public_ip --public-port 9000 --p2p-port 9001 --cli-port 9002 --collateral 0 --seedlist integrationnet-seedlist -e integrationnet  > logs.log 2>&1 &
```

**Check logs**

You should see a new directory `logs` with a `app.log` file. Check the logs for any errors.

**Join the network**

Now that the node is running, we need to join it to a node on the network. You can find a node to connect to using the network load balancer at

```
https://l0-lb-integrationnet.constellationnetwork.io/node/info
```

Run the following command with the **`id`**, **`ip`**, and **`p2pPort`** parameters updated.

```
curl -v -X POST http://localhost:9002/cluster/join -H "Content-type: application/json" -d '{ "id":":integrationnet_node_id", "ip": ":integrationnet_node_ip", "p2pPort": :integrationnet_node_p2p_port }'
```

**Check connection**

Verify that your node is connected to the network with the `/node/info` endpoint on your node. It can be accessed at the following url. You should see `state: Ready` if your node has successfully connected to the network.

```
http://your_node_id:9000/node/info
```

#### Repeat <a href="#repeat" id="repeat"></a>

Repeat the above steps for each of your 3 nodes before moving on to start your metagraph layers.


# Start Metagraph L0 Instances

In this section, we will start each of our metagraph L0 instances and join them to the Global L0 network.

#### Setup Metagraph L0 <a href="#setup-metagraph-l0" id="setup-metagraph-l0"></a>

SSH into one of your EC2 instances and move to the `metagraph-l0` directory.

```
ssh -i "MyKeypair.pem" ubuntu@your_instance_ip"
cd code/metagraph-l0
```

**Set environment variables**

Export the following environment variables, changing the values to use your p12 file's real name, alias, and password.

```
export CL_KEYSTORE=":p12_file_used_on_seedlist_1.p12"
export CL_KEYALIAS=":p12_file_used_on_seedlist_1"
export CL_PASSWORD=":file_password_1"
```

Also export the following environment variables, filling in `CL_GLOBAL_L0_PEER_ID` with the public ID of your Global L0 node which can be obtained from the `/node/info` endpoint at the end of the previous step. This is also the pub ID of your p12 file.

```
export CL_PUBLIC_HTTP_PORT=9100
export CL_P2P_HTTP_PORT=9101
export CL_CLI_HTTP_PORT=9102
export CL_GLOBAL_L0_PEER_HTTP_HOST=localhost
export CL_GLOBAL_L0_PEER_HTTP_PORT=9000
export CL_GLOBAL_L0_PEER_ID=:local_global_l0_id
CL_APP_ENV=integrationnet
export CL_COLLATERAL=0
```

**Start your metagraph L0 node (genesis)**

**note**

Run this command only on the first of your instances. When you repeat these steps for the 2nd and 3rd instance, use the `run-validator` joining process below instead.

Use the following command to start the metagraph L0 process in genesis mode. This should only be done once to start your network from the genesis snapshot. In the future, to restart the network use `run-rollback` instead to restart from the most recent snapshot. Fill in the `:instance_ip` variable with the public IP address of your node.

```
nohup java -jar metagraph-l0.jar run-genesis genesis.snapshot --ip :instance_ip > metagraph-l0-logs.log 2>&1 &
```

You can check if your metagraph L0 successfully started using the `/cluster/info` endpoint or by checking logs.

```
http://:your_ip:9100/cluster/info
```

**Start your metagraph L0 node (validator)**

The 2nd and 3rd nodes should be started in validator mode and joined to the first node that was run in genesis or run-rollback mode. All other steps are the same.

```
nohup java -jar metagraph-l0.jar run-validator --ip :ip > metagraph-l0-logs.log 2>&1 &
```

Once the node is running in validator mode, we need to join it to the first node using the following command

```
curl -v -X POST http://localhost:9102/cluster/join -H "Content-type: application/json" -d '{ "id":":metagraph_node_1_id", "ip": "metagraph_node_1_ip", "p2pPort": 9101 }'
```

You can check if the nodes successfully started using the `/cluster/info` endpoint for your metagraph L0. You should see nodes appear in the list if all started properly. http\://:your\_ip:9100/cluster/info

#### Repeat <a href="#repeat" id="repeat"></a>

Repeat the above steps for each of your 3 nodes before moving on to start your metagraph L1 layers. Note that the startup commands differ between the three nodes. The first node should be started in genesis or run-rollback mode. The second and third nodes should be started in validator mode and joined to the first node.

[Edit this page](https://github.com/Constellation-Labs/documentation-hub/edit/main/sdk/guides/deploy-a-metagraph/building-metagraph-instances/02-start-metagraph-l0-instances.md)<br>


# Start Currency L1 Instances

In this section, we will start each of our currency L1 instances and join them to the metagraph L0 network.

#### Setup Currency L1 <a href="#setup-currency-l1" id="setup-currency-l1"></a>

SSH into one of your EC2 instances and move to the `currency-l1` directory.

```
ssh -i "MyKeypair.pem" ubuntu@your_instance_ip"
cd code/currency-l1
```

**Set environment variables**

Export the following environment variables, changing the values to use your p12 file's real name, alias, and password.

```
export CL_KEYSTORE=":p12_file_used_on_seedlist_1.p12"
export CL_KEYALIAS=":p12_file_used_on_seedlist_1"
export CL_PASSWORD=":file_password_1"
```

Also export the following environment variables, filling in the following:

* `CL_GLOBAL_L0_PEER_ID`: The public ID of your Global L0 node which can be obtained from the `/node/info` endpoint of your Global L0 instance (<http://your\\_node\\_id:9000/node/info>).
* `CL_L0_PEER_ID`: The public ID of the metagraph l0 node which is the same as `CL_GLOBAL_L0_PEER_ID` above if you're using the same p12 files for all layers.
* `CL_GLOBAL_L0_PEER_HTTP_HOST`: The public IP of this node (points to global-l0 layer).
* `CL_L0_PEER_HTTP_HOST`: The public IP of this node (points to metagraph-l0 layer).
* `CL_L0_TOKEN_IDENTIFIER`: The metagraph ID in your address.genesis file.

```
export CL_PUBLIC_HTTP_PORT=9200
export CL_P2P_HTTP_PORT=9201
export CL_CLI_HTTP_PORT=9202
export CL_GLOBAL_L0_PEER_HTTP_PORT=9000
export CL_GLOBAL_L0_PEER_HTTP_HOST=:ip_from_metagraph_l0_node_1_global_l0
export CL_GLOBAL_L0_PEER_ID=:id_from_metagraph_l0_node_1_global_l0
export CL_L0_PEER_HTTP_HOST=:ip_from_metagraph_l0_node_1_metagraph_l0
export CL_L0_PEER_HTTP_PORT=9100
export CL_L0_PEER_ID=:id_from_metagraph_l0_node_1_metagraph_l0
export CL_L0_TOKEN_IDENTIFIER=:**METAGRAPH_ID**
export CL_APP_ENV=integrationnet
export CL_COLLATERAL=0
```

**Start your currency L1 node (initial)**

**note**

Run this command only on the first of your instances. When you repeat these steps for the 2nd and 3rd instance, use the `run-validator` joining process below instead.

Run the following command, filling in the public ip address of your instance.

```
nohup java -jar currency-l1.jar run-initial-validator --ip :instance_ip > metagprah-l1-logs.log 2>&1 &
```

Check if your Currency L1 successfully started: http\://:your\_ip:9200/cluster/info

**Start your currency L1 node (validator)**

The 2nd and 3rd nodes should be started in validator mode and joined to the first node that was run in initial-validator mode. All other steps are the same.

```
nohup java -jar currency-l1.jar run-validator --ip :ip > currency-l1-logs.log 2>&1 &
```

Run the following command to join, filling in the `id` and `ip` of your first currency L1 node.

```
curl -v -X POST http://localhost:9202/cluster/join -H "Content-type: application/json" -d '{ "id":":id_from_currency_l1_1", "ip": ":ip_from_currency_l1", "p2pPort": 9201 }'
```

You can check if the nodes successfully started using the `/cluster/info` endpoint for your metagraph L0. You should see nodes appear in the list if all started properly. http\://:your\_ip:9200/cluster/info

#### Repeat <a href="#repeat" id="repeat"></a>

Repeat the above steps for each of your 3 currency L1 nodes before moving on to start your data L1 layer. Note that the startup commands differ between the three nodes. The first node should be started in initial-validator mode. The second and third nodes should be started in validator mode and joined to the first node.

[Edit this page](https://github.com/Constellation-Labs/documentation-hub/edit/main/sdk/guides/deploy-a-metagraph/building-metagraph-instances/03-start-currency-l1-instances.md)<br>


# Start Data L1 Instances

In this section, we will start each of our data L1 instances and join them to the metagraph L0 network.

#### Setup Data L1 <a href="#setup-data-l1" id="setup-data-l1"></a>

SSH into one of your EC2 instances and move to the `data-l1` directory.

```
ssh -i "MyKeypair.pem" ubuntu@your_instance_ip"
cd code/data-l1
```

**Set environment variables**

Export the following environment variables, changing the values to use your p12 file's real name, alias, and password.

```
export CL_KEYSTORE=":p12_file_used_on_seedlist_1.p12"
export CL_KEYALIAS=":p12_file_used_on_seedlist_1"
export CL_PASSWORD=":file_password_1"
```

Also export the following environment variables, filling in the following:

* `CL_GLOBAL_L0_PEER_ID`: The public ID of your Global L0 node which can be obtained from the `/node/info` endpoint of your Global L0 instance (<http://your\\_node\\_id:9000/node/info>).
* `CL_L0_PEER_ID`: The public ID of the metagraph l0 node which is the same as `CL_GLOBAL_L0_PEER_ID` above if you're using the same p12 files for all layers.
* `CL_GLOBAL_L0_PEER_HTTP_HOST`: The public IP of this node (points to global-l0 layer).
* `CL_L0_PEER_HTTP_HOST`: The public IP of this node (points to metagraph-l0 layer).
* `CL_L0_TOKEN_IDENTIFIER`: The metagraph ID in your address.genesis file.

```
export CL_PUBLIC_HTTP_PORT=9300
export CL_P2P_HTTP_PORT=9301
export CL_CLI_HTTP_PORT=9302
export CL_GLOBAL_L0_PEER_HTTP_HOST=:ip_from_metagraph_l0_node_1_global_l0
export CL_GLOBAL_L0_PEER_HTTP_PORT=9000
export CL_GLOBAL_L0_PEER_ID=:id_from_metagraph_l0_node_1_global_l0
export CL_L0_PEER_HTTP_HOST=:ip_from_metagraph_l0_node_1_metagraph_l0
export CL_L0_PEER_HTTP_PORT=9100
export CL_L0_PEER_ID=:id_from_metagraph_l0_node_1_metagraph_l0
export CL_L0_TOKEN_IDENTIFIER=:**METAGRAPH_ID**
export CL_APP_ENV=integrationnet
export CL_COLLATERAL=0
```

**Start your data L1 node (initial)**

**note**

Run this command only on the first of your instances. When you repeat these steps for the 2nd and 3rd instance, use the `run-validator` joining process below instead.

Run the following command, filling in the public ip address of your instance.

```
nohup java -jar data-l1.jar run-initial-validator --ip :instance_ip > metagprah-l1-logs.log 2>&1 &
```

Check if your data L1 node successfully started: http\://:your\_ip:9300/cluster/info

**Start your data L1 node (validator)**

The 2nd and 3rd nodes should be started in validator mode and joined to the first node that was run in initial-validator mode. All other steps are the same.

```
nohup java -jar data-l1.jar run-validator --ip :ip > data-l1-logs.log 2>&1 &
```

Run the following command to join, filling in the `id` and `ip` of your first data L1 node.

```
curl -v -X POST http://localhost:9302/cluster/join -H "Content-type: application/json" -d '{ "id":":id_from_data_l1_1", "ip": ":ip_from_data_l1", "p2pPort": 9301 }'
```

#### Repeat <a href="#repeat" id="repeat"></a>

Repeat the above steps for each of your 3 data L1 nodes before moving on to start your data L1 layer. Note that the startup commands differ between the three nodes. The first node should be started in initial-validator mode. The second and third nodes should be started in validator mode and joined to the first node.

### Verify <a href="#verify" id="verify"></a>

If you followed all steps, your metagraph is now fully deployed.

You can check the status of each of the node layers using their IP address and layer port number.

**Ports**

* Global L0: 9000
* Metagraph L0: 9100
* Currency L1: 9200
* Data L1: 9300

**Endpoints**

* `/cluster/info`: View nodes joined to the current layer's cluster
* `/node/info`: View info about a specific node and its status


# Network APIs

Metagraph networks (metagraph L0, currency L1, and data L1) and Hypergraph Networks (Global L0 and DAG L1) are all accessible via REST API endpoints. The endpoints share a similar structure and composition for easy integration into wallets, exchanges, and dApps.

{% content-ref url="/spaces/lzDyHxpeesNyOR3WIEd4/pages/seh626Nx374cpEQPOr9Y" %}
[Broken mention](broken://spaces/lzDyHxpeesNyOR3WIEd4/pages/seh626Nx374cpEQPOr9Y)
{% endcontent-ref %}


# Example Codebases

## Example Codebases

The Euclid SDK is designed to provide developers with the tools they need to build robust and scalable decentralized applications on the Constellation Network. To help you get started, we have curated a list of exemplary codebases that you can explore and learn from. These codebases are open-source projects that demonstrate various aspects of using the Euclid SDK in real-world scenarios.

### Codebases[​](https://docs.constellationnetwork.io/sdk/resources/example-codebases#codebases) <a href="#codebases" id="codebases"></a>

<table data-card-size="large" data-view="cards" data-full-width="true"><thead><tr><th></th><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th><th data-hidden data-card-cover data-type="files"></th></tr></thead><tbody><tr><td><strong>Metagraph Examples</strong></td><td>The Metagraph Examples repository contains several minimalist metagraph codebases designed to demonstrate specific metagraph features in a simplified context. All projects in this repo can be installed with <code>hydra install-template</code></td><td><strong>Displays:</strong> many concepts.</td><td><a href="https://github.com/Constellation-Labs/metagraph-examples">https://github.com/Constellation-Labs/metagraph-examples</a></td><td><a href="/files/gN3mMSr7iwlNYJWpMLvO">/files/gN3mMSr7iwlNYJWpMLvO</a></td></tr><tr><td><strong>Dor Metagraph</strong></td><td>This repository is the codebase of the Dor Metagraph, the first metagraph to launch to MainNet. The Dor Metagraph ingests foot traffic data from a network of IoT sensors.</td><td><strong>Displays:</strong> strategies for processing binary data types using decoders, reward distribution, and separation of public/private data using calculated state.</td><td><a href="https://github.com/Constellation-Labs/dor-metagraph">https://github.com/Constellation-Labs/dor-metagraph</a></td><td><a href="/files/0rMoZhnEHqn9J0fCWAv2">/files/0rMoZhnEHqn9J0fCWAv2</a></td></tr><tr><td><strong>EL PACA Metagraph</strong></td><td>This repository is the codebase of the EL PACA Metagraph, a social credit metagraph designed to track and reward community activity within the Constellation ecosystem.</td><td><strong>Displays:</strong> data fetching using daemons, integration with 3rd party APIs, and reward distribution</td><td><a href="https://github.com/Constellation-Labs/elpaca-metagraph">https://github.com/Constellation-Labs/elpaca-metagraph</a></td><td><a href="/files/v7TNofXMQdORlzIODykM">/files/v7TNofXMQdORlzIODykM</a></td></tr></tbody></table>


# Metagraph Development Video Series

## Metagraph Development Video Series

Originally created for the Metagraph Hackathon, this six-part video series is a must-watch for anyone building on Constellation Network. Join core team members as they break down the fundamentals of metagraph development, explore real-world production codebases, and tackle advanced technical topics. Whether you're new to metagraphs or looking to refine your skills, this series provides valuable insights to help you build and scale effectively.

### Videos[​](https://docs.constellationnetwork.io/sdk/resources/video-series#videos) <a href="#videos" id="videos"></a>

## Hackathon Kickoff

Tracks, Prizes, and Network Overview

{% embed url="<https://www.youtube.com/watch?v=c170I48P6lU>" %}

## Environment Setup

Intro to Euclid SDK and Tooling

{% embed url="<https://www.youtube.com/watch?v=W-vccxg28Hs>" %}

## Metagraph Development

Core Concepts and Design Patterns

{% embed url="<https://www.youtube.com/watch?v=W2T-W4kNKXs>" %}

## Build Session

Metagraph Design and Build Session.

{% embed url="<https://www.youtube.com/watch?v=mxWrxK_35Do>" %}

## Production Metagraph Codebase Review

Dor and EL PACA Metagraph Codebase Review

{% embed url="<https://www.youtube.com/watch?v=cZaeIMWf164>" %}

## Stargazer Wallet & Tooling

Deep Dive into Stargazer Wallet & Tooling

{% embed url="<https://www.youtube.com/watch?v=GbEuZDKtGWE>" %}


# Architecture

## Architecture

{% hint style="info" %}
**Transaction Lifecyle**

Interested in more in-depth information about the currency transaction lifecycle and data flow within the Hypergraph? See [Network Fundamentals Architecture](/network-fundamentals/concepts/architecture) for more info.
{% endhint %}

![Constellation Network architecture overview](https://docs.constellationnetwork.io/assets/images/api-architecture-638bc8459a2d31759365d96a2aa9b966.png)

In order to make the most of Constellation Network APIs, a brief understanding of the architecture of the network is useful. The Hypergraph consists of multiple layers of networks of individual responsibility through which transactions flow. Each of the major network layers has REST API endpoints available with distinct functionality. Transactions are sent to the outermost layer, labeled as L1 networks in the graphic, before being processed into a state snapshot in an L0 layer.

DAG transactions are sent to the DAG L1 network which bundles the transactions into blocks and sends them to the Global L0 for inclusion into global snapshots. Snapshots are then indexed by the Block Explorer via a snapshot streaming service that processes them.

Metagraph token transactions flow in a similar way from the metagraph currency L1 where they're received, bundled into blocks, and then passed to the currency L0 layer to be included in metagraph snapshots. The metagraph snapshots are then submitted to the Global L0 to be included in global snapshots and eventually indexed into the Block Explorer via the snapshot streaming service.

The APIs for each of the L1 and L0 layers is nearly identical with a few minor differences, namely endpoint naming of `/dag` for DAG endpoints and `/currency` for currency endpoints. You can explore the API specs for each in the [Network APIs](broken://pages/MvMUSTiDwfE0qv8xAewu) sections below.

In summary, the functionalities of the different APIs for DAG and metagraph tokens are as follows:

## DAG[​](https://docs.constellationnetwork.io/hypergraph/architecture#dag) <a href="#dag" id="dag"></a>

### DAG L1[​](https://docs.constellationnetwork.io/hypergraph/architecture#dag-l1) <a href="#dag-l1" id="dag-l1"></a>

* DAG transactions are sent to this API via the `/transactions` POST endpoint.
* Pending transactions can be queried through this API via the `/transactions/:hash` endpoint.
* The address `lastRef` for an address can be queried here as well.

### Global L0[​](https://docs.constellationnetwork.io/hypergraph/architecture#global-l0) <a href="#global-l0" id="global-l0"></a>

* Query global snaphots
* Query DAG supply and address balances
* Submit metagraph (state channel) snapshots

## Metagraph Tokens[​](https://docs.constellationnetwork.io/hypergraph/architecture#metagraph-tokens) <a href="#metagraph-tokens" id="metagraph-tokens"></a>

### Metagraph L1[​](https://docs.constellationnetwork.io/hypergraph/architecture#metagraph-l1) <a href="#metagraph-l1" id="metagraph-l1"></a>

* DAG transactions are sent to this API via the `/transactions` POST endpoint.
* Pending transactions can be queried through this API via the `/transactions/:hash` endpoint.
* The address `lastRef` for an address can be queried here as well.

### Metagraph L0[​](https://docs.constellationnetwork.io/hypergraph/architecture#metagraph-l0) <a href="#metagraph-l0" id="metagraph-l0"></a>

* Query metagraph snapshots
* Query metagraph token supply and address balances

### Global L0[​](https://docs.constellationnetwork.io/hypergraph/architecture#global-l0-1) <a href="#global-l0-1" id="global-l0-1"></a>

* Submit metagraph (state channel) snapshots


# IntegrationNet

Constellation provides developers with a full featured IntegrationNet to test applications and metagraphs before they're ready for the production environment. The IntegrationNet has all of the same features as MainNet and can therefore be used to validate application integrations in a realistic way.

{% hint style="success" %}
**Developing a Metagraph**\
Metagraph developers may use IntegrationNet as they're nearing production readiness. See [Setup a metagraph](/metagraph-development/guides/quick-start).
{% endhint %}

## Connecting to IntegrationNet[​](https://docs.constellationnetwork.io/hypergraph/integrationnet#connecting-to-integrationnet) <a href="#connecting-to-integrationnet" id="connecting-to-integrationnet"></a>

The following urls can used to access IntegrationNet:

* **Block Explorer API**: [https://be-integrationnet.constellationnetwork.io](https://be-integrationnet.constellationnetwork.io/)
* **Global L0 API**: [https://l0-lb-integrationnet.constellationnetwork.io](https://l0-lb-integrationnet.constellationnetwork.io/)
* **DAG L1 API**: [https://l1-lb-integrationnet.constellationnetwork.io](https://l1-lb-integrationnet.constellationnetwork.io/)

### Faucet[​](https://docs.constellationnetwork.io/hypergraph/integrationnet#faucet) <a href="#faucet" id="faucet"></a>

Constellation hosts a IntegrationNet faucet which distributes IntegrationNet DAG for testing purposes. This coin has no value and can only be used on IntegrationNet. The faucet provides small amounts of DAG at each request with rate limiting to prevent depletion of its DAG reserves.

The faucet can be accessed at:

```
GET https://faucet.constellationnetwork.io/integrationnet/faucet/<YOUR WALLET ADDRESS>

```


# DAG4.js

Dag4.js Javascript API

The dag4.js typescript library provides secure wallet functionality in javascript and convenient wrappers for interacting with Constellation Network APIs. The library is platform agnostic and can be used to build apps in browsers, NodeJS, or React Native.

{% hint style="success" %}
**View Dag4.js on Github**

You can find the dag4 repo and additional documentation on [Github](https://github.com/StardustCollective/dag4.js).
{% endhint %}

## Installation[​](https://docs.constellationnetwork.io/hypergraph/dag4#installation) <a href="#installation" id="installation"></a>

### **NPM**

```typescript
npm install @stardust-collective/dag4
```

### ***or*****&#x20;Yarn**

```typescript
yarn add @stardust-collective/dag4
```

## Usage[​](https://docs.constellationnetwork.io/hypergraph/dag4#usage) <a href="#usage" id="usage"></a>

### **Node**

```typescript
const { dag4 } = require('@stardust-collective/dag4');
```

### **ES6**

```typescript
import { dag4 } from '@stardust-collective/dag4';
```


# Intro to dag4.js

The dag4.js typescript library provides secure wallet functionality in javascript and convenient wrappers for interacting with Constellation Network APIs. The library is platform agnostic and can be used to build apps in browsers, NodeJS, or React Native.

**View Dag4.js on Github**

You can find the dag4 repo and additional documentation on [Github](https://github.com/StardustCollective/dag4.js).

### Installation[​](https://docs.constellationnetwork.io/hypergraph/dag4#installation) <a href="#installation" id="installation"></a>

**NPM**

```bash
npm install @stardust-collective/dag4
```

***or*****&#x20;Yarn**

```bash
yarn add @stardust-collective/dag4
```

### Usage[​](https://docs.constellationnetwork.io/hypergraph/dag4#usage) <a href="#usage" id="usage"></a>

**Node**

```typescript
const { dag4 } = require('@stardust-collective/dag4');
```

**ES6**

```typescript
import { dag4 } from '@stardust-collective/dag4';
```


# Interacting with Wallets

{% hint style="info" %}
**Accounts and Keys**

Want more detailed information about accounts are handled on the Hypergraph? Read about [Accounts and Keys](/network-fundamentals/accounts-and-keys).
{% endhint %}

### Interacting with Wallets[​](https://docs.constellationnetwork.io/hypergraph/dag4-wallets#interacting-with-wallets) <a href="#interacting-with-wallets" id="interacting-with-wallets"></a>

A wallet consists of a private key, a public key, and an address. You can create a new private key like this.

```typescript
const pk = dag4.keyStore.generatePrivateKey();
```

#### Login with a PK[​](https://docs.constellationnetwork.io/hypergraph/dag4-wallets#login-with-a-pk) <a href="#login-with-a-pk" id="login-with-a-pk"></a>

Before accessing methods on dag4.account specific to a wallet, you'll need to log in with a private key or seed phrase.

```typescript
dag4.account.loginPrivateKey(pk);
```

#### Login with a seed phrase[​](https://docs.constellationnetwork.io/hypergraph/dag4-wallets#login-with-a-seed-phrase) <a href="#login-with-a-seed-phrase" id="login-with-a-seed-phrase"></a>

If you already have a pneumonic phrase generated by a web wallet or somewhere else you can log in with that as well.

```typescript
dag4.account.loginSeedPhrase('disco foxtrot calm appleseed trinity organ putter waldorf ordinary shatter green portion');
```

#### Check DAG address[​](https://docs.constellationnetwork.io/hypergraph/dag4-wallets#check-dag-address) <a href="#check-dag-address" id="check-dag-address"></a>

```typescript
const address = dag4.account.address;
```

#### Get wallet public key[​](https://docs.constellationnetwork.io/hypergraph/dag4-wallets#get-wallet-public-key) <a href="#get-wallet-public-key" id="get-wallet-public-key"></a>

```typescript
dag4.account.publicKey;
```


# Connecting to the Network

Dag4.js provides reasonable configuration values by default for accessing Constellation Network versions 1.0 and 2.0.

#### Minimal network configuration[​](https://docs.constellationnetwork.io/hypergraph/dag4-network#minimal-network-configuration) <a href="#minimal-network-configuration" id="minimal-network-configuration"></a>

```typescript
dag4.account.connect({
  networkVersion: '2.0',
  testnet: true
});
```

#### Custom network configuration[​](https://docs.constellationnetwork.io/hypergraph/dag4-network#custom-network-configuration) <a href="#custom-network-configuration" id="custom-network-configuration"></a>

You can provide custom values for each the three network API endpoints to set up a custom connection.

```typescript
dag4.account.connect({
  networkVersion: '2.0',
  beUrl: 'https://be-mainnet.constellationnetwork.io/',
  l0Url: 'http://13.52.246.74:9000',
  l1Url: 'http://13.52.246.74:9010'
});
```

#### Default Endpoints[​](https://docs.constellationnetwork.io/hypergraph/dag4-network#default-endpoints) <a href="#default-endpoints" id="default-endpoints"></a>

The following endpoints are used by default by Dag4.

**IntegrationNet**[**​**](https://docs.constellationnetwork.io/hypergraph/dag4-network#20-integrationnet)

* Block Explorer API: [https://be-integrationnet.constellationnetwork.io](https://be-integrationnet.constellationnetwork.io/)
* L0 API: [https://l0-lb-integrationnet.constellationnetwork.io](https://l0-lb-integrationnet.constellationnetwork.io/)
* L1 API: [https://l1-lb-integrationnet.constellationnetwork.io](https://l1-lb-integrationnet.constellationnetwork.io/)

```
dag4.account.connect({
  id: 'integration2',
  networkVersion: '2.0',
  beUrl: 'https://be-integrationnet.constellationnetwork.io',
  l0Url: 'https://l0-lb-integrationnet.constellationnetwork.io',
  l1Url: 'https://l1-lb-integrationnet.constellationnetwork.io'
}, false);
```

**MainNet**[**​**](https://docs.constellationnetwork.io/hypergraph/dag4-network#20-mainnet)

* Block Explorer API: [https://be-mainnet.constellationnetwork.io](https://be-mainnet.constellationnetwork.io/)
* L0 API: [https://l0-lb-mainnet.constellationnetwork.io](https://l0-lb-mainnet.constellationnetwork.io/)
* L1 API: [https://l1-lb-mainnet.constellationnetwork.io](https://l1-lb-mainnet.constellationnetwork.io/)

```
dag4.account.connect({
  networkVersion: '2.0',
  testnet: false
});
```

{% hint style="warning" %}
TestNet usage is not recommended as it is expected to be unstable. Use IntegrationNet as the preferred testnet.&#x20;
{% endhint %}

**TestNet**[**​**](https://docs.constellationnetwork.io/hypergraph/dag4-network#20-testnet)

* Block Explorer API: [https://be-testnet.constellationnetwork.io](https://be-testnet.constellationnetwork.io/)
* L0 API: [https://l0-lb-testnet.constellationnetwork.io](https://l0-lb-testnet.constellationnetwork.io/)
* L1 API: [https://l1-lb-testnet.constellationnetwork.io](https://l1-lb-testnet.constellationnetwork.io/)

```typescript
dag4.account.connect({
  networkVersion: '2.0',
  testnet: true
});
```


# Sending Transactions

#### Send a single transaction (online)[​](https://docs.constellationnetwork.io/hypergraph/dag4-transactions#send-a-single-transaction-online) <a href="#send-a-single-transaction-online" id="send-a-single-transaction-online"></a>

```typescript
const { dag4 } = require('@stardust-collective/dag4');

dag4.account.connect({
  networkVersion: '2.0',
  testnet: true
});

dag4.account.loginPrivateKey('MY-PRIVATE-KEY');

const toAddress = 'DAGabc123...';
const amount = 25.551;
const fee = 0;

await dag4.account.transferDag(toAddress, amount, fee);
```

#### Send a transaction (offline signed)[​](https://docs.constellationnetwork.io/hypergraph/dag4-transactions#send-a-transaction-offline-signed) <a href="#send-a-transaction-offline-signed" id="send-a-transaction-offline-signed"></a>

```typescript
// Get last ref online, or else fetch from an offline data store
const lastRef = await dag4.network.getAddressLastAcceptedTransactionRef('DAGWalletSendingAddress');

// Get signed transaction (offline)
const txn = await dag4.account.generateSignedTransaction('DAGabc123...', 25.551, 0, lastRef);

// Send transaction (online)
await dag4.network.postTransaction(txn);
```

#### Generate bulk transactions offline and send[​](https://docs.constellationnetwork.io/hypergraph/dag4-transactions#generate-bulk-transactions-offline-and-send) <a href="#generate-bulk-transactions-offline-and-send" id="generate-bulk-transactions-offline-and-send"></a>

```typescript
// Get last ref online, or else fetch from an offline data store
let lastRef = await dag4.network.getAddressLastAcceptedTransactionRef('DAGWalletSendingAddress');

// Generate txns offline
const txn_data = [
  {address: 'DAGabc123...', amount: 10, fee: 0},
  {address: 'DAGxyz987...', amount: 25.01, fee: 0},
  {address: 'DAGzzz555...', amount: 1.01, fee: 0},
  {address: 'DAGwww988...', amount: 0.00000001, fee: 0},
];

const hashes = await dag4.account.transferDagBatch(txn_data, lastRef);

// console.log(hashes)
```

**Choosing a Transaction Fee**

Transactions without a fee are processed at a maximum of one transaction per global snapshot, or roughly 1 transaction every 5 seconds. In practice this means that almost all transactions do not require a fee unless you need to send a large number of transactions in a short period of time. To send more transactions per snapshot, include a small fee of 0.00000001 DAG with each transaction. Up to 100 transactions per snapshot will be processed if a fee is included.

#### Check the status of a transaction[​](https://docs.constellationnetwork.io/hypergraph/dag4-transactions#check-the-status-of-a-transaction) <a href="#check-the-status-of-a-transaction" id="check-the-status-of-a-transaction"></a>

When a transaction is sent to the network and is accepted, the response will return a hash that can be used to monitor the status of the transaction.

The transaction will initially be in a "waiting" state before it's included in a block and sent to a snapshot. While in this state you can check its status with the L1 API. Once processed by the network, the transaction will no longer be found via the L1 API and will be found in the block explorer API. At this point the transaction is considered final.

The following process can be used to confirm a transaction has been processed and reached a successful final state.

```typescript
// Send transaction
const hash = await dag4.network.postTransaction(txn);

// Keep checking the transaction status until this returns null
const pendingTx = await dag4.network.getPendingTransaction(txHash);

// Check the block explore API
if (pendingTx === null) {
  const confirmedTx = await dag4.network.getTransaction(txHash);

  if (confirmedTx) {
    // Txn is confirmed - from this point the state cannot be changed
    console.log('Transaction confirmed');
  } else {
    // The txn cannot be found on block explorer. It's a good idea to wait several seconds and try again to confirm the txn has actually been dropped
    console.log('Transaction dropped - not confirmed');
  }
}
```


# Message Signing

#### Sign an arbitrary message[​](https://docs.constellationnetwork.io/hypergraph/dag4-message-signing#sign-an-arbitrary-message) <a href="#sign-an-arbitrary-message" id="sign-an-arbitrary-message"></a>

The dag4-keystore package can be used to sign messages using a private key. Messages are signed using secp256k1 which generates a deterministic and canonical ECDSA signature that can be verified with a public key. This example code is not intended to be used to sign transactions.

```typescript
const privKey = dag4.keyStore.generatePrivateKey();
const pubKey = dag4.keyStore.getPublicKeyFromPrivate(privateKey);

const signature = await dag4.keyStore.sign(privKey, message);

const verified = dag4.keyStore.verify(pubKey, message, signature);

if (verified) {
  console.log('Signature verified');
} else {
  console.log('Signature invalid');
}
```


# Metagraph Tokens

Metagraph tokens work in much the same way as DAG. They share a common transaction format and API interface. Both DAG and metagraph tokens use DAG addresses for their balance maps so a single public/private keypair can control DAG and metagraph token accounts.

**Minimum Version**

You will need version 2.1.1 or higher in order to interact with metagraph token networks.

### Connecting to a metagraph[​](https://docs.constellationnetwork.io/hypergraph/metagraph-tokens#connecting-to-a-metagraph) <a href="#connecting-to-a-metagraph" id="connecting-to-a-metagraph"></a>

In order to interact with a metagraph token you will need to first need to create a connection to the Hypergraph, then create a metagraph client instance to connect to the metagraph and send transactions.

The example below connects to **IntegrationNet**. Fill in `:metagraph-l0-endpoint`, `:metagraph-currency-l1-endpoint`, and `:metagraph-id` in the code below with the correct details for the metagraph you are connecting to.

```typescript
const { dag4 } = require('@stardust-collective/dag4');

// Connect to Hypergraph on IntegrationNet or MainNet
dag4.account.connect({
  networkVersion: '2.0',
  beUrl: "https://be-integrationnet.constellationnetwork.io",
  l0Url: "https://l0-lb-integrationnet.constellationnetwork.io",
  l1Url: "https://l1-lb-integrationnet.constellationnetwork.io",
});

dag4.account.loginPrivateKey('MY-PRIVATE-KEY');

// Create a metagraphClient instance to connect to a specific metagraph
const metagraphClient = dag4.account.createMetagraphTokenClient({
  beUrl: "https://be-integrationnet.constellationnetwork.io",
  l0Url: ':metagraph-l0-endpoint',
  l1Url: ':metagraph-currency-l1-endpoint',
  metagraphId: ':metagraph-id'
});

// Make calls directly to the metagraph (check balance, send transactions, etc.)
await metagraphClient.getBalance();
// 100000
```

#### Metagraph connection details[​](https://docs.constellationnetwork.io/hypergraph/metagraph-tokens#metagraph-connection-details) <a href="#metagraph-connection-details" id="metagraph-connection-details"></a>

A list of existing metagraphs can be found on the [DAG Explorer](https://mainnet.dagexplorer.io/metagraphs). On each metagraph's page you'll find the Metagraph ID, as well as L0 and currency L1 endpoints, which are necessary for configuring your metagraph client to connect to a specific metagraph network.

#### Send a single transaction[​](https://docs.constellationnetwork.io/hypergraph/metagraph-tokens#send-a-single-transaction) <a href="#send-a-single-transaction" id="send-a-single-transaction"></a>

The metagraph client has all the same methods as `dag4.account` except `transferDag` becomes `transfer` and `transferDagBatch` becomes `transferBatch`.

```typescript
// connect as shown above
const toAddress = 'DAGabc123...';
const amount = 25.551;
const fee = 0;

await metagraphClient.transfer(toAddress, amount, fee);
```

#### Generate bulk transactions offline and send[​](https://docs.constellationnetwork.io/hypergraph/metagraph-tokens#generate-bulk-transactions-offline-and-send) <a href="#generate-bulk-transactions-offline-and-send" id="generate-bulk-transactions-offline-and-send"></a>

```typescript
// Get last ref online, or else fetch from an offline data store
let lastRef = await metagraphClient.getAddressLastAcceptedTransactionRef('DAGWalletSendingAddress');

// Generate txns offline
const txn_data = [
  {address: 'DAGabc123...', amount: 10, fee: 0},
  {address: 'DAGxyz987...', amount: 25.01, fee: 0},
  {address: 'DAGzzz555...', amount: 1.01, fee: 0},
  {address: 'DAGwww988...', amount: 0.00000001, fee: 0},
];

const hashes = await metagraphClient.transferBatch(txn_data, lastRef);

// console.log(hashes)
```

**Transaction Fees**

Note that transaction fees on metagraph networks are paid in the network's metagraph token, not in DAG.


# Dag4.js Example Apps

See dag4.js used in production open source codebases.

Want to see your open source project featured here? [Submit your project for consideration](https://t.me/constellationcommunity).

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th><th data-hidden data-card-cover data-type="files"></th></tr></thead><tbody><tr><td><strong>Stargazer Wallet</strong></td><td>Stargazer Wallet is a cross-chain wallet supporting Constellation Network and Ethereum ecosystems. It is available as a Chrome extension and as a mobile app for iOS and Android.</td><td><a href="https://github.com/StardustCollective/stargazer-wallet-ext">https://github.com/StardustCollective/stargazer-wallet-ext</a></td><td><a href="/files/N0CpC7X2CGFVLVjftBF4">/files/N0CpC7X2CGFVLVjftBF4</a></td></tr><tr><td><strong>Telegram Tip Bot</strong></td><td>The Telegram Tip Bot is a small cloud application integrated with Telegram that allows users to send DAG to each other with TG commands. Because transactions on the Hypergraph are free, all tip transactions are able to be processed on-chain.</td><td><a href="https://github.com/StardustCollective/telegram-bot-tipjar">https://github.com/StardustCollective/telegram-bot-tipjar</a></td><td><a href="/files/Bxl66HpWhDNBR2r4mliz">/files/Bxl66HpWhDNBR2r4mliz</a></td></tr><tr><td><strong>Metagraph Examples</strong><br>Constellation maintains a repo with metagraph implementation examples, including several that demonstrate usage of dag4.js in combination with a metagraph codebase. </td><td></td><td><a href="https://github.com/Constellation-Labs/metagraph-examples">https://github.com/Constellation-Labs/metagraph-examples</a></td><td><a href="/files/qAqvL7a332eXmUYizsBS">/files/qAqvL7a332eXmUYizsBS</a></td></tr></tbody></table>


# Hypergraph APIs

The Hypergraph APIs are the public HTTP APIs hosted on Global L0 and the DAG L1 network nodes. Below you'll find an OpenAPI spec for each of the public network environments. In general, TestNet has the bleeding edge features, IntegrationNet has stable new features, and MainNet has fully released features.

{% hint style="info" %}
See [Architecture](/network-apis) for an overview of how these networks fit into the Constellation Network overall.
{% endhint %}

### DAG L1 API[​](https://docs.constellationnetwork.io/hypergraph/global-apis#dag-l1-api) <a href="#dag-l1-api" id="dag-l1-api"></a>

The DAG L1 API is used primarily for sending DAG transactions which are then processed through the Global L0 and are eventually visible on the Block Explorer API after reaching finality.

You can use one of the load balancer endpoints below or connect directly to a network node by IP address and port. You can use the load balancer /cluster/info endpoint to find an active network node to connect to. Connect to the node using http and the configured port, ex: [http://18.232.193.183:9010](http://18.232.193.183:9010/)

**API Spec**[**​**](https://docs.constellationnetwork.io/hypergraph/global-apis#api-spec)

* [TestNet](http://apidoc-testnet.constellationnetwork.io.s3-website.us-west-1.amazonaws.com/dag/l1/public/)
* [IntegrationNet](http://apidoc-integrationnet.constellationnetwork.io.s3-website-us-west-1.amazonaws.com/dag/l1/public/)
* [MainNet](http://apidoc.constellationnetwork.io.s3-website.us-west-1.amazonaws.com/dag/l1/public/)

**Base urls​:**[**​**](https://docs.constellationnetwork.io/hypergraph/global-apis#base-urls)

* TestNet: [https://l1-lb-testnet.constellationnetwork.io](https://l1-lb-testnet.constellationnetwork.io/)
* IntegrationNet: [https://l1-lb-integrationnet.constellationnetwork.io](https://l1-lb-integrationnet.constellationnetwork.io/)
* MainNet: [https://l1-lb-mainnet.constellationnetwork.io](https://l1-lb-mainnet.constellationnetwork.io/)

### Global L0 API[​](https://docs.constellationnetwork.io/hypergraph/global-apis#global-l0-api) <a href="#global-l0-api" id="global-l0-api"></a>

The Global L0 API can be used to fetch global snapshot information, view DAG supply and address balances, and submit metagraph snapshots.

You can use one of the load balancer endpoints below or connect directly to a network node by IP address and port. You can use the load balancer /cluster/info endpoint to find a network node. Connect using http and the configured port, ex: [http://18.232.193.183:9000](http://18.232.193.183:9000/).

**API Spec**[**​**](https://docs.constellationnetwork.io/hypergraph/global-apis#api-spec-1)

* [TestNet](http://apidoc-testnet.constellationnetwork.io.s3-website.us-west-1.amazonaws.com/dag/l0/public/)
* [IntegrationNet](http://apidoc-integrationnet.constellationnetwork.io.s3-website-us-west-1.amazonaws.com/dag/l0/public/)
* [MainNet](http://apidoc.constellationnetwork.io.s3-website.us-west-1.amazonaws.com/dag/l0/public/)

**Base urls​:**[**​**](https://docs.constellationnetwork.io/hypergraph/global-apis#base-urls-1)

* TestNet: [https://l0-lb-testnet.constellationnetwork.io](https://l0-lb-testnet.constellationnetwork.io/)
* IntegrationNet: [https://l0-lb-integrationnet.constellationnetwork.io](https://l0-lb-integrationnet.constellationnetwork.io/)
* MainNet: [https://l0-lb-mainnet.constellationnetwork.io](https://l0-lb-mainnet.constellationnetwork.io/)


# Metagraph APIs

Metagraph APIs are hosted on any metagraph that adheres to the Metagraph Token Standard or implements a custom data endpoint. The APIs described here are very similar to the [Hypergraph APIs](https://docs.constellationnetwork.io/hypergraph/global-apis) described in the previous section. The metagraph APIs consist of the Currency L0 API, Currency L1 API, and the Data L1 API. These APIs are hosted on individual metagraphs which may have their own rate limits or specific configurations required.

{% hint style="info" %}
See [Architecture](https://docs.constellationnetwork.io/hypergraph/architecture) for an overview of how these networks fit into the Constellation Network overall.
{% endhint %}

### Currency L0 API[​](https://docs.constellationnetwork.io/hypergraph/currency-apis#currency-l0-api) <a href="#currency-l0-api" id="currency-l0-api"></a>

The Currency L0 API can be used to fetch metagraph snapshot chain information, view token supply and address balances, and submit metagraph snapshots.

You can connect directly to a network node by IP address and port, or by an endpoint provided to you by the metagraph network.

**API Spec**[**​**](https://docs.constellationnetwork.io/hypergraph/currency-apis#api-spec)

* [TestNet](http://apidoc-testnet.constellationnetwork.io.s3-website.us-west-1.amazonaws.com/currency/v1/l0/public/)
* [IntegrationNet](http://apidoc-integrationnet.constellationnetwork.io.s3-website-us-west-1.amazonaws.com/currency/v1/l0/public/)
* [MainNet](http://apidoc.constellationnetwork.io.s3-website.us-west-1.amazonaws.com/currency/v1/l0/public/)

### Currency L1 API[​](https://docs.constellationnetwork.io/hypergraph/currency-apis#currency-l1-api) <a href="#currency-l1-api" id="currency-l1-api"></a>

The Currency L1 API is used primarily for sending metagraph token transactions which are then processed through the Global L0, Currency L0, and Global L0.

You can connect directly to a network node by IP address and port, or by an endpoint provided to you by the metagraph network.

**API Spec**[**​**](https://docs.constellationnetwork.io/hypergraph/currency-apis#api-spec-1)

* [TestNet](http://apidoc-testnet.constellationnetwork.io.s3-website.us-west-1.amazonaws.com/currency/v1/l1/public/)
* [IntegrationNet](http://apidoc-integrationnet.constellationnetwork.io.s3-website-us-west-1.amazonaws.com/currency/v1/l1/public/)
* [MainNet](http://apidoc.constellationnetwork.io.s3-website.us-west-1.amazonaws.com/currency/v1/l1/public/)

**Base urls​**[**​**](https://docs.constellationnetwork.io/hypergraph/currency-apis#base-urls)

Base urls or ip addresses will be provided by the metagraph network you wish to connect to.

### Data L1 API[​](https://docs.constellationnetwork.io/hypergraph/currency-apis#data-l1-api) <a href="#data-l1-api" id="data-l1-api"></a>

The Global L0 API can be used to fetch global snapshot information, view DAG supply and address balances, and submit metagraph (state channel) snapshots.

You can connect directly to a network node by IP address and port, or by an endpoint provided to you by the metagraph network.

**API Spec**[**​**](https://docs.constellationnetwork.io/hypergraph/currency-apis#api-spec-2)

* [TestNet](http://apidoc-testnet.constellationnetwork.io.s3-website.us-west-1.amazonaws.com/currency/v1/l1-data/public/)
* [IntegrationNet](http://apidoc-integrationnet.constellationnetwork.io.s3-website-us-west-1.amazonaws.com/currency/v1/l1-data/public/)
* [MainNet](http://apidoc.constellationnetwork.io.s3-website.us-west-1.amazonaws.com/currency/v1/l1-data/public/)

**Base urls​**[**​**](https://docs.constellationnetwork.io/hypergraph/currency-apis#base-urls-1)

Base urls or ip addresses will be provided by the metagraph network you wish to connect to.


# Block Explorer APIs

An off-network API offering indexed and searchable transactions, snapshots, and block information.&#x20;

**API Spec**[**​**](https://docs.constellationnetwork.io/hypergraph/block-explorer-api#api-spec)

* [TestNet](http://apidoc-testnet.constellationnetwork.io.s3-website.us-west-1.amazonaws.com/block-explorer/)
* [IntegrationNet](http://apidoc-integrationnet.constellationnetwork.io.s3-website.us-west-1.amazonaws.com/block-explorer/)
* [MainNet](http://apidoc.constellationnetwork.io.s3-website.us-west-1.amazonaws.com/block-explorer/)

**Base urls:**[**​**](https://docs.constellationnetwork.io/hypergraph/block-explorer-api#base-urls)

* TestNet: [https://be-testnet.constellationnetwork.io](https://be-testnet.constellationnetwork.io/)
* IntegrationNet: [https://be-integrationnet.constellationnetwork.io](https://be-integrationnet.constellationnetwork.io/)
* MainNet: [https://be-mainnet.constellationnetwork.io](https://be-mainnet.constellationnetwork.io/)


# Transaction Signing

This document describes how to manually sign transactions on the Constellation Network. Understanding the transaction signing process is crucial for developers implementing custom signing solutions in various programming languages or integrating with the Constellation Network.

## Overview

Constellation Network supports two distinct methods for transaction signing:

1. **DAG/L0 Token Transactions**: Uses Kryo serialization without compression
2. **Other Transaction Types**: Uses Brotli compression for serialization (TokenLock, AllowSpend, DelegatedStake, etc.)

In the long term, DAG and L0 token transactions will likely be migrated to use the same brotli compression as the newer transaction types but for now, the Kryo serialization method is maintained for backwards compatibility.&#x20;

### Transaction Format

All transactions in the Constellation Network, regardless of type, are submitted to the network using a standard format:

```json
{
  "value": {
    // Transaction body containing all transaction details
  },
  "proofs": [
    {
      "id": "<signer public key>",
      "signature": "<signature of transaction body>"
    }
  ]
}
```

Key components of this format:

* **value**: Contains the transaction body with all relevant transaction details
* **proofs**: An array of signatures that validate the transaction
  * Currently, all transactions require exactly one proof in the array
  * The array structure supports future multi-signature functionality
  * Each proof contains:
    * **id**: The public key of the signer
    * **signature**: The signature of the transaction body, created using the corresponding private key

The different transaction signing methods described in this document ultimately produce transaction data in this standard format, though the specific contents of the `value` field and the method of generating the signature in the `proofs` array will differ based on the transaction type.

## Prerequisites

To sign transactions, you need:

* A private key
* A public key
* Transaction details to be signed
* Understanding of cryptographic operations: SHA-256, SHA-512, and secp256k1 ECDSA signing

## 1. DAG/L0 Token Transaction Signing

DAG or L0 token transactions follow this signing process:

### 1.1 Transaction Structure

For token transactions, the following fields are required:

* `source`: Sender address
* `destination`: Recipient address
* `amount`: Transaction amount (in smallest unit, e.g., 1 DAG = 100,000,000 units)
* `fee`: Transaction fee (in smallest unit)
* `parent`: Last transaction reference (hash and ordinal)
* `salt`: Random value to ensure unique transaction hashes

### 1.2 Transaction Preparation

1. Create a transaction object with the required fields
2. Format the transaction according to the network's expected structure (v2 format)
3. Encode the transaction into a specific format that concatenates fields with their lengths

### 1.3 Kryo Serialization

The encoded transaction is serialized using Kryo serialization, which follows these steps:

1. Create a prefix using the format: `03` (fixed) + UTF-8 encoded length
2. Convert the encoded transaction to UTF-8 bytes
3. Convert the UTF-8 bytes to hexadecimal format
4. Concatenate the prefix with the hexadecimal transaction

Example pseudo-code for Kryo serialization:

```
function kryoSerialize(encodedTransaction):
    prefix = "03" + utf8EncodedLength(encodedTransaction.length + 1)
    hexTransaction = hexEncode(utf8Encode(encodedTransaction))
    return prefix + hexTransaction
```

The UTF-8 encoded length is variable-length encoded with specific bit patterns:

* Bit 8 denotes UTF-8
* Bit 7 denotes if another byte is present

### 1.4 Hash Computation

Compute the SHA-256 hash of the Kryo-serialized transaction bytes:

```
transactionHash = sha256(Buffer.from(serializedTransaction, 'hex'))
```

### 1.5 Signature Generation

Sign the hash using ECDSA with the secp256k1 curve and the private key:

1. Compute SHA-512 hash of the transaction hash
2. Sign the SHA-512 hash with the private key using secp256k1 ECDSA
3. Format the signature according to the expected format (often DER encoded and converted to hexadecimal)

```
sha512Hash = sha512(transactionHash)
signature = secp256k1Sign(sha512Hash, privateKey)
hexSignature = signature.toHex()
```

### 1.6 Verification (Optional)

To verify the signature:

1. Use the public key to verify the signature against the same SHA-512 hash
2. Ensure the signature verification passes

```
isValid = secp256k1Verify(signature, sha512Hash, publicKey)
```

## 2. Other Transaction Types (TokenLock, AllowSpend, DelegatedStake, etc.)

For other transaction types, the signing process uses Brotli compression:

### 2.1 Transaction Normalization

Before serialization, normalize the transaction object:

1. Sort object keys alphabetically
2. Remove null/undefined values
3. Convert the object to a consistent format

```
normalizedBody = normalizeObject(transactionBody)
```

### 2.2 Brotli Serialization

Serialize the normalized transaction using Brotli compression:

1. Convert the normalized JSON to a string
2. Encode the string as UTF-8 bytes
3. Compress the bytes using Brotli compression (typically with compression level 2)

```
normalizedJson = JSON.stringify(normalizedBody)
utf8Bytes = utf8Encode(normalizedJson)
compressedData = brotliCompress(utf8Bytes, compressionLevel=2)
```

### 2.3 Hash Computation

Compute the SHA-256 hash of the Brotli-compressed data:

```
messageHash = sha256(compressedData)
```

### 2.4 Signature Generation

Sign the hash with the private key:

1. Compute SHA-512 hash of the message hash
2. Sign the SHA-512 hash with the private key using secp256k1 ECDSA
3. Format the signature according to the expected format

```
sha512Hash = sha512(messageHash)
signature = secp256k1Sign(sha512Hash, privateKey)
hexSignature = signature.toHex()
```

### 2.5 Result

The final result should be structured as:

```
{
  "value": normalizedBody,
  "proofs": [
    {
      "id": publicKey,
      "signature": hexSignature
    }
  ]
}
```

## Implementation Considerations

#### Key Format

* Private keys should be in hexadecimal format without the "0x" prefix
* Public keys for verification can be in compressed or uncompressed format
* When using uncompressed public keys, they may need the "04" prefix

#### Transaction Amounts

* Transaction amounts and fees should be represented in the smallest unit (datum)
* Example: 1 DAG = 100,000,000 datum (8 decimal places)
* Amounts should be integers after being multiplied by 10^8

#### Hash Functions

* SHA-256 and SHA-512 implementations should follow the standard specifications
* Input to hash functions should be byte arrays, not hexadecimal strings

#### ECDSA Signing

* Use secp256k1 curve for ECDSA signing
* Sign the SHA-512 hash of the message, not the message directly
* DER encoding is commonly used for the signature format


# Delegated Staking

## Delegated Staking Integration Guide

{% hint style="warning" %}
This feature is currently available on IntegrationNet only.&#x20;
{% endhint %}

This guide walks you through integrating with Constellation Network’s Delegated Staking system, including how to create, update, and withdraw delegated stakes for users that want to automate this process through the network APIs.&#x20;

Delegated staking allows users to lock their tokens on the network and delegate them to a node operator, receiving a share of the validator’s rewards in return. The process relies on TokenLocks and is managed via the Global L0 (gL0) and DAG L1 (dagL1) APIs.

Manual staking using Stargazer Wallet is supported through the [DAG Explorer](https://integrationnet.dagexplorer.io) website.

{% hint style="success" %}

### Node Operators

For node operators looking for information on how to participate in Delegated Staking and how to attract delegators to their nodes, see [Node Operator Delegated Staking](/run-a-node/validator-node-guides/delegated-staking/for-node-operators).
{% endhint %}

***

## API Reference Summary

Before getting started, familiarize yourself with the following endpoints. Note that you'll be interacting with API endpoints on both the [DAG L1](/network-apis/api-reference/hypergraph-apis#dag-l1-api) and [Global L0](/network-apis/api-reference/hypergraph-apis#global-l0-api) APIs.&#x20;

| Endpoint                               | API                                                              | Method | Description                                                  |
| -------------------------------------- | ---------------------------------------------------------------- | ------ | ------------------------------------------------------------ |
| `/token-locks`                         | [DAG L1](/network-apis/api-reference/hypergraph-apis#dag-l1-api) | `POST` | Submit a TokenLock.                                          |
| `/token-locks/:address/last-reference` | [DAG L1](/network-apis/api-reference/hypergraph-apis#dag-l1-api) | `GET`  | Get the latest transaction reference for use in a TokenLock. |
| `/delegated-stakes/:address/info`      | [gL0](/network-apis/api-reference/hypergraph-apis#global-l0-api) | `GET`  | Fetch current delegated stake positions for an address.      |
| `/delegated-stakes`                    | [gL0](/network-apis/api-reference/hypergraph-apis#global-l0-api) | `POST` | Create or update a delegated stake position.                 |
| `/delegated-stakes`                    | [gL0](/network-apis/api-reference/hypergraph-apis#global-l0-api) | `PUT`  | Withdraw a delegated stake position.                         |
| `/node-params`                         | [gL0](/network-apis/api-reference/hypergraph-apis#global-l0-api) | `GET`  | Fetch node metadata including node IDs and reward settings.  |

***

## Transaction Signing

All `POST` and `PUT` requests below follow the brotli compressed signing scheme described in [Transaction Signing](/network-apis/integration-guides/transaction-signing#overview). If using a library like [dag4.js](https://github.com/StardustCollective/dag4.js) to generate and send requests to the network, serialization and signing will be handled for you automatically. If sending requests directly to the REST APIs without using a library, you will need to generate the signatures manually.&#x20;

## Creating a Delegated Stake

To create a delegated stake, follow these steps:

#### 1. Discover Available Nodes

Use the following API call to list the nodes currently accepting delegated stakes:

{% tabs %}
{% tab title="Bash" %}
{% code overflow="wrap" %}

```bash
curl -X GET "{GL0_API}/node-params" -H "Content-Type: application/json"
```

{% endcode %}
{% endtab %}
{% endtabs %}

Each node record includes:

* `nodeId`: used to delegate
* `name`: name provided by the operator&#x20;
* `description`: description provided by the operator
* `rewardFraction`: the validator's share of rewards

You’ll use the `nodeId` from this list when creating your stake.

***

#### 2. Fetch TokenLock Parent Reference

Before creating a TokenLock, you need the last reference for your wallet address:

{% tabs %}
{% tab title="Bash" %}

```bash
curl -X GET "{DAGL1_API}/token-locks/{address}/last-reference" -H "Content-Type: application/json"
```

{% endtab %}

{% tab title="Dag4.js" %}
This step can be skipped w/dag4.js. The parent reference will be fetched automatically when creating the TokenLock.&#x20;
{% endtab %}
{% endtabs %}

This value will be used as the `parentReference` in your new TokenLock transaction.

***

#### 3. Create the TokenLock

Submit a TokenLock to lock your tokens:

{% tabs %}
{% tab title="Bash" %}

```bash
curl -X POST "{DAGL1_API}/token-locks" -H "Content-Type: application/json" -d '{
  "value": {
    "source": "DAG4xPWQj3BpAg2YKg3kbdW2AJcMfZz2SUKqYb1t",
    "amount": 100000000,
    "fee": 0,
    "parent": {YOUR_PARENT_REFERENCE},
    "currencyId": null,
    "unlockEpoch": null
  },
  "proofs":[{
    "id": "c7f9a08bdea7ff5f51c8af16e223a1d751bac9c541125d9aef5658e9b7597aee8cba374119ebe83fb9edd8c0b4654af273f2d052e2d7dd5c6160b6d6c284a17c",
    "signature": "3045022017607e6f32295b0ba73b372e31780bd373322b6342c3d234b77bea46adc78dde022100e6ffe2bca011f4850b7c76d549f6768b88d0f4c09745c6567bbbe45983a28bf1"
  }]
}'
```

{% endtab %}

{% tab title="Dag4.js" %}

```typescript
import { dag4 } from '@stardust-collective/dag4'

dag4.account.loginSeedPhrase(YOUR_SEED_PHRASE)

dag4.account.connect({
  networkVersion: '2.0',
  l0Url: {GL0_API},
  l1Url: {DAGL1_API}
})

await dag4.account.postTokenLock({
  source: dag4.account.address,
  amount: 500000000000,
  fee: 0,
  tokenL1Url: {DAGL1_API},
  unlockEpoch: null,
  currencyId: null,
})
```

{% endtab %}
{% endtabs %}

* `source`**:** set to the address of the wallet sending the request
* `amount`: number of tokens to lock (in smallest unit, i.e., datum)
* `fee`: set to zero
* `currencyId`: set to `null`
* `unlockEpoch`: set to `null` — this ensures only the network can unlock the tokens upon withdrawal
* `parent`: from previous step

***

#### 4. Fetch DelegatedStake Parent Reference

Now fetch your DelegatedStake's last reference:

{% tabs %}
{% tab title="Bash" %}

```bash
curl -X GET "{GL0_API}/delegated-stakes/{address}/info" -H "Content-Type: application/json"
```

{% endtab %}

{% tab title="Dag4.js" %}
This step can be skipped w/dag4.js. The parent reference will be fetched automatically when creating the DelegatedStake.&#x20;
{% endtab %}
{% endtabs %}

Use the returned value as `parent` when submitting the new stake.

***

#### 5. Submit Delegated Stake Request

Now that you have your `tokenLockRef` and parent reference, submit the stake:

{% tabs %}
{% tab title="Bash" %}

```bash
curl -X POST "{GL0_API}/delegated-stakes" -H "Content-Type: application/json" -d '{
  "value": {
    "source": "{SENDER_ADDRESS}",
    "nodeId": "{NODE_ID}",
    "amount": 100000000,
    "fee": 0,
    "tokenLockRef": {TOKEN_LOCK_REF},
    "parent": {PARENT_REFERENCE}
  },
  "proofs":[{
    "id": "c7f9a08bdea7ff5f51c8af16e223a1d751bac9c541125d9aef5658e9b7597aee8cba374119ebe83fb9edd8c0b4654af273f2d052e2d7dd5c6160b6d6c284a17c",
    "signature": "3045022017607e6f32295b0ba73b372e31780bd373322b6342c3d234b77bea46adc78dde022100e6ffe2bca011f4850b7c76d549f6768b88d0f4c09745c6567bbbe45983a28bf1"
  }]
}'
```

{% endtab %}

{% tab title="Dag4.js" %}

```typescript
import { dag4 } from '@stardust-collective/dag4'

dag4.account.loginSeedPhrase(YOUR_SEED_PHRASE)

dag4.account.connect({
  networkVersion: '2.0',
  l0Url: {GL0_API},
  l1Url: {DAGL1_API}
})

await dag4.account.postDelegatedStake({
  source: dag4.account.address,
  nodeId: "{NODE_ID}",
  amount: 500000000000,
  fee: 0,
  tokenLockRef: "{TOKEN_LOCK_REF}"
})
```

{% endtab %}
{% endtabs %}

Request body includes:

* `nodeId`: from `/node-params`
* `amount`: must exactly match the amount of the TokenLock referenced
* `fee`: should be zero
* `tokenLockRef`: from TokenLock response
* `parent`: from `/delegated-stakes/:address/info`

If successful, a `hash` of the DelegatedStake record will be returned.&#x20;

***

#### 6. Verify Stake Activation

Use:

{% tabs %}
{% tab title="Bash" %}

```bash
curl -X GET "{GL0_API}/delegated-stakes/{address}/info" -H "Content-Type: application/json"
```

{% endtab %}
{% endtabs %}

Check that your stake is listed in the `activeDelegatedStakes` array, and that `rewardsAmount` is increasing.

***

## Updating a Delegated Stake

Delegated stakes can be redirected to a new node **without withdrawal** or penalty.

#### 1. Pick a New Node

Re-run:

{% tabs %}
{% tab title="Bash" %}

```bash
curl -X GET "{GL0_API}/node-params" -H "Content-Type: application/json"
```

{% endtab %}
{% endtabs %}

Choose a new node ID to delegate to.

***

#### 2. Re-submit the DelegatedStake

Use the **same** `tokenLockRef` **and stake amount**, but change the `nodeId`.

{% tabs %}
{% tab title="Bash" %}

```bash
curl -X POST "{GL0_API}/delegated-stakes" -H "Content-Type: application/json" -d '{
  "value": {
    "source": "{SENDER_ADDRESS}",
    "nodeId": "{NEW_NODE_ID}",
    "amount": 100000000,
    "fee": 0,
    "tokenLockRef": {TOKEN_LOCK_REF},
    "parent": {PARENT_REFERENCE}
  },
  "proofs":[{
    "id": "c7f9a08bdea7ff5f51c8af16e223a1d751bac9c541125d9aef5658e9b7597aee8cba374119ebe83fb9edd8c0b4654af273f2d052e2d7dd5c6160b6d6c284a17c",
    "signature": "3045022017607e6f32295b0ba73b372e31780bd373322b6342c3d234b77bea46adc78dde022100e6ffe2bca011f4850b7c76d549f6768b88d0f4c09745c6567bbbe45983a28bf1"
  }]
}'
```

{% endtab %}

{% tab title="Dag4.js" %}

```typescript
import { dag4 } from '@stardust-collective/dag4'

dag4.account.loginSeedPhrase(YOUR_SEED_PHRASE)

dag4.account.connect({
  networkVersion: '2.0',
  l0Url: {GL0_API},
  l1Url: {DAGL1_API}
})

await dag4.account.postDelegatedStake({
  source: dag4.account.address,
  nodeId: "{NEW_NODE_ID}",
  amount: 500000000000,
  fee: 0,
  tokenLockRef: "{TOKEN_LOCK_REF}"
})
```

{% endtab %}
{% endtabs %}

This will update the position to the new node without incurring a withdrawal penalty. All fields other than `nodeId` must remain the same as the original request.

***

#### 3. Confirm the Update

Use:

{% tabs %}
{% tab title="Bash" %}

```bash
curl -X GET "{GL0_API}/delegated-stakes/{address}/info" -H "Content-Type: application/json"
```

{% endtab %}
{% endtabs %}

Ensure the `nodeId` has updated and `rewardAmount` continues to increase.&#x20;

***

## Withdrawing a Delegated Stake

To withdraw a delegated stake (unlock your tokens and receive rewards), follow this process:

#### 1. Submit Withdrawal Request

{% tabs %}
{% tab title="Bash" %}

```bash
curl -X PUT "{GL0_API}/delegated-stakes" -H "Content-Type: application/json" -d '{
  "source": "{SENDER_ADDRESS}",
  "stakeRef": "{DELEGATED_STAKE_REFERENCE}"
}'
```

{% endtab %}

{% tab title="Dag4.js" %}

```typescript
dag4.account.loginSeedPhrase(YOUR_SEED_PHRASE)

dag4.account.connect({
  networkVersion: '2.0',
  l0Url: {GL0_API},
  l1Url: {DAGL1_API}
})

await dag4.account.putWithdrawDelegatedStake({
    source: dag4.account.address,
    stakeRef: "{DELEGATED_STAKE_REFERENCE}"
})
```

{% endtab %}
{% endtabs %}

You’ll need:

* Reference to the original DelegatedStake position

This will **start the 21-day unbonding period**.

***

#### 2. Verify Pending Status

After submitting, verify the stake has moved to `pendingWithdrawals`:

{% tabs %}
{% tab title="Bash" %}

```bash
curl -X GET "{GL0_API}/delegated-stakes/{address}/info" -H "Content-Type: application/json"
```

{% endtab %}
{% endtabs %}

During this time:

* The position no longer accrues rewards
* Tokens remain locked

***

#### 3. Wait and Confirm Completion

After \~21 days (estimated in network `epochProgress`), check your wallet:

* TokenLock should be removed
* Rewards should be distributed in a reward transaction


# Introduction

## Introduction to Stargazer Wallet

Stargazer is a non-custodial multichain wallet with support for Constellation and Ethereum networks. The following documentation will guide you through integrating Stargazer Wallet into a Web3 site or app.

{% embed url="<https://www.youtube.com/watch?index=6&list=PL1iI5n3l2OKB8AaU3-LTnKaJVLU5QAZs3&v=GbEuZDKtGWE>" %}

#### Available Environments[​](https://docs.constellationnetwork.io/stargazer#available-environments) <a href="#available-environments" id="available-environments"></a>

Stargazer is currently available in the following platforms:

* [Stargazer Extension (Chrome / Brave).](https://chrome.google.com/webstore/detail/stargazer-wallet/pgiaagfkgcbnmiiolekcfmljdagdhlcm)
* [Stargazer App (iOS).](https://apps.apple.com/us/app/stargazer-wallet/id1612326452)
* [Stargazer App (Android).](https://play.google.com/store/apps/details?id=com.stargazer)

You can interact with the [Stargazer Extension](https://chrome.google.com/webstore/detail/stargazer-wallet/pgiaagfkgcbnmiiolekcfmljdagdhlcm) via [injected javascript API](https://docs.constellationnetwork.io/stargazer/Guide/providerActivation#detect-stargazer). Mobile interactions are not supported at the moment.

#### Quick Start Demos[​](https://docs.constellationnetwork.io/stargazer#quick-start-demos) <a href="#quick-start-demos" id="quick-start-demos"></a>

A pair of interactive demo sites with implementation code are available to get started quickly with common functionality such as connecting the wallet, interacting with DAG + ETH chains, sending transactions, signing messages, and more.

The demo sites use the two most common integration strategies for Web3 sites: Standalone or Web3 React integration.

<table data-card-size="large" data-view="cards" data-full-width="true"><thead><tr><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th><th data-hidden data-card-cover data-type="files"></th></tr></thead><tbody><tr><td><strong>Standalone</strong></td><td>Standalone integration examples using the global window.stargazer object directly</td><td><a href="https://demos.stargazerwallet.io/">https://demos.stargazerwallet.io/</a></td><td><a href="/files/BKbNJyGqFvLqeyAZOuBq">/files/BKbNJyGqFvLqeyAZOuBq</a></td></tr><tr><td><strong>Web3 react</strong></td><td>Integration examples using Web3React and the Stargazer Wallet Connector package.</td><td><a href="https://demos-react.stargazerwallet.io/">https://demos-react.stargazerwallet.io/</a></td><td><a href="/files/BKbNJyGqFvLqeyAZOuBq">/files/BKbNJyGqFvLqeyAZOuBq</a></td></tr></tbody></table>


# Provider Activation

## Provider Activation

A chain provider allows you to interact with any available network. In this guide, you will learn how to obtain a chain provider and activate it.

**Tip**

With the Stargazer Extension installed you can test the following examples in the browser console ([devtools](https://developer.chrome.com/docs/devtools/console/)).

### Detect Stargazer[​](https://docs.constellationnetwork.io/stargazer/Guide/providerActivation#detect-stargazer) <a href="#detect-stargazer" id="detect-stargazer"></a>

The Stargazer browser extension injects a [`WalletProvider`](/stargazer-wallet/api-reference/wallet-provider-api) instance under `window.stargazer` each time a page loads. You can check the existence of this property using the following snippet.

TypeScript

```typescript
if (window.stargazer) {
  console.log("Stargazer version " + window.stargazer.version + " detected");
} else {
  console.log("Stargazer not detected");
}
```

Copy

### Obtain a ChainProvider[​](https://docs.constellationnetwork.io/stargazer/Guide/providerActivation#obtain-a-chainprovider) <a href="#obtain-a-chainprovider" id="obtain-a-chainprovider"></a>

Once you've verified your app has access to a [`WalletProvider`](/stargazer-wallet/api-reference/wallet-provider-api) instance you can obtain a [`ChainProvider`](/stargazer-wallet/chain-provider-api) to interact with a network of your choice (Constellation or Ethereum).

TypeScript

```typescript
const provider = window.stargazer.getProvider("constellation");
```

Copy

*Read more about the* [*WalletProvider API*](/stargazer-wallet/api-reference/wallet-provider-api) *and the* [*ChainProvider API*](/stargazer-wallet/chain-provider-api)*.*

### Activate your provider[​](https://docs.constellationnetwork.io/stargazer/Guide/providerActivation#activate-your-provider) <a href="#activate-your-provider" id="activate-your-provider"></a>

Activating the provider is required before it can be used to interact with the user's wallet. When activation is triggered, a popup is triggered for the user to allow your site access to their wallet. The user may choose a subset of their wallets to share if they have multiple. Activation can be achieved with one of the following methods.

#### Using `dag_requestAccounts` or `eth_requestAccounts` RPC methods[​](https://docs.constellationnetwork.io/stargazer/Guide/providerActivation#using-dag_requestaccounts-or-eth_requestaccounts-rpc-methods) <a href="#using-dag_requestaccounts-or-eth_requestaccounts-rpc-methods" id="using-dag_requestaccounts-or-eth_requestaccounts-rpc-methods"></a>

Calling `dag_requestAccounts` or `eth_requestAccounts` RPC methods, depending on the provider being used, will send an activation request for the user to accept. If the user accepts the request, the RPC method will return available accounts for the provider; if not, it will throw an error.

TypeScript

```typescript
await dagProvider.request({ method: "dag_requestAccounts", params: [] });
// ["DAG88C9WDSKH451sisyEP3hAkgCKn5DN72fuwjfX"] provider was activated

await ethProvider.request({ method: "eth_requestAccounts", params: [] });
// ["0xAab2C30c02016585EB36b7a0d5608Db787c1e44E"] provider was activated
```

Copy

*Read more about the different RPC methods available both for* [*Constellation*](https://docs.constellationnetwork.io/stargazer/APIReference/constellationRPCAPI/) *and* [*Ethereum*](https://docs.constellationnetwork.io/stargazer/APIReference/ethereumRPCAPI/)*.*

#### Activate method (deprecated)[​](https://docs.constellationnetwork.io/stargazer/Guide/providerActivation#activate-method-deprecated) <a href="#activate-method-deprecated" id="activate-method-deprecated"></a>

**Warning**

This method of activation has been deprecated in favor of the [EIP-1102](https://eips.ethereum.org/EIPS/eip-1102) specification, in both Constellation and Ethereum providers.

You can send an activation request to the user using the provider's [`activate()`](https://docs.constellationnetwork.io/stargazer/APIReference/chainProviderAPI/activate) method. Once the user accepts the request you'll be able to use the provider's RPC interface and methods for the selected chain.

TypeScript

```typescript
const activated = await provider.activate("A Cool App Name");
```

Copy

*Read more about the different RPC methods available both for* [*Constellation*](https://docs.constellationnetwork.io/stargazer/APIReference/constellationRPCAPI/) *and* [*Ethereum*](https://docs.constellationnetwork.io/stargazer/APIReference/ethereumRPCAPI/)*.*

### Scope of the activation[​](https://docs.constellationnetwork.io/stargazer/Guide/providerActivation#scope-of-the-activation) <a href="#scope-of-the-activation" id="scope-of-the-activation"></a>

Activations are issued for the page [origin](https://datatracker.ietf.org/doc/html/rfc6454) and cover all chains available (currently Constellation and Ethereum) and on all providers given. If you have been granted activation in the past the user will not be asked to grant it again. If the user is logged out, they will be prompted to log in again.

### ChainProvider identity[​](https://docs.constellationnetwork.io/stargazer/Guide/providerActivation#chainprovider-identity) <a href="#chainprovider-identity" id="chainprovider-identity"></a>

All chain providers are instantiated once per page, and per chain with the following setup:

TypeScript

```typescript
const constellationProviderA = window.stargazer.getProvider("constellation");
const constellationProviderB = window.stargazer.getProvider("constellation");

const ethereumProviderA = window.stargazer.getProvider("ethereum");
const ethereumProviderB = window.stargazer.getProvider("ethereum");
```

Copy

Two chain providers from the same network and page will share the same underlying reference:

* `Object.is(constellationProviderA, constellationProviderB)` will be true.
* `Object.is(ethereumProviderA, ethereumProviderB)` will be true.
* `Object.is(constellationProviderA, ethereumProviderB)` will be false.
* `Object.is(constellationProviderB, ethereumProviderA)` will be false.


# Sending RPC Requests

Communication with the wallet is sent via RPC requests. This guide will show you how to send an RPC request and how to interpret responses.

**Obtain a chain provider**

With the steps mentioned in [*Provider Activation*](/stargazer-wallet/guide/provider-activation), get a chain provider for the networks you want to interact with. In the following examples we will use both ethereum and constellation providers.

```typescript
const dagProvider = window.stargazer.getProvider("constellation");
const ethProvider = window.stargazer.getProvider("ethereum");
```

### List active account[​](https://docs.constellationnetwork.io/stargazer/Guide/sendingRPCRequests#list-active-account) <a href="#list-active-account" id="list-active-account"></a>

For listing the active accounts in the wallet you can send the following calls to [`dag_accounts`](/stargazer-wallet/constellation-rpc-api/dag_accounts) RPC method and [`eth_accounts`](/stargazer-wallet/ethereum-rpc-api/eth_accounts) RPC method.

{% hint style="info" %}
**Important**

The account returned will always be the active account in Stargazer. Both for Constellation and Ethereum providers.
{% endhint %}

```typescript
const dagAccounts = await dagProvider.request({ method: "dag_accounts" });
console.log(dagAccounts);
// ["DAG88C9WDSKH451sisyEP3hAkgCKn5DN72fuwjfX"]

const ethAccounts = await ethProvider.request({ method: "eth_accounts" });
console.log(eth_accounts);
// ["0x567d0382442c5178105fC03bd52b8Db6Afb4fE40"]
```

*Read more about* [*`dag_accounts` RPC method*](/stargazer-wallet/constellation-rpc-api/dag_accounts) *and* [*`eth_accounts` RPC method*](/stargazer-wallet/ethereum-rpc-api/eth_accounts)*.*

### Send an ETH contract call[​](https://docs.constellationnetwork.io/stargazer/Guide/sendingRPCRequests#send-an-eth-contract-call) <a href="#send-an-eth-contract-call" id="send-an-eth-contract-call"></a>

For interaction with ethereum smart contracts you can use the [`eth_call`](/stargazer-wallet/ethereum-rpc-api/eth_call) RPC method and the [`eth_sendTransaction`](/stargazer-wallet/ethereum-rpc-api/eth_sendtransaction) RPC method, respectively for read and write operations. In the following example we will be using the [ethers](https://www.npmjs.com/package/ethers) package, and a [demo contract](https://sepolia.etherscan.io/address/0x74299a718b2c44483a27325d7725f0b2646de3b1#code) from the [Stargazer Demos](https://github.com/StardustCollective/stargazer-wallet-demos). The [ethers](https://www.npmjs.com/package/ethers) package will help us encode method parameters based on the contract's ABI. It is encouraged to use external libraries to encode contract call parameters.

{% hint style="info" %}
**Important**

Interaction with smart contracts is done through an ABI (Application Binary Interface), you can read more about it in the [Contract ABI Specification](https://docs.soliditylang.org/en/v0.6.0/abi-spec.html) article from the [solidity docs](https://docs.soliditylang.org/en/v0.6.0/index.html).

You can think about an ABI as any other programming interface, where you have defined method signatures and interaction abstractions without the actual implementation.
{% endhint %}

#### Send an ETH read call[​](https://docs.constellationnetwork.io/stargazer/Guide/sendingRPCRequests#send-an-eth-read-call) <a href="#send-an-eth-read-call" id="send-an-eth-read-call"></a>

In the next example we will use the `greet` method from the [StargazerGreeter](https://sepolia.etherscan.io/address/0x74299a718b2c44483a27325d7725f0b2646de3b1#code) contract. It reads a greet string saved in the network state. For interacting with the contract we will create an ethers [`Contract`](https://docs.ethers.io/v5/api/contract/contract/#Contract--creating) instance, and therefore an ethers [`Web3Provider`](https://docs.ethers.io/v5/api/providers/other/#Web3Provider). In the background the [ethers](https://www.npmjs.com/package/ethers) package will call [`eth_call`](/stargazer-wallet/ethereum-rpc-api/eth_call) for us.

```typescript
import * as ethers from "ethers";

const ethersProvider = new ethers.providers.Web3Provider(ethProvider);

const StargazerGreeterAddress = "0x74299a718b2c44483a27325d7725f0b2646de3b1";
const StargazerGreeterABI = [...[]]; // You can get StargazerGreeter's ABI from https://sepolia.etherscan.io/address/0x74299a718b2c44483a27325d7725f0b2646de3b1#code;

const contract = new ethers.Contract(
  StargazerGreeterAddress,
  StargazerGreeterABI,
  ethersProvider
);

await contract.greet();
// "Bon Matin!"
```

#### Send an ETH contract write call[​](https://docs.constellationnetwork.io/stargazer/Guide/sendingRPCRequests#send-an-eth-contract-write-call) <a href="#send-an-eth-contract-write-call" id="send-an-eth-contract-write-call"></a>

In the next example we will use the `setGreeting` method from the [StargazerGreeter](https://sepolia.etherscan.io/address/0x74299a718b2c44483a27325d7725f0b2646de3b1#code) contract. It sets a greet string in the network state. For interacting with the contract we will create an ethers [`Contract`](https://docs.ethers.io/v5/api/contract/contract/#Contract--creating) instance, and therefore an ethers [`Web3Provider`](https://docs.ethers.io/v5/api/providers/other/#Web3Provider). In the background the [ethers](https://www.npmjs.com/package/ethers) package will call [`eth_sendTransaction`](/stargazer-wallet/ethereum-rpc-api/eth_sendtransaction) for us.

{% hint style="info" %}
**Important**

Write calls need to be confirmed by the user. Read more [here](/stargazer-wallet/guide/sending-rpc-requests#send-an-eth-contract-call).
{% endhint %}

```typescript
import * as ethers from "ethers";

const ethersProvider = new ethers.providers.Web3Provider(ethProvider);

const signer = ethersProvider.getSigner();

const StargazerGreeterAddress = "0x74299a718b2c44483a27325d7725f0b2646de3b1";
const StargazerGreeterABI = [...[]]; // You can get StargazerGreeter's ABI from https://sepolia.etherscan.io/address/0x74299a718b2c44483a27325d7725f0b2646de3b1#code;

const contract = new ethers.Contract(
  StargazerGreeterAddress,
  StargazerGreeterABI,
  signer
);

const greetingId = 1; // Bon Matin!

// We send a transaction to the network
const trxResponse = await contract.setGreeting(greetingId);

// We wait for confirmation
const trxReceipt = await library.waitForTransaction(trxResponse.hash);

console.log(trxReceipt.blockNumber);
// 12415408
```

### Send ETH Transactions[​](https://docs.constellationnetwork.io/stargazer/Guide/sendingRPCRequests#send-eth-transactions) <a href="#send-eth-transactions" id="send-eth-transactions"></a>

As the ethereum chain reveals the [`eth_sendTransaction`](/stargazer-wallet/ethereum-rpc-api/eth_sendtransaction) RPC method you can send any kind of transaction you need (Token Transfer, Contract Interaction, ETH Transfers, etc.).

#### Transfer ERC20 Tokens[​](https://docs.constellationnetwork.io/stargazer/Guide/sendingRPCRequests#transfer-erc20-tokens) <a href="#transfer-erc20-tokens" id="transfer-erc20-tokens"></a>

You can send ERC20 tokens using the `transfer` method from any ERC20 contract. For interacting with the contract we will create an ethers [`Contract`](https://docs.ethers.io/v5/api/contract/contract/#Contract--creating) instance, and therefore an ethers [`Web3Provider`](https://docs.ethers.io/v5/api/providers/other/#Web3Provider). In the background the [ethers](https://www.npmjs.com/package/ethers) package will call [`eth_sendTransaction`](/stargazer-wallet/ethereum-rpc-api/eth_sendtransaction) for us.

```typescript
import * as ethers from "ethers";

const ethersProvider = new ethers.providers.Web3Provider(ethProvider);

const signer = ethersProvider.getSigner();

const StargazerSampleTokenAddress =
  "0xfe9885baff18074846aaa2d5541581adf068731d";
const StargazerSampleTokenABI = [...[]]; // You can get StargazerSampleToken's ABI from https://sepolia.etherscan.io/address/0xfe9885baff18074846aaa2d5541581adf068731d#code;

const contract = new ethers.Contract(
  StargazerSampleTokenAddress,
  StargazerSampleTokenABI,
  signer
);

const receiverAddress = "0x....";
const receiveValue = ethers.utils.parseUnits("10", 18).toHexString(); // 10 SST

// We send a transaction to the network
const trxResponse = await contract.transfer(receiverAddress, receiveValue);

// We wait for confirmation
const trxReceipt = await library.waitForTransaction(trxResponse.hash);

console.log(trxReceipt.blockNumber);
// 12415408
```

#### Approve ERC20 token Spend[​](https://docs.constellationnetwork.io/stargazer/Guide/sendingRPCRequests#approve-erc20-token-spend) <a href="#approve-erc20-token-spend" id="approve-erc20-token-spend"></a>

You can approve spend of ERC20 tokens to external contracts using the `approve` method from any ERC20 contract. For interacting with the contract we will create an ethers [`Contract`](https://docs.ethers.io/v5/api/contract/contract/#Contract--creating) instance, and therefore an ethers [`Web3Provider`](https://docs.ethers.io/v5/api/providers/other/#Web3Provider). In the background the [ethers](https://www.npmjs.com/package/ethers) package will call [`eth_sendTransaction`](https://docs.constellationnetwork.io/stargazer/APIReference/ethereumRPCAPI/eth_sendTransaction) for us.

TypeScript

```typescript
import * as ethers from "ethers";

const ethersProvider = new ethers.providers.Web3Provider(ethProvider);

const signer = ethersProvider.getSigner();

const StargazerSampleTokenAddress =
  "0xfe9885baff18074846aaa2d5541581adf068731d";
const StargazerSampleTokenABI = [...[]]; // You can get StargazerSampleToken's ABI from https://sepolia.etherscan.io/address/0xfe9885baff18074846aaa2d5541581adf068731d#code;

const contract = new ethers.Contract(
  StargazerSampleTokenAddress,
  StargazerSampleTokenABI,
  signer
);

const spenderAddress = "0x....";
const spendValue = ethers.utils.parseUnits("10", 18).toHexString(); // 10 SST

// We send a transaction to the network
const trxResponse = await contract.approve(spenderAddress, spendValue);

// We wait for confirmation
const trxReceipt = await library.waitForTransaction(trxResponse.hash);

console.log(trxReceipt.blockNumber);
// 12415408
```

#### Send ETH[​](https://docs.constellationnetwork.io/stargazer/Guide/sendingRPCRequests#send-eth) <a href="#send-eth" id="send-eth"></a>

You can send ETH (The ethereum's native currency) sending a simple transaction to the network. For interacting with the network we will create an ethers [`Web3Provider`](https://docs.ethers.io/v5/api/providers/other/#Web3Provider) and an ethers [`Signer`](https://docs.ethers.io/v5/api/signer/#Signer). In the background the [ethers](https://www.npmjs.com/package/ethers) package will call [`eth_sendTransaction`](/stargazer-wallet/ethereum-rpc-api/eth_sendtransaction) for us.

TypeScript

```typescript
import * as ethers from "ethers";

const ethersProvider = new ethers.providers.Web3Provider(ethProvider);

const oneGwei = ethers.BigNumber.from(1 * 1e9).toHexString();

const signer = ethersProvider.getSigner();

// We send a transaction to the network
const trxResponse = await signer.sendTransaction({
  to: "0x....",
  value: oneGwei,
});

// We wait for confirmation
const trxReceipt = await library.waitForTransaction(trxResponse.hash);

console.log(trxReceipt.blockNumber);
// 12415408
```


# Signing Data

Signing arbitrary data enables you to verify the user's possession of an account. This guide will walk you through the signing process and verification.

**Obtain a chain provider**

As covered in [Provider Activation](/stargazer-wallet/guide/provider-activation), obtain a chain provider for the networks you want to interact with. In the following examples, we will use both Ethereum and Constellation providers.

```typescript
const dagProvider = window.stargazer.getProvider("constellation");
const ethProvider = window.stargazer.getProvider("ethereum");
```

### Constellation Message Signing[​](https://docs.constellationnetwork.io/stargazer/Guide/signingData#constellation-message-signing) <a href="#constellation-message-signing" id="constellation-message-signing"></a>

#### Build a signature request[​](https://docs.constellationnetwork.io/stargazer/Guide/signingData#build-a-signature-request) <a href="#build-a-signature-request" id="build-a-signature-request"></a>

Constellation signatures for messages are done through a [signature request object](/stargazer-wallet/constellation-rpc-api/dag_signmessage). The signature request object is sent for the user to accept. Uppon approval, a signature of the whole object is returned.

```typescript
// Build the signature request
const signatureRequest: SignatureRequest = {
  content: "Sign this message to confirm your address",
  metadata: {
    user: "3feb69d6-d3f0-4812-9c93-384bee08afe8",
  },
};
```

#### Encode the signature request[​](https://docs.constellationnetwork.io/stargazer/Guide/signingData#encode-the-signature-request) <a href="#encode-the-signature-request" id="encode-the-signature-request"></a>

Requests need to be a `Base64 < JSON` encoded string to sign. The wallet will then generate the signature from the same characters that compose this encoded request.

```typescript
// Encode the signature request - Base64 < JSON < Request
const signatureRequestEnconded = window.btoa(JSON.stringify(signatureRequest));
```

#### Send the signature request[​](https://docs.constellationnetwork.io/stargazer/Guide/signingData#send-the-signature-request) <a href="#send-the-signature-request" id="send-the-signature-request"></a>

Once built and encoded, you can send the encoded signature request using the [`dag_signMessage`](/stargazer-wallet/constellation-rpc-api/dag_signmessage) RPC method.

**Important**

When the signature request is sent, the wallet will verify compliance with the schema of the [signature request object](/stargazer-wallet/constellation-rpc-api/dag_signmessage). If it does not comply, the wallet will throw an error.

```typescript
// Send the request and wait for the signature
await dagProvider.request({
  method: "dag_signMessage",
  params: [
    "DAG88C9WDSKH451sisyEP3hAkgCKn5DN72fuwjfX",
    signatureRequestEnconded,
  ],
});
// "3045022100b35798008516373fcc6eef75fe8e322ce8fe0dccc4802b052f3ddc7c6b5dc2900220154cac1e4f3e7d9a64f4ed9d2a518221b273fe782f037a5842725054f1c62280"
```

The returned signature corresponds to the SHA512 hash of the encoded signature request and the private key of the user. `ECDSA.sign(privateKey, sha512(signatureRequestEnconded))`.

*Read more about* [*Constellation signature verification*](/stargazer-wallet/guide/signing-data)

#### Get the account public key[​](https://docs.constellationnetwork.io/stargazer/Guide/signingData#get-the-account-public-key) <a href="#get-the-account-public-key" id="get-the-account-public-key"></a>

After you generate a signature from your encoded request, you need to retrieve the public key from the signer's account for future verification. This is due to the fact that Constellation signatures are not recoverable (i.e. do not contain the `v` parameter like in Ethereum).

```typescript
// Send the request and wait for the signature
await dagProvider.request({
  method: "dag_getPublicKey",
  params: ["DAG88C9WDSKH451sisyEP3hAkgCKn5DN72fuwjfX"],
});
// "0482c4566a9c4cbb6f23b9a31c96876501c71f5c04b35f416e0b2243113cce8fb386a2db0b3881d1c908d33465748b948649165a6705904120238999eed6eed1f4"
```

### Ethereum Message Signing[​](https://docs.constellationnetwork.io/stargazer/Guide/signingData#ethereum-message-signing) <a href="#ethereum-message-signing" id="ethereum-message-signing"></a>

The Stargazer Ethereum RPC API implements both [EIP-191](https://eips.ethereum.org/EIPS/eip-191) ([`personal_sign`](/stargazer-wallet/ethereum-rpc-api/personal_sign)) and [EIP-712](https://eips.ethereum.org/EIPS/eip-712) ([`eth_signTypedData`](/stargazer-wallet/ethereum-rpc-api/eth_signtypeddata)) as arbitrary message signing methods.

#### personal\_sign method[​](https://docs.constellationnetwork.io/stargazer/Guide/signingData#personal_sign-method) <a href="#personal_sign-method" id="personal_sign-method"></a>

The RPC API provided reveals the [`personal_sign`](/stargazer-wallet/ethereum-rpc-api/personal_sign) RPC method for message signing. In this case, the message signed is an arbitrary hex string prefixed by the `"\x19Ethereum Signed Message:\n"` string and the length of the message in bytes from [EIP-191](https://eips.ethereum.org/EIPS/eip-191#specification).

```typescript
// Send the request and wait for the signature
await dagProvider.request({
  method: "personal_sign",
  params: [
    "0x5369676e2074686973206d65737361676520746f20636f6e6669726d20796f7572206164647265737320616e64207573657249642033666562363964362d643366302d343831322d396339332d333834626565303861666538",
    "0x9b2055d370f73ec7d8a03e965129118dc8f5bf83",
  ],
});
// "0xa3f20717a250c2b0b729b7e5becbff67fdaef7e0699da4de7ca5895b02a170a12d887fd3b17bfdce3481f10bea41f45ba9f709d39ce8325427b57afcfc994cee1b"

// Can also be a valid UTF-8 string
await dagProvider.request({
  method: "personal_sign",
  params: [
    "Sign this message to confirm your address and userId 3feb69d6-d3f0-4812-9c93-384bee08afe8",
    "0x9b2055d370f73ec7d8a03e965129118dc8f5bf83",
  ],
});
// "0xa3f20717a250c2b0b729b7e5becbff67fdaef7e0699da4de7ca5895b02a170a12d887fd3b17bfdce3481f10bea41f45ba9f709d39ce8325427b57afcfc994cee1b"
```

The returned signature corresponds to the keccak256 hash of the prefix + message string and the private key of the user. `ECDSA.sign(privateKey, keccak256("\x19Ethereum Signed Message:\n" + len(message) + message))`.

*Read more about* [*Ethereum signature verification*](/stargazer-wallet/guide/signing-data#ethereum-message-signing)

#### eth\_signTypedData method[​](https://docs.constellationnetwork.io/stargazer/Guide/signingData#eth_signtypeddata-method) <a href="#eth_signtypeddata-method" id="eth_signtypeddata-method"></a>

The RPC API provided reveals the [`eth_signTypedData`](/stargazer-wallet/ethereum-rpc-api/eth_signtypeddata) RPC method for typed message signing. In this case, the message signed is the hash of the typed data according to [EIP-712](https://eips.ethereum.org/EIPS/eip-712#specification) prefixed by the `"\x19\x01"` string according to [EIP-191](https://eips.ethereum.org/EIPS/eip-191#specification).

```typescript
await provider.request({
  method: "eth_signTypedData",
  params: [
    "0x567d0382442c5178105fC03bd52b8Db6Afb4fE40",
    {
      types: {
        DeviceControl: [
          {
            name: "principal",
            type: "AuthorizedEntity",
          },
          {
            name: "emergency",
            type: "AuthorizedEntity",
          },
        ],
        AuthorizedEntity: [
          {
            name: "address",
            type: "address",
          },
          {
            name: "validUntil",
            type: "uint256",
          },
        ],
        EIP712Domain: [
          {
            name: "name",
            type: "string",
          },
          {
            name: "version",
            type: "string",
          },
          {
            name: "chainId",
            type: "uint256",
          },
          {
            name: "verifyingContract",
            type: "address",
          },
        ],
      },
      domain: {
        name: "Stargazer Demo",
        version: "1.0.0",
        chainId: "3",
        verifyingContract: "0xeb14c9bb6c2dec2ecb9b278c9fa1ec763b04d545",
      },
      primaryType: "DeviceControl",
      message: {
        principal: {
          address: "0xeb14c9bb6c2dec2ecb9b278c9fa1ec763b04d545",
          validUntil: "1657823568",
        },
        emergency: {
          address: "0xcac3da343670abb46bc6e8e6d375b66217519093",
          validUntil: "1752517998",
        },
      },
    },
  ],
});
// "0xa3f20717a250c2b0b729b7e5becbff67fdaef7e0699da4de7ca5895b02a170a12d887fd3b17bfdce3481f10bea41f45ba9f709d39ce8325427b57afcfc994cee1b"
```

The returned signature corresponds to the keccak256 hash of the domainSeparator + hashStruct(message) and the private key of the user. `ECDSA.sign(privateKey, keccak256("\x19\x01" + domainSeparator + hashStruct(message))`.

*Read more about* [*Ethereum signature verification*](https://docs.constellationnetwork.io/stargazer/Guide/signingData#ethereum-signature-verification)

### Constellation Signature Verification[​](https://docs.constellationnetwork.io/stargazer/Guide/signingData#constellation-signature-verification) <a href="#constellation-signature-verification" id="constellation-signature-verification"></a>

For signature verification, we will be using the [@stardust-collective/dag4](https://www.npmjs.com/package/@stardust-collective/dag4) package. The following snippet illustrates how you can verify an encoded request signature.

```typescript
import { dag4 } from "@stardust-collective/dag4";

const publicKey = "account-public-key";
const signatureRequestEnconded = "the-base64-encoded-signature-request";
const signatureHex = "some-hex-encoded-signature";

const valid: boolean = dag4.keyStore.verify(
  publicKey,
  signatureRequestEnconded,
  signatureHex
);

const publicKeyAddress = dag4.keyStore.getDagAddressFromPublicKey(publicKey);
```

### Ethereum Signature Verification[​](https://docs.constellationnetwork.io/stargazer/Guide/signingData#ethereum-signature-verification) <a href="#ethereum-signature-verification" id="ethereum-signature-verification"></a>

For signature verification, we will be using the [ethers](https://www.npmjs.com/package/ethers) package. The following snippets illustrate how you can verify different message signatures.

eth\_personalSign

```typescript
import * as ethers from "ethers";

const accountWhichSigned = "0x9b2055d370f73ec7d8a03e965129118dc8f5bf83";
const messageSigned = "some-message-the-user-signed";
const signatureHex = "some-hex-encoded-signature";

const messageHash = ethers.utils.hashMessage(messageSigned);
const recoveredAddress = ethers.utils.recoverAddress(messageHash, signatureHex);

if (recoveredAddress !== accountWhichSigned) {
  throw new Error("Signature is not valid");
}
```

eth\_signTypedData

```typescript
import * as ethers from "ethers";

const accountWhichSigned = "0x9b2055d370f73ec7d8a03e965129118dc8f5bf83";
const messageSigned = {
  // The EIP-712 domain signed
  domain: {
    name: "Stargazer Demo",
    version: "1.0.0",
    chainId: 3,
    verifyingContract: "0xabcdefABCDEF1234567890abcdefABCDEF123456",
  },
  // The EIP-712 types signed
  types: {
    DeviceControl: [
      { name: "principal", type: "AuthorizedEntity" },
      { name: "emergency", type: "AuthorizedEntity" },
    ],
    AuthorizedEntity: [
      { name: "address", type: "address" },
      { name: "validUntil", type: "uint256" },
    ],
  },
  // The EIP-712 message signed
  value: {
    principal: {
      address: "0xEb14c9bb6C2DEc2eCb9B278C9fa1EC763B04d545",
      validUntil: 1657823568,
    },
    emergency: {
      address: "0xcAc3DA343670aBB46BC6E8e6d375B66217519093",
      validUntil: 1752517998,
    },
  },
};
const signatureHex = "some-hex-encoded-signature";

const messageHash = ethers.utils._TypedDataEncoder.hash(
  messageSigned.domain,
  messageSigned.types,
  messageSigned.value
);
const recoveredAddress = ethers.utils.recoverAddress(messageHash, signatureHex);

if (recoveredAddress !== accountWhichSigned) {
  throw new Error("Signature is not valid");
}
```


# Supported Connectors

This section provides guidance on integrating different library connectors to facilitate wallet connectivity in your application. We support connectors for [`web3react/v6`](https://github.com/Uniswap/web3-react/tree/v6), [`wagmi`](https://wagmi.sh/), and [`react hooks`](https://react.dev/reference/react/hooks). Each connector has its own set of configurations/features and is designed to simplify the process of connecting to the Stargazer Wallet.

#### Web3React[​](https://docs.constellationnetwork.io/stargazer/Guide/supportedConnectors#web3react) <a href="#web3react" id="web3react"></a>

[`web3react/v6`](https://github.com/Uniswap/web3-react/tree/v6) is a framework that allows you to interact with Ethereum blockchain and smart contracts. It provides a simple and flexible way to connect to different wallets.

**Installation**[**​**](https://docs.constellationnetwork.io/stargazer/Guide/supportedConnectors#installation)

To install the [`web3react/v6`](https://github.com/Uniswap/web3-react/tree/v6) connector, run the following command:

If you're using NPM

```typescript
npm install @stardust-collective/web3-react-stargazer-connector
```

If you're using NPM

```typescript
yarn add @stardust-collective/web3-react-stargazer-connector
```

**Example Usage**[**​**](https://docs.constellationnetwork.io/stargazer/Guide/supportedConnectors#example-usage)

```typescript
import { StargazerWeb3ReactConnector } from "@stardust-collective/web3-react-stargazer-connector";
import { useWeb3React } from "@web3-react/core";

const stargazerConnector = new StargazerWeb3ReactConnector({
  supportedChainIds: [1, 3],
});

function App() {
  const { activate, active } = useWeb3React();

  const connect = async () => {
    try {
      await activate(stargazerConnector);
    } catch (ex) {
      console.error(ex);
    }
  };

  return (
    <div>
      <button onClick={connect}>{active ? "Connected" : "Connect"}</button>
    </div>
  );
}

export default App;
```

#### Wagmi[​](https://docs.constellationnetwork.io/stargazer/Guide/supportedConnectors#wagmi) <a href="#wagmi" id="wagmi"></a>

[`wagmi`](https://wagmi.sh/) is a set of React Hooks for Ethereum, which simplifies the process of connecting to Ethereum networks and smart contracts.

**Installation**[**​**](https://docs.constellationnetwork.io/stargazer/Guide/supportedConnectors#installation-1)

To install the [`wagmi`](https://wagmi.sh/) connector, run the following command:

If you're using NPM

```typescript
npm install @stardust-collective/web3-react-stargazer-connector
```

If you're using NPM

```typescript
yarn add @stardust-collective/web3-react-stargazer-connector
```

**Example Usage**[**​**](https://docs.constellationnetwork.io/stargazer/Guide/supportedConnectors#example-usage-1)

```typescript
import {stargazerWalletWagmiConnector} from '@stardust-collective/web3-react-stargazer-connector';
import { mainnet, polygon } from 'wagmi/chains'
import { createConfig, http, useConnect } from 'wagmi'

const stargazerConnector = stargazerWalletWagmiConnector();

declare module 'wagmi' {
  interface Register {
    config: typeof config
  }
}

const config = createConfig({
  chains: [mainnet, polygon],
  transports: {
    [mainnet.id]: http('[your rpc endpoint url]'),
    [polygon.id]: http('[your rpc endpoint url]'),
  },
  connectors: [
    stargazerWalletWagmiConnector({}),
    ...other wallet connectors
  ],
})

function App() {
  const { connectors, connect } = useConnect()
  const { address } = useAccount();

  const doConnect = () => {
    for(const connector of connectors){
      if(connector.type === stargazerWalletWagmiConnector.type){
        connect(connector);
      }
    }
  }

  return (
    <div>
      <button onClick={doConnect}>Connect Wallet</button>
      {address && <p>Connected as {address}</p>}
    </div>
  );
}

export default App;
```

#### React Hooks[​](https://docs.constellationnetwork.io/stargazer/Guide/supportedConnectors#react-hooks) <a href="#react-hooks" id="react-hooks"></a>

The [`react hooks`](https://react.dev/reference/react/hooks) connector is a generic react hook that will enable your app to connect to the stargazer wallet on the constellation network, it will return a EIP-1193 compatible provider (among other properties), that will **only** connect to the constellation network (DAG) via RPC requests, the constellation RPC API reference can be found [here](https://docs.constellationnetwork.io/stargazer/APIReference/constellationRPCAPI/).

**Installation**[**​**](https://docs.constellationnetwork.io/stargazer/Guide/supportedConnectors#installation-2)

To install the [`react hooks`](https://react.dev/reference/react/hooks) connector, run the following command:

If you're using NPM

```typescript
npm install @stardust-collective/web3-react-stargazer-connector
```

If you're using NPM

```typescript
yarn add @stardust-collective/web3-react-stargazer-connector
```

**Example Usage**[**​**](https://docs.constellationnetwork.io/stargazer/Guide/supportedConnectors#example-usage-2)

```typescript
import {useStargazerWallet} from '@stardust-collective/web3-react-stargazer-connector';

function App() {
  const {activate, deactivate, ...state } = useStargazerWallet();

  const doConnect = async () => {
    await activate();
  };

  const doSignMessage = async () => {
    if(!state.active){
      return;
    }

    const signatureRequest = {
      content: 'Sign this message to confirm your participation in this project.',
      metadata: {
        field1: 'an-useful-value',
        field2: 1,
        field3: null /* ,
        field4: {
          // Nested fields are not supported
          prop:1
        } */
      }
    };

    // Encode the signature request - Base64 < JSON < Request
    const signatureRequestEnconded = window.btoa(JSON.stringify(signatureRequest));

    await state.request({
      method: 'dag_signMessage',
      params: [state.account, signatureRequestEnconded]
    });
  }

  return (
    <div>
      <span>Connected To: {state.active && state.account}</span>
      <button onClick={doConnect}>{state.active ? "Connected" : "Connect"}</button>
      <button onClick={doSignMessage}>Sign Message</button>
    </div>
  );
}

export default App;
```

#### New Connectors Support[​](https://docs.constellationnetwork.io/stargazer/Guide/supportedConnectors#new-connectors-support) <a href="#new-connectors-support" id="new-connectors-support"></a>

We are committed to expanding our support for library connectors to meet the evolving needs of our users. If you require a connector that is not currently supported, or have suggestions for new connectors, we are open to exploring these possibilities and integrating them into the wallet.

**Requesting New Connectors**[**​**](https://docs.constellationnetwork.io/stargazer/Guide/supportedConnectors#requesting-new-connectors)

To request the addition of new library connectors or suggest improvements, please reach out to us through the following channels:

* **GitHub Issues**: [StardustCollective/stargazer-wallet-connector](https://github.com/StardustCollective/stargazer-wallet-connector/issues)
* **Discord Channel**: [Constellation Discord](https://discord.gg/NKXD5ZJ5cq)


# Using External Libraries

Sending raw RPC requests can be error-prone and sometimes overwhelming. This guide will list some common external libraries for the Ethereum ecosystem that are compatible with the Stargazer ChainProvider.

#### Ethers.js[​](https://docs.constellationnetwork.io/stargazer/Guide/usingExternalLibraries#ethersjs) <a href="#ethersjs" id="ethersjs"></a>

The [ethers.js](https://docs.ethers.io/v5/) package is a general purpose library for interacting with the ethereum ecosystem. It offers different features from contract interaction to [EIP-712](https://eips.ethereum.org/EIPS/eip-712) message signing for wallets.

In [ethers.js](https://docs.ethers.io/v5/) there are different types of providers, the Stargazer [`ChainProvider`](/stargazer-wallet/chain-provider-api) is compatible with [ethers.js](https://docs.ethers.io/v5/) [`Web3Provider`](https://docs.ethers.io/v5/api/providers/other/#Web3Provider).

```typescript
import * as ethers from "ethers";

const ethProvider = window.stargazer.getProvider("ethereum");

const ethersProvider = new ethers.providers.Web3Provider(ethProvider);
```

Once the [ethers.js](https://docs.ethers.io/v5/) [`Web3Provider`](https://docs.ethers.io/v5/api/providers/other/#Web3Provider) is created you can start interacting with the network using this library.

```typescript
// get balance from address
await ethersProvider.getBalance("0xEb14c9bb6C2DEc2eCb9B278C9fa1EC763B04d545");
// { BigNumber: "36428926959297445147" }
```

```typescript
// get current block number
await ethersProvider.getBlockNumber();
// 14983198
```

```typescript
// get current gas price
await ethersProvider.getGasPrice();
// { BigNumber: "23610503242" }
```

#### Web3.js[​](https://docs.constellationnetwork.io/stargazer/Guide/usingExternalLibraries#web3js) <a href="#web3js" id="web3js"></a>

The [web3.js](https://web3js.readthedocs.io/en/v1.7.4/index.html) library offers a simple but powerful API to interact with the ethereum ecosystem using [EIP-1193](https://eips.ethereum.org/EIPS/eip-1193), HTTP, IPC or WebSocket providers.

The [web3.js](https://web3js.readthedocs.io/en/v1.7.4/index.html) library reveals the [`Web3`](https://web3js.readthedocs.io/en/v1.7.4/web3.html) class which is compatible with the Stargazer [`ChainProvider`](/stargazer-wallet/chain-provider-api).

```typescript
import Web3 from "web3";

const ethProvider = window.stargazer.getProvider("ethereum");

const web3Provider = new Web3(ethProvider);
```

Once the [web3.js](https://web3js.readthedocs.io/en/v1.7.4/index.html) [`Web3`](https://web3js.readthedocs.io/en/v1.7.4/web3.html) object is created you can start interacting with the network using this library.

```typescript
// get balance from address
await web3Provider.eth.getBalance("0xEb14c9bb6C2DEc2eCb9B278C9fa1EC763B04d545");
// "36428926959297445147"
```

```typescript
// get current block number
await web3Provider.eth.getBlockNumber();
// 14983198
```

```typescript
// get current gas price
await web3Provider.eth.getGasPrice();
// "23610503242"
```


# Overview

The following pages will cover various classes and interfaces found while using the Stargazer Wallet API in the browser.


# Wallet provider API

{% content-ref url="/pages/RzGVWCCT0cAxX2Msq2Wr" %}
[Overview](/stargazer-wallet/api-reference/overview)
{% endcontent-ref %}


# Overview

The `WalletProvider` allows access to different chain providers. The `WalletProvider` is injected into every page you visit under `window.stargazer`.




---

[Next Page](/llms-full.txt/1)

