Some checks failed
Deploy to Phoenix / deploy (push) Has been cancelled
- MASTER_INDEX: Last Updated 2026-03-06; status 59/59 contracts; add NEXT_STEPS_LIST, CONTRACT_NEXT_STEPS_LIST - docs/README, NEXT_STEPS_INDEX, 06-besu/MASTER_INDEX: Last Updated 2026-03-06 - Contract check script: 59 addresses (PMM, vault/reserve, CompliantFiatTokens); canonical CCIP/router - New docs: EXECUTION_CHECKLIST, NEXT_STEPS_LIST, DOTENV_AUDIT, ADDITIONAL_PATHS, deployer gas runbook, WEMIX_ACQUISITION_TABLED, etc. - Config: deployer-gas-routes, cro-wemix-swap-routes, routing-registry, token-mapping - Scripts: check-contracts-on-chain-138, check-pmm-pool-balances-chain138, deployer-gas-auto-route, acquire-cro-and-wemix-gas - Operator rule: operator-lan-access-check.mdc Made-with: Cursor
5.3 KiB
5.3 KiB
Activity Feed — Event Schema and Ingestion
Purpose: Canonical event model and ingestion spec for the normalized activity feed: transfers, app events, and bridge stitching. Table: activity_events (migration 0014).
References: indexer-architecture.md, heatmap-chains.ts (ALT vs B/SBS), cross-chain-bridges.ts (getRouteFromRegistry).
1. Table: activity_events
| Column | Type | Description |
|---|---|---|
id |
uuid | Primary key (default gen_random_uuid()) |
chain_id |
integer | 138 or 651940 (and others when indexed) |
transaction_hash |
varchar(66) | Tx hash |
log_index |
integer | Log index (0 for tx-level) |
block_number |
bigint | Block number |
block_timestamp |
timestamptz | Block time |
actor |
varchar(42) | Wallet that initiated the action |
subject |
varchar(42) | Optional: user/account/tokenId/resource |
event_type |
varchar(32) | TRANSFER, APP_ACTION, CLAIM, BRIDGE_OUT, BRIDGE_IN |
contract_address |
varchar(42) | Contract that emitted or was called |
data |
jsonb | Parsed event fields |
routing |
jsonb | `{ "path": "ALT" |
created_at |
timestamptz | Insert time |
Unique: (chain_id, transaction_hash, log_index).
2. Ingestion
2.1 Transfers
- Source: Existing
token_transfers(and ERC-721/1155 logs when indexed). - Mapping: For each row: insert into
activity_eventswithevent_type = 'TRANSFER',actor = from_address,subject = to_address(or token id for NFT),data = { from, to, value, tokenContract },contract_address = token_contract.routing= NULL for same-chain transfers. - Backfill: Migration
0015_activity_events_backfill_from_token_transfers.up.sqlruns a one-timeINSERT ... SELECTfromtoken_transferswithON CONFLICT DO NOTHING. Run after 0014. - Real-time: The Track 2 token indexer (
explorer-monorepo/backend/indexer/track2/token_indexer.go) inserts intoactivity_eventson each new token transfer (same row astoken_transfers), so the feed stays current without a separate job.
2.2 App events
- Source: Application-lifecycle events (create, complete, settle, redeem, etc.) from your contracts.
- Registry: Maintain a mapping (event signature →
event_type+ parser). Example:0x...→APP_ACTION, parsedatafrom log topics/data. - Insert: Decode log; set
event_type,actor(e.g. tx from),subject(e.g. orderId),data(decoded fields),contract_address.
2.3 Bridge stitching
- Source: Bridge contracts (AlltraAdapter, CCIP WETH9/WETH10); events such as lock/burn on source, mint/release on destination.
- Routing: Use getRouteFromRegistry or config/routing-registry.json: 138↔651940 →
path: "ALT", 138↔others →path: "CCIP". - Insert: For each bridge event, set
routing = { path: "ALT"|"CCIP", fromChain, toChain, bridgeTxHash }. Optionally correlate "bridge out" and "bridge in" with a shareddata.correlationIdso the API can return one stitched feed item per cross-chain move.
3. Activity feed API
Endpoint: GET /api/v1/track2/activity (Track 2 auth required). Implemented in explorer-monorepo/backend/api/track2/endpoints.go (HandleActivityFeed).
Query params:
address— filter by actor or subject (user feed).event_type— filter by event type (e.g.TRANSFER,APP_ACTION).chain_id— filter by chain (default: server chain).page,limit(default 50, max 100) — pagination.
Queries:
- By user:
address=0x...→WHERE actor = $address OR subject = $address(paginated). - By token/NFT: Use
event_type=TRANSFERandcontract_addressor filter client-side bydata.tokenContract/data.tokenId. - Global: Omit
address; optionalevent_type; pagination by(block_timestamp DESC, id DESC).
Pagination: Page/limit (offset-based); limit 50 per page, max 100.
Example (by user):
SELECT * FROM activity_events
WHERE actor = $1 OR subject = $1
ORDER BY block_timestamp DESC, id DESC
LIMIT 50 OFFSET $2;
4. Event type enum (logical)
| event_type | Description |
|---|---|
| TRANSFER | ERC-20/721/1155 transfer |
| APP_ACTION | App-lifecycle (create, complete, settle, etc.) |
| CLAIM | Claim/mint from drop or contract |
| BRIDGE_OUT | Lock/burn on source chain |
| BRIDGE_IN | Mint/release on destination chain |
5. Migrations
- 0014 — table: 0014_activity_events.up.sql (down:
0014_activity_events.down.sql). - 0015 — backfill: 0015_activity_events_backfill_from_token_transfers.up.sql: one-time backfill from
token_transfers; down is no-op.
Run with your existing migration runner (e.g. golang-migrate, node-pg-migrate) against the explorer/backend DB.