1
1
import type { Account , BaseWallet , BaseWalletProvider , WalletMetadata } from '@polkadot-onboard/core' ;
2
+ import { WalletType } from '@polkadot-onboard/core' ;
2
3
import type { Signer } from '@polkadot/types/types' ;
4
+ import { WalletConnectModal } from '@walletconnect/modal' ;
5
+ import Client , { SignClient } from '@walletconnect/sign-client' ;
3
6
import type { SessionTypes } from '@walletconnect/types' ;
4
- import type { WalletConnectConfiguration , WcAccount } from './types.js' ;
5
7
6
- import { WalletType } from '@polkadot-onboard/core' ;
7
- import SignClient from '@walletconnect/sign-client' ;
8
- import QRCodeModal from '@walletconnect/qrcode-modal' ;
9
8
import { WalletConnectSigner } from './signer.js' ;
9
+ import type { WalletConnectConfiguration , WcAccount } from './types.js' ;
10
10
11
11
export const POLKADOT_CHAIN_ID = 'polkadot:91b171bb158e2d3848fa23a9f1c25182' ;
12
12
export const WC_VERSION = '2.0' ;
13
13
14
- const toWalletAccount = ( wcAccount : WcAccount ) => {
15
- let address = wcAccount . split ( ':' ) [ 2 ] ;
16
- return { address } ;
17
- } ;
14
+ const toWalletAccount = ( wcAccount : WcAccount ) => ( { address : wcAccount . split ( ':' ) [ 2 ] } ) ;
15
+
16
+ interface ModalState {
17
+ open : boolean ;
18
+ }
18
19
19
20
class WalletConnectWallet implements BaseWallet {
20
21
type = WalletType . WALLET_CONNECT ;
21
22
appName : string ;
22
23
metadata : WalletMetadata ;
23
24
config : WalletConnectConfiguration ;
24
- client : SignClient | undefined ;
25
+ client : Client | undefined ;
25
26
signer : Signer | undefined ;
26
27
session : SessionTypes . Struct | undefined ;
28
+ walletConnectModal : WalletConnectModal ;
27
29
28
30
constructor ( config : WalletConnectConfiguration , appName : string ) {
29
31
if ( ! config . chainIds || config . chainIds . length === 0 ) config . chainIds = [ POLKADOT_CHAIN_ID ] ;
@@ -37,6 +39,10 @@ class WalletConnectWallet implements BaseWallet {
37
39
iconUrl : config . metadata ?. icons [ 0 ] || '' ,
38
40
version : WC_VERSION ,
39
41
} ;
42
+ this . walletConnectModal = new WalletConnectModal ( {
43
+ projectId : config . projectId ,
44
+ chains : config . chainIds ,
45
+ } ) ;
40
46
}
41
47
42
48
reset ( ) : void {
@@ -47,50 +53,84 @@ class WalletConnectWallet implements BaseWallet {
47
53
48
54
async getAccounts ( ) : Promise < Account [ ] > {
49
55
let accounts : Account [ ] = [ ] ;
56
+
50
57
if ( this . session ) {
51
- let wcAccounts = Object . values ( this . session . namespaces )
58
+ const wcAccounts = Object . values ( this . session . namespaces )
52
59
. map ( ( namespace ) => namespace . accounts )
53
60
. flat ( ) ;
61
+
54
62
accounts = wcAccounts . map ( ( wcAccount ) => toWalletAccount ( wcAccount as WcAccount ) ) ;
55
63
}
64
+
56
65
return accounts ;
57
66
}
58
67
59
68
async connect ( ) {
60
- // reset the client
61
69
this . reset ( ) ;
62
70
63
- // init the client
64
- let client = await SignClient . init ( this . config ) ;
65
- let params = {
71
+ this . client = await SignClient . init ( this . config ) ;
72
+
73
+ this . client . on ( 'session_delete' , ( ) => {
74
+ this . reset ( ) ;
75
+
76
+ if ( this . config . onSessionDelete ) {
77
+ this . config . onSessionDelete ( ) ;
78
+ }
79
+ } ) ;
80
+
81
+ const namespaces = {
66
82
requiredNamespaces : {
67
83
polkadot : {
68
- methods : [ 'polkadot_signTransaction' , 'polkadot_signMessage' ] ,
69
84
chains : this . config . chainIds ,
85
+ methods : [ 'polkadot_signTransaction' , 'polkadot_signMessage' ] ,
86
+ events : [ ] ,
87
+ } ,
88
+ } ,
89
+ optionalNamespaces : {
90
+ polkadot : {
91
+ chains : this . config . optionalChainIds ,
92
+ methods : [ 'polkadot_signTransaction' , 'polkadot_signMessage' ] ,
70
93
events : [ ] ,
71
94
} ,
72
95
} ,
73
96
} ;
74
97
75
- const { uri, approval } = await client . connect ( params ) ;
98
+ const lastKeyIndex = this . client . session . getAll ( ) . length - 1 ;
99
+ const lastSession = this . client . session . getAll ( ) [ lastKeyIndex ] ;
100
+
101
+ if ( lastSession ) {
102
+ return new Promise < void > ( ( resolve ) => {
103
+ this . session = lastSession ;
104
+ this . signer = new WalletConnectSigner ( this . client ! , lastSession ) ;
105
+ resolve ( ) ;
106
+ } ) ;
107
+ }
108
+
109
+ const { uri, approval } = await this . client . connect ( namespaces ) ;
110
+
76
111
return new Promise < void > ( ( resolve , reject ) => {
77
- // Open QRCode modal if a URI was returned (i.e. we're not connecting an existing pairing).
78
112
if ( uri ) {
79
- QRCodeModal . open ( uri , ( ) => {
80
- reject ( new Error ( 'Canceled pairing. QR Code Modal closed.' ) ) ;
81
- } ) ;
113
+ this . walletConnectModal . openModal ( { uri } ) ;
82
114
}
83
- // Await session approval from the wallet.
115
+
116
+ const unsubscribeModal = this . walletConnectModal . subscribeModal ( ( state : ModalState ) => {
117
+ if ( state . open === false ) {
118
+ unsubscribeModal ( ) ;
119
+ resolve ( ) ;
120
+ }
121
+ } ) ;
122
+
84
123
approval ( )
85
124
. then ( ( session ) => {
86
- // setup the client
87
- this . client = client ;
88
125
this . session = session ;
89
- this . signer = new WalletConnectSigner ( client , session ) ;
126
+ this . signer = new WalletConnectSigner ( this . client ! , session ) ;
127
+
90
128
resolve ( ) ;
91
129
} )
92
- . catch ( reject )
93
- . finally ( ( ) => QRCodeModal . close ( ) ) ;
130
+ . catch ( ( error ) => {
131
+ reject ( error ) ;
132
+ } )
133
+ . finally ( ( ) => this . walletConnectModal . closeModal ( ) ) ;
94
134
} ) ;
95
135
}
96
136
@@ -104,6 +144,7 @@ class WalletConnectWallet implements BaseWallet {
104
144
} ,
105
145
} ) ;
106
146
}
147
+
107
148
this . reset ( ) ;
108
149
}
109
150
0 commit comments