Files
smom-dbis-138/services/token-aggregation/README.md

267 lines
12 KiB
Markdown
Raw Normal View History

# Token Aggregation Service
A comprehensive token aggregation service that indexes token info, volume, liquidity, and market signals from on-chain data and enriches with CoinGecko, CoinMarketCap, and DexScreener APIs for ChainID 138 (DeFi Oracle Meta Mainnet) and ChainID 651940 (ALL Mainnet).
**REST API reference:** [docs/REST_API_REFERENCE.md](docs/REST_API_REFERENCE.md) — tokens, pools, prices, volume, OHLCV for dApps and MetaMask Snap discovery.
2026-06-01 22:26:06 -07:00
**Chain 138 Snap:** The MetaMask Chain 138 Snap (companion site at e.g. https://explorer.d-bis.org/snap/) calls this service for market data, swap quotes, and bridge routes. If the Snap is built with `GATSBY_SNAP_API_BASE_URL=https://explorer.d-bis.org`, then explorer.d-bis.org must serve this API (e.g. proxy `/api/v1/*` to this service). Otherwise build the Snap site with `GATSBY_SNAP_API_BASE_URL` set to this services public URL. See [metamask-integration/chain138-snap/docs/CHAIN138_SNAP_TROUBLESHOOTING.md](~/projects/metamask-integration/chain138-snap/docs/CHAIN138_SNAP_TROUBLESHOOTING.md). **CORS:** The service uses `cors()` (all origins allowed by default) so MetaMask Snap and browser clients can fetch token list and networks.
## Features
- **Chain-Native Indexing**: Indexes tokens, DEX pools, and swap events directly from blockchain
- **External API Enrichment**: Enriches data with CoinGecko, CoinMarketCap, and DexScreener
- **Multi-DEX Support**: Supports UniswapV2, UniswapV3, and DODO PMM protocols
- **Chain 138 PMM quotes**: `GET /api/v1/quote` runs on-chain `querySellBase` / `querySellQuote` when RPC is configured (`RPC_URL_138` or `TOKEN_AGGREGATION_*` in `.env.example`); JSON includes `quoteEngine` (`pmm-onchain` vs `constant-product`)
- **OHLCV Data**: Generates Open, High, Low, Close, Volume data for price charts
- **Volume Analytics**: Calculates 5m, 1h, 24h, 7d, 30d volume metrics
- **REST API**: Unified REST API for all token data
## Architecture
### Three-Layer Design
1. **Layer 1: Chain-Native Indexer** - Source of truth from on-chain data
2. **Layer 2: External Enrichment Adapters** - Best-effort enrichment from external APIs
3. **Layer 3: Unified REST API** - Single API endpoint for consumption
## Prerequisites
- Node.js 20+
- PostgreSQL 14+ with TimescaleDB extension
- Access to RPC endpoints for ChainID 138 and 651940
- (Optional) API keys for CoinGecko, CoinMarketCap, DexScreener
## Installation
1. Clone the repository and navigate to the service directory:
```bash
cd smom-dbis-138/services/token-aggregation
```
2. Install dependencies:
```bash
npm install
```
3. Copy environment file:
```bash
cp .env.example .env
```
4. Configure environment variables in `.env` (see `.env.example` for full list):
```bash
# Chain RPCs
# Explorer-side/LAN deployment: use the public RPC node directly.
CHAIN_138_RPC_URL=http://192.168.11.221:8545
# External-only deployments may use: https://rpc-http-pub.d-bis.org
CHAIN_651940_RPC_URL=https://mainnet-rpc.alltra.global
# Database
DATABASE_URL=postgresql://user:password@localhost:5432/explorer_db
# External APIs (optional) — use placeholders in .env.example; get keys from provider dashboards
COINGECKO_API_KEY=your_key_here
COINMARKETCAP_API_KEY=your_key_here
DEXSCREENER_API_KEY=your_key_here
```
For Chain 138 there is an important split:
- Explorer, Blockscout, token-aggregation, and other read-mostly services should use the public RPC node on `192.168.11.221:8545` when they run on the LAN.
- External wallets and dApps should use `https://rpc-http-pub.d-bis.org`.
- Operator/deploy workflows use the core RPC `http://192.168.11.211:8545`, but that core endpoint is not for explorer/read traffic.
**Canonical token addresses (report API):** Set per-chain env vars for tokens you want in `/api/v1/report/*`. Required/minimal for report: `CUSDC_ADDRESS_138`, `CUSDT_ADDRESS_138` (Chain 138); optionally `CUSDC_ADDRESS_651940`, `CUSDT_ADDRESS_651940` for Chain 651940. **Chain 138 compliant fiat** (cEURC, cEURT, cGBPC, cGBPT, cAUDC, cJPYC, cCHFC, cCADC, cXAUC, cXAUT) have **fallback addresses** in `src/config/canonical-tokens.ts` (DeployCompliantFiatTokens 2026-02-27); they are included in the report without env. The live **ALL Mainnet AUSDT corridor** is also surfaced there as `cAUSDT` on Chain 138 plus `cWAUSDT` mirrors on BSC, Polygon, Avalanche, and Celo. The planned **ALL Mainnet gold corridor** is env-gated under `CAXAUC_ADDRESS_651940`, `CAXAUT_ADDRESS_651940`, `CWAXAUC_ADDRESS_651940`, and `CWAXAUT_ADDRESS_651940`. Other symbols (USDW, acUSDC, vdcUSDC, sdcUSDC, etc.) — see `.env.example`. Unset tokens (with no fallback) are omitted from the report.
### Required environment variables (canonical tokens — Blitzkrieg Step 1/9)
The canonical token list is defined in `src/config/canonical-tokens.ts` and is the single source of truth for the Token Aggregation API and report endpoints. Addresses are read from environment variables; unset tokens are omitted from `getCanonicalTokensByChain` and report output.
| Purpose | Env var pattern | Example |
|--------|------------------|--------|
| Chain 138 | `{SYMBOL}_ADDRESS_138` (symbol with `-``_`, uppercase) | `CUSDC_ADDRESS_138`, `CUSDT_ADDRESS_138`, `CAUSDT_ADDRESS_138`, `USDW_ADDRESS_138`, `ACUSDC_ADDRESS_138`, `VDCUSDC_ADDRESS_138`, `SDCUSDC_ADDRESS_138` |
| Chain 651940 (ALL Mainnet) | `{SYMBOL}_ADDRESS_651940` | `CUSDC_ADDRESS_651940`, `CUSDT_ADDRESS_651940`, `AUSDT_ADDRESS_651940`, `CAXAUC_ADDRESS_651940`, `CWAXAUC_ADDRESS_651940` |
**Minimum for report API:** `CUSDC_ADDRESS_138`, `CUSDT_ADDRESS_138`. For full GRU M1 + W-tokens + ac*/vdc*/sdc* coverage, set the corresponding `*_ADDRESS_138` and `*_ADDRESS_651940` vars. See `.env.example` for the full commented list. Refs: [BLITZKRIEG_SUPER_PRO_MAX_MASTER_PLAN](../../../docs/00-meta/BLITZKRIEG_SUPER_PRO_MAX_MASTER_PLAN.md) §2§3, [PLACEHOLDERS_AND_COMPLETION_MASTER_LIST](../../../docs/00-meta/PLACEHOLDERS_AND_COMPLETION_MASTER_LIST.md).
**CoinGecko/CMC chain support:** ChainID 138 and 651940 are not yet supported by CoinGecko/CMC; external price/volume for these chains will be empty in the report until the platforms add support or you use another source. The report API still returns chain-native token/pool data.
**Bridge routes (CCIP + Trustless):** `GET /api/v1/bridge/routes` returns CCIP (WETH9/WETH10) and **Trustless** bridge data. Trustless is **enabled in production by default**: the deployed Lockbox138 address on Chain 138 is included when `LOCKBOX_138` is not set. Optional env (restart after change):
- `LOCKBOX_138` — Override Lockbox contract address on Chain 138 (default: deployed Lockbox138).
- `INBOX_ETH` — (Optional) InboxETH contract on Ethereum Mainnet; when set, the Snap shows "Trustless → Ethereum Mainnet" with this address.
The MetaMask Snap bridge dialog always shows the Trustless (Lockbox) route when using this API. **Full Trustless operations** (user lock/claim) also require the Trustless stack on Ethereum (InboxETH, BondManager, LiquidityPool, etc.) to be deployed and operational; see `smom-dbis-138/docs/bridge/trustless`.
**Token mapping (multichain):** When run from the monorepo (proxmox), `GET /api/v1/token-mapping?fromChain=138&toChain=651940` (and `?fromChain=&toChain=` for any pair), `GET /api/v1/token-mapping/pairs`, and `GET /api/v1/token-mapping/resolve?fromChain=&toChain=&address=` expose `config/token-mapping-multichain.json` for bridge UIs and cross-chain address resolution.
5. Run database migrations:
```bash
# Ensure the migration has been run in the explorer database
2026-06-01 22:26:06 -07:00
# Migration file: ~/projects/explorer-monorepo/backend/database/migrations/0011_token_aggregation_schema.up.sql
```
6. Build the project:
```bash
npm run build
```
7. Start the service:
```bash
npm start
```
## Development
```bash
# Run in development mode with hot reload
npm run dev
# Run tests
npm test
# Lint code
npm run lint
```
## Docker Deployment
### Build and run with Docker Compose
```bash
docker-compose up -d
```
### Build Docker image
```bash
docker build -t token-aggregation-service .
docker run -p 3000:3000 --env-file .env token-aggregation-service
```
## API Endpoints
### Health Check
```
GET /health
```
### List Chains
```
GET /api/v1/chains
```
### List Tokens
```
GET /api/v1/tokens?chainId=138&limit=50&offset=0
```
### Get Token Details
```
GET /api/v1/tokens/:address?chainId=138
```
### Get Token Pools
```
GET /api/v1/tokens/:address/pools?chainId=138
```
### Get OHLCV Data
```
GET /api/v1/tokens/:address/ohlcv?chainId=138&interval=1h&from=timestamp&to=timestamp
```
### Get Token Signals
```
GET /api/v1/tokens/:address/signals?chainId=138
```
### Search Tokens
```
GET /api/v1/search?q=USDT&chainId=138
```
### Get Pool Details
```
GET /api/v1/pools/:poolAddress?chainId=138
```
### Route Decision Tree
```
GET /api/v1/routes/tree?chainId=138&tokenIn=0x...&tokenOut=0x...&amountIn=1000000&destinationChainId=1
```
Live route tree with current pool depth, freshness, bridge fallback, and destination-swap legs.
### Route Depth Summary
```
GET /api/v1/routes/depth?chainId=138&tokenIn=0x...&tokenOut=0x...&amountIn=1000000&destinationChainId=1
```
Compact summary of the same route tree for routing UIs.
### CMC and CoinGecko Reporting (all tokens, liquidity, volume)
Full API for all coins, tokens, liquidity, and reportable data in CMC/CoinGecko-friendly formats:
| Endpoint | Description |
|----------|-------------|
| `GET /api/v1/report/all` | All tokens, pools, liquidity, volume, and summary by chain |
| `GET /api/v1/report/coingecko?chainId=138` | Token list in CoinGecko submission format |
| `GET /api/v1/report/cmc?chainId=138` | Token list and DEX pairs in CoinMarketCap format |
| `GET /api/v1/report/token-list` | Flat canonical token list, including explicit Chain 138 V1/V2 GRU deployments where available |
| `GET /api/v1/report/canonical` | Raw canonical token spec with version/family metadata and addresses |
See [docs/CMC_COINGECKO_REPORTING.md](docs/CMC_COINGECKO_REPORTING.md) for usage and listing submission.
### Token mapping (multichain)
When the service runs from the monorepo (with `config/token-mapping-multichain.json` available):
| Endpoint | Description |
|----------|-------------|
| `GET /api/v1/token-mapping?fromChain=138&toChain=651940` | Token mapping for a chain pair (tokens, addressMapFromTo, addressMapToFrom) |
| `GET /api/v1/token-mapping/pairs` | All defined chain pairs |
| `GET /api/v1/token-mapping/resolve?fromChain=&toChain=&address=` | Resolve token address on target chain |
## Configuration
### DEX Factory Configuration
Configure DEX factory addresses in `src/config/dex-factories.ts` or via environment variables:
```bash
# ChainID 138
CHAIN_138_DODO_POOL_MANAGER=0x...
CHAIN_138_UNISWAP_V2_FACTORY=0x0C30F6e67Ab3667fCc2f5CEA8e274ef1FB920279
CHAIN_138_UNISWAP_V2_ROUTER=0x3019A7fDc76ba7F64F18d78e66842760037ee638
CHAIN_138_UNISWAP_V2_START_BLOCK=4041370
CHAIN_138_SUSHISWAP_FACTORY=0x2871207ff0d56089D70c0134d33f1291B6Fce0BE
CHAIN_138_SUSHISWAP_ROUTER=0xB37b93D38559f53b62ab020A14919f2630a1aE34
CHAIN_138_SUSHISWAP_START_BLOCK=4041495
CHAIN_138_UNISWAP_V3_FACTORY=0x2f7219276e3ce367dB9ec74C1196a8ecEe67841C
CHAIN_138_UNISWAP_V3_ROUTER=0xde9cD8ee2811E6E64a41D5F68Be315d33995975E
# ChainID 651940
CHAIN_651940_UNISWAP_V2_FACTORY=0x...
CHAIN_651940_UNISWAP_V2_ROUTER=0x...
CHAIN_651940_UNISWAP_V2_START_BLOCK=0
CHAIN_651940_UNISWAP_V3_FACTORY=0x...
CHAIN_651940_UNISWAP_V3_ROUTER=0x...
CHAIN_651940_UNISWAP_V3_START_BLOCK=0
CHAIN_651940_HYDX_FACTORY=0x...
CHAIN_651940_HYDX_ROUTER=0x...
CHAIN_651940_HYDX_START_BLOCK=0
```
For ALL Mainnet non-DODO discovery, the repo now treats `HYDX` as the canonical custom venue surface when factory/router details are known. The broader `651940` non-DODO inventory is tracked in `config/allmainnet-non-dodo-protocol-surface.json`.
## Monitoring
The service includes:
- Health check endpoint at `/health`
- Structured logging with Winston
- Request rate limiting
- Response caching
## License
MIT