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

# Onboarding quickstart

> Get a machine, or a whole fleet, running peaqOS from the terminal: install the CLI, set up wallets, activate on peaq or on Solana, and know what to do next.

export const KeyTerms = ({all = {}, ids = [], title = "Key terms in this guide"}) => <details className="not-prose my-4 rounded-xl border border-zinc-200 px-4 py-3 dark:border-zinc-800">
    <summary className="cursor-pointer font-medium text-zinc-900 dark:text-zinc-100">
      {title}
    </summary>
    <div className="mt-3 space-y-2 text-sm text-zinc-700 dark:text-zinc-300">
      {ids.map(id => {
  const t = all[id] || ({});
  return <div key={id}>
            <strong>{t.term}.</strong> {t.def}
          </div>;
})}
    </div>
  </details>;

export const G = {
  onchain: {
    id: "onchain",
    cat: "chain-infra",
    term: "On-chain vs off-chain",
    def: "On-chain means written to the shared public ledger every machine agrees on: permanent and readable by anyone. Off-chain means kept on a normal private server instead."
  },
  blockchain: {
    id: "blockchain",
    cat: "chain-infra",
    term: "Chain / blockchain",
    def: "A shared, tamper-resistant public database maintained by a whole network of computers with no single owner. Different chains are separate such networks."
  },
  peaqChain: {
    id: "peaqChain",
    cat: "chain-infra",
    term: "peaq chain",
    def: "The machine-focused blockchain peaqOS uses as home base for identity and credit records."
  },
  transaction: {
    id: "transaction",
    cat: "chain-infra",
    term: "Transaction (tx) / tx hash",
    def: "A single signed request that changes the ledger. Its hash is a unique, receipt-like ID you can use to look it up later."
  },
  rpcUrl: {
    id: "rpcUrl",
    cat: "chain-infra",
    term: "RPC URL / endpoint",
    def: "The network address your code calls to read from or write to a chain, like the base URL of the chain's API server."
  },
  mainnet: {
    id: "mainnet",
    cat: "chain-infra",
    term: "Mainnet / testnet (agung)",
    def: "Mainnet is the real, live network where tokens have real value. Testnet is a free practice copy with worthless tokens; peaq's is called agung."
  },
  evm: {
    id: "evm",
    cat: "chain-infra",
    term: "EVM / EVM-compatible",
    def: "The Ethereum Virtual Machine: the standard runtime many chains share, so the same 0x... addresses and tools work across all of them. peaq is EVM-compatible."
  },
  node: {
    id: "node",
    cat: "chain-infra",
    term: "Node (RPC node)",
    def: "A server running the blockchain software that holds a copy of the ledger and answers queries. NOT a ROS 2 node, despite the shared word."
  },
  chainId: {
    id: "chainId",
    cat: "chain-infra",
    term: "Chain ID",
    def: "A number that uniquely labels a chain so software doesn't confuse networks (peaq is 3338, Base is 8453)."
  },
  precompile: {
    id: "precompile",
    cat: "chain-infra",
    term: "Precompile",
    def: "A built-in function baked into the chain at a fixed address that acts like a contract but runs as faster native code. The batch one bundles several actions into one all-or-nothing transaction."
  },
  dataHash: {
    id: "dataHash",
    cat: "chain-infra",
    term: "Data hash (keccak256)",
    def: "A short, fixed-length fingerprint of a file, stored on-chain instead of the file itself, so data can be verified later while the raw data stays off-chain."
  },
  depin: {
    id: "depin",
    cat: "chain-infra",
    term: "DePIN",
    def: "Decentralized Physical Infrastructure Network: a network of real-world machines built and run by many independent owners who earn for the work their machines do."
  },
  wallet: {
    id: "wallet",
    cat: "wallet-keys",
    term: "Wallet",
    def: "An account on the chain, identified by a public address, that holds a machine's funds and approves its actions. Really just a pair of keys, not a place money is stored."
  },
  keypair: {
    id: "keypair",
    cat: "wallet-keys",
    term: "Keypair",
    def: "The two matched secrets behind a wallet: a public address you can share, and a private key you keep secret that signs actions."
  },
  privateKey: {
    id: "privateKey",
    cat: "wallet-keys",
    term: "Private key",
    def: "The secret string that proves you control a wallet. Anyone who has it has full control, like a master password that can never be reset."
  },
  sign: {
    id: "sign",
    cat: "wallet-keys",
    term: "Sign / signature",
    def: "Using your private key to produce a cryptographic stamp proving you approved a specific action, without ever revealing the key."
  },
  signer: {
    id: "signer",
    cat: "wallet-keys",
    term: "Signer / signing identity",
    def: "The wallet whose private key authorizes an action: the account the network treats as the one taking it. NOT a file or an app."
  },
  address: {
    id: "address",
    cat: "wallet-keys",
    term: "Address (0x...)",
    def: "The public 0x... identifier of a wallet or contract you can freely share so others can send to it or look it up, like an account number."
  },
  eoa: {
    id: "eoa",
    cat: "wallet-keys",
    term: "EOA (externally owned account)",
    def: "A plain wallet controlled directly by a private key, as opposed to one controlled by code. Here, the account that IS the machine."
  },
  ows: {
    id: "ows",
    cat: "wallet-keys",
    term: "OWS / wallet vault",
    def: "An open standard for storing wallet keys in an encrypted local file (a vault) with a backup phrase, instead of a bare key in a text file."
  },
  passphrase: {
    id: "passphrase",
    cat: "wallet-keys",
    term: "Passphrase (OWS_PASSPHRASE)",
    def: "The password that unlocks the encrypted wallet vault so its key can be used to sign."
  },
  mnemonic: {
    id: "mnemonic",
    cat: "wallet-keys",
    term: "Mnemonic / seed phrase",
    def: "A list of 12 or 24 ordinary words that encodes a wallet's secret key, used to back it up and recover it. Whoever has the words controls the wallet."
  },
  derivation: {
    id: "derivation",
    cat: "wallet-keys",
    term: "Derivation path",
    def: "The deterministic recipe that turns one backup phrase into many specific keys and addresses, one per network or index."
  },
  challenge: {
    id: "challenge",
    cat: "wallet-keys",
    term: "Challenge (sign-to-prove)",
    def: "A login-style handshake: the server sends a random message, you sign it with your key, and the signature proves you control the account without sending the key."
  },
  eip191: {
    id: "eip191",
    cat: "wallet-keys",
    term: "EIP-191 / personal_sign",
    def: "A standard way to sign a plain message to prove you control an account, without sending any on-chain transaction."
  },
  did: {
    id: "did",
    cat: "identity",
    term: "DID / peaqID",
    def: "A globally unique, self-owned ID for a machine that lives on the chain and isn't issued by any single company. peaqID is peaq's version: did:peaq:<machine ID as a decimal> for an Economics 2.0 machine, did:peaq:0x<address> for a Tokenomics 1.0 machine or an operator."
  },
  register: {
    id: "register",
    cat: "identity",
    term: "Register a machine",
    def: "Putting a machine on the network for the first time, which gives it an ID, a DID, an ownership token, and a locked deposit. Under Economics 2.0 this is one activateMachine call signed by the machine's owner on peaq, or the seven-stage onboarding for a machine homed on Solana; registerMachine and registerFor are the older Tokenomics 1.0 calls."
  },
  machineId: {
    id: "machineId",
    cat: "identity",
    term: "Machine ID",
    def: "Your machine's handle in every later call. Under Economics 2.0 it is derived from the machine type and credential subject (a large uint256, written as a decimal string); Tokenomics 1.0 machines got a small sequential number."
  },
  ownerOperator: {
    id: "ownerOperator",
    cat: "identity",
    term: "Owner / operator",
    def: "The owner owns a machine; the operator runs it. They can be the same account (self-managed) or different (proxy-managed)."
  },
  proxyOperator: {
    id: "proxyOperator",
    cat: "identity",
    term: "Proxy operator",
    def: "One account that registers and manages many machines on behalf of their owners, so a fleet operator can handle a whole fleet from one wallet."
  },
  didAttributes: {
    id: "didAttributes",
    cat: "identity",
    term: "DID attributes",
    def: "Public name-value facts (a docs link, a data endpoint) attached to a machine's DID and stored on-chain for anyone to read. An Economics 2.0 machine sets them as service endpoints during activation; a Tokenomics 1.0 machine writes them in a separate transaction after registration."
  },
  pairing: {
    id: "pairing",
    cat: "identity",
    term: "Pairing / pairing token",
    def: "The verified link between an AI agent and a machine, set up by signing a challenge. The pairing token is the signed credential the agent sends with each request, like a temporary access badge."
  },
  hardwareAttestation: {
    id: "hardwareAttestation",
    cat: "identity",
    term: "Hardware attestation",
    def: "A tamper-resistant chip on the machine cryptographically vouching that it's genuine hardware, so its identity can't be faked in software. This is the Verify layer."
  },
  gas: {
    id: "gas",
    cat: "tokens-economics",
    term: "Gas",
    def: "The small fee, paid in the chain's token, that every action writing to the ledger costs, like a per-write transaction cost."
  },
  peaqToken: {
    id: "peaqToken",
    cat: "tokens-economics",
    term: "PEAQ (token)",
    def: "The peaq network's own token, used to pay gas fees and to lock up as the deposit when registering a machine."
  },
  gasStation: {
    id: "gasStation",
    cat: "tokens-economics",
    term: "Gas Station / faucet",
    def: "A peaq service that hands a brand-new, empty wallet a tiny starting amount of tokens so it can afford its first network fees. Gated by 2FA."
  },
  bond: {
    id: "bond",
    cat: "tokens-economics",
    term: "Bond",
    def: "PEAQ locked when a machine activates, proving skin in the game. Under Economics 2.0 it is priced per tier in USD and converted to PEAQ at the oracle rate, and it is not withdrawable; Tokenomics 1.0 machines locked a fixed 1 PEAQ. Bonded means the deposit is in place."
  },
  nft: {
    id: "nft",
    cat: "tokens-economics",
    term: "NFT",
    def: "A unique, one-of-a-kind ownership token recorded on the chain. Unlike a coin, no two are interchangeable."
  },
  mint: {
    id: "mint",
    cat: "tokens-economics",
    term: "Mint / minting",
    def: "Creating a brand-new token on the chain and assigning it to an owner, like stamping a fresh serial-numbered certificate into existence."
  },
  machineNft: {
    id: "machineNft",
    cat: "tokens-economics",
    term: "Machine NFT",
    def: "The unique token representing one specific physical machine. Under Economics 2.0 a peaq-homed machine has one ERC-721 in MachineRegistry and a Solana-homed machine has a native Machine account; transferring it transfers ownership of the machine. Under Tokenomics 1.0 it is a separate financial NFT that can be sold or bridged apart from the machine's identity."
  },
  identityNft: {
    id: "identityNft",
    cat: "tokens-economics",
    term: "Identity NFT",
    def: "Tokenomics 1.0 only: a non-transferable (soulbound) token minted automatically when a machine registered, representing its identity. Its token ID equals the machine ID. An Economics 2.0 machine has no separate identity NFT; its Machine NFT in MachineRegistry carries the identity."
  },
  tokenId: {
    id: "tokenId",
    cat: "tokens-economics",
    term: "Token ID",
    def: "The unique number identifying one specific token within a collection, like a serial number."
  },
  mcr: {
    id: "mcr",
    cat: "tokens-economics",
    term: "Machine Credit Rating (MCR)",
    def: "A creditworthiness score for a machine (a Moody's-style grade AAA down to NR, plus a 0-100 number) computed from its recorded earnings and activity. Like a credit score for a robot."
  },
  mcrApi: {
    id: "mcrApi",
    cat: "tokens-economics",
    term: "MCR API",
    def: "The public web service you call to fetch a machine's credit score and profile as JSON, and the one place a machine's monetization is switched on or off with a signed message. No login needed: reads are open, and the write is authorized by the signature itself."
  },
  provisioned: {
    id: "provisioned",
    cat: "tokens-economics",
    term: "Provisioned / NR (Not Rated)",
    def: "Early MCR statuses. Provisioned means registered and bonded but with too little history to score yet. NR means no grade, because the score is too low or the machine isn't bonded."
  },
  event: {
    id: "event",
    cat: "tokens-economics",
    term: "Event (revenue / activity)",
    def: "A recorded data point about a machine's work, submitted to the chain to feed its credit score. Revenue events report money earned; activity events report work with no money. NOT a ROS topic message."
  },
  trustLevel: {
    id: "trustLevel",
    cat: "tokens-economics",
    term: "Trust level",
    def: "A label on each submitted event saying how strongly its truth is backed: the machine's word (0), a checkable on-chain record (1), or tamper-proof hardware proof (2)."
  },
  escrow: {
    id: "escrow",
    cat: "tokens-economics",
    term: "Escrow",
    def: "Holding a buyer's payment in a neutral locked place until the service is delivered, then releasing it, so neither side has to trust the other first."
  },
  paymentRail: {
    id: "paymentRail",
    cat: "tokens-economics",
    term: "Payment rail",
    def: "The specific method or channel a payment moves through, like choosing card vs bank transfer vs a particular token."
  },
  x402: {
    id: "x402",
    cat: "tokens-economics",
    term: "x402",
    def: "A web payment standard where a server answers 'payment required' with exact instructions, and the buyer's wallet signs an authorization instead of sending a separate transaction. Built for machines and agents paying per request."
  },
  usdt: {
    id: "usdt",
    cat: "tokens-economics",
    term: "USDT",
    def: "A stablecoin token meant to hold a value of one US dollar, used to pay service providers without price swings."
  },
  fractionalize: {
    id: "fractionalize",
    cat: "tokens-economics",
    term: "Fractionalize (ERC-3643)",
    def: "Splitting ownership of one machine into many small tradable shares so multiple people can each own a piece. ERC-3643 is the regulated-securities token standard used to do it."
  },
  smartContract: {
    id: "smartContract",
    cat: "smart-contracts",
    term: "Smart contract / contract address",
    def: "A program deployed on the chain that runs exactly as written and that anyone can call, identified by its own 0x... address."
  },
  registryContracts: {
    id: "registryContracts",
    cat: "smart-contracts",
    term: "Registry contracts",
    def: "On-chain programs that each keep an official, lookup-able list. Under Economics 2.0, MachineRegistry tracks which machines exist, EventRegistry stores their events and MachineSubscription holds their bonds; under Tokenomics 1.0 these were IdentityRegistry, EventRegistry and IdentityStaking."
  },
  smartAccount: {
    id: "smartAccount",
    cat: "smart-contracts",
    term: "Smart account (ERC-4337)",
    def: "A programmable wallet controlled by code instead of a single key, so it can enforce rules like spending limits. A machine gets one through a separate deploySmartAccount call after activation."
  },
  submitEvent: {
    id: "submitEvent",
    cat: "smart-contracts",
    term: "submitEvent / batchSubmitEvents",
    def: "The calls that record one or many of a machine's revenue or activity entries onto the chain."
  },
  revert: {
    id: "revert",
    cat: "smart-contracts",
    term: "Revert",
    def: "When an on-chain call is rejected and fully undone because a rule was broken, leaving no changes and usually a named error."
  },
  soulbound: {
    id: "soulbound",
    cat: "smart-contracts",
    term: "Soulbound",
    def: "A token that can never be transferred or sold and stays permanently attached to one owner. The Tokenomics 1.0 Identity NFT is soulbound."
  },
  bridge: {
    id: "bridge",
    cat: "cross-chain",
    term: "Bridge / bridging",
    def: "Moving a token from one chain to another. Tokenomics 1.0 Machine NFTs can be bridged from peaq to Base through the SDKs (mainnet only); Economics 2.0 machines cannot be bridged or relocated yet."
  },
  base: {
    id: "base",
    cat: "cross-chain",
    term: "Base",
    def: "Another blockchain network (built by Coinbase). Tokenomics 1.0 Machine NFTs can be bridged to and from it. Paying fees on Base needs Base ETH."
  },
  omniChain: {
    id: "omniChain",
    cat: "cross-chain",
    term: "Omni-chain / cross-chain",
    def: "Working across many separate chains at once, so a machine's identity and credit created on peaq can be read or used on other chains."
  },
  homeChain: {
    id: "homeChain",
    cat: "cross-chain",
    term: "Home chain",
    def: "The chain where a record's canonical, authoritative copy lives. For a peaqOS machine that is peaq, or Solana for an Economics 2.0 machine created there; other chains hold mirrors. The subscription is booked on peaq either way; a Solana-homed machine pays its bond on Solana."
  },
  satelliteChain: {
    id: "satelliteChain",
    cat: "cross-chain",
    term: "Satellite chain",
    def: "A chain carrying a read-only, automatically synced mirror of home-chain records, so apps there can use them without crossing back to the home chain."
  },
  sourceChainId: {
    id: "sourceChainId",
    cat: "cross-chain",
    term: "sourceChainId / sourceTxHash",
    def: "Two fields recording which chain an action happened on and its hash there, so a cross-chain event can be traced back and verified."
  },
  machineAgent: {
    id: "machineAgent",
    cat: "general-web3",
    term: "Machine Agent",
    def: "A third-party AI program (Claude, OpenAI, a custom bot) paired to a machine and given limited permission to find, buy, and pay for services on its behalf."
  },
  delegationPolicy: {
    id: "delegationPolicy",
    cat: "general-web3",
    term: "Delegation policy",
    def: "The rules an owner gives an AI agent that cap how much it can spend per transaction and per day and which services it may use, so it transacts within guardrails."
  },
  machineMarkets: {
    id: "machineMarkets",
    cat: "general-web3",
    term: "Machine Markets / Service Registry",
    def: "peaqOS's marketplace where machines list services they offer (Service Registry) and where agents discover, order, pay for, and run services from others."
  },
  sdk: {
    id: "sdk",
    cat: "general-web3",
    term: "SDK (peaq-os-sdk)",
    def: "peaq's code library (Python and JS) you install to call all this functionality without writing low-level blockchain calls yourself."
  },
  stream: {
    id: "stream",
    cat: "data-stream",
    term: "Stream (Data-as-a-Service)",
    def: "The peaqOS function where a machine sells the data it generates: it signs the data, encrypts what's sensitive, and grants buyers access. Selling data, as opposed to selling capacity (that's Monetize)."
  },
  edgeAgent: {
    id: "edgeAgent",
    cat: "data-stream",
    term: "peaqOS Edge Agent",
    def: "Software that runs on the machine itself (as a ROS 2 node) and signs, encrypts, and ships the data it produces. The on-machine half of Stream."
  },
  dataPackage: {
    id: "dataPackage",
    cat: "data-stream",
    term: "Signed data package",
    def: "A bundle of machine data stamped with the machine's identity (DID, timestamp, sequence number) and a signature, so anyone can prove which machine produced it and that it wasn't altered."
  },
  dataEventMap: {
    id: "dataEventMap",
    cat: "data-stream",
    term: "Data Event Map",
    def: "The policy file a machine owner writes to control what streams out: which topics to read, which fields to keep, drop, or encrypt, and where the signed data goes."
  },
  chunk: {
    id: "chunk",
    cat: "data-stream",
    term: "Chunk",
    def: "A bounded, individually encrypted slice of a data stream (by time window or size). The unit a buyer actually purchases and decrypts."
  },
  chunkChain: {
    id: "chunkChain",
    cat: "data-stream",
    term: "Chunk chain",
    def: "A run of chunks linked in order, each referencing the one before it, so missing, reordered, or edited chunks are detectable. Tamper-evidence for a continuous stream."
  },
  manifest: {
    id: "manifest",
    cat: "data-stream",
    term: "Manifest",
    def: "A record describing a chunk: its hashes, storage location, and encryption details, without the data itself. The machine signs the chunk's encrypted data hash; buyers check the signature and hashes before trusting or buying."
  },
  envelopeEncryption: {
    id: "envelopeEncryption",
    cat: "data-stream",
    term: "Envelope encryption / key wrapping",
    def: "Encrypt the data once with a random key, then lock that key separately for each authorized reader. Granting a buyer access re-locks the key to their public key; the data itself is never re-encrypted."
  },
  accessGrant: {
    id: "accessGrant",
    cat: "data-stream",
    term: "Access grant",
    def: "What a buyer receives after paying: the chunk keys they bought, each locked to their public key. They unlock with their private key and decrypt only those chunks."
  },
  contextProvider: {
    id: "contextProvider",
    cat: "data-stream",
    term: "Context Provider",
    def: "A third party that buys machine data, normalizes it into datasets, and serves or resells it (for example, for AI training). The buyer side of Stream, such as DataHive."
  },
  computeProvider: {
    id: "computeProvider",
    cat: "monetize",
    term: "Compute provider",
    def: "A machine that rents out its processing power to a compute network. Instead of sitting idle, the machine runs other people's workloads and earns for it."
  },
  provisioningManifest: {
    id: "provisioningManifest",
    cat: "monetize",
    term: "Provisioning manifest",
    def: "A published, step-by-step install plan that turns a machine into a compute provider: the checks to run first, the commands to execute, and the probes that prove it worked. The machine pulls it on demand and runs it locally."
  },
  heartbeat: {
    id: "heartbeat",
    cat: "monetize",
    term: "Heartbeat",
    def: "A short signed 'I'm here' message a machine sends out at a regular interval. As long as heartbeats keep arriving, the machine counts as online; if they stop, it's marked offline automatically."
  },
  aggregator: {
    id: "aggregator",
    cat: "monetize",
    term: "Aggregator",
    def: "A network that pools capacity from many machines and sells it on, such as a decentralized compute marketplace. Machines connect to an aggregator, which then dispatches work to them."
  },
  machineWallet: {
    id: "machineWallet",
    cat: "monetize",
    term: "Machine wallet",
    def: "The wallet that belongs to the machine itself, separate from its owner's or operator's wallet. Earnings from the machine's work land here by default."
  },
  walrus: {
    id: "walrus",
    cat: "chain-infra",
    term: "Walrus",
    def: "A decentralized storage network where encrypted data chunks can be parked, referenced by walrus:// links. The data stays off the blockchain; only its reference and fingerprint are tracked on-chain."
  },
  solana: {
    id: "solana",
    cat: "cross-chain",
    term: "Solana",
    def: "A high-throughput blockchain. peaqOS wallets hold a Solana account and sign Solana transactions, machine-economy payments can settle there, and an Economics 2.0 machine can be homed there (identity, DID and NFT as Solana accounts, the bond paid on Solana and booked on peaq)."
  }
};

