Skip to main content
Revenue events (type 0) and activity events (type 1) feed the Machine Credit Rating. Every is validated client-side, hashed, and submitted to the EventRegistry contract. A machine homed on Solana submits to the Solana 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.
Set EVENT_REGISTRY_ADDRESS to 0xA1e7F1d7B24dAb55Dc92491e6d9B89F6E925Ad1e for Economics 2.0 machines and 0x43c6AF2E14dc1327dc3cc6c7117D1CD72fffEcbA for Tokenomics 1.0 machines. Both contracts share the submitEvent selector, so the SDK cannot catch a wrong address before sending: the 1.0 contract does not hold 2.0 machine IDs, reverts with MachineNotFound, and the event is not recorded.
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

Call validateSubmitEventParams (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 with computeDataHash (JS) or compute_data_hash (Python).
The hash is passed as the 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 Solana EventRegistry 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 .env need PEAQOS_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 .env themselves.
  • 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. metadata is capped at 256 bytes (4,096 on peaq). timestamp must not be later than the Solana cluster’s clock. sourceChainId / source_chain_id is provenance only: any value is accepted, and the examples use 0 (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 0.0.18 or newer, with 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:
The result names the Solana transaction:
The full preview, the --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).
See SDK errors reference for the full code map and the cross-language equivalence between RuntimeError (JS) and RpcError/ApiError (Python).

Next steps