Developer Guide

Build on arknet with a pure peer-to-peer SDK. Your application joins the mesh as a lightweight libp2p peer, discovers compute nodes via gossip, and sends inference requests directly over Noise-encrypted channels. No HTTP. No gateway. No middleman.

Install

# Python
pip install arknet-sdk

# Rust
cargo add arknet-sdk

# TypeScript / Node.js (coming soon — p2p update pending)
npm install arknet-sdk

Architecture overview

When you call Client.connect(), the SDK:

  1. Loads seed addresses from seeds.json (fetched at build time, hardcoded fallback in the binary)
  2. Connects to a validator acting as a circuit relay via libp2p
  3. Subscribes to gossip on arknet/pool/offer/1 to discover compute nodes and their loaded models
  4. Sends inference directly to the compute node — through the relay initially, then DCUtR hole-punches a direct connection when possible

Prompts travel only between your machine and the compute node. Validators, verifiers, and other peers never see your prompt content.

Wallets

Every SDK client needs a wallet. A wallet is an Ed25519 keypair stored as a 64-byte file at ~/.arknet/wallet.key. Your address is blake3(pubkey)[0..20].

Python

from arknet_sdk import Wallet

wallet = Wallet.create()     # generate a new keypair
wallet.save()                # writes to ~/.arknet/wallet.key
print(wallet.address)        # hex-encoded 20-byte address

Rust

use arknet_sdk::wallet::Wallet;

let wallet = Wallet::create();
wallet.save()?;
println!("{}", wallet.address());

Or create one with the CLI: arknet wallet create

The same wallet file works across Python, Rust, and the CLI.

Session keys

Instead of signing every inference request with your main wallet key, create a session key. Your wallet signs a DelegationCert that authorizes an ephemeral key with a spending limit and expiry. Inference requests are signed by the session key — if it is compromised, damage is bounded.

Python

from arknet_sdk import Wallet

wallet = Wallet.create()
wallet.save()

# Create a session key: 1 ARK spending limit, 1 hour expiry
session = wallet.create_session(
    spending_limit=100_000_000,   # in atoms (1 ARK = 1e9 atoms)
    expires_secs=3600,
)

Rust

use std::time::Duration;
use arknet_sdk::{wallet::Wallet, session::SessionKey};

let wallet = Wallet::create();
let session = SessionKey::create(
    &wallet,
    100_000_000,                     // spending limit in atoms
    Duration::from_secs(3600),       // 1 hour expiry
)?;

Best practice: Create a session key at application startup. Set the spending limit to the maximum you expect to spend in that session. If the session key leaks, an attacker can only spend up to the limit before it expires.

Connecting

Pass the session key to Client.connect(). The client joins the p2p mesh, discovers compute nodes, and is ready to send inference.

Python

from arknet_sdk import Wallet, Client

wallet = Wallet.create()
wallet.save()
session = wallet.create_session(spending_limit=100_000_000, expires_secs=3600)

client = Client.connect(session=session)

Rust

use std::time::Duration;
use arknet_sdk::{Client, ConnectOptions, wallet::Wallet, session::SessionKey};

let wallet = Wallet::create();
let session = SessionKey::create(&wallet, 100_000_000, Duration::from_secs(3600))?;

let client = Client::connect(ConnectOptions {
    session: Some(session),
    ..Default::default()
}).await?;

Inference

Call client.infer() with a model name, prompt, and max tokens. The SDK finds a compute node serving that model via gossip, connects through the mesh, and returns the result.

Python

from arknet_sdk import Wallet, Client

wallet = Wallet.create()
wallet.save()
session = wallet.create_session(spending_limit=100_000_000, expires_secs=3600)
client = Client.connect(session=session)

response = client.infer(
    model="Qwen/Qwen3-0.6B-Q8_0",
    prompt="Hi, how are you?",
    max_tokens=64,
)
print(response.text)

Rust

use std::time::Duration;
use arknet_sdk::{Client, ConnectOptions, InferRequest, wallet::Wallet, session::SessionKey};