Onboarding a machine to peaqOS gives it a permanent identity (a <Tooltip tip={G.did.def}>peaqID</Tooltip>), an ownership record (a <Tooltip tip={G.machineNft.def}>Machine NFT</Tooltip>) and a subscription <Tooltip tip={G.bond.def}>bond</Tooltip> that says the machine is committed to the network. From that point on it can build a credit history, be managed by its owner and operator, and sell the data it produces.

This page walks you through that from a blank terminal to an activated machine. You don't need to know how the contracts work; you need a terminal, PEAQ for the bond (40 USD per Pro machine per year, paid in PEAQ), and about half an hour for a first machine on peaq. A Solana onboarding took about 10 minutes in the proven production runs on top of that, because it goes through seven stages on two chains with waits in between. One command runs them all. Each step says what it does, what to type, and how you know it worked. The reference pages ([Activate](/peaqos/functions/activate), [peaqOS CLI](/peaqos/cli), [Onboard a machine on Solana](/peaqos/guides/onboard-on-solana)) go deeper on any flag you want to understand.

<KeyTerms all={G} ids={["did", "machineId", "machineNft", "bond", "wallet", "ows", "homeChain", "gas", "peaqToken", "solana", "mainnet", "rpcUrl"]} />

## First decision: where should the machine live?

