Skip to main content
A machine can live on instead of peaq. Its identity record, DID document and Machine NFT are then Solana accounts owned by a Solana key, while the subscription and the peaq-side registry entry stay on peaq. Onboarding therefore happens in two places and three phases, in a fixed order: reserve the machine ID on peaq, activate its subscription on peaq, wait for peaq to mirror both to Solana, then create the machine on Solana. The CLI runs one phase per invocation; the SDKs expose the same phases.
Solana support needs CLI 0.0.12 and @peaqos/peaq-os-sdk / peaq-os-sdk 0.8.0 (all 2026-09-16). Upgrade with pip install -U peaq-os-cli "peaq-os-sdk[solana,ows]" or npm install @peaqos/peaq-os-sdk@latest @solana/web3.js @coral-xyz/anchor. Earlier CLI versions, including 0.0.10, have no --chain solana and fail peaq-mainnet activation and renewal with READ_FAILED (CLI: RPC_FAILED) since the 2026-09-15 mainnet upgrade renamed fullMode() to isEconomicAuthority().

What you need

Mainnet only. The Solana half of the deployment record exists for peaq-mainnet; agung-2026-08-28 has none, and there is no testnet walkthrough.

Configure

Every CLI client, keyless previews included, also needs the six Tokenomics 1.0 contract addresses: run peaqos init in this directory first (or copy a .env that has them), otherwise the first preview exits 3 naming IDENTITY_REGISTRY_ADDRESS. --svm-rpc-url and --svm-network before the command name override the environment, which overrides .env. peaqos whoami shows the cluster and a redacted RPC origin once either variable is set. The SDK journal peaqos.log and the original inputs must stay in this directory for every later phase; the same journal is what lets a rerun reconcile instead of resubmitting. Create the two wallets in the vault and note their public addresses. Fund them yourself; wallet creation does not.

The DID document

Save as native-did.json. authentication entries are zero-based indices into verificationMethods. The optional machine-level controller is a separate flag (--solana-controller), not a field here.
Limits come from the Solana program: 8 verification methods, 8 authentication indices, 8 service endpoints, 128 UTF-8 bytes per string field, 64 bytes for the machine type, 512 bytes of credential subject. Oversized input is rejected before anything is signed; nothing is truncated.

The argument set

Every phase takes the same complete arguments. A changed machine type or credential computes a different machine ID, so the CLI treats it as a new attempt with its own journal entries instead of continuing this one; a changed wallet or ceiling on the same machine ID is refused. Keep the original inputs. Ceilings are explicit integers in base units; 0 is a strict cap, never “unlimited”; the USDT cap is enforced on chain, the PEAQ cap is checked before signing and against the mined receipt. Set the ten shell variables first (OWNER, OPERATOR, MANUFACTURER, CREDENTIAL_SUBJECT_HEX, PEAQ_CAP, FEE_CAP, RENT_CAP, HISTORY_START = the peaq block number just before your reservation, COMPUTE_LIMIT, PRIORITY_PRICE); the :? guards make the shell stop on an unset one instead of passing an empty argument.
Tier entry is not offered on Solana: basic or pro. --for, --machine-key, and --slippage-bps are rejected with --chain solana. The machine ID is the same derivation as on peaq, uint256(keccak256(abi.encode(machineType, credentialSubject))), a decimal string in JSON and the DID did:peaq:<decimal id>.

Run the three phases

1

Preview

Keyless. Reports each stage’s unresolved prerequisites and the native fee and rent estimate. A preview is not transaction evidence, and did is null before the machine exists.
2

Reserve on peaq (operator wallet)

Reserves the machine ID for the Solana owner. --yes accepts the displayed terms for this phase only.
3

Activate the subscription on peaq (operator wallet)

Bonds the tier. Approval and activation are separate transactions; an approval receipt alone is not a subscription. The preflight requires isEconomicAuthority() on peaq and reads both technical pause flags before the approval; a pause before the first approval stops with TECHNICALLY_PAUSED and spends nothing; a pause that starts after the approval confirmed ends with the same code, the approval gas spent and the allowance in place, so read the retained transactions before assuming nothing moved.
4

Wait for the reservation mirror and the subscription status

