@peaqos/peaq-os-sdk is the opinionated TypeScript entry point for the Machine Financial Passport flow. Each capability is exposed both as a PeaqosClient instance method and as a standalone function.
0.6.0 (2026-09-04) adds Economics 2.0. Pass
tokenomics20: { deploymentId } to the constructor to enter Tokenomics mode: one-transaction activation, machine management, and the 2.0 monetization client. In that mode the legacy registration, mint, bridge, event, and MCR-query methods throw typed errors instead of running. Without tokenomics20 the client behaves as before, with one exception that applies to every 0.6.0 client: SubmitEventParams.machineId and MachineEvent.machineId are now bigint, not number.Install
- Node.js: ≥ 22
- TypeScript: ≥ 5
- Peer dependency:
viem(>= 2.47.10) - Economics 2.0: 0.6.0 or newer
- Exports: ESM and CJS. No bundler workarounds.
dotenv is optional but recommended: PeaqosClient.fromEnv() reads from process.env, so import "dotenv/config" at the top of your entry file is the simplest way to load .env.
Environment variables
peaq mainnet contracts
Use these addresses for the contract-address variables (IDENTITY_REGISTRY_ADDRESS and friends — note they are unprefixed) when pointing at peaq mainnet. All contracts are UUPS upgradeable proxies; treat the addresses as the current proxy pointers.
For agung testnet addresses see Install → Agung testnet contracts. Bridging is mainnet-only: LayerZero has no DVN routes to agung.
Machine Markets orchestration
Scale lives underclient.orchestration — the Machine Markets surface (machine identity proofs, agent pairings, skill registry, market search, orders, payments). Reach it by setting PEAQOS_ORCHESTRATION_URL (and optionally PEAQOS_API_KEY) before PeaqosClient.fromEnv(). Full method reference: Orchestration (JS).
Client
PeaqosClient
0.7.0 makes the client generic over its mode:
PeaqosClient<M extends SdkMode = "legacy"> with readonly mode: M. Construct a 2.0 client as new PeaqosClient<"tokenomics20">({ ...config, tokenomics20: { deploymentId: "peaq-mainnet" } }); without the type argument TypeScript infers "legacy" and the constructor call is a compile error. Query results carry machineId: bigint on a tokenomics20 client and number on a legacy one. fromEnv() returns the union of both and fromWallet() preserves the config’s mode; narrow on client.mode.string
required
RPC endpoint (non-empty).
string
required
0x + 64 hex characters.ContractAddresses
required
All six contract addresses.
string
MCR API URL. Defaults to
DEFAULT_API_URL.OperationalLimits
Per-tx and rate-limit caps. All-zero disables limits.
PeaqosClient instance. toJSON() and util.inspect output redact the private key ("[REDACTED]").
Other RPC endpoints are available. See Public RPC endpoints.
Errors: ValidationError: missing/invalid rpcUrl, privateKey, or any contract address.
fromEnv
Since 0.7.0 fromEnv() reads TOKENOMICS_DEPLOYMENT_ID: a non-empty value selects Tokenomics mode, absent or empty stays legacy, an unknown or unreleased ID throws TokenomicsConfigError at construction. The return type is PeaqosClient<"legacy"> | PeaqosClient<"tokenomics20">; narrow on client.mode.
PeaqosClient. All required env vars must be set (see Environment variables).
Errors: ValidationError: any required env var missing or empty.
fromWallet
PeaqosClient from an OWS vault wallet. When owsSigning is true (default), signing routes through OWS: the key is decrypted only per-sign and wiped immediately after. When false, the key is decrypted at construction and signing uses viem directly.
string
required
Wallet name or UUID in the OWS vault.
string | undefined
required
Vault passphrase. Pass
undefined to fall back to the OWS_PASSPHRASE env var.boolean | undefined
required
Route signing through OWS. Defaults to
true when undefined.Omit<PeaqosClientConfig, 'privateKey'>
required
Client config without
privateKey (the wallet provides the signer).WalletOptions
Optional vault configuration (e.g. custom
vaultPath).PeaqosError: wallet not found, passphrase missing, or OWS signing failure. With owsSigning: false a wrong passphrase throws at construction (eager decrypt). With owsSigning: true a wrong passphrase surfaces on the first sign call. Key material is never decrypted at construction.
Wallets (OWS)
Wallet lifecycle helpers (createWallet, importWallet, importWalletMnemonic, listWallets, getWallet, exportWallet, deleteWallet, plus the extractPeaqAddress utility) back the Open Wallet Standard integration: mnemonic-backed encrypted vault, multi-chain accounts (peaq, Base, Ethereum, Solana, Bitcoin, etc.). Lifecycle helpers are available as module-level imports and as static methods on PeaqosClient; the PeaqosClient.fromWallet factory wires a vault wallet directly into a client (OWS-native signing by default). The JS package bundles @open-wallet-standard/core as a regular dependency; no separate peer install is required. The raw-key constructor and fromEnv flow keep working unchanged. Full reference on the Wallets page.
generateKeypair
secp256k1 privateKey and its derived address. No chain interaction. The private key never touches disk.
OWS wallet lifecycle
OWS wallet helpers are available as staticPeaqosClient methods and standalone functions. They derive multi-chain accounts, keep wallet material in an encrypted OWS vault, and return public WalletInfo metadata.
@peaqos/peaq-os-sdk. createWallet, importWallet, importWalletMnemonic, exportWallet, and fromWallet require a passphrase argument or OWS_PASSPHRASE. options.vaultPath can point at a custom vault directory. fromWallet can sign through OWS (owsSigning=true, default) so key material is decrypted only for the signing operation.
object
Frozen object with
id, name, createdAt, keyType, peaqAddress, and accounts. Each account has accountId, address, chainId, network, and derivationPath.Accessors
All accessors are read-only. The private key is held in an ECMAScript#private field: never exposed through the public surface and redacted in JSON.stringify and util.inspect.
Tokenomics 2.0
Available on a client constructed withtokenomics20: { deploymentId: "peaq-mainnet" | "agung-2026-08-28" }. The seven contract addresses come from the SDK’s snapshot (TOKENOMICS_2_0_DEPLOYMENTS, resolveTokenomics20Deployment), resolved at construction with no network call and verified against InfoDesk.peer(role) before every write. Addresses are never accepted from callers. Every function below is a PeaqosClient method and a package-root export taking the client first. Machine IDs are bigint; a number throws ValidationError. Source of truth in the repo: docs/18_TOKENOMICS_ACTIVATION.md and docs/19_TOKENOMICS_MACHINE_MANAGEMENT.md. Concepts: Economics 2.0.
activateMachine
MachineStateAndSync.activateMachine: mints the ERC-721 in MachineRegistry (token ID equals machine ID), stores the DID document, bonds the tier in MachineSubscription, and records the home chain. The signer becomes owner and bond payer.
ActivateMachineResult: machineId, owner, controller, tier, bondAmount, voucherCreditApplied, netPeaqAmount, transactionHash, chainId, contract, method, receipt, events, and the re-read subscription state. Amounts come from the receipt. Success requires MachineOnboarded, MachineMinted, and Activated from the right contracts (matched by emitting address) plus a matching post-state read. The write is never retried; a receipt timeout throws RECEIPT_UNAVAILABLE carrying the hash.
activateMachineWithUsdt
Same activation, bond settled in USDT through SubscriptionTokenProvisionPool. Requires maxUsdtAmount, taken from previewMachineActivationWithUsdt(...) after applying slippageBps.
previewMachineActivation, previewMachineActivationWithUsdt
machineId, bondAmount, voucherCredit, netPeaqAmount, balance, approvalRequired. Throws MACHINE_ID_MISMATCH and MAX_NET_PEAQ_EXCEEDED; a low balance is returned, not thrown.
computeMachineId
Reads
Lifecycle and subscription
maxNetPeaqAmount, USDT writes maxUsdtAmount; take both from the matching preview. The SDK re-quotes before simulation and never raises an accepted bound. Owner or controller may sign; credits accrue to the owner.
Ownership (ERC-721)
DID updates
AUTHENTICATION_REWRITE_REQUIRED before submission. Ownership and DID writes accept a synchronous onTransactionSubmitted(submission) callback.
previewMachineAction
Side-effect-free preview for ownership and DID actions (not suspend/resume): contract, method, current state, intended effect. Never simulates, signs, or submits.
Machine-ID helpers
Number(bigint), no leading zeros except "0".
Disabled in Tokenomics mode
Enabled in Tokenomics mode since 0.7.0 (2026-09-11):
submitEvent, batchSubmitEvents (Events) and queryMcr, queryMachine, queryOperatorMachines (Queries). Still available in Tokenomics mode: orchestration health, skills, policies, market-service reads, audit reads, payment rails, delivery transports; heartbeat; provisioning; stream. waitForBridgeArrival is static and not gated; it is marked deprecated.
Registration
registerMachine
Registers the caller’s own address as a machine. Reads minBond from the IdentityRegistry contract (currently 1 PEAQ) and sends that value with the transaction.
number
The newly allocated machine ID, decoded from the
Registered event in the transaction receipt.registerFor
Registers a machine on behalf of another address. The caller becomes the proxy operator and supplies the current minBond (read from the IdentityRegistry contract) as msg.value.
0x${string}
required
Machine EOA. The client’s signing address becomes the operator and pays the bond.
number
The newly allocated machine ID for the proxied machine.
Gas Station
1
Setup 2FA
Call
setupFaucet2FA to enroll the owner.2
Confirm 2FA
Call
confirmFaucet2FA with a TOTP from the authenticator.3
Fund
Call
fundFromGasStation to send gas to a machine wallet.setupFaucet2FA
Enrolls an owner address for 2FA with the Gas Station. Returns a QR code URL (expires after ~2 minutes).
string
required
Owner to enroll (SS58 or hex).
string
required
Gas Station base URL.
'svg' | 'png'
QR format. Defaults to
"svg".object
ValidationError on empty args. RuntimeError for INVALID_OWNER_ADDRESS, INVALID_PAYLOAD, QR_GENERATION_FAILED, unexpected envelope, or HTTP failure. See errors.
confirmFaucet2FA
Confirms 2FA enrollment with a fresh TOTP code.
string
required
Owner address being confirmed.
string
required
Gas Station base URL.
string
required
Fresh 6-digit TOTP.
void on successful activation.
Errors: ValidationError on any empty argument. RuntimeError for INVALID_2FA, 2FA_NOT_CONFIGURED, 2FA_LOCKED, unexpected envelope, or transport failure.
fundFromGasStation
Sends gas tokens to a machine wallet. Returns a discriminated union on status.
string
required
2FA-enrolled owner (SS58 or hex).
string
required
Machine EOA to fund.
string
required
Faucet-configured chain identifier (e.g.,
"peaq").string
required
Current TOTP.
string
UUID idempotency key. Auto-generated if omitted.
FaucetFundSuccessResponse | FaucetFundSkippedResponse
Cross-SDK behavior: The JS SDK echoes
requestId back in both success and skipped responses. The Python SDK does not include request_id in the response at all — it is a request-side idempotency key only. Do not write code that reads requestId from the response and expects it to work in both SDKs.NFT & DID
Machine NFT minting, token-ID lookup, and the two canonical DID attribute writers. The DID writes batch six (machine) or two (proxy) attributes into a single atomicbatchAll transaction via the peaq Batch precompile.
mintNft
Mints a Machine NFT on the MachineNFT contract for a registered, bonded machine. Returns the transaction hash.
number
required
Registered machine ID. Must be a positive integer.
0x${string}
required
Address that will own the minted NFT.
tokenIdOf
Reads the NFT token ID assigned to a registered machine via a view call.
number
required
Registered machine ID. Must be a positive integer.
number
The NFT token ID, or
0 if no NFT has been minted for this machine.Cross-SDK behavior: The JS SDK returns
0 when no NFT has been minted for the machine. The Python SDK raises RpcError instead (the contract reverts). In polyglot codebases, check for 0 in JS and catch RpcError in Python — do not assume the same pattern works in both.writeMachineDIDAttributes
Atomically writes the six canonical Machine DID attributes (machineId, nftTokenId, operator, documentation_url, data_api, data_visibility) to the caller’s DID via a single batched transaction.
number
required
Registered machine ID.
number
required
NFT token ID assigned to the machine.
string
required
Operator DID reference. May be an empty string. ASCII, ≤ 2560 bytes.
string
required
Non-empty ASCII URL, ≤ 2560 bytes.
string
required
Non-empty ASCII URL for the machine’s data API, ≤ 2560 bytes.
'public' | 'private' | 'onchain'
required
Visibility setting.
writeProxyDIDAttributes
Atomically writes the two canonical Proxy DID attributes (machineId, machines) to the caller’s DID.
number
required
The proxy operator’s registered machine ID.
readonly number[]
required
Non-empty list of positive machine IDs managed by this proxy. The JSON-encoded array must be ≤ 2560 bytes.
readAttribute
Reads a single DID attribute directly from the peaq DID precompile. Most consumers should prefer the /machine/{did} API, which composes the full attribute set; this helper is the on-chain escape hatch.
Address
required
The DID account address whose attribute is being read (typically a machine address, but any DID-bearing EOA works).
string
required
Attribute key, e.g.
"machineId", "data_visibility", "machines".object
{ name: string; value: string; validity: number; created: bigint }. validity is 0 when the attribute has no expiry. Throws RuntimeError if the attribute does not exist on the precompile.encodeAddAttribute
Encodes ABI call data for the DID precompile’s addAttribute(didAccount, name, value, validFor) function. Useful when constructing smart-account executeBatch calls that touch the DID precompile alongside other contracts. writeMachineDIDAttributes and writeProxyDIDAttributes use this helper internally; reach for it directly only when composing custom batch flows.
Address
required
Address of the DID account being written. On-chain this must equal
msg.sender of the resulting precompile call.string
required
Attribute name. ASCII only, ≤ 64 bytes.
string
required
Attribute value. ASCII only, ≤ 2560 bytes.
number
required
Validity period in blocks.
0 means no expiry. Must be a non-negative integer in the uint32 range.string
ABI-encoded call data. Throws
ValidationError if any constraint is violated.Smart accounts
ERC-4337 smart accounts deployed via theMachineAccountFactory. Requires the client to be constructed with a machineAccountFactory address (or the MACHINE_ACCOUNT_FACTORY_ADDRESS env var via fromEnv).
deploySmartAccount
Deploys a smart account via MachineAccountFactory.createAccount and returns the deployed address.
Address
required
EOA that will own the smart account.
Address
required
Machine EOA the account is scoped to.
number
required
Non-negative CREATE2 salt.
getSmartAccountAddress
Read-only equivalent: computes the CREATE2 address for the given (owner, machine, salt) without deploying. Returns the same address deploySmartAccount would produce.
deploySmartAccount. No transaction, no gas.
Bridge
Supported routes: peaq ↔ Base. The peaq ↔ Solana lane is live on chain but not yet exposed here. In Tokenomics mode
bridgeNft throws MACHINE_RELOCATION_UNAVAILABLE: Economics 2.0 relocates whole machine records and is disabled on chain today. See Machine NFT cross-chain portability.machineNftAdapter address (or MACHINE_NFT_ADAPTER_ADDRESS) when sending from peaq. The SDK’s source / destination literal union expands as peer contracts deploy on new chains.
bridgeNft
Bridges a Machine NFT from source to destination. When source === "base", baseRpcUrl and baseNftAddress are required so the SDK can build a per-call viem client for the Base side.
On the peaq→Base path the SDK runs an ERC-721 approval pre-flight: it checks MachineNFT.getApproved(tokenId) and submits a one-shot approve(adapter, tokenId) if the token isn’t already cleared for the adapter. The Base→peaq path uses burn-and-unlock and needs no approval. Either way, callers don’t handle approvals themselves.
number
required
Positive NFT id to bridge.
'peaq' | 'base'
required
Origin chain.
'peaq' | 'base'
required
Target chain (must differ from
source).Address
required
Destination-chain recipient.
Hex
Raw LayerZero v2
extraOptions bytes. Defaults to "0x" (the contract’s enforced options).string
Base RPC URL. Required only when
source === "base".Address
MachineNFTBase address on Base. Required only when source === "base".Hex
The source-chain transaction hash.
waitForBridgeArrival
Static method that polls the destination chain’s MachineNFT.ownerOf(tokenId) every 10 seconds until a non-zero owner returns or the timeout elapses. No PeaqosClient instance required.
string
required
Destination-chain RPC endpoint.
Address
required
MachineNFT contract address on the destination.number
required
The NFT id expected to arrive.
number
Wait budget in seconds. Defaults to 300 (5 min).
AbortSignal
Optional abort signal. When aborted, the poll stops immediately with a
RuntimeError code ABORTED.Events (Qualify)
submitEvent
Submits a single event to EventRegistry. Validates and normalizes the payload, then calls the contract. Returns the transaction hash and the computed dataHash.
validateSubmitEventParams below. value is an ISO 4217 minor-unit integer (cents for USD/HKD, whole units for JPY/KRW/VND, thousandths for BHD). currency is required on revenue events (^[A-Z0-9]{3,10}$) and must be "" on activity events; the SDK applies a smart default (revenue → "USD", activity → "") when omitted on submitEvent. batchSubmitEvents is strict: every event must carry currency explicitly.
batchSubmitEvents
Submits multiple events atomically through the peaq Batch precompile. All events land in the same transaction: all succeed or all revert.
readonly SubmitEventParams[]
required
Non-empty list of event payloads. Each element is validated individually before submission.
Hex[]
One transaction hash per input event. All hashes are identical (same batch tx).
validateSubmitEventParams
number
required
Machine ID returned by
registerMachine / registerFor.0 | 1
required
0 revenue, 1 activity.number
required
Non-negative ISO 4217 minor-unit integer. Cents for USD/HKD, whole units for JPY/KRW/VND, thousandths for BHD. Activity events: any non-negative integer or
0.string
Revenue: 3-10 uppercase alphanumeric (e.g.
"USD", "HKD", "JPY"). Activity: must be "". Omit to apply the SDK smart default (revenue → "USD", activity → ""); batchSubmitEvents requires it explicitly.number
required
Unix seconds.
Uint8Array | null
required
Off-chain payload hashed into
dataHash.0 | 1 | 2
required
0 self-reported, 1 on-chain verifiable, 2 hardware-signed.number
required
Originating chain. Use
SUPPORTED_CHAIN_IDS.peaq for local.Hex | null
required
Cross-chain tx hash when applicable.
Uint8Array
required
Arbitrary bytes stored on-chain alongside the event. Use empty bytes when no metadata is needed.
void. Throws ValidationError on any invariant violation.
computeDataHash
Uint8Array
required
Off-chain payload bytes to hash.
keccak256 hash as 0x + 64 hex characters.
checkOperationalLimits
{ machineId: number; value: number }
required
Machine ID and event value.
OperationalLimits
required
Configured
maxValuePerTx, rateLimitMaxEvents, rateLimitWindowSeconds.EventTracker | null
required
Current rate-tracking state for the machine. Pass
null if you are not tracking window state. EventTracker is { machineId: number; count: number; windowStart: number }.void. Throws ValueCapExceeded or RateLimitExceeded on limit violation.
Queries
Read-only helpers backed by the off-chain MCR API server (client.apiUrl). Each function validates the DID, issues a single GET, and returns a frozen, shape-checked response. All three accept an optional GetJsonOptions with timeoutMs (default 30 000 ms) and a caller AbortSignal.
queryMcr
Fetches the Machine Credit Rating for a machine DID. See GET /mcr/{did}.
string
required
Machine DID.
did:peaq:0x<address> on a legacy client, did:peaq:<decimal machine id> on a tokenomics20 client (0.7.0+).number
Request budget in ms. Defaults to 30 000.
AbortSignal
Caller abort signal. Either signal aborting wins.
object
Frozen object with camelCase fields:
did, machineId, mcrScore (number, 0–100), mcr ("AAA" | "AA" | "A" | "BBB" | "BB" | "B" | "NR" | "Provisioned"), mcrDegraded (boolean: true when ≥1 scored event used a stale or unavailable FX source), bondStatus ("bonded" | "unbonded"), negativeFlag (boolean: true when the machine has been flagged for negative behaviour; consumers should down-rank or alert independently of the numeric score), eventCount, revenueEventCount, activityEventCount, revenueTrend ("up" | "stable" | "down" | "insufficient"), totalRevenue (integer USD cents; divide by 100 for display), averageRevenuePerEvent (USD cents as float; divide by 100 for display), lastUpdated (unix seconds or null).The MCR API returns
mcr_score: null while a machine is still Provisioned or has rating NR. The JS SDK coerces this to 0 so mcrScore is always a number.queryMachine
Fetches the full machine profile (NFT Metadata JSON v1.0) for a DID. The SDK strictly validates the response against MachineProfileResponse and throws BAD_RESPONSE for any missing or malformed required field. See GET /machine/{did}.
string
required
Machine DID.
did:peaq:0x<address> on a legacy client, did:peaq:<decimal machine id> on a tokenomics20 client (0.7.0+).GetJsonOptions
Optional
timeoutMs (default 30 000) and caller signal.object
Frozen, strictly-validated machine profile. Top-level fields:
schema_version (string) and name (string). The peaqos sub-object always carries machine_id, did, operator, mcr, mcr_score, bond_status, negative_flag, event_count, data_visibility, and documentation_url. Visibility-dependent extras: data_api, event_data, partner_data, partner_data_error. The SDK throws BAD_RESPONSE if the server returns anything that fails the schema guard. See GET /machine/{did} for full field semantics.queryOperatorMachines
Fetches the fleet of machines managed by a proxy operator. Each machine summary carries its DID, machine ID, score, rating tier, and negativeFlag; the response also includes pagination metadata. See GET /operator/{did}/machines.
string
required
Operator DID. Must start with
did:peaq:0x.GetJsonOptions
Optional
timeoutMs (default 30 000) and caller signal.object
Frozen object with
operatorDid, a frozen machines array, and a pagination object. Each machine entry exposes did, machineId, mcrScore (number, 0–100; null coerced to 0), mcr rating, and negativeFlag (boolean: true when the machine has been flagged for negative behaviour). pagination carries offset, limit, and total (all non-negative integers).Error classes
See errors for the full hierarchy and the 20-code faucet table.Type exports
All exported types
All exported types
Constants
Tokenomics 2.0 tiers and activation defaults
Tokenomics 2.0 tiers and activation defaults
Event types & trust levels
Event types & trust levels
DID attributes & limits
DID attributes & limits
Chain IDs & LayerZero endpoints
Chain IDs & LayerZero endpoints
Wallet import chains, key types & passphrase env
Wallet import chains, key types & passphrase env
IMPORT_CHAIN_* is the union behind the ImportChain type alias used by importWallet. KEY_TYPE_* matches the KeyType field on WalletInfo.OWS signing error codes
OWS signing error codes
PeaqosClient.fromWallet(..., owsSigning: true). The matching OwsSigningErrorCode type is the union of all five string-literal codes.
