From a92766e56ad04185625037d84fc28adaac7fae8c Mon Sep 17 00:00:00 2001 From: Richard Moore Date: Sat, 11 Nov 2023 18:41:40 -0500 Subject: [PATCH] Added safe and finalized provider events (#3921). --- src.ts/providers/abstract-provider.ts | 20 +++++++++++++---- src.ts/providers/subscriber-polling.ts | 30 ++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 4 deletions(-) diff --git a/src.ts/providers/abstract-provider.ts b/src.ts/providers/abstract-provider.ts index 19ef00f5f6..302ad1052b 100644 --- a/src.ts/providers/abstract-provider.ts +++ b/src.ts/providers/abstract-provider.ts @@ -36,7 +36,8 @@ import { import { Network } from "./network.js"; import { copyRequest, Block, FeeData, Log, TransactionReceipt, TransactionResponse } from "./provider.js"; import { - PollingBlockSubscriber, PollingEventSubscriber, PollingOrphanSubscriber, PollingTransactionSubscriber + PollingBlockSubscriber, PollingBlockTagSubscriber, PollingEventSubscriber, + PollingOrphanSubscriber, PollingTransactionSubscriber } from "./subscriber-polling.js"; import type { Addressable, AddressLike } from "../address/index.js"; @@ -127,7 +128,7 @@ export type DebugEventAbstractProvider = { * if they are modifying a low-level feature of how subscriptions operate. */ export type Subscription = { - type: "block" | "close" | "debug" | "error" | "network" | "pending", + type: "block" | "close" | "debug" | "error" | "finalized" | "network" | "pending" | "safe", tag: string } | { type: "transaction", @@ -235,7 +236,13 @@ async function getSubscription(_event: ProviderEvent, provider: AbstractProvider if (typeof(_event) === "string") { switch (_event) { - case "block": case "pending": case "debug": case "error": case "network": { + case "block": + case "debug": + case "error": + case "finalized": + case "network": + case "pending": + case "safe": { return { type: _event, tag: _event }; } } @@ -708,7 +715,10 @@ export class AbstractProvider implements Provider { switch (blockTag) { case "earliest": return "0x0"; - case "latest": case "pending": case "safe": case "finalized": + case "finalized": + case "latest": + case "pending": + case "safe": return blockTag; } @@ -1319,6 +1329,8 @@ export class AbstractProvider implements Provider { subscriber.pollingInterval = this.pollingInterval; return subscriber; } + case "safe": case "finalized": + return new PollingBlockTagSubscriber(this, sub.type); case "event": return new PollingEventSubscriber(this, sub.filter); case "transaction": diff --git a/src.ts/providers/subscriber-polling.ts b/src.ts/providers/subscriber-polling.ts index 3e40c1f938..6b048be8bb 100644 --- a/src.ts/providers/subscriber-polling.ts +++ b/src.ts/providers/subscriber-polling.ts @@ -113,6 +113,7 @@ export class PollingBlockSubscriber implements Subscriber { } } + /** * An **OnBlockSubscriber** can be sub-classed, with a [[_poll]] * implmentation which will be called on every new block. @@ -161,6 +162,35 @@ export class OnBlockSubscriber implements Subscriber { resume(): void { this.start(); } } +export class PollingBlockTagSubscriber extends OnBlockSubscriber { + readonly #tag: string; + #lastBlock: number; + + constructor(provider: AbstractProvider, tag: string) { + super(provider); + this.#tag = tag; + this.#lastBlock = -2; + } + + pause(dropWhilePaused?: boolean): void { + if (dropWhilePaused) { this.#lastBlock = -2; } + super.pause(dropWhilePaused); + } + + async _poll(blockNumber: number, provider: AbstractProvider): Promise { + const block = await provider.getBlock(this.#tag); + if (block == null) { return; } + + if (this.#lastBlock === -2) { + this.#lastBlock = block.number; + } else if (block.number > this.#lastBlock) { + provider.emit(this.#tag, block.number); + this.#lastBlock = block.number; + } + } +} + + /** * @_ignore: *