@0xsequence/provider 1.0.5 → 1.1.1

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 (32) hide show
  1. package/dist/0xsequence-provider.cjs.dev.js +1763 -1678
  2. package/dist/0xsequence-provider.cjs.prod.js +1763 -1678
  3. package/dist/0xsequence-provider.esm.js +1756 -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/transactions.ts +23 -0
  22. package/src/transports/base-wallet-transport.ts +3 -8
  23. package/src/transports/mux-transport/mux-message-provider.ts +86 -2
  24. package/src/transports/proxy-transport/proxy-message-provider.ts +1 -1
  25. package/src/transports/wallet-request-handler.ts +8 -33
  26. package/src/transports/window-transport/window-message-provider.ts +4 -2
  27. package/src/types.ts +41 -10
  28. package/src/utils/index.ts +16 -76
  29. package/src/utils.ts +81 -51
  30. package/dist/declarations/src/extended.d.ts +0 -6
  31. package/dist/declarations/src/wallet.d.ts +0 -105
  32. package/src/wallet.ts +0 -770
package/src/signer.ts ADDED
@@ -0,0 +1,316 @@
1
+ import { ethers } from "ethers"
2
+
3
+ import { SequenceProvider, SingleNetworkSequenceProvider } from "./provider"
4
+ import { SequenceClient } from "./client"
5
+ import { commons } from "@0xsequence/core"
6
+ import { ChainIdLike, NetworkConfig } from "@0xsequence/network"
7
+ import { resolveArrayProperties } from "./utils"
8
+ import { WalletUtils } from "./utils/index"
9
+ import { OptionalChainIdLike, OptionalEIP6492 } from "./types"
10
+
11
+ export interface ISequenceSigner extends ethers.Signer {
12
+ getProvider(): SequenceProvider
13
+ getProvider(chainId: ChainIdLike): SingleNetworkSequenceProvider
14
+ getProvider(chainId?: ChainIdLike): SequenceProvider | SingleNetworkSequenceProvider
15
+
16
+ getSigner(): SequenceSigner
17
+ getSigner(chainId: ChainIdLike): SingleNetworkSequenceSigner
18
+ getSigner(chainId?: ChainIdLike): SequenceSigner | SingleNetworkSequenceSigner
19
+
20
+ getWalletConfig(chainId?: ChainIdLike): Promise<commons.config.Config>
21
+ getNetworks(): Promise<NetworkConfig[]>
22
+
23
+ signMessage(
24
+ message: ethers.BytesLike,
25
+ options?: OptionalChainIdLike & OptionalEIP6492
26
+ ): Promise<string>
27
+
28
+ signTypedData(
29
+ domain: ethers.TypedDataDomain,
30
+ types: Record<string, Array<ethers.TypedDataField>>,
31
+ message: Record<string, any>,
32
+ options?: OptionalChainIdLike & OptionalEIP6492
33
+ ): Promise<string>
34
+
35
+ // sendTransaction takes an unsigned transaction, or list of unsigned transactions, and then has it signed by
36
+ // the signer, and finally sends it to the relayer for submission to an Ethereum network.
37
+ // It supports any kind of transaction, including regular ethers transactions, and Sequence transactions.
38
+ sendTransaction(
39
+ transaction: (
40
+ ethers.utils.Deferrable<ethers.providers.TransactionRequest>[] |
41
+ ethers.utils.Deferrable<ethers.providers.TransactionRequest>
42
+ ),
43
+ options?: OptionalChainIdLike
44
+ ): Promise<commons.transaction.TransactionResponse>
45
+
46
+ utils: WalletUtils
47
+ }
48
+
49
+ export class SequenceSigner implements ISequenceSigner {
50
+ private readonly singleNetworkSigners: { [chainId: number]: SingleNetworkSequenceSigner } = {}
51
+
52
+ readonly _isSigner: boolean = true
53
+ readonly _isSequenceSigner: boolean = true
54
+
55
+ get utils(): WalletUtils {
56
+ return this.provider.utils
57
+ }
58
+
59
+ constructor (
60
+ public client: SequenceClient,
61
+ public provider: SequenceProvider
62
+ ) { }
63
+
64
+ async getAddress(): Promise<string> {
65
+ return this.client.getAddress()
66
+ }
67
+
68
+ // This method shouldn't be used directly
69
+ // it exists to maintain compatibility with ethers.Signer
70
+ connect(provider: ethers.providers.Provider): SequenceSigner {
71
+ if (!SequenceProvider.is(provider)) {
72
+ throw new Error("SequenceSigner can only be connected to a SequenceProvider")
73
+ }
74
+
75
+ return new SequenceSigner(this.client, provider)
76
+ }
77
+
78
+ getSigner(): SequenceSigner
79
+ getSigner(chainId: ChainIdLike): SingleNetworkSequenceSigner
80
+ getSigner(chainId?: ChainIdLike): SingleNetworkSequenceSigner | SequenceSigner
81
+
82
+ getSigner(chainId?: ChainIdLike): SingleNetworkSequenceSigner | SequenceSigner {
83
+ // The signer for the default network is this signer
84
+ if (!chainId) {
85
+ return this
86
+ }
87
+
88
+ const useChainId = this.provider.toChainId(chainId)
89
+
90
+ if (!this.singleNetworkSigners[useChainId]) {
91
+ this.singleNetworkSigners[useChainId] = new SingleNetworkSequenceSigner(this.client, this.provider, useChainId)
92
+ }
93
+
94
+ return this.singleNetworkSigners[useChainId]
95
+ }
96
+
97
+ /**
98
+ * Resolves the chainId to use for the given request. If no chainId is provided,
99
+ * it uses the chainId defined by the client (default chainId). This can be
100
+ * overriden to build a single-network SequenceProvider.
101
+ */
102
+ protected useChainId(chainId?: ChainIdLike): number {
103
+ return this.provider.toChainId(chainId) || this.client.getChainId()
104
+ }
105
+
106
+ async signMessage(
107
+ message: ethers.BytesLike,
108
+ options?: OptionalChainIdLike & OptionalEIP6492
109
+ ): Promise<string> {
110
+ const { eip6492 = true } = options || {}
111
+ const chainId = this.useChainId(options?.chainId)
112
+ return this.client.signMessage(message, { eip6492, chainId })
113
+ }
114
+
115
+ async signTypedData(
116
+ domain: ethers.TypedDataDomain,
117
+ types: Record<string, Array<ethers.TypedDataField>>,
118
+ message: Record<string, any>,
119
+ options?: OptionalChainIdLike & OptionalEIP6492
120
+ ): Promise<string> {
121
+ const { eip6492 = true } = options || {}
122
+ const chainId = this.useChainId(options?.chainId)
123
+ return this.client.signTypedData({ domain, types, message }, { eip6492, chainId })
124
+ }
125
+
126
+ getProvider(): SequenceProvider
127
+ getProvider(chainId: ChainIdLike): SingleNetworkSequenceProvider
128
+ getProvider(chainId?: ChainIdLike): SingleNetworkSequenceProvider | SequenceProvider
129
+
130
+ getProvider(chainId?: ChainIdLike): SingleNetworkSequenceProvider | SequenceProvider {
131
+ return this.provider.getProvider(chainId)
132
+ }
133
+
134
+ async sendTransaction(
135
+ transaction: (
136
+ ethers.utils.Deferrable<ethers.providers.TransactionRequest>[] |
137
+ ethers.utils.Deferrable<ethers.providers.TransactionRequest>
138
+ ),
139
+ options?: OptionalChainIdLike
140
+ ) {
141
+ const chainId = this.useChainId(options?.chainId)
142
+ const resolved = await resolveArrayProperties(transaction)
143
+ const txHash = await this.client.sendTransaction(resolved, { chainId })
144
+ const provider = this.getProvider(chainId)
145
+
146
+ try {
147
+ return await ethers.utils.poll(async () => {
148
+ const tx = await provider.getTransaction(txHash)
149
+ return tx ? provider._wrapTransaction(tx, txHash) : undefined
150
+ }, { onceBlock: provider }) as ethers.providers.TransactionResponse
151
+ } catch (err) {
152
+ err.transactionHash = txHash
153
+ throw err
154
+ }
155
+ }
156
+
157
+ async getWalletConfig(chainId?: ChainIdLike | undefined): Promise<commons.config.Config> {
158
+ const useChainId = this.useChainId(chainId)
159
+ return this.client.getOnchainWalletConfig({ chainId: useChainId })
160
+ }
161
+
162
+ getNetworks(): Promise<NetworkConfig[]> {
163
+ return this.client.getNetworks()
164
+ }
165
+
166
+ async getBalance(
167
+ blockTag?: ethers.providers.BlockTag | undefined,
168
+ optionals?: OptionalChainIdLike
169
+ ): Promise<ethers.BigNumber> {
170
+ const provider = this.getProvider(optionals?.chainId)
171
+ return provider.getBalance(this.getAddress(), blockTag)
172
+ }
173
+
174
+ async estimateGas(
175
+ transaction: ethers.utils.Deferrable<ethers.providers.TransactionRequest>,
176
+ optionals?: OptionalChainIdLike
177
+ ): Promise<ethers.BigNumber> {
178
+ return this.getProvider(optionals?.chainId).estimateGas(transaction)
179
+ }
180
+
181
+ async call(
182
+ transaction: ethers.utils.Deferrable<ethers.providers.TransactionRequest>,
183
+ blockTag?: ethers.providers.BlockTag | undefined,
184
+ optionals?: OptionalChainIdLike
185
+ ): Promise<string> {
186
+ return this.getProvider(optionals?.chainId).call(transaction, blockTag)
187
+ }
188
+
189
+ getChainId(): Promise<number> {
190
+ return Promise.resolve(this.client.getChainId())
191
+ }
192
+
193
+ async getGasPrice(optionals?: OptionalChainIdLike): Promise<ethers.BigNumber> {
194
+ return this.getProvider(optionals?.chainId).getGasPrice()
195
+ }
196
+
197
+ async getFeeData(optionals?: OptionalChainIdLike): Promise<ethers.providers.FeeData> {
198
+ return this.getProvider(optionals?.chainId).getFeeData()
199
+ }
200
+
201
+ async resolveName(name: string): Promise<string> {
202
+ const res = await this.provider.resolveName(name)
203
+
204
+ // For some reason ethers.Signer expects this to return `string`
205
+ // but ethers.providers.Provider expects this to return `string | null`.
206
+ // The signer doesn't have any other source of information, so we'll
207
+ // fail if the provider doesn't return a result.
208
+ if (res === null) {
209
+ throw new Error(`ENS name not found: ${name}`)
210
+ }
211
+
212
+ return res
213
+ }
214
+
215
+ _checkProvider(_operation?: string | undefined): void {
216
+ // We always have a provider, so this is a noop
217
+ }
218
+
219
+ populateTransaction(
220
+ _transaction: ethers.utils.Deferrable<ethers.providers.TransactionRequest>
221
+ ): Promise<ethers.providers.TransactionRequest> {
222
+ throw new Error("SequenceSigner does not support populateTransaction")
223
+ }
224
+
225
+ checkTransaction(
226
+ _transaction: ethers.utils.Deferrable<ethers.providers.TransactionRequest>
227
+ ): ethers.utils.Deferrable<ethers.providers.TransactionRequest> {
228
+ throw new Error("SequenceSigner does not support checkTransaction")
229
+ }
230
+
231
+ getTransactionCount(_blockTag?: ethers.providers.BlockTag | undefined): Promise<number> {
232
+ // We could try returning the sequence nonce here
233
+ // but we aren't sure how ethers will use this nonce
234
+ throw new Error("SequenceSigner does not support getTransactionCount")
235
+ }
236
+
237
+ signTransaction(_transaction: ethers.utils.Deferrable<commons.transaction.Transactionish>): Promise<string> {
238
+ // We could implement signTransaction/sendTransaction here
239
+ // but first we need a way of serializing these signed transactions
240
+ // and it could lead to more trouble, because the dapp could try to send this transaction
241
+ // using a different provider, which would fail.
242
+ throw new Error("SequenceWallet does not support signTransaction, use sendTransaction instead.")
243
+ }
244
+
245
+ static is(cand: any): cand is SequenceSigner {
246
+ return (
247
+ cand &&
248
+ typeof cand === "object" &&
249
+ cand._isSequenceSigner === true
250
+ )
251
+ }
252
+ }
253
+
254
+ /**
255
+ * This is the same provider, but it only allows a single network at a time.
256
+ * the network defined by the constructor is the only one that can be used.
257
+ *
258
+ * Attempting to call any method with a different network will throw an error.
259
+ * Attempting to change the network of this provider will throw an error.
260
+ *
261
+ * NOTICE: These networks won't support ENS unless they are the mainnet.
262
+ */
263
+ export class SingleNetworkSequenceSigner extends SequenceSigner {
264
+ readonly _isSingleNetworkSequenceSigner = true
265
+
266
+ constructor (
267
+ client: SequenceClient,
268
+ provider: SequenceProvider,
269
+ public readonly chainId: ChainIdLike
270
+ ) {
271
+ super(client, provider.getProvider(chainId))
272
+ }
273
+
274
+ private _useChainId(chainId?: ChainIdLike): number {
275
+ const provided = this.provider.toChainId(chainId)
276
+
277
+ if (provided && provided !== this.chainId) {
278
+ throw new Error(`This signer only supports the network ${this.chainId}, but ${provided} was requested.`)
279
+ }
280
+
281
+ return provided || this.provider.toChainId(this.chainId)
282
+ }
283
+
284
+ protected useChainId(chainId?: ChainIdLike): number {
285
+ return this._useChainId(chainId)
286
+ }
287
+
288
+ getChainId(): Promise<number> {
289
+ return Promise.resolve(this.provider.toChainId(this.chainId))
290
+ }
291
+
292
+ /**
293
+ * Override getProvider and getSigner so they always use `useChainId`
294
+ * this way they can't return providers and signers that can switch networks,
295
+ * or that don't match the chainId of this signer.
296
+ */
297
+ getProvider(chainId?: ChainIdLike): SingleNetworkSequenceProvider {
298
+ return super.getProvider(this._useChainId(chainId))
299
+ }
300
+
301
+ getSigner(chainId?: ChainIdLike | undefined): SingleNetworkSequenceSigner {
302
+ if (this._useChainId(chainId) !== this.chainId) {
303
+ throw new Error(`Unreachable code`)
304
+ }
305
+
306
+ return this
307
+ }
308
+
309
+ static is(cand: any): cand is SingleNetworkSequenceSigner {
310
+ return (
311
+ cand &&
312
+ typeof cand === "object" &&
313
+ cand._isSingleNetworkSequenceSigner === true
314
+ )
315
+ }
316
+ }
@@ -0,0 +1,23 @@
1
+ import { commons } from '@0xsequence/core'
2
+ import { ethers } from 'ethers'
3
+
4
+ export function validateTransactionRequest(wallet: string, transaction: commons.transaction.Transactionish) {
5
+ const transactions = commons.transaction.fromTransactionish(wallet, transaction)
6
+ const unwound = commons.transaction.unwind(wallet, transactions)
7
+ unwound.forEach(transaction => validateTransaction(wallet, transaction))
8
+ }
9
+
10
+ function validateTransaction(wallet: string, transaction: commons.transaction.Transaction) {
11
+ if (transaction.to.toLowerCase() === wallet.toLowerCase()) {
12
+ if (transaction.data) {
13
+ const data = ethers.utils.arrayify(transaction.data)
14
+ if (data.length >= 4) {
15
+ throw new Error('self calls are forbidden')
16
+ }
17
+ }
18
+ }
19
+
20
+ if (transaction.delegateCall) {
21
+ throw new Error('delegate calls are forbidden')
22
+ }
23
+ }
@@ -19,7 +19,7 @@ import { logger, sanitizeAlphanumeric, sanitizeHost, sanitizeNumberString } from
19
19
  import { AuthorizationOptions } from '@0xsequence/auth'
