Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.peaq.xyz/llms.txt

Use this file to discover all available pages before exploring further.

Owner equals operator. One keypair, one machine, one identity. This guide covers the full flow from environment setup through on-chain registration.

Prerequisites

  • Node.js ≥ 22 or Python 3.10+
  • A funded EVM wallet (the owner address) with at least 1.1 PEAQ (1 PEAQ bond + gas)
  • Environment variables configured per the install guide

Environment setup

Set these environment variables before running any SDK call. Both SDKs read the same variable names.
.env
# peaq mainnet RPC. See /peaqos/install#public-rpc-endpoints for alternatives
PEAQOS_RPC_URL=https://peaq.api.onfinality.io/public
PEAQOS_PRIVATE_KEY=0x<64-hex-chars>

# Mainnet contracts. fromEnv() requires every variable below to be set.
# For agung testnet addresses see /peaqos/install#agung-testnet-contracts.
IDENTITY_REGISTRY_ADDRESS=0xb53Af985765031936311273599389b5B68aC9956
IDENTITY_STAKING_ADDRESS=0x11c05A650704136786253e8685f56879A202b1C7
EVENT_REGISTRY_ADDRESS=0x43c6c12eecAf4fB3F164375A9c44f8a6Efc139b9
MACHINE_NFT_ADDRESS=0x2943F80e9DdB11B9Dd275499C661Df78F5F691F9
DID_REGISTRY_ADDRESS=0x0000000000000000000000000000000000000800
BATCH_PRECOMPILE_ADDRESS=0x0000000000000000000000000000000000000805
JS examples load the file via import "dotenv/config". Python’s from_env() reads from the shell, so export the file first with set -a && source .env && set +a.

Full flow

1

Initialize the client from environment

fromEnv reads all required variables and returns a configured client. Throws ValidationError if any variable is missing.
import "dotenv/config";
import { PeaqosClient } from "@peaqos/peaq-os-sdk";

const client = PeaqosClient.fromEnv();
console.log("Signer:", client.address);
2

Generate a keypair (optional)

If the machine does not already have a wallet, generate one. This is a local operation with no chain interaction.
const keypair = PeaqosClient.generateKeypair();
console.log("Address:", keypair.address);
console.log("Key:", keypair.privateKey);
// Store the private key securely. It cannot be recovered.
If the machine already has a funded wallet, skip to step 5 and construct the client with that key directly. Steps 3-5 will fund the generated keypair.
3

Set up 2FA on the owner wallet

The Gas Station requires 2FA before it funds any address. Call setupFaucet2FA to start enrollment.
const FAUCET_URL = "https://depinstation.peaq.network";

const enrollment = await client.setupFaucet2FA(
  keypair.address,
  FAUCET_URL,
);
console.log("OTPAuth URI:", enrollment.otpauthUri);
console.log("QR image:", enrollment.qrImageUrl);
// Scan the QR or paste the URI into your authenticator app.
// The QR URL expires after roughly 2 minutes.
4

Confirm 2FA

After adding the secret to your authenticator app, submit the current TOTP code.
await client.confirmFaucet2FA(
  keypair.address,
  FAUCET_URL,
  "123456", // Replace with your actual TOTP code
);
// No return value. Success means 2FA is active.
5

Fund the machine wallet

Request initial gas from the Gas Station. The faucet either funds the wallet or skips if the balance is already sufficient.
const result = await client.fundFromGasStation(
  {
    ownerAddress: keypair.address,
    targetWalletAddress: keypair.address,
    chainId: "peaq",
    twoFactorCode: "654321", // Fresh TOTP code
  },
  FAUCET_URL,
);

if (result.status === "success") {
  console.log("Funded:", result.txHash, result.fundedAmount);
} else {
  console.log("Skipped, current balance:", result.currentBalance);
}
6

Register the machine

Call registerMachine to register the machine on the IdentityRegistry. The call sends 1 PEAQ as a bond with the transaction.
// Build a new client using the machine's own key
const machineClient = new PeaqosClient({
  rpcUrl: client.rpcUrl,
  privateKey: keypair.privateKey,
  contracts: client.contracts,
});

const machineId = await machineClient.registerMachine();
console.log("Registered, machine ID:", machineId);
registerMachine mints the Identity NFT (tokenId == machineId) and stakes the bond. It does not mint the Machine NFT or write DID attributes; those are two separate calls in the next step.
7

Mint the Machine NFT and link the DID

Call mintNft to create the machine’s financial NFT, then writeMachineDIDAttributes to bind machineId and the new nftTokenId to the machine’s DID.
const tx = await machineClient.mintNft(machineId, keypair.address);
const nftTokenId = await machineClient.tokenIdOf(machineId);

await machineClient.writeMachineDIDAttributes({
  machineId,
  nftTokenId,
  operatorDid: "",
  documentationUrl: "https://example.com/docs",
  dataApi: "https://example.com/events",
  dataVisibility: "public",
});
The Machine NFT gets an independent tokenId separate from machineId. See Machine NFT ownership for the full rationale.After all three calls, the machine has a peaqID, an Identity NFT, a Machine NFT, and a 1 PEAQ bond. It starts as Provisioned: on-chain, but not yet rated. It will graduate onto the rated MCR scale once it accumulates enough revenue and activity events.

Error handling

ErrorCauseResolution
ValidationError: PEAQOS_PRIVATE_KEY is requiredMissing environment variableCheck your .env file and shell export
AlreadyRegistered (both SDKs)The address is already registeredQuery the MCR API with the address to find the existing machine ID
RuntimeError: Invalid 2FA code / ApiError: Invalid 2FA codeTOTP code expired or mistypedWait for a fresh code from your authenticator and retry
RuntimeError: 2FA locked / ApiError: 2FA lockedToo many invalid 2FA attemptsWait before retrying
RuntimeError: Faucet rate limit exceeded / ApiError: Faucet rate limit exceededToo many funding requestsWait and retry after a short interval
RuntimeError: Owner daily funding cap exceeded / ApiError: Owner daily funding cap exceededDaily funding cap reached for this ownerFund manually or wait until the cap resets
Insufficient balance for gas + bondWallet does not hold 1 PEAQ + gasTop up the machine wallet and retry

What the machine receives

After completing the full flow (register + mint NFT + write DID attributes):
  • peaqID (W3C DID) anchoring the machine’s identity
  • Identity NFT minted automatically at registration (tokenId == machineId)
  • Machine NFT (LayerZero V2 ONFT) minted via mintNft, with an independent tokenId
  • 1 PEAQ bond deposited into the IdentityStaking contract
  • Gas Station funding (if requested)