Initial commit
This commit is contained in:
151
skills/hyperindex-development/references/block-handlers.md
Normal file
151
skills/hyperindex-development/references/block-handlers.md
Normal file
@@ -0,0 +1,151 @@
|
||||
# Block Handlers
|
||||
|
||||
Run logic on every block or at intervals using the `onBlock` API (v2.29+).
|
||||
|
||||
## Basic Usage
|
||||
|
||||
```typescript
|
||||
import { onBlock } from "generated";
|
||||
|
||||
onBlock(
|
||||
{
|
||||
name: "MyBlockHandler",
|
||||
chain: 1,
|
||||
},
|
||||
async ({ block, context }) => {
|
||||
context.log.info(`Processing block ${block.number}`);
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
**Note:** Block handlers don't require config changes or codegen runs.
|
||||
|
||||
## Options
|
||||
|
||||
| Option | Required | Description |
|
||||
|--------|----------|-------------|
|
||||
| `name` | Yes | Handler name for logging/metrics |
|
||||
| `chain` | Yes | Chain ID to run on |
|
||||
| `interval` | No | Block interval (default: 1 = every block) |
|
||||
| `startBlock` | No | Block to start from |
|
||||
| `endBlock` | No | Block to end at |
|
||||
|
||||
## Handler Function
|
||||
|
||||
**Important:** Block handlers require `preload_handlers: true` in config.yaml.
|
||||
|
||||
```typescript
|
||||
onBlock(
|
||||
{ name: "HourlyStats", chain: 1, interval: 300 },
|
||||
async ({ block, context }) => {
|
||||
// block.number - The block number
|
||||
// block.chainId - The chain ID
|
||||
// context - Same as event handlers
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
## Time-Based Intervals
|
||||
|
||||
Convert time to blocks:
|
||||
|
||||
```typescript
|
||||
// Every 60 minutes on Ethereum (12s blocks)
|
||||
const interval = (60 * 60) / 12; // 300 blocks
|
||||
|
||||
// Every 60 minutes on Optimism (2s blocks)
|
||||
const interval = (60 * 60) / 2; // 1800 blocks
|
||||
```
|
||||
|
||||
## Multichain Block Handlers
|
||||
|
||||
Use `forEach` for multiple chains:
|
||||
|
||||
```typescript
|
||||
import { onBlock } from "generated";
|
||||
|
||||
[
|
||||
{ chain: 1 as const, startBlock: 19783636, interval: 300 },
|
||||
{ chain: 10 as const, startBlock: 119534316, interval: 1800 },
|
||||
].forEach(({ chain, startBlock, interval }) => {
|
||||
onBlock(
|
||||
{ name: "HourlyPrice", chain, startBlock, interval },
|
||||
async ({ block, context }) => {
|
||||
// Handle block...
|
||||
}
|
||||
);
|
||||
});
|
||||
```
|
||||
|
||||
## Different Historical vs Realtime Intervals
|
||||
|
||||
Speed up historical sync with larger intervals:
|
||||
|
||||
```typescript
|
||||
const realtimeBlock = 19783636;
|
||||
|
||||
// Historical: every 1000 blocks
|
||||
onBlock(
|
||||
{
|
||||
name: "HistoricalHandler",
|
||||
chain: 1,
|
||||
endBlock: realtimeBlock - 1,
|
||||
interval: 1000,
|
||||
},
|
||||
async ({ block, context }) => { /* ... */ }
|
||||
);
|
||||
|
||||
// Realtime: every block
|
||||
onBlock(
|
||||
{
|
||||
name: "RealtimeHandler",
|
||||
chain: 1,
|
||||
startBlock: realtimeBlock,
|
||||
interval: 1,
|
||||
},
|
||||
async ({ block, context }) => { /* ... */ }
|
||||
);
|
||||
```
|
||||
|
||||
## Preset/Initial Data Handler
|
||||
|
||||
Load initial data on block 0:
|
||||
|
||||
```typescript
|
||||
onBlock(
|
||||
{
|
||||
name: "Preset",
|
||||
chain: 1,
|
||||
startBlock: 0,
|
||||
endBlock: 0,
|
||||
},
|
||||
async ({ block, context }) => {
|
||||
// Skip preload phase for initial data
|
||||
if (context.isPreload) return;
|
||||
|
||||
const users = await fetch("https://api.example.com/users");
|
||||
for (const user of users) {
|
||||
context.User.set({
|
||||
id: user.id,
|
||||
address: user.address,
|
||||
name: user.name,
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
## Use Cases
|
||||
|
||||
- **Hourly/Daily aggregations** - Price snapshots, volume totals
|
||||
- **Time-series data** - Create periodic data points
|
||||
- **Initial state loading** - Populate entities on startup
|
||||
- **State snapshots** - Capture state at intervals
|
||||
|
||||
## Limitations
|
||||
|
||||
- Requires `preload_handlers: true`
|
||||
- Ordered multichain mode not supported
|
||||
- Only EVM chains (no Fuel)
|
||||
- No test framework support yet
|
||||
- Only `block.number` and `block.chainId` available
|
||||
Reference in New Issue
Block a user