20
20
 
21
21
  import { PROVIDER_OPEN_TIMEOUT } from './base-provider-transport'
22
- import { isBrowserExtension, LocalStorage } from '../utils'
22
+ import { isBrowserExtension, useBestStore } from '../utils'
23
23
  import { commons } from '@0xsequence/core'
24
24
 
25
25
  const TRANSPORT_SESSION_LS_KEY = '@sequence.transportSession'
@@ -375,11 +375,6 @@ export abstract class BaseWalletTransport implements WalletTransport {
375
375
  // Set connect options on the walletRequestHandler as our primary
376
376
  // wallet controller, and fall back to networkId if necessary
377
377
  this.walletRequestHandler.setConnectOptions(connectOptions)
378
- if (connectOptions.networkId) {
379
- networkId = connectOptions.networkId
380
- } else if (networkId) {
381
- connectOptions.networkId = networkId
382
- }
383
378
  } else {
384
379
  this.walletRequestHandler.setConnectOptions(undefined)
385
380
  }
@@ -452,11 +447,11 @@ export abstract class BaseWalletTransport implements WalletTransport {
452
447
  }
453
448
 
454
449
  private saveTransportSession = (session: TransportSession) => {
455
- LocalStorage.getInstance().setItem(TRANSPORT_SESSION_LS_KEY, JSON.stringify(session))
450
+ useBestStore().setItem(TRANSPORT_SESSION_LS_KEY, JSON.stringify(session))
456
451
  }
