@apibara/evm-rpc 2.1.0-beta.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/dist/index.cjs +479 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +49 -0
- package/dist/index.d.mts +49 -0
- package/dist/index.d.ts +49 -0
- package/dist/index.mjs +477 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +36 -0
- package/src/block.ts +13 -0
- package/src/filter.ts +61 -0
- package/src/index.ts +3 -0
- package/src/log-fetcher.ts +195 -0
- package/src/range-oracle.ts +61 -0
- package/src/stream-config.ts +299 -0
- package/src/transform.ts +70 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { RpcStreamConfig, ValidateFilterResult, FetchCursorArgs, BlockInfo, FetchBlockRangeArgs, FetchBlockRangeResult, FetchBlockByNumberArgs, FetchBlockByNumberResult } from '@apibara/protocol/rpc';
|
|
2
|
+
import { EIP1193Parameters, PublicRpcSchema } from 'viem';
|
|
3
|
+
import { BlockHeader as BlockHeader$1, Log as Log$1, HeaderFilter, LogFilter as LogFilter$1 } from '@apibara/evm';
|
|
4
|
+
|
|
5
|
+
type BlockHeader = BlockHeader$1;
|
|
6
|
+
type Log = Omit<Log$1, "logIndexInTransaction">;
|
|
7
|
+
type Block = {
|
|
8
|
+
header: BlockHeader;
|
|
9
|
+
logs: Log[];
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
type Filter = {
|
|
13
|
+
header?: HeaderFilter;
|
|
14
|
+
logs: LogFilter[];
|
|
15
|
+
};
|
|
16
|
+
type LogFilter = Pick<LogFilter$1, "address" | "topics" | "strict" | "id">;
|
|
17
|
+
|
|
18
|
+
type RequestParameters = EIP1193Parameters<PublicRpcSchema>;
|
|
19
|
+
type RequestReturnType<method extends RequestParameters["method"]> = Extract<PublicRpcSchema[number], {
|
|
20
|
+
Method: method;
|
|
21
|
+
}>["ReturnType"];
|
|
22
|
+
type ViemRpcClient = {
|
|
23
|
+
request: <TParams extends RequestParameters>(params: TParams) => Promise<RequestReturnType<TParams["method"]>>;
|
|
24
|
+
};
|
|
25
|
+
type EvmRpcStreamOptions = {
|
|
26
|
+
/** How many blocks to fetch in a single eth_getLogs call. */
|
|
27
|
+
getLogsRangeSize?: bigint;
|
|
28
|
+
/** How often to refresh the head block. */
|
|
29
|
+
headRefreshIntervalMs?: number;
|
|
30
|
+
/** How often to refresh the finalized block. */
|
|
31
|
+
finalizedRefreshIntervalMs?: number;
|
|
32
|
+
};
|
|
33
|
+
declare class EvmRpcStream extends RpcStreamConfig<Filter, Block> {
|
|
34
|
+
private client;
|
|
35
|
+
private options;
|
|
36
|
+
private blockRangeOracle;
|
|
37
|
+
constructor(client: ViemRpcClient, options?: EvmRpcStreamOptions);
|
|
38
|
+
headRefreshIntervalMs(): number;
|
|
39
|
+
finalizedRefreshIntervalMs(): number;
|
|
40
|
+
validateFilter(filter: Filter): ValidateFilterResult;
|
|
41
|
+
fetchCursor(args: FetchCursorArgs): Promise<BlockInfo | null>;
|
|
42
|
+
fetchBlockRange({ startBlock, finalizedBlock, filter, }: FetchBlockRangeArgs<Filter>): Promise<FetchBlockRangeResult<Block>>;
|
|
43
|
+
fetchBlockByNumber({ blockNumber, expectedParentBlockHash, filter, }: FetchBlockByNumberArgs<Filter>): Promise<FetchBlockByNumberResult<Block>>;
|
|
44
|
+
private fetchLogsForRangeWithRetry;
|
|
45
|
+
private fetchLogsByBlockHashWithRetry;
|
|
46
|
+
private fetchBlockHeaderByNumberWithRetry;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export { type Block, type BlockHeader, EvmRpcStream, type Filter, type Log, type LogFilter };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,477 @@
|
|
|
1
|
+
import { RpcStreamConfig } from '@apibara/protocol/rpc';
|
|
2
|
+
import { isHex, formatBlock, hexToNumber, numberToHex, pad, trim, toHex } from 'viem';
|
|
3
|
+
|
|
4
|
+
function validateFilter(filter) {
|
|
5
|
+
if (!filter.logs || filter.logs.length === 0) {
|
|
6
|
+
return { valid: false, error: "Missing logs filter" };
|
|
7
|
+
}
|
|
8
|
+
let logFilterIndex = 0;
|
|
9
|
+
for (const logFilter of filter.logs ?? []) {
|
|
10
|
+
if (logFilter.address === void 0 && (logFilter.topics?.length ?? 0) === 0) {
|
|
11
|
+
return {
|
|
12
|
+
valid: false,
|
|
13
|
+
error: `Must provide at least one address or topic in log filter at position ${logFilterIndex}`
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
if (logFilter.address) {
|
|
17
|
+
if (!isHex(logFilter.address)) {
|
|
18
|
+
return {
|
|
19
|
+
valid: false,
|
|
20
|
+
error: "Invalid address format. Expected 0x-prefixed hex string"
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
if (logFilter.topics) {
|
|
25
|
+
for (let i = 0; i < logFilter.topics.length; i++) {
|
|
26
|
+
const topic = logFilter.topics[i];
|
|
27
|
+
if (topic === null) {
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
if (!isHex(topic)) {
|
|
31
|
+
return {
|
|
32
|
+
valid: false,
|
|
33
|
+
error: `Invalid topic at index ${i}: ${topic}. Must be null or a 0x-prefixed hex string`
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
logFilterIndex++;
|
|
39
|
+
}
|
|
40
|
+
return { valid: true };
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function viemRpcLogToDna(viemLog) {
|
|
44
|
+
if (viemLog.logIndex === null || viemLog.transactionIndex === null || viemLog.transactionHash === null) {
|
|
45
|
+
throw new Error(
|
|
46
|
+
"Invalid log: missing required fields: logIndex, transactionIndex, transactionHash"
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
filterIds: [],
|
|
51
|
+
logIndex: hexToNumber(viemLog.logIndex),
|
|
52
|
+
address: viemLog.address,
|
|
53
|
+
topics: viemLog.topics,
|
|
54
|
+
data: viemLog.data,
|
|
55
|
+
transactionIndex: hexToNumber(viemLog.transactionIndex),
|
|
56
|
+
transactionHash: viemLog.transactionHash,
|
|
57
|
+
transactionStatus: viemLog.removed ? "reverted" : "succeeded"
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
function rpcBlockHeaderToDna(block) {
|
|
61
|
+
const formattedBlock = formatBlock(block);
|
|
62
|
+
return viemBlockHeaderToDna(formattedBlock);
|
|
63
|
+
}
|
|
64
|
+
function viemBlockHeaderToDna(viemBlock) {
|
|
65
|
+
if (viemBlock.number === null || !viemBlock.hash) {
|
|
66
|
+
throw new Error(
|
|
67
|
+
`Invalid block: missing required fields (number: ${viemBlock.number}, hash: ${viemBlock.hash})`
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
blockNumber: viemBlock.number,
|
|
72
|
+
blockHash: viemBlock.hash,
|
|
73
|
+
parentBlockHash: viemBlock.parentHash,
|
|
74
|
+
unclesHash: viemBlock.sha3Uncles,
|
|
75
|
+
miner: viemBlock.miner ?? void 0,
|
|
76
|
+
stateRoot: viemBlock.stateRoot,
|
|
77
|
+
transactionsRoot: viemBlock.transactionsRoot,
|
|
78
|
+
receiptsRoot: viemBlock.receiptsRoot,
|
|
79
|
+
logsBloom: viemBlock.logsBloom ?? void 0,
|
|
80
|
+
difficulty: viemBlock.difficulty,
|
|
81
|
+
gasLimit: viemBlock.gasLimit,
|
|
82
|
+
gasUsed: viemBlock.gasUsed,
|
|
83
|
+
timestamp: new Date(Number(viemBlock.timestamp) * 1e3),
|
|
84
|
+
extraData: viemBlock.extraData,
|
|
85
|
+
mixHash: viemBlock.mixHash ?? void 0,
|
|
86
|
+
nonce: viemBlock.nonce ? BigInt(viemBlock.nonce) : void 0,
|
|
87
|
+
baseFeePerGas: viemBlock.baseFeePerGas ?? void 0,
|
|
88
|
+
withdrawalsRoot: viemBlock.withdrawalsRoot ?? void 0,
|
|
89
|
+
totalDifficulty: viemBlock.totalDifficulty ?? void 0,
|
|
90
|
+
blobGasUsed: viemBlock.blobGasUsed ?? void 0,
|
|
91
|
+
excessBlobGas: viemBlock.excessBlobGas ?? void 0,
|
|
92
|
+
parentBeaconBlockRoot: viemBlock.parentBeaconBlockRoot ?? void 0,
|
|
93
|
+
requestsHash: void 0
|
|
94
|
+
// TODO: check
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
async function fetchLogsByBlockHash({
|
|
99
|
+
client,
|
|
100
|
+
blockHash,
|
|
101
|
+
filter
|
|
102
|
+
}) {
|
|
103
|
+
if (!filter.logs || filter.logs.length === 0) {
|
|
104
|
+
return { logs: [] };
|
|
105
|
+
}
|
|
106
|
+
const responses = await Promise.all(
|
|
107
|
+
filter.logs.map(async (logFilter) => {
|
|
108
|
+
const logs = await client.request({
|
|
109
|
+
method: "eth_getLogs",
|
|
110
|
+
params: [
|
|
111
|
+
{
|
|
112
|
+
blockHash,
|
|
113
|
+
address: logFilter.address,
|
|
114
|
+
topics: logFilter.topics ? [...logFilter.topics] : void 0
|
|
115
|
+
}
|
|
116
|
+
]
|
|
117
|
+
});
|
|
118
|
+
return { logs, logFilter };
|
|
119
|
+
})
|
|
120
|
+
);
|
|
121
|
+
const allLogs = [];
|
|
122
|
+
const seenLogsByIndex = {};
|
|
123
|
+
for (const { logFilter, logs } of responses) {
|
|
124
|
+
for (const log of logs) {
|
|
125
|
+
if (log.blockNumber === null) {
|
|
126
|
+
throw new Error("Log block number is null");
|
|
127
|
+
}
|
|
128
|
+
const refinedLog = refineLog(log, logFilter);
|
|
129
|
+
if (refinedLog) {
|
|
130
|
+
const existingPosition = seenLogsByIndex[refinedLog.logIndex];
|
|
131
|
+
if (existingPosition !== void 0) {
|
|
132
|
+
const existingLog = allLogs[existingPosition];
|
|
133
|
+
existingLog.filterIds.push(logFilter.id ?? 0);
|
|
134
|
+
} else {
|
|
135
|
+
refinedLog.filterIds.push(logFilter.id ?? 0);
|
|
136
|
+
allLogs.push(refinedLog);
|
|
137
|
+
seenLogsByIndex[refinedLog.logIndex] = allLogs.length - 1;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return { logs: allLogs };
|
|
143
|
+
}
|
|
144
|
+
async function fetchLogsForRange({
|
|
145
|
+
client,
|
|
146
|
+
fromBlock,
|
|
147
|
+
toBlock,
|
|
148
|
+
filter
|
|
149
|
+
}) {
|
|
150
|
+
const logsByBlock = {};
|
|
151
|
+
if (!filter.logs || filter.logs.length === 0) {
|
|
152
|
+
return { logs: logsByBlock, blockNumbers: [] };
|
|
153
|
+
}
|
|
154
|
+
const responses = await Promise.all(
|
|
155
|
+
filter.logs.map(async (logFilter) => {
|
|
156
|
+
const logs = await client.request({
|
|
157
|
+
method: "eth_getLogs",
|
|
158
|
+
params: [
|
|
159
|
+
{
|
|
160
|
+
fromBlock: numberToHex(fromBlock),
|
|
161
|
+
toBlock: numberToHex(toBlock),
|
|
162
|
+
address: logFilter.address,
|
|
163
|
+
topics: logFilter.topics ? [...logFilter.topics] : void 0
|
|
164
|
+
}
|
|
165
|
+
]
|
|
166
|
+
});
|
|
167
|
+
return { logs, logFilter };
|
|
168
|
+
})
|
|
169
|
+
);
|
|
170
|
+
const blockNumbers = /* @__PURE__ */ new Set();
|
|
171
|
+
const seenLogsByBlockNumberAndIndex = {};
|
|
172
|
+
for (const { logFilter, logs } of responses) {
|
|
173
|
+
for (const log of logs) {
|
|
174
|
+
if (log.blockNumber === null) {
|
|
175
|
+
throw new Error("Log block number is null");
|
|
176
|
+
}
|
|
177
|
+
const refinedLog = refineLog(log, logFilter);
|
|
178
|
+
if (refinedLog) {
|
|
179
|
+
const blockNumber = hexToNumber(log.blockNumber);
|
|
180
|
+
blockNumbers.add(BigInt(blockNumber));
|
|
181
|
+
if (!logsByBlock[blockNumber]) {
|
|
182
|
+
logsByBlock[blockNumber] = [];
|
|
183
|
+
}
|
|
184
|
+
if (!seenLogsByBlockNumberAndIndex[blockNumber]) {
|
|
185
|
+
seenLogsByBlockNumberAndIndex[blockNumber] = {};
|
|
186
|
+
}
|
|
187
|
+
const existingPosition = seenLogsByBlockNumberAndIndex[blockNumber][refinedLog.logIndex];
|
|
188
|
+
if (existingPosition !== void 0) {
|
|
189
|
+
const existingLog = logsByBlock[blockNumber][existingPosition];
|
|
190
|
+
existingLog.filterIds.push(logFilter.id ?? 0);
|
|
191
|
+
} else {
|
|
192
|
+
refinedLog.filterIds.push(logFilter.id ?? 0);
|
|
193
|
+
logsByBlock[blockNumber].push(refinedLog);
|
|
194
|
+
seenLogsByBlockNumberAndIndex[blockNumber][refinedLog.logIndex] = logsByBlock[blockNumber].length - 1;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return { logs: logsByBlock, blockNumbers: Array.from(blockNumbers) };
|
|
200
|
+
}
|
|
201
|
+
function refineLog(log, filter) {
|
|
202
|
+
if (log.removed) {
|
|
203
|
+
return null;
|
|
204
|
+
}
|
|
205
|
+
const filterTopics = filter.topics ?? [];
|
|
206
|
+
if (filter.strict && log.topics.length !== filterTopics.length) {
|
|
207
|
+
return null;
|
|
208
|
+
}
|
|
209
|
+
if (filterTopics.length === 0) {
|
|
210
|
+
return viemRpcLogToDna(log);
|
|
211
|
+
}
|
|
212
|
+
if (log.topics.length < filterTopics.length) {
|
|
213
|
+
return null;
|
|
214
|
+
}
|
|
215
|
+
for (let i = 0; i < filterTopics.length; i++) {
|
|
216
|
+
const filterTopic = filterTopics[i];
|
|
217
|
+
const logTopic = log.topics[i];
|
|
218
|
+
if (filterTopic === null)
|
|
219
|
+
continue;
|
|
220
|
+
if (!logTopic)
|
|
221
|
+
return null;
|
|
222
|
+
if (!isHex(filterTopic) || !isHex(logTopic)) {
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
225
|
+
const normalizedFilter = pad(trim(filterTopic), { size: 32 });
|
|
226
|
+
const normalizedLog = pad(trim(logTopic), { size: 32 });
|
|
227
|
+
if (normalizedFilter !== normalizedLog) {
|
|
228
|
+
return null;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return viemRpcLogToDna(log);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
const BLOCK_RANGE_ERROR_PATTERNS = ["invalid block range params"];
|
|
235
|
+
function createBlockRangeOracle({
|
|
236
|
+
startingSize,
|
|
237
|
+
minSize = 1n,
|
|
238
|
+
maxSize = 10000n
|
|
239
|
+
}) {
|
|
240
|
+
let currentSize = startingSize;
|
|
241
|
+
return {
|
|
242
|
+
clampRange(original) {
|
|
243
|
+
const start = original.start;
|
|
244
|
+
let end = original.end;
|
|
245
|
+
const newEnd = start + currentSize - 1n;
|
|
246
|
+
if (newEnd < end) {
|
|
247
|
+
end = newEnd;
|
|
248
|
+
}
|
|
249
|
+
return { start, end };
|
|
250
|
+
},
|
|
251
|
+
handleSuccess() {
|
|
252
|
+
},
|
|
253
|
+
handleError(error) {
|
|
254
|
+
if (error instanceof Error) {
|
|
255
|
+
const message = error.message.toLowerCase();
|
|
256
|
+
const isBlockRangeError = BLOCK_RANGE_ERROR_PATTERNS.some(
|
|
257
|
+
(pattern) => message.includes(pattern)
|
|
258
|
+
);
|
|
259
|
+
if (isBlockRangeError) {
|
|
260
|
+
if (currentSize > minSize) {
|
|
261
|
+
const newSize = currentSize / 2n;
|
|
262
|
+
currentSize = newSize > minSize ? newSize : minSize;
|
|
263
|
+
}
|
|
264
|
+
return { retry: true };
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
return { retry: false };
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
var __defProp = Object.defineProperty;
|
|
273
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
274
|
+
var __publicField = (obj, key, value) => {
|
|
275
|
+
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
276
|
+
return value;
|
|
277
|
+
};
|
|
278
|
+
class EvmRpcStream extends RpcStreamConfig {
|
|
279
|
+
constructor(client, options = {}) {
|
|
280
|
+
super();
|
|
281
|
+
this.client = client;
|
|
282
|
+
this.options = options;
|
|
283
|
+
__publicField(this, "blockRangeOracle");
|
|
284
|
+
this.blockRangeOracle = createBlockRangeOracle({
|
|
285
|
+
startingSize: options.getLogsRangeSize ?? 1000n,
|
|
286
|
+
// Use the provided size to limit the maximum range size
|
|
287
|
+
maxSize: options.getLogsRangeSize ? options.getLogsRangeSize : void 0
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
headRefreshIntervalMs() {
|
|
291
|
+
return this.options.headRefreshIntervalMs ?? 3e3;
|
|
292
|
+
}
|
|
293
|
+
finalizedRefreshIntervalMs() {
|
|
294
|
+
return this.options.finalizedRefreshIntervalMs ?? 3e4;
|
|
295
|
+
}
|
|
296
|
+
validateFilter(filter) {
|
|
297
|
+
return validateFilter(filter);
|
|
298
|
+
}
|
|
299
|
+
async fetchCursor(args) {
|
|
300
|
+
let block = null;
|
|
301
|
+
if (args.blockNumber !== void 0) {
|
|
302
|
+
const blockNumber = toHex(args.blockNumber);
|
|
303
|
+
block = await this.client.request({
|
|
304
|
+
method: "eth_getBlockByNumber",
|
|
305
|
+
params: [blockNumber, false]
|
|
306
|
+
});
|
|
307
|
+
} else if (args.blockTag) {
|
|
308
|
+
block = await this.client.request({
|
|
309
|
+
method: "eth_getBlockByNumber",
|
|
310
|
+
params: [args.blockTag, false]
|
|
311
|
+
});
|
|
312
|
+
} else if (args.blockHash) {
|
|
313
|
+
block = await this.client.request({
|
|
314
|
+
method: "eth_getBlockByHash",
|
|
315
|
+
params: [args.blockHash, false]
|
|
316
|
+
});
|
|
317
|
+
} else {
|
|
318
|
+
throw new Error(
|
|
319
|
+
"One of blockNumber, blockHash or blockTag must be provided"
|
|
320
|
+
);
|
|
321
|
+
}
|
|
322
|
+
if (!block) {
|
|
323
|
+
return null;
|
|
324
|
+
}
|
|
325
|
+
const formattedBlock = formatBlock(block);
|
|
326
|
+
if (formattedBlock.number === null) {
|
|
327
|
+
throw new Error("RPC block is missing required block number");
|
|
328
|
+
}
|
|
329
|
+
if (formattedBlock.hash === null) {
|
|
330
|
+
throw new Error("RPC block is missing required block hash");
|
|
331
|
+
}
|
|
332
|
+
return {
|
|
333
|
+
blockNumber: formattedBlock.number,
|
|
334
|
+
blockHash: formattedBlock.hash,
|
|
335
|
+
parentBlockHash: formattedBlock.parentHash
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
async fetchBlockRange({
|
|
339
|
+
startBlock,
|
|
340
|
+
finalizedBlock,
|
|
341
|
+
filter
|
|
342
|
+
}) {
|
|
343
|
+
const { start: fromBlock, end: toBlock } = this.blockRangeOracle.clampRange(
|
|
344
|
+
{ start: startBlock, end: finalizedBlock }
|
|
345
|
+
);
|
|
346
|
+
const { logs: logsByBlockNumber, blockNumbers } = await this.fetchLogsForRangeWithRetry({
|
|
347
|
+
fromBlock,
|
|
348
|
+
toBlock,
|
|
349
|
+
filter
|
|
350
|
+
});
|
|
351
|
+
const data = [];
|
|
352
|
+
const blockNumberResponses = [];
|
|
353
|
+
if (filter.header === "always") {
|
|
354
|
+
for (let blockNumber = fromBlock; blockNumber <= toBlock; blockNumber++) {
|
|
355
|
+
blockNumberResponses.push(
|
|
356
|
+
this.fetchBlockHeaderByNumberWithRetry({
|
|
357
|
+
blockNumber
|
|
358
|
+
})
|
|
359
|
+
);
|
|
360
|
+
}
|
|
361
|
+
} else {
|
|
362
|
+
for (const blockNumber of blockNumbers) {
|
|
363
|
+
blockNumberResponses.push(
|
|
364
|
+
this.fetchBlockHeaderByNumberWithRetry({
|
|
365
|
+
blockNumber
|
|
366
|
+
})
|
|
367
|
+
);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
const blockNumbersWithHeader = await Promise.all(blockNumberResponses);
|
|
371
|
+
for (const { blockNumber, header } of blockNumbersWithHeader) {
|
|
372
|
+
const logs = logsByBlockNumber[Number(blockNumber)] ?? [];
|
|
373
|
+
data.push({
|
|
374
|
+
cursor: void 0,
|
|
375
|
+
endCursor: { orderKey: blockNumber },
|
|
376
|
+
block: { header, logs }
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
return { startBlock: fromBlock, endBlock: toBlock, data };
|
|
380
|
+
}
|
|
381
|
+
async fetchBlockByNumber({
|
|
382
|
+
blockNumber,
|
|
383
|
+
expectedParentBlockHash,
|
|
384
|
+
filter
|
|
385
|
+
}) {
|
|
386
|
+
const { header } = await this.fetchBlockHeaderByNumberWithRetry({
|
|
387
|
+
blockNumber
|
|
388
|
+
});
|
|
389
|
+
if (header.blockHash === void 0) {
|
|
390
|
+
throw new Error(`Block ${blockNumber} has no block hash`);
|
|
391
|
+
}
|
|
392
|
+
const blockInfo = {
|
|
393
|
+
blockNumber: header.blockNumber,
|
|
394
|
+
blockHash: header.blockHash,
|
|
395
|
+
parentBlockHash: header.parentBlockHash
|
|
396
|
+
};
|
|
397
|
+
if (header.parentBlockHash !== expectedParentBlockHash) {
|
|
398
|
+
return {
|
|
399
|
+
status: "reorg",
|
|
400
|
+
blockInfo
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
const { logs } = await this.fetchLogsByBlockHashWithRetry({
|
|
404
|
+
blockHash: header.blockHash,
|
|
405
|
+
filter
|
|
406
|
+
});
|
|
407
|
+
let cursor = void 0;
|
|
408
|
+
if (blockNumber > 0n) {
|
|
409
|
+
cursor = {
|
|
410
|
+
orderKey: blockNumber - 1n,
|
|
411
|
+
uniqueKey: header.parentBlockHash
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
const endCursor = {
|
|
415
|
+
orderKey: blockNumber,
|
|
416
|
+
uniqueKey: header.blockHash
|
|
417
|
+
};
|
|
418
|
+
let block = null;
|
|
419
|
+
if (filter.header === "always" || logs.length > 0) {
|
|
420
|
+
block = {
|
|
421
|
+
header,
|
|
422
|
+
logs
|
|
423
|
+
};
|
|
424
|
+
}
|
|
425
|
+
return {
|
|
426
|
+
status: "success",
|
|
427
|
+
blockInfo,
|
|
428
|
+
data: {
|
|
429
|
+
cursor,
|
|
430
|
+
endCursor,
|
|
431
|
+
block
|
|
432
|
+
}
|
|
433
|
+
};
|
|
434
|
+
}
|
|
435
|
+
async fetchLogsForRangeWithRetry({
|
|
436
|
+
fromBlock,
|
|
437
|
+
toBlock,
|
|
438
|
+
filter
|
|
439
|
+
}) {
|
|
440
|
+
try {
|
|
441
|
+
return await fetchLogsForRange({
|
|
442
|
+
client: this.client,
|
|
443
|
+
fromBlock,
|
|
444
|
+
toBlock,
|
|
445
|
+
filter
|
|
446
|
+
});
|
|
447
|
+
} catch (error) {
|
|
448
|
+
this.blockRangeOracle.handleError(error);
|
|
449
|
+
throw error;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
async fetchLogsByBlockHashWithRetry({
|
|
453
|
+
blockHash,
|
|
454
|
+
filter
|
|
455
|
+
}) {
|
|
456
|
+
return await fetchLogsByBlockHash({
|
|
457
|
+
client: this.client,
|
|
458
|
+
blockHash,
|
|
459
|
+
filter
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
async fetchBlockHeaderByNumberWithRetry({
|
|
463
|
+
blockNumber
|
|
464
|
+
}) {
|
|
465
|
+
const block = await this.client.request({
|
|
466
|
+
method: "eth_getBlockByNumber",
|
|
467
|
+
params: [numberToHex(blockNumber), false]
|
|
468
|
+
});
|
|
469
|
+
if (block === null) {
|
|
470
|
+
throw new Error(`Block ${blockNumber} not found`);
|
|
471
|
+
}
|
|
472
|
+
return { header: rpcBlockHeaderToDna(block), blockNumber };
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
export { EvmRpcStream };
|
|
477
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../src/filter.ts","../src/transform.ts","../src/log-fetcher.ts","../src/range-oracle.ts","../src/stream-config.ts"],"sourcesContent":["import type { LogFilter as DnaLogFilter, HeaderFilter } from \"@apibara/evm\";\nimport type { ValidateFilterResult } from \"@apibara/protocol/rpc\";\nimport { isHex } from \"viem\";\n\nexport type Filter = {\n header?: HeaderFilter;\n logs: LogFilter[];\n};\n\nexport type LogFilter = Pick<\n DnaLogFilter,\n \"address\" | \"topics\" | \"strict\" | \"id\"\n>;\n\nexport function validateFilter(filter: Filter): ValidateFilterResult {\n if (!filter.logs || filter.logs.length === 0) {\n return { valid: false, error: \"Missing logs filter\" };\n }\n\n let logFilterIndex = 0;\n for (const logFilter of filter.logs ?? []) {\n if (\n logFilter.address === undefined &&\n (logFilter.topics?.length ?? 0) === 0\n ) {\n return {\n valid: false,\n error: `Must provide at least one address or topic in log filter at position ${logFilterIndex}`,\n };\n }\n\n if (logFilter.address) {\n if (!isHex(logFilter.address)) {\n return {\n valid: false,\n error: \"Invalid address format. Expected 0x-prefixed hex string\",\n };\n }\n }\n\n if (logFilter.topics) {\n for (let i = 0; i < logFilter.topics.length; i++) {\n const topic = logFilter.topics[i];\n if (topic === null) {\n continue;\n }\n\n if (!isHex(topic)) {\n return {\n valid: false,\n error: `Invalid topic at index ${i}: ${topic}. Must be null or a 0x-prefixed hex string`,\n };\n }\n }\n }\n\n logFilterIndex++;\n }\n\n return { valid: true };\n}\n","import {\n type RpcBlock,\n type RpcLog,\n type Block as ViemBlock,\n formatBlock,\n hexToNumber,\n} from \"viem\";\nimport type { BlockHeader as DnaBlockHeader, Log as DnaLog } from \"./block\";\n\nexport function viemRpcLogToDna(viemLog: RpcLog): DnaLog {\n if (\n viemLog.logIndex === null ||\n viemLog.transactionIndex === null ||\n viemLog.transactionHash === null\n ) {\n throw new Error(\n \"Invalid log: missing required fields: logIndex, transactionIndex, transactionHash\",\n );\n }\n\n return {\n filterIds: [],\n logIndex: hexToNumber(viemLog.logIndex),\n address: viemLog.address,\n topics: viemLog.topics,\n data: viemLog.data,\n transactionIndex: hexToNumber(viemLog.transactionIndex),\n transactionHash: viemLog.transactionHash,\n transactionStatus: viemLog.removed ? \"reverted\" : \"succeeded\",\n };\n}\n\nexport function rpcBlockHeaderToDna(block: RpcBlock): DnaBlockHeader {\n const formattedBlock = formatBlock(block);\n return viemBlockHeaderToDna(formattedBlock);\n}\n\nexport function viemBlockHeaderToDna(viemBlock: ViemBlock): DnaBlockHeader {\n if (viemBlock.number === null || !viemBlock.hash) {\n throw new Error(\n `Invalid block: missing required fields (number: ${viemBlock.number}, hash: ${viemBlock.hash})`,\n );\n }\n\n return {\n blockNumber: viemBlock.number,\n blockHash: viemBlock.hash,\n parentBlockHash: viemBlock.parentHash,\n unclesHash: viemBlock.sha3Uncles,\n miner: viemBlock.miner ?? undefined,\n stateRoot: viemBlock.stateRoot,\n transactionsRoot: viemBlock.transactionsRoot,\n receiptsRoot: viemBlock.receiptsRoot,\n logsBloom: viemBlock.logsBloom ?? undefined,\n difficulty: viemBlock.difficulty,\n gasLimit: viemBlock.gasLimit,\n gasUsed: viemBlock.gasUsed,\n timestamp: new Date(Number(viemBlock.timestamp) * 1000),\n extraData: viemBlock.extraData,\n mixHash: viemBlock.mixHash ?? undefined,\n nonce: viemBlock.nonce ? BigInt(viemBlock.nonce) : undefined,\n baseFeePerGas: viemBlock.baseFeePerGas ?? undefined,\n withdrawalsRoot: viemBlock.withdrawalsRoot ?? undefined,\n totalDifficulty: viemBlock.totalDifficulty ?? undefined,\n blobGasUsed: viemBlock.blobGasUsed ?? undefined,\n excessBlobGas: viemBlock.excessBlobGas ?? undefined,\n parentBeaconBlockRoot: viemBlock.parentBeaconBlockRoot ?? undefined,\n requestsHash: undefined, // TODO: check\n };\n}\n","import type { Bytes } from \"@apibara/protocol\";\nimport type { RpcLog } from \"viem\";\nimport { hexToNumber, isHex, numberToHex, pad, trim } from \"viem\";\nimport type { Log } from \"./block\";\nimport type { Filter, LogFilter } from \"./filter\";\nimport type { ViemRpcClient } from \"./stream-config\";\nimport { viemRpcLogToDna } from \"./transform\";\n\nexport async function fetchLogsByBlockHash({\n client,\n blockHash,\n filter,\n}: {\n client: ViemRpcClient;\n blockHash: Bytes;\n filter: Filter;\n}): Promise<{ logs: Log[] }> {\n if (!filter.logs || filter.logs.length === 0) {\n return { logs: [] };\n }\n\n const responses = await Promise.all(\n filter.logs.map(async (logFilter) => {\n const logs = await client.request({\n method: \"eth_getLogs\",\n params: [\n {\n blockHash,\n address: logFilter.address,\n topics: logFilter.topics ? [...logFilter.topics] : undefined,\n },\n ],\n });\n return { logs, logFilter };\n }),\n );\n\n // Multiple calls may have produced the same log.\n // We track all the logs (by their logIndex, which is unique within a block).\n // logIndex -> position\n const allLogs: Log[] = [];\n const seenLogsByIndex: Record<number, number> = {};\n\n for (const { logFilter, logs } of responses) {\n for (const log of logs) {\n if (log.blockNumber === null) {\n throw new Error(\"Log block number is null\");\n }\n\n const refinedLog = refineLog(log, logFilter);\n\n if (refinedLog) {\n const existingPosition = seenLogsByIndex[refinedLog.logIndex];\n\n if (existingPosition !== undefined) {\n const existingLog = allLogs[existingPosition];\n (existingLog.filterIds as number[]).push(logFilter.id ?? 0);\n } else {\n (refinedLog.filterIds as number[]).push(logFilter.id ?? 0);\n\n allLogs.push(refinedLog);\n seenLogsByIndex[refinedLog.logIndex] = allLogs.length - 1;\n }\n }\n }\n }\n\n return { logs: allLogs };\n}\n\nexport async function fetchLogsForRange({\n client,\n fromBlock,\n toBlock,\n filter,\n}: {\n client: ViemRpcClient;\n fromBlock: bigint;\n toBlock: bigint;\n filter: Filter;\n}): Promise<{ logs: Record<number, Log[]>; blockNumbers: bigint[] }> {\n const logsByBlock: Record<number, Log[]> = {};\n\n if (!filter.logs || filter.logs.length === 0) {\n return { logs: logsByBlock, blockNumbers: [] };\n }\n\n const responses = await Promise.all(\n filter.logs.map(async (logFilter) => {\n const logs = await client.request({\n method: \"eth_getLogs\",\n params: [\n {\n fromBlock: numberToHex(fromBlock),\n toBlock: numberToHex(toBlock),\n address: logFilter.address,\n topics: logFilter.topics ? [...logFilter.topics] : undefined,\n },\n ],\n });\n return { logs, logFilter };\n }),\n );\n\n const blockNumbers = new Set<bigint>();\n\n // Multiple calls may have produced the same log.\n // We track all the logs (by their logIndex, which is unique within a block).\n // blockNumber -> logIndex -> position\n const seenLogsByBlockNumberAndIndex: Record<\n number,\n Record<number, number>\n > = {};\n\n for (const { logFilter, logs } of responses) {\n for (const log of logs) {\n if (log.blockNumber === null) {\n throw new Error(\"Log block number is null\");\n }\n\n const refinedLog = refineLog(log, logFilter);\n\n if (refinedLog) {\n const blockNumber = hexToNumber(log.blockNumber);\n blockNumbers.add(BigInt(blockNumber));\n\n if (!logsByBlock[blockNumber]) {\n logsByBlock[blockNumber] = [];\n }\n\n if (!seenLogsByBlockNumberAndIndex[blockNumber]) {\n seenLogsByBlockNumberAndIndex[blockNumber] = {};\n }\n\n const existingPosition =\n seenLogsByBlockNumberAndIndex[blockNumber][refinedLog.logIndex];\n\n if (existingPosition !== undefined) {\n const existingLog = logsByBlock[blockNumber][existingPosition];\n (existingLog.filterIds as number[]).push(logFilter.id ?? 0);\n } else {\n (refinedLog.filterIds as number[]).push(logFilter.id ?? 0);\n\n logsByBlock[blockNumber].push(refinedLog);\n seenLogsByBlockNumberAndIndex[blockNumber][refinedLog.logIndex] =\n logsByBlock[blockNumber].length - 1;\n }\n }\n }\n }\n\n return { logs: logsByBlock, blockNumbers: Array.from(blockNumbers) };\n}\n\nfunction refineLog(log: RpcLog, filter: LogFilter): Log | null {\n if (log.removed) {\n return null;\n }\n\n const filterTopics = filter.topics ?? [];\n // Strict mode\n if (filter.strict && log.topics.length !== filterTopics.length) {\n return null;\n }\n\n if (filterTopics.length === 0) {\n return viemRpcLogToDna(log);\n }\n\n if (log.topics.length < filterTopics.length) {\n return null;\n }\n\n for (let i = 0; i < filterTopics.length; i++) {\n const filterTopic = filterTopics[i];\n const logTopic = log.topics[i];\n\n if (filterTopic === null) continue;\n\n if (!logTopic) return null;\n\n if (!isHex(filterTopic) || !isHex(logTopic)) {\n return null;\n }\n\n const normalizedFilter = pad(trim(filterTopic), { size: 32 });\n const normalizedLog = pad(trim(logTopic), { size: 32 });\n\n if (normalizedFilter !== normalizedLog) {\n return null;\n }\n }\n\n return viemRpcLogToDna(log);\n}\n","const BLOCK_RANGE_ERROR_PATTERNS = [\"invalid block range params\"] as const;\n\nexport type BlockRange = {\n start: bigint;\n end: bigint;\n};\n\nexport type BlockRangeOracle = {\n clampRange(original: BlockRange): BlockRange;\n handleSuccess(): void;\n handleError(error: unknown): { retry: boolean };\n};\n\nexport function createBlockRangeOracle({\n startingSize,\n minSize = 1n,\n maxSize = 10_000n,\n}: {\n startingSize: bigint;\n minSize?: bigint;\n maxSize?: bigint;\n}): BlockRangeOracle {\n let currentSize = startingSize;\n\n return {\n clampRange(original: BlockRange): BlockRange {\n const start = original.start;\n let end = original.end;\n\n const newEnd = start + currentSize - 1n;\n if (newEnd < end) {\n end = newEnd;\n }\n\n return { start, end };\n },\n handleSuccess(): void {\n // TODO: we can track how many successful requests and increase the size.\n // Probably want to receive the number of logs as argument and have a \"target\"\n },\n handleError(error: unknown): { retry: boolean } {\n if (error instanceof Error) {\n const message = error.message.toLowerCase();\n const isBlockRangeError = BLOCK_RANGE_ERROR_PATTERNS.some((pattern) =>\n message.includes(pattern),\n );\n\n if (isBlockRangeError) {\n if (currentSize > minSize) {\n const newSize = currentSize / 2n;\n currentSize = newSize > minSize ? newSize : minSize;\n }\n\n return { retry: true };\n }\n }\n\n return { retry: false };\n },\n };\n}\n","import type { Bytes } from \"@apibara/protocol\";\nimport {\n type BlockInfo,\n type FetchBlockByNumberArgs,\n type FetchBlockByNumberResult,\n type FetchBlockRangeArgs,\n type FetchBlockRangeResult,\n type FetchBlockResult,\n type FetchCursorArgs,\n RpcStreamConfig,\n type ValidateFilterResult,\n} from \"@apibara/protocol/rpc\";\nimport {\n type EIP1193Parameters,\n type PublicRpcSchema,\n type RpcBlock,\n formatBlock,\n numberToHex,\n toHex,\n} from \"viem\";\nimport type { Block, Log } from \"./block\";\nimport { type Filter, validateFilter } from \"./filter\";\nimport { fetchLogsByBlockHash, fetchLogsForRange } from \"./log-fetcher\";\nimport { type BlockRangeOracle, createBlockRangeOracle } from \"./range-oracle\";\nimport { rpcBlockHeaderToDna } from \"./transform\";\n\nexport type RequestParameters = EIP1193Parameters<PublicRpcSchema>;\n\nexport type RequestReturnType<method extends RequestParameters[\"method\"]> =\n Extract<PublicRpcSchema[number], { Method: method }>[\"ReturnType\"];\n\n// Require just the bare minimum from the provided viem client.\nexport type ViemRpcClient = {\n request: <TParams extends RequestParameters>(\n params: TParams,\n ) => Promise<RequestReturnType<TParams[\"method\"]>>;\n};\n\nexport type EvmRpcStreamOptions = {\n /** How many blocks to fetch in a single eth_getLogs call. */\n getLogsRangeSize?: bigint;\n /** How often to refresh the head block. */\n headRefreshIntervalMs?: number;\n /** How often to refresh the finalized block. */\n finalizedRefreshIntervalMs?: number;\n};\n\nexport class EvmRpcStream extends RpcStreamConfig<Filter, Block> {\n private blockRangeOracle: BlockRangeOracle;\n\n constructor(\n private client: ViemRpcClient,\n private options: EvmRpcStreamOptions = {},\n ) {\n super();\n\n this.blockRangeOracle = createBlockRangeOracle({\n startingSize: options.getLogsRangeSize ?? 1_000n,\n // Use the provided size to limit the maximum range size\n maxSize: options.getLogsRangeSize ? options.getLogsRangeSize : undefined,\n });\n }\n\n headRefreshIntervalMs(): number {\n return this.options.headRefreshIntervalMs ?? 3_000;\n }\n\n finalizedRefreshIntervalMs(): number {\n return this.options.finalizedRefreshIntervalMs ?? 30_000;\n }\n\n validateFilter(filter: Filter): ValidateFilterResult {\n return validateFilter(filter);\n }\n\n async fetchCursor(args: FetchCursorArgs): Promise<BlockInfo | null> {\n let block: RpcBlock | null = null;\n if (args.blockNumber !== undefined) {\n const blockNumber = toHex(args.blockNumber);\n block = await this.client.request({\n method: \"eth_getBlockByNumber\",\n params: [blockNumber, false],\n });\n } else if (args.blockTag) {\n block = await this.client.request({\n method: \"eth_getBlockByNumber\",\n params: [args.blockTag, false],\n });\n } else if (args.blockHash) {\n block = await this.client.request({\n method: \"eth_getBlockByHash\",\n params: [args.blockHash, false],\n });\n } else {\n throw new Error(\n \"One of blockNumber, blockHash or blockTag must be provided\",\n );\n }\n\n if (!block) {\n return null;\n }\n\n const formattedBlock = formatBlock(block);\n\n if (formattedBlock.number === null) {\n throw new Error(\"RPC block is missing required block number\");\n }\n\n if (formattedBlock.hash === null) {\n throw new Error(\"RPC block is missing required block hash\");\n }\n\n return {\n blockNumber: formattedBlock.number,\n blockHash: formattedBlock.hash,\n parentBlockHash: formattedBlock.parentHash,\n };\n }\n\n async fetchBlockRange({\n startBlock,\n finalizedBlock,\n filter,\n }: FetchBlockRangeArgs<Filter>): Promise<FetchBlockRangeResult<Block>> {\n const { start: fromBlock, end: toBlock } = this.blockRangeOracle.clampRange(\n { start: startBlock, end: finalizedBlock },\n );\n\n // console.log(\"Fetching block range\", fromBlock, toBlock, filter);\n\n const { logs: logsByBlockNumber, blockNumbers } =\n await this.fetchLogsForRangeWithRetry({\n fromBlock,\n toBlock,\n filter,\n });\n\n // If the client needs all headers, we iterate over the range and fetch headers\n // and then join them with the logs\n // Otherwise, we drive the block number iteration from the fetched logs.\n const data: FetchBlockResult<Block>[] = [];\n\n // Fetch block headers in parallel to optimize batching.\n const blockNumberResponses = [];\n if (filter.header === \"always\") {\n for (let blockNumber = fromBlock; blockNumber <= toBlock; blockNumber++) {\n blockNumberResponses.push(\n this.fetchBlockHeaderByNumberWithRetry({\n blockNumber,\n }),\n );\n }\n } else {\n for (const blockNumber of blockNumbers) {\n blockNumberResponses.push(\n this.fetchBlockHeaderByNumberWithRetry({\n blockNumber,\n }),\n );\n }\n }\n\n const blockNumbersWithHeader = await Promise.all(blockNumberResponses);\n for (const { blockNumber, header } of blockNumbersWithHeader) {\n const logs = logsByBlockNumber[Number(blockNumber)] ?? [];\n\n data.push({\n cursor: undefined,\n endCursor: { orderKey: blockNumber },\n block: { header, logs },\n });\n }\n\n return { startBlock: fromBlock, endBlock: toBlock, data };\n }\n\n async fetchBlockByNumber({\n blockNumber,\n expectedParentBlockHash,\n filter,\n }: FetchBlockByNumberArgs<Filter>): Promise<FetchBlockByNumberResult<Block>> {\n // Fetch block header and check it matches the expected parent block hash.\n const { header } = await this.fetchBlockHeaderByNumberWithRetry({\n blockNumber,\n });\n\n if (header.blockHash === undefined) {\n throw new Error(`Block ${blockNumber} has no block hash`);\n }\n\n const blockInfo: BlockInfo = {\n blockNumber: header.blockNumber,\n blockHash: header.blockHash,\n parentBlockHash: header.parentBlockHash,\n };\n\n if (header.parentBlockHash !== expectedParentBlockHash) {\n return {\n status: \"reorg\",\n blockInfo,\n };\n }\n\n // Use the hash from the current block to fetch logs in a reorg-safe way.\n const { logs } = await this.fetchLogsByBlockHashWithRetry({\n blockHash: header.blockHash,\n filter,\n });\n\n let cursor = undefined;\n if (blockNumber > 0n) {\n cursor = {\n orderKey: blockNumber - 1n,\n uniqueKey: header.parentBlockHash,\n };\n }\n const endCursor = {\n orderKey: blockNumber,\n uniqueKey: header.blockHash,\n };\n\n let block = null;\n\n // TODO: handle header on new block.\n if (filter.header === \"always\" || logs.length > 0) {\n block = {\n header,\n logs,\n };\n }\n\n return {\n status: \"success\",\n blockInfo,\n data: {\n cursor,\n endCursor,\n block,\n },\n };\n }\n\n private async fetchLogsForRangeWithRetry({\n fromBlock,\n toBlock,\n filter,\n }: {\n fromBlock: bigint;\n toBlock: bigint;\n filter: Filter;\n }): Promise<{ logs: Record<number, Log[]>; blockNumbers: bigint[] }> {\n // TODO: implement retry\n try {\n return await fetchLogsForRange({\n client: this.client,\n fromBlock,\n toBlock,\n filter,\n });\n } catch (error) {\n this.blockRangeOracle.handleError(error);\n throw error;\n }\n }\n\n private async fetchLogsByBlockHashWithRetry({\n blockHash,\n filter,\n }: {\n blockHash: Bytes;\n filter: Filter;\n }): Promise<{ logs: Log[] }> {\n // TODO: implement retry\n return await fetchLogsByBlockHash({\n client: this.client,\n blockHash,\n filter,\n });\n }\n\n private async fetchBlockHeaderByNumberWithRetry({\n blockNumber,\n }: {\n blockNumber: bigint;\n }) {\n // TODO: implement retry\n const block = await this.client.request({\n method: \"eth_getBlockByNumber\",\n params: [numberToHex(blockNumber), false],\n });\n\n if (block === null) {\n throw new Error(`Block ${blockNumber} not found`);\n }\n\n return { header: rpcBlockHeaderToDna(block), blockNumber };\n }\n}\n"],"names":[],"mappings":";;;AAcO,SAAS,eAAe,MAAsC,EAAA;AACnE,EAAA,IAAI,CAAC,MAAO,CAAA,IAAA,IAAQ,MAAO,CAAA,IAAA,CAAK,WAAW,CAAG,EAAA;AAC5C,IAAA,OAAO,EAAE,KAAA,EAAO,KAAO,EAAA,KAAA,EAAO,qBAAsB,EAAA,CAAA;AAAA,GACtD;AAEA,EAAA,IAAI,cAAiB,GAAA,CAAA,CAAA;AACrB,EAAA,KAAA,MAAW,SAAa,IAAA,MAAA,CAAO,IAAQ,IAAA,EAAI,EAAA;AACzC,IAAA,IACE,UAAU,OAAY,KAAA,KAAA,CAAA,IAAA,CACrB,UAAU,MAAQ,EAAA,MAAA,IAAU,OAAO,CACpC,EAAA;AACA,MAAO,OAAA;AAAA,QACL,KAAO,EAAA,KAAA;AAAA,QACP,KAAA,EAAO,wEAAwE,cAAc,CAAA,CAAA;AAAA,OAC/F,CAAA;AAAA,KACF;AAEA,IAAA,IAAI,UAAU,OAAS,EAAA;AACrB,MAAA,IAAI,CAAC,KAAA,CAAM,SAAU,CAAA,OAAO,CAAG,EAAA;AAC7B,QAAO,OAAA;AAAA,UACL,KAAO,EAAA,KAAA;AAAA,UACP,KAAO,EAAA,yDAAA;AAAA,SACT,CAAA;AAAA,OACF;AAAA,KACF;AAEA,IAAA,IAAI,UAAU,MAAQ,EAAA;AACpB,MAAA,KAAA,IAAS,IAAI,CAAG,EAAA,CAAA,GAAI,SAAU,CAAA,MAAA,CAAO,QAAQ,CAAK,EAAA,EAAA;AAChD,QAAM,MAAA,KAAA,GAAQ,SAAU,CAAA,MAAA,CAAO,CAAC,CAAA,CAAA;AAChC,QAAA,IAAI,UAAU,IAAM,EAAA;AAClB,UAAA,SAAA;AAAA,SACF;AAEA,QAAI,IAAA,CAAC,KAAM,CAAA,KAAK,CAAG,EAAA;AACjB,UAAO,OAAA;AAAA,YACL,KAAO,EAAA,KAAA;AAAA,YACP,KAAO,EAAA,CAAA,uBAAA,EAA0B,CAAC,CAAA,EAAA,EAAK,KAAK,CAAA,0CAAA,CAAA;AAAA,WAC9C,CAAA;AAAA,SACF;AAAA,OACF;AAAA,KACF;AAEA,IAAA,cAAA,EAAA,CAAA;AAAA,GACF;AAEA,EAAO,OAAA,EAAE,OAAO,IAAK,EAAA,CAAA;AACvB;;ACnDO,SAAS,gBAAgB,OAAyB,EAAA;AACvD,EACE,IAAA,OAAA,CAAQ,aAAa,IACrB,IAAA,OAAA,CAAQ,qBAAqB,IAC7B,IAAA,OAAA,CAAQ,oBAAoB,IAC5B,EAAA;AACA,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,mFAAA;AAAA,KACF,CAAA;AAAA,GACF;AAEA,EAAO,OAAA;AAAA,IACL,WAAW,EAAC;AAAA,IACZ,QAAA,EAAU,WAAY,CAAA,OAAA,CAAQ,QAAQ,CAAA;AAAA,IACtC,SAAS,OAAQ,CAAA,OAAA;AAAA,IACjB,QAAQ,OAAQ,CAAA,MAAA;AAAA,IAChB,MAAM,OAAQ,CAAA,IAAA;AAAA,IACd,gBAAA,EAAkB,WAAY,CAAA,OAAA,CAAQ,gBAAgB,CAAA;AAAA,IACtD,iBAAiB,OAAQ,CAAA,eAAA;AAAA,IACzB,iBAAA,EAAmB,OAAQ,CAAA,OAAA,GAAU,UAAa,GAAA,WAAA;AAAA,GACpD,CAAA;AACF,CAAA;AAEO,SAAS,oBAAoB,KAAiC,EAAA;AACnE,EAAM,MAAA,cAAA,GAAiB,YAAY,KAAK,CAAA,CAAA;AACxC,EAAA,OAAO,qBAAqB,cAAc,CAAA,CAAA;AAC5C,CAAA;AAEO,SAAS,qBAAqB,SAAsC,EAAA;AACzE,EAAA,IAAI,SAAU,CAAA,MAAA,KAAW,IAAQ,IAAA,CAAC,UAAU,IAAM,EAAA;AAChD,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAmD,gDAAA,EAAA,SAAA,CAAU,MAAM,CAAA,QAAA,EAAW,UAAU,IAAI,CAAA,CAAA,CAAA;AAAA,KAC9F,CAAA;AAAA,GACF;AAEA,EAAO,OAAA;AAAA,IACL,aAAa,SAAU,CAAA,MAAA;AAAA,IACvB,WAAW,SAAU,CAAA,IAAA;AAAA,IACrB,iBAAiB,SAAU,CAAA,UAAA;AAAA,IAC3B,YAAY,SAAU,CAAA,UAAA;AAAA,IACtB,KAAA,EAAO,UAAU,KAAS,IAAA,KAAA,CAAA;AAAA,IAC1B,WAAW,SAAU,CAAA,SAAA;AAAA,IACrB,kBAAkB,SAAU,CAAA,gBAAA;AAAA,IAC5B,cAAc,SAAU,CAAA,YAAA;AAAA,IACxB,SAAA,EAAW,UAAU,SAAa,IAAA,KAAA,CAAA;AAAA,IAClC,YAAY,SAAU,CAAA,UAAA;AAAA,IACtB,UAAU,SAAU,CAAA,QAAA;AAAA,IACpB,SAAS,SAAU,CAAA,OAAA;AAAA,IACnB,WAAW,IAAI,IAAA,CAAK,OAAO,SAAU,CAAA,SAAS,IAAI,GAAI,CAAA;AAAA,IACtD,WAAW,SAAU,CAAA,SAAA;AAAA,IACrB,OAAA,EAAS,UAAU,OAAW,IAAA,KAAA,CAAA;AAAA,IAC9B,OAAO,SAAU,CAAA,KAAA,GAAQ,MAAO,CAAA,SAAA,CAAU,KAAK,CAAI,GAAA,KAAA,CAAA;AAAA,IACnD,aAAA,EAAe,UAAU,aAAiB,IAAA,KAAA,CAAA;AAAA,IAC1C,eAAA,EAAiB,UAAU,eAAmB,IAAA,KAAA,CAAA;AAAA,IAC9C,eAAA,EAAiB,UAAU,eAAmB,IAAA,KAAA,CAAA;AAAA,IAC9C,WAAA,EAAa,UAAU,WAAe,IAAA,KAAA,CAAA;AAAA,IACtC,aAAA,EAAe,UAAU,aAAiB,IAAA,KAAA,CAAA;AAAA,IAC1C,qBAAA,EAAuB,UAAU,qBAAyB,IAAA,KAAA,CAAA;AAAA,IAC1D,YAAc,EAAA,KAAA,CAAA;AAAA;AAAA,GAChB,CAAA;AACF;;AC7DA,eAAsB,oBAAqB,CAAA;AAAA,EACzC,MAAA;AAAA,EACA,SAAA;AAAA,EACA,MAAA;AACF,CAI6B,EAAA;AAC3B,EAAA,IAAI,CAAC,MAAO,CAAA,IAAA,IAAQ,MAAO,CAAA,IAAA,CAAK,WAAW,CAAG,EAAA;AAC5C,IAAO,OAAA,EAAE,IAAM,EAAA,EAAG,EAAA,CAAA;AAAA,GACpB;AAEA,EAAM,MAAA,SAAA,GAAY,MAAM,OAAQ,CAAA,GAAA;AAAA,IAC9B,MAAO,CAAA,IAAA,CAAK,GAAI,CAAA,OAAO,SAAc,KAAA;AACnC,MAAM,MAAA,IAAA,GAAO,MAAM,MAAA,CAAO,OAAQ,CAAA;AAAA,QAChC,MAAQ,EAAA,aAAA;AAAA,QACR,MAAQ,EAAA;AAAA,UACN;AAAA,YACE,SAAA;AAAA,YACA,SAAS,SAAU,CAAA,OAAA;AAAA,YACnB,QAAQ,SAAU,CAAA,MAAA,GAAS,CAAC,GAAG,SAAA,CAAU,MAAM,CAAI,GAAA,KAAA,CAAA;AAAA,WACrD;AAAA,SACF;AAAA,OACD,CAAA,CAAA;AACD,MAAO,OAAA,EAAE,MAAM,SAAU,EAAA,CAAA;AAAA,KAC1B,CAAA;AAAA,GACH,CAAA;AAKA,EAAA,MAAM,UAAiB,EAAC,CAAA;AACxB,EAAA,MAAM,kBAA0C,EAAC,CAAA;AAEjD,EAAA,KAAA,MAAW,EAAE,SAAA,EAAW,IAAK,EAAA,IAAK,SAAW,EAAA;AAC3C,IAAA,KAAA,MAAW,OAAO,IAAM,EAAA;AACtB,MAAI,IAAA,GAAA,CAAI,gBAAgB,IAAM,EAAA;AAC5B,QAAM,MAAA,IAAI,MAAM,0BAA0B,CAAA,CAAA;AAAA,OAC5C;AAEA,MAAM,MAAA,UAAA,GAAa,SAAU,CAAA,GAAA,EAAK,SAAS,CAAA,CAAA;AAE3C,MAAA,IAAI,UAAY,EAAA;AACd,QAAM,MAAA,gBAAA,GAAmB,eAAgB,CAAA,UAAA,CAAW,QAAQ,CAAA,CAAA;AAE5D,QAAA,IAAI,qBAAqB,KAAW,CAAA,EAAA;AAClC,UAAM,MAAA,WAAA,GAAc,QAAQ,gBAAgB,CAAA,CAAA;AAC5C,UAAC,WAAY,CAAA,SAAA,CAAuB,IAAK,CAAA,SAAA,CAAU,MAAM,CAAC,CAAA,CAAA;AAAA,SACrD,MAAA;AACL,UAAC,UAAW,CAAA,SAAA,CAAuB,IAAK,CAAA,SAAA,CAAU,MAAM,CAAC,CAAA,CAAA;AAEzD,UAAA,OAAA,CAAQ,KAAK,UAAU,CAAA,CAAA;AACvB,UAAA,eAAA,CAAgB,UAAW,CAAA,QAAQ,CAAI,GAAA,OAAA,CAAQ,MAAS,GAAA,CAAA,CAAA;AAAA,SAC1D;AAAA,OACF;AAAA,KACF;AAAA,GACF;AAEA,EAAO,OAAA,EAAE,MAAM,OAAQ,EAAA,CAAA;AACzB,CAAA;AAEA,eAAsB,iBAAkB,CAAA;AAAA,EACtC,MAAA;AAAA,EACA,SAAA;AAAA,EACA,OAAA;AAAA,EACA,MAAA;AACF,CAKqE,EAAA;AACnE,EAAA,MAAM,cAAqC,EAAC,CAAA;AAE5C,EAAA,IAAI,CAAC,MAAO,CAAA,IAAA,IAAQ,MAAO,CAAA,IAAA,CAAK,WAAW,CAAG,EAAA;AAC5C,IAAA,OAAO,EAAE,IAAA,EAAM,WAAa,EAAA,YAAA,EAAc,EAAG,EAAA,CAAA;AAAA,GAC/C;AAEA,EAAM,MAAA,SAAA,GAAY,MAAM,OAAQ,CAAA,GAAA;AAAA,IAC9B,MAAO,CAAA,IAAA,CAAK,GAAI,CAAA,OAAO,SAAc,KAAA;AACnC,MAAM,MAAA,IAAA,GAAO,MAAM,MAAA,CAAO,OAAQ,CAAA;AAAA,QAChC,MAAQ,EAAA,aAAA;AAAA,QACR,MAAQ,EAAA;AAAA,UACN;AAAA,YACE,SAAA,EAAW,YAAY,SAAS,CAAA;AAAA,YAChC,OAAA,EAAS,YAAY,OAAO,CAAA;AAAA,YAC5B,SAAS,SAAU,CAAA,OAAA;AAAA,YACnB,QAAQ,SAAU,CAAA,MAAA,GAAS,CAAC,GAAG,SAAA,CAAU,MAAM,CAAI,GAAA,KAAA,CAAA;AAAA,WACrD;AAAA,SACF;AAAA,OACD,CAAA,CAAA;AACD,MAAO,OAAA,EAAE,MAAM,SAAU,EAAA,CAAA;AAAA,KAC1B,CAAA;AAAA,GACH,CAAA;AAEA,EAAM,MAAA,YAAA,uBAAmB,GAAY,EAAA,CAAA;AAKrC,EAAA,MAAM,gCAGF,EAAC,CAAA;AAEL,EAAA,KAAA,MAAW,EAAE,SAAA,EAAW,IAAK,EAAA,IAAK,SAAW,EAAA;AAC3C,IAAA,KAAA,MAAW,OAAO,IAAM,EAAA;AACtB,MAAI,IAAA,GAAA,CAAI,gBAAgB,IAAM,EAAA;AAC5B,QAAM,MAAA,IAAI,MAAM,0BAA0B,CAAA,CAAA;AAAA,OAC5C;AAEA,MAAM,MAAA,UAAA,GAAa,SAAU,CAAA,GAAA,EAAK,SAAS,CAAA,CAAA;AAE3C,MAAA,IAAI,UAAY,EAAA;AACd,QAAM,MAAA,WAAA,GAAc,WAAY,CAAA,GAAA,CAAI,WAAW,CAAA,CAAA;AAC/C,QAAa,YAAA,CAAA,GAAA,CAAI,MAAO,CAAA,WAAW,CAAC,CAAA,CAAA;AAEpC,QAAI,IAAA,CAAC,WAAY,CAAA,WAAW,CAAG,EAAA;AAC7B,UAAY,WAAA,CAAA,WAAW,IAAI,EAAC,CAAA;AAAA,SAC9B;AAEA,QAAI,IAAA,CAAC,6BAA8B,CAAA,WAAW,CAAG,EAAA;AAC/C,UAA8B,6BAAA,CAAA,WAAW,IAAI,EAAC,CAAA;AAAA,SAChD;AAEA,QAAA,MAAM,gBACJ,GAAA,6BAAA,CAA8B,WAAW,CAAA,CAAE,WAAW,QAAQ,CAAA,CAAA;AAEhE,QAAA,IAAI,qBAAqB,KAAW,CAAA,EAAA;AAClC,UAAA,MAAM,WAAc,GAAA,WAAA,CAAY,WAAW,CAAA,CAAE,gBAAgB,CAAA,CAAA;AAC7D,UAAC,WAAY,CAAA,SAAA,CAAuB,IAAK,CAAA,SAAA,CAAU,MAAM,CAAC,CAAA,CAAA;AAAA,SACrD,MAAA;AACL,UAAC,UAAW,CAAA,SAAA,CAAuB,IAAK,CAAA,SAAA,CAAU,MAAM,CAAC,CAAA,CAAA;AAEzD,UAAY,WAAA,CAAA,WAAW,CAAE,CAAA,IAAA,CAAK,UAAU,CAAA,CAAA;AACxC,UAA8B,6BAAA,CAAA,WAAW,EAAE,UAAW,CAAA,QAAQ,IAC5D,WAAY,CAAA,WAAW,EAAE,MAAS,GAAA,CAAA,CAAA;AAAA,SACtC;AAAA,OACF;AAAA,KACF;AAAA,GACF;AAEA,EAAA,OAAO,EAAE,IAAM,EAAA,WAAA,EAAa,cAAc,KAAM,CAAA,IAAA,CAAK,YAAY,CAAE,EAAA,CAAA;AACrE,CAAA;AAEA,SAAS,SAAA,CAAU,KAAa,MAA+B,EAAA;AAC7D,EAAA,IAAI,IAAI,OAAS,EAAA;AACf,IAAO,OAAA,IAAA,CAAA;AAAA,GACT;AAEA,EAAM,MAAA,YAAA,GAAe,MAAO,CAAA,MAAA,IAAU,EAAC,CAAA;AAEvC,EAAA,IAAI,OAAO,MAAU,IAAA,GAAA,CAAI,MAAO,CAAA,MAAA,KAAW,aAAa,MAAQ,EAAA;AAC9D,IAAO,OAAA,IAAA,CAAA;AAAA,GACT;AAEA,EAAI,IAAA,YAAA,CAAa,WAAW,CAAG,EAAA;AAC7B,IAAA,OAAO,gBAAgB,GAAG,CAAA,CAAA;AAAA,GAC5B;AAEA,EAAA,IAAI,GAAI,CAAA,MAAA,CAAO,MAAS,GAAA,YAAA,CAAa,MAAQ,EAAA;AAC3C,IAAO,OAAA,IAAA,CAAA;AAAA,GACT;AAEA,EAAA,KAAA,IAAS,CAAI,GAAA,CAAA,EAAG,CAAI,GAAA,YAAA,CAAa,QAAQ,CAAK,EAAA,EAAA;AAC5C,IAAM,MAAA,WAAA,GAAc,aAAa,CAAC,CAAA,CAAA;AAClC,IAAM,MAAA,QAAA,GAAW,GAAI,CAAA,MAAA,CAAO,CAAC,CAAA,CAAA;AAE7B,IAAA,IAAI,WAAgB,KAAA,IAAA;AAAM,MAAA,SAAA;AAE1B,IAAA,IAAI,CAAC,QAAA;AAAU,MAAO,OAAA,IAAA,CAAA;AAEtB,IAAA,IAAI,CAAC,KAAM,CAAA,WAAW,KAAK,CAAC,KAAA,CAAM,QAAQ,CAAG,EAAA;AAC3C,MAAO,OAAA,IAAA,CAAA;AAAA,KACT;AAEA,IAAM,MAAA,gBAAA,GAAmB,IAAI,IAAK,CAAA,WAAW,GAAG,EAAE,IAAA,EAAM,IAAI,CAAA,CAAA;AAC5D,IAAM,MAAA,aAAA,GAAgB,IAAI,IAAK,CAAA,QAAQ,GAAG,EAAE,IAAA,EAAM,IAAI,CAAA,CAAA;AAEtD,IAAA,IAAI,qBAAqB,aAAe,EAAA;AACtC,MAAO,OAAA,IAAA,CAAA;AAAA,KACT;AAAA,GACF;AAEA,EAAA,OAAO,gBAAgB,GAAG,CAAA,CAAA;AAC5B;;AClMA,MAAM,0BAAA,GAA6B,CAAC,4BAA4B,CAAA,CAAA;AAazD,SAAS,sBAAuB,CAAA;AAAA,EACrC,YAAA;AAAA,EACA,OAAU,GAAA,EAAA;AAAA,EACV,OAAU,GAAA,MAAA;AACZ,CAIqB,EAAA;AACnB,EAAA,IAAI,WAAc,GAAA,YAAA,CAAA;AAElB,EAAO,OAAA;AAAA,IACL,WAAW,QAAkC,EAAA;AAC3C,MAAA,MAAM,QAAQ,QAAS,CAAA,KAAA,CAAA;AACvB,MAAA,IAAI,MAAM,QAAS,CAAA,GAAA,CAAA;AAEnB,MAAM,MAAA,MAAA,GAAS,QAAQ,WAAc,GAAA,EAAA,CAAA;AACrC,MAAA,IAAI,SAAS,GAAK,EAAA;AAChB,QAAM,GAAA,GAAA,MAAA,CAAA;AAAA,OACR;AAEA,MAAO,OAAA,EAAE,OAAO,GAAI,EAAA,CAAA;AAAA,KACtB;AAAA,IACA,aAAsB,GAAA;AAAA,KAGtB;AAAA,IACA,YAAY,KAAoC,EAAA;AAC9C,MAAA,IAAI,iBAAiB,KAAO,EAAA;AAC1B,QAAM,MAAA,OAAA,GAAU,KAAM,CAAA,OAAA,CAAQ,WAAY,EAAA,CAAA;AAC1C,QAAA,MAAM,oBAAoB,0BAA2B,CAAA,IAAA;AAAA,UAAK,CAAC,OAAA,KACzD,OAAQ,CAAA,QAAA,CAAS,OAAO,CAAA;AAAA,SAC1B,CAAA;AAEA,QAAA,IAAI,iBAAmB,EAAA;AACrB,UAAA,IAAI,cAAc,OAAS,EAAA;AACzB,YAAA,MAAM,UAAU,WAAc,GAAA,EAAA,CAAA;AAC9B,YAAc,WAAA,GAAA,OAAA,GAAU,UAAU,OAAU,GAAA,OAAA,CAAA;AAAA,WAC9C;AAEA,UAAO,OAAA,EAAE,OAAO,IAAK,EAAA,CAAA;AAAA,SACvB;AAAA,OACF;AAEA,MAAO,OAAA,EAAE,OAAO,KAAM,EAAA,CAAA;AAAA,KACxB;AAAA,GACF,CAAA;AACF;;;;;;;;ACbO,MAAM,qBAAqB,eAA+B,CAAA;AAAA,EAG/D,WACU,CAAA,MAAA,EACA,OAA+B,GAAA,EACvC,EAAA;AACA,IAAM,KAAA,EAAA,CAAA;AAHE,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA,CAAA;AACA,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA,CAAA;AAJV,IAAQ,aAAA,CAAA,IAAA,EAAA,kBAAA,CAAA,CAAA;AAQN,IAAA,IAAA,CAAK,mBAAmB,sBAAuB,CAAA;AAAA,MAC7C,YAAA,EAAc,QAAQ,gBAAoB,IAAA,KAAA;AAAA;AAAA,MAE1C,OAAS,EAAA,OAAA,CAAQ,gBAAmB,GAAA,OAAA,CAAQ,gBAAmB,GAAA,KAAA,CAAA;AAAA,KAChE,CAAA,CAAA;AAAA,GACH;AAAA,EAEA,qBAAgC,GAAA;AAC9B,IAAO,OAAA,IAAA,CAAK,QAAQ,qBAAyB,IAAA,GAAA,CAAA;AAAA,GAC/C;AAAA,EAEA,0BAAqC,GAAA;AACnC,IAAO,OAAA,IAAA,CAAK,QAAQ,0BAA8B,IAAA,GAAA,CAAA;AAAA,GACpD;AAAA,EAEA,eAAe,MAAsC,EAAA;AACnD,IAAA,OAAO,eAAe,MAAM,CAAA,CAAA;AAAA,GAC9B;AAAA,EAEA,MAAM,YAAY,IAAkD,EAAA;AAClE,IAAA,IAAI,KAAyB,GAAA,IAAA,CAAA;AAC7B,IAAI,IAAA,IAAA,CAAK,gBAAgB,KAAW,CAAA,EAAA;AAClC,MAAM,MAAA,WAAA,GAAc,KAAM,CAAA,IAAA,CAAK,WAAW,CAAA,CAAA;AAC1C,MAAQ,KAAA,GAAA,MAAM,IAAK,CAAA,MAAA,CAAO,OAAQ,CAAA;AAAA,QAChC,MAAQ,EAAA,sBAAA;AAAA,QACR,MAAA,EAAQ,CAAC,WAAA,EAAa,KAAK,CAAA;AAAA,OAC5B,CAAA,CAAA;AAAA,KACH,MAAA,IAAW,KAAK,QAAU,EAAA;AACxB,MAAQ,KAAA,GAAA,MAAM,IAAK,CAAA,MAAA,CAAO,OAAQ,CAAA;AAAA,QAChC,MAAQ,EAAA,sBAAA;AAAA,QACR,MAAQ,EAAA,CAAC,IAAK,CAAA,QAAA,EAAU,KAAK,CAAA;AAAA,OAC9B,CAAA,CAAA;AAAA,KACH,MAAA,IAAW,KAAK,SAAW,EAAA;AACzB,MAAQ,KAAA,GAAA,MAAM,IAAK,CAAA,MAAA,CAAO,OAAQ,CAAA;AAAA,QAChC,MAAQ,EAAA,oBAAA;AAAA,QACR,MAAQ,EAAA,CAAC,IAAK,CAAA,SAAA,EAAW,KAAK,CAAA;AAAA,OAC/B,CAAA,CAAA;AAAA,KACI,MAAA;AACL,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,4DAAA;AAAA,OACF,CAAA;AAAA,KACF;AAEA,IAAA,IAAI,CAAC,KAAO,EAAA;AACV,MAAO,OAAA,IAAA,CAAA;AAAA,KACT;AAEA,IAAM,MAAA,cAAA,GAAiB,YAAY,KAAK,CAAA,CAAA;AAExC,IAAI,IAAA,cAAA,CAAe,WAAW,IAAM,EAAA;AAClC,MAAM,MAAA,IAAI,MAAM,4CAA4C,CAAA,CAAA;AAAA,KAC9D;AAEA,IAAI,IAAA,cAAA,CAAe,SAAS,IAAM,EAAA;AAChC,MAAM,MAAA,IAAI,MAAM,0CAA0C,CAAA,CAAA;AAAA,KAC5D;AAEA,IAAO,OAAA;AAAA,MACL,aAAa,cAAe,CAAA,MAAA;AAAA,MAC5B,WAAW,cAAe,CAAA,IAAA;AAAA,MAC1B,iBAAiB,cAAe,CAAA,UAAA;AAAA,KAClC,CAAA;AAAA,GACF;AAAA,EAEA,MAAM,eAAgB,CAAA;AAAA,IACpB,UAAA;AAAA,IACA,cAAA;AAAA,IACA,MAAA;AAAA,GACqE,EAAA;AACrE,IAAA,MAAM,EAAE,KAAO,EAAA,SAAA,EAAW,KAAK,OAAQ,EAAA,GAAI,KAAK,gBAAiB,CAAA,UAAA;AAAA,MAC/D,EAAE,KAAA,EAAO,UAAY,EAAA,GAAA,EAAK,cAAe,EAAA;AAAA,KAC3C,CAAA;AAIA,IAAA,MAAM,EAAE,IAAM,EAAA,iBAAA,EAAmB,cAC/B,GAAA,MAAM,KAAK,0BAA2B,CAAA;AAAA,MACpC,SAAA;AAAA,MACA,OAAA;AAAA,MACA,MAAA;AAAA,KACD,CAAA,CAAA;AAKH,IAAA,MAAM,OAAkC,EAAC,CAAA;AAGzC,IAAA,MAAM,uBAAuB,EAAC,CAAA;AAC9B,IAAI,IAAA,MAAA,CAAO,WAAW,QAAU,EAAA;AAC9B,MAAA,KAAA,IAAS,WAAc,GAAA,SAAA,EAAW,WAAe,IAAA,OAAA,EAAS,WAAe,EAAA,EAAA;AACvE,QAAqB,oBAAA,CAAA,IAAA;AAAA,UACnB,KAAK,iCAAkC,CAAA;AAAA,YACrC,WAAA;AAAA,WACD,CAAA;AAAA,SACH,CAAA;AAAA,OACF;AAAA,KACK,MAAA;AACL,MAAA,KAAA,MAAW,eAAe,YAAc,EAAA;AACtC,QAAqB,oBAAA,CAAA,IAAA;AAAA,UACnB,KAAK,iCAAkC,CAAA;AAAA,YACrC,WAAA;AAAA,WACD,CAAA;AAAA,SACH,CAAA;AAAA,OACF;AAAA,KACF;AAEA,IAAA,MAAM,sBAAyB,GAAA,MAAM,OAAQ,CAAA,GAAA,CAAI,oBAAoB,CAAA,CAAA;AACrE,IAAA,KAAA,MAAW,EAAE,WAAA,EAAa,MAAO,EAAA,IAAK,sBAAwB,EAAA;AAC5D,MAAA,MAAM,OAAO,iBAAkB,CAAA,MAAA,CAAO,WAAW,CAAC,KAAK,EAAC,CAAA;AAExD,MAAA,IAAA,CAAK,IAAK,CAAA;AAAA,QACR,MAAQ,EAAA,KAAA,CAAA;AAAA,QACR,SAAA,EAAW,EAAE,QAAA,EAAU,WAAY,EAAA;AAAA,QACnC,KAAA,EAAO,EAAE,MAAA,EAAQ,IAAK,EAAA;AAAA,OACvB,CAAA,CAAA;AAAA,KACH;AAEA,IAAA,OAAO,EAAE,UAAA,EAAY,SAAW,EAAA,QAAA,EAAU,SAAS,IAAK,EAAA,CAAA;AAAA,GAC1D;AAAA,EAEA,MAAM,kBAAmB,CAAA;AAAA,IACvB,WAAA;AAAA,IACA,uBAAA;AAAA,IACA,MAAA;AAAA,GAC2E,EAAA;AAE3E,IAAA,MAAM,EAAE,MAAA,EAAW,GAAA,MAAM,KAAK,iCAAkC,CAAA;AAAA,MAC9D,WAAA;AAAA,KACD,CAAA,CAAA;AAED,IAAI,IAAA,MAAA,CAAO,cAAc,KAAW,CAAA,EAAA;AAClC,MAAA,MAAM,IAAI,KAAA,CAAM,CAAS,MAAA,EAAA,WAAW,CAAoB,kBAAA,CAAA,CAAA,CAAA;AAAA,KAC1D;AAEA,IAAA,MAAM,SAAuB,GAAA;AAAA,MAC3B,aAAa,MAAO,CAAA,WAAA;AAAA,MACpB,WAAW,MAAO,CAAA,SAAA;AAAA,MAClB,iBAAiB,MAAO,CAAA,eAAA;AAAA,KAC1B,CAAA;AAEA,IAAI,IAAA,MAAA,CAAO,oBAAoB,uBAAyB,EAAA;AACtD,MAAO,OAAA;AAAA,QACL,MAAQ,EAAA,OAAA;AAAA,QACR,SAAA;AAAA,OACF,CAAA;AAAA,KACF;AAGA,IAAA,MAAM,EAAE,IAAA,EAAS,GAAA,MAAM,KAAK,6BAA8B,CAAA;AAAA,MACxD,WAAW,MAAO,CAAA,SAAA;AAAA,MAClB,MAAA;AAAA,KACD,CAAA,CAAA;AAED,IAAA,IAAI,MAAS,GAAA,KAAA,CAAA,CAAA;AACb,IAAA,IAAI,cAAc,EAAI,EAAA;AACpB,MAAS,MAAA,GAAA;AAAA,QACP,UAAU,WAAc,GAAA,EAAA;AAAA,QACxB,WAAW,MAAO,CAAA,eAAA;AAAA,OACpB,CAAA;AAAA,KACF;AACA,IAAA,MAAM,SAAY,GAAA;AAAA,MAChB,QAAU,EAAA,WAAA;AAAA,MACV,WAAW,MAAO,CAAA,SAAA;AAAA,KACpB,CAAA;AAEA,IAAA,IAAI,KAAQ,GAAA,IAAA,CAAA;AAGZ,IAAA,IAAI,MAAO,CAAA,MAAA,KAAW,QAAY,IAAA,IAAA,CAAK,SAAS,CAAG,EAAA;AACjD,MAAQ,KAAA,GAAA;AAAA,QACN,MAAA;AAAA,QACA,IAAA;AAAA,OACF,CAAA;AAAA,KACF;AAEA,IAAO,OAAA;AAAA,MACL,MAAQ,EAAA,SAAA;AAAA,MACR,SAAA;AAAA,MACA,IAAM,EAAA;AAAA,QACJ,MAAA;AAAA,QACA,SAAA;AAAA,QACA,KAAA;AAAA,OACF;AAAA,KACF,CAAA;AAAA,GACF;AAAA,EAEA,MAAc,0BAA2B,CAAA;AAAA,IACvC,SAAA;AAAA,IACA,OAAA;AAAA,IACA,MAAA;AAAA,GAKmE,EAAA;AAEnE,IAAI,IAAA;AACF,MAAA,OAAO,MAAM,iBAAkB,CAAA;AAAA,QAC7B,QAAQ,IAAK,CAAA,MAAA;AAAA,QACb,SAAA;AAAA,QACA,OAAA;AAAA,QACA,MAAA;AAAA,OACD,CAAA,CAAA;AAAA,aACM,KAAO,EAAA;AACd,MAAK,IAAA,CAAA,gBAAA,CAAiB,YAAY,KAAK,CAAA,CAAA;AACvC,MAAM,MAAA,KAAA,CAAA;AAAA,KACR;AAAA,GACF;AAAA,EAEA,MAAc,6BAA8B,CAAA;AAAA,IAC1C,SAAA;AAAA,IACA,MAAA;AAAA,GAI2B,EAAA;AAE3B,IAAA,OAAO,MAAM,oBAAqB,CAAA;AAAA,MAChC,QAAQ,IAAK,CAAA,MAAA;AAAA,MACb,SAAA;AAAA,MACA,MAAA;AAAA,KACD,CAAA,CAAA;AAAA,GACH;AAAA,EAEA,MAAc,iCAAkC,CAAA;AAAA,IAC9C,WAAA;AAAA,GAGC,EAAA;AAED,IAAA,MAAM,KAAQ,GAAA,MAAM,IAAK,CAAA,MAAA,CAAO,OAAQ,CAAA;AAAA,MACtC,MAAQ,EAAA,sBAAA;AAAA,MACR,MAAQ,EAAA,CAAC,WAAY,CAAA,WAAW,GAAG,KAAK,CAAA;AAAA,KACzC,CAAA,CAAA;AAED,IAAA,IAAI,UAAU,IAAM,EAAA;AAClB,MAAA,MAAM,IAAI,KAAA,CAAM,CAAS,MAAA,EAAA,WAAW,CAAY,UAAA,CAAA,CAAA,CAAA;AAAA,KAClD;AAEA,IAAA,OAAO,EAAE,MAAA,EAAQ,mBAAoB,CAAA,KAAK,GAAG,WAAY,EAAA,CAAA;AAAA,GAC3D;AACF;;;;"}
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@apibara/evm-rpc",
|
|
3
|
+
"version": "2.1.0-beta.41",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"files": [
|
|
6
|
+
"dist",
|
|
7
|
+
"src",
|
|
8
|
+
"README.md"
|
|
9
|
+
],
|
|
10
|
+
"main": "./dist/index.mjs",
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"import": "./dist/index.mjs",
|
|
16
|
+
"require": "./dist/index.cjs",
|
|
17
|
+
"default": "./dist/index.mjs"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build": "unbuild",
|
|
22
|
+
"typecheck": "tsc --noEmit",
|
|
23
|
+
"lint": "biome check .",
|
|
24
|
+
"lint:fix": "pnpm lint --write",
|
|
25
|
+
"format": "biome format . --write"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@types/node": "^20.12.13",
|
|
29
|
+
"unbuild": "^2.0.0"
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@apibara/protocol": "2.1.0-beta.42",
|
|
33
|
+
"@apibara/evm": "2.1.0-beta.42",
|
|
34
|
+
"viem": "^2.13.2"
|
|
35
|
+
}
|
|
36
|
+
}
|
package/src/block.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
BlockHeader as DnaBlockHeader,
|
|
3
|
+
Log as DnaLog,
|
|
4
|
+
} from "@apibara/evm";
|
|
5
|
+
|
|
6
|
+
export type BlockHeader = DnaBlockHeader;
|
|
7
|
+
|
|
8
|
+
export type Log = Omit<DnaLog, "logIndexInTransaction">;
|
|
9
|
+
|
|
10
|
+
export type Block = {
|
|
11
|
+
header: BlockHeader;
|
|
12
|
+
logs: Log[];
|
|
13
|
+
};
|