peaq-os-sdk on PyPI is the Python equivalent of @peaqos/peaq-os-sdk. Every method and type mirrors the JS SDK; the key differences are listed below.
Differences from the JavaScript SDK
Install
- Python: ≥ 3.10
- Dependencies:
web3>=6.0,eth-account,requests - Optional wallet dependency:
open-wallet-standardthrough the[ows]extra - Virtualenv recommended.
python-dotenv is optional but recommended: PeaqosClient.from_env() reads from dotenv, so load_dotenv() at the top of your entry file is the simplest way to load .env.
Environment variables
Same set as the JS SDK: 8 required core vars (RPC URL, private key, and the 6 contract addresses), plusPEAQOS_MCR_API_URL (defaults to http://127.0.0.1:8000), plus 2 optional vars for smart-account deploy (MACHINE_ACCOUNT_FACTORY_ADDRESS) and cross-chain Machine NFT bridging (MACHINE_NFT_ADAPTER_ADDRESS). See JS environment variables and peaq mainnet contracts. For agung testnet addresses see Install → Agung testnet contracts. Bridging is mainnet-only since LayerZero has no DVN routes to agung.
For OWS wallet lifecycle helpers, pass a passphrase argument or set OWS_PASSPHRASE.
For Scale, set PEAQOS_ORCHESTRATION_URL (and optionally PEAQOS_API_KEY) before PeaqosClient.from_env() to enable client.orchestration. Full method reference: Orchestration (Python).
Client
PeaqosClient
str
required
RPC endpoint.
str
required
0x + 64 hex.str
required
Identity Registry contract address.
str
required
Identity Staking contract address.
str
required
Event Registry contract address.
str
required
Machine NFT contract address (ONFT).
str
required
DID Registry precompile address.
str
required
Batch precompile address.
str | None
MachineAccountFactory contract address. Required only for deploy_smart_account and get_smart_account_address.str | None
MachineNFTAdapter (LayerZero ONFT adapter) contract address on peaq. Required only for bridge_nft when source="peaq".str
MCR API base URL. Defaults to
DEFAULT_API_URL.OperationalLimits | None
Per-tx and rate-limit caps.
PeaqosClient instance. __repr__ redacts the private key.
Other RPC endpoints are available. See Public RPC endpoints.
Errors: ValidationError: missing/invalid constructor args.
from_env
ValidationError: any required env var missing or empty.
from_wallet
PeaqosClient.fromWallet. The remaining keyword arguments (rpc_url, contract addresses, etc.) match the regular PeaqosClient constructor.
In OWS-native mode the SDK never holds the private key — OWS decrypts it inside the Rust FFI for each
sign_hash call and wipes it immediately. The passphrase is verified eagerly: a wrong or missing one raises PeaqosError at construction. Each transaction’s chainId (from the tx dict) drives both the CAIP-2 OWS arg and the EIP-155 v value, so the same client transparently signs both peaq (eip155:3338) and Base (eip155:8453) bridge transactions.
Errors: PeaqosError when the wallet is missing, the passphrase is wrong (eager-mode) or missing, or OWS itself rejects the request. See OWS signing error codes for the canonical 5 codes mapped from OWSAccount.sign_transaction.
Wallets (OWS)
Wallet lifecycle helpers (create_wallet, import_wallet, import_wallet_mnemonic, list_wallets, get_wallet, export_wallet, delete_wallet) back the Open Wallet Standard integration: mnemonic-backed encrypted vault, multi-chain accounts (peaq, Base, Ethereum, Solana, Bitcoin, etc.). Available under peaq_os_sdk.wallet and as @staticmethods on PeaqosClient. Install with the optional [ows] extra (pip install 'peaq-os-sdk[ows]'). The raw-key constructor and from_env flow keep working unchanged. Full reference on the Wallets page.
Wallet returns are typed as WalletInfo (frozen dataclass) with an accounts: list[AccountInfo] field. AccountInfo carries account_id (CAIP-10), address, chain_id (CAIP-2), network (human-readable name like "peaq", "base", "ethereum", "solana"), and derivation_path. The SDK synthesizes accounts for every supported EVM chain from the first EVM source returned by OWS: peaq, ethereum, base, polygon, arbitrum, and optimism all surface in accounts even when OWS only returns one EVM key. Both classes are re-exported from the package root.
generate_keypair
(address, private_key). Both are 0x-prefixed hex strings; Address is a NewType over str (checksummed).
OWS wallet lifecycle
OWS wallet helpers are available as staticPeaqosClient methods. They derive multi-chain accounts, keep wallet material in an encrypted OWS vault, and return public WalletInfo metadata.
peaq-os-sdk[ows] before using these helpers. create_wallet, import_wallet, import_wallet_mnemonic, and export_wallet require a passphrase argument or OWS_PASSPHRASE. vault_path can point at a custom OWS vault directory.
dataclass
Frozen dataclass with
id, name, created_at, key_type, peaq_address, and accounts. Each account has account_id, address, chain_id, network, and derivation_path. Supported EVM accounts include peaq, Ethereum, Base, Polygon, Arbitrum, and Optimism; missing EVM chain entries are synthesized from the first available EVM address.Accessors (Python-only)
Registration
register_machine
machine_id. The SDK decodes it from the Registered event in the transaction receipt. 1 PEAQ is sent as msg.value: the payable register() function auto-bonds the machine.
Errors: RpcError: chain revert (AlreadyRegistered), insufficient balance for gas + 1 PEAQ bond, or any other on-chain failure. See errors.
register_for
str
required
Machine EOA to register. The caller acts as proxy operator.
machine_id for the proxied machine. 1 PEAQ is sent as msg.value.
Errors: ValidationError on invalid machine_address. RpcError on chain revert (AlreadyRegistered, InvalidMachineAddress).
Gas Station
setup_faucet_2fa
str
required
Owner to enroll.
str
required
Gas Station base URL.
'svg' | 'png'
QR format. Defaults to
"svg".TypedDict
Keys:
owner_address: str, otpauth_uri: str (OTP auth URI for authenticator apps), qr_image_url: str (expires after ~2 minutes).ValidationError if owner_address or faucet_base_url is empty. ApiError for INVALID_OWNER_ADDRESS, QR_GENERATION_FAILED, NETWORK_ERROR, or an unexpected response envelope. See errors.
confirm_faucet_2fa
ValidationError, ApiError (INVALID_2FA, 2FA_NOT_CONFIGURED, 2FA_LOCKED).
fund_from_gas_station
str
required
2FA-enrolled owner address.
str
required
Machine EOA to fund.
str
required
Chain identifier configured on the faucet, e.g.
"peaq".str
required
Current TOTP.
str
required
Gas Station base URL.
str | None
UUID idempotency key. Auto-generated if omitted.
union
Discriminated union on
status. Either a FundedResponse ({status: "success", tx_hash: str, funded_amount: str}, funded_amount is decimal wei) or a SkippedResponse ({status: "skipped", current_balance: str, min_gas_balance: str}). request_id is a request-side idempotency key passed by the caller; the response does not echo it back.Cross-SDK behavior: The Python SDK does not include
request_id in the response. The JS SDK echoes requestId back in both success and skipped responses. Do not write code that reads requestId / request_id from the response and expects it to work in both SDKs.ValidationError, ApiError (any of the 20 faucet codes). See errors.
NFT & DID
Machine NFT minting, token-ID lookup, and the two canonical DID attribute writers. The DID writes are submitted as a single atomicbatchAll transaction via the peaq Batch precompile.
mint_nft
Mints a Machine NFT on the MachineNFT contract for a registered, bonded machine.
int
required
Registered machine ID. Must be a positive integer.
str
required
0x-prefixed 20-byte hex address that will receive the NFT.str
Transaction hash as a
0x-prefixed hex string.ValidationError on non-positive machine_id or invalid recipient. RpcError on chain revert (MachineNotBonded, AlreadyMinted, NotMachineOwner) or transaction failure.
token_id_of
Reads the NFT token ID assigned to a registered machine via a view call.
int
required
Registered machine ID. Must be a positive integer.
int
The NFT token ID, as a positive integer.
ValidationError if machine_id is not positive. RpcError when the machine has no NFT minted (contract reverts).
Cross-SDK behavior: The Python SDK raises
RpcError when no NFT has been minted for the machine (contract reverts). The JS SDK returns 0 instead. In polyglot codebases, catch RpcError in Python and check for 0 in JS — do not assume the same pattern works in both.write_machine_did_attributes
Atomically writes the six canonical Machine DID attributes to the caller’s DID via a single batchAll transaction.
int
required
Registered machine ID.
int
required
NFT token ID assigned to the machine.
str
required
Operator DID reference. May be an empty string. ASCII, ≤ 2560 bytes.
str
required
Non-empty ASCII URL, ≤ 2560 bytes.
str
required
Non-empty ASCII URL for the machine’s data API, ≤ 2560 bytes.
'public' | 'private' | 'onchain'
required
Visibility setting.
write_proxy_did_attributes
Atomically writes the two canonical Proxy DID attributes (machineId, machines) to the caller’s DID.
int
required
The proxy operator’s registered machine ID.
list[int]
required
Non-empty list of positive machine IDs. The JSON-encoded array must be ≤ 2560 bytes.
read_attribute
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. Not exported from the package root: import from peaq_os_sdk.did.did_precompile.
str
required
The machine address whose DID is being read.
str
required
Attribute key, e.g.
"machineId", "data_visibility", "machines".TypedDict
Keys:
name: str, value: str, validity: int (seconds; 0 = no expiry), created: int (block timestamp). Raises RpcError if the attribute does not exist on the precompile.Smart accounts
ERC-4337 smart accounts deployed via theMachineAccountFactory. Requires the client to be constructed with machine_account_factory (or MACHINE_ACCOUNT_FACTORY_ADDRESS when using from_env).
deploy_smart_account
Deploys a smart account via MachineAccountFactory.createAccount and returns the deployed address.
str
required
EOA that will own the smart account.
str
required
Machine EOA the account is scoped to.
int
required
Non-negative CREATE2 salt.
ValidationError on invalid param or client constructed without machine_account_factory. RpcError on revert or missing AccountCreated event.
get_smart_account_address
Read-only equivalent: computes the CREATE2 address without deploying. Identical result to deploy_smart_account for the same inputs.
deploy_smart_account. No transaction, no gas.
Bridge
Supported routes: peaq ↔ Base. Additional peaqOS chains are added as peer contracts deploy. See Machine NFT cross-chain portability.
machine_nft_adapter (or MACHINE_NFT_ADAPTER_ADDRESS) when sending from peaq. The SDK’s source / destination string union expands as peer contracts deploy on new chains.
bridge_nft
Bridges a Machine NFT from source to destination.
On the peaq→Base path the SDK runs an ERC-721 approval pre-flight: it reads MachineNFT.getApproved(token_id) and submits a one-shot approve(adapter, token_id) if the token isn’t already cleared for the adapter. The Base→peaq path uses burn-and-unlock and needs no approval. Callers don’t handle approvals themselves.
int
required
Positive NFT id to bridge.
'peaq' | 'base'
required
Origin chain.
'peaq' | 'base'
required
Target chain. Must differ from
source.str
required
Destination-chain recipient address.
str | None
Base RPC URL. Required only when
source == "base".str | None
MachineNFTBase address on Base. Required only when source == "base".bytes
Raw LayerZero v2
extraOptions bytes.wait_for_bridge_arrival
Static method that polls the destination chain’s MachineNFT.ownerOf(token_id) every 10 seconds until a non-zero owner returns or the timeout elapses. Does not require a client instance.
str
required
Destination-chain RPC endpoint.
str
required
MachineNFT contract address on the destination.int
required
The NFT id expected to arrive.
int
Wait budget in seconds. Defaults to 300 (5 min).
Events (Qualify)
submit_event
Submits a single event to EventRegistry. Returns (tx_hash, data_hash).
validate_submit_event_params below.
value is an ISO 4217 minor-unit integer: cents for USD/HKD, whole units for JPY/KRW/VND, thousandths for BHD. The MCR pipeline FX-normalizes to USD cents using the rate at timestamp. currency is a 3-10 char uppercase alphanumeric code on revenue events and "" on activity events; omitting the kwarg applies the smart default. batch_submit_events is strict: currency must be supplied per event.
tuple[str, bytes]
tx_hash is a 0x-prefixed hash string; data_hash is exactly 32 bytes.ValidationError, ValueCapExceeded, RateLimitExceeded, RpcError.
batch_submit_events
Submits multiple events atomically through the peaq Batch precompile. All succeed or all revert.
list[dict | SubmitEventParams]
required
Non-empty list of event payloads. Items may be
SubmitEventParams instances or dicts with matching keys.list[str]
One transaction hash per input event. All hashes are identical (same batch tx).
ValidationError on empty list or invalid event. ValueCapExceeded / RateLimitExceeded when operational limits hit. RpcError on revert or transport failure.
validate_submit_event_params
SubmitEventParams is a frozen dataclass (imported from peaq_os_sdk.types.events):
SubmitEventParams instance. Dict literals will raise AttributeError.
Errors: ValidationError: any field out of range.
compute_data_hash
keccak256 digest of raw_data. Pair with submit_event’s data_hash output (also bytes) to compare on-chain payloads.
check_operational_limits
SubmitEventParams
required
Event with
machine_id and value.OperationalLimits
required
Configured
max_value_per_tx, rate_limit_max_events, rate_limit_window_seconds.EventTracker | None
required
Current rate-tracking state for the machine, or
None when tracking is disabled.ValueCapExceeded if value > max_value_per_tx. RateLimitExceeded when the event window is exceeded.
Queries
Read-only helpers backed by the off-chain MCR API server (client.api_url). Each function validates the DID, issues a single GET through client.session, and returns a shape-checked TypedDict. The default per-request timeout is 30 seconds, enforced inside peaq_os_sdk.query.http_client.get_json; the public query_* functions do not currently expose an override.
query_mcr
Fetches the Machine Credit Rating for a machine DID. See GET /mcr/{did}.
str
required
Machine DID. Must start with
did:peaq:0x.TypedDict
Snake_case keys:
did: str, machine_id: int, mcr_score: int (0–100), mcr: str ("AAA" | "AA" | "A" | "BBB" | "BB" | "B" | "NR" | "Provisioned"), bond_status: str ("bonded" | "unbonded"), negative_flag: bool, event_count: int, revenue_event_count: int, activity_event_count: int, revenue_trend: str ("up" | "stable" | "down" | "insufficient"), total_revenue: float (USD cents; divide by 100 for display), average_revenue_per_event: float (USD cents; divide by 100 for display), last_updated: int | None, mcr_degraded: bool (true when ≥1 scored event used a stale or unavailable FX source).mcr_score is always an int. The SDK coerces a null score from the API to 0. Provisioned machines (bonded but not yet scored) surface as 0, matching the JavaScript SDK.ValidationError if did does not start with did:peaq:0x. ApiError with code in NOT_FOUND (HTTP 404), SERVICE_UNAVAILABLE (503), SERVER_ERROR (other 5xx), HTTP_ERROR (other non-2xx), BAD_RESPONSE (malformed body), TIMEOUT, NETWORK_ERROR.
query_machine
Fetches the full machine profile (NFT Metadata JSON v1.0) and validates the response shape against a strict TypedDict. The SDK raises BAD_RESPONSE if the server payload does not match the schema. See GET /machine/{did}.
str
required
Machine DID. Must start with
did:peaq:0x.TypedDict
Top-level keys:
schema_version: str, name: str, peaqos: PeaqosData. PeaqosData always carries machine_id: int, did: str, operator: str | None, mcr: str, mcr_score: int, bond_status: str, negative_flag: bool, event_count: int, data_visibility: str, documentation_url: str | None. Visibility-dependent extras (data_api: str, event_data: list[EventEntry], partner_data: dict[str, Any], partner_data_error: str) are present only when the API includes them. Use "data_api" in profile["peaqos"] (etc.) to test for presence rather than truthiness.ValidationError on invalid DID. ApiError with the same codes as query_mcr; BAD_RESPONSE if any required field is missing, has the wrong type, or is out of range.
query_operator_machines
Fetches the fleet of machines managed by a proxy operator. Each entry is individually validated. See GET /operator/{did}/machines.
str
required
Operator DID. Must start with
did:peaq:0x.TypedDict
Keys:
operator_did: str, machines: list[OperatorMachine], and pagination: Pagination. Each OperatorMachine has did: str, machine_id: int, mcr_score: int (0–100), mcr: str, and negative_flag: bool. Pagination carries offset: int, limit: int, and total: int.ValidationError on invalid DID. ApiError with the same codes as query_mcr; BAD_RESPONSE if the body or any machines entry is malformed.
Error classes
Constants
Machine status
Machine status
MCR ratings (Python-only)
MCR ratings (Python-only)
Event types, trust levels & chain IDs
Event types, trust levels & chain IDs
Identical to the JS SDK:
EVENT_TYPE_REVENUE, EVENT_TYPE_ACTIVITY, TRUST_SELF_REPORTED, TRUST_ON_CHAIN_VERIFIABLE, TRUST_HARDWARE_SIGNED, DID_ATTR_*, DID_MAX_NAME_BYTES, DID_MAX_VALUE_BYTES, SUPPORTED_CHAINS, LAYERZERO_EIDS, DEFAULT_API_URL. Same values, Python-idiomatic names.Data visibility (Python-only)
Data visibility (Python-only)
data_visibility= on write_machine_did_attributes. Validated server-side; using one of these constants avoids typos.Wallet import chains & passphrase env
Wallet import chains & passphrase env
import_wallet(..., chain=IMPORT_CHAIN_SOLANA). The JS SDK exports identical constants. See JS Constants.
