@0xsequence/provider 0.43.34 → 1.0.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.
package/src/provider.ts CHANGED
@@ -1,21 +1,23 @@
1
- import { ethers, BytesLike, Bytes, providers, TypedDataDomain, TypedDataField, BigNumber } from 'ethers'
1
+ import { ethers, BytesLike, Bytes, providers, TypedDataDomain, TypedDataField } from 'ethers'
2
+
2
3
  import {
3
4
  NetworkConfig,
4
- WalletContext,
5
5
  ChainIdLike,
6
6
  JsonRpcHandler,
7
7
  JsonRpcFetchFunc,
8
8
  JsonRpcRequest,
9
9
  JsonRpcResponseCallback,
10
- maybeChainId,
11
- JsonRpcSender
10
+ JsonRpcSender,
11
+ maybeChainId
12
12
  } from '@0xsequence/network'
13
+
13
14
  import { resolveArrayProperties, Signer } from '@0xsequence/wallet'
14
- import { WalletConfig, WalletState } from '@0xsequence/config'
15
15
  import { Relayer } from '@0xsequence/relayer'
16
16
  import { Deferrable, shallowCopy, resolveProperties, Forbid } from '@0xsequence/utils'
17
- import { TransactionRequest, TransactionResponse, SignedTransactions } from '@0xsequence/transactions'
18
17
  import { WalletRequestHandler } from './transports/wallet-request-handler'
18
+ import { commons, universal } from '@0xsequence/core'
19
+ import { Account, AccountStatus } from '@0xsequence/account'
20
+ import { ExtendedTransactionRequest, toExtended } from './extended'
19
21
 
20
22
  export class Web3Provider extends providers.Web3Provider implements JsonRpcHandler {
21
23
  static isSequenceProvider(cand: any): cand is Web3Provider {
@@ -62,15 +64,16 @@ export class Web3Provider extends providers.Web3Provider implements JsonRpcHandl
62
64
  }
63
65
 
64
66
  async getChainId(): Promise<number> {
65
- // TODO: is it safe to memoize this?
66
- const result = await this.send('eth_chainId', [])
67
- const chainId = ethers.BigNumber.from(result).toNumber()
67
+ // If we already have a default chainId, then we can just return it
68
+ const defaultChainId = this._defaultChainId
69
+ if (defaultChainId) return defaultChainId
68
70
 
69
- if (this._defaultChainId && this._defaultChainId !== chainId) {
70
- throw new Error(`provider chainId (${chainId}) does not match provider-bound chainId ${this._defaultChainId}`)
71
- }
71
+ // If there is no default chain, then we can just return the chainId of the provider
72
+ return this.send('eth_chainId', [])
73
+ }
72
74
 
73
- return chainId
75
+ getNetworks(): Promise<NetworkConfig[]> {
76
+ return this.send('sequence_getNetworks', [])
74
77
  }
75
78
  }
76
79
 
@@ -80,8 +83,8 @@ export function isSequenceProvider(provider: any): provider is Web3Provider {
80
83
  }
81
84
 
