@@ -3,22 +3,30 @@ import { initPolkadotJs } from '@helpers/initPolkadotJs'
3
3
import { ApiPromise , HttpProvider , WsProvider } from '@polkadot/api'
4
4
import { ApiOptions } from '@polkadot/api/types'
5
5
import {
6
- InjectedAccountWithMeta ,
6
+ InjectedAccount ,
7
+ InjectedExtension ,
7
8
Unsubcall ,
8
9
} from '@polkadot/extension-inject/types'
9
10
import { Signer } from '@polkadot/types/types'
10
- import { registerDeployments , SubstrateDeployment } from '@registry'
11
+ import { SubstrateDeployment , registerDeployments } from '@registry'
12
+ import {
13
+ SubstrateWallet ,
14
+ allSubstrateWallets ,
15
+ enableWallet ,
16
+ getSubstrateWallet ,
17
+ isWalletInstalled ,
18
+ } from '@wallets'
11
19
import {
12
- createContext ,
13
20
Dispatch ,
14
21
FC ,
15
22
PropsWithChildren ,
16
23
SetStateAction ,
24
+ createContext ,
17
25
useContext ,
18
26
useEffect ,
19
27
useState ,
20
28
} from 'react'
21
- import { getSubstrateChain , SubstrateChain } from './chains'
29
+ import { SubstrateChain , getSubstrateChain } from './chains'
22
30
23
31
/**
24
32
* Helper Types
@@ -44,14 +52,13 @@ export type UseInkathonProviderContextType = {
44
52
switchActiveChain ?: ( chain : SubstrateChain ) => Promise < void >
45
53
api ?: ApiPromise
46
54
provider ?: WsProvider | HttpProvider
47
- connect ?: ( ) => Promise < void >
55
+ connect ?: ( chain ?: SubstrateChain , wallet ?: SubstrateWallet ) => Promise < void >
48
56
disconnect ?: ( ) => void
49
- accounts ?: InjectedAccountWithMeta [ ]
50
- activeAccount ?: InjectedAccountWithMeta
57
+ accounts ?: InjectedAccount [ ]
58
+ activeAccount ?: InjectedAccount
59
+ activeExtension ?: InjectedExtension
51
60
activeSigner ?: Signer
52
- setActiveAccount ?: Dispatch <
53
- SetStateAction < InjectedAccountWithMeta | undefined >
54
- >
61
+ setActiveAccount ?: Dispatch < SetStateAction < InjectedAccount | undefined > >
55
62
deployments ?: SubstrateDeployment [ ]
56
63
}
57
64
export const UseInkathonProviderContext =
@@ -110,10 +117,11 @@ export const UseInkathonProvider: FC<UseInkathonProviderProps> = ({
110
117
)
111
118
const [ api , setApi ] = useState < ApiPromise > ( )
112
119
const [ provider , setProvider ] = useState < WsProvider | HttpProvider > ( )
113
- const [ accounts , setAccounts ] = useState < InjectedAccountWithMeta [ ] > ( [ ] )
114
- const [ activeAccount , setActiveAccount ] = useState < InjectedAccountWithMeta > ( )
120
+ const [ accounts , setAccounts ] = useState < InjectedAccount [ ] > ( [ ] )
121
+ const [ activeAccount , setActiveAccount ] = useState < InjectedAccount > ( )
122
+ const [ activeExtension , setActiveExtension ] = useState < InjectedExtension > ( )
115
123
const [ latestActiveAccount , setLatestActiveAccount ] =
116
- useState < InjectedAccountWithMeta > ( )
124
+ useState < InjectedAccount > ( )
117
125
const [ activeSigner , setActiveSigner ] = useState < Signer > ( )
118
126
const [ unsubscribeAccounts , setUnsubscribeAccounts ] = useState < Unsubcall > ( )
119
127
const [ deployments , setDeployments ] = useState < SubstrateDeployment [ ] > ( [ ] )
@@ -150,34 +158,8 @@ export const UseInkathonProvider: FC<UseInkathonProviderProps> = ({
150
158
}
151
159
}
152
160
153
- // Update signer when account changes
154
- const udpateSigner = async ( ) => {
155
- await api ?. isReadyOrError
156
- if ( ! activeAccount ?. meta ?. source || ! api ) {
157
- setActiveSigner ( undefined )
158
- api ?. setSigner ( undefined as any )
159
- return
160
- }
161
-
162
- try {
163
- // NOTE: Dynamic import to prevent hydration error in SSR environments
164
- const { web3FromSource } = await import ( '@polkadot/extension-dapp' )
165
- const injector = await web3FromSource ( activeAccount . meta . source )
166
- const signer = injector ?. signer
167
- setActiveSigner ( signer )
168
- api . setSigner ( signer )
169
- } catch ( e ) {
170
- console . error ( 'Error while setting signer:' , e )
171
- setActiveSigner ( undefined )
172
- api . setSigner ( undefined as any )
173
- }
174
- }
175
- useEffect ( ( ) => {
176
- udpateSigner ( )
177
- } , [ api , activeAccount ] )
178
-
179
161
// Updates account list and active account
180
- const updateAccounts = ( injectedAccounts : InjectedAccountWithMeta [ ] ) => {
162
+ const updateAccounts = ( injectedAccounts : InjectedAccount [ ] ) => {
181
163
const newAccounts = injectedAccounts || [ ]
182
164
// Find active account in new accounts or fallback to first account
183
165
const newAccount =
@@ -202,8 +184,8 @@ export const UseInkathonProvider: FC<UseInkathonProviderProps> = ({
202
184
}
203
185
} , [ activeAccount ] )
204
186
205
- // Connect to injected wallets via polkadot-js/extension-dapp
206
- const connect = async ( chain ?: SubstrateChain ) => {
187
+ // Connect to injected wallet
188
+ const connect = async ( chain ?: SubstrateChain , wallet ?: SubstrateWallet ) => {
207
189
setError ( undefined )
208
190
setIsConnecting ( true )
209
191
setIsConnected ( false )
@@ -214,14 +196,9 @@ export const UseInkathonProvider: FC<UseInkathonProviderProps> = ({
214
196
}
215
197
216
198
try {
217
- // NOTE: Dynamic import to prevent hydration error in SSR environments
218
- const { web3AccountsSubscribe, web3Enable } = await import (
219
- '@polkadot/extension-dapp'
220
- )
221
-
222
- // Initialize web3 extension
223
- const extensions = await web3Enable ( appName )
224
- if ( ! extensions ?. length ) {
199
+ // Determine installed wallets
200
+ const wallets = allSubstrateWallets . filter ( ( w ) => isWalletInstalled ( w ) )
201
+ if ( ! wallets ?. length ) {
225
202
const message = 'No Substrate-compatible extension detected'
226
203
setError ( {
227
204
code : UseInkathonErrorCode . NoSubstrateExtensionDetected ,
@@ -230,17 +207,34 @@ export const UseInkathonProvider: FC<UseInkathonProviderProps> = ({
230
207
throw new Error ( message )
231
208
}
232
209
210
+ // Determine wallet to use
211
+ const preferredWallet = wallet && wallets . find ( ( w ) => w . id === wallet . id )
212
+ const _wallet = preferredWallet || wallets [ 0 ]
213
+
214
+ // Enable wallet
215
+ const extension = await enableWallet ( _wallet , appName )
216
+ const signer = extension ?. signer as Signer
217
+ setActiveExtension ( extension )
218
+ setActiveSigner ( signer )
219
+
233
220
// Query & keep listening to injected accounts
234
221
unsubscribeAccounts ?.( )
235
- const unsubscribe = await web3AccountsSubscribe ( updateAccounts )
222
+ const unsubscribe = extension ?. accounts . subscribe ( updateAccounts )
236
223
setUnsubscribeAccounts ( unsubscribe )
237
224
} catch ( e : any ) {
238
225
console . error ( 'Error while connecting wallet:' , e )
226
+ setActiveExtension ( undefined )
227
+ setActiveSigner ( undefined )
239
228
} finally {
240
229
setIsConnecting ( false )
241
230
}
242
231
}
243
232
233
+ // Keep active signer up to date
234
+ useEffect ( ( ) => {
235
+ api ?. setSigner ( activeSigner as Signer )
236
+ } , [ api , activeSigner ] )
237
+
244
238
// Disconnect
245
239
const disconnect = async ( ) => {
246
240
await api ?. disconnect ( )
@@ -249,6 +243,7 @@ export const UseInkathonProvider: FC<UseInkathonProviderProps> = ({
249
243
updateAccounts ( [ ] )
250
244
unsubscribeAccounts ?.( )
251
245
setUnsubscribeAccounts ( undefined )
246
+ setActiveExtension ( undefined )
252
247
}
253
248
254
249
// Initialze
@@ -261,7 +256,9 @@ export const UseInkathonProvider: FC<UseInkathonProviderProps> = ({
261
256
262
257
// Switch active chain
263
258
const switchActiveChain = async ( chain : SubstrateChain ) => {
264
- await connect ( chain )
259
+ const activeWallet =
260
+ activeExtension && getSubstrateWallet ( activeExtension . name )
261
+ await connect ( chain , activeWallet )
265
262
}
266
263
267
264
return (
@@ -278,6 +275,7 @@ export const UseInkathonProvider: FC<UseInkathonProviderProps> = ({
278
275
disconnect,
279
276
accounts,
280
277
activeAccount,
278
+ activeExtension,
281
279
activeSigner,
282
280
setActiveAccount,
283
281
deployments,
0 commit comments