457
452
 
458
453
  protected getCachedTransportSession = async (): Promise<TransportSession | null> => {
459
- const session = await LocalStorage.getInstance().getItem(TRANSPORT_SESSION_LS_KEY)
454
+ const session = useBestStore().getItem(TRANSPORT_SESSION_LS_KEY)
460
455
 
461
456
  try {
462
457
  return session ? (JSON.parse(session) as TransportSession) : null
@@ -1,12 +1,62 @@
1
1
  import {
2
- ProviderMessage, EventType, ProviderTransport,
2
+ ProviderMessage, ProviderTransport,
3
3
  ProviderEventTypes, ProviderMessageRequest, ProviderMessageResponse, WalletSession, OpenWalletIntent, ConnectDetails
4
4
  } from '../../types'
5
5
 
6
6
  import { JsonRpcRequest, JsonRpcResponseCallback } from '@0xsequence/network'
7
+ import { ProxyMessageChannelPort, ProxyMessageProvider } from '../proxy-transport'
8
+ import { Runtime } from 'webextension-polyfill'
9
+ import { UnrealMessageProvider } from '../unreal-transport'
10
+ import { ExtensionMessageProvider } from '../extension-transport'
11
+ import { WindowMessageProvider } from '../window-transport'
7
12
 
8
- export class MuxMessageProvider implements ProviderTransport {
13
+ export type MuxTransportTemplate = {
14
+ walletAppURL?: string
15
+
16
+ // WindowMessage transport (optional)
17
+ windowTransport?: {
18
+ enabled: boolean
19
+ }
20
+
21
+ // ProxyMessage transport (optional)
22
+ proxyTransport?: {
23
+ enabled: boolean
24
+ appPort?: ProxyMessageChannelPort
25
+ }
26
+
27
+ // Extension transport (optional)
28
+ extensionTransport?: {
29
+ enabled: boolean
30
+ runtime: Runtime.Static
31
+ }
9
32
 
33
+ // Unreal Engine transport (optional)
34
+ unrealTransport?: {
35
+ enabled: boolean
36
+ }
37
+ }
38
+
39
+ export function isMuxTransportTemplate(obj: any): obj is MuxTransportTemplate {
40
+ return (
41
+ obj &&
42
+ typeof obj === 'object' &&
43
+ (
44
+ (obj.windowTransport && typeof obj.windowTransport === 'object') ||
45
+ (obj.proxyTransport && typeof obj.proxyTransport === 'object') ||
46
+ (obj.extensionTransport && typeof obj.extensionTransport === 'object') ||
47
+ (obj.unrealTransport && typeof obj.unrealTransport === 'object')
48
+ ) &&
49
+ (
50
+ // One of the transports must be enabled
51
+ (obj.windowTransport && obj.windowTransport.enabled) ||
52
+ (obj.proxyTransport && obj.proxyTransport.enabled) ||
53
+ (obj.extensionTransport && obj.extensionTransport.enabled) ||
54
+ (obj.unrealTransport && obj.unrealTransport.enabled)
55
+ )
56
+ )
57
+ }
58
+
59
+ export class MuxMessageProvider implements ProviderTransport {
10
60
  private messageProviders: ProviderTransport[]
11
61
  private provider: ProviderTransport | undefined
12
62
 
@@ -15,6 +65,40 @@ export class MuxMessageProvider implements ProviderTransport {
15
65
  this.provider = undefined
16
66
  }
17
67
 
68
+ static new(template: MuxTransportTemplate): MuxMessageProvider {
69
+ const muxMessageProvider = new MuxMessageProvider()
70
+
71
+ if (template.windowTransport?.enabled && typeof window === 'object' && template.walletAppURL) {
72
+ const windowMessageProvider = new WindowMessageProvider(template.walletAppURL)
73
+ muxMessageProvider.add(windowMessageProvider)
74
+ }
75
+
76
+ if (template.proxyTransport?.enabled) {
77
+ const proxyMessageProvider = new ProxyMessageProvider(template.proxyTransport.appPort!)
78
+ muxMessageProvider.add(proxyMessageProvider)
79
+ }
80
+
81
+ if (template.extensionTransport?.enabled) {
82
+ const extensionMessageProvider = new ExtensionMessageProvider(template.extensionTransport.runtime)
83
+ muxMessageProvider.add(extensionMessageProvider)
84
+
85
+ // NOTE/REVIEW: see note in mux-message-provider
86
+ //
87
+ // We don't add the extensionMessageProvider here because we don't send requests to it anyways, we seem to
88
+ // send all requests to the WindowMessageProvider anyways. By allowing it, if browser restarts, it will break
89
+ // the entire extension because messageProvider.provider will be undefined. So this is a hack to fix it.
90
+ }
91
+
92
+ if (template.unrealTransport?.enabled && template.windowTransport && template.walletAppURL) {
93
+ const unrealMessageProvider = new UnrealMessageProvider(template.walletAppURL)
94
+ muxMessageProvider.add(unrealMessageProvider)
95
+ }
96
+
97
+ muxMessageProvider.register()
98
+
99
+ return muxMessageProvider
100
+ }
101
+
18
102
  add(...messageProviders: ProviderTransport[]) {
19
103
  this.messageProviders.push(...messageProviders)
20
104
  }
@@ -13,7 +13,7 @@ export class ProxyMessageProvider extends BaseProviderTransport {
13
13
  constructor(port: ProxyMessageChannelPort) {
14
14
  super()
15
15
  this.state = OpenState.CLOSED
16
- this.port = port
16
+ this.port = port
17
17
  if (!port) {
18
18
  throw new Error('port argument cannot be empty')
19
19
  }
@@ -7,6 +7,7 @@ import { BigNumber, ethers, providers } from 'ethers'
7
7
  import { EventEmitter2 as EventEmitter } from 'eventemitter2'
8
8
 
9
9
  import { fromExtended } from '../extended'
10
+ import { validateTransactionRequest } from '../transactions'
10
11
  import {
11
12
  ProviderMessageRequest,
12
13
  ProviderMessageResponse,
@@ -22,7 +23,7 @@ import {
22
23
  ProviderEventTypes,
23
24
  TypedEventEmitter
24
25
  } from '../types'
25
- import { isWalletUpToDate, prefixEIP191Message } from '../utils'
26
+ import { prefixEIP191Message } from '../utils'
26
27
 
27
28
  type ExternalProvider = providers.ExternalProvider
28
29
 
@@ -64,19 +65,6 @@ export class WalletRequestHandler implements ExternalProvider, JsonRpcHandler, P
64
65
  return this.prompter?.getDefaultChainId() ?? this.networks[0].chainId
65
66
  }
66
67
 
67
- private findNetworkID(network: string | number) {
68
- const lnet = typeof network === 'string' ? network.toLowerCase() : network
69
- const networkId = this.networks.find(n => {
70
- return n.name.toLowerCase() === lnet || n.chainId.toString() === lnet || n.chainId === lnet
71
- })
72
-
73
- if (!networkId) {
74
- throw new Error(`Network ${network} not found`)
75
- }
76
-
77
- return networkId.chainId
78
- }
79
-
80
68
  async signIn(account: Account | null, options: WalletSignInOptions = {}) {
81
69
  this.setAccount(account)
82
70
 
@@ -150,25 +138,7 @@ export class WalletRequestHandler implements ExternalProvider, JsonRpcHandler, P
150
138
  }
151
139
  }
152
140
 
153
- let chainId: number | string
154
- switch (typeof options?.networkId) {
155
- case 'string':
156
- // First see if it matches the name of a network
157
- try {
158
- chainId = this.findNetworkID(options.networkId)
159
- } catch (err) {
160
- // If not, try to parse it as a big number
161
- chainId = getChainId(options.networkId)
162
- }
163
-
164
- break
165
- case 'number':
166
- chainId = options.networkId
167
- break
168
- default:
169
- chainId = this.prompter?.getDefaultChainId() ?? 1
170
- break
171
- }
141
+ const chainId: number | string = this.prompter?.getDefaultChainId() ?? 1
172
142
 
173
143
  const connectDetails: ConnectDetails = {
174
144
  connected: true,
@@ -424,6 +394,8 @@ export class WalletRequestHandler implements ExternalProvider, JsonRpcHandler, P
424
394
  return tx
425
395
  })
426
396
 
397
+ validateTransactionRequest(account.address, transactionParams)
398
+
427
399
  let txnHash = ''
428
400
  if (this.prompter === null) {
429
401
  // prompter is null, so we'll send from here
@@ -452,6 +424,8 @@ export class WalletRequestHandler implements ExternalProvider, JsonRpcHandler, P
452
424
  throw new Error('sender address does not match wallet')
453
425
  }
454
426
 
427
+ validateTransactionRequest(account.address, transaction)
428
+
455
429
  if (this.prompter === null) {
456
430
  // The eth_signTransaction method expects a `string` return value we instead return a `SignedTransactions` object,
457
431
  // this can only be broadcasted using an RPC provider with support for signed Sequence transactions, like this one.
@@ -740,6 +714,7 @@ export class WalletRequestHandler implements ExternalProvider, JsonRpcHandler, P
740
714
  }
741
715
 
742
716
  notifyConnect(connectDetails: ConnectDetails, origin?: string) {
717
+ console.log('emit connect', connectDetails)
743
718
  this.events.emit('connect', connectDetails)
744
719
  if (connectDetails.session?.accountAddress) {
745
720
  this.events.emit('accountsChanged', [connectDetails.session?.accountAddress], origin)
@@ -88,11 +88,13 @@ export class WindowMessageProvider extends BaseProviderTransport {
88
88
  // when connecting to the wallet, however, this will be verified and enforced
89
89
  // on the wallet-side, so if a dapp provides the wrong origin, it will be dropped.
90
90
  if (intent.type === 'connect') {
91
- if (!intent.options) intent.options = {}
91
+ if (!intent.options) intent.options = {
92
+ app: window.location.origin
93
+ }
92
94
 
93
95
  // skip setting origin host if we're in an browser extension execution context
94
96
  // allow origin that is passed in
95
- if (!isBrowserExtension() && !isUnityPlugin()) {
97
+ if (!isBrowserExtension() && !isUnityPlugin() && intent.options) {
96
98
  intent.options.origin = window.location.origin
97
99
  }
98
100
  }
package/src/types.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { ETHAuthProof as AuthETHAuthProof } from '@0xsequence/auth'
2
2
  import { commons } from '@0xsequence/core'
3
- import { JsonRpcHandler, JsonRpcRequest, JsonRpcResponse, NetworkConfig, ProviderRpcError as NetworkProviderRpcError } from '@0xsequence/network'
3
+ import { ChainIdLike, JsonRpcHandler, JsonRpcRequest, JsonRpcResponse, NetworkConfig, ProviderRpcError as NetworkProviderRpcError } from '@0xsequence/network'
4
4
  import { TypedData } from '@0xsequence/utils'
5
5
 
6
6
  export interface ProviderTransport extends JsonRpcHandler, ProviderMessageTransport, ProviderMessageRequestHandler {
@@ -21,6 +21,20 @@ export interface ProviderTransport extends JsonRpcHandler, ProviderMessageTransp
21
21
  waitUntilConnected(): Promise<ConnectDetails>
22
22
  }
23
23
 
24
+ export function isProviderTransport(transport: any): transport is ProviderTransport {
25
+ return (
26
+ transport &&
27
+ typeof transport === 'object' &&
28
+ typeof transport.register === 'function' &&
29
+ typeof transport.unregister === 'function' &&
30
+ typeof transport.openWallet === 'function' &&
31
+ typeof transport.closeWallet === 'function' &&
32
+ typeof transport.isOpened === 'function' &&
33
+ typeof transport.isConnected === 'function' &&
34
+ typeof transport.on === 'function'
35
+ )
36
+ }
37
+
24
38
  export interface WalletTransport extends JsonRpcHandler, ProviderMessageTransport, ProviderMessageRequestHandler {
25
39
  register(): void
26
40
  unregister(): void
@@ -134,12 +148,8 @@ export enum InitState {
134
148
  }
135
149
 
136
150
  export interface ConnectOptions {
137
- /** Specifies the default network a dapp would like to connect to. This field
138
- * is optional as it can be provided a number of different ways. */
139
- networkId?: string | number
140
-
141
151
  /** app name of the dapp which will be announced to user on connect screen */
142
- app?: string
152
+ app: string
143
153
 
144
154
  /** custom protocol for auth redirect (unity/unreal) */
145
155
  appProtocol?: string
@@ -171,6 +181,13 @@ export interface ConnectOptions {
171
181
  settings?: Settings
172
182
  }
173
183
 
184
+ export interface NetworkedConnectOptions extends ConnectOptions {
185
+ /** chainId is the chainId to connect to. If not specified, the default chainId
186
+ * will be used. This does not define a default chain id, it is only used for the connect
187
+ * authorization signature. */
188
+ networkId?: string | number;
189
+ }
190
+
174
191
  /** Options to further customize the wallet experience. */
175
192
  export interface Settings {
176
193
  /** Specify a wallet theme. `light` and `dark` are the main themes, to use other available
@@ -256,7 +273,7 @@ export interface ConnectDetails {
256
273
  export type PromptConnectDetails = Pick<ConnectDetails, 'chainId' | 'error' | 'connected' | 'proof' | 'email'>
257
274
 
258
275
  export type OpenWalletIntent =
259
- | { type: 'connect'; options?: ConnectOptions }
276
+ | { type: 'connect'; options?: NetworkedConnectOptions }
260
277
  | { type: 'openWithOptions'; options?: ConnectOptions }
261
278
  | { type: 'jsonRpcRequest'; method: string }
262
279
 
@@ -280,9 +297,6 @@ export interface WalletSession {
280
297
  // Networks in use for the session. The default/dapp network will show
281
298
  // up as the first one in the list as the "main chain"
282
299
  networks?: NetworkConfig[]
283
-
284
- // Caching provider responses for things such as account and chainId
285
- providerCache?: { [key: string]: any }
286
300
  }
287
301
 
288
302
  export class ProviderError extends Error {
@@ -314,3 +328,20 @@ export interface TypedEventEmitter<Events> {
314
328
  }
315
329
 
316
330
  type Arguments<T> = [T] extends [(...args: infer U) => any] ? U : [T] extends [void] ? [] : [T]
331
+
332
+ export type OptionalChainIdLike = {
333
+ chainId?: ChainIdLike
334
+ } | undefined
335
+
336
+ export type OptionalChainId = {
337
+ chainId?: number
338
+ } | undefined
339
+
340
+ export type OptionalEIP6492 = {
341
+ eip6492?: boolean
342
+ } | undefined
343
+
344
+ // This is required by viem, it expects a provider to have an EIP-1193 compliant `request` attribute.
345
+ export interface EIP1193Provider {
346
+ request: (request: { method: string, params?: Array<any> }) => Promise<any>
347
+ }