Files
proxmox/docs/schemas/event-schema-v1.md
defiQUG fbda1b4beb
Some checks failed
Deploy to Phoenix / deploy (push) Has been cancelled
docs: Ledger Live integration, contract deploy learnings, NEXT_STEPS updates
- ADD_CHAIN138_TO_LEDGER_LIVE: Ledger form done; public code review repo bis-innovations/LedgerLive; init/push commands
- CONTRACT_DEPLOYMENT_RUNBOOK: Chain 138 gas price 1 gwei, 36-addr check, TransactionMirror workaround
- CONTRACT_*: AddressMapper, MirrorManager deployed 2026-02-12; 36-address on-chain check
- NEXT_STEPS_FOR_YOU: Ledger done; steps completable now (no LAN); run-completable-tasks-from-anywhere
- MASTER_INDEX, OPERATOR_OPTIONAL, SMART_CONTRACTS_INVENTORY_SIMPLE: updates
- LEDGER_BLOCKCHAIN_INTEGRATION_COMPLETE: bis-innovations/LedgerLive reference

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-12 15:46:57 -08:00

209 lines
8.7 KiB
Markdown

# Normalized Event Schema v1
**Last Updated:** 2026-01-31
**Document Version:** 1.0
**Status:** Active Documentation
---
**Purpose:** Canonical schema for EII (Event Ingestion + Indexing), SAL (State & Accounting Ledger), and Mirroring Service. All chains (138, 651940, public mainnets) use this schema for blocks, transactions, receipts, logs, decoded_events, and execution_steps.
**Version:** 1.0
**Status:** Active
---
## 1. Design principles
- Append-only event store; no in-place updates.
- Every entity has `chain_id`, `created_at` (ingestion time).
- Hashes and addresses are lowercase hex with `0x` prefix.
- Optional fields may be null; required fields are non-null.
---
## 2. Blocks
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| chain_id | integer | yes | EVM chain ID (138, 651940, 1, etc.) |
| number | bigint | yes | Block number |
| hash | string(66) | yes | Block hash (0x + 64 hex) |
| parent_hash | string(66) | yes | Parent block hash |
| state_root | string(66) | no | State root |
| receipts_root | string(66) | no | Receipts root (for commitment leaves) |
| transactions_root | string(66) | no | Transactions root |
| miner | string(42) | no | Miner/validator address |
| difficulty | string | no | Block difficulty (numeric string) |
| total_difficulty | string | no | Total difficulty |
| size | bigint | no | Block size in bytes |
| gas_limit | bigint | yes | Gas limit |
| gas_used | bigint | yes | Gas used |
| timestamp | bigint | yes | Unix timestamp (seconds) |
| base_fee_per_gas | bigint | no | EIP-1559 base fee |
| transaction_count | integer | no | Number of transactions |
| extra_data | string | no | Extra data (hex) |
| created_at | string (ISO8601) | yes | Ingestion timestamp |
**Unique:** `(chain_id, number)`
**Indexes:** `(chain_id, number)`, `(chain_id, hash)`, `(chain_id, timestamp)`
---
## 3. Transactions
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| chain_id | integer | yes | EVM chain ID |
| hash | string(66) | yes | Transaction hash |
| block_number | bigint | yes | Block number |
| block_hash | string(66) | yes | Block hash |
| transaction_index | integer | yes | Index within block |
| from_address | string(42) | yes | Sender |
| to_address | string(42) | no | Recipient (null for contract creation) |
| value | string | yes | Value in wei (decimal string) |
| gas_price | bigint | no | Legacy gas price |
| max_fee_per_gas | bigint | no | EIP-1559 max fee |
| max_priority_fee_per_gas | bigint | no | EIP-1559 priority fee |
| gas_limit | bigint | yes | Gas limit |
| gas_used | bigint | no | Gas used (from receipt) |
| nonce | bigint | yes | Sender nonce |
| input_data | string | no | Calldata (hex) |
| status | integer | no | 0 = failed, 1 = success |
| contract_address | string(42) | no | Created contract (if creation) |
| cumulative_gas_used | bigint | no | From receipt |
| effective_gas_price | bigint | no | Actual gas price paid |
| created_at | string (ISO8601) | yes | Ingestion timestamp |
**Unique:** `(chain_id, hash)`
**Indexes:** `(chain_id, hash)`, `(chain_id, block_number, transaction_index)`, `(chain_id, from_address)`, `(chain_id, to_address)`
---
## 4. Receipts
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| chain_id | integer | yes | EVM chain ID |
| transaction_hash | string(66) | yes | Transaction hash |
| transaction_index | integer | yes | Index in block |
| block_number | bigint | yes | Block number |
| block_hash | string(66) | yes | Block hash |
| from_address | string(42) | yes | Sender |
| to_address | string(42) | no | Recipient |
| gas_used | bigint | no | Gas used |
| cumulative_gas_used | bigint | no | Cumulative gas |
| contract_address | string(42) | no | Created contract |
| logs_bloom | string | no | Logs bloom (hex) |
| status | integer | no | 0 = failed, 1 = success |
| root | string(66) | no | Pre-Byzantium state root |
| created_at | string (ISO8601) | yes | Ingestion timestamp |
**Unique:** `(chain_id, transaction_hash)`
**Indexes:** `(chain_id, transaction_hash)`, `(chain_id, block_number)`
---
## 5. Logs
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| chain_id | integer | yes | EVM chain ID |
| transaction_hash | string(66) | yes | Transaction hash |
| block_number | bigint | yes | Block number |
| block_hash | string(66) | yes | Block hash |
| log_index | integer | yes | Index within transaction |
| address | string(42) | yes | Contract address |
| topic0 | string(66) | no | Event signature hash |
| topic1 | string(66) | no | First indexed parameter |
| topic2 | string(66) | no | Second indexed parameter |
| topic3 | string(66) | no | Third indexed parameter |
| data | string | no | Non-indexed data (hex) |
| created_at | string (ISO8601) | yes | Ingestion timestamp |
**Unique:** `(chain_id, transaction_hash, log_index)`
**Indexes:** `(chain_id, transaction_hash)`, `(chain_id, address)`, `(chain_id, topic0)`, `(chain_id, block_number)`, `(chain_id, address, topic0)`
---
## 6. Decoded events
Decoded view of logs when ABI is available. Used for indexing and for commitment leaf payload hash.
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| chain_id | integer | yes | EVM chain ID |
| transaction_hash | string(66) | yes | Transaction hash |
| block_number | bigint | yes | Block number |
| log_index | integer | yes | Log index |
| address | string(42) | yes | Contract address |
| event_signature | string | yes | e.g. Transfer(address,address,uint256) |
| event_name | string | yes | e.g. Transfer |
| decoded_params | object | yes | Key-value of decoded parameters |
| payload_hash | string(66) | no | keccak256(canonical_json(decoded_params)) for commitment leaf |
| created_at | string (ISO8601) | yes | Ingestion timestamp |
**Unique:** `(chain_id, transaction_hash, log_index)`
**Indexes:** `(chain_id, address)`, `(chain_id, event_name)`, `(chain_id, block_number)`
**Canonical encoding for payload_hash:** Sort keys of `decoded_params` alphabetically; encode as JSON without whitespace; hash with keccak256.
---
## 7. Execution steps
Links intents/executions to on-chain transactions. Used by EO and for SAL reconciliation.
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| execution_id | string(UUID) | yes | Execution run ID |
| intent_id | string(UUID) | yes | Intent ID |
| step_index | integer | yes | Order of step (0-based) |
| step_type | string | yes | transfer, swap, bridge, message_send, message_receive, mint, burn |
| chain_id | integer | yes | Chain where tx was submitted |
| transaction_hash | string(66) | no | Tx hash once submitted |
| status | string | yes | pending, submitted, confirmed, finalized, failed |
| preconditions | string | no | JSON array of precondition IDs |
| postconditions | string | no | JSON array of postcondition IDs |
| gas_used | bigint | no | Filled after confirmation |
| created_at | string (ISO8601) | yes | Created timestamp |
| updated_at | string (ISO8601) | yes | Last update |
**Unique:** `(execution_id, step_index)`
**Indexes:** `(execution_id)`, `(intent_id)`, `(chain_id, transaction_hash)`, `(status)`
---
## 8. SAL journal entry hash (optional for commitment leaf)
For Merkle commitment leaves, a leaf may include the hash of the SAL journal entry that corresponds to this transaction (if any). Schema for the hash input:
- **Input to hash:** `ledger_id || entry_id || debit_account_id || credit_account_id || amount || currency_code || reference_id || timestamp_utc`
- **Encoding:** Concatenate as UTF-8 strings with a single delimiter (e.g. `|`); then keccak256.
- **Field in commitment leaf:** `sal_journal_entry_hash` (bytes32), optional; null if no ledger entry.
---
## 9. Commitment leaf (Merkle tree)
Each leaf in the mirroring Merkle tree is built from:
| Field | Source | Description |
|-------|--------|-------------|
| tx_hash | transactions.hash | Transaction hash |
| block_number | blocks.number | Block number |
| receipt_root or logs_bloom | receipts / blocks | Receipt root or logs bloom (chain-dependent) |
| normalized_event_payload_hash | decoded_events.payload_hash | Hash of decoded event payload (or logs hash if no decode) |
| sal_journal_entry_hash | ledger_entries | Optional; from SAL if applicable |
**Leaf encoding (canonical):** `keccak256(abi.encodePacked(chain_id, tx_hash, block_number, receipt_root_or_logs_bloom, normalized_event_payload_hash, sal_journal_entry_hash))`
Schema version and chain_id are also stored at commit level (startBlock, endBlock, root, chain_id, schema_version).
---
## 10. Changelog
| Version | Date | Change |
|---------|------|--------|
| 1.0 | 2026-01-28 | Initial normalized event schema v1 for EII, SAL, and Mirroring. |