@0xsequence/provider 0.35.7 → 0.35.11

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.
@@ -24,7 +24,7 @@ export declare class WalletRequestHandler implements ExternalProvider, JsonRpcHa
24
24
  signIn(signer: Signer | null, options?: WalletSignInOptions): Promise<void>;
25
25
  signOut(): void;
26
26
  signerReset(): void;
27
- signerReady(): Promise<unknown>;
27
+ signerReady(timeout?: number): Promise<void>;
28
28
  connect(options?: ConnectOptions): Promise<ConnectDetails>;
29
29
  promptConnect: (options?: ConnectOptions | undefined) => Promise<ConnectDetails>;
30
30
  sendMessageRequest(message: ProviderMessageRequest): Promise<ProviderMessageResponse>;
@@ -46,8 +46,8 @@ export declare class WalletRequestHandler implements ExternalProvider, JsonRpcHa
46
46
  notifyNetworks(networks?: NetworkConfig[]): Promise<void>;
47
47
  notifyWalletContext(): Promise<void>;
48
48
  notifyClose(error?: ProviderRpcError): void;
49
- isSignedIn(): boolean;
50
- getSigner(): Signer | null | undefined;
49
+ isSignedIn: () => Promise<boolean>;
50
+ getSigner: () => Promise<Signer | null>;
51
51
  setSigner(signer: Signer | null | undefined): void;
52
52
  private handleConfirmWalletDeployPrompt;
53
53
  }
@@ -1,9 +1,12 @@
1
- import { BigNumberish, BytesLike } from 'ethers';
1
+ import { ethers, BigNumberish, BytesLike } from 'ethers';
2
2
  import { WalletContext } from '@0xsequence/network';
3
3
  import { WalletConfig, DecodedSignature } from '@0xsequence/config';
4
+ import { TypedData } from '@0xsequence/utils';
4
5
  import { Web3Provider } from './provider';
5
6
  import { Signer } from '@0xsequence/wallet';
6
- export declare const isValidSignature: (address: string, digest: Uint8Array, sig: string, provider: Web3Provider, chainId?: number | undefined, walletContext?: WalletContext | undefined) => Promise<boolean | undefined>;
7
+ export declare const isValidSignature: (address: string, digest: Uint8Array, sig: string, provider: Web3Provider | ethers.providers.Web3Provider, chainId?: number | undefined, walletContext?: WalletContext | undefined) => Promise<boolean | undefined>;
8
+ export declare const isValidMessageSignature: (address: string, message: string | Uint8Array, signature: string, provider: Web3Provider | ethers.providers.Web3Provider, chainId?: number | undefined, walletContext?: WalletContext | undefined) => Promise<boolean | undefined>;
9
+ export declare const isValidTypedDataSignature: (address: string, typedData: TypedData, signature: string, provider: Web3Provider | ethers.providers.Web3Provider, chainId?: number | undefined, walletContext?: WalletContext | undefined) => Promise<boolean | undefined>;
7
10
  export declare const recoverWalletConfig: (address: string, digest: BytesLike, signature: string | DecodedSignature, chainId: BigNumberish, walletContext?: WalletContext | undefined) => Promise<WalletConfig>;
8
11
  export declare const isBrowserExtension: () => boolean;
9
12
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@0xsequence/provider",
3
- "version": "0.35.7",
3
+ "version": "0.35.11",
4
4
  "description": "provider sub-package for Sequence",
5
5
  "repository": "https://github.com/0xsequence/sequence.js/tree/master/packages/provider",
6
6
  "source": "src/index.ts",
@@ -13,13 +13,13 @@
13
13
  "typecheck": "tsc --noEmit"
14
14
  },
