> ## Documentation Index
> Fetch the complete documentation index at: https://docs.peaq.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Events

> Revenue and activity events that feed a machine's credit history.

Events are the atomic units of a machine's financial history. The EventRegistry contract stores them onchain; the MCR scoring pipeline reads them to compute credit ratings.

## Two event types

| Type     | Value | Description                                                                                                                                                                                                                                                                                                                                                                                          |
| :------- | :---- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Revenue  | `0`   | The machine earned money. `value` carries the amount as a minor-unit integer (cents for USD/HKD, whole units for JPY/KRW) in the event's `currency`; the MCR scoring pipeline normalizes to USD cents via FX at the event timestamp. Single-event `submitEvent` resolves an omitted `currency` to `"USD"` for revenue and `""` for activity; batch submit requires an explicit `currency` per event. |
| Activity | `1`   | The machine performed an action (telemetry, data generation, task completion). `value` may be 0. `currency` must be empty (`""`); non-empty currency on an activity event reverts `InvalidCurrencyShape`.                                                                                                                                                                                            |

Both SDKs export these as constants:

<CodeGroup>
  ```typescript JS/TS theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
  import {
    EVENT_TYPE_REVENUE,  // 0
    EVENT_TYPE_ACTIVITY, // 1
  } from "@peaqos/peaq-os-sdk";
  ```

  ```python Python theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
  from peaq_os_sdk.constants import (
      EVENT_TYPE_REVENUE,  # 0
      EVENT_TYPE_ACTIVITY, # 1
  )
  ```
</CodeGroup>

## MachineEvent schema

Every event stored in the EventRegistry follows this structure:

The SDKs expose the stored struct as `MachineEvent` (with `dataHash` / `data_hash` as a 32-byte `keccak256`). The SDK input type `SubmitEventParams` takes `rawData` / `raw_data` bytes instead; the SDK computes the hash for you before the call.

| Field           | Type      | Description                                                                                                                                                                                                                                                    |
| :-------------- | :-------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `machineId`     | `uint256` | Machine identity from IdentityRegistry. Primary key linking event to machine.                                                                                                                                                                                  |
| `eventType`     | `uint8`   | `0` = revenue, `1` = activity.                                                                                                                                                                                                                                 |
| `value`         | `uint256` | Amount earned (revenue) or metric value (activity). May be 0 for activity events. Revenue events express `value` as an ISO 4217 minor-unit integer (cents for USD/HKD, whole units for JPY/KRW) in the event's `currency`.                                     |
| `currency`      | `string`  | Revenue events: 3-10 char uppercase alphanumeric ISO 4217 code (e.g. `"USD"`, `"HKD"`, `"JPY"`). Activity events: empty string `""`. Validated on-chain.                                                                                                       |
| `timestamp`     | `uint256` | Unix timestamp when the event occurred, not when it was submitted.                                                                                                                                                                                             |
| `dataHash`      | `bytes32` | `keccak256(raw_data)`. Raw data stays off-chain; hash proves integrity.                                                                                                                                                                                        |
| `trustLevel`    | `uint8`   | `0` = self-reported, `1` = on-chain verifiable, `2` = hardware-signed.                                                                                                                                                                                         |
| `sourceChainId` | `uint256` | Chain where the original activity occurred (e.g., 3338 for peaq, 8453 for Base). 0 for off-chain events.                                                                                                                                                       |
| `sourceTxHash`  | `bytes32` | Transaction hash on the source chain. Combined with `sourceChainId`, creates a verifiable cross-chain link. Null for off-chain events.                                                                                                                         |
| `metadata`      | `bytes`   | Arbitrary bytes stored on-chain alongside the event (4096-byte cap). The MCR API server parses JSON metadata into the `event_data[].metadata` object surfaced on `/machine/{did}` for machines with `data_visibility: onchain`; the SDK only writes raw bytes. |

## Cross-chain revenue accounting

`sourceChainId` and `sourceTxHash` together form a cross-chain audit trail. When a machine earns revenue on Base, the proxy submits the event to the EventRegistry on peaq with `sourceChainId = 8453` and the Base transaction hash. Any verifier can look up the transaction on the source chain and confirm the event happened.

