EventRegistry program instead.
Any client submits events; EVENT_REGISTRY_ADDRESS decides whether they reach the Tokenomics 1.0 or the Economics 2.0 registry (see the warning below). machineId is a uint256 in both generations (bigint in JS): the Economics 2.0 machine ID, or the numeric IdentityRegistry ID of a Tokenomics 1.0 machine. From the terminal, peaqos qualify event --machine-id <decimal machine id> reaches the configured EventRegistry.
For a machine homed on Solana, events go to the Solana EventRegistry program, signed by the machine’s Solana owner or controller. The parameters and validation below apply there too; setup, cost and recovery differ: see Machines homed on Solana.
Event types
Trust levels
Each event carries a describing how the data was attested. See Trust levels for the concept overview.Currency and value units
currency is a first-class parameter on submitEvent / submit_event. Revenue events take a 3-10 char uppercase alphanumeric code (USD, HKD, JPY, …); activity events must pass "". On single-event submits an omitted currency defaults to "USD" for revenue and "" for activity: JS applies this on both chains, Python only for peaq-homed machines (a Solana-homed machine needs it explicitly in Python). batchSubmitEvents / batch_submit_events always requires it.
value is an ISO 4217 minor-unit integer:
The MCR converts 25 currencies:
USD, HKD, JPY, CNY, KRW, SGD, TWD, THB, PHP, MYR, IDR, VND, INR, EUR, GBP, CHF, SEK, NOK, DKK, PLN, CAD, AUD, NZD, MXN, BRL. Any other code the contract accepts (for example BHD or a token symbol) is stored on chain but adds no revenue.
The pipeline converts value to USD cents using the FX rate at timestamp. Only revenue events worth at least 1,000 USD cents ($10) after conversion are summed into total_revenue (USD cents) on GET /mcr/{did}. An event in a currency outside the supported list (unsupported_currency) or with no FX rate available (fx_unavailable) adds no USD revenue. When every FX source fails but the server holds an earlier stored rate for the currency pair, it converts the event at that stale rate and the revenue counts; for a machine homed on peaq, GET /mcr/{did} then returns mcr_degraded: true. "unsupported_currency" and "fx_unavailable" events do not set it.
Activity events ignore the FX path entirely. They don’t accumulate revenue.
Validation
CallvalidateSubmitEventParams (JS) or validate_submit_event_params (Python) before submitting. It throws ValidationError on the first invalid field, and a native TypeError when value is not an integer.
Validation rules
The messages above use the JS field names. Python prints the snake_case names (
event_type, trust_level, source_chain_id, raw_data, source_tx_hash).
The contract additionally rejects metadata larger than 4096 bytes with a MetadataTooLarge . The SDK validators don’t enforce this client-side, so oversized payloads surface as a failure rather than ValidationError: JS throws RuntimeError with code: "MetadataTooLarge", Python raises RpcError with code: "TX_REVERTED". For a Solana-homed machine the Solana EventRegistry program caps metadata at 256 bytes; currency follows the same 3 to 10 character rule.
Computing the data hash
The EventRegistry stores a of the raw data, not the data itself. Compute it withcomputeDataHash (JS) or compute_data_hash (Python).
dataHash field in the on-chain MachineEvent struct. Consumers who need to verify the original data compare its keccak256 against the stored hash.
Submitting a revenue event (type 0)
Submitting an activity event (type 1)
Activity events record operational telemetry with no direct revenue value.Machines homed on Solana
A machine homed on Solana takes its events on Solana: the SolanaEventRegistry program, signed by the machine’s Solana owner or controller, who also pays. Event types, trust levels, currency and value units are the same as on peaq. What differs:
- Endpoint. The CLI, both SDKs and the machine’s
.envneedPEAQOS_SVM_RPC_URL, the Solana endpoint the machine was onboarded with.from_env()/fromEnv()do not read it; the examples below build the client from the.envthemselves. - Signer. The OWS wallet holding the machine’s Solana owner or controller key. A peaq key signs nothing.
- Cost, in SOL. The first event for a machine pays rent for its event-log account (2,946,400 lamports measured) plus a 5,000-lamport network fee, about 0.003 SOL. Every later event pays the fee only.
- Gates. The signer must be the machine’s current owner or controller and its subscription must be eligible; the registry must not be paused and the machine not relocating. Python and the CLI check all of this in a preview before signing; JS checks it before signing too, but has no separate preview.
- Limits.
metadatais capped at 256 bytes (4,096 on peaq).timestampmust not be later than the Solana cluster’s clock.sourceChainId/source_chain_idis provenance only: any value is accepted, and the examples use0(same chain), as the CLI does. - Confirmation is not the MCR. The MCR indexes Solana events on its own schedule.
GET /mcr/{did}(peaqos qualify mcr) counted them within minutes in our runs. At the time of writing, the machine profile (peaqos show machine) and machines.peaq.xyz do not list them yet (event_history_not_indexed).
- CLI
- Python
- TypeScript
CLI 0.0.18 or newer, with The result names the Solana transaction:The full preview, the
pip install 'peaq-os-cli[solana,ows]'. 0.0.16 and 0.0.17 refuse a Solana-homed machine with MACHINE_HOMED_ELSEWHERE. Run it in the machine’s directory, with the .env it was onboarded with:--json fields and the --resume recovery are on the CLI page.Cross-chain revenue pattern
When a machine earns revenue on another (e.g., ), reference the source transaction for on-chain verifiable trust (level 1).Supported chain IDs
Operational limits
The SDK enforces per-transaction value caps and rate limits before submitting.
Set limits to
0 to disable (the default).
Error handling
submitEvent / submit_event raise four SDK error types, plus a native TypeError for a non-integer value. Validation and limit errors are local; RuntimeError (JS) / RpcError (Python) wraps every chain or RPC failure on peaq. A submission for a Solana-homed machine raises TokenomicsActivationError instead (JS also TokenomicsConfigError), which the handlers below do not catch. JS collapses chain and HTTP errors into a single RuntimeError; Python keeps them separate (RpcError for chain, ApiError for HTTP).
RuntimeError (JS) and RpcError/ApiError (Python).
Next steps
- Events concept for deeper coverage of event types and trust levels
- SDK reference for full method signatures

