Only this pageAll pages
Powered by GitBook
1 of 18

Network APIs

Concepts

Loading...

Loading...

API Reference

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Integration Guides

Loading...

Loading...

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.

View Dag4.js on Github

You can find the dag4 repo and additional documentation on Github.

Installation​

NPM

npm install @stardust-collective/dag4

or Yarn

yarn add @stardust-collective/dag4

Usage​

Node

const { dag4 } = require('@stardust-collective/dag4');

ES6

import { dag4 } from '@stardust-collective/dag4';

Architecture

Architecture

Transaction Lifecyle

Interested in more in-depth information about the currency transaction lifecycle and data flow within the Hypergraph? See for more info.

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 sections below.

In summary, the functionalities of the different APIs for DAG and metagraph tokens are as follows:

DAG

DAG L1

  • 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

  • Query global snaphots

  • Query DAG supply and address balances

  • Submit metagraph (state channel) snapshots

Metagraph Tokens

Metagraph L1

  • 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

  • Query metagraph snapshots

  • Query metagraph token supply and address balances

Global L0

  • Submit metagraph (state channel) snapshots

Interacting with Wallets

Accounts and Keys

Want more detailed information about accounts are handled on the Hypergraph? Read about .

Interacting with Wallets

A wallet consists of a private key, a public key, and an address. You can create a new private key like this.

Login with a PK

Before accessing methods on dag4.account specific to a wallet, you'll need to log in with a private key or seed phrase.

Login with a seed phrase

If you already have a pneumonic phrase generated by a web wallet or somewhere else you can log in with that as well.

Check DAG address

Get wallet public key

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 .

Installation

NPM

or Yarn

Usage

Node

ES6

npm install @stardust-collective/dag4
yarn add @stardust-collective/dag4
const { dag4 } = require('@stardust-collective/dag4');
import { dag4 } from '@stardust-collective/dag4';
Github
​
​
const pk = dag4.keyStore.generatePrivateKey();
dag4.account.loginPrivateKey(pk);
dag4.account.loginSeedPhrase('disco foxtrot calm appleseed trinity organ putter waldorf ordinary shatter green portion');
const address = dag4.account.address;
dag4.account.publicKey;
​
​
​
​
​
Network APIs
​
​
​
​
​
​
​
Constellation Network architecture overview

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.

Developing a Metagraph Metagraph developers may use IntegrationNet as they're nearing production readiness. See .

Connecting to IntegrationNet​

The following urls can used to access IntegrationNet:

  • Block Explorer API: https://be-integrationnet.constellationnetwork.io

  • Global L0 API: https://l0-lb-integrationnet.constellationnetwork.io

  • DAG L1 API: https://l1-lb-integrationnet.constellationnetwork.io

Faucet​

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>

Sending Transactions

Send a single transaction (online)​

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)​

// 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​

// 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 = [
  {to: 'DAGabc123...', amount: 10, fee: 0},
  {to: 'DAGxyz987...', amount: 25.01, fee: 0},
  {to: 'DAGzzz555...', amount: 1.01, fee: 0},
  {to: '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​

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.

// 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');
  }
}

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

See Architecture for an overview of how these networks fit into the Constellation Network overall.

Currency L0 API​

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​

  • TestNet

  • IntegrationNet

  • MainNet

Currency L1 API​

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​

  • TestNet

  • IntegrationNet

  • MainNet

Base urls​​

Base urls or ip addresses will be provided by the metagraph network you wish to connect to.

Data L1 API​

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​

  • TestNet

  • IntegrationNet

  • MainNet

Base urls​​

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.

API Spec​

  • TestNet

  • IntegrationNet

  • MainNet

Base urls:​

  • TestNet: https://be-testnet.constellationnetwork.io

  • IntegrationNet: https://be-integrationnet.constellationnetwork.io

  • MainNet: https://be-mainnet.constellationnetwork.io

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.

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

Custom network configuration

You can provide custom values for each the three network API endpoints to set up a custom connection.

Default Endpoints

The following endpoints are used by default by Dag4.

IntegrationNet

  • Block Explorer API:

  • L0 API:

  • L1 API:

MainNet

  • Block Explorer API:

  • L0 API:

  • L1 API:

TestNet usage is not recommended as it is expected to be unstable. Use IntegrationNet as the preferred testnet.

TestNet

  • Block Explorer API:

  • L0 API:

  • L1 API:

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

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.

Metagraph connection details

A list of existing metagraphs can be found on the . 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

The metagraph client has all the same methods as dag4.account except transferDag becomes transfer and transferDagBatch becomes transferBatch.

Generate bulk transactions offline and send

Transaction Fees

Note that transaction fees on metagraph networks are paid in the network's metagraph token, not in DAG.

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.

See for an overview of how these networks fit into the Constellation Network overall.

DAG L1 API

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:

API Spec

Base urls​:

  • TestNet:

  • IntegrationNet:

  • MainNet:

Global L0 API

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

API Spec

Base urls​:

  • TestNet:

  • IntegrationNet:

  • MainNet:

