From c2f7b145cd9e41132a89cc927e70773244152e36 Mon Sep 17 00:00:00 2001
From: Kodey Kilday-Thomas <kodey.kildaythomas@smartcontract.com>
Date: Thu, 5 Dec 2024 13:53:19 +0000
Subject: [PATCH 1/2] fix: ensure toolkit works for non standard chains

---
 src/ResponseListener.ts    | 18 +++++++++++++++--
 src/SubscriptionManager.ts | 40 ++++++++++++++++++++++++++++++++------
 src/events.ts              |  6 ++++++
 3 files changed, 56 insertions(+), 8 deletions(-)
 create mode 100644 src/events.ts

diff --git a/src/ResponseListener.ts b/src/ResponseListener.ts
index df94ce3..9eecc08 100644
--- a/src/ResponseListener.ts
+++ b/src/ResponseListener.ts
@@ -4,6 +4,7 @@ import { FunctionsRouterSource } from './v1_contract_sources'
 
 import type { BigNumber, providers } from 'ethers'
 
+import { FunctionsTopics } from './events'
 import { FulfillmentCode, type FunctionsResponse } from './types'
 
 export class ResponseListener {
@@ -88,7 +89,20 @@ export class ResponseListener {
 
         const check = async () => {
           const receipt = await this.provider.waitForTransaction(txHash, confirmations, timeoutMs)
-          const updatedId = receipt.logs[0].topics[1]
+
+          // There must be logs in the receipt otherwise it's a chain that doesn't support logs or the tx was reverted
+          if (!receipt.logs) throw new Error('No logs found in the transaction receipt')
+
+          // Find the RequestStart event in the logs
+          const requestStartLog = receipt.logs.find(
+            log => log.topics[0] === FunctionsTopics.RequestStart,
+          )
+
+          // Ensure the requestID exists in the logs
+          if (!requestStartLog) throw new Error('RequestStart event not found in the logs')
+          if (!requestStartLog.topics[1]) throw new Error('Request ID not found in the logs')
+
+          const updatedId = requestStartLog.topics[1]
           if (updatedId !== requestId) {
             requestId = updatedId
             const response = await this.listenForResponse(requestId, timeoutMs)
@@ -119,7 +133,7 @@ export class ResponseListener {
     }
 
     this.functionsRouter.on(
-      'RequestProcessed',
+      { topics: [FunctionsTopics.RequestProcessed] },
       (
         requestId: string,
         _subscriptionId: BigNumber,
diff --git a/src/SubscriptionManager.ts b/src/SubscriptionManager.ts
index 174ff99..f184366 100644
--- a/src/SubscriptionManager.ts
+++ b/src/SubscriptionManager.ts
@@ -8,7 +8,7 @@ import {
 } from './v1_contract_sources'
 
 import type { Signer } from 'ethers'
-import type { TransactionReceipt } from '@ethersproject/abstract-provider'
+import type { TransactionReceipt, TransactionResponse } from '@ethersproject/abstract-provider'
 
 import type {
   SubConsumerConfig,
@@ -21,6 +21,7 @@ import type {
   SubCreateConfig,
   EstimateCostConfig,
 } from './types'
+import { FunctionsTopics } from './events'
 
 export class SubscriptionManager {
   private signer: Signer
@@ -109,12 +110,24 @@ export class SubscriptionManager {
           : await this.functionsRouter.createSubscriptionWithConsumer(
               subCreateConfig.consumerAddress,
             )
-        const createSubWithConsumerTxReceipt = await createSubWithConsumerTx.wait(
+
+        const txReceipt: TransactionReceipt = await createSubWithConsumerTx.wait(
           subCreateConfig.txOptions?.confirmations,
         )
 
-        const subscriptionId = createSubWithConsumerTxReceipt.events[0].args['subscriptionId']
+        // Search through logs to find the topic that matches the SubscriptionCreated event
+        if (!txReceipt.logs) throw new Error('No logs present within transaction receipt')
+
+        const createSubscriptionLog = txReceipt.logs.find(
+          log => log.topics[0] === FunctionsTopics.SubscriptionCreated,
+        )
 
+        // Sanity checking, ensure that the SubscriptionCreated event was found in the log
+        if (!createSubscriptionLog) throw new Error('No SubscriptionCreated event found in logs')
+        if (!createSubscriptionLog.topics[1]) throw new Error('No subscriptionId found in logs')
+
+        // The signature is SubscriptionCreated(uint64,address) so the subscriptionId is the second topic
+        const subscriptionId = createSubscriptionLog.topics[1]
         return Number(subscriptionId.toString())
       } catch (error) {
         throw Error(`createSubscriptionWithConsumer failed\n${error}`)
@@ -122,11 +135,26 @@ export class SubscriptionManager {
     }
 
     try {
-      const createSubTx = subCreateConfig?.txOptions?.overrides
+      const createSubTx: TransactionResponse = subCreateConfig?.txOptions?.overrides
         ? await this.functionsRouter.createSubscription(subCreateConfig?.txOptions.overrides)
         : await this.functionsRouter.createSubscription()
-      const createSubTxReceipt = await createSubTx.wait(subCreateConfig?.txOptions?.confirmations)
-      const subscriptionId = createSubTxReceipt.events[0].args['subscriptionId']
+
+      const createSubTxReceipt: TransactionReceipt = await createSubTx.wait(
+        subCreateConfig?.txOptions?.confirmations,
+      )
+
+      // Search through logs to find the topic that matches the SubscriptionCreated event
+      if (!createSubTxReceipt.logs) throw new Error('No logs present within transaction receipt')
+      const createSubscriptionLog = createSubTxReceipt.logs.find(
+        log => log.topics[0] === FunctionsTopics.SubscriptionCreated,
+      )
+
+      // Sanity checking, ensure that the SubscriptionCreated event was found in the log
+      if (!createSubscriptionLog) throw new Error('No SubscriptionCreated event found in logs')
+      if (!createSubscriptionLog.topics[1]) throw new Error('No subscriptionId found in logs')
+
+      // The signature is SubscriptionCreated(uint64,address) so the subscriptionId is the second topic
+      const subscriptionId = createSubscriptionLog.topics[1]
       return Number(subscriptionId.toString())
     } catch (error) {
       throw Error(`createSubscription failed\n${error}`)
diff --git a/src/events.ts b/src/events.ts
new file mode 100644
index 0000000..450bd1a
--- /dev/null
+++ b/src/events.ts
@@ -0,0 +1,6 @@
+// This file contains a list of topics for events that are emitted by the Functions Contracts.
+export const FunctionsTopics = {
+  SubscriptionCreated: '0x464722b4166576d3dcbba877b999bc35cf911f4eaf434b7eba68fa113951d0bf',
+  RequestStart: '0xf67aec45c9a7ede407974a3e0c3a743dffeab99ee3f2d4c9a8144c2ebf2c7ec9',
+  RequestProcessed: '0x64778f26c70b60a8d7e29e2451b3844302d959448401c0535b768ed88c6b505e',
+}

From 96aa37bcc34ba461758fc8b8a497df2be16833f7 Mon Sep 17 00:00:00 2001
From: Kodey Kilday-Thomas <kodey.kildaythomas@smartcontract.com>
Date: Thu, 5 Dec 2024 14:07:45 +0000
Subject: [PATCH 2/2] fix: sonarlint issues

---
 src/ResponseListener.ts    | 13 ++++++++++---
 src/SubscriptionManager.ts | 27 +++++++++++++++++++++------
 2 files changed, 31 insertions(+), 9 deletions(-)

diff --git a/src/ResponseListener.ts b/src/ResponseListener.ts
index 9eecc08..f9972a5 100644
--- a/src/ResponseListener.ts
+++ b/src/ResponseListener.ts
@@ -91,7 +91,9 @@ export class ResponseListener {
           const receipt = await this.provider.waitForTransaction(txHash, confirmations, timeoutMs)
 
           // There must be logs in the receipt otherwise it's a chain that doesn't support logs or the tx was reverted
-          if (!receipt.logs) throw new Error('No logs found in the transaction receipt')
+          if (!receipt.logs) {
+            throw new Error('No logs found in the transaction receipt')
+          }
 
           // Find the RequestStart event in the logs
           const requestStartLog = receipt.logs.find(
@@ -99,8 +101,13 @@ export class ResponseListener {
           )
 
           // Ensure the requestID exists in the logs
-          if (!requestStartLog) throw new Error('RequestStart event not found in the logs')
-          if (!requestStartLog.topics[1]) throw new Error('Request ID not found in the logs')
+          if (!requestStartLog) {
+            throw new Error('RequestStart event not found in the logs')
+          }
+
+          if (!requestStartLog.topics[1]) {
+            throw new Error('Request ID not found in the logs')
+          }
 
           const updatedId = requestStartLog.topics[1]
           if (updatedId !== requestId) {
diff --git a/src/SubscriptionManager.ts b/src/SubscriptionManager.ts
index f184366..ac29ef6 100644
--- a/src/SubscriptionManager.ts
+++ b/src/SubscriptionManager.ts
@@ -116,15 +116,22 @@ export class SubscriptionManager {
         )
 
         // Search through logs to find the topic that matches the SubscriptionCreated event
-        if (!txReceipt.logs) throw new Error('No logs present within transaction receipt')
+        if (!txReceipt.logs) {
+          throw new Error('No logs present within transaction receipt')
+        }
 
         const createSubscriptionLog = txReceipt.logs.find(
           log => log.topics[0] === FunctionsTopics.SubscriptionCreated,
         )
 
         // Sanity checking, ensure that the SubscriptionCreated event was found in the log
-        if (!createSubscriptionLog) throw new Error('No SubscriptionCreated event found in logs')
-        if (!createSubscriptionLog.topics[1]) throw new Error('No subscriptionId found in logs')
+        if (!createSubscriptionLog) {
+          throw new Error('No SubscriptionCreated event found in logs')
+        }
+
+        if (!createSubscriptionLog.topics[1]) {
+          throw new Error('No subscriptionId found in logs')
+        }
 
         // The signature is SubscriptionCreated(uint64,address) so the subscriptionId is the second topic
         const subscriptionId = createSubscriptionLog.topics[1]
@@ -144,14 +151,22 @@ export class SubscriptionManager {
       )
 
       // Search through logs to find the topic that matches the SubscriptionCreated event
-      if (!createSubTxReceipt.logs) throw new Error('No logs present within transaction receipt')
+      if (!createSubTxReceipt.logs) {
+        throw new Error('No logs present within transaction receipt')
+      }
+
       const createSubscriptionLog = createSubTxReceipt.logs.find(
         log => log.topics[0] === FunctionsTopics.SubscriptionCreated,
       )
 
       // Sanity checking, ensure that the SubscriptionCreated event was found in the log
-      if (!createSubscriptionLog) throw new Error('No SubscriptionCreated event found in logs')
-      if (!createSubscriptionLog.topics[1]) throw new Error('No subscriptionId found in logs')
+      if (!createSubscriptionLog) {
+        throw new Error('No SubscriptionCreated event found in logs')
+      }
+
+      if (!createSubscriptionLog.topics[1]) {
+        throw new Error('No subscriptionId found in logs')
+      }
 
       // The signature is SubscriptionCreated(uint64,address) so the subscriptionId is the second topic
       const subscriptionId = createSubscriptionLog.topics[1]