From 7855a6446348ae18ab7253883e862760f5387b2d Mon Sep 17 00:00:00 2001
From: jsanmigimeno <8038323+jsanmigimeno@users.noreply.github.com>
Date: Thu, 30 May 2024 11:10:11 +0200
Subject: [PATCH] feat: Allow 'startingBlock' to be a negative offset (#21)

---
 src/collector/mock/mock.worker.ts                 | 15 ++++++++++++---
 src/collector/polymer/polymer.worker.ts           | 15 ++++++++++++---
 .../wormhole/wormhole-message-sniffer.worker.ts   | 15 ++++++++++++---
 src/config/config.schema.ts                       |  9 ++++++++-
 src/getter/getter.worker.ts                       | 15 ++++++++++++---
 5 files changed, 56 insertions(+), 13 deletions(-)

diff --git a/src/collector/mock/mock.worker.ts b/src/collector/mock/mock.worker.ts
index 9b63fb8..02bb8b5 100644
--- a/src/collector/mock/mock.worker.ts
+++ b/src/collector/mock/mock.worker.ts
@@ -147,9 +147,18 @@ class MockCollectorWorker {
             // Do not initialize 'fromBlock' whilst 'currentStatus' is null, even if
             // 'startingBlock' is specified.
             if (this.currentStatus != null) {
-                fromBlock = (
-                    this.config.startingBlock ?? this.currentStatus.blockNumber
-                );
+                if (this.config.startingBlock != null) {
+                    if (this.config.startingBlock < 0) {
+                        fromBlock = this.currentStatus.blockNumber + this.config.startingBlock;
+                        if (fromBlock < 0) {
+                            throw new Error(`Invalid 'startingBlock': negative offset is larger than the current block number.`)
+                        }
+                    } else {
+                        fromBlock = this.config.startingBlock;
+                    }
+                } else {
+                    fromBlock = this.currentStatus.blockNumber;
+                }
             }
 
             await wait(this.config.processingInterval);
diff --git a/src/collector/polymer/polymer.worker.ts b/src/collector/polymer/polymer.worker.ts
index 9b9f682..391a82d 100644
--- a/src/collector/polymer/polymer.worker.ts
+++ b/src/collector/polymer/polymer.worker.ts
@@ -110,9 +110,18 @@ class PolymerCollectorSnifferWorker {
             // Do not initialize 'fromBlock' whilst 'currentStatus' is null, even if
             // 'startingBlock' is specified.
             if (this.currentStatus != null) {
-                fromBlock = (
-                    this.config.startingBlock ?? this.currentStatus.blockNumber
-                );
+                if (this.config.startingBlock != null) {
+                    if (this.config.startingBlock < 0) {
+                        fromBlock = this.currentStatus.blockNumber + this.config.startingBlock;
+                        if (fromBlock < 0) {
+                            throw new Error(`Invalid 'startingBlock': negative offset is larger than the current block number.`)
+                        }
+                    } else {
+                        fromBlock = this.config.startingBlock;
+                    }
+                } else {
+                    fromBlock = this.currentStatus.blockNumber;
+                }
             }
 
             await wait(this.config.processingInterval);
diff --git a/src/collector/wormhole/wormhole-message-sniffer.worker.ts b/src/collector/wormhole/wormhole-message-sniffer.worker.ts
index 69854f1..b6e405a 100644
--- a/src/collector/wormhole/wormhole-message-sniffer.worker.ts
+++ b/src/collector/wormhole/wormhole-message-sniffer.worker.ts
@@ -132,9 +132,18 @@ class WormholeMessageSnifferWorker {
             // Do not initialize 'fromBlock' whilst 'currentStatus' is null, even if
             // 'startingBlock' is specified.
             if (this.currentStatus != null) {
-                fromBlock = (
-                    this.config.startingBlock ?? this.currentStatus.blockNumber
-                );
+                if (this.config.startingBlock != null) {
+                    if (this.config.startingBlock < 0) {
+                        fromBlock = this.currentStatus.blockNumber + this.config.startingBlock;
+                        if (fromBlock < 0) {
+                            throw new Error(`Invalid 'startingBlock': negative offset is larger than the current block number.`)
+                        }
+                    } else {
+                        fromBlock = this.config.startingBlock;
+                    }
+                } else {
+                    fromBlock = this.currentStatus.blockNumber;
+                }
             }
 
             await wait(this.config.processingInterval);
diff --git a/src/config/config.schema.ts b/src/config/config.schema.ts
index 8563d2a..2c4d80e 100644
--- a/src/config/config.schema.ts
+++ b/src/config/config.schema.ts
@@ -13,6 +13,12 @@ const POSITIVE_NUMBER_SCHEMA = {
     minimum: 0,
 }
 
+const INTEGER_SCHEMA = {
+    $id: "integer-schema",
+    type: "number",
+    multipleOf: 1,
+}
+
 const POSITIVE_NON_ZERO_INTEGER_SCHEMA = {
     $id: "positive-non-zero-integer-schema",
     type: "number",
@@ -212,7 +218,7 @@ const CHAINS_SCHEMA = {
             rpc: { $ref: "non-empty-string-schema" },
             resolver: { $ref: "non-empty-string-schema" },
 
-            startingBlock: { $ref: "positive-number-schema" },
+            startingBlock: { $ref: "integer-schema" },
             stoppingBlock: { $ref: "positive-number-schema" },
 
             monitor: { $ref: "monitor-schema" },
@@ -229,6 +235,7 @@ const CHAINS_SCHEMA = {
 export function getConfigValidator(): AnyValidateFunction<unknown> {
     const ajv = new Ajv({ strict: true });
     ajv.addSchema(POSITIVE_NUMBER_SCHEMA);
+    ajv.addSchema(INTEGER_SCHEMA);
     ajv.addSchema(POSITIVE_NON_ZERO_INTEGER_SCHEMA);
     ajv.addSchema(NON_EMPTY_STRING_SCHEMA);
     ajv.addSchema(ADDRESS_FIELD_SCHEMA);
diff --git a/src/getter/getter.worker.ts b/src/getter/getter.worker.ts
index 75b6c08..242a106 100644
--- a/src/getter/getter.worker.ts
+++ b/src/getter/getter.worker.ts
@@ -109,9 +109,18 @@ class GetterWorker {
             // Do not initialize 'fromBlock' whilst 'currentStatus' is null, even if
             // 'startingBlock' is specified.
             if (this.currentStatus != null) {
-                fromBlock = (
-                    this.config.startingBlock ?? this.currentStatus.blockNumber
-                );
+                if (this.config.startingBlock != null) {
+                    if (this.config.startingBlock < 0) {
+                        fromBlock = this.currentStatus.blockNumber + this.config.startingBlock;
+                        if (fromBlock < 0) {
+                            throw new Error(`Invalid 'startingBlock': negative offset is larger than the current block number.`)
+                        }
+                    } else {
+                        fromBlock = this.config.startingBlock;
+                    }
+                } else {
+                    fromBlock = this.currentStatus.blockNumber;
+                }
             }
 
             await wait(this.config.processingInterval);