Skip to content

Commit 7ceff85

Browse files
committed
feat: dolomite liquidator migration
0 parents  commit 7ceff85

39 files changed

Lines changed: 14573 additions & 0 deletions

File tree

.claude/skills/envio-docs/SKILL.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
---
2+
name: envio-docs
3+
description: >-
4+
Use when something is unclear, confusing, or not covered by other skills.
5+
Search and read the latest Envio documentation without leaving the terminal.
6+
metadata:
7+
managed-by: envio
8+
---
9+
10+
- `envio tools search-docs "<query>"` — find docs pages by keyword
11+
- `envio tools fetch-docs <url>` — read a page in full (use a URL from search results)
12+
- `envio --help` — list available CLI commands and flags
13+
14+
Example: `envio tools search-docs "schema derivedFrom"` → pick a URL → `envio tools fetch-docs <url>`
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
---
2+
name: indexer-blocks
3+
description: >-
4+
Use when processing every block (or every Nth block) for time-series data,
5+
periodic snapshots, or block-level aggregations. indexer.onBlock API, where
6+
filter with block-number range and stride, and block handler context.
7+
metadata:
8+
managed-by: envio
9+
---
10+
11+
# Block Handlers
12+
13+
Process every block (or every Nth block) using `indexer.onBlock`. No contract
14+
address or `config.yaml` entry needed.
15+
16+
## Handler
17+
18+
Branch by `chain.id` with a `switch` so the type system flags any
19+
unconfigured chain via the `default: never` exhaustiveness check:
20+
21+
```ts
22+
import { indexer } from "envio";
23+
24+
indexer.onBlock(
25+
{
26+
name: "BlockTracker",
27+
where: ({ chain }) => {
28+
switch (chain.id) {
29+
case 1:
30+
return { block: { number: { _gte: 18000000, _every: 100 } } };
31+
case 8453:
32+
return { block: { number: { _every: 50 } } };
33+
default: {
34+
// Exhaustiveness check: TypeScript errors here if a new chain ID
35+
// is added to config.yaml but not handled above.
36+
const _exhaustive: never = chain.id;
37+
return false;
38+
}
39+
}
40+
},
41+
},
42+
async ({ block, context }) => {
43+
context.BlockSnapshot.set({
44+
id: `${block.number}`,
45+
blockNumber: BigInt(block.number),
46+
});
47+
}
48+
);
49+
```
50+
51+
## Options
52+
53+
| Option | Type | Required | Description |
54+
|--------|------|----------|-------------|
55+
| `name` | `string` | yes | Handler name for logging |
56+
| `where` | `({ chain }) => boolean \| filter` | no | Predicate evaluated once per configured chain at registration. Return `false` to skip a chain, `true` / omit to match every block, or `{block: {number: {_gte?, _lte?, _every?}}}` to restrict range and stride. `_every` aligns relative to `_gte`, preserving `(blockNumber - _gte) % _every === 0`. |
57+
58+
## Other ecosystems
59+
60+
- **Fuel**: same `indexer.onBlock` API; filter is keyed by `block.height` instead of `block.number`.
61+
- **SVM**: use `indexer.onSlot`; filter shape is `{slot: {_gte?, _lte?, _every?}}` and the handler arg is `{slot: number, context}` (no `block` wrapper).
62+
63+
## Notes
64+
65+
- `indexer.onBlock` self-registers — no `config.yaml` entry needed
66+
- No events or contract address required
67+
- The handler context has the same entity API as event handlers
68+
- If `where` returns `false` for every configured chain, a warning is logged at registration time
69+
- For per-event startBlock (not stride), use `indexer.onEvent` with `where.block.number._gte` (see `indexer-filters`). Event filters accept `_gte` only; `_lte`/`_every` are reserved for `onBlock`.
70+
71+
> If something is unclear, use the `envio-docs` skill to search and read the latest documentation.
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
---
2+
name: indexer-configuration
3+
description: >-
4+
Use when writing or editing config.yaml. Chain/contract structure, addresses,
5+
start_block, event selection, field_selection, custom event names, env vars,
6+
address_format, schema/output paths, YAML validation, and deprecated options.
7+
metadata:
8+
managed-by: envio
9+
---
10+
11+
# Config Reference (config.yaml)
12+
13+
## Structure Overview
14+
15+
```yaml
16+
name: my-indexer
17+
description: Optional description
18+
schema: schema.graphql # custom path (default: schema.graphql)
19+
address_format: checksum # checksum (default) | lowercase
20+
21+
contracts:
22+
- name: MyContract
23+
abi_file_path: ./abis/MyContract.json
24+
handler: ./src/EventHandlers.ts # optional — auto-discovered from src/handlers/
25+
events:
26+
- event: Transfer(address indexed from, address indexed to, uint256 value)
27+
28+
chains:
29+
- id: 1
30+
start_block: 0
31+
contracts:
32+
- name: MyContract
33+
address: "0x1234..."
34+
```
35+
36+
Uses `chains` (not `networks`) and `max_reorg_depth` (not `confirmed_block_threshold`).
37+
38+
## Contract Addresses
39+
40+
```yaml
41+
# Single address
42+
- name: Token
43+
address: "0x1234..."
44+
45+
# Multiple addresses
46+
- name: Token
47+
address:
48+
- "0xaaa..."
49+
- "0xbbb..."
50+
51+
# No address — wildcard indexing (all contracts matching ABI)
52+
- name: Token
53+
# address omitted — indexes all matching events chain-wide
54+
55+
# Factory-registered — see indexer-factory skill
56+
```
57+
58+
For proxied contracts, use the **proxy address** (where events emit), not the implementation.
59+
60+
## start_block
61+
62+
```yaml
63+
chains:
64+
- id: 1
65+
start_block: 0 # 0 = HyperSync auto-detects first event block
66+
contracts:
67+
- name: Token
68+
address: "0x1234..."
69+
start_block: 18000000 # per-contract override (takes precedence)
70+
```
71+
72+
`start_block: 0` with HyperSync skips empty blocks automatically.
73+
74+
## Custom Event Names
75+
76+
When two events share the same name (different signatures), disambiguate:
77+
78+
```yaml
79+
events:
80+
- event: Transfer(address indexed from, address indexed to, uint256 value)
81+
name: TransferERC20
82+
- event: Transfer(address indexed from, address indexed to, uint256 indexed tokenId)
83+
name: TransferERC721
84+
```
85+
86+
## field_selection
87+
88+
Request additional transaction/block fields globally or per event:
89+
90+
```yaml
91+
# Global (root level — applies to all events)
92+
field_selection:
93+
transaction_fields:
94+
- hash
95+
- from
96+
- to
97+
block_fields:
98+
- number
99+
- timestamp
100+
101+
contracts:
102+
- name: MyContract
103+
events:
104+
# Per-event (overrides global for this event)
105+
- event: Transfer(address indexed from, address indexed to, uint256 value)
106+
field_selection:
107+
transaction_fields:
108+
- hash
109+
- from
110+
- to
111+
- gasPrice
112+
```
113+
114+
Global `field_selection` is at the root level (sibling to `contracts` and `chains`). Per-event `field_selection` is directly under the event entry. See `indexer-transactions` skill for full field lists.
115+
116+
## Environment Variables
117+
118+
```yaml
119+
rpc:
120+
- url: ${ENVIO_RPC_URL} # required — errors if missing
121+
- url: ${ENVIO_RPC_URL:-http://localhost:8545} # with default value
122+
```
123+
124+
Works in any string value in config. Set via `.env` file or shell environment.
125+
126+
**IMPORTANT:** All environment variables MUST use the `ENVIO_` prefix (e.g., `ENVIO_RPC_URL`, not `RPC_URL`). The hosted service requires the `ENVIO_` prefix — variables without it will not be available at runtime.
127+
128+
## Runtime Environment Variables
129+
130+
Set on the indexer process (not interpolated into config.yaml):
131+
132+
- `ENVIO_TUI` — `true` forces the terminal UI on, `false` forces it off. Unset (default) auto-disables under agents, CI, and non-TTY stdout, so plain `pnpm dev` produces line-buffered output suitable for log capture without manual intervention.
133+
134+
## YAML Validation
135+
136+
Add at top of file for IDE schema validation:
137+
138+
```yaml
139+
# yaml-language-server: $schema=./node_modules/envio/evm.schema.json
140+
```
141+
142+
## Deprecated Options (Do NOT Use)
143+
144+
- `loaders` / `preload_handlers` — replaced by async handler API
145+
- `preRegisterDynamicContracts` — replaced by `contractRegistrations` in factory pattern
146+
- `event_decoder` — removed
147+
- `rpc_config` — replaced by `rpc:` under chains
148+
- `unordered_multichain_mode` — removed
149+
150+
## RPC Configuration
151+
152+
RPC tuning parameters are documented in the `indexer-performance` skill.
153+
154+
> If something is unclear, use the `envio-docs` skill to search and read the latest documentation.
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
---
2+
name: indexer-external-calls
3+
description: >-
4+
Use when making RPC calls, fetch requests, or any external I/O from handlers.
5+
Effect API with createEffect, S schema validation, context.effect(), preload
6+
optimization (handlers run twice), cache and rateLimit options.
7+
metadata:
8+
managed-by: envio
9+
---
10+
11+
# External Calls (Effect API)
12+
13+
Handlers run twice: parallel **preload pass** (warms caches), then **sequential pass** (state changes). All external I/O (fetch, RPC, APIs) MUST go through `createEffect` + `context.effect()` — otherwise it double-executes and blocks parallelization.
14+
15+
## Define and call
16+
17+
```ts
18+
import { S, createEffect } from "envio";
19+
20+
const getOwner = createEffect(
21+
{
22+
name: "getOwner",
23+
input: { tokenId: S.bigint },
24+
output: S.union([S.string, null]),
25+
cache: true,
26+
rateLimit: false,
27+
},
28+
async ({ input }) => {
29+
const res = await fetch(`https://api.example.com/owner/${input.tokenId}`);
30+
return res.json();
31+
}
32+
);
33+
34+
indexer.onEvent(
35+
{ contract: "Token", event: "Transfer" },
36+
async ({ event, context }) => {
37+
const owner = await context.effect(getOwner, { tokenId: event.params.tokenId });
38+
}
39+
);
40+
```
41+
42+
## Pass minimum input
43+
44+
`input` carries only what varies per call. Bake static config (URLs, tokens, channel IDs, env vars) into the effect body. Build payloads/strings inside the effect.
45+
46+
```ts
47+
// ❌ input: { url, chatId, text } — config and pre-built strings leak into the call site
48+
// ✅ input: { usd, blockNumber } — only the values that vary per call
49+
```
50+
51+
Dedup is keyed by hash of `input`; leaner inputs dedupe better, validate faster, and let one effect serve many call sites.
52+
53+
## Schema (`S`)
54+
55+
`S.string`, `S.number`, `S.bigint`, `S.boolean`, `S.schema({ ... })`, `S.array(...)`, `S.union([..., null])`, `S.optional(...)`.
56+
Full ref: https://raw.githubusercontent.com/DZakh/sury/refs/tags/v9.3.0/docs/js-usage.md
57+
58+
## RPC pattern (viem)
59+
60+
```ts
61+
const client = createPublicClient({ transport: http(process.env.ENVIO_RPC_URL) });
62+
63+
const getTokenMetadata = createEffect(
64+
{
65+
name: "getTokenMetadata",
66+
input: S.string,
67+
output: { name: S.string, symbol: S.string, decimals: S.number },
68+
cache: true,
69+
rateLimit: false,
70+
},
71+
async ({ input: address }) => {
72+
const args = { address: address as `0x${string}`, abi: ERC20_ABI };
73+
const [name, symbol, decimals] = await Promise.all([
74+
client.readContract({ ...args, functionName: "name" }),
75+
client.readContract({ ...args, functionName: "symbol" }),
76+
client.readContract({ ...args, functionName: "decimals" }),
77+
]);
78+
return { name, symbol, decimals: Number(decimals) };
79+
}
80+
);
81+
```
82+
83+
## Options
84+
85+
| Option | Type | Default |
86+
|---|---|---|
87+
| `name` | `string` ||
88+
| `input` | `S.Schema` ||
89+
| `output` | `S.Schema` ||
90+
| `cache` | `boolean` | `false` |
91+
| `rateLimit` | `false \| { calls, per }` | required |
92+
93+
> If something is unclear, use the `envio-docs` skill to search and read the latest documentation.

0 commit comments

Comments
 (0)