@0xsequence/provider 1.0.5 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/dist/0xsequence-provider.cjs.dev.js +1742 -1678
  2. package/dist/0xsequence-provider.cjs.prod.js +1742 -1678
  3. package/dist/0xsequence-provider.esm.js +1735 -1676
  4. package/dist/declarations/src/client.d.ts +74 -0
  5. package/dist/declarations/src/index.d.ts +3 -1
  6. package/dist/declarations/src/init.d.ts +25 -0
  7. package/dist/declarations/src/provider.d.ts +127 -63
  8. package/dist/declarations/src/signer.d.ts +87 -0
  9. package/dist/declarations/src/transports/mux-transport/mux-message-provider.d.ts +21 -0
  10. package/dist/declarations/src/transports/wallet-request-handler.d.ts +0 -1
  11. package/dist/declarations/src/types.d.ts +25 -9
  12. package/dist/declarations/src/utils/index.d.ts +10 -7
  13. package/dist/declarations/src/utils.d.ts +21 -15
  14. package/package.json +19 -12
  15. package/src/client.ts +423 -0
  16. package/src/extended.ts +4 -0
  17. package/src/index.ts +3 -1
  18. package/src/init.ts +134 -0
  19. package/src/provider.ts +447 -424
  20. package/src/signer.ts +316 -0
  21. package/src/transports/base-wallet-transport.ts +3 -8
  22. package/src/transports/mux-transport/mux-message-provider.ts +86 -2
  23. package/src/transports/proxy-transport/proxy-message-provider.ts +1 -1
  24. package/src/transports/wallet-request-handler.ts +3 -33
  25. package/src/transports/window-transport/window-message-provider.ts +4 -2
  26. package/src/types.ts +41 -10
  27. package/src/utils/index.ts +16 -76
  28. package/src/utils.ts +81 -51
  29. package/dist/declarations/src/extended.d.ts +0 -6
  30. package/dist/declarations/src/wallet.d.ts +0 -105
  31. package/src/wallet.ts +0 -770