dag4.account.connect({
  networkVersion: '2.0',
  testnet: true
});
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'
});
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);
dag4.account.connect({
  networkVersion: '2.0',
  testnet: false
});
dag4.account.connect({
  networkVersion: '2.0',
  testnet: true
});
​
​
​
​
https://be-integrationnet.constellationnetwork.io
https://l0-lb-integrationnet.constellationnetwork.io
https://l1-lb-integrationnet.constellationnetwork.io
​
https://be-mainnet.constellationnetwork.io
https://l0-lb-mainnet.constellationnetwork.io
https://l1-lb-mainnet.constellationnetwork.io
​
https://be-testnet.constellationnetwork.io
https://l0-lb-testnet.constellationnetwork.io
https://l1-lb-testnet.constellationnetwork.io
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
// connect as shown above
const toAddress = 'DAGabc123...';
const amount = 25.551;
const fee = 0;

await metagraphClient.transfer(toAddress, amount, fee);
// Get last ref online, or else fetch from an offline data store
let lastRef = await metagraphClient.getAddressLastAcceptedTransactionRef('DAGWalletSendingAddress');

// Generate txns offline
const txn_data = [
  {to: 'DAGabc123...', amount: 10, fee: 0},
  {to: 'DAGxyz987...', amount: 25.01, fee: 0},
  {to: 'DAGzzz555...', amount: 1.01, fee: 0},
  {to: 'DAGwww988...', amount: 0.00000001, fee: 0},
];

const hashes = await metagraphClient.transferBatch(txn_data, lastRef);

// console.log(hashes)
​
​
DAG Explorer
​
​
Architecture
​
http://18.232.193.183:9010
​
TestNet
IntegrationNet
MainNet
​
https://l1-lb-testnet.constellationnetwork.io
https://l1-lb-integrationnet.constellationnetwork.io
https://l1-lb-mainnet.constellationnetwork.io
​
http://18.232.193.183:9000
​
TestNet
IntegrationNet
MainNet
​
https://l0-lb-testnet.constellationnetwork.io
https://l0-lb-integrationnet.constellationnetwork.io
https://l0-lb-mainnet.constellationnetwork.io

Stargazer Wallet

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.

Telegram Tip Bot

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.

Metagraph Examples Constellation maintains a repo with metagraph implementation examples, including several that demonstrate usage of dag4.js in combination with a metagraph codebase.

Cover
Cover
Cover

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.

Transaction Format

All transactions in the Constellation Network, regardless of type, are submitted to the network using a standard format:

{
  "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

Accounts and Keys
Network Fundamentals Architecture

Delegated Staking

Delegated Staking Integration Guide

This feature is currently available on IntegrationNet only.

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.

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

Node Operators

For node operators looking for information on how to participate in Delegated Staking and how to attract delegators to their nodes, see .


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 and Global L0 APIs.

Endpoint
API
Method
Description

/token-locks

POST

Submit a TokenLock.

/token-locks/:address/last-reference

GET

Get the latest transaction reference for use in a TokenLock.

/delegated-stakes/:address/info

GET

Fetch current delegated stake positions for an address.

/delegated-stakes

POST

Create or update a delegated stake position.

/delegated-stakes

PUT

Withdraw a delegated stake position.

/node-params

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. If using a library like 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.

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:

curl -X GET "{GL0_API}/node-params" -H "Content-Type: application/json"

Each node record includes:

  • nodeId: used to delegate

  • name: name provided by the operator

  • 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:

curl -X GET "{DAGL1_API}/token-locks/{address}/last-reference" -H "Content-Type: application/json"

This step can be skipped w/dag4.js. The parent reference will be fetched automatically when creating the TokenLock.

This value will be used as the parentReference in your new TokenLock transaction.


3. Create the TokenLock

Submit a TokenLock to lock your tokens:

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"
  }]
}'
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,
})
  • 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:

curl -X GET "{GL0_API}/delegated-stakes/{address}/info" -H "Content-Type: application/json"

This step can be skipped w/dag4.js. The parent reference will be fetched automatically when creating the DelegatedStake.

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:

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"
  }]
}'

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}"
})

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.


6. Verify Stake Activation

Use:

curl -X GET "{GL0_API}/delegated-stakes/{address}/info" -H "Content-Type: application/json"

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:

curl -X GET "{GL0_API}/node-params" -H "Content-Type: application/json"

Choose a new node ID to delegate to.


2. Re-submit the DelegatedStake

Use the same tokenLockRef and stake amount, but change the nodeId.

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"
  }]
}'
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}"
})

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:

curl -X GET "{GL0_API}/delegated-stakes/{address}/info" -H "Content-Type: application/json"

Ensure the nodeId has updated and rewardAmount continues to increase.


Withdrawing a Delegated Stake

To withdraw a delegated stake (unlock your tokens and receive rewards), follow this process:

1. Submit Withdrawal Request

curl -X PUT "{GL0_API}/delegated-stakes" -H "Content-Type: application/json" -d '{
  "source": "{SENDER_ADDRESS}",
  "stakeRef": "{DELEGATED_STAKE_REFERENCE}"
}'
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}"
})

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:

curl -X GET "{GL0_API}/delegated-stakes/{address}/info" -H "Content-Type: application/json"

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

DAG L1
DAG L1
gL0
gL0
gL0
gL0
Setup a metagraph

Message Signing

Sign an arbitrary message​

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.

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');
}
Node Operator Delegated Staking