82
85
  export class LocalWeb3Provider extends Web3Provider {
83
- constructor(signer: Signer, networks?: NetworkConfig[]) {
84
- const walletRequestHandler = new WalletRequestHandler(signer, null, networks || [])
86
+ constructor(account: Account, networks?: NetworkConfig[]) {
87
+ const walletRequestHandler = new WalletRequestHandler(account, null, networks || [])
85
88
  super(walletRequestHandler)
86
89
  }
87
90
  }
@@ -108,7 +111,7 @@ export class Web3Signer extends Signer implements TypedDataSigner {
108
111
  // memoized
109
112
  _address: string
110
113
  _index: number
111
- _context: WalletContext
114
+ _context: commons.context.VersionedContext
112
115
  _networks: NetworkConfig[]
113
116
  private _providers: { [key: number]: Web3Provider } = {}
114
117
 
@@ -124,7 +127,7 @@ export class Web3Signer extends Signer implements TypedDataSigner {
124
127
  return ethers.utils.getAddress(this._address)
125
128
  }
126
129
 
127
- signTransaction(transaction: Deferrable<TransactionRequest>): Promise<string> {
130
+ signTransaction(transaction: Deferrable<ethers.providers.TransactionRequest>): Promise<string> {
128
131
  // TODO .. since ethers isn't using this method, perhaps we will?
129
132
  throw new Error('signTransaction is unsupported, use signTransactions instead')
130
133
  }
@@ -175,55 +178,53 @@ export class Web3Signer extends Signer implements TypedDataSigner {
175
178
  throw new Error('TODO')
176
179
  }
177
180
 
178
- async getWalletContext(): Promise<WalletContext> {
181
+ async getWalletContext(): Promise<commons.context.VersionedContext> {
179
182
  if (!this._context) {
180
183
  this._context = await this.provider.send('sequence_getWalletContext', [])
181
184
  }
182
185
  return this._context
183
186
  }
184
187
 
185
- async getWalletConfig(chainId?: ChainIdLike): Promise<WalletConfig[]> {
186
- return await this.provider.send(
188
+ async getWalletConfig(chainId?: ChainIdLike): Promise<commons.config.Config> {
189
+ const reqChainId = maybeChainId(chainId) || this.defaultChainId
190
+ if (!reqChainId) throw new Error('chainId is required')
191
+ return (await this.provider.send(
187
192
  'sequence_getWalletConfig',
188
- [maybeChainId(chainId)],
189
- maybeChainId(chainId) || this.defaultChainId
190
- )
193
+ [reqChainId],
194
+ reqChainId
195
+ ))[0]
191
196
  }
192
197
 
193
- async getWalletState(chainId?: ChainIdLike): Promise<WalletState[]> {
194
- return await this.provider.send(
198
+ async getWalletState(chainId?: ChainIdLike): Promise<AccountStatus> {
199
+ const reqChainId = maybeChainId(chainId) || this.defaultChainId
200
+ if (!reqChainId) throw new Error('chainId is required')
201
+ return (await this.provider.send(
195
202
  'sequence_getWalletState',
196
- [maybeChainId(chainId)],
197
- maybeChainId(chainId) || this.defaultChainId
198
- )
203
+ [reqChainId],
204
+ reqChainId
205
+ ))[0].status
199
206
  }
200
207
 
201
208
  async getNetworks(): Promise<NetworkConfig[]> {
202
- if (!this._networks) {
203
- this._networks = await this.provider.send('sequence_getNetworks', [])
204
- }
209
+ if (!this._networks) this._networks = await this.provider.getNetworks()
205
210
  return this._networks
206
211
  }
207
212
 
208
213
  async getSigners(): Promise<string[]> {
209
214
  const networks = await this.getNetworks()
210
215
 
211
- const authChainId = networks.find(n => n.isAuthChain)
212
- if (!authChainId) {
213
- throw new Error('authChainId could not be determined from network list')
214
- }
215
-
216
- const walletConfig = await this.getWalletConfig(authChainId)
217
- if (!walletConfig || walletConfig.length === 0) {
216
+ // TODO: Replace this with a method that aggregates signer addresses from all chains
217
+ const config = await this.getWalletConfig(networks[0].chainId)
218
+ if (!config) {
218
219
  throw new Error(`walletConfig returned zero results for authChainId {authChainId}`)
219
220
  }
220
221
 
221
- return walletConfig[0].signers.map(s => s.address)
222
+ return universal.genericCoderFor(config.version).config.signersOf(config).map((s) => s.address)
222
223
  }
223
224
 
224
225
  // signMessage matches implementation from ethers JsonRpcSigner for compatibility, but with
225
226
  // multi-chain support.
226
- async signMessage(message: BytesLike, chainId?: ChainIdLike, allSigners?: boolean): Promise<string> {
227
+ async signMessage(message: BytesLike, chainId?: ChainIdLike, sequenceVerified: boolean = true): Promise<string> {
227
228
  const provider = await this.getSender(maybeChainId(chainId) || this.defaultChainId)
228
229
 
229
230
  const data = typeof message === 'string' ? ethers.utils.toUtf8Bytes(message) : message
@@ -232,7 +233,10 @@ export class Web3Signer extends Signer implements TypedDataSigner {
232
233
  // NOTE: as of ethers v5.5, it switched to using personal_sign, see
233
234
  // https://github.com/ethers-io/ethers.js/pull/1542 and see
234
235
  // https://github.com/WalletConnect/walletconnect-docs/issues/32 for additional info.
235
- return await provider!.send('personal_sign', [ethers.utils.hexlify(data), address])
236
+ return provider!.send(
237
+ sequenceVerified ? 'sequence_sign' : 'personal_sign',
238
+ [ethers.utils.hexlify(data), address]
239
+ )
236
240
  }
237
241
 
238
242
  // signTypedData matches implementation from ethers JsonRpcSigner for compatibility, but with
@@ -242,15 +246,15 @@ export class Web3Signer extends Signer implements TypedDataSigner {
242
246
  types: Record<string, Array<TypedDataField>>,
243
247
  message: Record<string, any>,
244
248
  chainId?: ChainIdLike,
245
- allSigners?: boolean
249
+ sequenceVerified: boolean = true
246
250
  ): Promise<string> {
247
251
  // Populate any ENS names (in-place)
248
252
  // const populated = await ethers.utils._TypedDataEncoder.resolveNames(domain, types, message, (name: string) => {
249
253
  // return this.provider.resolveName(name)
250
254
  // })
251
255
 
252
- return await this.provider.send(
253
- 'eth_signTypedData_v4',
256
+ return this.provider.send(
257
+ sequenceVerified ? 'sequence_signTypedData_v4' : 'eth_signTypedData_v4',
254
258
  [await this.getAddress(), ethers.utils._TypedDataEncoder.getPayload(domain, types, message)],
255
259
  maybeChainId(chainId) || this.defaultChainId
256
260
  )
@@ -259,17 +263,16 @@ export class Web3Signer extends Signer implements TypedDataSigner {
259
263
  // sendTransaction matches implementation from ethers JsonRpcSigner for compatibility, but with
260
264
  // multi-chain support.
261
265
  async sendTransaction(
262
- transaction: Deferrable<TransactionRequest>,
263
- chainId?: ChainIdLike,
264
- allSigners?: boolean
265
- ): Promise<TransactionResponse> {
266
+ transaction: Deferrable<ExtendedTransactionRequest>,
267
+ chainId?: ChainIdLike
268
+ ): Promise<commons.transaction.TransactionResponse> {
266
269
  const provider = await this.getSender(maybeChainId(chainId) || this.defaultChainId)
267
270
 
268
271
  const tx = this.sendUncheckedTransaction(transaction, chainId).then(hash => {
269
272
  return ethers.utils
270
273
  .poll(
271
274
  () => {
272
- return provider!.getTransaction(hash).then((tx: TransactionResponse) => {
275
+ return provider!.getTransaction(hash).then((tx: ethers.providers.TransactionResponse) => {
273
276
  if (tx === null) {
274
277
  return undefined
275
278
  }
@@ -291,11 +294,10 @@ export class Web3Signer extends Signer implements TypedDataSigner {
291
294
  // sendTransactionBatch is a convenience method to call sendTransaction in a batch format, allowing you to
292
295
  // send multiple transaction as a single payload and just one on-chain transaction.
293
296
  async sendTransactionBatch(
294
- transactions: Deferrable<Forbid<TransactionRequest, 'wait'>[]>,
295
- chainId?: ChainIdLike,
296
- allSigners?: boolean
297
- ): Promise<TransactionResponse> {
298
- const batch = await resolveArrayProperties<Forbid<TransactionRequest, 'wait'>[]>(transactions)
297
+ transactions: Deferrable<ethers.providers.TransactionRequest[]>,
298
+ chainId?: ChainIdLike
299
+ ): Promise<ethers.providers.TransactionResponse> {
300
+ const batch = await resolveArrayProperties<Forbid<ethers.providers.TransactionRequest, 'wait'>[]>(transactions)
299
301
  if (!batch || batch.length === 0) {
300
302
  throw new Error('cannot send empty batch')
301
303
  }
@@ -305,33 +307,31 @@ export class Web3Signer extends Signer implements TypedDataSigner {
305
307
  throw new Error('transaction request expected for sendTransactionBatch, transaction response found')
306
308
  }
307
309
 
308
- const tx: TransactionRequest = { ...batch[0] }
309
- if (batch.length > 1) {
310
- tx.auxiliary = batch.splice(1)
311
- }
312
-
313
- return this.sendTransaction(tx, chainId, allSigners)
310
+ const asExtended = toExtended(batch)
311
+ return this.sendTransaction(asExtended, chainId)
314
312
  }
315
313
 
316
314
  signTransactions(
317
- transaction: Deferrable<TransactionRequest>,
318
- chainId?: ChainIdLike,
319
- allSigners?: boolean
320
- ): Promise<SignedTransactions> {
315
+ transaction: Deferrable<ethers.providers.TransactionRequest>,
316
+ chainId?: ChainIdLike
317
+ ): Promise<commons.transaction.SignedTransactionBundle> {
321
318
  transaction = shallowCopy(transaction)
322
319
  // TODO: transaction argument..? make sure to resolve any properties and serialize property before sending over
323
320
  // the wire.. see sendUncheckedTransaction and resolveProperties
324
321
  return this.provider.send('eth_signTransaction', [transaction], maybeChainId(chainId) || this.defaultChainId)
325
322
  }
326
323
 
327
- sendSignedTransactions(signedTxs: SignedTransactions, chainId?: ChainIdLike): Promise<TransactionResponse> {
324
+ sendSignedTransactions(
325
+ signedTxs: commons.transaction.SignedTransactionBundle,
326
+ chainId?: ChainIdLike
327
+ ): Promise<ethers.providers.TransactionResponse> {
328
328
  // sequence_relay
329
329
  throw new Error('TODO')
330
330
  }
331
331
 
332
332
  // updateConfig..
333
333
  // NOTE: this is not supported by the remote wallet by default.
334
- async updateConfig(newConfig?: WalletConfig): Promise<[WalletConfig, TransactionResponse | undefined]> {
334
+ async updateConfig(newConfig?: commons.config.Config): Promise<[commons.config.Config, ethers.providers.TransactionResponse | undefined]> {
335
335
  // sequence_updateConfig
336
336
  const [config, tx] = await this.provider.send('sequence_updateConfig', [newConfig], this.defaultChainId)
337
337
  if (tx === null) {
@@ -344,7 +344,7 @@ export class Web3Signer extends Signer implements TypedDataSigner {
344
344
 
345
345
  // publishConfig..
346
346
  // NOTE: this is not supported by the remote wallet by default.
347
- async publishConfig(): Promise<TransactionResponse | undefined> {
347
+ async publishConfig(): Promise<ethers.providers.TransactionResponse | undefined> {
348
348
  const provider = await this.getSender(this.defaultChainId)
349
349
 
350
350
  const tx = await provider!.send('sequence_publishConfig', [])
@@ -364,7 +364,7 @@ export class Web3Signer extends Signer implements TypedDataSigner {
364
364
  // ethers JsonRpcSigner methods
365
365
  //
366
366
 
367
- async _legacySignMessage(message: Bytes | string, chainId?: ChainIdLike, allSigners?: boolean): Promise<string> {
367
+ async _legacySignMessage(message: Bytes | string, chainId?: ChainIdLike): Promise<string> {
368
368
  const provider = await this.getSender(maybeChainId(chainId) || this.defaultChainId)
369
369
 
370
370
  const data = typeof message === 'string' ? ethers.utils.toUtf8Bytes(message) : message
@@ -379,13 +379,12 @@ export class Web3Signer extends Signer implements TypedDataSigner {
379
379
  domain: TypedDataDomain,
380
380
  types: Record<string, Array<TypedDataField>>,
381
381
  message: Record<string, any>,
382
- chainId?: ChainIdLike,
383
- allSigners?: boolean
382
+ chainId?: ChainIdLike
384
383
  ): Promise<string> {
385
- return this.signTypedData(domain, types, message, chainId, allSigners)
384
+ return this.signTypedData(domain, types, message, chainId)
386
385
  }
387
386
 
388
- async sendUncheckedTransaction(transaction: Deferrable<TransactionRequest>, chainId?: ChainIdLike): Promise<string> {
387
+ async sendUncheckedTransaction(transaction: Deferrable<ExtendedTransactionRequest>, chainId?: ChainIdLike): Promise<string> {
389
388
  transaction = shallowCopy(transaction)
390
389
 
391
390
  const fromAddress = this.getAddress()
@@ -460,7 +459,7 @@ const allowedTransactionKeys: { [key: string]: boolean } = {
460
459
  }
461
460
 
462
461
  const hexlifyTransaction = (
463
- transaction: TransactionRequest,
462
+ transaction: ExtendedTransactionRequest,
464
463
  allowExtra?: { [key: string]: boolean }
465
464
  ): { [key: string]: string } => {
466
465
  // Check only allowed properties are given
@@ -513,9 +512,9 @@ const hexlifyTransaction = (
513
512
  }
514
513
 
515
514
  class UncheckedJsonRpcSigner extends Web3Signer {
516
- sendTransaction(transaction: Deferrable<TransactionRequest>): Promise<TransactionResponse> {
515
+ sendTransaction(transaction: Deferrable<ethers.providers.TransactionRequest>): Promise<commons.transaction.TransactionResponse> {
517
516
  return this.sendUncheckedTransaction(transaction).then(hash => {
518
- return <TransactionResponse>{
517
+ return <commons.transaction.TransactionResponse>{
519
518
  chainId: 0,
520
519
  confirmations: 0,
521
520
  data: '',
@@ -17,9 +17,10 @@ import {
17
17
  TypedEventEmitter
18
18
  } from '../types'
19
19
 
20
- import { NetworkConfig, WalletContext, JsonRpcRequest, JsonRpcResponseCallback, JsonRpcResponse } from '@0xsequence/network'
20
+ import { NetworkConfig, JsonRpcRequest, JsonRpcResponseCallback } from '@0xsequence/network'
21
21
  import { logger } from '@0xsequence/utils'
22
22
  import { ethers } from 'ethers'
23
+ import { commons } from '@0xsequence/core'
23
24
 
24
25
  export const PROVIDER_OPEN_TIMEOUT = 30000 // in ms
25
26
 
@@ -39,7 +40,7 @@ export abstract class BaseProviderTransport implements ProviderTransport {
39
40
  protected connectPayload: ConnectDetails | undefined
40
41
  protected accountsChangedPayload: { accounts: string[]; origin?: string } | undefined
41
42
  protected networksPayload: NetworkConfig[] | undefined
42
- protected walletContextPayload: WalletContext | undefined
43
+ protected walletContextPayload: commons.context.VersionedContext | undefined
43
44
 
44
45
  protected _sessionId?: string
45
46
  protected _init: InitState
@@ -5,23 +5,22 @@ import {
5
5
  ProviderMessageRequest,
6
6
  EventType,
7
7
  ProviderMessageResponse,
8
- ProviderMessageTransport,
9
8
  ProviderRpcError,
10
9
  InitState,
11
10
  ConnectDetails,
12
- OpenWalletIntent,
13
11
  WalletSession,
14
12
  TransportSession
15
13
  } from '../types'
16
14
 
17
15
  import { WalletRequestHandler } from './wallet-request-handler'
18
16
 
19
- import { NetworkConfig, WalletContext, JsonRpcRequest, JsonRpcResponseCallback } from '@0xsequence/network'
17
+ import { NetworkConfig, JsonRpcRequest, JsonRpcResponseCallback } from '@0xsequence/network'
20
18
  import { logger, sanitizeAlphanumeric, sanitizeHost, sanitizeNumberString } from '@0xsequence/utils'
21
19
  import { AuthorizationOptions } from '@0xsequence/auth'
22
20
 
23
21
  import { PROVIDER_OPEN_TIMEOUT } from './base-provider-transport'
24
22
  import { isBrowserExtension, LocalStorage } from '../utils'
23
+ import { commons } from '@0xsequence/core'
25
24
 
26
25
  const TRANSPORT_SESSION_LS_KEY = '@sequence.transportSession'
27
26
 
@@ -70,7 +69,7 @@ export abstract class BaseWalletTransport implements WalletTransport {
70
69
  }
71
70
  })
72
71
 
73
- this.walletRequestHandler.on('walletContext', (walletContext: WalletContext) => {
72
+ this.walletRequestHandler.on('walletContext', (walletContext: commons.context.VersionedContext) => {
74
73
  if (!this.registered || !walletContext) return
75
74
  this.notifyWalletContext(walletContext)
76
75
  })
@@ -231,7 +230,7 @@ export abstract class BaseWalletTransport implements WalletTransport {
231
230
  })
232
231
  }
233
232
 
234
- notifyWalletContext(walletContext: WalletContext) {
233
+ notifyWalletContext(walletContext: commons.context.VersionedContext) {
235
234
  this.sendMessage({
236
235
  idx: -1,
237
236
  type: EventType.WALLET_CONTEXT,
@@ -368,7 +367,7 @@ export abstract class BaseWalletTransport implements WalletTransport {
368
367
  }
369
368
 
370
369
  // ensure signer is ready
371
- await this.walletRequestHandler.getSigner()
370
+ await this.walletRequestHandler.getAccount()
372
371
 
373
372
  // Notify open and proceed to prompt for connection if intended
374
373
  if (!(await this.walletRequestHandler.isSignedIn())) {
@@ -386,9 +385,10 @@ export abstract class BaseWalletTransport implements WalletTransport {
386
385
  let chainId: number | undefined = undefined
387
386
  try {
388
387
  if (networkId) {
389
- chainId = await this.walletRequestHandler.setDefaultNetwork(networkId, false)
388
+ const networkIdNumber = ethers.BigNumber.from(networkId).toNumber()
389
+ chainId = await this.walletRequestHandler.setDefaultChainId(networkIdNumber)
390
390
  } else {
391
- chainId = await this.walletRequestHandler.getChainId()
391
+ chainId = this.walletRequestHandler.defaultChainId()
392
392
  }
393
393
  } catch (err) {
394
394
  console.error(err)
@@ -423,9 +423,10 @@ export abstract class BaseWalletTransport implements WalletTransport {
423
423
  let chainId: number | undefined = undefined
424
424
  try {
425
425
  if (networkId) {
426
- chainId = await this.walletRequestHandler.setDefaultNetwork(networkId, false)
426
+ const networkIdNumber = ethers.BigNumber.from(networkId).toNumber()
427
+ chainId = await this.walletRequestHandler.setDefaultChainId(networkIdNumber)
427
428
  } else {
428
- chainId = await this.walletRequestHandler.getChainId()
429
+ chainId = this.walletRequestHandler.defaultChainId()
429
430
  }
430
431
  } catch (err) {
431
432
  console.error(err)