SDKs

SDKs

UltraDAG provides 4 official SDKs for interacting with the network. All SDKs support local Ed25519 key generation, Blake3 address derivation, client-side transaction signing, and all RPC endpoints.


Overview

SDKLanguageInstallTests
PythonPython 3.8+pip install ultradag41
JavaScriptNode.js / Browsernpm install ultradag55
RustRust 1.70+cargo add ultradag-sdk14
GoGo 1.21+go get github.com/ultradag/sdk-go/ultradag36

SDK Features (All Languages)

All 4 SDKs provide:

  • Local Ed25519 keypair generation (no RPC needed)
  • Blake3 address derivation from public key
  • Client-side transaction signing for all 8 transaction types
  • Complete RPC wrapper for all endpoints
  • Type-safe response structs with error handling
  • Unit conversion helpers (sats_to_udag(), udag_to_sats())
  • /tx/submit support for mainnet-compatible pre-signed transactions

Python SDK

Installation

pip install ultradag

Dependencies: pynacl (Ed25519), blake3 (hashing), requests (HTTP).

Quick Start

from ultradag import UltraDagClient, Keypair

# Connect to a node
client = UltraDagClient("https://ultradag-node-1.fly.dev")

# Generate a local keypair
keypair = Keypair.generate()
print(f"Address: {keypair.address}")
print(f"Public key: {keypair.public_key_hex}")

# Check node status
status = client.get_status()
print(f"Round: {status.dag_round}, Finalized: {status.last_finalized_round}")

# Get faucet funds (testnet)
faucet_result = client.faucet(keypair.address, 100_00000000)  # 100 UDAG
print(f"Faucet tx: {faucet_result.tx_hash}")

# Check balance
balance = client.get_balance(keypair.address)
print(f"Balance: {balance.balance_udag} UDAG")

# Send a transfer
tx_hash = client.send_tx(
    secret_key=keypair.secret_key_hex,
    to="recipient_address_here",
    amount=50_00000000,  # 50 UDAG
    fee=10_000
)
print(f"Transfer tx: {tx_hash}")

Client-Side Signing (Mainnet)

from ultradag import Keypair, TransferTx

keypair = Keypair.from_secret_key("your_secret_key_hex")

# Build and sign locally
tx = TransferTx(
    from_addr=keypair.address,
    to="recipient_address",
    amount=50_00000000,
    fee=10_000,
    nonce=0,
    pub_key=keypair.public_key_hex,
)
signed = tx.sign(keypair.secret_key_bytes)

# Submit pre-signed transaction
client.submit_tx(signed)

Running Tests

cd sdk/python
python -m pytest tests/ -v

JavaScript / TypeScript SDK

Installation

npm install ultradag

Dependencies: @noble/ed25519 (signatures), blake3 (hashing).

Quick Start

import { UltraDagClient, Keypair } from 'ultradag';

// Connect to a node
const client = new UltraDagClient('https://ultradag-node-1.fly.dev');

// Generate a local keypair
const keypair = Keypair.generate();
console.log(`Address: ${keypair.address}`);

// Check node status
const status = await client.getStatus();
console.log(`Round: ${status.dagRound}, Finalized: ${status.lastFinalizedRound}`);

// Get faucet funds (testnet)
const faucet = await client.faucet(keypair.address, 10_000_000_000n);
console.log(`Faucet tx: ${faucet.txHash}`);

// Check balance
const balance = await client.getBalance(keypair.address);
console.log(`Balance: ${balance.balanceUdag} UDAG`);

// Send a transfer
const txHash = await client.sendTx(
  keypair.secretKeyHex,
  'recipient_address_here',
  5_000_000_000n,  // 50 UDAG
  10_000n
);
console.log(`Transfer tx: ${txHash}`);

Client-Side Signing (Mainnet)

import { Keypair, TransferTx } from 'ultradag';

const keypair = Keypair.fromSecretKey('your_secret_key_hex');

// Build and sign locally
const tx = new TransferTx({
  from: keypair.address,
  to: 'recipient_address',
  amount: 5_000_000_000n,
  fee: 10_000n,
  nonce: 0n,
  pubKey: keypair.publicKeyHex,
});
const signed = tx.sign(keypair.secretKeyBytes);

// Submit pre-signed transaction
await client.submitTx(signed);

Running Tests

cd sdk/javascript
npm test

Rust SDK

Installation

Add to your Cargo.toml:

[dependencies]
ultradag-sdk = { path = "sdk/rust" }

Or from the workspace:

cargo add ultradag-sdk

Quick Start

use ultradag_sdk::{Client, Keypair};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Connect to a node
    let client = Client::new("https://ultradag-node-1.fly.dev");

    // Generate a local keypair
    let keypair = Keypair::generate();
    println!("Address: {}", keypair.address_hex());

    // Check node status
    let status = client.get_status().await?;
    println!("Round: {}, Finalized: {}",
        status.dag_round, status.last_finalized_round);

    // Check balance
    let balance = client.get_balance(&keypair.address_hex()).await?;
    println!("Balance: {} sats", balance.balance);

    Ok(())
}

Running Tests

cargo test -p ultradag-sdk

Go SDK

Installation

go get github.com/ultradag/sdk-go/ultradag

Quick Start

package main

import (
    "fmt"
    "log"

    "github.com/ultradag/sdk-go/ultradag"
)

func main() {
    // Connect to a node
    client := ultradag.NewClient("https://ultradag-node-1.fly.dev")

    // Generate a local keypair
    keypair, err := ultradag.GenerateKeypair()
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("Address: %s\n", keypair.Address)

    // Check node status
    status, err := client.GetStatus()
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("Round: %d, Finalized: %d\n",
        status.DagRound, status.LastFinalizedRound)

    // Get faucet funds (testnet)
    faucet, err := client.Faucet(keypair.Address, 10_000_000_000)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("Faucet tx: %s\n", faucet.TxHash)

    // Check balance
    balance, err := client.GetBalance(keypair.Address)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("Balance: %.4f UDAG\n", balance.BalanceUDAG)

    // Send a transfer
    txHash, err := client.SendTx(
        keypair.SecretKeyHex,
        "recipient_address_here",
        5_000_000_000,  // 50 UDAG
        10_000,
    )
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("Transfer tx: %s\n", txHash)
}

Running Tests

cd sdk/go
go test ./...

Client-Side Signing Flow

The signing flow is a sequence where your application builds a transaction via the SDK, the SDK constructs signable_bytes and signs with Ed25519, then the signed transaction is submitted to a node via POST /tx/submit. The node verifies the signature, validates state (balance, nonce), and returns the transaction hash and status. Your app can then poll GET /tx/{hash} until the transaction reaches “finalized” status.

All SDKs construct signable_bytes() byte-identically to the Rust reference implementation, ensuring cross-language signing compatibility.


Test Counts

SDKUnit TestsCoverage
Python41All tx types, signing, RPC, address derivation
JavaScript55All tx types, signing, RPC, address derivation, BigInt handling
Rust14Wrapper around ultradag-coin types, RPC client
Go36All tx types, signing, RPC, address derivation
Total146

Next Steps