|
| 1 | +# Add Data Provider |
| 2 | + |
| 3 | +Interactive workflow for scaffolding a new data provider. Follow CLAUDE.md "How to Add a New Data Provider" exactly. |
| 4 | + |
| 5 | +## Input |
| 6 | + |
| 7 | +Ask the user for: |
| 8 | +1. **Provider name** (camelCase, e.g. `theGraph`) — this becomes the `DataProviderName` union member and directory name |
| 9 | +2. **Whether the provider needs config constants** (deployment blocks, subgraph URLs, etc.) |
| 10 | +3. **Whether the provider needs an `init()` step** (e.g. spinning up infrastructure, waiting for backfill) |
| 11 | + |
| 12 | +## Steps |
| 13 | + |
| 14 | +### 1. Config package (`apps/config`) |
| 15 | + |
| 16 | +**a) Add to union type** in `apps/config/src/types.ts`: |
| 17 | +- Add `"<name>"` to the `DataProviderName` union type (maintain alphabetical order within the union) |
| 18 | + |
| 19 | +**b) If config constants are needed**, create `apps/config/src/dataProviders/<name>.ts`: |
| 20 | +- Follow the pattern in `apps/config/src/dataProviders/hyperindex.ts` for per-chain config records |
| 21 | +- Use `Record<number, ...>` keyed by chain ID |
| 22 | +- Export from `apps/config/src/dataProviders/index.ts` |
| 23 | + |
| 24 | +### 2. Data Providers package (`apps/data-providers`) |
| 25 | + |
| 26 | +**a) Create provider implementation** at `apps/data-providers/src/<name>/index.ts`: |
| 27 | + |
| 28 | +```typescript |
| 29 | +import type { AccrualPosition } from "@morpho-org/blue-sdk"; |
| 30 | +import type { Account, Address, Chain, Client, Hex, Transport } from "viem"; |
| 31 | + |
| 32 | +import type { DataProvider } from "../dataProvider"; |
| 33 | + |
| 34 | +export class <ClassName> implements DataProvider { |
| 35 | + async init(): Promise<void> { |
| 36 | + // TODO: implement initialization (or remove if not needed) |
| 37 | + } |
| 38 | + |
| 39 | + async fetchMarkets( |
| 40 | + client: Client<Transport, Chain, Account>, |
| 41 | + vaults: Address[], |
| 42 | + ): Promise<Hex[]> { |
| 43 | + // TODO: implement market fetching |
| 44 | + throw new Error("Not implemented"); |
| 45 | + } |
| 46 | + |
| 47 | + async fetchLiquidatablePositions( |
| 48 | + client: Client<Transport, Chain, Account>, |
| 49 | + marketIds: Hex[], |
| 50 | + ): Promise<AccrualPosition[]> { |
| 51 | + // TODO: implement position fetching |
| 52 | + throw new Error("Not implemented"); |
| 53 | + } |
| 54 | +} |
| 55 | +``` |
| 56 | + |
| 57 | +Replace `<ClassName>` with an appropriate PascalCase class name (e.g. `TheGraphDataProvider`). |
| 58 | + |
| 59 | +**b) Register in factory** at `apps/data-providers/src/factory.ts`: |
| 60 | +- Add import for the new class |
| 61 | +- Add `case "<name>":` to the switch returning `new <ClassName>()` |
| 62 | + |
| 63 | +**c) Add re-export** in `apps/data-providers/src/index.ts`: |
| 64 | +- Add `export * from "./<name>";` |
| 65 | + |
| 66 | +### 3. Reminder |
| 67 | + |
| 68 | +After scaffolding, remind the user: |
| 69 | +- Set `options.dataProvider` to `"<name>"` in relevant chain configs in `apps/config/src/config.ts` |
| 70 | +- Data providers are multi-chain: a single instance is shared across all chains using that provider |
| 71 | +- The factory calls `init()` once before the provider is used — use it for any async setup |
| 72 | +- Run `/test` to validate the scaffold compiles and tests pass |
0 commit comments