Understanding the codebase
Repo structure
the‑parsoor/
├── .github/ ← CI & templates
├── .vscode/ ← local dev helpers
├── .env.example
├── jest.config.js
├── package*.json
├── tsconfig.json
├─┬ src/ ← **all production TypeScript**
│ ├─┬ config/ ← global registries
│ │ ├── chainConfig.ts
│ │ ├── protocols.ts
│ │ └── index.ts
│ ├─┬ enums/ ← string/number enums shared project‑wide
│ │ └── index.ts
│ ├─┬ helpers/ ← pure utility functions
│ │ ├── ProtocolHelper.ts
│ │ └── …
│ ├─┬ lib/ ← **one folder per protocol parser**
│ │ ├─┬ Across/ ← ✧ *focus of this tour*
│ │ │ ├─┬ abis/
│ │ │ │ └── SpokePool.json
│ │ │ ├── contracts.ts ← address + event signature map
│ │ │ ├── parser.ts ← core parsing logic
│ │ │ └── index.ts ← tiny export wrapper
│ │ ├── Curve/
│ │ ├── Uniswap/
│ │ ├── … (~15 other dApps)
│ │ └── index.ts ← collects **every** protocol parser into a map
│ ├─┬ types/ ← strict domain interfaces
│ │ ├─┬ chunks/ ← granular sub‑interfaces
│ │ │ ├── IProtocolParser.ts
│ │ │ └── …
│ │ └── index.ts
│ └── index.ts ← library entry‑point
└─┬ tests/ ← mirrors `src/lib` one‑for‑one
├─┬ lib/
│ ├─┬ Across/
│ │ ├── data.ts ← sample on‑chain tx hashes
│ │ └── index.test.ts ← Jest unit tests
│ └── … ← other protocol test suites
└── index.ts ← test boot‑strap
1. config/ — global registries
config/ — global registries• chainConfig.ts
chainConfig.tsA simple map from CHAIN_ID → RPC URL. Environment variables override the public defaults so contributors can drop in their own Alchemy/Infura keys without touching code. GitHub
• protocols.ts
protocols.tsCanonical metadata for every dApp OpenRep understands: human‑readable name, logo, website, protocol type, and the action‑tags that matter for reputation scoring. New parsers only need to add one JSON‑ish entry here. GitHub
• index.ts
index.tsOne‑liner that re‑exports the two files above for ergonomic imports. GitHub
2. enums/ — shared constants
enums/ — shared constantsTiny, dependency‑free enums that keep magic strings out of business logic:
actions.ts – ACTION_ENUM
High‑level actions a parser can emit (SINGLE_SWAP, BRIDGE_OUT, …) GitHub
chains.ts – CHAIN_ID
Numeric IDs for every EVM chain we care about; keeps config and tests in sync. GitHub
listeners.ts – LISTEN_FOR_TRANSACTIONS
Indicates whether we inspect incoming or outgoing txs for a contract. GitHub
index.ts simply re‑exports the chunk files. GitHub
3. helpers/ — pure utility code
helpers/ — pure utility code• ProtocolHelper.ts
ProtocolHelper.tsA 150‑line Swiss‑army knife used by every parser:
decode calldata (
parseTransaction) and logs (parseLog) with the right ABIquick checks like “is
txn.toone of my listener contracts?”
• index.ts
index.tsJust re‑exports ProtocolHelper. GitHub
4. types/ — strongly‑typed domain model
types/ — strongly‑typed domain modelAll interfaces live here so parsers stay 100 % type‑safe:
ITransaction– normalized block‑data recordITransactionAction(+ variants) – the output of a parser: swap, bridge‑in/out, etc. GitHubIProtocolParser– contract every parser class must implement (identifier +parseTransaction+getProtocolContracts). GitHub
The chunked layout keeps each interface tiny and tree‑shakeable; types/index.ts gathers them for downstream imports. GitHub
5. lib/<Protocol> — the actual protocol parsers
lib/<Protocol> — the actual protocol parsersEvery dApp gets its own folder; let’s zoom into Across as a template.
abis/SpokePool.json
Minimal ABI for the contract(s) we parse — only the events/functions we need, nothing else.
contracts.ts
1️⃣ enum of internal contract IDs
2️⃣ address map per chain & listen‑direction
3️⃣ event signatures → ABI fragments — all nested under IProtocolContractDefinitions. GitHub
parser.ts
Pure, stateless functions that inspect logs and build IBridgeIn / IBridgeOut actions. It leans on ProtocolHelper.parseLog so ABI decoding is one‑liner. GitHub
index.ts
A small class that wires the pieces together:
• sets protocolIdentifier from config/protocols
• decides if the tx is relevant (using helper)
• delegates to parser.ts and returns the array of actions. GitHub
lib/index.ts instantiates every parser and exports a lookup map keyed by the identifiers defined in config/protocols.ts. When the indexer hands a raw tx to OpenRep, it just does parsers[protoId].parseTransaction(tx). GitHub
6. Root src/index.ts
src/index.tsFive export lines that fan‑out the public surface of the SDK — effortless consumption from other Mercle services or external dApps. GitHub
How it all clicks together
Indexer forwards a raw
ITransactionto the parser layer.Top‑level code picks the right parser via
lib/index.ts.The parser uses its contract map +
ProtocolHelperto decide if the tx is for it, decode logs, and emitITransactionAction[].Actions flow downstream to the scoring engine you described earlier.
With this structure contributors can add a new protocol by touching just four places:
config/protocols.ts– one metadata entry.lib/<Protocol>/– the four‑file mini‑module.lib/index.ts– add an import + line in theparsersmap.(Optional)
tests/lib/<Protocol>/– real‑TX unit tests.
That’s the whole puzzle — no global singleton state, no hand‑rolled type unions, just clean, modular TypeScript ready for fast community contributions.
Last updated