15
15
  "dependencies": {
16
- "@0xsequence/abi": "^0.35.7",
17
- "@0xsequence/auth": "^0.35.7",
18
- "@0xsequence/config": "^0.35.7",
19
- "@0xsequence/network": "^0.35.7",
20
- "@0xsequence/transactions": "^0.35.7",
21
- "@0xsequence/utils": "^0.35.7",
22
- "@0xsequence/wallet": "^0.35.7",
16
+ "@0xsequence/abi": "^0.35.11",
17
+ "@0xsequence/auth": "^0.35.11",
18
+ "@0xsequence/config": "^0.35.11",
19
+ "@0xsequence/network": "^0.35.11",
20
+ "@0xsequence/transactions": "^0.35.11",
21
+ "@0xsequence/utils": "^0.35.11",
22
+ "@0xsequence/wallet": "^0.35.11",
23
23
  "@ethersproject/abstract-signer": "^5.5.0",
24
24
  "@ethersproject/hash": "^5.5.0",
25
25
  "@ethersproject/providers": "^5.5.1",
@@ -1,10 +1,11 @@
1
- import { BigNumberish, BytesLike } from 'ethers'
1
+ import { ethers, BigNumberish, BytesLike } from 'ethers'
2
2
  import { TypedDataDomain, TypedDataField, TypedDataSigner } from '@ethersproject/abstract-signer'
3
3
  import { WalletContext, ChainIdLike } from '@0xsequence/network'
4
4
  import { encodeMessageDigest, TypedData, encodeTypedDataDigest } from '@0xsequence/utils'
5
5
  import { DecodedSignature, WalletConfig } from '@0xsequence/config'
6
6
  import { Wallet } from '../wallet'
7
7
  import { isValidSignature, recoverWalletConfig } from '../utils'
8
+ import { isValidEIP712Signature, isValidEthSignSignature } from '@0xsequence/wallet'
8
9
 
9
10
  export class WalletCommands {
10
11
  private wallet: Wallet
@@ -66,13 +67,19 @@ export class WalletCommands {
66
67
  }
67
68
 
68
69
  // Verify message signature
69
- isValidMessageSignature(
70
+ async isValidMessageSignature(
70
71
  address: string,
71
72
  message: string | Uint8Array,
72
73
  signature: string,
73
74
  chainId: number,
74
75
  walletContext?: WalletContext
75
76
  ): Promise<boolean | undefined> {
77
+ const msgDigest = ethers.utils.arrayify(ethers.utils.hashMessage(message))
78
+ if (
79
+ isValidEIP712Signature(address, msgDigest, signature) ||
80
+ isValidEthSignSignature(address, msgDigest, signature)
81
+ ) return true
82
+
76
83
  return this.isValidSignature(address, encodeMessageDigest(message), signature, chainId, walletContext)
77
84
  }
78
85
 
package/src/provider.ts CHANGED
@@ -72,6 +72,7 @@ export class Web3Provider extends EthersWeb3Provider implements JsonRpcHandler {
72
72
  }
73
73
 
74
74
  async getChainId(): Promise<number> {
75
+ // TODO: is it safe to memoize this?
75
76
  const result = await this.send('eth_chainId', [])
76
77
  const chainId = ethers.BigNumber.from(result).toNumber()
77
78
 
@@ -100,11 +100,6 @@ export abstract class BaseWalletTransport implements WalletTransport {
100
100
  handleMessage = async (message: ProviderMessage<any>) => {
101
101
  const request = message
102
102
 
103
- // ensure signer is ready to handle requests
104
- if (this.walletRequestHandler.getSigner() === undefined) {
105
- await this.walletRequestHandler.signerReady()
106
- }
107
-
108
103
  // ensure initial handshake is complete before accepting
109
104
  // other kinds of messages.
110
105
  if (this._init !== InitState.OK) {
@@ -123,6 +118,11 @@ export abstract class BaseWalletTransport implements WalletTransport {
123
118
  return
124
119
  }
125
120
 
121
+ // ensure signer is ready to handle requests
122
+ // if (this.walletRequestHandler.getSigner() === undefined) {
123
+ // await this.walletRequestHandler.signerReady()
124
+ // }
125
+
126
126
  // handle request
127
127
  switch (request.type) {
128
128
  case EventType.OPEN: {
@@ -321,11 +321,6 @@ export abstract class BaseWalletTransport implements WalletTransport {
321
321
 
322
322
  this.walletRequestHandler.setOpenIntent(intent)
323
323
 
324
- // ensure signer is ready
325
- if (this.walletRequestHandler.getSigner() === undefined) {
326
- await this.walletRequestHandler.signerReady()
327
- }
328
-
329
324
  // init handshake for certain transports, before we can open the communication.
330
325
  //
331
326
  // for example, with the window-transport, we have to exchange messages to determine the
@@ -369,8 +364,11 @@ export abstract class BaseWalletTransport implements WalletTransport {
369
364
  this.walletRequestHandler.setConnectOptions(undefined)
370
365
  }
371
366
 
367
+ // ensure signer is ready
368
+ await this.walletRequestHandler.getSigner()
369
+
372
370
  // Notify open and proceed to prompt for connection if intended
373
- if (!this.walletRequestHandler.isSignedIn()) {
371
+ if (!(await this.walletRequestHandler.isSignedIn())) {
374
372
  // open wallet without a specific connected chainId, as the user is not signed in
375
373
  this.notifyOpen({
376
374
  sessionId: this._sessionId
@@ -34,6 +34,8 @@ import { logger, TypedData } from '@0xsequence/utils'
34
34
 
35
35
  import { isWalletUpToDate } from '../utils'
36
36
 
37
+ const SIGNER_READY_TIMEOUT = 10000
38
+
37
39
  export interface WalletSignInOptions {
38
40
  connect?: boolean
39
41
  mainnetNetworks?: Networks
@@ -118,7 +120,7 @@ export class WalletRequestHandler implements ExternalProvider, JsonRpcHandler, P
118
120
 
119
121
  signOut() {
120
122
  // signed out state
121
- this.signer = null
123
+ this.setSigner(null)
122
124
  }
123
125
 
124
126
  signerReset() {
@@ -127,14 +129,18 @@ export class WalletRequestHandler implements ExternalProvider, JsonRpcHandler, P
127
129
  this.signer = undefined
128
130
  }
129
131
 
130
- signerReady() {
132
+ signerReady(timeout: number = SIGNER_READY_TIMEOUT): Promise<void> {
131
133
  return new Promise((resolve, reject) => {
132
134
  if (this.signer !== undefined) {
133
- resolve(undefined)
135
+ resolve()
134
136
  } else {
135
- this.signerReadyCallbacks.push(() => {
136
- resolve(undefined)
137
- })
137
+ setTimeout(() => {
138
+ if (this.signer === undefined) {
139
+ this.signerReadyCallbacks = []
140
+ reject(`signerReady timed out`)
141
+ }
142
+ }, timeout)
143
+ this.signerReadyCallbacks.push(resolve)
138
144
  }
139
145
  })
140
146
  }
@@ -238,9 +244,7 @@ export class WalletRequestHandler implements ExternalProvider, JsonRpcHandler, P
238
244
  result: null
239
245
  }
240
246
 
241
- if (this.signer === undefined) {
242
- await this.signerReady()
243
- }
247
+ await this.getSigner()
244
248
 
245
249
  try {
246
250
  // only allow public json rpc method to the provider when user is not logged in, aka signer is not set
@@ -720,11 +724,16 @@ export class WalletRequestHandler implements ExternalProvider, JsonRpcHandler, P
720
724
  this.events.emit('close', error)
721
725
  }
722
726
 
723
- isSignedIn(): boolean {
727
+ isSignedIn = async (): Promise<boolean> => {
728
+ await this.signerReady()
724
729
  return !!this.signer
725
730
  }
726
731
 
727
- getSigner(): Signer | null | undefined {
732
+ getSigner = async (): Promise<Signer | null> => {
733
+ await this.signerReady()
734
+ if (this.signer === undefined) {
735
+ throw new Error('signerReady failed resolve')
736
+ }
728
737
  return this.signer
729
738
  }
730
739
 
@@ -17,7 +17,9 @@ export class WindowMessageProvider extends BaseProviderTransport {
17
17
 
18
18
  register = () => {
19
19
  if (registeredWindowMessageProvider) {
20
- throw new Error('A WindowMessageProvider is already registered. There can only be one.')
20
+ // overriding the registered message provider
21
+ registeredWindowMessageProvider.unregister()
22
+ registeredWindowMessageProvider = this
21
23
  }
22
24
 
23
25
  // listen for incoming messages from wallet
@@ -80,6 +82,7 @@ export class WindowMessageProvider extends BaseProviderTransport {
80
82
  this._init = InitState.NIL
81
83
  this._sessionId = `${performance.now()}`
82
84
  windowSessionParams.set('sid', this._sessionId)
85
+
83
86
  if (intent) {
84
87
  // for the window-transport, we eagerly/optimistically set the origin host
85
88
  // when connecting to the wallet, however, this will be verified and enforced
package/src/utils.ts CHANGED
@@ -1,23 +1,55 @@
1
- import { BigNumberish, BytesLike } from 'ethers'
1
+ import { ethers, BigNumberish, BytesLike } from 'ethers'
2
2
  import { WalletContext } from '@0xsequence/network'
3
3
  import { WalletConfig, addressOf, DecodedSignature, isConfigEqual } from '@0xsequence/config'
4
- import { packMessageData } from '@0xsequence/utils'
4
+ import { packMessageData, encodeMessageDigest, TypedData, encodeTypedDataDigest } from '@0xsequence/utils'
5
5
  import { Web3Provider } from './provider'
6
- import { isValidSignature as _isValidSignature, recoverConfig, Signer } from '@0xsequence/wallet'
6
+ import { isValidSignature as _isValidSignature, recoverConfig, Signer, isValidEIP712Signature, isValidEthSignSignature } from '@0xsequence/wallet'
7
7
 
8
8
  export const isValidSignature = async (
9
9
  address: string,
10
10
  digest: Uint8Array,
11
11
  sig: string,
12
- provider: Web3Provider,
12
+ provider: Web3Provider | ethers.providers.Web3Provider,
13
13
  chainId?: number,
14
14
  walletContext?: WalletContext
15
15
  ): Promise<boolean | undefined> => {
16
- chainId = chainId || (await provider.getChainId())
17
- walletContext = walletContext || (await provider.getSigner().getWalletContext())
16
+ if (!chainId) {
17
+ chainId = (await provider.getNetwork())?.chainId
18
+ }
19
+ if (!walletContext && Web3Provider.isSequenceProvider(provider)) {
20
+ walletContext = await provider.getSigner().getWalletContext()
21
+ }
18
22
  return _isValidSignature(address, digest, sig, provider, walletContext, chainId)
19
23
  }
20
24
 
25
+ export const isValidMessageSignature = async (
26
+ address: string,
27
+ message: string | Uint8Array,
28
+ signature: string,
29
+ provider: Web3Provider | ethers.providers.Web3Provider,
30
+ chainId?: number,
31
+ walletContext?: WalletContext
32
+ ): Promise<boolean | undefined> => {
33
+ const msgDigest = ethers.utils.arrayify(ethers.utils.hashMessage(message))
34
+ if (
35
+ isValidEIP712Signature(address, msgDigest, signature) ||
36
+ isValidEthSignSignature(address, msgDigest, signature)
37
+ ) return true
38
+
39
+ return isValidSignature(address, encodeMessageDigest(message), signature, provider, chainId, walletContext)
40
+ }
41
+
42
+ export const isValidTypedDataSignature = (
43
+ address: string,
44
+ typedData: TypedData,
45
+ signature: string,
46
+ provider: Web3Provider | ethers.providers.Web3Provider,
47
+ chainId?: number,
48
+ walletContext?: WalletContext
49
+ ): Promise<boolean | undefined> => {
50
+ return isValidSignature(address, encodeTypedDataDigest(typedData), signature, provider, chainId, walletContext)
51
+ }
52
+
21
53
  export const recoverWalletConfig = async (
22
54
  address: string,
23
55
  digest: BytesLike,