@apibara/evm-rpc 2.1.0-beta.44 → 2.1.0-beta.46

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/dist/index.cjs CHANGED
@@ -162,7 +162,7 @@ async function fetchLogsForRange({
162
162
  fromBlock: viem.numberToHex(fromBlock),
163
163
  toBlock: viem.numberToHex(toBlock),
164
164
  address: logFilter.address,
165
- topics: logFilter.topics ? [...logFilter.topics] : void 0
165
+ topics: logFilter.topics !== void 0 ? [...logFilter.topics] : void 0
166
166
  }
167
167
  ]
168
168
  });
@@ -198,7 +198,10 @@ async function fetchLogsForRange({
198
198
  }
199
199
  }
200
200
  }
201
- return { logs: logsByBlock, blockNumbers: Array.from(blockNumbers) };
201
+ const sortedBlockNumbers = Array.from(blockNumbers).sort(
202
+ (a, b) => a < b ? -1 : a > b ? 1 : 0
203
+ );
204
+ return { logs: logsByBlock, blockNumbers: sortedBlockNumbers };
202
205
  }
203
206
  function refineLog(log, filter) {
204
207
  if (log.removed) {
@@ -340,6 +343,7 @@ class EvmRpcStream extends rpc.RpcStreamConfig {
340
343
  async fetchBlockRange({
341
344
  startBlock,
342
345
  finalizedBlock,
346
+ force,
343
347
  filter
344
348
  }) {
345
349
  const { start: fromBlock, end: toBlock } = this.blockRangeOracle.clampRange(
@@ -360,6 +364,12 @@ class EvmRpcStream extends rpc.RpcStreamConfig {
360
364
  })
361
365
  );
362
366
  }
367
+ } else if (force && blockNumbers.length === 0) {
368
+ blockNumberResponses.push(
369
+ this.fetchBlockHeaderByNumberWithRetry({
370
+ blockNumber: toBlock
371
+ })
372
+ );
363
373
  } else {
364
374
  for (const blockNumber of blockNumbers) {
365
375
  blockNumberResponses.push(
@@ -384,6 +394,7 @@ class EvmRpcStream extends rpc.RpcStreamConfig {
384
394
  async fetchBlockByNumber({
385
395
  blockNumber,
386
396
  expectedParentBlockHash,
397
+ isAtHead,
387
398
  filter
388
399
  }) {
389
400
  const { header } = await this.fetchBlockHeaderByNumberWithRetry({
@@ -420,7 +431,8 @@ class EvmRpcStream extends rpc.RpcStreamConfig {
420
431
  uniqueKey: header.blockHash
421
432
  };
422
433
  let block = null;
423
- if (filter.header === "always" || logs.length > 0) {
434
+ const shouldSendBlock = filter.header === "always" || logs.length > 0 || filter.header === "on_data_or_on_new_block" && isAtHead;
435
+ if (shouldSendBlock) {
424
436
  block = {
425
437
  header,
426
438
  logs
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../src/filter.ts","../src/transform.ts","../src/log-fetcher.ts","../src/range-oracle.ts","../src/stream-config.ts","../src/rate-limited-http.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 logs.sort((a, b) => a.logIndex - b.logIndex);\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 logs.sort((a, b) => a.logIndex - b.logIndex);\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","import {\n http,\n type HttpTransport,\n type HttpTransportConfig,\n type RpcSchema,\n} from \"viem\";\n\n/**\n * @description Creates a rate-limited HTTP transport that connects to a JSON-RPC API.\n */\nexport function rateLimitedHttp<\n rpcSchema extends RpcSchema | undefined = undefined,\n raw extends boolean = false,\n>(\n /** URL of the JSON-RPC API. Defaults to the chain's public RPC URL. */\n url?: string | undefined,\n config: HttpTransportConfig<rpcSchema, raw> & { rps?: number } = {},\n): HttpTransport<rpcSchema, raw> {\n const { onFetchRequest, onFetchResponse, ...rest } = config;\n\n const rps = config.rps ?? 10;\n\n const limiter = createRateLimiter({\n capacity: rps,\n refillRate: rps,\n });\n\n return http(url, {\n ...rest,\n async onFetchRequest(request, init) {\n await limiter.acquireOne();\n await onFetchRequest?.(request, init);\n },\n async onFetchResponse(response) {\n await onFetchResponse?.(response);\n },\n });\n}\n\nfunction createRateLimiter({\n capacity,\n refillRate,\n refillInterval: refillInterval_,\n lastRefillTime: startingRefillTime,\n}: {\n capacity: number;\n refillRate: number;\n refillInterval?: number;\n lastRefillTime?: number;\n}) {\n const refillInterval = refillInterval_ ?? 100;\n\n let tokens = capacity;\n let lastRefillTime = startingRefillTime ?? Date.now();\n\n function refill(now: number) {\n const elapsed = (now - lastRefillTime) / 1_000;\n const newTokens = elapsed * refillRate;\n tokens = Math.min(capacity, tokens + newTokens);\n lastRefillTime = now;\n }\n\n return {\n available() {\n return tokens;\n },\n // Wait for a single token to become available.\n async acquireOne(now?: number) {\n while (true) {\n refill(now ?? Date.now());\n if (tokens > 0) {\n tokens -= 1;\n return;\n }\n\n await new Promise((resolve) => setTimeout(resolve, refillInterval));\n }\n },\n };\n}\n"],"names":["isHex","hexToNumber","formatBlock","numberToHex","pad","trim","RpcStreamConfig","toHex","http"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","sources":["../src/filter.ts","../src/transform.ts","../src/log-fetcher.ts","../src/range-oracle.ts","../src/stream-config.ts","../src/rate-limited-http.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 { LogFilter } from \"@apibara/evm\";\nimport 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 } 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:\n logFilter.topics !== undefined\n ? [...logFilter.topics]\n : 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 const sortedBlockNumbers = Array.from(blockNumbers).sort((a, b) =>\n a < b ? -1 : a > b ? 1 : 0,\n );\n\n return { logs: logsByBlock, blockNumbers: sortedBlockNumbers };\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 force,\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 if (force && blockNumbers.length === 0) {\n blockNumberResponses.push(\n this.fetchBlockHeaderByNumberWithRetry({\n blockNumber: toBlock,\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 logs.sort((a, b) => a.logIndex - b.logIndex);\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 isAtHead,\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 logs.sort((a, b) => a.logIndex - b.logIndex);\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 const shouldSendBlock =\n filter.header === \"always\" ||\n logs.length > 0 ||\n (filter.header === \"on_data_or_on_new_block\" && isAtHead);\n\n if (shouldSendBlock) {\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","import {\n http,\n type HttpTransport,\n type HttpTransportConfig,\n type RpcSchema,\n} from \"viem\";\n\n/**\n * @description Creates a rate-limited HTTP transport that connects to a JSON-RPC API.\n */\nexport function rateLimitedHttp<\n rpcSchema extends RpcSchema | undefined = undefined,\n raw extends boolean = false,\n>(\n /** URL of the JSON-RPC API. Defaults to the chain's public RPC URL. */\n url?: string | undefined,\n config: HttpTransportConfig<rpcSchema, raw> & { rps?: number } = {},\n): HttpTransport<rpcSchema, raw> {\n const { onFetchRequest, onFetchResponse, ...rest } = config;\n\n const rps = config.rps ?? 10;\n\n const limiter = createRateLimiter({\n capacity: rps,\n refillRate: rps,\n });\n\n return http(url, {\n ...rest,\n async onFetchRequest(request, init) {\n await limiter.acquireOne();\n await onFetchRequest?.(request, init);\n },\n async onFetchResponse(response) {\n await onFetchResponse?.(response);\n },\n });\n}\n\nfunction createRateLimiter({\n capacity,\n refillRate,\n refillInterval: refillInterval_,\n lastRefillTime: startingRefillTime,\n}: {\n capacity: number;\n refillRate: number;\n refillInterval?: number;\n lastRefillTime?: number;\n}) {\n const refillInterval = refillInterval_ ?? 100;\n\n let tokens = capacity;\n let lastRefillTime = startingRefillTime ?? Date.now();\n\n function refill(now: number) {\n const elapsed = (now - lastRefillTime) / 1_000;\n const newTokens = elapsed * refillRate;\n tokens = Math.min(capacity, tokens + newTokens);\n lastRefillTime = now;\n }\n\n return {\n available() {\n return tokens;\n },\n // Wait for a single token to become available.\n async acquireOne(now?: number) {\n while (true) {\n refill(now ?? Date.now());\n if (tokens > 0) {\n tokens -= 1;\n return;\n }\n\n await new Promise((resolve) => setTimeout(resolve, refillInterval));\n }\n },\n };\n}\n"],"names":["isHex","hexToNumber","formatBlock","numberToHex","pad","trim","RpcStreamConfig","toHex","http"],"mappings":"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"}
package/dist/index.d.cts CHANGED
@@ -39,8 +39,8 @@ declare class EvmRpcStream extends RpcStreamConfig<Filter, Block> {
39
39
  finalizedRefreshIntervalMs(): number;
40
40
  validateFilter(filter: Filter): ValidateFilterResult;
41
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>>;
42
+ fetchBlockRange({ startBlock, finalizedBlock, force, filter, }: FetchBlockRangeArgs<Filter>): Promise<FetchBlockRangeResult<Block>>;
43
+ fetchBlockByNumber({ blockNumber, expectedParentBlockHash, isAtHead, filter, }: FetchBlockByNumberArgs<Filter>): Promise<FetchBlockByNumberResult<Block>>;
44
44
  private fetchLogsForRangeWithRetry;
45
45
  private fetchLogsByBlockHashWithRetry;
46
46
  private fetchBlockHeaderByNumberWithRetry;
package/dist/index.d.mts CHANGED
@@ -39,8 +39,8 @@ declare class EvmRpcStream extends RpcStreamConfig<Filter, Block> {
39
39
  finalizedRefreshIntervalMs(): number;
40
40
  validateFilter(filter: Filter): ValidateFilterResult;
41
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>>;
42
+ fetchBlockRange({ startBlock, finalizedBlock, force, filter, }: FetchBlockRangeArgs<Filter>): Promise<FetchBlockRangeResult<Block>>;
43
+ fetchBlockByNumber({ blockNumber, expectedParentBlockHash, isAtHead, filter, }: FetchBlockByNumberArgs<Filter>): Promise<FetchBlockByNumberResult<Block>>;
44
44
  private fetchLogsForRangeWithRetry;
45
45
  private fetchLogsByBlockHashWithRetry;
46
46
  private fetchBlockHeaderByNumberWithRetry;
package/dist/index.d.ts CHANGED
@@ -39,8 +39,8 @@ declare class EvmRpcStream extends RpcStreamConfig<Filter, Block> {
39
39
  finalizedRefreshIntervalMs(): number;
40
40
  validateFilter(filter: Filter): ValidateFilterResult;
41
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>>;
42
+ fetchBlockRange({ startBlock, finalizedBlock, force, filter, }: FetchBlockRangeArgs<Filter>): Promise<FetchBlockRangeResult<Block>>;
43
+ fetchBlockByNumber({ blockNumber, expectedParentBlockHash, isAtHead, filter, }: FetchBlockByNumberArgs<Filter>): Promise<FetchBlockByNumberResult<Block>>;
44
44
  private fetchLogsForRangeWithRetry;
45
45
  private fetchLogsByBlockHashWithRetry;
46
46
  private fetchBlockHeaderByNumberWithRetry;
package/dist/index.mjs CHANGED
@@ -160,7 +160,7 @@ async function fetchLogsForRange({
160
160
  fromBlock: numberToHex(fromBlock),
161
161
  toBlock: numberToHex(toBlock),
162
162
  address: logFilter.address,
163
- topics: logFilter.topics ? [...logFilter.topics] : void 0
163
+ topics: logFilter.topics !== void 0 ? [...logFilter.topics] : void 0
164
164
  }
165
165
  ]
166
166
  });
@@ -196,7 +196,10 @@ async function fetchLogsForRange({
196
196
  }
197
197
  }
198
198
  }
199
- return { logs: logsByBlock, blockNumbers: Array.from(blockNumbers) };
199
+ const sortedBlockNumbers = Array.from(blockNumbers).sort(
200
+ (a, b) => a < b ? -1 : a > b ? 1 : 0
201
+ );
202
+ return { logs: logsByBlock, blockNumbers: sortedBlockNumbers };
200
203
  }
201
204
  function refineLog(log, filter) {
202
205
  if (log.removed) {
@@ -338,6 +341,7 @@ class EvmRpcStream extends RpcStreamConfig {
338
341
  async fetchBlockRange({
339
342
  startBlock,
340
343
  finalizedBlock,
344
+ force,
341
345
  filter
342
346
  }) {
343
347
  const { start: fromBlock, end: toBlock } = this.blockRangeOracle.clampRange(
@@ -358,6 +362,12 @@ class EvmRpcStream extends RpcStreamConfig {
358
362
  })
359
363
  );
360
364
  }
365
+ } else if (force && blockNumbers.length === 0) {
366
+ blockNumberResponses.push(
367
+ this.fetchBlockHeaderByNumberWithRetry({
368
+ blockNumber: toBlock
369
+ })
370
+ );
361
371
  } else {
362
372
  for (const blockNumber of blockNumbers) {
363
373
  blockNumberResponses.push(
@@ -382,6 +392,7 @@ class EvmRpcStream extends RpcStreamConfig {
382
392
  async fetchBlockByNumber({
383
393
  blockNumber,
384
394
  expectedParentBlockHash,
395
+ isAtHead,
385
396
  filter
386
397
  }) {
387
398
  const { header } = await this.fetchBlockHeaderByNumberWithRetry({
@@ -418,7 +429,8 @@ class EvmRpcStream extends RpcStreamConfig {
418
429
  uniqueKey: header.blockHash
419
430
  };
420
431
  let block = null;
421
- if (filter.header === "always" || logs.length > 0) {
432
+ const shouldSendBlock = filter.header === "always" || logs.length > 0 || filter.header === "on_data_or_on_new_block" && isAtHead;
433
+ if (shouldSendBlock) {
422
434
  block = {
423
435
  header,
424
436
  logs
@@ -1 +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","../src/rate-limited-http.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 logs.sort((a, b) => a.logIndex - b.logIndex);\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 logs.sort((a, b) => a.logIndex - b.logIndex);\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","import {\n http,\n type HttpTransport,\n type HttpTransportConfig,\n type RpcSchema,\n} from \"viem\";\n\n/**\n * @description Creates a rate-limited HTTP transport that connects to a JSON-RPC API.\n */\nexport function rateLimitedHttp<\n rpcSchema extends RpcSchema | undefined = undefined,\n raw extends boolean = false,\n>(\n /** URL of the JSON-RPC API. Defaults to the chain's public RPC URL. */\n url?: string | undefined,\n config: HttpTransportConfig<rpcSchema, raw> & { rps?: number } = {},\n): HttpTransport<rpcSchema, raw> {\n const { onFetchRequest, onFetchResponse, ...rest } = config;\n\n const rps = config.rps ?? 10;\n\n const limiter = createRateLimiter({\n capacity: rps,\n refillRate: rps,\n });\n\n return http(url, {\n ...rest,\n async onFetchRequest(request, init) {\n await limiter.acquireOne();\n await onFetchRequest?.(request, init);\n },\n async onFetchResponse(response) {\n await onFetchResponse?.(response);\n },\n });\n}\n\nfunction createRateLimiter({\n capacity,\n refillRate,\n refillInterval: refillInterval_,\n lastRefillTime: startingRefillTime,\n}: {\n capacity: number;\n refillRate: number;\n refillInterval?: number;\n lastRefillTime?: number;\n}) {\n const refillInterval = refillInterval_ ?? 100;\n\n let tokens = capacity;\n let lastRefillTime = startingRefillTime ?? Date.now();\n\n function refill(now: number) {\n const elapsed = (now - lastRefillTime) / 1_000;\n const newTokens = elapsed * refillRate;\n tokens = Math.min(capacity, tokens + newTokens);\n lastRefillTime = now;\n }\n\n return {\n available() {\n return tokens;\n },\n // Wait for a single token to become available.\n async acquireOne(now?: number) {\n while (true) {\n refill(now ?? Date.now());\n if (tokens > 0) {\n tokens -= 1;\n return;\n }\n\n await new Promise((resolve) => setTimeout(resolve, refillInterval));\n }\n },\n };\n}\n"],"names":[],"mappings":"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"}
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","../src/rate-limited-http.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 { LogFilter } from \"@apibara/evm\";\nimport 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 } 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:\n logFilter.topics !== undefined\n ? [...logFilter.topics]\n : 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 const sortedBlockNumbers = Array.from(blockNumbers).sort((a, b) =>\n a < b ? -1 : a > b ? 1 : 0,\n );\n\n return { logs: logsByBlock, blockNumbers: sortedBlockNumbers };\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 force,\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 if (force && blockNumbers.length === 0) {\n blockNumberResponses.push(\n this.fetchBlockHeaderByNumberWithRetry({\n blockNumber: toBlock,\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 logs.sort((a, b) => a.logIndex - b.logIndex);\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 isAtHead,\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 logs.sort((a, b) => a.logIndex - b.logIndex);\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 const shouldSendBlock =\n filter.header === \"always\" ||\n logs.length > 0 ||\n (filter.header === \"on_data_or_on_new_block\" && isAtHead);\n\n if (shouldSendBlock) {\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","import {\n http,\n type HttpTransport,\n type HttpTransportConfig,\n type RpcSchema,\n} from \"viem\";\n\n/**\n * @description Creates a rate-limited HTTP transport that connects to a JSON-RPC API.\n */\nexport function rateLimitedHttp<\n rpcSchema extends RpcSchema | undefined = undefined,\n raw extends boolean = false,\n>(\n /** URL of the JSON-RPC API. Defaults to the chain's public RPC URL. */\n url?: string | undefined,\n config: HttpTransportConfig<rpcSchema, raw> & { rps?: number } = {},\n): HttpTransport<rpcSchema, raw> {\n const { onFetchRequest, onFetchResponse, ...rest } = config;\n\n const rps = config.rps ?? 10;\n\n const limiter = createRateLimiter({\n capacity: rps,\n refillRate: rps,\n });\n\n return http(url, {\n ...rest,\n async onFetchRequest(request, init) {\n await limiter.acquireOne();\n await onFetchRequest?.(request, init);\n },\n async onFetchResponse(response) {\n await onFetchResponse?.(response);\n },\n });\n}\n\nfunction createRateLimiter({\n capacity,\n refillRate,\n refillInterval: refillInterval_,\n lastRefillTime: startingRefillTime,\n}: {\n capacity: number;\n refillRate: number;\n refillInterval?: number;\n lastRefillTime?: number;\n}) {\n const refillInterval = refillInterval_ ?? 100;\n\n let tokens = capacity;\n let lastRefillTime = startingRefillTime ?? Date.now();\n\n function refill(now: number) {\n const elapsed = (now - lastRefillTime) / 1_000;\n const newTokens = elapsed * refillRate;\n tokens = Math.min(capacity, tokens + newTokens);\n lastRefillTime = now;\n }\n\n return {\n available() {\n return tokens;\n },\n // Wait for a single token to become available.\n async acquireOne(now?: number) {\n while (true) {\n refill(now ?? Date.now());\n if (tokens > 0) {\n tokens -= 1;\n return;\n }\n\n await new Promise((resolve) => setTimeout(resolve, refillInterval));\n }\n },\n };\n}\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@apibara/evm-rpc",
3
- "version": "2.1.0-beta.44",
3
+ "version": "2.1.0-beta.46",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist",
@@ -29,8 +29,8 @@
29
29
  "unbuild": "^2.0.0"
30
30
  },
31
31
  "dependencies": {
32
- "@apibara/protocol": "2.1.0-beta.43",
33
- "@apibara/evm": "2.1.0-beta.43",
32
+ "@apibara/protocol": "2.1.0-beta.45",
33
+ "@apibara/evm": "2.1.0-beta.45",
34
34
  "viem": "^2.40.3"
35
35
  }
36
36
  }
@@ -1,8 +1,9 @@
1
+ import type { LogFilter } from "@apibara/evm";
1
2
  import type { Bytes } from "@apibara/protocol";
2
3
  import type { RpcLog } from "viem";
3
4
  import { hexToNumber, isHex, numberToHex, pad, trim } from "viem";
4
5
  import type { Log } from "./block";
5
- import type { Filter, LogFilter } from "./filter";
6
+ import type { Filter } from "./filter";
6
7
  import type { ViemRpcClient } from "./stream-config";
7
8
  import { viemRpcLogToDna } from "./transform";
8
9
 
@@ -94,7 +95,10 @@ export async function fetchLogsForRange({
94
95
  fromBlock: numberToHex(fromBlock),
95
96
  toBlock: numberToHex(toBlock),
96
97
  address: logFilter.address,
97
- topics: logFilter.topics ? [...logFilter.topics] : undefined,
98
+ topics:
99
+ logFilter.topics !== undefined
100
+ ? [...logFilter.topics]
101
+ : undefined,
98
102
  },
99
103
  ],
100
104
  });
@@ -149,7 +153,11 @@ export async function fetchLogsForRange({
149
153
  }
150
154
  }
151
155
 
152
- return { logs: logsByBlock, blockNumbers: Array.from(blockNumbers) };
156
+ const sortedBlockNumbers = Array.from(blockNumbers).sort((a, b) =>
157
+ a < b ? -1 : a > b ? 1 : 0,
158
+ );
159
+
160
+ return { logs: logsByBlock, blockNumbers: sortedBlockNumbers };
153
161
  }
154
162
 
155
163
  function refineLog(log: RpcLog, filter: LogFilter): Log | null {
@@ -121,6 +121,7 @@ export class EvmRpcStream extends RpcStreamConfig<Filter, Block> {
121
121
  async fetchBlockRange({
122
122
  startBlock,
123
123
  finalizedBlock,
124
+ force,
124
125
  filter,
125
126
  }: FetchBlockRangeArgs<Filter>): Promise<FetchBlockRangeResult<Block>> {
126
127
  const { start: fromBlock, end: toBlock } = this.blockRangeOracle.clampRange(
@@ -151,6 +152,12 @@ export class EvmRpcStream extends RpcStreamConfig<Filter, Block> {
151
152
  }),
152
153
  );
153
154
  }
155
+ } else if (force && blockNumbers.length === 0) {
156
+ blockNumberResponses.push(
157
+ this.fetchBlockHeaderByNumberWithRetry({
158
+ blockNumber: toBlock,
159
+ }),
160
+ );
154
161
  } else {
155
162
  for (const blockNumber of blockNumbers) {
156
163
  blockNumberResponses.push(
@@ -180,6 +187,7 @@ export class EvmRpcStream extends RpcStreamConfig<Filter, Block> {
180
187
  async fetchBlockByNumber({
181
188
  blockNumber,
182
189
  expectedParentBlockHash,
190
+ isAtHead,
183
191
  filter,
184
192
  }: FetchBlockByNumberArgs<Filter>): Promise<FetchBlockByNumberResult<Block>> {
185
193
  // Fetch block header and check it matches the expected parent block hash.
@@ -226,8 +234,12 @@ export class EvmRpcStream extends RpcStreamConfig<Filter, Block> {
226
234
 
227
235
  let block = null;
228
236
 
229
- // TODO: handle header on new block.
230
- if (filter.header === "always" || logs.length > 0) {
237
+ const shouldSendBlock =
238
+ filter.header === "always" ||
239
+ logs.length > 0 ||
240
+ (filter.header === "on_data_or_on_new_block" && isAtHead);
241
+
242
+ if (shouldSendBlock) {
231
243
  block = {
232
244
  header,
233
245
  logs,