package/src/wallet.ts DELETED
@@ -1,770 +0,0 @@
1
- import {
2
- NetworkConfig,
3
- ChainIdLike,
4
- JsonRpcSender,
5
- JsonRpcRouter,
6
- JsonRpcMiddleware,
7
- allowProviderMiddleware,
8
- CachedProvider,
9
- loggingProviderMiddleware,
10
- SigningProvider,
11
- EagerProvider,
12
- exceptionProviderMiddleware,
13
- networkProviderMiddleware,
14
- JsonRpcRequest,
15
- findNetworkConfig,
16
- updateNetworkConfig,
17
- ensureValidNetworks,
18
- sortNetworks,
19
- findSupportedNetwork
20
- } from '@0xsequence/network'
21
- import { getDefaultConnectionInfo, logger } from '@0xsequence/utils'
22
- import { Web3Provider, Web3Signer } from './provider'
23
- import {
24
- MuxMessageProvider,
25
- WindowMessageProvider,
26
- ProxyMessageProvider,
27
- ProxyMessageChannelPort,
28
- UnrealMessageProvider
29
- } from './transports'
30
- import { WalletSession, ProviderEventTypes, ConnectOptions, OpenWalletIntent, ConnectDetails } from './types'
31
- import { ethers, providers } from 'ethers'
32
- import { ExtensionMessageProvider } from './transports/extension-transport/extension-message-provider'
33
- import { LocalStore, ItemStore, LocalStorage } from './utils'
34
- import { WalletUtils } from './utils/index'
35
-
36
- import { Runtime } from 'webextension-polyfill'
37
- import { commons } from '@0xsequence/core'
38
- import { AccountStatus } from '@0xsequence/account'
39
-
40
- export const SESSION_LOCALSTORE_KEY = '@sequence.session'
41
-
42
- export interface WalletProvider {
43
- connect(options?: ConnectOptions): Promise<ConnectDetails>
44
- disconnect(): void
45
-
46
- isConnected(): boolean
47
- getSession(): WalletSession | undefined
48
-
49
- getAddress(): Promise<string>
50
- getNetworks(chainId?: ChainIdLike): Promise<NetworkConfig[]>
51
- getChainId(): Promise<number>
52
-
53
- isOpened(): boolean
54
- openWallet(path?: string, intent?: OpenWalletIntent, networkId?: string | number): Promise<boolean>
55
- closeWallet(): void
56
-
57
- getProvider(chainId?: ChainIdLike): Web3Provider | undefined
58
- getSigner(chainId?: ChainIdLike): Web3Signer
59
-
60
- getWalletContext(): Promise<commons.context.VersionedContext>
61
- getWalletConfig(chainId?: ChainIdLike): Promise<commons.config.Config>
62
- getWalletState(chainId?: ChainIdLike): Promise<AccountStatus>
63
- isDeployed(chainId?: ChainIdLike): Promise<boolean>
64
-
65
- getProviderConfig(): ProviderConfig
66
-
67
- on<K extends keyof ProviderEventTypes>(event: K, fn: ProviderEventTypes[K]): void
68
- once<K extends keyof ProviderEventTypes>(event: K, fn: ProviderEventTypes[K]): void
69
-
70
- utils: WalletUtils
71
- }
72
-
73
- export class Wallet implements WalletProvider {
74
- public utils: WalletUtils
75
-
76
- private config: ProviderConfig
77
- private session?: WalletSession
78
-
79
- private connectedSites: LocalStore<string[]>
80
-
81
- private transport: {
82
- // top-level provider which connects all transport layers
83
- provider?: Web3Provider
84
-
85
- // middleware stack for provider
86
- router?: JsonRpcRouter
87
- networkProvider?: JsonRpcMiddleware
88
- allowProvider?: JsonRpcMiddleware
89
- cachedProvider?: CachedProvider
90
-
91
- // message communication
92
- messageProvider?: MuxMessageProvider
93
- windowMessageProvider?: WindowMessageProvider
94
- proxyMessageProvider?: ProxyMessageProvider
95
- extensionMessageProvider?: ExtensionMessageProvider
96
- unrealMessageProvider?: UnrealMessageProvider
97
- }
98
-
99
- private networks: NetworkConfig[]
100
- private providers: { [chainId: number]: Web3Provider }
101
-
102
- constructor(network?: string | number, config?: Partial<ProviderConfig>) {
103
- // config is a Partial, so that we may intersect it with the DefaultProviderConfig,
104
- // which allows easy overriding and control of the config.
105
- this.config = { ...DefaultProviderConfig }
106
- if (config) {
107
- this.config = { ...this.config, ...config }
108
- }
109
- if (network) {
110
- this.config.defaultNetworkId = network
111
- } else if (!this.config.defaultNetworkId) {
112
- this.config.defaultNetworkId = 'mainnet'
113
- }
114
-
115
- if (config?.localStorage) {
116
- LocalStorage.use(config.localStorage)
117
- }
118
-
119
- this.transport = {}
120
- this.networks = []
121
- this.providers = {}
122
- this.connectedSites = new LocalStore('@sequence.connectedSites', [])
123
- this.utils = new WalletUtils(this)
124
- this.init()
125
- }
126
-
127
- private init = () => {
128
- if (this.transport.provider) {
129
- // init must have already been called
130
- return
131
- }
132
-
133
- // Setup provider
134
-
135
- this.transport.messageProvider = new MuxMessageProvider()
136
-
137
- // multiple message provider setup, first one to connect will be the main transport
138
- if (this.config.transports?.windowTransport?.enabled && typeof window === 'object') {
139
- this.transport.windowMessageProvider = new WindowMessageProvider(this.config.walletAppURL)
140
- this.transport.messageProvider.add(this.transport.windowMessageProvider)
141
- }
142
- if (this.config.transports?.proxyTransport?.enabled) {
143
- this.transport.proxyMessageProvider = new ProxyMessageProvider(this.config.transports.proxyTransport.appPort!)
144
- this.transport.messageProvider.add(this.transport.proxyMessageProvider)
145
- }
146
- if (this.config.transports?.extensionTransport?.enabled) {
147
- this.transport.extensionMessageProvider = new ExtensionMessageProvider(this.config.transports.extensionTransport.runtime)
148
- // this.transport.extensionMessageProvider.register()
149
- this.transport.messageProvider.add(this.transport.extensionMessageProvider)
150
-
151
- // NOTE/REVIEW: see note in mux-message-provider
152
- //
153
- // We don't add the extensionMessageProvider here because we don't send requests to it anyways, we seem to
154
- // send all requests to the WindowMessageProvider anyways. By allowing it, if browser restarts, it will break
155
- // the entire extension because messageProvider.provider will be undefined. So this is a hack to fix it.
156
- //
157
- // this.transport.messageProvider.add(this.transport.extensionMessageProvider)
158
- }
159
- if (this.config.transports?.unrealTransport?.enabled) {
160
- this.transport.unrealMessageProvider = new UnrealMessageProvider(this.config.walletAppURL)
161
- this.transport.messageProvider.add(this.transport.unrealMessageProvider)
162
- }
163
- this.transport.messageProvider.register()
164
-
165
- // .....
166
- this.transport.allowProvider = allowProviderMiddleware((request: JsonRpcRequest): boolean => {
167
- if (request.method === 'sequence_setDefaultNetwork') return true
168
-
169
- const isConnected = this.isConnected()
170
- if (!isConnected) {
171
- throw new Error('Sequence: wallet not connected')
172
- }
173
- return isConnected
174
- })
175
-
176
- // ...
177
- this.transport.networkProvider = networkProviderMiddleware((request: JsonRpcRequest): number => {
178
- // return stub chainId of 0 when not connected to any
179
- if (!this.networks || this.networks.length === 0) return 0
180
-
181
- // return the default chainId as we're connected
182
- return findNetworkConfig(this.networks, this.config.defaultNetworkId!)!.chainId
183
- })
184
-
185
- // Provider proxy to support middleware stack of logging, caching and read-only rpc calls
186
- this.transport.cachedProvider = new CachedProvider()
187
- this.transport.cachedProvider.onUpdate(() => {
188
- if (!this.session) this.session = { providerCache: {} }
189
- this.session.providerCache = this.transport.cachedProvider!.getCache()
190
- this.saveSession(this.session)
191
- })
192
-
193
- // ..
194
- this.transport.router = new JsonRpcRouter(
195
- [
196
- loggingProviderMiddleware,
197
- this.transport.networkProvider,
198
- this.transport.allowProvider,
199
- exceptionProviderMiddleware,
200
- this.transport.cachedProvider
201
- ],
202
- this.transport.messageProvider
203
- )
204
-
205
- // TODO: Move finding this config to upper in the stack
206
- this.transport.provider = new Web3Provider(
207
- this.transport.router,
208
- findSupportedNetwork(this.config.defaultNetworkId!)?.chainId
209
- )
210
-
211
- // NOTE: we don't listen on 'connect' even here as we handle it within connect() method
212
- // in more synchronous flow.
213
-
214
- // below will update the wallet session object and persist it. In case the session
215
- // is undefined, we consider the session to have been removed by the user, so we clear it.
216
- this.transport.messageProvider.on('open', (openInfo: { session?: WalletSession }) => {
217
- const { session } = openInfo
218
- if (!session) {
219
- if (this.session && this.session.accountAddress) {
220
- // emit disconnect even if previously we had a session, and now we don't.
221
- this.transport.messageProvider!.emit('disconnect')
222
- }
223
- this.clearSession()
224
- } else {
225
- this.useSession(session, true)
226
- }
227
- })
228
-
229
- // below will update the account upon wallet connect/disconnect - aka, login/logout.
230
- // if an origin is provided, this operation should be performed only on that origin
231
- // and shouldn't affect the session of the wallet.
232
- this.transport.messageProvider.on('accountsChanged', (accounts: string[], origin?: string) => {
233
- if (origin) {
234
- if (accounts.length > 0) {
235
- this.useSession({ accountAddress: accounts[0] }, true)
236
- }
237
- return
238
- }
239
-
240
- if (!accounts || accounts.length === 0 || accounts[0] === '') {
241
- this.clearSession()
242
- } else {
243
- this.useSession({ accountAddress: accounts[0] }, true)
244
- }
245
- })
246
-
247
- // below will update the networks automatically when the wallet networks change
248
- this.transport.messageProvider.on('networks', (networks: NetworkConfig[]) => {
249
- this.useSession({ networks: networks }, true)
250
- })
251
-
252
- // below will update the wallet context automatically
253
- this.transport.messageProvider.on('walletContext', (walletContext: commons.context.VersionedContext) => {
254
- this.useSession({ walletContext: walletContext }, true)
255
- })
256
- }
257
-
258
- loadSession = async (preferredNetwork?: string | number): Promise<WalletSession | undefined> => {
259
- const data = await LocalStorage.getInstance().getItem(SESSION_LOCALSTORE_KEY)
260
- if (!data || data === '') {
261
- return undefined
262
- }
263
-
264
- try {
265
- const session = JSON.parse(data) as WalletSession
266
- if (session) {
267
- // Setting preferredNetwork as default network if it's in session.networks
268
- if (preferredNetwork !== undefined) {
269
- const preferredNetworkIdNum = typeof preferredNetwork === 'string' ? parseInt(preferredNetwork) : preferredNetwork
270
- const isPreferredNetwork = (n: NetworkConfig) => n.name === preferredNetwork || n.chainId === preferredNetworkIdNum
271
- const preferredNetworkInConfig = session.networks?.find(isPreferredNetwork)
272
- const isAlreadyDefaultChain = preferredNetworkInConfig?.isDefaultChain
273
-
274
- if (session.networks && preferredNetworkInConfig && !isAlreadyDefaultChain) {
275
- const updatedNetworks = session.networks.map(n => ({ ...n, isDefaultChain: isPreferredNetwork(n) }))
276
- session.networks = sortNetworks(updatedNetworks)
277
- session.providerCache = undefined
278
- }
279
- }
280
-
281
- this.useSession(session, true)
282
- }
283
- return session
284
- } catch (err) {
285
- logger.warn('loadSession failed, unable to parse session payload from storage.')
286
- return undefined
287
- }
288
- }
289
-
290
- connect = async (options?: ConnectOptions): Promise<ConnectDetails> => {
291
- if (options && options?.authorizeVersion === undefined) {
292
- // Populate default authorize version if not provided
293
- options.authorizeVersion = 2
294
- }
295
-
296
- if (options?.refresh === true) {
297
- this.disconnect()
298
- }
299
-
300
- if (
301
- this.isConnected() &&
302
- (await this.isSiteConnected(options?.origin)) &&
303
- !!this.session &&
304
- !options?.authorize &&
305
- !options?.askForEmail
306
- ) {
307
- return {
308
- connected: true,
309
- session: this.session,
310
- chainId: ethers.utils.hexlify(await this.getChainId())
311
- }
312
- }
313
-
314
- if (options) {
315
- if (options.authorize) {
316
- if (!options.app) {
317
- throw new Error(`connecting with 'authorize' option also requires 'app' to be set`)
318
- }
319
- if (options.authorizeVersion === undefined) {
320
- options.authorizeVersion = 2
321
- }
322
- }
323
- }
324
-
325
- await this.openWallet(undefined, { type: 'connect', options })
326
-
327
- const connectDetails = await this.transport.messageProvider!.waitUntilConnected().catch((error): ConnectDetails => {
328
- if (error instanceof Error) {
329
- return { connected: false, error: error.message }
330
- } else {
331
- return { connected: false, error: JSON.stringify(error) }
332
- }
333
- })
334
-
335
- if (connectDetails.connected) {
336
- if (!!connectDetails.session) {
337
- this.useSession(connectDetails.session, true)
338
-
339
- this.addConnectedSite(options?.origin)
340
- } else {
341
- throw new Error('impossible state, connect response is missing session')
342
- }
343
- }
344
-
345
- return connectDetails
346
- }
347
-
348
- async addConnectedSite(origin: string | undefined) {
349
- origin = origin || window.location.origin
350
-
351
- const connectedSites = await this.connectedSites.get()
352
-
353
- if (connectedSites) {
354
- if (connectedSites.includes(origin)) {
355
- return
356
- }
357
- this.connectedSites.set([...connectedSites, origin])
358
- } else {
359
- this.connectedSites.set([origin])
360
- }
361
- }
362
-
363
- async removeConnectedSite(origin: string) {
364
- const authorized = await this.connectedSites.get()
365
-
366
- if (authorized) {
367
- this.connectedSites.set(authorized.filter(domain => domain !== origin))
368
- }
369
- }
370
-
371
- getConnectedSites() {
372
- return this.connectedSites.get()
373
- }
374
-
375
- async isSiteConnected(origin: string | undefined): Promise<boolean> {
376
- const authorized = await this.connectedSites.get()
377
-
378
- return !!authorized && authorized.includes(origin || window.location.origin)
379
- }
380
-
381
- authorize = async (options?: ConnectOptions): Promise<ConnectDetails> => {
382
- return this.connect({ ...options, authorize: true })
383
- }
384
-
385
- disconnect(): Promise<void> {
386
- if (this.isOpened()) {
387
- this.closeWallet()
388
- }
389
- return this.clearSession()
390
- }
391
-
392
- // TODO: add switchNetwork(network: string | number) which will call wallet_switchEthereumChain
393
- // and on successful response, will update the provider info here, etc.
394
-
395
- getProviderConfig(): ProviderConfig {
396
- return this.config
397
- }
398
-
399
- isOpened(): boolean {
400
- return this.transport.messageProvider!.isOpened()
401
- }
402
-
403
- isConnected(): boolean {
404
- return (
405
- this.session !== undefined &&
406
- this.session.networks !== undefined &&
407
- this.session.networks.length > 0 &&
408
- this.networks !== undefined &&
409
- this.networks.length > 0 &&
410
- !!this.session.accountAddress &&
411
- this.session.accountAddress.startsWith('0x')
412
- )
413
- }
414
-
415
- getSession = (): WalletSession | undefined => {
416
- if (!this.isConnected()) {
417
- return undefined
418
- }
419
- return this.session
420
- }
421
-
422
- getAddress = async (): Promise<string> => {
423
- if (!this.isConnected()) {
424
- throw new Error('connect first')
425
- }
426
- const session = this.getSession()
427
- return session!.accountAddress!
428
- }
429
-
430
- getNetworks = async (chainId?: ChainIdLike): Promise<NetworkConfig[]> => {
431
- if (!this.isConnected() || !this.networks) {
432
- throw new Error('connect first')
433
- }
434
- if (chainId) {
435
- // filter list to just the specific chain requested
436
- const network = findNetworkConfig(this.networks, chainId)
437
- return network ? [network] : []
438
- }
439
- return this.networks
440
- }
441
-
442
- // getChainId returns the default chain id
443
- getChainId = async (): Promise<number> => {
444
- if (!this.networks || this.networks.length < 1) {
445
- throw new Error('networks have not been set by session. connect first.')
446
- }
447
-
448
- const network = findNetworkConfig(this.networks, this.config.defaultNetworkId!)
449
-
450
- if (!network) {
451
- throw new Error('networks must have a default chain specified')
452
- }
453
-
454
- return network.chainId
455
- }
456
-
457
- openWallet = async (path?: string, intent?: OpenWalletIntent, networkId?: string | number): Promise<boolean> => {
458
- if (intent?.type !== 'connect' && !this.isConnected()) {
459
- throw new Error('connect first')
460
- }
461
-
462
- let currentNetworkId
463
-
464
- if (!this.networks || this.networks.length < 1) {
465
- currentNetworkId = this.config.defaultNetworkId
466
- } else {
467
- currentNetworkId = await this.getChainId()
468
- }
469
-
470
- this.transport.messageProvider!.openWallet(path, intent, networkId || currentNetworkId)
471
- await this.transport.messageProvider!.waitUntilOpened()
472
-
473
- return true
474
- }
475
-
476
- closeWallet = (): void => {
477
- this.transport.messageProvider!.closeWallet()
478
- }
479
-
480
- getProvider(chainId?: ChainIdLike): Web3Provider | undefined {
481
- // return the top-level provider message transport when chainId is unspecified
482
- // and user has not logged in
483
- if (!this.isConnected()) {
484
- if (chainId) {
485
- throw new Error(`session is empty. connect and try again.`)
486
- } else {
487
- return this.transport.provider
488
- }
489
- }
490
-
491
- let network: NetworkConfig | undefined = findNetworkConfig(this.networks, this.config.defaultNetworkId!)!
492
- if (chainId) {
493
- network = findNetworkConfig(this.networks, chainId)
494
- if (!network) {
495
- throw new Error(`network ${chainId} is not in the network list`)
496
- }
497
- }
498
-
499
- // return memoized network provider
500
- if (this.providers[network.chainId]) {
501
- return this.providers[network.chainId]
502
- }
503
-
504
- // builder web3 provider stack
505
- let provider: Web3Provider
506
-
507
- // network.provider may be set by the ProviderConfig override
508
- const rpcProvider = new providers.JsonRpcProvider(getDefaultConnectionInfo(network.rpcUrl), network.chainId)
509
-
510
- if (network.isDefaultChain) {
511
- // communicating with defaultChain will prioritize the wallet message transport
512
- const router = new JsonRpcRouter(
513
- [
514
- loggingProviderMiddleware,
515
- exceptionProviderMiddleware,
516
- new EagerProvider({ accountAddress: this.session!.accountAddress, walletContext: this.session!.walletContext }),
517
- new SigningProvider(this.transport!.provider!),
518
- this.transport.cachedProvider!
519
- ],
520
- new JsonRpcSender(rpcProvider)
521
- )
522
-
523
- provider = new Web3Provider(router, network.chainId)
524
- } else {
525
- // communicating with another chain will bind to that network, but will forward
526
- // any signing-related requests to the wallet message transport
527
- const router = new JsonRpcRouter(
528
- [
529
- loggingProviderMiddleware,
530
- exceptionProviderMiddleware,
531
- new EagerProvider({
532
- accountAddress: this.session!.accountAddress,
533
- walletContext: this.session!.walletContext,
534
- chainId: network.chainId
535
- }),
536
- new SigningProvider(this.transport.provider!),
537
- new CachedProvider({ defaultChainId: network.chainId })
538
- ],
539
- new JsonRpcSender(rpcProvider)
540
- )
541
-
542
- provider = new Web3Provider(router, network.chainId)
543
- }
544
-
545
- this.providers[network.chainId] = provider
546
- return provider
547
- }
548
-
549
- getAllProviders(): { [chainId: number]: Web3Provider } {
550
- return this.providers
551
- }
552
-
553
- getSigner(chainId?: ChainIdLike): Web3Signer {
554
- return this.getProvider(chainId)!.getSigner()
555
- }
556
-
557
- getWalletConfig(chainId?: ChainIdLike): Promise<commons.config.Config> {
558
- return this.getSigner().getWalletConfig(chainId)
559
- }
560
-
561
- getWalletState(chainId?: ChainIdLike): Promise<AccountStatus> {
562
- return this.getSigner().getWalletState(chainId)
563
- }
564
-
565
- getWalletContext(): Promise<commons.context.VersionedContext> {
566
- return this.getSigner().getWalletContext()
567
- }
568
-
569
- isDeployed(chainId?: ChainIdLike): Promise<boolean> {
570
- return this.getSigner(chainId).isDeployed()
571
- }
572
-
573
- on<K extends keyof ProviderEventTypes>(event: K, fn: ProviderEventTypes[K]) {
574
- this.transport.messageProvider!.on(event, fn)
575
- }
576
-
577
- once<K extends keyof ProviderEventTypes>(event: K, fn: ProviderEventTypes[K]) {
578
- this.transport.messageProvider!.once(event, fn)
579
- }
580
-
581
- unregister = () => {
582
- this.disconnect()
583
- this.transport.messageProvider?.unregister()
584
- }
585
-
586
- private saveSession = async (session: WalletSession) => {
587
- logger.debug('wallet provider: saving session')
588
- const data = JSON.stringify(session)
589
- await LocalStorage.getInstance().setItem(SESSION_LOCALSTORE_KEY, data)
590
- }
591
-
592
- private useSession = async (session: WalletSession, autoSave: boolean = true) => {
593
- if (!this.session) this.session = {}
594
-
595
- // setup wallet context
596
- if (this.config.walletContext) {
597
- this.session.walletContext = this.config.walletContext
598
- } else if (session.walletContext) {
599
- this.session.walletContext = session.walletContext
600
- }
601
-
602
- // setup account
603
- if (session.accountAddress) {
604
- this.useAccountAddress(session.accountAddress)
605
- }
606
-
607
- // setup networks
608
- if (session.networks) {
609
- this.useNetworks(session.networks)
610
- }
611
-
612
- // setup provider cache
613
- if (session.providerCache) {
614
- this.transport.cachedProvider!.setCache(session.providerCache)
615
- } else {
616
- this.transport.cachedProvider!.clearCache()
617
- }
618
-
619
- // persist
620
- if (autoSave) {
621
- this.saveSession(this.session)
622
- }
623
- }
624
-
625
- private useAccountAddress(accountAddress: string) {
626
- if (!this.session) this.session = {}
627
- this.session.accountAddress = ethers.utils.getAddress(accountAddress)
628
- }
629
-
630
- private useNetworks(networks: NetworkConfig[]) {
631
- // set networks in the session
632
- if (!this.session) this.session = {}
633
-
634
- // set networks on session object
635
- this.session.networks = networks
636
-
637
- // short-circuit if setting empty network list (aka logged out state)
638
- if (!this.session.networks || this.session.networks.length === 0) {
639
- return
640
- }
641
-
642
- // check if any custom network settings, otherwise return early
643
- if (!this.config.networks && !this.config.networkRpcUrl) {
644
- this.networks = networks
645
- return
646
- }
647
-
648
- // init networks
649
- this.networks = networks
650
-
651
- // combine custom network config with networks in the session
652
- if (this.config.networks) {
653
- this.networks = networks.map(n => ({ ...n })) // copy
654
- this.config.networks.forEach(n => {
655
- const network = findNetworkConfig(this.networks, n.chainId || n.name!)
656
- if (!network) return
657
- updateNetworkConfig(n, network)
658
- })
659
- ensureValidNetworks(this.networks, true)
660
- }
661
-
662
- // an extra override for convenience
663
- if (this.config.networkRpcUrl) {
664
- const network = this.networks.find(network => network.isDefaultChain)
665
- if (network) {
666
- network.rpcUrl = this.config.networkRpcUrl
667
- }
668
- }
669
- }
670
-
671
- private async clearSession(): Promise<void> {
672
- logger.debug('wallet provider: clearing session')
673
- await LocalStorage.getInstance().removeItem(SESSION_LOCALSTORE_KEY)
674
- this.session = undefined
675
- this.networks = []
676
- this.providers = {}
677
- this.transport.cachedProvider?.clearCache()
678
- }
679
- }
680
-
681
- export interface ProviderConfig {
682
- // The local storage dependency for the wallet provider, defaults to window.localStorage.
683
- // For example, this option should be used when using React Native since window.localStorage is not available.
684
- localStorage?: ItemStore
685
-
686
- // Sequence Wallet App URL, default: https://sequence.app
687
- walletAppURL: string
688
-
689
- // Sequence Wallet Session URL, default: https://session.sequence.app
690
- // walletSessionURL: string
691
-
692
- // networks is a configuration list of networks used by the wallet. This list
693
- // is combined with the network list supplied from the wallet upon login,
694
- // and settings here take precedence such as overriding a relayer setting, or rpcUrl.
695
- networks?: Partial<NetworkConfig>[]
696
-
697
- // networkRpcUrl will set the provider rpcUrl of the default network
698
- networkRpcUrl?: string
699
-
700
- // defaultNetworkId is the primary network of a dapp and the default network a
701
- // provider will communicate. Note: this setting is also configurable from the
702
- // Wallet constructor's first argument.
703
- defaultNetworkId?: string | number
704
-
705
- // transports for dapp to wallet jron-rpc communication
706
- transports?: {
707
- // WindowMessage transport (optional)
708
- windowTransport?: {
709
- enabled: boolean
710
- }
711
-
712
- // ProxyMessage transport (optional)
713
- proxyTransport?: {
714
- enabled: boolean
715
- appPort?: ProxyMessageChannelPort
716
- }
717
-
718
- // Extension transport (optional)
719
- extensionTransport?: {
720
- enabled: boolean
721
- runtime: Runtime.Static
722
- }
723
-
724
- // Unreal Engine transport (optional)
725
- unrealTransport?: {
726
- enabled: boolean
727
- }
728
- }
729
-
730
- // Sequence Wallet Modules Context override. By default (and recommended), the
731
- // WalletContext used the one returned by the wallet app upon login.
732
- //
733
- // NOTE: do not use this option unless you know what you're doing
734
- walletContext?: commons.context.VersionedContext
735
- }
736
-
737
- export const DefaultProviderConfig: ProviderConfig = {
738
- walletAppURL: 'https://sequence.app',
739
-
740
- // walletSessionURL: 'https://session.sequence.app',
741
-
742
- transports: {
743
- windowTransport: { enabled: true },
744
- proxyTransport: { enabled: false }
745
- }
746
- }
747
-
748
- let walletInstance: Wallet | undefined
749
-
750
- export const initWallet = async (network?: string | number, config?: Partial<ProviderConfig>) => {
751
- if (walletInstance) {
752
- return walletInstance
753
- }
754
- walletInstance = new Wallet(network, config)
755
- await walletInstance.loadSession(network)
756
- return walletInstance
757
- }
758
-
759
- export const unregisterWallet = () => {
760
- if (!walletInstance) return
761
- walletInstance.closeWallet()
762
- walletInstance.unregister()
763
- }
764
-
765
- export const getWallet = () => {
766
- if (!walletInstance) {
767
- throw new Error('Wallet has not been initialized, call sequence.initWallet(network, config) first.')
768
- }
769
- return walletInstance
770
- }