let wallet = Wallet::create();
let session = SessionKey::create(&wallet, 100_000_000, Duration::from_secs(3600))?;
let client = Client::connect(ConnectOptions {
    session: Some(session),
    ..Default::default()
}).await?;

let response = client.infer(InferRequest {
    model: "Qwen/Qwen3-0.6B-Q8_0".into(),
    prompt: "Hi, how are you?".into(),
    max_tokens: 64,
    ..Default::default()
}).await?;
println!("{}", response.text);

TypeScript (coming soon)

The TypeScript SDK has not yet been updated for the p2p architecture. The npm install arknet-sdk package still works but uses the older HTTP-based API. A p2p-native TypeScript SDK is in development.

Complete example

End-to-end in Python — wallet, session, connect, infer:

from arknet_sdk import Wallet, Client

# 1. Create (or load) a wallet
wallet = Wallet.create()
wallet.save()

# 2. Create a session key (bounded spending, 1 hour)
session = wallet.create_session(
    spending_limit=100_000_000,
    expires_secs=3600,
)

# 3. Join the mesh
client = Client.connect(session=session)

# 4. Run inference
response = client.infer(
    model="Qwen/Qwen3-0.6B-Q8_0",
    prompt="Explain arknet in one sentence.",
    max_tokens=100,
)
print(response.text)

How the mesh works

Under the hood, the network is a libp2p mesh with two gossip topics:

TopicPurpose
arknet/pool/offer/1Compute nodes announce their loaded models (heartbeat every 60s)
arknet/tx/mempool/1Transactions broadcast for consensus

When a compute node starts and loads a model, it publishes a PoolOffer message to the gossip mesh. Your SDK subscribes to these offers and maintains a local table of which models are available on which peers. When you call client.infer(), the SDK picks a peer from this table and sends the request directly.

Relay and hole punching

Validators act as circuit relays. If your SDK and the compute node are both behind NAT, the initial connection goes through a validator relay. libp2p DCUtR (Direct Connection Upgrade through Relay) then attempts to hole-punch a direct connection. Once hole-punched, subsequent requests travel directly between you and the compute node with no relay overhead.

Discovery

The SDK discovers the network in this order:

  1. Seedsseeds.json contains multiaddrs of known validators. A hardcoded fallback is compiled into the SDK binary.
  2. Bootstrap — the SDK connects to a seed validator and joins the gossip mesh.
  3. Gossip — the SDK receives PoolOffer messages from compute nodes announcing their models.
  4. Inference — the SDK connects to a compute node offering the requested model.

No HTTP endpoints are involved at any stage. Everything is libp2p.

On-chain transactions

Use the CLI for all on-chain actions:

# Staking
arknet wallet stake --role compute --amount 50000000000000
arknet wallet unstake --role compute --amount 50000000000000
arknet wallet complete-unbond --role compute --unbond-id 1
arknet wallet redelegate --role compute --to-node 0x... --amount 50000000000000

# Governance
arknet governance propose --title "Add new model" --body @proposal.md
arknet governance vote --proposal 1 --choice yes

Under the hood, the CLI builds a borsh-encoded SignedTransaction, signs it with your wallet key, and submits it to the local node RPC.

Transaction types

TypeDescriptionGas
TransferSend ARK between accounts21,000
StakeOpDeposit, withdraw, redelegate stake100,000
RegisterModelRegister a model (10K ARK deposit)200,000
EscrowLockLock funds for an inference job50,000
GovProposalSubmit governance proposal (10K ARK)500,000
GovVoteVote on a proposal30,000
RegisterTeeCapabilityRegister TEE attestation + enclave pubkey200,000

Privacy

See the Privacy & Security page for the full three-tier privacy model.

Bootstrap period

First 6 months or until 100 validators: inference is free. No ARK balance needed. Each wallet gets 10 free inference jobs per hour and 100 per day. After the bootstrap period, inference is paid from your ARK balance.

Contributing

The codebase is Rust.

git clone https://github.com/st-hannibal/arknet.git
cd arknet
cargo test
cargo clippy -- -D warnings
cargo fmt --check

Discussions, issues, and PRs welcome on GitHub.