Mento Airdrop
A gamified DeFi loyalty platform tracking cross-chain trading activity and social engagement for community rewards.
Architecture Overview
Event-driven monolith. It uses a 'Staggered Cron' architecture to poll multiple Subgraphs without rate-limiting, reconciling 5 different DEX schemas into a single 'Swap Event' model for scoring.
The Challenges
Problem
We had to track user volume across 5 different protocols (Uniswap, Curve, Mento, etc.), each with different event schemas and Subgraphs. Missing a single trade meant a user might lose their airdrop eligibility.
Solution
Implemented a 'Staggered Ingestion Engine'. Independent cron jobs run at offset intervals (15s, 40s, 55s) to poll specific Subgraphs. We built a normalization layer that maps disparate schemas (e.g., Uniswap `Swap` vs. Curve `TokenExchange`) into a unified `TransactionModel`, deduplicating events by Hash to prevent double-counting.
tasks.service.ts
Problem
Marketing teams wanted complex, changing criteria: 'Hold $50 of cUSD for 7 days' OR 'Trade 5 different assets'. Hardcoding these rules would require a deploy for every new quest.
Solution
Designed a Polymorphic Task Pipeline. We treated Tasks as configurations, not code. The system uses a Strategy Pattern (`TaskProcessor`) where events trigger specific handlers based on the `TaskType` enum. This allowed us to launch 'Volume Challenges' or 'Diversity Quests' dynamically without rewriting the core tracking logic.
taskTracking.service.ts
Problem
To calculate 'Volume Leaderboards', we needed the USD value of every trade. However, many exotic pairs (e.g., cEUR/Celo) didn't have a direct USD price feed at the moment of the trade.
Solution
Built a multi-hop pricing resolver in AssemblyScript (Subgraph level). If a direct USD pair didn't exist, the indexer recursively checked for a route through CELO (e.g., cEUR -> CELO -> cUSD). We also verified rates against the on-chain Broker contract's `getAmountOut` to prevent price manipulation exploits.
pricing.ts
Problem
Users try to farm airdrops by linking one Discord account to 50 wallets. We needed strict 1:1 identity mapping.
Solution
Implemented an idempotent Identity Merging system. We use ECDSA signatures to prove wallet ownership and OAuth for Discord/Twitter. The backend enforces a strict unique constraint: If a Discord ID is linked to a new wallet, the previous link is atomically severed (orphaned), ensuring one human cannot farm rewards across multiple addresses.
auth.utils.ts