From 7a0fcf14e35d811493f58106b03f16c1bd3efc1d Mon Sep 17 00:00:00 2001 From: Taylor Dawson Date: Tue, 21 Sep 2021 15:44:47 -0700 Subject: [PATCH] 1.34.2-0.0.5: [fix] Dangling event listeners (#687) * 1.34.2-0.0.5: [fix] Dangling event listeners * Fix prefer const lint issue --- package.json | 2 +- src/utilities.ts | 52 +++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 46 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 6c0910790..6e490aa2d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "bnc-onboard", - "version": "1.34.2-0.0.4", + "version": "1.34.2-0.0.5", "description": "Onboard users to web3 by allowing them to select a wallet, get that wallet ready to transact and have access to synced wallet state.", "keywords": [ "ethereum", diff --git a/src/utilities.ts b/src/utilities.ts index 06c5a5430..1afd21dad 100644 --- a/src/utilities.ts +++ b/src/utilities.ts @@ -141,14 +141,33 @@ export function createModernProviderInterface(provider: any): WalletInterface { const onFuncExists = typeof provider.on === 'function' + interface ProviderEventHandlers { + accountsChanged: ((arg: string[]) => void) | null + networkChanged: ((arg: string | number) => void) | null + chainChanged: ((arg: string | number) => void) | null + } + + // A map of provider event handlers -- refferences needed + // in order to remove the event listners when their no longer needed + const providerEventHandler: ProviderEventHandlers = { + accountsChanged: null, + networkChanged: null, + chainChanged: null + } + return { address: onFuncExists ? { onChange: func => { + providerEventHandler['accountsChanged'] = (accounts: string[]) => { + func(accounts && accounts[0]) + } + // get the initial value getAddress(provider).then(func) - provider.on('accountsChanged', (accounts: string[]) => - func(accounts && accounts[0]) + provider.on( + 'accountsChanged', + providerEventHandler['accountsChanged'] ) } } @@ -158,18 +177,26 @@ export function createModernProviderInterface(provider: any): WalletInterface { network: onFuncExists ? { onChange: (func: (val: string | number) => void) => { + providerEventHandler['networkChanged'] = (netId: string | number) => + func(netId && Number(netId)) + + // We clone the previous handler in order to get a distinct refference + // to the 'chainChanged' event handler + providerEventHandler['chainChanged'] = providerEventHandler[ + 'networkChanged' + ].bind({}) + // get initial value getNetwork(provider).then(func) // networkChanged event is deprecated in MM, keep for wallets that may not have updated - provider.on('networkChanged', (netId: string | number) => - func(netId && Number(netId)) + provider.on( + 'networkChanged', + providerEventHandler['networkChanged'] ) // use new chainChanged event for network change - provider.on('chainChanged', (netId: string | number) => - func(netId && Number(netId)) - ) + provider.on('chainChanged', providerEventHandler['chainChanged']) } } : { get: () => getNetwork(provider) }, @@ -193,6 +220,17 @@ export function createModernProviderInterface(provider: any): WalletInterface { } } }, + disconnect: () => { + if (provider?.removeListener) { + // Iterate over the event handlers and remove them from the event listener. + for (const [key, handler] of Object.entries(providerEventHandler)) { + // If the handler is null, this indicates that no event listener was created + if (handler) { + provider.removeListener(key, handler) + } + } + } + }, name: getProviderName(provider) } }