From ae04656cc1a2ca54b977fc8efb078446fe75e891 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Ribo=CC=81?= Date: Fri, 3 Oct 2025 10:40:40 +0200 Subject: [PATCH 1/2] fix: prevent glitch in default transport with a "connecting" state --- packages/sdk-multichain/src/multichain/index.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/sdk-multichain/src/multichain/index.ts b/packages/sdk-multichain/src/multichain/index.ts index f4b37ad66..447b749b3 100644 --- a/packages/sdk-multichain/src/multichain/index.ts +++ b/packages/sdk-multichain/src/multichain/index.ts @@ -242,6 +242,15 @@ export class MultichainSDK extends MultichainCore { } private async showInstallModal(desktopPreferred: boolean, scopes: Scope[], caipAccountIds: CaipAccountId[]) { + if (typeof window !== 'undefined') { + window.addEventListener('beforeunload', async () => { + if (this.options.ui.factory.modal) { + //Modal is still visible, remove storage to prevent glitch with "connecting" state + await this.storage.removeTransport(); + } + logger('beforeunload'); + }); + } return new Promise((resolve, reject) => { // Use Connection Modal this.options.ui.factory.renderInstallModal( From 97bd3a5692c09bf54eae9de1cb203cb167b7fd7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Ribo=CC=81?= Date: Fri, 3 Oct 2025 11:28:43 +0200 Subject: [PATCH 2/2] fix: memory leak improvement on beforeunload window event listener --- .../sdk-multichain/src/multichain/index.ts | 30 +++++++++++++------ 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/packages/sdk-multichain/src/multichain/index.ts b/packages/sdk-multichain/src/multichain/index.ts index 447b749b3..d929171f9 100644 --- a/packages/sdk-multichain/src/multichain/index.ts +++ b/packages/sdk-multichain/src/multichain/index.ts @@ -23,7 +23,7 @@ export class MultichainSDK extends MultichainCore { private __provider: MultichainApiClient | undefined = undefined; private __transport: ExtendedTransport | undefined = undefined; private __dappClient: DappClient | undefined = undefined; - + private __beforeUnloadListener: (() => void) | undefined; public __state: SDKState = 'pending'; private listener: (() => void | Promise) | undefined; @@ -241,16 +241,26 @@ export class MultichainSDK extends MultichainCore { } } - private async showInstallModal(desktopPreferred: boolean, scopes: Scope[], caipAccountIds: CaipAccountId[]) { + private async onBeforeUnload() { + if (this.options.ui.factory.modal) { + //Modal is still visible, remove storage to prevent glitch with "connecting" state + await this.storage.removeTransport(); + } + } + + private createBeforeUnloadListener() { if (typeof window !== 'undefined') { - window.addEventListener('beforeunload', async () => { - if (this.options.ui.factory.modal) { - //Modal is still visible, remove storage to prevent glitch with "connecting" state - await this.storage.removeTransport(); - } - logger('beforeunload'); - }); + window.addEventListener('beforeunload', this.onBeforeUnload.bind(this)); } + return () => { + if (typeof window !== 'undefined') { + window.removeEventListener('beforeunload', this.onBeforeUnload.bind(this)); + } + }; + } + private async showInstallModal(desktopPreferred: boolean, scopes: Scope[], caipAccountIds: CaipAccountId[]) { + // create the listener only once to avoid memory leaks + this.__beforeUnloadListener ??= this.createBeforeUnloadListener(); return new Promise((resolve, reject) => { // Use Connection Modal this.options.ui.factory.renderInstallModal( @@ -421,6 +431,7 @@ export class MultichainSDK extends MultichainCore { async disconnect(): Promise { this.listener?.(); + this.__beforeUnloadListener?.(); await this.__transport?.disconnect(); await this.storage.removeTransport(); @@ -429,6 +440,7 @@ export class MultichainSDK extends MultichainCore { this.emit('stateChanged', 'disconnected'); this.listener = undefined; + this.__beforeUnloadListener = undefined; this.__transport = undefined; this.__provider = undefined; this.__dappClient = undefined;