@@ -160,7 +160,7 @@ export class UniversalProvider implements IUniversalProvider {
160160 // assign namespaces from session if not already defined
161161 const approved = populateNamespacesChains ( this . session . namespaces ) as NamespaceConfig ;
162162 this . namespaces = mergeRequiredOptionalNamespaces ( this . namespaces , approved ) ;
163- this . persist ( "namespaces" , this . namespaces ) ;
163+ await this . persist ( "namespaces" , this . namespaces ) ;
164164 this . onConnect ( ) ;
165165 }
166166 return result ;
@@ -205,7 +205,8 @@ export class UniversalProvider implements IUniversalProvider {
205205 // assign namespaces from session if not already defined
206206 const approved = populateNamespacesChains ( session . namespaces ) as NamespaceConfig ;
207207 this . namespaces = mergeRequiredOptionalNamespaces ( this . namespaces , approved ) ;
208- this . persist ( "namespaces" , this . namespaces ) ;
208+ await this . persist ( "namespaces" , this . namespaces ) ;
209+ await this . persist ( "optionalNamespaces" , this . optionalNamespaces ) ;
209210
210211 this . onConnect ( ) ;
211212 return this . session ;
@@ -253,13 +254,9 @@ export class UniversalProvider implements IUniversalProvider {
253254 // ---------- Private ----------------------------------------------- //
254255
255256 private async checkStorage ( ) {
256- this . namespaces = await this . getFromStore ( "namespaces" ) ;
257- this . optionalNamespaces = ( await this . getFromStore ( "optionalNamespaces" ) ) || { } ;
258- if ( this . client . session . length ) {
259- const lastKeyIndex = this . client . session . keys . length - 1 ;
260- this . session = this . client . session . get ( this . client . session . keys [ lastKeyIndex ] ) ;
261- this . createProviders ( ) ;
262- }
257+ this . namespaces = ( await this . getFromStore ( `namespaces` ) ) || { } ;
258+ this . optionalNamespaces = ( await this . getFromStore ( `optionalNamespaces` ) ) || { } ;
259+ if ( this . session ) this . createProviders ( ) ;
263260 }
264261
265262 private async initialize ( ) {
@@ -285,6 +282,19 @@ export class UniversalProvider implements IUniversalProvider {
285282 telemetryEnabled : this . providerOpts . telemetryEnabled ,
286283 } ) ) ;
287284
285+ if ( this . providerOpts . session ) {
286+ try {
287+ this . session = this . client . session . get ( this . providerOpts . session . topic ) ;
288+ } catch ( error ) {
289+ this . logger . error ( "Failed to get session" , error ) ;
290+ throw new Error (
291+ `The provided session: ${ this . providerOpts ?. session ?. topic } doesn't exist in the Sign client` ,
292+ ) ;
293+ }
294+ } else {
295+ const sessions = this . client . session . getAll ( ) ;
296+ this . session = sessions [ 0 ] ;
297+ }
288298 this . logger . trace ( `SignClient Initialized` ) ;
289299 }
290300
@@ -389,11 +399,14 @@ export class UniversalProvider implements IUniversalProvider {
389399 }
390400
391401 this . client . on ( "session_ping" , ( args ) => {
402+ const { topic } = args ;
403+ if ( topic !== this . session ?. topic ) return ;
392404 this . events . emit ( "session_ping" , args ) ;
393405 } ) ;
394406
395407 this . client . on ( "session_event" , ( args ) => {
396- const { params } = args ;
408+ const { params, topic } = args ;
409+ if ( topic !== this . session ?. topic ) return ;
397410 const { event } = params ;
398411 if ( event . name === "accountsChanged" ) {
399412 const accounts = event . data ;
@@ -419,6 +432,7 @@ export class UniversalProvider implements IUniversalProvider {
419432 } ) ;
420433
421434 this . client . on ( "session_update" , ( { topic, params } ) => {
435+ if ( topic !== this . session ?. topic ) return ;
422436 const { namespaces } = params ;
423437 const _session = this . client ?. session . get ( topic ) ;
424438 this . session = { ..._session , namespaces } as SessionTypes . Struct ;
@@ -427,6 +441,7 @@ export class UniversalProvider implements IUniversalProvider {
427441 } ) ;
428442
429443 this . client . on ( "session_delete" , async ( payload ) => {
444+ if ( payload . topic !== this . session ?. topic ) return ;
430445 await this . cleanup ( ) ;
431446 this . events . emit ( "session_delete" , payload ) ;
432447 this . events . emit ( "disconnect" , {
@@ -463,8 +478,6 @@ export class UniversalProvider implements IUniversalProvider {
463478 }
464479 this . sessionProperties = sessionProperties ;
465480 this . scopedProperties = scopedProperties ;
466- this . persist ( "namespaces" , namespaces ) ;
467- this . persist ( "optionalNamespaces" , optionalNamespaces ) ;
468481 }
469482
470483 private validateChain ( chain ?: string ) : [ string , string ] {
@@ -497,7 +510,7 @@ export class UniversalProvider implements IUniversalProvider {
497510 return await this . getProvider ( namespace ) . requestAccounts ( ) ;
498511 }
499512
500- private onChainChanged ( caip2Chain : string , internal = false ) : void {
513+ private async onChainChanged ( caip2Chain : string , internal = false ) : Promise < void > {
501514 if ( ! this . namespaces ) return ;
502515
503516 const [ namespace , chainId ] = this . validateChain ( caip2Chain ) ;
@@ -517,8 +530,8 @@ export class UniversalProvider implements IUniversalProvider {
517530 this . namespaces [ `${ namespace } :${ chainId } ` ] = { defaultChain : chainId } ;
518531 }
519532
520- this . persist ( "namespaces" , this . namespaces ) ;
521533 this . events . emit ( "chainChanged" , chainId ) ;
534+ await this . persist ( "namespaces" , this . namespaces ) ;
522535 }
523536
524537 private onConnect ( ) {
@@ -527,23 +540,48 @@ export class UniversalProvider implements IUniversalProvider {
527540 }
528541
529542 private async cleanup ( ) {
530- this . session = undefined ;
531543 this . namespaces = undefined ;
532544 this . optionalNamespaces = undefined ;
533545 this . sessionProperties = undefined ;
534- this . scopedProperties = undefined ;
535- this . persist ( "namespaces" , undefined ) ;
536- this . persist ( "optionalNamespaces" , undefined ) ;
537- this . persist ( "sessionProperties" , undefined ) ;
546+ await this . deleteFromStore ( "namespaces" ) ;
547+ await this . deleteFromStore ( "optionalNamespaces" ) ;
548+ await this . deleteFromStore ( "sessionProperties" ) ;
549+ // reset the session after removing from store as the topic is used there
550+ this . session = undefined ;
538551 await this . cleanupPendingPairings ( { deletePairings : true } ) ;
552+ await this . cleanupStorage ( ) ;
539553 }
540554
541- private persist ( key : string , data : unknown ) {
542- this . client . core . storage . setItem ( `${ STORAGE } /${ key } ` , data ) ;
555+ private async persist ( key : string , data : unknown ) {
556+ const topic = this . session ?. topic || "" ;
557+ await this . client . core . storage . setItem ( `${ STORAGE } /${ key } ${ topic } ` , data ) ;
543558 }
544559
545560 private async getFromStore ( key : string ) {
546- return await this . client . core . storage . getItem ( `${ STORAGE } /${ key } ` ) ;
561+ const topic = this . session ?. topic || "" ;
562+ return await this . client . core . storage . getItem ( `${ STORAGE } /${ key } ${ topic } ` ) ;
563+ }
564+
565+ private async deleteFromStore ( key : string ) {
566+ const topic = this . session ?. topic || "" ;
567+ await this . client . core . storage . removeItem ( `${ STORAGE } /${ key } ${ topic } ` ) ;
568+ }
569+
570+ // remove all storage items if there are no sessions left
571+ private async cleanupStorage ( ) {
572+ try {
573+ if ( this . client ?. session . length > 0 ) {
574+ return ;
575+ }
576+ const keys = await this . client . core . storage . getKeys ( ) ;
577+ for ( const key of keys ) {
578+ if ( key . startsWith ( STORAGE ) ) {
579+ await this . client . core . storage . removeItem ( key ) ;
580+ }
581+ }
582+ } catch ( error ) {
583+ this . logger . warn ( "Failed to cleanup storage" , error ) ;
584+ }
547585 }
548586}
549587export default UniversalProvider ;
0 commit comments