peaq pushes the reservation to Solana, and the subscription status reaches the machine’s SubscriptionTerminal account (it must read Active or Grace with a non-zero sequence that matches peaq’s subscription signal, and its tier must match your plan). Delivery is external to the CLI; a peaq receipt does not prove it. Repeat the native preview until the SDK reports both ready.
5

Create the machine on Solana (owner wallet)

Exit 0 means the Solana transaction confirmed. It does not mean onboarding is complete: peaq still has to apply the link. Rerun the same phase without --yes to reconcile; done is onboarding_state.evidence.stage.phase equal to complete.

Read the state

With the machine ID alone, no wallet, journal or DID document:
Two read modes. Without --chain solana, the CLI falls back to the Solana read when the peaq record is missing or homed elsewhere and PEAQOS_SVM_RPC_URL is configured; that result has status: "observed" and a native_current_state with separate peaq (finalized) and Solana (confirmed) observations, not an atomic snapshot. Native states: absent, reserved, pending_external, present, conflict, in_flight, unavailable. With --chain solana the CLI reads the native management state instead and prints a different object (execution_chain, identity, mirrors with subscription_source, subscription_terminal_status and subscription_terminal_last_seq, peaq with subscription_status, operator_synchronization, pause flags), not native_current_state; it needs the native machine to exist, so before native creation use the fallback read. present proves the accounts exist, not that this attempt created them or that the link is complete. Pending or conflicting state exits 0; an unavailable configuration exits 3; read failures exit 2.

Resume after an interruption

Never delete peaqos.log, never change the inputs, never submit a replacement transaction on a hunch. The SDK records peaq hashes and nonces before it waits for a receipt, and Solana signatures with their blockhash validity before broadcast. Exit codes: 1 input or consent, 2 chain, read or transaction failure, 3 configuration or missing dependency. With --json, read the error_code and the retained evidence, not only the exit code: a phase failure sits in errors[] with its own error_code, and a native transaction can be confirmed at top level while the linkage read afterwards fails with exit 1, 2 or 3, so a nonzero exit is not proof that nothing was created.

The same flow in the SDKs

Store the accepted plan and the serialized progress; restore them with restoreSvmOnboardingProgress(plan, json) before the next phase. In JS 0.8.0 activateMachine previews, reconciles and reports the Solana flow but does not submit its write phases: the public path carries read and linkage capabilities only, so a new reservation, subscription or native creation is reported unavailable and nothing is signed. Submit the phases from the CLI or Python and use JS for status and recovery. Reference: SDK JS: Solana.

After onboarding

  • Manage the machine with the same peaqos machine commands plus --chain solana (status, transfer --unsafe, suspend, resume, did set-controller, the DID setters, and the Solana-only set-evm-operator), or the same SDK methods; the SDK resolves the home chain from the machine ID and refuses the wrong chain. Transfer, controller and the peaq operator link need the Solana owner signature; DID lists, suspend and resume take owner or controller. There is no safe transfer on Solana (transfer requires --unsafe, --data-hex is refused), and approve / approve-all do not exist; the SDKs refuse approveMachine, setMachineApprovalForAll and safeTransferMachine by name. Details: SDK JS, SDK Python.
  • Submit events with submitEvent / submit_event: the SDK routes a Solana-homed machine to the Solana EventRegistry program and signs with the owner’s or controller’s OWS Solana signer (the EVM operator does not qualify). In Python set client.solana_signer to an OwsSolanaSigner (for example from PeaqosClient.solana_signer_from_wallet(...)) before the call, or submit_event raises SIGNER_UNAVAILABLE; the CLI attaches it itself. The first event for a machine also pays rent for its event-log account. A confirmed event is not yet a rating; the 2.0 MCR indexes Solana events asynchronously.
  • Credit rating: the 2.0 MCR scores a Solana-homed machine once its Solana indexer has the machine’s events; until then the response carries home_chain: 5 and a rating_unavailable reason (any non-empty reason means the score is a floor, not a measurement). What mcr-20.peaq.xyz returns for such a machine was not verified live at the time of writing. See the API reference.
  • Monetization opt-in for a Solana-homed machine (signed by the Solana owner) is built into the SDKs but refused with SOLANA_MONETIZATION_UNVERIFIED until the server contract is confirmed.
  • Relocation between peaq and Solana stays switched off on chain. Onboarding on Solana is not a relocation: the machine is created there.