@0xsequence/provider 0.35.5 → 0.35.9

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
@@ -1368,7 +1376,9 @@ class WindowMessageProvider extends BaseProviderTransport {
1368
1376
 
1369
1377
  this.register = () => {
1370
1378
  if (registeredWindowMessageProvider) {
1371
- throw new Error('A WindowMessageProvider is already registered. There can only be one.');
1379
+ // overriding the registered message provider
1380
+ registeredWindowMessageProvider.unregister();
1381
+ registeredWindowMessageProvider = this;
1372
1382
  } // listen for incoming messages from wallet
1373
1383
 
1374
1384
 
@@ -1616,12 +1626,6 @@ class WindowMessageHandler extends BaseWalletTransport {
1616
1626
  if (!session) {
1617
1627
  utils.logger.error('window session is undefined');
1618
1628
  return;
1619
- }
1620
-
1621
- if (session.intent && isNewWindowSession) {
1622
- window.history.replaceState({
1623
- openWalletIntent: true
1624
- }, document.title, pathname);
1625
1629
  } // record parent window instance for communication
1626
1630
 
1627
1631
 
@@ -1699,14 +1703,20 @@ class WindowMessageHandler extends BaseWalletTransport {
1699
1703
 
1700
1704
  }
1701
1705
 
1706
+ const SIGNER_READY_TIMEOUT = 10000;
1702
1707
  class WalletRequestHandler {
1708
+ // signer interface of the wallet. A null value means there is no signer (ie. user not signed in). An undefined
1709
+ // value means the signer state is unknown, usually meaning the wallet app is booting up and initializing. Of course
1710
+ // a Signer value is the actually interface to a signed-in account
1703
1711
  constructor(_signer, prompter, mainnetNetworks, testnetNetworks = []) {
1704
1712
  var _this = this;
1705
1713
 
1706
1714
  this.signer = void 0;
1715
+ this.signerReadyCallbacks = [];
1707
1716
  this.prompter = void 0;
1708
1717
  this.mainnetNetworks = void 0;
1709
1718
  this.testnetNetworks = void 0;
1719
+ this._openIntent = void 0;
1710
1720
  this._connectOptions = void 0;
1711
1721
  this._defaultNetworkId = void 0;
1712
1722
  this._chainId = void 0;
@@ -1743,6 +1753,7 @@ class WalletRequestHandler {
1743
1753
  id: request.id,
1744
1754
  result: null
1745
1755
  };
1756
+ await _this.getSigner();
1746
1757
 
1747
1758
  try {
1748
1759
  // only allow public json rpc method to the provider when user is not logged in, aka signer is not set
@@ -2135,6 +2146,21 @@ class WalletRequestHandler {
2135
2146
  callback(undefined, response);
2136
2147
  };
2137
2148
 
2149
+ this.isSignedIn = async function () {
2150
+ await _this.signerReady();
2151
+ return !!_this.signer;
2152
+ };
2153
+
2154
+ this.getSigner = async function () {
2155
+ await _this.signerReady();
2156
+
2157
+ if (_this.signer === undefined) {
2158
+ throw new Error('signerReady failed resolve');
2159
+ }
2160
+
2161
+ return _this.signer;
2162
+ };
2163
+
2138
2164
  this.signer = _signer;
2139
2165
  this.prompter = prompter;
2140
2166
  this.mainnetNetworks = mainnetNetworks;
@@ -2142,7 +2168,7 @@ class WalletRequestHandler {
2142
2168
  }
2143
2169
 
2144
2170
  async signIn(signer, options = {}) {
2145
- this.signer = signer;
2171
+ this.setSigner(signer);
2146
2172
  const {
2147
2173
  connect,
2148
2174
  mainnetNetworks,
@@ -2189,6 +2215,33 @@ class WalletRequestHandler {
2189
2215
  }
2190
2216
  }
2191
2217
 
2218
+ signOut() {
2219
+ // signed out state
2220
+ this.setSigner(null);
2221
+ }
2222
+
2223
+ signerReset() {
2224
+ // resetting signer puts the wallet in an uninitialized state, which requires the app to
2225
+ // re-initiatize and set the signer either as "null" (ie. no signer) or "Signer" (ie. signed in).
2226
+ this.signer = undefined;
2227
+ }
2228
+
2229
+ signerReady(timeout = SIGNER_READY_TIMEOUT) {
2230
+ return new Promise((resolve, reject) => {
2231
+ if (this.signer !== undefined) {
2232
+ resolve();
2233
+ } else {
2234
+ setTimeout(() => {
2235
+ if (this.signer === undefined) {
2236
+ this.signerReadyCallbacks = [];
2237
+ reject(`signerReady timed out`);
2238
+ }
2239
+ }, timeout);
2240
+ this.signerReadyCallbacks.push(resolve);
2241
+ }
2242
+ });
2243
+ }
2244
+
2192
2245
  async connect(options) {
2193
2246
  if (!this.signer) {
2194
2247
  return {
@@ -2277,6 +2330,14 @@ class WalletRequestHandler {
2277
2330
  }
2278
2331
  }
2279
2332
 
2333
+ get openIntent() {
2334
+ return this._openIntent;
2335
+ }
2336
+
2337
+ setOpenIntent(intent) {
2338
+ this._openIntent = intent;
2339
+ }
2340
+
2280
2341
  get connectOptions() {
2281
2342
  return this._connectOptions;
2282
2343
  }
@@ -2380,16 +2441,16 @@ class WalletRequestHandler {
2380
2441
  this.events.emit('close', error);
2381
2442
  }
2382
2443
 
2383
- isSignedIn() {
2384
- return !!this.signer;
2385
- }
2386
-
2387
- getSigner() {
2388
- return this.signer;
2389
- }
2390
-
2391
2444
  setSigner(signer) {
2392
2445
  this.signer = signer;
2446
+
2447
+ if (signer !== undefined) {
2448
+ for (let i = 0; i < this.signerReadyCallbacks.length; i++) {
2449
+ this.signerReadyCallbacks[i]();
2450
+ }
2451
+
2452
+ this.signerReadyCallbacks = [];
2453
+ }
2393
2454
  }
2394
2455
 
2395
2456
  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
@@ -1368,7 +1376,9 @@ class WindowMessageProvider extends BaseProviderTransport {
1368
1376
 
1369
1377
  this.register = () => {
1370
1378
  if (registeredWindowMessageProvider) {
1371
- throw new Error('A WindowMessageProvider is already registered. There can only be one.');
1379
+ // overriding the registered message provider
1380
+ registeredWindowMessageProvider.unregister();
1381
+ registeredWindowMessageProvider = this;
1372
1382
  } // listen for incoming messages from wallet
1373
1383
 
1374
1384
 
@@ -1616,12 +1626,6 @@ class WindowMessageHandler extends BaseWalletTransport {
1616
1626
  if (!session) {
1617
1627
  utils.logger.error('window session is undefined');
1618
1628
  return;
1619
- }
1620
-
1621
- if (session.intent && isNewWindowSession) {
1622
- window.history.replaceState({
1623
- openWalletIntent: true
1624
- }, document.title, pathname);
1625
1629
  } // record parent window instance for communication
1626
1630
 
1627
1631
 
@@ -1699,14 +1703,20 @@ class WindowMessageHandler extends BaseWalletTransport {
1699
1703
 
1700
1704
  }
1701
1705
 
1706
+ const SIGNER_READY_TIMEOUT = 10000;
1702
1707
  class WalletRequestHandler {
1708
+ // signer interface of the wallet. A null value means there is no signer (ie. user not signed in). An undefined
1709
+ // value means the signer state is unknown, usually meaning the wallet app is booting up and initializing. Of course
1710
+ // a Signer value is the actually interface to a signed-in account
1703
1711
  constructor(_signer, prompter, mainnetNetworks, testnetNetworks = []) {
1704
1712
  var _this = this;
1705
1713
 
1706
1714
  this.signer = void 0;
1715
+ this.signerReadyCallbacks = [];
1707
1716
  this.prompter = void 0;
1708
1717
  this.mainnetNetworks = void 0;
1709
1718
  this.testnetNetworks = void 0;
1719
+ this._openIntent = void 0;
1710
1720
  this._connectOptions = void 0;
1711
1721
  this._defaultNetworkId = void 0;
1712
1722
  this._chainId = void 0;
@@ -1743,6 +1753,7 @@ class WalletRequestHandler {
1743
1753
  id: request.id,
1744
1754
  result: null
1745
1755
  };
1756
+ await _this.getSigner();
1746
1757
 
1747
1758
  try {
1748
1759
  // only allow public json rpc method to the provider when user is not logged in, aka signer is not set
@@ -2135,6 +2146,21 @@ class WalletRequestHandler {
2135
2146
  callback(undefined, response);
2136
2147
  };
2137
2148
 
2149
+ this.isSignedIn = async function () {
2150
+ await _this.signerReady();
2151
+ return !!_this.signer;
2152
+ };
2153
+
2154
+ this.getSigner = async function () {
2155
+ await _this.signerReady();
2156
+
2157
+ if (_this.signer === undefined) {
2158
+ throw new Error('signerReady failed resolve');
2159
+ }
2160
+
2161
+ return _this.signer;
2162
+ };
2163
+
2138
2164
  this.signer = _signer;
2139
2165
  this.prompter = prompter;
2140
2166
  this.mainnetNetworks = mainnetNetworks;
@@ -2142,7 +2168,7 @@ class WalletRequestHandler {
2142
2168
  }
2143
2169
 
2144
2170
  async signIn(signer, options = {}) {
2145
- this.signer = signer;
2171
+ this.setSigner(signer);
2146
2172
  const {
2147
2173
  connect,
2148
2174
  mainnetNetworks,
@@ -2189,6 +2215,33 @@ class WalletRequestHandler {
2189
2215
  }
2190
2216
  }
2191
2217
 
2218
+ signOut() {
2219
+ // signed out state
2220
+ this.setSigner(null);
2221
+ }
2222
+
2223
+ signerReset() {
2224
+ // resetting signer puts the wallet in an uninitialized state, which requires the app to
2225
+ // re-initiatize and set the signer either as "null" (ie. no signer) or "Signer" (ie. signed in).
2226
+ this.signer = undefined;
2227
+ }
2228
+
2229
+ signerReady(timeout = SIGNER_READY_TIMEOUT) {
2230
+ return new Promise((resolve, reject) => {
2231
+ if (this.signer !== undefined) {
2232
+ resolve();
2233
+ } else {
2234
+ setTimeout(() => {
2235
+ if (this.signer === undefined) {
2236
+ this.signerReadyCallbacks = [];
2237
+ reject(`signerReady timed out`);
2238
+ }
2239
+ }, timeout);
2240
+ this.signerReadyCallbacks.push(resolve);
2241
+ }
2242
+ });
2243
+ }
2244
+
2192
2245
  async connect(options) {
2193
2246
  if (!this.signer) {
2194
2247
  return {
@@ -2277,6 +2330,14 @@ class WalletRequestHandler {
2277
2330
  }
2278
2331
  }
2279
2332
 
2333
+ get openIntent() {
2334
+ return this._openIntent;
2335
+ }
2336
+
2337
+ setOpenIntent(intent) {
2338
+ this._openIntent = intent;
2339
+ }
2340
+
2280
2341
  get connectOptions() {
2281
2342
  return this._connectOptions;
2282
2343
  }
@@ -2380,16 +2441,16 @@ class WalletRequestHandler {
2380
2441
  this.events.emit('close', error);
2381
2442
  }
2382
2443
 
2383
- isSignedIn() {
2384
- return !!this.signer;
2385
- }
2386
-
2387
- getSigner() {
2388
- return this.signer;
2389
- }
2390
-
2391
2444
  setSigner(signer) {
2392
2445
  this.signer = signer;
2446
+
2447
+ if (signer !== undefined) {
2448
+ for (let i = 0; i < this.signerReadyCallbacks.length; i++) {
2449
+ this.signerReadyCallbacks[i]();
2450
+ }
2451
+
2452
+ this.signerReadyCallbacks = [];
2453
+ }
2393
2454
  }
2394
2455
 
2395
2456
  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
@@ -1364,7 +1372,9 @@ class WindowMessageProvider extends BaseProviderTransport {
1364
1372
 
1365
1373
  this.register = () => {
1366
1374
  if (registeredWindowMessageProvider) {
1367
- throw new Error('A WindowMessageProvider is already registered. There can only be one.');
1375
+ // overriding the registered message provider
1376
+ registeredWindowMessageProvider.unregister();
1377
+ registeredWindowMessageProvider = this;
1368
1378
  } // listen for incoming messages from wallet
1369
1379
 
1370
1380
 
@@ -1612,12 +1622,6 @@ class WindowMessageHandler extends BaseWalletTransport {
1612
1622
  if (!session) {
1613
1623
  logger.error('window session is undefined');
1614
1624
  return;
1615
- }
1616
-
1617
- if (session.intent && isNewWindowSession) {
1618
- window.history.replaceState({
1619
- openWalletIntent: true
1620
- }, document.title, pathname);
1621
1625
  } // record parent window instance for communication
1622
1626
 
1623
1627
 
@@ -1695,14 +1699,20 @@ class WindowMessageHandler extends BaseWalletTransport {
1695
1699
 
1696
1700
  }
1697
1701
 
1702
+ const SIGNER_READY_TIMEOUT = 10000;
1698
1703
  class WalletRequestHandler {
1704
+ // signer interface of the wallet. A null value means there is no signer (ie. user not signed in). An undefined
1705
+ // value means the signer state is unknown, usually meaning the wallet app is booting up and initializing. Of course
1706
+ // a Signer value is the actually interface to a signed-in account
1699
1707
  constructor(_signer, prompter, mainnetNetworks, testnetNetworks = []) {
1700
1708
  var _this = this;
1701
1709
 
1702
1710
  this.signer = void 0;
1711
+ this.signerReadyCallbacks = [];
1703
1712
  this.prompter = void 0;
1704
1713
  this.mainnetNetworks = void 0;
1705
1714
  this.testnetNetworks = void 0;
1715
+ this._openIntent = void 0;
1706
1716
  this._connectOptions = void 0;
1707
1717
  this._defaultNetworkId = void 0;
1708
1718
  this._chainId = void 0;
@@ -1739,6 +1749,7 @@ class WalletRequestHandler {
1739
1749
  id: request.id,
1740
1750
  result: null
1741
1751
  };
1752
+ await _this.getSigner();
1742
1753
 
1743
1754
  try {
1744
1755
  // only allow public json rpc method to the provider when user is not logged in, aka signer is not set
@@ -2131,6 +2142,21 @@ class WalletRequestHandler {
2131
2142
  callback(undefined, response);
2132
2143
  };
2133
2144
 
2145
+ this.isSignedIn = async function () {
2146
+ await _this.signerReady();
2147
+ return !!_this.signer;
2148
+ };
2149
+
2150
+ this.getSigner = async function () {
2151
+ await _this.signerReady();
2152
+
2153
+ if (_this.signer === undefined) {
2154
+ throw new Error('signerReady failed resolve');
2155
+ }
2156
+
2157
+ return _this.signer;
2158
+ };
2159
+
2134
2160
  this.signer = _signer;
2135
2161
  this.prompter = prompter;
2136
2162
  this.mainnetNetworks = mainnetNetworks;
@@ -2138,7 +2164,7 @@ class WalletRequestHandler {
2138
2164
  }
2139
2165
 
2140
2166
  async signIn(signer, options = {}) {
2141
- this.signer = signer;
2167
+ this.setSigner(signer);
2142
2168
  const {
2143
2169
  connect,
2144
2170
  mainnetNetworks,
@@ -2185,6 +2211,33 @@ class WalletRequestHandler {
2185
2211
  }
2186
2212
  }
2187
2213
 
2214
+ signOut() {
2215
+ // signed out state
2216
+ this.setSigner(null);
2217
+ }
2218
+
2219
+ signerReset() {
2220
+ // resetting signer puts the wallet in an uninitialized state, which requires the app to
2221
+ // re-initiatize and set the signer either as "null" (ie. no signer) or "Signer" (ie. signed in).
2222
+ this.signer = undefined;
2223
+ }
2224
+
2225
+ signerReady(timeout = SIGNER_READY_TIMEOUT) {
2226
+ return new Promise((resolve, reject) => {
2227
+ if (this.signer !== undefined) {
2228
+ resolve();
2229
+ } else {
2230
+ setTimeout(() => {
2231
+ if (this.signer === undefined) {
2232
+ this.signerReadyCallbacks = [];
2233
+ reject(`signerReady timed out`);
2234
+ }
2235
+ }, timeout);
2236
+ this.signerReadyCallbacks.push(resolve);
2237
+ }
2238
+ });
2239
+ }
2240
+
2188
2241
  async connect(options) {
2189
2242
  if (!this.signer) {
2190
2243
  return {
@@ -2273,6 +2326,14 @@ class WalletRequestHandler {
2273
2326
  }
2274
2327
  }
2275
2328
 
2329
+ get openIntent() {
2330
+ return this._openIntent;
2331
+ }
2332
+
2333
+ setOpenIntent(intent) {
2334
+ this._openIntent = intent;
2335
+ }
2336
+
2276
2337
  get connectOptions() {
2277
2338
  return this._connectOptions;
2278
2339
  }
@@ -2376,16 +2437,16 @@ class WalletRequestHandler {
2376
2437
  this.events.emit('close', error);
2377
2438
  }
2378
2439
 
2379
- isSignedIn() {
2380
- return !!this.signer;
2381
- }
2382
-
2383
- getSigner() {
2384
- return this.signer;
2385
- }
2386
-
2387
2440
  setSigner(signer) {
2388
2441
  this.signer = signer;
2442
+
2443
+ if (signer !== undefined) {
2444
+ for (let i = 0; i < this.signerReadyCallbacks.length; i++) {
2445
+ this.signerReadyCallbacks[i]();
2446
+ }
2447
+
2448
+ this.signerReadyCallbacks = [];
2449
+ }
2389
2450
  }
2390
2451
 
2391
2452
  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.5",
3
+ "version": "0.35.9",
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.5",
17
- "@0xsequence/auth": "^0.35.5",
18
- "@0xsequence/config": "^0.35.5",
19
- "@0xsequence/network": "^0.35.5",
20
- "@0xsequence/transactions": "^0.35.5",
21
- "@0xsequence/utils": "^0.35.5",
22
- "@0xsequence/wallet": "^0.35.5",
16
+ "@0xsequence/abi": "^0.35.9",
17
+ "@0xsequence/auth": "^0.35.9",
18
+ "@0xsequence/config": "^0.35.9",
19
+ "@0xsequence/network": "^0.35.9",
20
+ "@0xsequence/transactions": "^0.35.9",
21
+ "@0xsequence/utils": "^0.35.9",
22
+ "@0xsequence/wallet": "^0.35.9",
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
 
@@ -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