- 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>
8.7 KiB
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
0xprefix. - 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. |