| Scenario               | `sourceChainId` | `sourceTxHash`        |
| :--------------------- | :-------------- | :-------------------- |
| Revenue earned on Base | `8453`          | Base transaction hash |
| Revenue earned on peaq | `3338`          | peaq transaction hash |
| Off-chain telemetry    | `0`             | null (`bytes32(0)`)   |

## Data integrity via `dataHash`

Raw event data stays with the project (in their database, behind their API). The `dataHash` stored onchain is `keccak256(raw_data)`, computed by the SDK before submission. This keeps gas costs at 32 bytes per event regardless of payload size, while anyone can fetch the raw data from the project's `data_api` (set in the machine's DID) and verify `keccak256(fetched_data) == dataHash`.

<CodeGroup>
  ```typescript JS/TS theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
  import { computeDataHash } from "@peaqos/peaq-os-sdk";

  const rawData = new Uint8Array([1, 2, 3]);
  const hash = computeDataHash(rawData);
  // hash === "0x..." (keccak256)
  ```

  ```python Python theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
  from peaq_os_sdk.utils import compute_data_hash

  raw_data = b"revenue data"
  data_hash = compute_data_hash(raw_data)
  # data_hash is 32 bytes (keccak256)
  ```
</CodeGroup>

## Authorization

EventRegistry reads IdentityRegistry to verify submit authority. `msg.sender` must be one of:

| Path           | Address                      | Use case                                                                                                              |
| :------------- | :--------------------------- | :-------------------------------------------------------------------------------------------------------------------- |
| NFT owner      | Identity NFT holder          | The account that holds the Identity NFT submits directly.                                                             |
| Machine wallet | `machineWalletOf(machineId)` | The machine's registered wallet submits. Typical for self-managed flows where the machine signs its own transactions. |
| Operator       | `operatorOf(machineId)`      | Assigned operator submits on behalf of the machine. Only valid when an operator has been set (non-zero).              |

All three paths produce identical on-chain records: the `machineId` in the stored event always identifies the machine, regardless of who submitted.

## Validation

The JS SDK exports `validateSubmitEventParams`, which checks all nine fields before any chain interaction:

```typescript theme={"theme":{"light":"github-light-default","dark":"github-dark"}}
import { validateSubmitEventParams } from "@peaqos/peaq-os-sdk";

validateSubmitEventParams({
  machineId: 1,
  eventType: 0,
  value: 100,                  // $1.00 in cents
  currency: "USD",
  timestamp: Math.floor(Date.now() / 1000),
  rawData: new Uint8Array([1, 2, 3]),
  trustLevel: 1,
  sourceChainId: 8453,
  sourceTxHash: "0xabc...def",
  metadata: new Uint8Array([]),
});
```

Key validation rules:

* `eventType` must be 0 or 1
* `value` must be a non-negative integer (subunit, per ISO 4217 minor units)
* `trustLevel` must be 0, 1, or 2
* `sourceChainId` must be a supported chain (0, 3338, or 8453)
* When `trustLevel` is 1 (on-chain verifiable), `sourceTxHash` is required
* `rawData` must be non-empty when provided (null is allowed, empty array is not)
* `currency` on revenue events must match `^[A-Z0-9]{3,10}$`; on activity events it must be `""`
* `timestamp` must be a positive integer; the EventRegistry contract additionally rejects `timestamp > block.timestamp` (`FutureTimestamp` revert)
* `metadata` is capped at 4096 bytes on-chain (`MetadataTooLarge` revert above the limit)

## Cross-links

* [JS SDK `validateSubmitEventParams`](/peaqos/sdk-reference/sdk-js#validatesubmiteventparams) documents every validation rule
* [JS SDK `computeDataHash`](/peaqos/sdk-reference/sdk-js#computedatahash) documents the hashing utility
* [Machine Credit Rating](/peaqos/concepts/machine-credit-rating) shows how events feed into a machine's credit history