A machine has a **home chain**: the chain that holds its identity, DID document and NFT. Today that is either peaq or Solana. The machine ID and the peaqID look the same either way, and both homes can use Stream to sell data.

| | Home on peaq | Home on Solana |
| :- | :- | :- |
| How activation works | One command, one transaction | One command, seven stages: register the owner wallet on peaq (once), pay the bond into a request on Solana, settle it, mint the machine, push the link back to peaq |
| Who finishes it | You, with one confirmed transaction | Your Solana wallet sends the link push, then peaq's Trust Validator node (the node) delivers it on peaq, and the command waits for that delivery. Earlier in the run, the node credits the request and peaq books the bond on its own; the command waits for both |
| Wallets you need | One wallet, funded with PEAQ | Two: an **operator** wallet with a little PEAQ on peaq for one registration, and an **owner** wallet on Solana holding the bond (PEAQ or USDC) and SOL |
| Tiers available | Entry, Basic, Pro | Entry, Basic, Pro (the proven runs used Basic) |
| Where the bond is held | peaq | Paid on Solana by the owner wallet, in PEAQ or USDC, and booked on peaq |
| Where identity, DID and NFT live | peaq contracts | Solana accounts naming your Solana key as owner |
| Where events are recorded | peaq `EventRegistry` | Solana `EventRegistry` program |
| Credit rating (MCR) | Available | Provisioned at activation; scored once the MCR has indexed the machine's Solana events |
| Monetize (opt-in) | Available through the 2.0 MCR | The opt-in is refused for a Solana-homed machine (`SOLANA_MONETIZATION_UNVERIFIED`) |

