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.ts
A 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.ts
Canonical 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.ts
One‑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.ts
A 150‑line Swiss‑army knife used by every parser:
decode calldata (
parseTransaction
) and logs (parseLog
) with the right ABIquick checks like “is
txn.to
one of my listener contracts?”
• index.ts
index.ts
Just 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.ts
Five 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
ITransaction
to the parser layer.Top‑level code picks the right parser via
lib/index.ts
.The parser uses its contract map +
ProtocolHelper
to 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 theparsers
map.(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