@0xsequence/provider 0.35.4 → 0.35.8

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.
@@ -613,7 +613,11 @@ class BaseWalletTransport {
613
613
  }
614
614
 
615
615
  return;
616
- } // handle request
616
+ } // ensure signer is ready to handle requests
617
+ // if (this.walletRequestHandler.getSigner() === undefined) {
618
+ // await this.walletRequestHandler.signerReady()
619
+ // }
620
+ // handle request
617
621
 
618
622
 
619
623
  switch (request.type) {
@@ -671,7 +675,9 @@ class BaseWalletTransport {
671
675
  intent,
672
676
  networkId
673
677
  });
674
- } // init handshake for certain transports, before we can open the communication.
678
+ }
679
+
680
+ _this.walletRequestHandler.setOpenIntent(intent); // init handshake for certain transports, before we can open the communication.
675
681
  //
676
682
  // for example, with the window-transport, we have to exchange messages to determine the
677
683
  // origin host of the dapp.
@@ -713,10 +719,12 @@ class BaseWalletTransport {
713
719
  }
714
720
  } else {
715
721
  _this.walletRequestHandler.setConnectOptions(undefined);
716
- } // Notify open and proceed to prompt for connection if intended
722
+ } // ensure signer is ready
717
723
 
718
724
 
719
- if (!_this.walletRequestHandler.isSignedIn()) {
725
+ await _this.walletRequestHandler.getSigner(); // Notify open and proceed to prompt for connection if intended
726
+
727
+ if (!(await _this.walletRequestHandler.isSignedIn())) {
720
728
  // open wallet without a specific connected chainId, as the user is not signed in
721
729
  _this.notifyOpen({
722
730
  sessionId: _this._sessionId
@@ -1616,12 +1624,6 @@ class WindowMessageHandler extends BaseWalletTransport {
1616
1624
  if (!session) {
1617
1625
  utils.logger.error('window session is undefined');
1618
1626
  return;
1619
- }
1620
-
1621
- if (session.intent && isNewWindowSession) {
1622
- window.history.replaceState({
1623
- openWalletIntent: true
1624
- }, document.title, pathname);
1625
1627
  } // record parent window instance for communication
1626
1628
 
1627
1629
 
@@ -1699,14 +1701,20 @@ class WindowMessageHandler extends BaseWalletTransport {
1699
1701
 
1700
1702
  }
1701
1703
 
1704
+ const SIGNER_READY_TIMEOUT = 10000;
1702
1705
  class WalletRequestHandler {
1706
+ // signer interface of the wallet. A null value means there is no signer (ie. user not signed in). An undefined
1707
+ // value means the signer state is unknown, usually meaning the wallet app is booting up and initializing. Of course
1708
+ // a Signer value is the actually interface to a signed-in account
1703
1709
  constructor(_signer, prompter, mainnetNetworks, testnetNetworks = []) {
1704
1710
  var _this = this;
1705
1711
 
1706
1712
  this.signer = void 0;
1713
+ this.signerReadyCallbacks = [];
1707
1714
  this.prompter = void 0;
1708
1715
  this.mainnetNetworks = void 0;
1709
1716
  this.testnetNetworks = void 0;
1717
+ this._openIntent = void 0;
1710
1718
  this._connectOptions = void 0;
1711
1719
  this._defaultNetworkId = void 0;
1712
1720
  this._chainId = void 0;
@@ -1743,6 +1751,7 @@ class WalletRequestHandler {
1743
1751
  id: request.id,
1744
1752
  result: null
1745
1753
  };
1754
+ await _this.getSigner();
1746
1755
 
1747
1756
  try {
1748
1757
  // only allow public json rpc method to the provider when user is not logged in, aka signer is not set
@@ -2135,6 +2144,21 @@ class WalletRequestHandler {
2135
2144
  callback(undefined, response);
2136
2145
  };
2137
2146
 
2147
+ this.isSignedIn = async function () {
2148
+ await _this.signerReady();
2149
+ return !!_this.signer;
2150
+ };
2151
+
2152
+ this.getSigner = async function () {
2153
+ await _this.signerReady();
2154
+
2155
+ if (_this.signer === undefined) {
2156
+ throw new Error('signerReady failed resolve');
2157
+ }
2158
+
2159
+ return _this.signer;
2160
+ };
2161
+
2138
2162
  this.signer = _signer;
2139
2163
  this.prompter = prompter;
2140
2164
  this.mainnetNetworks = mainnetNetworks;
@@ -2142,7 +2166,7 @@ class WalletRequestHandler {
2142
2166
  }
2143
2167
 
2144
2168
  async signIn(signer, options = {}) {
2145
- this.signer = signer;
2169
+ this.setSigner(signer);
2146
2170
  const {
2147
2171
  connect,
2148
2172
  mainnetNetworks,
@@ -2189,6 +2213,33 @@ class WalletRequestHandler {
2189
2213
  }
2190
2214
  }
2191
2215
 
2216
+ signOut() {
2217
+ // signed out state
2218
+ this.setSigner(null);
2219
+ }
2220
+
2221
+ signerReset() {
2222
+ // resetting signer puts the wallet in an uninitialized state, which requires the app to
2223
+ // re-initiatize and set the signer either as "null" (ie. no signer) or "Signer" (ie. signed in).
2224
+ this.signer = undefined;
2225
+ }
2226
+
2227
+ signerReady(timeout = SIGNER_READY_TIMEOUT) {
2228
+ return new Promise((resolve, reject) => {
2229
+ if (this.signer !== undefined) {
2230
+ resolve();
2231
+ } else {
2232
+ setTimeout(() => {
2233
+ if (this.signer === undefined) {
2234
+ this.signerReadyCallbacks = [];
2235
+ reject(`signerReady timed out`);
2236
+ }
2237
+ }, timeout);
2238
+ this.signerReadyCallbacks.push(resolve);
2239
+ }
2240
+ });
2241
+ }
2242
+
2192
2243
  async connect(options) {
2193
2244
  if (!this.signer) {
2194
2245
  return {
@@ -2277,6 +2328,14 @@ class WalletRequestHandler {
2277
2328
  }
2278
2329
  }
2279
2330
 
2331
+ get openIntent() {
2332
+ return this._openIntent;
2333
+ }
2334
+
2335
+ setOpenIntent(intent) {
2336
+ this._openIntent = intent;
2337
+ }
2338
+
2280
2339
  get connectOptions() {
2281
2340
  return this._connectOptions;
2282
2341
  }
@@ -2380,16 +2439,16 @@ class WalletRequestHandler {
2380
2439
  this.events.emit('close', error);
2381
2440
  }
2382
2441
 
2383
- isSignedIn() {
2384
- return !!this.signer;
2385
- }
2386
-
2387
- getSigner() {
2388
- return this.signer;
2389
- }
2390
-
2391
2442
  setSigner(signer) {
2392
2443
  this.signer = signer;
2444
+
2445
+ if (signer !== undefined) {
2446
+ for (let i = 0; i < this.signerReadyCallbacks.length; i++) {
2447
+ this.signerReadyCallbacks[i]();
2448
+ }
2449
+
2450
+ this.signerReadyCallbacks = [];
2451
+ }
2393
2452
  }
2394
2453
 
2395
2454
  async handleConfirmWalletDeployPrompt(prompter, signer, chainId) {
@@ -613,7 +613,11 @@ class BaseWalletTransport {
613
613
  }
614
614
 
615
615
  return;
616
- } // handle request
616
+ } // ensure signer is ready to handle requests
617
+ // if (this.walletRequestHandler.getSigner() === undefined) {
618
+ // await this.walletRequestHandler.signerReady()
619
+ // }
620
+ // handle request
617
621
 
618
622
 
619
623
  switch (request.type) {
@@ -671,7 +675,9 @@ class BaseWalletTransport {
671
675
  intent,
672
676
  networkId
673
677
  });
674
- } // init handshake for certain transports, before we can open the communication.
678
+ }
679
+
680
+ _this.walletRequestHandler.setOpenIntent(intent); // init handshake for certain transports, before we can open the communication.
675
681
  //
676
682
  // for example, with the window-transport, we have to exchange messages to determine the
677
683
  // origin host of the dapp.
@@ -713,10 +719,12 @@ class BaseWalletTransport {
713
719
  }
714
720
  } else {
715
721
  _this.walletRequestHandler.setConnectOptions(undefined);
716
- } // Notify open and proceed to prompt for connection if intended
722
+ } // ensure signer is ready
717
723
 
718
724
 
719
- if (!_this.walletRequestHandler.isSignedIn()) {
725
+ await _this.walletRequestHandler.getSigner(); // Notify open and proceed to prompt for connection if intended
726
+
727
+ if (!(await _this.walletRequestHandler.isSignedIn())) {
720
728
  // open wallet without a specific connected chainId, as the user is not signed in
721
729
  _this.notifyOpen({
722
730
  sessionId: _this._sessionId
@@ -1616,12 +1624,6 @@ class WindowMessageHandler extends BaseWalletTransport {
1616
1624
  if (!session) {
1617
1625
  utils.logger.error('window session is undefined');
1618
1626
  return;
1619
- }
1620
-
1621
- if (session.intent && isNewWindowSession) {
1622
- window.history.replaceState({
1623
- openWalletIntent: true
1624
- }, document.title, pathname);
1625
1627
  } // record parent window instance for communication
1626
1628
 
1627
1629
 
@@ -1699,14 +1701,20 @@ class WindowMessageHandler extends BaseWalletTransport {
1699
1701
 
1700
1702
  }
1701
1703
 
1704
+ const SIGNER_READY_TIMEOUT = 10000;
1702
1705
  class WalletRequestHandler {
1706
+ // signer interface of the wallet. A null value means there is no signer (ie. user not signed in). An undefined
1707
+ // value means the signer state is unknown, usually meaning the wallet app is booting up and initializing. Of course
1708
+ // a Signer value is the actually interface to a signed-in account
1703
1709
  constructor(_signer, prompter, mainnetNetworks, testnetNetworks = []) {
1704
1710
  var _this = this;
1705
1711
 
1706
1712
  this.signer = void 0;
1713
+ this.signerReadyCallbacks = [];
1707
1714
  this.prompter = void 0;
1708
1715
  this.mainnetNetworks = void 0;
1709
1716
  this.testnetNetworks = void 0;
1717
+ this._openIntent = void 0;
1710
1718
  this._connectOptions = void 0;
1711
1719
  this._defaultNetworkId = void 0;
1712
1720
  this._chainId = void 0;
@@ -1743,6 +1751,7 @@ class WalletRequestHandler {
1743
1751
  id: request.id,
1744
1752
  result: null
1745
1753
  };
1754
+ await _this.getSigner();
1746
1755
 
1747
1756
  try {
1748
1757
  // only allow public json rpc method to the provider when user is not logged in, aka signer is not set
@@ -2135,6 +2144,21 @@ class WalletRequestHandler {
2135
2144
  callback(undefined, response);
2136
2145
  };
2137
2146
 
2147
+ this.isSignedIn = async function () {
2148
+ await _this.signerReady();
2149
+ return !!_this.signer;
2150
+ };
2151
+
2152
+ this.getSigner = async function () {
2153
+ await _this.signerReady();
2154
+
2155
+ if (_this.signer === undefined) {
2156
+ throw new Error('signerReady failed resolve');
2157
+ }
2158
+
2159
+ return _this.signer;
2160
+ };
2161
+
2138
2162
  this.signer = _signer;
2139
2163
  this.prompter = prompter;
2140
2164
  this.mainnetNetworks = mainnetNetworks;
@@ -2142,7 +2166,7 @@ class WalletRequestHandler {
2142
2166
  }
2143
2167
 
2144
2168
  async signIn(signer, options = {}) {
2145
- this.signer = signer;
2169
+ this.setSigner(signer);
2146
2170
  const {
2147
2171
  connect,
2148
2172
  mainnetNetworks,
@@ -2189,6 +2213,33 @@ class WalletRequestHandler {
2189
2213
  }
2190
2214
  }
2191
2215
 
2216
+ signOut() {
2217
+ // signed out state
2218
+ this.setSigner(null);
2219
+ }
2220
+
2221
+ signerReset() {
2222
+ // resetting signer puts the wallet in an uninitialized state, which requires the app to
2223
+ // re-initiatize and set the signer either as "null" (ie. no signer) or "Signer" (ie. signed in).
2224
+ this.signer = undefined;
2225
+ }
2226
+
2227
+ signerReady(timeout = SIGNER_READY_TIMEOUT) {
2228
+ return new Promise((resolve, reject) => {
2229
+ if (this.signer !== undefined) {
2230
+ resolve();
2231
+ } else {
2232
+ setTimeout(() => {
2233
+ if (this.signer === undefined) {
2234
+ this.signerReadyCallbacks = [];
2235
+ reject(`signerReady timed out`);
2236
+ }
2237
+ }, timeout);
2238
+ this.signerReadyCallbacks.push(resolve);
2239
+ }
2240
+ });
2241
+ }
2242
+
2192
2243
  async connect(options) {
2193
2244
  if (!this.signer) {
2194
2245
  return {
@@ -2277,6 +2328,14 @@ class WalletRequestHandler {
2277
2328
  }
2278
2329
  }
2279
2330
 
2331
+ get openIntent() {
2332
+ return this._openIntent;
2333
+ }
2334
+
2335
+ setOpenIntent(intent) {
2336
+ this._openIntent = intent;
2337
+ }
2338
+
2280
2339
  get connectOptions() {
2281
2340
  return this._connectOptions;
2282
2341
  }
@@ -2380,16 +2439,16 @@ class WalletRequestHandler {
2380
2439
  this.events.emit('close', error);
2381
2440
  }
2382
2441
 
2383
- isSignedIn() {
2384
- return !!this.signer;
2385
- }
2386
-
2387
- getSigner() {
2388
- return this.signer;
2389
- }
2390
-
2391
2442
  setSigner(signer) {
2392
2443
  this.signer = signer;
2444
+
2445
+ if (signer !== undefined) {
2446
+ for (let i = 0; i < this.signerReadyCallbacks.length; i++) {
2447
+ this.signerReadyCallbacks[i]();
2448
+ }
2449
+
2450
+ this.signerReadyCallbacks = [];
2451
+ }
2393
2452
  }
2394
2453
 
2395
2454
  async handleConfirmWalletDeployPrompt(prompter, signer, chainId) {
@@ -609,7 +609,11 @@ class BaseWalletTransport {
609
609
  }
610
610
 
611
611
  return;
612
- } // handle request
612
+ } // ensure signer is ready to handle requests
613
+ // if (this.walletRequestHandler.getSigner() === undefined) {
614
+ // await this.walletRequestHandler.signerReady()
615
+ // }
616
+ // handle request
613
617
 
614
618
 
615
619
  switch (request.type) {
@@ -667,7 +671,9 @@ class BaseWalletTransport {
667
671
  intent,
668
672
  networkId
669
673
  });
670
- } // init handshake for certain transports, before we can open the communication.
674
+ }
675
+
676
+ _this.walletRequestHandler.setOpenIntent(intent); // init handshake for certain transports, before we can open the communication.
671
677
  //
672
678
  // for example, with the window-transport, we have to exchange messages to determine the
673
679
  // origin host of the dapp.
@@ -709,10 +715,12 @@ class BaseWalletTransport {
709
715
  }
710
716
  } else {
711
717
  _this.walletRequestHandler.setConnectOptions(undefined);
712
- } // Notify open and proceed to prompt for connection if intended
718
+ } // ensure signer is ready
713
719
 
714
720
 
715
- if (!_this.walletRequestHandler.isSignedIn()) {
721
+ await _this.walletRequestHandler.getSigner(); // Notify open and proceed to prompt for connection if intended
722
+
723
+ if (!(await _this.walletRequestHandler.isSignedIn())) {
716
724
  // open wallet without a specific connected chainId, as the user is not signed in
717
725
  _this.notifyOpen({
718
726
  sessionId: _this._sessionId
@@ -1612,12 +1620,6 @@ class WindowMessageHandler extends BaseWalletTransport {
1612
1620
  if (!session) {
1613
1621
  logger.error('window session is undefined');
1614
1622
  return;
1615
- }
1616
-
1617
- if (session.intent && isNewWindowSession) {
1618
- window.history.replaceState({
1619
- openWalletIntent: true
1620
- }, document.title, pathname);
1621
1623
  } // record parent window instance for communication
1622
1624
 
1623
1625
 
@@ -1695,14 +1697,20 @@ class WindowMessageHandler extends BaseWalletTransport {
1695
1697
 
1696
1698
  }
1697
1699
 
1700
+ const SIGNER_READY_TIMEOUT = 10000;
1698
1701
  class WalletRequestHandler {
1702
+ // signer interface of the wallet. A null value means there is no signer (ie. user not signed in). An undefined
1703
+ // value means the signer state is unknown, usually meaning the wallet app is booting up and initializing. Of course
1704
+ // a Signer value is the actually interface to a signed-in account
1699
1705
  constructor(_signer, prompter, mainnetNetworks, testnetNetworks = []) {
1700
1706
  var _this = this;
1701
1707
 
1702
1708
  this.signer = void 0;
1709
+ this.signerReadyCallbacks = [];
1703
1710
  this.prompter = void 0;
1704
1711
  this.mainnetNetworks = void 0;
1705
1712
  this.testnetNetworks = void 0;
1713
+ this._openIntent = void 0;
1706
1714
  this._connectOptions = void 0;
1707
1715
  this._defaultNetworkId = void 0;
1708
1716
  this._chainId = void 0;
@@ -1739,6 +1747,7 @@ class WalletRequestHandler {
1739
1747
  id: request.id,
1740
1748
  result: null
1741
1749
  };
1750
+ await _this.getSigner();
1742
1751
 
1743
1752
  try {
1744
1753
  // only allow public json rpc method to the provider when user is not logged in, aka signer is not set
@@ -2131,6 +2140,21 @@ class WalletRequestHandler {
2131
2140
  callback(undefined, response);
2132
2141
  };
2133
2142
 
2143
+ this.isSignedIn = async function () {
2144
+ await _this.signerReady();
2145
+ return !!_this.signer;
2146
+ };
2147
+
2148
+ this.getSigner = async function () {
2149
+ await _this.signerReady();
2150
+
2151
+ if (_this.signer === undefined) {
2152
+ throw new Error('signerReady failed resolve');
2153
+ }
2154
+
2155
+ return _this.signer;
2156
+ };
2157
+
2134
2158
  this.signer = _signer;
2135
2159
  this.prompter = prompter;
2136
2160
  this.mainnetNetworks = mainnetNetworks;
@@ -2138,7 +2162,7 @@ class WalletRequestHandler {
2138
2162
  }
2139
2163
 
2140
2164
  async signIn(signer, options = {}) {
2141
- this.signer = signer;
2165
+ this.setSigner(signer);
2142
2166
  const {
2143
2167
  connect,
2144
2168
  mainnetNetworks,
@@ -2185,6 +2209,33 @@ class WalletRequestHandler {
2185
2209
  }
2186
2210
  }
2187
2211
 
2212
+ signOut() {
2213
+ // signed out state
2214
+ this.setSigner(null);
2215
+ }
2216
+
2217
+ signerReset() {
2218
+ // resetting signer puts the wallet in an uninitialized state, which requires the app to
2219
+ // re-initiatize and set the signer either as "null" (ie. no signer) or "Signer" (ie. signed in).
2220
+ this.signer = undefined;
2221
+ }
2222
+
2223
+ signerReady(timeout = SIGNER_READY_TIMEOUT) {
2224
+ return new Promise((resolve, reject) => {
2225
+ if (this.signer !== undefined) {
2226
+ resolve();
2227
+ } else {
2228
+ setTimeout(() => {
2229
+ if (this.signer === undefined) {
2230
+ this.signerReadyCallbacks = [];
2231
+ reject(`signerReady timed out`);
2232
+ }
2233
+ }, timeout);
2234
+ this.signerReadyCallbacks.push(resolve);
2235
+ }
2236
+ });
2237
+ }
2238
+
2188
2239
  async connect(options) {
2189
2240
  if (!this.signer) {
2190
2241
  return {
@@ -2273,6 +2324,14 @@ class WalletRequestHandler {
2273
2324
  }
2274
2325
  }
2275
2326
 
2327
+ get openIntent() {
2328
+ return this._openIntent;
2329
+ }
2330
+
2331
+ setOpenIntent(intent) {
2332
+ this._openIntent = intent;
2333
+ }
2334
+
2276
2335
  get connectOptions() {
2277
2336
  return this._connectOptions;
2278
2337
  }
@@ -2376,16 +2435,16 @@ class WalletRequestHandler {
2376
2435
  this.events.emit('close', error);
2377
2436
  }
2378
2437
 
2379
- isSignedIn() {
2380
- return !!this.signer;
2381
- }
2382
-
2383
- getSigner() {
2384
- return this.signer;
2385
- }
2386
-
2387
2438
  setSigner(signer) {
2388
2439
  this.signer = signer;
2440
+
2441
+ if (signer !== undefined) {
2442
+ for (let i = 0; i < this.signerReadyCallbacks.length; i++) {
2443
+ this.signerReadyCallbacks[i]();
2444
+ }
2445
+
2446
+ this.signerReadyCallbacks = [];
2447
+ }
2389
2448
  }
2390
2449
 
2391
2450
  async handleConfirmWalletDeployPrompt(prompter, signer, chainId) {
@@ -1,4 +1,4 @@
1
- import { ProviderMessageRequest, ProviderMessageResponse, ProviderMessageRequestHandler, MessageToSign, ProviderRpcError, ConnectOptions, ConnectDetails, PromptConnectDetails, WalletSession, ProviderEventTypes } from '../types';
1
+ import { ProviderMessageRequest, ProviderMessageResponse, ProviderMessageRequestHandler, MessageToSign, ProviderRpcError, ConnectOptions, ConnectDetails, PromptConnectDetails, WalletSession, OpenWalletIntent, ProviderEventTypes } from '../types';
2
2
  import { ExternalProvider } from '@ethersproject/providers';
3
3
  import { Networks, NetworkConfig, JsonRpcHandler, JsonRpcRequest, JsonRpcResponseCallback } from '@0xsequence/network';
4
4
  import { Signer } from '@0xsequence/wallet';
@@ -11,15 +11,20 @@ export interface WalletSignInOptions {
11
11
  }
12
12
  export declare class WalletRequestHandler implements ExternalProvider, JsonRpcHandler, ProviderMessageRequestHandler {
13
13
  private signer;
14
+ private signerReadyCallbacks;
14
15
  private prompter;
15
16
  private mainnetNetworks;
16
17
  private testnetNetworks;
18
+ private _openIntent?;
17
19
  private _connectOptions?;
18
20
  private _defaultNetworkId?;
19
21
  private _chainId?;
20
22
  private events;
21
- constructor(signer: Signer | null, prompter: WalletUserPrompter | null, mainnetNetworks: Networks, testnetNetworks?: Networks);
23
+ constructor(signer: Signer | null | undefined, prompter: WalletUserPrompter | null, mainnetNetworks: Networks, testnetNetworks?: Networks);
22
24
  signIn(signer: Signer | null, options?: WalletSignInOptions): Promise<void>;
25
+ signOut(): void;
26
+ signerReset(): void;
27
+ signerReady(timeout?: number): Promise<void>;
23
28
  connect(options?: ConnectOptions): Promise<ConnectDetails>;
24
29
  promptConnect: (options?: ConnectOptions | undefined) => Promise<ConnectDetails>;
25
30
  sendMessageRequest(message: ProviderMessageRequest): Promise<ProviderMessageResponse>;
@@ -28,6 +33,8 @@ export declare class WalletRequestHandler implements ExternalProvider, JsonRpcHa
28
33
  once<K extends keyof ProviderEventTypes>(event: K, fn: ProviderEventTypes[K]): void;
29
34
  getAddress(): Promise<string>;
30
35
  getChainId(): Promise<number>;
36
+ get openIntent(): OpenWalletIntent | undefined;
37
+ setOpenIntent(intent: OpenWalletIntent | undefined): void;
31
38
  get connectOptions(): ConnectOptions | undefined;
32
39
  setConnectOptions(options: ConnectOptions | undefined): void;
33
40
  get defaultNetworkId(): string | number | undefined;
@@ -39,9 +46,9 @@ export declare class WalletRequestHandler implements ExternalProvider, JsonRpcHa
39
46
  notifyNetworks(networks?: NetworkConfig[]): Promise<void>;
40
47
  notifyWalletContext(): Promise<void>;
41
48
  notifyClose(error?: ProviderRpcError): void;
42
- isSignedIn(): boolean;
43
- getSigner(): Signer | null;
44
- setSigner(signer: Signer | null): void;
49
+ isSignedIn: () => Promise<boolean>;
50
+ getSigner: () => Promise<Signer | null>;
51
+ setSigner(signer: Signer | null | undefined): void;
45
52
  private handleConfirmWalletDeployPrompt;
46
53
  }
47
54
  export interface WalletUserPrompter {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@0xsequence/provider",
3
- "version": "0.35.4",
3
+ "version": "0.35.8",
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.4",
17
- "@0xsequence/auth": "^0.35.4",
18
- "@0xsequence/config": "^0.35.4",
19
- "@0xsequence/network": "^0.35.4",
20
- "@0xsequence/transactions": "^0.35.4",
21
- "@0xsequence/utils": "^0.35.4",
22
- "@0xsequence/wallet": "^0.35.4",
16
+ "@0xsequence/abi": "^0.35.8",
17
+ "@0xsequence/auth": "^0.35.8",
18
+ "@0xsequence/config": "^0.35.8",
19
+ "@0xsequence/network": "^0.35.8",
20
+ "@0xsequence/transactions": "^0.35.8",
21
+ "@0xsequence/utils": "^0.35.8",
22
+ "@0xsequence/wallet": "^0.35.8",
23
23
  "@ethersproject/abstract-signer": "^5.5.0",
24
24
  "@ethersproject/hash": "^5.5.0",
25
25
  "@ethersproject/providers": "^5.5.1",
@@ -118,6 +118,11 @@ export abstract class BaseWalletTransport implements WalletTransport {
118
118
  return
119
119
  }
120
120
 
121
+ // ensure signer is ready to handle requests
122
+ // if (this.walletRequestHandler.getSigner() === undefined) {
123
+ // await this.walletRequestHandler.signerReady()
124
+ // }
125
+
121
126
  // handle request
122
127
  switch (request.type) {
123
128
  case EventType.OPEN: {
@@ -314,6 +319,8 @@ export abstract class BaseWalletTransport implements WalletTransport {
314
319
  this.saveTransportSession({ sessionId, intent, networkId })
315
320
  }
316
321
 
322
+ this.walletRequestHandler.setOpenIntent(intent)
323
+
317
324
  // init handshake for certain transports, before we can open the communication.
318
325
  //
319
326
  // for example, with the window-transport, we have to exchange messages to determine the
@@ -357,8 +364,11 @@ export abstract class BaseWalletTransport implements WalletTransport {
357
364
  this.walletRequestHandler.setConnectOptions(undefined)
358
365
  }
359
366
 
367
+ // ensure signer is ready
368
+ await this.walletRequestHandler.getSigner()
369
+
360
370
  // Notify open and proceed to prompt for connection if intended
361
- if (!this.walletRequestHandler.isSignedIn()) {
371
+ if (!(await this.walletRequestHandler.isSignedIn())) {
362
372
  // open wallet without a specific connected chainId, as the user is not signed in
363
373
  this.notifyOpen({
364
374
  sessionId: this._sessionId
@@ -10,6 +10,7 @@ import {
10
10
  ConnectDetails,
11
11
  PromptConnectDetails,
12
12
  WalletSession,
13
+ OpenWalletIntent,
13
14
  ErrSignedInRequired,
14
15
  ProviderEventTypes,
15
16
  TypedEventEmitter
@@ -33,6 +34,8 @@ import { logger, TypedData } from '@0xsequence/utils'
33
34
 
34
35
  import { isWalletUpToDate } from '../utils'
35
36
 
37
+ const SIGNER_READY_TIMEOUT = 10000
38
+
36
39
  export interface WalletSignInOptions {
37
40
  connect?: boolean
38
41
  mainnetNetworks?: Networks
@@ -41,11 +44,17 @@ export interface WalletSignInOptions {
41
44
  }
42
45
 
43
46
  export class WalletRequestHandler implements ExternalProvider, JsonRpcHandler, ProviderMessageRequestHandler {
44
- private signer: Signer | null
47
+ // signer interface of the wallet. A null value means there is no signer (ie. user not signed in). An undefined
48
+ // value means the signer state is unknown, usually meaning the wallet app is booting up and initializing. Of course
49
+ // a Signer value is the actually interface to a signed-in account
50
+ private signer: Signer | null | undefined
51
+ private signerReadyCallbacks: Array<() => void> = []
52
+
45
53
  private prompter: WalletUserPrompter | null
46
54
  private mainnetNetworks: NetworkConfig[]
47
55
  private testnetNetworks: NetworkConfig[]
48
56
 
57
+ private _openIntent?: OpenWalletIntent
49
58
  private _connectOptions?: ConnectOptions
50
59
  private _defaultNetworkId?: string | number
51
60
  private _chainId?: number
@@ -53,7 +62,7 @@ export class WalletRequestHandler implements ExternalProvider, JsonRpcHandler, P
53
62
  private events: TypedEventEmitter<ProviderEventTypes> = new EventEmitter() as TypedEventEmitter<ProviderEventTypes>
54
63
 
55
64
  constructor(
56
- signer: Signer | null,
65
+ signer: Signer | null | undefined,
57
66
  prompter: WalletUserPrompter | null,
58
67
  mainnetNetworks: Networks,
59
68
  testnetNetworks: Networks = []
@@ -65,7 +74,7 @@ export class WalletRequestHandler implements ExternalProvider, JsonRpcHandler, P
65
74
  }
66
75
 
67
76
  async signIn(signer: Signer | null, options: WalletSignInOptions = {}) {
68
- this.signer = signer
77
+ this.setSigner(signer)
69
78
 
70
79
  const { connect, mainnetNetworks, testnetNetworks, defaultNetworkId } = options
71
80
 
@@ -109,6 +118,33 @@ export class WalletRequestHandler implements ExternalProvider, JsonRpcHandler, P
109
118
  }
110
119
  }
111
120
 
121
+ signOut() {
122
+ // signed out state
123
+ this.setSigner(null)
124
+ }
125
+
126
+ signerReset() {
127
+ // resetting signer puts the wallet in an uninitialized state, which requires the app to
128
+ // re-initiatize and set the signer either as "null" (ie. no signer) or "Signer" (ie. signed in).
129
+ this.signer = undefined
130
+ }
131
+
132
+ signerReady(timeout: number = SIGNER_READY_TIMEOUT): Promise<void> {
133
+ return new Promise((resolve, reject) => {
134
+ if (this.signer !== undefined) {
135
+ resolve()
136
+ } else {
137
+ setTimeout(() => {
138
+ if (this.signer === undefined) {
139
+ this.signerReadyCallbacks = []
140
+ reject(`signerReady timed out`)
141
+ }
142
+ }, timeout)
143
+ this.signerReadyCallbacks.push(resolve)
144
+ }
145
+ })
146
+ }
147
+
112
148
  async connect(options?: ConnectOptions): Promise<ConnectDetails> {
113
149
  if (!this.signer) {
114
150
  return {
@@ -208,6 +244,8 @@ export class WalletRequestHandler implements ExternalProvider, JsonRpcHandler, P
208
244
  result: null
209
245
  }
210
246
 
247
+ await this.getSigner()
248
+
211
249
  try {
212
250
  // only allow public json rpc method to the provider when user is not logged in, aka signer is not set
213
251
  if ((!this.signer || this.signer === null) && !permittedJsonRpcMethods.includes(request.method)) {
@@ -583,6 +621,14 @@ export class WalletRequestHandler implements ExternalProvider, JsonRpcHandler, P
583
621
  }
584
622
  }
585
623
 
624
+ get openIntent(): OpenWalletIntent | undefined {
625
+ return this._openIntent
626
+ }
627
+
628
+ setOpenIntent(intent: OpenWalletIntent | undefined) {
629
+ this._openIntent = intent
630
+ }
631
+
586
632
  get connectOptions(): ConnectOptions | undefined {
587
633
  return this._connectOptions
588
634
  }
@@ -678,16 +724,28 @@ export class WalletRequestHandler implements ExternalProvider, JsonRpcHandler, P
678
724
  this.events.emit('close', error)
679
725
  }
680
726
 
681
- isSignedIn(): boolean {
727
+ isSignedIn = async (): Promise<boolean> => {
728
+ await this.signerReady()
682
729
  return !!this.signer
683
730
  }
684
731
 
685
- getSigner(): Signer | null {
732
+ getSigner = async (): Promise<Signer | null> => {
733
+ await this.signerReady()
734
+ if (this.signer === undefined) {
735
+ throw new Error('signerReady failed resolve')
736
+ }
686
737
  return this.signer
687
738
  }
688
739
 
689
- setSigner(signer: Signer | null) {
740
+ setSigner(signer: Signer | null | undefined) {
690
741
  this.signer = signer
742
+
743
+ if (signer !== undefined) {
744
+ for (let i = 0; i < this.signerReadyCallbacks.length; i++) {
745
+ this.signerReadyCallbacks[i]()
746
+ }
747
+ this.signerReadyCallbacks = []
748
+ }
691
749
  }
692
750
 
693
751
  private async handleConfirmWalletDeployPrompt(
@@ -47,10 +47,6 @@ export class WindowMessageHandler extends BaseWalletTransport {
47
47
  return
48
48
  }
49
49
 
50
- if (session.intent && isNewWindowSession) {
51
- window.history.replaceState({ openWalletIntent: true }, document.title, pathname)
52
- }
53
-
54
50
  // record parent window instance for communication
55
51
  this.parentWindow = parent.window.opener
56
52
 
@@ -80,6 +80,7 @@ export class WindowMessageProvider extends BaseProviderTransport {
80
80
  this._init = InitState.NIL
81
81
  this._sessionId = `${performance.now()}`
82
82
  windowSessionParams.set('sid', this._sessionId)
83
+
83
84
  if (intent) {
84
85
  // for the window-transport, we eagerly/optimistically set the origin host
85
86
  // when connecting to the wallet, however, this will be verified and enforced