Choose peaq unless the machine's owner, its buyers or its payments already live on Solana. If you are not sure, start on peaq; it is the shorter path.

## What it costs

Activation costs the tier bond plus gas. The bond is priced in US dollars per tier and paid in PEAQ at the oracle's most recently committed price. The preview (`--dry-run`) prints the exact PEAQ amount before anything is submitted. To size a wallet before you run anything, divide the tier's dollar price by the current PEAQ price.

| Tier | USD price per 365-day period | Available on |
| :- | :- | :- |
| Entry | \$0.02 | peaq, Solana |
| Basic | \$0.20 | peaq, Solana |
| Pro | \$40 | peaq, Solana |

The bond buys one 365-day subscription period, so budget it per machine per year. For a peaq-homed machine, renew with `peaqos machine subscription renew <machine_id>` before the period ends; the CLI and SDKs do not renew a Solana-homed machine. A renewal keeps the machine's tier: `--tier` is refused with `RENEWAL_TIER_UNSUPPORTED` before anything is sent, so pick the tier at activation. After the period ends you get a 14-day grace period, then a 14-day runoff in which the bond decays to zero, and then the machine is terminated: on peaq its Machine NFT is burned; on Solana the machine's accounts stay, with the subscription status mirrored to its terminal record. Renewing late does not refund lost time: the new period runs from the old period end, not from the day you renew, and it costs a full bond. Suspending a machine does not pause any of this. The [subscription lifecycle](/peaqos/concepts/economics-2-0#subscription-lifecycle) describes the whole sequence.

On top of the bond you pay peaq gas (a few transactions, about 0.3 PEAQ in the measured run). A Solana home works differently: the owner wallet pays the bond on Solana, in PEAQ (bridged to Solana) or in USDC, and peaq books it. On 2026-10-06 a Basic bond was 4.744535245 PEAQ, or 0.200807 USDC through the swap; the price moves with the oracle, and the preview prints yours. The owner also pays about 0.0081 SOL of rent and fees per machine with the DID document below (8,122,140 lamports paying in PEAQ, 8,125,140 paying in USDC; a larger document costs a little more), and the operator wallet pays about 0.01 PEAQ of gas once, for the owner wallet's registration. There is no messaging fee: peaq's Trust Validator node delivers the link push.

On peaq, USDT settlement of the bond (`--payment usdt`) is not configured on peaq mainnet; pay the bond in PEAQ. Gas on peaq is always PEAQ. Bonds are not withdrawable. Prices and the formula are on [Economics 2.0](/peaqos/concepts/economics-2-0#tiers).

## Part 1: Set up once per fleet

Everything in this part you do once, and every machine you onboard afterwards reuses it.

<Steps>
  <Step title="Install the CLI">
    You need Python 3.10 or newer. Installing into a virtual environment keeps it separate from anything else on your machine.

    ```bash theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
    python3 -m venv .peaqos-env && source .peaqos-env/bin/activate
    pip install -U 'peaq-os-cli[solana,ows]'
    peaqos --version
    ```

    You should see the CLI version and the SDK version it runs on. For a Solana home it must be CLI 0.0.19 or newer on SDK 0.11.2 or newer (0.0.17 and 0.0.18 onboard, but cannot send the machine's events (0.0.17) or manage it (0.0.18) afterwards). Older releases implement a Solana flow that the current programs no longer accept. The `ows` extra adds the encrypted wallet vault used below; `solana` is only needed for a Solana home. Everything here is mainnet.
  </Step>

  <Step title="Make a folder for the fleet and run the setup wizard">
    The CLI keeps three things in the folder you run it from: a `.env` file with your settings, your DID documents, and `peaqos.log`, a journal of every transaction it sends. The journal is what lets the CLI pick up safely after an interruption, so keep this folder and back it up. Your wallets are not in it: they live in the vault at `~/.ows/`, which needs its own backup.

    ```bash theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
    mkdir my-fleet && cd my-fleet
    peaqos init
    ```

    The wizard asks a handful of questions. Choose **mainnet** and keep the deployment `peaq-mainnet`. For a Solana home, enter your own provider's peaq RPC endpoint when it asks for the RPC URL; the public endpoint rate-limits a Solana run. When offered, choose **wallet** as the key source; it creates an encrypted wallet rather than a raw key. Name the wallet `fleet-owner` for a peaq home or `fleet-operator` for a Solana home. It also asks for a passphrase; you need it for every command that signs with that wallet. Accept the defaults for the rest, including the Event Registry address (the wizard fills in the Economics 2.0 contract, `0xA1e7F1d7B24dAb55Dc92491e6d9B89F6E925Ad1e`). It fills in the contract addresses from its network defaults and finishes by running `peaqos whoami` to show what it wrote.
  </Step>

  <Step title="Create and fund the wallet(s)">
    Wallets live in the <Tooltip tip={G.ows.def}>OWS</Tooltip> vault at `~/.ows/`, each protected by its own passphrase. For each wallet, run `peaqos wallet export <name>` once and store the seed phrase somewhere safe; nothing else can recover the key. The command prints the phrase to the terminal, so do not run it anywhere the output is logged. Creating a wallet does not put any funds in it: send PEAQ (and SOL, for a Solana home) to the addresses it prints.

    <Tabs>
      <Tab title="Home on peaq">
        The wizard already created `fleet-owner` and named it in `.env` as the signer. One wallet does everything: it pays the bond and gas and owns the machine.

        ```bash theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
        peaqos wallet show fleet-owner --json
        ```

        Copy the `0x…` address and send PEAQ to it: the bond plus at least 0.5 PEAQ. Below 0.5 PEAQ a real `peaqos activate` run stops to fund the wallet for you through the Gas Station, which the first time means enrolling an authenticator app from a QR code. Staying above 0.5 PEAQ avoids it, and `--skip-funding` turns it off.

        If you would rather each machine own its own NFT while you keep control as operator, give each machine its own raw key file and activate with `--for` and `--machine-key`; the [fleet guide](/peaqos/guides/proxy-operator-fleet) explains that pattern and how to make the key files.
      </Tab>

      <Tab title="Home on Solana">
        You need two wallets, split by role. The **operator** wallet acts on peaq: it signs one registration per owner wallet, which binds the owner to it, and becomes the operator that owns the machines' points and revenue on peaq. The wizard already created it as `fleet-operator`. The **owner** wallet acts on Solana: it pays the bond, in PEAQ or USDC, plus rent and fees in SOL, and signs every Solana transaction. One pair can serve your whole fleet.

        ```bash theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
        peaqos wallet create fleet-owner
        peaqos wallet export fleet-owner        # store the seed phrase now
        peaqos wallet show fleet-operator --json
        peaqos wallet show fleet-owner --json
        ```

        `create` asks for a passphrase for the new wallet. Give it the same passphrase as `fleet-operator`: the onboarding command signs with both wallets in one run and asks for each wallet's passphrase when it first needs it, so one shared passphrase is one value to remember (or one `OWS_PASSPHRASE` variable in a script). Fund them:

        * **`fleet-operator`**, the `0x…` address from the first `show`: 0.05 PEAQ on peaq covers the registration gas (about 0.01 PEAQ, paid once).
        * **`fleet-owner`**, the Solana (base58) address from the second: the bond per machine in the token you will pay with, plus a little headroom, and at least 0.015 SOL per machine. For PEAQ, that is PEAQ **on Solana** (the OFT mint `PEAQjk7SRS6rXHVFFmpRr7zrC4g5ZuEebpwTxvaLr3b`), bridged over or bought there. For USDC, Solana USDC. A Basic bond was 4.74 PEAQ or 0.20 USDC on 2026-10-06; the preview prints the current figure.

        Then tell the CLI which Solana network and RPC to use by adding two lines to `.env`:

        ```bash theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
        PEAQOS_SVM_NETWORK=mainnet-beta
        PEAQOS_SVM_RPC_URL=<your Solana RPC endpoint>
        ```

        Any Solana RPC provider works here. The public `https://api.mainnet-beta.solana.com` works too: all six proven production runs used it, and the CLI waits out its rate limits and its lagging servers on reads, and warns once at the start of every run that writes. It can be slow to show fresh transactions, so a run against it occasionally stops and needs a rerun; a provider endpoint avoids that. The peaq endpoint in `.env` matters more: an onboarding makes bursts of peaq reads that the public peaq endpoints rate-limit (`RPC_RATE_LIMITED`), so set `PEAQOS_RPC_URL` to an endpoint from your own provider.
      </Tab>
    </Tabs>
  </Step>

  <Step title="Write the DID document">
    The DID document is a small JSON file that describes the machine: which key speaks for it and where to find its data and documentation. Save it as `did.json` in the fleet folder. You can reuse one template for the whole fleet and change only the URLs if they differ per machine. Replace the example URLs below with your own before you activate: they are written on chain and shown on the machine's public MCR profile.

    For a first fleet, point the verification method at the wallet that will own the machines. `publicKeyMultibase` carries the verifying key in multibase form (`z6Mk…` for an Ed25519 key). No `peaqos` command prints it.

    <Tabs>
      <Tab title="Home on peaq">
        Set `controller` to the `0x…` address of `fleet-owner` (from `peaqos wallet show fleet-owner --json`). The CLI accepts only a `0x` address with 40 hex characters here.

        `publicKeyMultibase` takes an Ed25519 public key, and the `0x…` address cannot give you one: it is a hash of the wallet's key, not the key itself. If the machine already has an Ed25519 key, use its public key. Otherwise generate one. Run `pip install base58` first (the CLI does not install it):

        ```bash theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
        python3 -c 'import nacl.signing,base58,os; k=nacl.signing.SigningKey.generate(); fd=os.open("machine-ed25519.key",os.O_WRONLY|os.O_CREAT|os.O_EXCL,0o600); os.write(fd,bytes(k)); os.close(fd); print("z"+base58.b58encode(b"\xed\x01"+bytes(k.verify_key)).decode())'
        ```

        It prints the `z6Mk…` value for `publicKeyMultibase` and writes the private key to `machine-ed25519.key`, readable only by your user. It refuses to overwrite an existing file. Keep that file safe: it is the key the verification method names.

        The value is stored exactly as you write it and nothing checks it. One key per machine is the clean setup. The chain does not reject a repeated key, so a first fleet can share one key through the template and give each machine its own later with `peaqos machine did set-verification-methods`.
      </Tab>

      <Tab title="Home on Solana">
        Set `controller` to the base58 address of `fleet-owner`, the Solana owner wallet. The CLI accepts only a base58 public key that decodes to 32 bytes here, so a `0x…` address is rejected.

        A Solana address is itself an Ed25519 public key, so compute `publicKeyMultibase` from that same address. Run `pip install base58` first; the CLI does not install it:

        ```bash theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
        python3 -c 'import base58,sys; k=base58.b58decode(sys.argv[1]); print("z"+base58.b58encode(b"\xed\x01"+k).decode())' <fleet-owner Solana address>
        ```

        It prints a `z6Mk…` value. Nothing on chain checks it against the address. Every string in the DID document must stay within 128 bytes; the full limits are on [the Solana page](/peaqos/guides/onboard-on-solana#the-did-document).
      </Tab>
    </Tabs>

    ```json did.json theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
    {
      "verificationMethods": [
        {
          "id": "#key-1",
          "methodType": "Ed25519VerificationKey2020",
          "controller": "<owner wallet address>",
          "publicKeyMultibase": "z6Mk<public key in multibase>"
        }
      ],
      "authentication": [0],
      "serviceEndpoints": [
        { "id": "#data", "serviceType": "peaq-data-api", "serviceEndpoint": "https://api.example.com/machines" },
        { "id": "#docs", "serviceType": "peaq-documentation", "serviceEndpoint": "https://docs.example.com" }
      ]
    }
    ```

    Keep the three keys above and nothing else at the top level: `id` and `controller` are rejected there, because the machine's ID is computed on chain and the CLI sets the controller itself. `authentication` lists which verification methods may authenticate, by position (`0` is the first one).
  </Step>
</Steps>

## Part 2: Activate each machine

Two inputs define a machine forever: a **machine type**, one word or phrase you use for the whole fleet (`Sensor`, `Robot`, `Vehicle`, `Charger`…), and a **credential subject**, some bytes that identify this particular unit. The serial number is the usual choice. Together they produce the machine ID, and that pair cannot be activated a second time while the machine exists, so pick them deliberately.

```bash theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
SERIAL=<the machine's serial number>
CREDENTIAL_SUBJECT_HEX=0x$(printf '%s' "$SERIAL" | od -An -v -tx1 | tr -d ' \n')
echo "$CREDENTIAL_SUBJECT_HEX"
```

Check that `echo` prints more than `0x` before you go on. An unset `SERIAL` produces an empty credential subject, which is accepted and cannot be changed afterwards. Use the serial exactly as printed on the unit and decide the format once for the fleet (case, leading zeros, no spaces): a one-character difference is a different machine for good.

Now follow the tab for your home chain. Every `activate` and `machine` write first shows you what it is about to do and asks for confirmation, and most take `--dry-run`, which shows the same preview and stops.

<Tabs>
  <Tab title="Home on peaq">
    <Steps>
      <Step title="Preview">
        Nothing is sent. The output shows the bond for your tier, any voucher credit, and the net PEAQ the wallet needs.

        ```bash theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
        peaqos activate \
          --machine-type Sensor \
          --credential-subject-hex "$CREDENTIAL_SUBJECT_HEX" \
          --manufacturer 0x<manufacturer address> \
          --tier basic \
          --did-document ./did.json \
          --dry-run
        ```

        `--manufacturer` is any EVM address you choose to record as the maker; the network stores it but does not check it. `--tier` is `entry`, `basic` or `pro`. If the preview says the wallet is short, top it up and preview again.
      </Step>

      <Step title="Activate">
        The same command without `--dry-run`. Read the terms it prints and confirm. In a script, add `--yes` to confirm and `--json` for machine-readable output, and set `OWS_PASSPHRASE` (no `PEAQOS_` prefix on this one) to the signing wallet's passphrase or it still stops to ask.

        ```bash theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
        peaqos activate \
          --machine-type Sensor \
          --credential-subject-hex "$CREDENTIAL_SUBJECT_HEX" \
          --manufacturer 0x<manufacturer address> \
          --tier basic \
          --did-document ./did.json
        ```

        Activation is one atomic call: it mints the NFT, stores the DID document, bonds the tier and records peaq as the home. When your wallet's allowance does not already cover the bond, the CLI sends a separate token approval before it, so you may see two transactions go out. The output includes the `machine_id`, a long decimal number. Keep it; every later command identifies the machine by it.
      </Step>

      <Step title="Check">
        ```bash theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
        peaqos machine status <machine_id> --json
        ```

        You should see your wallet as `owner`, your tier under `subscription`, and `is_homed_locally: true`. The machine's peaqID is `did:peaq:<machine_id>`.
      </Step>
    </Steps>
  </Tab>

  <Tab title="Home on Solana">
    On Solana, activation is seven stages on two chains, and one command runs them all. The operator wallet registers the owner wallet on peaq (first machine only). The owner wallet pays the bond into a request on Solana and settles the request. peaq books the bond. Then the owner wallet mints the machine and pushes the link back to peaq, where peaq's Trust Validator node (the node) delivers it. Give each Solana machine its own working folder, so that its journal `peaqos.log`, its run record and its saved arguments stay together. The journal itself is scoped by machine ID. From the fleet folder:

    ```bash theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
    mkdir "../machine-$SERIAL" && cp .env did.json "../machine-$SERIAL/" && cd "../machine-$SERIAL"
    ```

    If you come back to this folder in a new terminal, activate the virtual environment and `source machine.vars` (written in the next step) instead of pasting the variable block again; then rebuild `ARGS`.

    <Steps>
      <Step title="Fill in the argument set">
        The two ceilings are limits the CLI will not exceed, not prices. A ceiling below the real cost refuses the stage before signing instead of warning. They are the ones the proven runs used. The block has `#` comments: paste it into bash, or run `setopt interactive_comments` first in an interactive zsh.

        ```bash theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
        OWNER=<fleet-owner Solana address>
        MANUFACTURER=<a Solana address to record as the maker>   # recorded, never verified; the owner address is fine
        MACHINE_TYPE=<one word for the fleet>    # with the serial it fixes the machine ID for good, so pick it once
        PAY_IN=PEAQ                              # or USDC
        printf '%s=%q\n' OWNER "$OWNER" MANUFACTURER "$MANUFACTURER" MACHINE_TYPE "$MACHINE_TYPE" \
          CREDENTIAL_SUBJECT_HEX "$CREDENTIAL_SUBJECT_HEX" PAY_IN "$PAY_IN" > machine.vars
        cat machine.vars
        ```

        Check that every line has a value. `OWNER` must be the base58 address that `peaqos wallet show fleet-owner` printed: the request records it as the payer, and the mint and the link push need the same wallet. `machine.vars` keeps the values for a later terminal (`source machine.vars`).

        Then build the argument set. The escrow, `--max-in`, is added after the preview in the next step, which suggests it. For a Pro machine, change `--tier basic` to `--tier pro`. Every Solana write pays the default priority price of 10,000 micro-lamports per compute unit (about 4,900 lamports across a PEAQ onboarding, about 7,900 on USDC). Keep it: a write without priority can be dropped. The mint's compute limit is sized from its simulation, so the consent quotes the fee the mint will pay (CLI 0.0.17 or newer). What each flag means: [the argument set](/peaqos/guides/onboard-on-solana#the-argument-set).

        ```bash theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
        ARGS=(
          --chain solana
          --solana-owner "$OWNER" --manufacturer "$MANUFACTURER"
          --machine-type "$MACHINE_TYPE" --credential-subject-hex "$CREDENTIAL_SUBJECT_HEX"
          --tier basic --did-document ./did.json
          --pay-in "$PAY_IN"
          --max-native-fee-lamports 50000 --max-native-rent-lamports 6000000
          --timeout-seconds 300
        )
        ```

        <Warning>
          Keep the identity, the owner wallet, the DID document, the tier, the rail, `MAX_IN` and the two ceilings unchanged between runs of one machine. The SDK fingerprints every onboarding input (identity, owner, controller, manufacturer, DID document and the two ceilings), so a changed one stops the next stage; the request freezes the tier, the rail and the escrow when it opens. Do not upgrade the CLI or the SDK in the middle of onboarding a machine either. Details: [what stays fixed](/peaqos/guides/onboard-on-solana#what-stays-fixed).
        </Warning>
      </Step>

      <Step title="Preview the whole plan">
        No wallet needed, nothing is sent. The preview is one screen: whether the owner wallet is registered yet, the bond, the escrow it suggests against what the owner holds, the rents and the seven stages. Check that the owner holds at least the suggested escrow and the SOL.

        ```bash theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
        peaqos activate "${ARGS[@]}" --dry-run
        ```

        It ends with `Run it with --max-in <N>`. Add that escrow to the argument set and save it with the other values:

        ```bash theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
        MAX_IN=<the suggested escrow>
        printf 'MAX_IN=%q\n' "$MAX_IN" >> machine.vars
        ARGS+=(--max-in "$MAX_IN")
        ```

        In a later terminal, `source machine.vars`, paste the `ARGS=(...)` block and run the `ARGS+=` line again.

        On PEAQ the escrow is the bond plus a 1% cushion; what the bond does not use comes back at settlement. On USDC it covers the swap's estimated cost with the same cushion, and the remainder comes back in USDC.
      </Step>

      <Step title="Run the onboarding">
        This command runs all seven stages with both wallets. It prints a plan block, then each stage's terms (signer, every amount in base units with the exact token figure, each cap) and asks you to confirm it (add `--yes` in a script). It asks for each wallet's passphrase when it first needs it (or reads `OWS_PASSPHRASE`). After each confirmed stage it prints an indented `landed after 1 send` line (the mint's also shows its compute use). A send the network dropped is sent again with the same signed bytes while it can still land, so a higher count never means a second payment. While the command waits, it prints a "still waiting" line every two minutes and "landed in …" when a wait ends. The proven runs took about 10 minutes.

        ```bash theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
        peaqos activate "${ARGS[@]}" \
          --operator-wallet fleet-operator --owner-wallet fleet-owner \
          --wait-minutes 60
        ```

        There is no link fee to cap: production's link push goes to peaq's Trust Validator node, with no messaging fee. It ends with a summary: the `machine_id`, every transaction reference, `link seq 1 applied`, and a `Spent` block read from the receipts (what the operator paid on peaq, what the owner paid on Solana). Done means exit `0`; with `--json`, `jq -r .next_step.phase` on the output reads `complete`. Keep the `machine_id`; it stays the same for every later command. The folder now also holds `onboarding-<machine_id>.json`, a record of the run.

        If the command stops before `complete` (its wait budget ran out, you pressed Ctrl-C, the connection dropped), nothing is lost and nothing is paid twice: run the same command again. It reads its journal, skips every stage that already landed and continues from the first unfinished one. The output also prints the command to run next as `resume_command`.
      </Step>

      <Step title="Check">
        ```bash theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
        peaqos machine history <machine_id> --chain solana
        peaqos machine status <machine_id> --json --chain solana
        ```

        `machine history` lists every transaction of the onboarding on both chains, who sent it and what it cost, from the chains alone; the link push's delivery reads `node`. In `machine status`, `identity` shows the Solana owner and the `link` block shows peaq's watermark for the machine; that watermark is what made the run `complete`.
      </Step>
    </Steps>

    Running one stage at a time with `--phase`, interrupted runs, state reads and the Python and JavaScript scripts are in [Onboard a machine on Solana](/peaqos/guides/onboard-on-solana).
  </Tab>
</Tabs>

For the next machine, go back to the top of Part 2 with the next serial number. The wallets and your `.env` are reused either way; a peaq machine can run from the same fleet folder, a Solana machine gets its own folder. Keep a list of serial number to `machine_id` as you go: the machine ID is how every later command, and peaq support, identifies the machine.

For a fleet on Solana, run the machines one after another, each in its own folder. The owner wallet's registration is sent once, by the first machine; every later machine reconciles it and sends nothing on peaq. At about 10 minutes per machine, 28 machines take about 5 hours; script Part 2 per serial with `--yes --json` and `OWS_PASSPHRASE` exported, write each run's JSON to a file in the machine's folder, and read `machine_id` and `spent` from there.

## Part 3: After activation

<Tabs>
  <Tab title="Home on peaq">
    **Record what the machine does.** Events are how a machine builds its credit history. An activity event says "I did work"; a revenue event says "I earned this much" (in the currency's smallest unit, so cents for USD). On peaq, `qualify event` submits straight away, with no preview and no confirmation prompt, so check the values before you run it (`--dry-run` previews native Solana submissions only).

    ```bash theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
    peaqos qualify event --machine-id <machine_id> --type activity --value 0 \
      --ts "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
    peaqos qualify mcr did:peaq:<machine_id>
    ```

    The second command reads the machine's credit rating.

    **Manage it.** `peaqos machine` covers the lifecycle: `status`, `suspend`, `resume`, `subscription renew`, `transfer`, and the `did set-…` commands to update the DID document. The two `subscription` writes prompt for confirmation but have no `--dry-run`. Details on [CLI: machine](/peaqos/cli#peaqos-machine).
  </Tab>

  <Tab title="Home on Solana">
    **Record what the machine does.** Events go to the Solana `EventRegistry` program, signed by the owner wallet. The first event for a machine also creates its event-log account, so it costs a little extra rent.

    ```bash theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
    PEAQOS_OWS_WALLET=fleet-owner peaqos qualify event --machine-id <machine_id> \
      --type activity --value 0 --ts "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
    ```

    `peaqos qualify mcr did:peaq:<machine_id>` answers for a Solana-homed machine too. A fresh machine reads `mcr: "Provisioned"`, `mcr_score: 0` and `rating_unavailable: "no_events_yet"`, with `home_chain: 5` marking Solana; the score is computed once the MCR has indexed the machine's Solana events.

    **Manage it.** Add `--chain solana` to the `peaqos machine` commands: `status`, `suspend`, `resume`, the `did set-…` commands, `transfer --unsafe` (Solana has no "safe transfer" variant, hence the flag) and `set-evm-operator` if you ever move the machine to a different peaq operator wallet. Details on [CLI: machine](/peaqos/cli#peaqos-machine).

    **Renew it.** The bond buys one 365-day period, the same as on peaq. Renewing a Solana-homed machine is not covered on these pages yet; check this guide again before its period ends.
  </Tab>
</Tabs>

**Sell its data.** Both homes can package and sell machine data through [Stream](/peaqos/functions/stream): `peaqos stream publish` encrypts and signs a data file, `stream distribute` delivers it to a buyer once their payment is confirmed, and `stream grant` hands a buyer access directly when you have checked payment yourself. Buyers pay with the native token or an ERC-20 on peaq or Base, or with SOL or an SPL token on Solana.

## If something goes wrong

The CLI is designed so that a failed or interrupted step is safe to run again: it reads its journal first and reconciles a pending transaction instead of sending it twice. Don't delete `peaqos.log`, don't change the arguments, and rerun the step. For `peaqos machine` writes this covers pending writes only: once a write is recorded as confirmed, running the same command again is a new write (a second `subscription renew` pays again), so check `machine status` before repeating one that already went through. A Solana onboarding run is different: every confirmed phase is reconciled from the journal and never sent again, so rerunning it with the same inputs never pays twice.

### On peaq

| You see | What it means and what to do |
| :- | :- |
| `INSUFFICIENT_PEAQ` or a short-balance message | The wallet named in the message needs more funds. Top it up to the quoted amount plus gas and rerun. |
| A QR code and a prompt for a six-digit code | The signing wallet holds under 0.5 PEAQ, so the CLI is funding it for you through the Gas Station. Nothing has been quoted or spent on chain at this point. Either complete the enrollment, or fund the wallet yourself and rerun with `--skip-funding`. A preview does not run this step, so a wallet that previewed clean can still meet it on the real run. |
| `PENDING` | The transaction was sent but not yet confirmed when the CLI stopped waiting. Rerun the same command; it will report the outcome. |
| A run failed after its token approval confirmed | The approval stands and the next run skips it. It is for the exact amount quoted, never unlimited, and it is what bounds the transfer on chain on the rerun, because the activation call itself carries no spending limit when paying in PEAQ. |
| Two machines from one wallet at once | Finish one machine before starting the next from the same wallet. The duplicate guard is per machine, so a still-pending activation and a fresh one can collide on the same nonce. |
| `NOT_ECONOMIC_AUTHORITY` | `TOKENOMICS_DEPLOYMENT_ID` in `.env` names a deployment that is not the economic authority. Set it to `peaq-mainnet`. |
| `QUOTE_MOVED` | The cost rose above the amount the preview showed. Rerun to see the current quote. |
| `ORACLE_UNPRICED` | The price oracle has no usable PEAQ price, so the bond cannot be quoted. Nothing local fixes it; try again later. |
| `TECHNICALLY_PAUSED` | The contracts are paused. It is caught before the quote, so nothing is spent. Try again later. |
| `RENEWAL_TIER_UNSUPPORTED` on `subscription renew --tier` | A renewal cannot change the tier. Run it again without `--tier`; it renews at the machine's current tier. Nothing was sent. |
| `peaqos init` stops at the Event Registry prompt | On agung the prompt has no default. Agung has no Economics 2.0 EventRegistry, so `peaqos qualify event` for a 2.0 machine needs peaq mainnet. To finish `peaqos init` on agung, type the agung Tokenomics 1.0 `EVENT_REGISTRY_ADDRESS` from the [agung contract tables](/peaqos/install#agung-testnet-contracts), `0x2DAD8905380993940e340C5cE6d313d5c2780040`, then check the other addresses in `.env` against the same tables. |
| `qualify mcr` answers `NOT_FOUND` with a 404 | Either the machine ID is wrong or not registered on this deployment, or the rating service has not indexed the machine yet. Check the ID with `machine status` first; if it is registered, try again later. |

### On Solana

| You see | What it means and what to do |
| :- | :- |
| `PENDING` (exit `2`) after the wait, naming `credit` or `bond` | peaq's node has not committed the credit, or peaq has not booked the bond, yet. The credit landed within about 2 minutes and the bond within about 5 in the proven runs; the command stops waiting after 3 and 6 minutes, whatever `--wait-minutes` says. Rerun the command; it continues waiting. If nothing has moved after 30 minutes, the node may be down: post your `machine_id` in the [peaq Discord](https://discord.gg/UKTFkPWsyH). peaq's Trust Validator node (the node) can stall for hours; it did on 2026-10-07 and again on 2026-10-08. While the node is stalled, every Solana onboarding stops at `[3/7]` with `PENDING`. The request expires after an hour; once the node is back it cancels and refunds the request (or you cancel it with `--phase cancel_request`), and the rerun opens a new request. Nothing is lost: the escrow and the rents come back. |
| `PENDING` after the wait, naming `link_application` | The node has not delivered your link push on peaq yet. Rerun the command; the push is never sent twice. |
| `REQUEST_EXPIRED` | The node did not credit the request within its hour, so it can no longer settle. Nothing was settled. The node cancels it on its own once it is back, returning the escrow and the request's rents; or cancel it yourself with `peaqos activate "${ARGS[@]}" --phase cancel_request --owner-wallet fleet-owner`, which prints `Cancel request on Solana: confirmed <signature>`. Then rerun the command: it opens a new request, even though `peaqos.log` still holds the old one (CLI 0.0.17 or newer; before, the rerun could take the old request for a live one and stop at `[3/7]` with `ActivationRequest absent`). |
| `COMMIT_EXPIRED` | The credit expired before the settlement. Nothing was settled. Cancel as above, then rerun. |
| `REQUEST_CLOSED` | You ran a single `--phase` (`finalise` or `cancel_request`) on a request that had already been cancelled or refunded. Nothing was signed. Rerun the command without `--phase`: it opens a new request. |
| `ESCROW_BELOW_BOND` or `INSUFFICIENT_BALANCE` | `MAX_IN` is below the bond, or the owner wallet holds less than `MAX_IN` in the pay-in token on Solana. Nothing was signed. Take the preview's suggested `--max-in`, or fund the owner wallet, and rerun. |
| `ACTIVATION_REFUNDED` | peaq refused the bond after the settlement; the Trust Validator returned it in PEAQ to the owner wallet. Rerun the command: it opens a new request. |
| `INSUFFICIENT_SOL` | The owner wallet cannot pay a write's fee and rent and still keep its own minimum balance. Nothing was signed. Top up its SOL and rerun. |
| A stage that stays unconfirmed for minutes after "signed and journaled" | The transaction may have been dropped before landing. While its blockhash is still valid (about 80 s), the SDK re-sends the same signed bytes on its own (SDK 0.11.2 or newer). After that, rerun once: the rerun reconciles the journaled transaction and does not sign it again. A request, settlement or cancellation that failed, or expired without landing, is replaced by a fresh one. A mint that never landed is proven dead and minted again on the next run (since CLI 0.0.16; the dead signature is printed as `expired`), and so is a mint that ran out of compute and created nothing (CLI 0.0.17 or newer). A link push is never signed again. If it still reads unconfirmed, post your `machine_id` in the [peaq Discord](https://discord.gg/UKTFkPWsyH). |
| `STATE_MISMATCH` with `Select the accepted phase's wallet` | The wrong wallet for the stage, usually when running single stages. Nothing was submitted. The registration takes the operator wallet, every Solana write the owner wallet. |
| A conflict about inputs, signer or account | The wallet or one of the fingerprinted arguments differs from the original run. Restore the saved values and the original `did.json` and rerun. |
| `MACHINE_ALREADY_ACTIVE` in the preview | The machine type and serial pair is already a machine with a subscription, and a pair cannot be activated twice. If it is not one you onboarded, change the serial format or the machine type and start again with a new folder. |
| `OPTION_NOT_FOR_CHAIN` | An option of the old reservation flow (`--payment`, `--max-net-peaq-amount`). The error names the replacement (`--pay-in`, `--max-in`). |
| `TECHNICALLY_PAUSED` | The programs are mid-upgrade. Nothing was signed. Rerun later; the preview shows `upgrade lock released` once it is over. |
| `RPC_RATE_LIMITED`, or `RPC_FAILED` naming `-32016` | An endpoint kept rate-limiting reads, or a Solana server behind the chain kept answering. Rerun; if it repeats, switch `PEAQOS_RPC_URL` (or the Solana endpoint) to one from your own provider. Nothing was sent twice. |

Exit codes: `1` means something in your input or a declined confirmation, `2` a chain or network failure, `3` a configuration problem such as a missing setting or extra. With `--json`, the `error_code` field says exactly which. Full tables live on [CLI: exit codes](/peaqos/cli#exit-codes) and [Solana onboarding: resume and troubleshoot](/peaqos/guides/onboard-on-solana#resume-and-troubleshoot).

## Where to go next

* [Activate](/peaqos/functions/activate): what activation creates and why it is one transaction
* [Self-managed onboarding](/peaqos/guides/self-managed-onboarding): the peaq flow from the SDKs instead of the CLI
* [Fleet onboarding with an operator](/peaqos/guides/proxy-operator-fleet): machines that own themselves while you operate them
* [Onboard a machine on Solana](/peaqos/guides/onboard-on-solana): every Solana flag, state and recovery path
* [Wallets (OWS)](/peaqos/wallets), [Install](/peaqos/install), [Economics 2.0](/peaqos/concepts/economics-2-0)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.