@web3auth/no-modal 11.0.0-beta.1 → 11.0.0-beta.2

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.
@@ -19,6 +19,7 @@ require('../../base/connector/constants.js');
19
19
  require('jwt-decode');
20
20
  require('../../base/plugin/errors.js');
21
21
  require('../../base/plugin/IPlugin.js');
22
+ var useChain = require('../composables/useChain.js');
22
23
  var useWeb3Auth = require('../composables/useWeb3Auth.js');
23
24
  var constants = require('./constants.js');
24
25
 
@@ -45,58 +46,81 @@ const SolanaProvider = vue.defineComponent({
45
46
  connection,
46
47
  web3Auth
47
48
  } = useWeb3Auth.useWeb3Auth();
49
+ const {
50
+ chainId
51
+ } = useChain.useChain();
48
52
  const clientRef = vue.ref(null);
53
+ // Holds the token for the newest requested sync run. Older async runs compare against it
54
+ // before publishing results so a slower reconnect cannot overwrite a newer chain/account update.
55
+ let activeSyncToken = null;
49
56
  // provide the client to the app
50
57
  vue.provide(constants.SOLANA_CLIENT_KEY, clientRef);
51
- // watch for changes in the connection and chain namespace
52
- vue.watch([isConnected, connection], async ([newIsConnected, newConnection]) => {
53
- var _web3Auth$value;
54
- if (!newIsConnected || !(newConnection !== null && newConnection !== void 0 && newConnection.solanaWallet)) {
55
- if (clientRef.value) {
56
- await disposeClient(clientRef.value);
57
- clientRef.value = null;
58
+ const syncClient = async () => {
59
+ var _web3Auth$value, _web3Auth$value2;
60
+ // Only the latest async, `syncing` run should be allowed to attach its client.
61
+ // A fresh Symbol gives each run a unique identity without relying on counters.
62
+ const syncToken = Symbol("solana-client-sync");
63
+ activeSyncToken = syncToken;
64
+ const newIsConnected = isConnected.value;
65
+ const newConnection = connection.value;
66
+ const currentChain = (_web3Auth$value = web3Auth.value) === null || _web3Auth$value === void 0 ? void 0 : _web3Auth$value.currentChain;
67
+ if (!newIsConnected || !(newConnection !== null && newConnection !== void 0 && newConnection.solanaWallet) || (currentChain === null || currentChain === void 0 ? void 0 : currentChain.chainNamespace) !== baseControllers.CHAIN_NAMESPACES.SOLANA ||
68
+ // only reconnect for the primary connector
69
+ newConnection.connectorName !== ((_web3Auth$value2 = web3Auth.value) === null || _web3Auth$value2 === void 0 ? void 0 : _web3Auth$value2.primaryConnectorName)) {
70
+ const prevClient = clientRef.value;
71
+ clientRef.value = null;
72
+ if (prevClient) {
73
+ await disposeClient(prevClient);
58
74
  }
59
75
  return;
60
76
  }
61
- const currentChain = web3Auth.value.currentChain;
62
- let chainConfig;
63
- if ((currentChain === null || currentChain === void 0 ? void 0 : currentChain.chainNamespace) === baseControllers.CHAIN_NAMESPACES.SOLANA) {
64
- chainConfig = currentChain;
65
- } else {
66
- // use the 1st Solana chain if current chain is not solana
67
- chainConfig = web3Auth.value.coreOptions.chains.find(c => c.chainNamespace === baseControllers.CHAIN_NAMESPACES.SOLANA);
68
- if (!chainConfig) return;
69
- }
70
- // only reconnect for the primary connector
71
- if (newConnection.connectorName !== ((_web3Auth$value = web3Auth.value) === null || _web3Auth$value === void 0 ? void 0 : _web3Auth$value.primaryConnectorName)) return;
72
77
  const prevClient = clientRef.value;
78
+ clientRef.value = null;
79
+ if (prevClient) {
80
+ await disposeClient(prevClient);
81
+ }
82
+ let client$1 = null;
73
83
  try {
74
84
  // create a wallet standard connector from connected wallet
75
- const solanaWalletId = "wallet-standard:" + connection.value.connectorName;
76
- const connector = client.createWalletStandardConnector(connection.value.solanaWallet, {
85
+ const solanaWalletId = "wallet-standard:" + newConnection.connectorName;
86
+ const connector = client.createWalletStandardConnector(newConnection.solanaWallet, {
77
87
  id: solanaWalletId,
78
- name: connection.value.connectorName
88
+ name: newConnection.connectorName
79
89
  });
80
90
  // create a solana client
81
91
  const {
82
92
  rpcTarget,
83
93
  wsTarget
84
- } = chainConfig;
85
- const client$1 = client.createClient({
94
+ } = currentChain;
95
+ client$1 = client.createClient({
86
96
  endpoint: rpcTarget,
87
97
  websocketEndpoint: wsTarget,
88
98
  walletConnectors: [connector]
89
99
  });
90
- clientRef.value = client$1;
91
- if (prevClient) await disposeClient(prevClient);
92
100
  // connect the client to the wallet
93
101
  await client$1.actions.connectWallet(solanaWalletId, {
94
102
  autoConnect: true
95
103
  });
104
+ // If another sync started while connectWallet was in flight, this client is stale.
105
+ if (activeSyncToken !== syncToken) {
106
+ await disposeClient(client$1);
107
+ return;
108
+ }
109
+ clientRef.value = client$1;
96
110
  } catch (err) {
111
+ if (client$1) {
112
+ await disposeClient(client$1);
113
+ }
97
114
  loglevel.log.error("Failed to create or connect Solana client", err);
98
- clientRef.value = null;
115
+ // Only clear the shared ref when this failing run is still the newest one.
116
+ if (activeSyncToken === syncToken) {
117
+ clientRef.value = null;
118
+ }
99
119
  }
120
+ };
121
+ // watch for changes in the connection and active chain
122
+ vue.watch([isConnected, connection, chainId], () => {
123
+ void syncClient();
100
124
  }, {
101
125
  immediate: true
102
126
  });
@@ -89,7 +89,8 @@ const Web3AuthWagmiProvider = vue.defineComponent({
89
89
  setup() {
90
90
  const {
91
91
  isConnected,
92
- connection
92
+ connection,
93
+ chainNamespace
93
94
  } = useWeb3Auth.useWeb3Auth();
94
95
  const {
95
96
  disconnect
@@ -98,11 +99,15 @@ const Web3AuthWagmiProvider = vue.defineComponent({
98
99
  const {
99
100
  mutate: reconnect
100
101
  } = vue$1.useReconnect();
101
- const lastSyncedWeb3AuthConnection = vue.shallowRef(null);
102
+ const lastSyncedProvider = vue.shallowRef(null);
103
+ const lastSyncedConnectorName = vue.ref(null);
104
+ const suppressWagmiDisconnect = vue.ref(false);
102
105
  vue$1.useConnectionEffect({
103
106
  onDisconnect: async () => {
104
107
  loglevel.log.info("Disconnected from wagmi");
105
- if (isConnected.value) await disconnect();
108
+ const isSuppressed = suppressWagmiDisconnect.value;
109
+ suppressWagmiDisconnect.value = false;
110
+ if (!isSuppressed && isConnected.value) await disconnect();
106
111
  const connector = getWeb3authConnector(wagmiConfig);
107
112
  // reset wagmi connector state if the provider handles disconnection because of the accountsChanged event
108
113
  // from the connected provider
@@ -111,30 +116,41 @@ const Web3AuthWagmiProvider = vue.defineComponent({
111
116
  }
112
117
  }
113
118
  });
114
- vue.watch([isConnected, connection], async () => {
119
+ vue.watch([isConnected, connection, chainNamespace], async () => {
115
120
  var _newConnection$ethere;
116
121
  const newIsConnected = isConnected.value;
117
122
  const newConnection = connection.value;
118
123
  const newEth = (_newConnection$ethere = newConnection === null || newConnection === void 0 ? void 0 : newConnection.ethereumProvider) !== null && _newConnection$ethere !== void 0 ? _newConnection$ethere : null;
119
- if (newIsConnected && newConnection && newEth) {
120
- // Linked-account switches can reuse or replace the underlying wallet provider,
121
- // so key wagmi resyncs off the Web3Auth connection object instead of provider identity.
122
- if (lastSyncedWeb3AuthConnection.value !== newConnection) {
123
- if (getWeb3authConnector(wagmiConfig)) {
124
+ const shouldBindToWagmi = newIsConnected && chainNamespace.value === baseControllers.CHAIN_NAMESPACES.EIP155 && Boolean(newConnection && newEth);
125
+ if (shouldBindToWagmi && newConnection && newEth) {
126
+ const hasSameBinding = lastSyncedProvider.value === newEth && lastSyncedConnectorName.value === newConnection.connectorName;
127
+ if (hasSameBinding && wagmiConfig.state.status === "connected") {
128
+ return;
129
+ }
130
+ if (!hasSameBinding && getWeb3authConnector(wagmiConfig)) {
131
+ if (wagmiConfig.state.status === "connected") {
132
+ suppressWagmiDisconnect.value = true;
133
+ await disconnectWeb3AuthFromWagmi(wagmiConfig);
134
+ } else {
124
135
  resetConnectorState(wagmiConfig);
125
136
  }
126
- lastSyncedWeb3AuthConnection.value = newConnection;
127
- const connector = await setupConnector(newEth, wagmiConfig);
128
- if (!connector) {
129
- throw new Error("Failed to setup connector");
130
- }
131
- await connectWeb3AuthWithWagmi(connector, wagmiConfig);
132
- reconnect();
133
137
  }
134
- } else if (!newIsConnected) {
135
- lastSyncedWeb3AuthConnection.value = null;
138
+ const connector = await setupConnector(newEth, wagmiConfig);
139
+ if (!connector) {
140
+ throw new Error("Failed to setup connector");
141
+ }
142
+ await connectWeb3AuthWithWagmi(connector, wagmiConfig);
143
+ lastSyncedProvider.value = newEth;
144
+ lastSyncedConnectorName.value = newConnection.connectorName;
145
+ reconnect();
146
+ } else {
147
+ lastSyncedProvider.value = null;
148
+ lastSyncedConnectorName.value = null;
136
149
  if (wagmiConfig.state.status === "connected") {
150
+ suppressWagmiDisconnect.value = true;
137
151
  await disconnectWeb3AuthFromWagmi(wagmiConfig);
152
+ } else if (getWeb3authConnector(wagmiConfig)) {
153
+ resetConnectorState(wagmiConfig);
138
154
  }
139
155
  }
140
156
  }, {
@@ -149,7 +149,7 @@ const getWalletServicesAnalyticsProperties = walletServicesConfig => {
149
149
  ws_default_portfolio: walletServicesConfig === null || walletServicesConfig === void 0 || (_walletServicesConfig10 = walletServicesConfig.whiteLabel) === null || _walletServicesConfig10 === void 0 ? void 0 : _walletServicesConfig10.defaultPortfolio
150
150
  };
151
151
  };
152
- const sdkVersion = "11.0.0-beta.1";
152
+ const sdkVersion = "11.0.0-beta.2";
153
153
  const getErrorAnalyticsProperties = error => {
154
154
  try {
155
155
  const code = error instanceof Web3AuthError ? error.code : error === null || error === void 0 ? void 0 : error.code;
@@ -6,6 +6,7 @@ import { SecurePubSub } from '@toruslabs/secure-pub-sub';
6
6
  import { BUILD_ENV, UX_MODE, Auth, SDK_MODE, SUPPORTED_KEY_CURVES, generateRecordId, version, createHandler, PopupHandler, getUserId } from '@web3auth/auth';
7
7
  import { WS_EMBED_LOGIN_MODE } from '@web3auth/ws-embed';
8
8
  import deepmerge from 'deepmerge';
9
+ import { numberToHex } from 'viem';
9
10
  import { generateNonce, parseToken } from '../utils.js';
10
11
  import { AuthSolanaWallet } from './authSolanaWallet.js';
11
12
  import { WalletLoginError, WalletInitializationError, Web3AuthError, AccountLinkingError } from '../../base/errors/index.js';
@@ -13,13 +14,22 @@ import { WALLET_CONNECTORS } from '../../base/wallet/index.js';
13
14
  import { BaseConnector } from '../../base/connector/baseConnector.js';
14
15
  import { CONNECTOR_NAMESPACES } from '../../base/chain/IChainInterface.js';
15
16
  import { CONNECTOR_CATEGORY, CONNECTOR_STATUS, CONNECTOR_EVENTS } from '../../base/connector/constants.js';
16
- import { Analytics, ANALYTICS_EVENTS } from '../../base/analytics.js';
17
- import { log } from '../../base/loglevel.js';
18
- import { citadelServerUrl, getCaipChainId, getErrorAnalyticsProperties, parseChainNamespaceFromCitadelResponse } from '../../base/utils.js';
19
17
  import { CONNECTED_STATUSES } from '../../base/connector/connectorStatus.js';
18
+ import { log } from '../../base/loglevel.js';
19
+ import { Analytics, ANALYTICS_EVENTS } from '../../base/analytics.js';
20
+ import { citadelServerUrl, getErrorAnalyticsProperties, parseChainNamespaceFromCitadelResponse } from '../../base/utils.js';
20
21
  import { makeAccountLinkingRequest, makeAccountUnlinkingRequest } from '../../account-linking/rest.js';
21
22
  import { CHAIN_NAMESPACES, cloneDeep } from '@toruslabs/base-controllers';
22
23
 
24
+ // Auth connections that have been deprecated and are no longer supported by the SDK.
25
+ // Passing any of these as `authConnection` results in a hard error so consumers
26
+ // migrate off the removed providers instead of silently continuing.
27
+ const DEPRECATED_AUTH_CONNECTIONS = new Set(["farcaster"]);
28
+ function assertAuthConnectionSupported(authConnection) {
29
+ if (DEPRECATED_AUTH_CONNECTIONS.has(authConnection)) {
30
+ throw WalletInitializationError.invalidParams(`Auth connection "${authConnection}" has been deprecated and is no longer supported by the Web3Auth SDKs. ` + `Please use a different authConnection value.`);
31
+ }
32
+ }
23
33
  class AuthConnector extends BaseConnector {
24
34
  constructor(params) {
25
35
  super(params);
@@ -37,8 +47,22 @@ class AuthConnector extends BaseConnector {
37
47
  _defineProperty(this, "wsEmbedInstance", null);
38
48
  _defineProperty(this, "authConnectionConfig", []);
39
49
  _defineProperty(this, "wsEmbedInstancePromise", null);
50
+ _defineProperty(this, "wsEmbedProviderListenerTarget", null);
40
51
  _defineProperty(this, "_solanaWallet", null);
41
52
  _defineProperty(this, "analytics", void 0);
53
+ _defineProperty(this, "handleWsEmbedAccountsChanged", accounts => {
54
+ if (accounts.length === 0) {
55
+ if (!CONNECTED_STATUSES.includes(this.status)) {
56
+ return;
57
+ }
58
+ log.info("No accounts found in the wallet, disconnecting");
59
+ void this.disconnect({
60
+ cleanup: true
61
+ }).catch(error => {
62
+ log.error("Failed to disconnect auth connector after wallet accounts changed", error);
63
+ });
64
+ }
65
+ });
42
66
  this.authOptions = params.connectorSettings;
43
67
  this.loginSettings = params.loginSettings || {
44
68
  authConnection: ""
@@ -51,10 +75,8 @@ class AuthConnector extends BaseConnector {
51
75
  }
52
76
  get provider() {
53
77
  if (this.status !== CONNECTOR_STATUS.NOT_READY) {
54
- var _this$wsEmbedInstance;
55
- if ((_this$wsEmbedInstance = this.wsEmbedInstance) !== null && _this$wsEmbedInstance !== void 0 && _this$wsEmbedInstance.provider) {
56
- return this.wsEmbedInstance.provider;
57
- } else if (this.privateKeyProvider) return this.privateKeyProvider;
78
+ const wsEmbedProvider = this.getWsEmbedProvider();
79
+ return wsEmbedProvider || this.privateKeyProvider;
58
80
  }
59
81
  return null;
60
82
  }
@@ -123,6 +145,7 @@ class AuthConnector extends BaseConnector {
123
145
  buildEnv: this.authOptions.buildEnv,
124
146
  whiteLabel: _objectSpread(_objectSpread({}, this.authOptions.whiteLabel), this.wsSettings.whiteLabel)
125
147
  })).then(() => {
148
+ this.bindWsEmbedProviderEvents();
126
149
  this.wsEmbedInstancePromise = null;
127
150
  return;
128
151
  });
@@ -172,6 +195,7 @@ class AuthConnector extends BaseConnector {
172
195
  }
173
196
  }
174
197
  async connect(params) {
198
+ assertAuthConnectionSupported(params === null || params === void 0 ? void 0 : params.authConnection);
175
199
  super.checkConnectionRequirements();
176
200
  this.status = CONNECTOR_STATUS.CONNECTING;
177
201
  this.emit(CONNECTOR_EVENTS.CONNECTING, _objectSpread(_objectSpread({}, params), {}, {
@@ -201,6 +225,7 @@ class AuthConnector extends BaseConnector {
201
225
  async enableMFA(params = {
202
226
  authConnection: ""
203
227
  }) {
228
+ assertAuthConnectionSupported(params === null || params === void 0 ? void 0 : params.authConnection);
204
229
  if (!this.connected) throw WalletLoginError.notConnectedError("Not connected with wallet");
205
230
  if (!this.authInstance) throw WalletInitializationError.notReady("authInstance is not ready");
206
231
  try {
@@ -218,6 +243,7 @@ class AuthConnector extends BaseConnector {
218
243
  async manageMFA(params = {
219
244
  authConnection: ""
220
245
  }) {
246
+ assertAuthConnectionSupported(params === null || params === void 0 ? void 0 : params.authConnection);
221
247
  if (!this.connected) throw WalletLoginError.notConnectedError("Not connected with wallet");
222
248
  if (!this.authInstance) throw WalletInitializationError.notReady("authInstance is not ready");
223
249
  try {
@@ -249,6 +275,7 @@ class AuthConnector extends BaseConnector {
249
275
  }
250
276
  this.rehydrated = false;
251
277
  this._solanaWallet = null;
278
+ this.unbindWsEmbedProviderEvents();
252
279
  this.emit(CONNECTOR_EVENTS.DISCONNECTED, {
253
280
  connector: WALLET_CONNECTORS.AUTH
254
281
  });
@@ -310,13 +337,15 @@ class AuthConnector extends BaseConnector {
310
337
  const newChainConfig = this.coreOptions.chains.find(c => c.chainId === newChainId);
311
338
  if (!newChainConfig) throw WalletInitializationError.invalidParams("Chain config is not available");
312
339
  if (newChainConfig.chainNamespace === CHAIN_NAMESPACES.SOLANA || newChainConfig.chainNamespace === CHAIN_NAMESPACES.EIP155) {
313
- var _this$wsEmbedInstance2;
314
- if (!((_this$wsEmbedInstance2 = this.wsEmbedInstance) !== null && _this$wsEmbedInstance2 !== void 0 && _this$wsEmbedInstance2.provider)) throw WalletInitializationError.notReady("Wallet embed is not ready");
315
- const fullChainId = getCaipChainId(newChainConfig);
340
+ var _this$wsEmbedInstance;
341
+ if (!((_this$wsEmbedInstance = this.wsEmbedInstance) !== null && _this$wsEmbedInstance !== void 0 && _this$wsEmbedInstance.provider)) throw WalletInitializationError.notReady("Wallet embed is not ready");
342
+ const chainIdNum = parseInt(newChainConfig.chainId, 16);
343
+ // WsEmbed expects the chainId in hex format
344
+ const chainIdHex = numberToHex(chainIdNum);
316
345
  await this.wsEmbedInstance.provider.request({
317
346
  method: "wallet_switchChain",
318
347
  params: {
319
- chainId: fullChainId
348
+ chainId: chainIdHex
320
349
  }
321
350
  });
322
351
  } else {
@@ -330,6 +359,8 @@ class AuthConnector extends BaseConnector {
330
359
  if (this.wsEmbedInstance) {
331
360
  this.wsEmbedInstance.clearInit();
332
361
  }
362
+ this._solanaWallet = null;
363
+ this.unbindWsEmbedProviderEvents();
333
364
  }
334
365
  getOAuthProviderConfig(params) {
335
366
  const {
@@ -416,11 +447,11 @@ class AuthConnector extends BaseConnector {
416
447
  const {
417
448
  connectorName,
418
449
  chainId,
419
- walletConnector
450
+ connectorToLink
420
451
  } = params;
421
452
  try {
422
- if (!walletConnector.connected) {
423
- const connection = await walletConnector.connect({
453
+ if (!connectorToLink.connected) {
454
+ const connection = await connectorToLink.connect({
424
455
  chainId,
425
456
  isAccountLinking: true
426
457
  });
@@ -445,7 +476,7 @@ class AuthConnector extends BaseConnector {
445
476
  accessToken,
446
477
  idToken
447
478
  } = await this.getPrimaryAuthSession(params.authSessionTokens);
448
- const walletProof = await this.createWalletLinkingProof(params.walletConnector);
479
+ const walletProof = await this.createWalletLinkingProof(params.connectorToLink);
449
480
  const authServerUrl = citadelServerUrl(this.coreOptions.authBuildEnv);
450
481
  const result = await makeAccountLinkingRequest(authServerUrl, accessToken, {
451
482
  idToken,
@@ -466,9 +497,11 @@ class AuthConnector extends BaseConnector {
466
497
 
467
498
  // disconnect the wallet connector to avoid any leftover state
468
499
  try {
469
- await walletConnector.disconnect({
470
- cleanup: true
471
- });
500
+ if (connectorToLink.connected) {
501
+ await connectorToLink.disconnect({
502
+ cleanup: true
503
+ });
504
+ }
472
505
  } catch (disconnectError) {
473
506
  log.debug("Failed to disconnect wallet connector after linking failure", disconnectError);
474
507
  }
@@ -690,9 +723,35 @@ class AuthConnector extends BaseConnector {
690
723
  }
691
724
  return accounts[0];
692
725
  }
726
+ getWsEmbedProvider() {
727
+ var _ref, _this$wsEmbedInstance2;
728
+ return (_ref = (_this$wsEmbedInstance2 = this.wsEmbedInstance) === null || _this$wsEmbedInstance2 === void 0 ? void 0 : _this$wsEmbedInstance2.provider) !== null && _ref !== void 0 ? _ref : null;
729
+ }
730
+ bindWsEmbedProviderEvents() {
731
+ const rawProvider = this.getWsEmbedProvider();
732
+ if (this.wsEmbedProviderListenerTarget === rawProvider) {
733
+ return;
734
+ }
735
+ this.unbindWsEmbedProviderEvents();
736
+ if (!rawProvider) {
737
+ return;
738
+ }
739
+ rawProvider.on("accountsChanged", this.handleWsEmbedAccountsChanged);
740
+ this.wsEmbedProviderListenerTarget = rawProvider;
741
+ }
742
+ unbindWsEmbedProviderEvents() {
743
+ if (!this.wsEmbedProviderListenerTarget) {
744
+ return;
745
+ }
746
+ this.wsEmbedProviderListenerTarget.removeListener("accountsChanged", this.handleWsEmbedAccountsChanged);
747
+ this.wsEmbedProviderListenerTarget = null;
748
+ }
693
749
  setupSolanaWallet() {
694
750
  const solanaChains = this.coreOptions.chains.filter(c => c.chainNamespace === CHAIN_NAMESPACES.SOLANA);
695
751
  if (solanaChains.length === 0 || !this.provider) return;
752
+ if (this._solanaWallet instanceof AuthSolanaWallet) {
753
+ return;
754
+ }
696
755
  this._solanaWallet = new AuthSolanaWallet(this.provider, solanaChains);
697
756
  }
698
757
  _getFinalPrivKey() {
@@ -755,13 +814,13 @@ class AuthConnector extends BaseConnector {
755
814
  } = this.authInstance || {};
756
815
  if (sessionId) {
757
816
  this.wsEmbedInstance.setAccessTokenProvider(this.accessTokenProvider.bind(this));
817
+ this.bindWsEmbedProviderEvents();
758
818
  const isLoggedIn = await this.wsEmbedInstance.connectWithSession({
759
819
  sessionId,
760
820
  sessionNamespace,
761
821
  idToken: await this.getIdToken()
762
822
  });
763
823
  if (isLoggedIn) {
764
- var _this$wsEmbedInstance3;
765
824
  this.setupSolanaWallet();
766
825
  // if getAuthTokenInfo is true, then get auth token info
767
826
  // No need to get auth token info for auth connector as it is already handled
@@ -775,12 +834,6 @@ class AuthConnector extends BaseConnector {
775
834
  if (params.getAuthTokenInfo) {
776
835
  await this.getAuthTokenInfo();
777
836
  }
778
- // handle disconnect from ws embed
779
- (_this$wsEmbedInstance3 = this.wsEmbedInstance) === null || _this$wsEmbedInstance3 === void 0 || _this$wsEmbedInstance3.provider.on("accountsChanged", (accounts = []) => {
780
- if (accounts.length === 0 && CONNECTED_STATUSES.includes(this.status)) this.disconnect({
781
- cleanup: false
782
- });
783
- });
784
837
  }
785
838
  }
786
839
  } else {
@@ -882,9 +935,7 @@ class AuthConnector extends BaseConnector {
882
935
  }).catch(error => {
883
936
  // swallow the error, dont need to throw.
884
937
  log.error("Error during login with social", error);
885
- this.auditOAuditProgress(loginParams, "failed").catch(error => {
886
- log.error("Error reporting `oauthFailed` audit progress", error);
887
- });
938
+ this.reportFailedOauthAudit(loginParams);
888
939
  });
889
940
  verifierWindow.once("close", () => {
890
941
  if (!isClosedWindow) {
@@ -894,9 +945,7 @@ class AuthConnector extends BaseConnector {
894
945
  }
895
946
  });
896
947
  this.authInstance.postLoginInitiatedMessage(loginParams, nonce).then(resolve).catch(error => {
897
- this.auditOAuditProgress(loginParams, "failed").catch(error => {
898
- log.error("Error reporting `oauthFailed` audit progress", error);
899
- });
948
+ this.reportFailedOauthAudit(loginParams);
900
949
  if (error instanceof Web3AuthError) {
901
950
  throw error;
902
951
  }
@@ -1012,6 +1061,11 @@ class AuthConnector extends BaseConnector {
1012
1061
  }
1013
1062
  await put(auditServerUrl, auditPayload);
1014
1063
  }
1064
+ reportFailedOauthAudit(loginParams) {
1065
+ void this.auditOAuditProgress(loginParams, "failed").catch(error => {
1066
+ log.error("Error reporting `oauthFailed` audit progress", error);
1067
+ });
1068
+ }
1015
1069
  }
1016
1070
  const authConnector = params => {
1017
1071
  return ({
@@ -925,7 +925,6 @@ class Web3AuthNoModal extends SafeEventEmitter {
925
925
  }));
926
926
  this.setActiveWalletConnectorKey();
927
927
  this.connectionReconnected = data.reconnected;
928
- const connectedChainId = ethereumProvider === null || ethereumProvider === void 0 ? void 0 : ethereumProvider.chainId;
929
928
 
930
929
  // when ssr is enabled, we need to get the idToken from the connector.
931
930
  if (this.coreOptions.ssr) {
@@ -950,14 +949,15 @@ class Web3AuthNoModal extends SafeEventEmitter {
950
949
  // The following block only hits during rehydration
951
950
 
952
951
  const {
953
- activeAccount
952
+ activeAccount,
953
+ currentChainId
954
954
  } = this.state;
955
955
  // if the active account is not the primary account, i.e. not `null`, create an isolated connector and connect to the chain
956
956
  if (activeAccount && !activeAccount.isPrimary && activeAccount.connector !== WALLET_CONNECTORS.AUTH) {
957
957
  var _ref3, _walletConnector$prov, _linkedAccountConnect, _ref4, _walletConnector$sola, _linkedAccountConnect2;
958
958
  const accountLinkingConnector = isAuthConnector(connector) ? connector : this.getConnector(WALLET_CONNECTORS.AUTH);
959
959
  assertAuthConnector(accountLinkingConnector, "Account switching requires the AUTH connector to be available.");
960
- const targetChainId = accountLinkingConnector.getChainIdForLinkedAccount(activeAccount, connectedChainId);
960
+ const targetChainId = accountLinkingConnector.getChainIdForLinkedAccount(activeAccount, currentChainId);
961
961
  const walletConnector = await this.createIsolatedWalletConnector(activeAccount.connector, targetChainId);
962
962
  let linkedAccountConnection = null;
963
963
  if (!this.hasUsableConnectedSwitchConnector(walletConnector)) {
@@ -989,23 +989,36 @@ class Web3AuthNoModal extends SafeEventEmitter {
989
989
  });
990
990
  this.setConnectedWalletConnectorState(primaryConnectedWalletState);
991
991
  await this.setState({
992
- primaryConnectorName: data.connectorName,
993
- currentChainId: connectedChainId
992
+ primaryConnectorName: data.connectorName
994
993
  });
995
994
  this.cacheWallet(data.connectorName);
996
995
  const isConnectAndSign = this.coreOptions.initialAuthenticationMode === CONNECTOR_INITIAL_AUTHENTICATION_MODE.CONNECT_AND_SIGN;
997
- if (this.consentRequired && !isConnectAndSign && !this.state.hasUserConsent) {
996
+ const pendingUserConsent = this.consentRequired && !this.state.hasUserConsent;
997
+ if (pendingUserConsent && !isConnectAndSign) {
998
998
  this.status = CONNECTOR_STATUS.CONSENT_REQUIRING;
999
999
  this.emit(CONNECTOR_EVENTS.CONSENT_REQUIRING);
1000
1000
  log.debug("consent_requiring", this.status, this.primaryConnectorName);
1001
1001
  } else {
1002
- this.status = CONNECTOR_STATUS.CONNECTED;
1002
+ // In CONNECT_AND_SIGN mode the AUTHORIZED handler can run before this point (e.g. when `ssr=true`
1003
+ // this handler `await`s `connector.getAuthTokenInfo()` which fires AUTHORIZED mid-execution).
1004
+ // Don't downgrade an already-advanced status (CONSENT_REQUIRING or AUTHORIZED) back to CONNECTED;
1005
+ // otherwise `acceptConsent` would throw "Cannot accept consent: not in consent_requiring state".
1006
+ if (this.status !== CONNECTOR_STATUS.CONSENT_REQUIRING && this.status !== CONNECTOR_STATUS.AUTHORIZED) {
1007
+ this.status = CONNECTOR_STATUS.CONNECTED;
1008
+ }
1003
1009
  log.debug("connected", this.status, this.primaryConnectorName);
1004
- this.connectToPlugins(_objectSpread(_objectSpread({}, data), {}, {
1005
- connector: data.connectorName
1006
- }));
1010
+ // Defer plugin connection until consent is accepted; otherwise plugins would start before the consent step completes.
1011
+ // `completeConsentAcceptance` connects the plugins once the user accepts the consent.
1012
+ if (!pendingUserConsent) {
1013
+ this.connectToPlugins(_objectSpread(_objectSpread({}, data), {}, {
1014
+ connector: data.connectorName
1015
+ }));
1016
+ }
1017
+ // `pendingUserConsent` signals listeners (LoginModal, React/Vue contexts) to skip processing this CONNECTED event,
1018
+ // so the upcoming AUTHORIZED -> CONSENT_REQUIRING transition is not overridden by a late CONNECTED handler in CONNECT_AND_SIGN mode.
1007
1019
  this.emit(CONNECTOR_EVENTS.CONNECTED, _objectSpread(_objectSpread({}, data), {}, {
1008
- loginMode: this.loginMode
1020
+ loginMode: this.loginMode,
1021
+ pendingUserConsent
1009
1022
  }));
1010
1023
  }
1011
1024
  });
@@ -1381,12 +1394,12 @@ class Web3AuthNoModal extends SafeEventEmitter {
1381
1394
  account
1382
1395
  });
1383
1396
  }
1384
- async linkAccountWithConnector(connectorName, chainId, walletConnector) {
1397
+ async linkAccountWithConnector(connectorName, chainId, connectorToLink) {
1385
1398
  const authConnector = this.getMainAuthConnector();
1386
1399
  const result = await authConnector.linkAccount({
1387
1400
  connectorName,
1388
1401
  chainId,
1389
- walletConnector,
1402
+ connectorToLink,
1390
1403
  authSessionTokens: {
1391
1404
  accessToken: this.accessToken,
1392
1405
  idToken: this.idToken
@@ -1395,7 +1408,7 @@ class Web3AuthNoModal extends SafeEventEmitter {
1395
1408
  await this.setState({
1396
1409
  idToken: result.idToken
1397
1410
  });
1398
- await this.cacheConnectedLinkedWalletConnector(authConnector, walletConnector);
1411
+ await this.cacheConnectedLinkedWalletConnector(authConnector, connectorToLink);
1399
1412
  return result;
1400
1413
  }
1401
1414
  getMainAuthConnector() {
@@ -1575,7 +1588,10 @@ class Web3AuthNoModal extends SafeEventEmitter {
1575
1588
  });
1576
1589
  }
1577
1590
  async setCurrentChain(chainId) {
1578
- if (chainId === this.currentChainId) return;
1591
+ const {
1592
+ currentChainId
1593
+ } = this.state;
1594
+ if (chainId === currentChainId) return;
1579
1595
  const newChain = this.coreOptions.chains.find(chain => chain.chainId === chainId);
1580
1596
  if (!newChain) throw WalletInitializationError.invalidParams(`Invalid chainId: ${chainId}`);
1581
1597
  await this.setState({
@@ -148,6 +148,13 @@ function useWeb3AuthInnerContextValue({
148
148
  const mfaEnabledListener = nextIsMFAEnabled => {
149
149
  if (typeof nextIsMFAEnabled === "boolean") setIsMFAEnabled(nextIsMFAEnabled);
150
150
  };
151
+ const connectionUpdatedListener = () => {
152
+ var _web3Auth$currentChai9, _web3Auth$currentChai0;
153
+ setStatus(web3Auth.status);
154
+ setConnection(web3Auth.connection);
155
+ setChainId(web3Auth.currentChainId);
156
+ setChainNamespace((_web3Auth$currentChai9 = (_web3Auth$currentChai0 = web3Auth.currentChain) === null || _web3Auth$currentChai0 === void 0 ? void 0 : _web3Auth$currentChai0.chainNamespace) !== null && _web3Auth$currentChai9 !== void 0 ? _web3Auth$currentChai9 : null);
157
+ };
151
158
  if (web3Auth) {
152
159
  web3Auth.on(CONNECTOR_EVENTS.NOT_READY, notReadyListener);
153
160
  web3Auth.on(CONNECTOR_EVENTS.READY, readyListener);
@@ -158,6 +165,7 @@ function useWeb3AuthInnerContextValue({
158
165
  web3Auth.on(CONNECTOR_EVENTS.ERRORED, errorListener);
159
166
  web3Auth.on(CONNECTOR_EVENTS.REHYDRATION_ERROR, rehydrationErrorListener);
160
167
  web3Auth.on(CONNECTOR_EVENTS.MFA_ENABLED, mfaEnabledListener);
168
+ web3Auth.on(CONNECTOR_EVENTS.CONNECTION_UPDATED, connectionUpdatedListener);
161
169
  if (web3Auth.loginMode === LOGIN_MODE.MODAL) {
162
170
  web3Auth.on(CONNECTOR_EVENTS.CONSENT_ACCEPTED, consentAcceptedListener);
163
171
  }
@@ -173,6 +181,7 @@ function useWeb3AuthInnerContextValue({
173
181
  web3Auth.removeListener(CONNECTOR_EVENTS.REHYDRATION_ERROR, rehydrationErrorListener);
174
182
  web3Auth.removeListener(CONNECTOR_EVENTS.MFA_ENABLED, mfaEnabledListener);
175
183
  web3Auth.removeListener(CONNECTOR_EVENTS.AUTHORIZED, authorizedListener);
184
+ web3Auth.removeListener(CONNECTOR_EVENTS.CONNECTION_UPDATED, connectionUpdatedListener);
176
185
  if (web3Auth.loginMode === LOGIN_MODE.MODAL) {
177
186
  web3Auth.removeListener(CONNECTOR_EVENTS.CONSENT_ACCEPTED, consentAcceptedListener);
178
187
  }
@@ -52,6 +52,7 @@ function useFrameworkKitSolanaClient() {
52
52
  isInitialized
53
53
  } = useWeb3Auth();
54
54
  const {
55
+ chainId,
55
56
  chainNamespace
56
57
  } = useChain();
57
58
  const ref = useRef(null);
@@ -102,7 +103,10 @@ function useFrameworkKitSolanaClient() {
102
103
  }
103
104
 
104
105
  // only reconnect for the primary connector
105
- if (conn.connectorName !== (web3Auth === null || web3Auth === void 0 ? void 0 : web3Auth.primaryConnectorName)) return;
106
+ if (conn.connectorName !== (web3Auth === null || web3Auth === void 0 ? void 0 : web3Auth.primaryConnectorName)) {
107
+ adopt(makePlaceholder(rpc));
108
+ return;
109
+ }
106
110
  try {
107
111
  const solanaWalletId = "wallet-standard:" + conn.connectorName;
108
112
  const connector = createWalletStandardConnector(solanaWallet, {
@@ -134,7 +138,7 @@ function useFrameworkKitSolanaClient() {
134
138
  return () => {
135
139
  stale = true;
136
140
  };
137
- }, [isConnected, connection === null || connection === void 0 ? void 0 : connection.solanaWallet, chainNamespace, web3Auth, isInitialized, connection === null || connection === void 0 ? void 0 : connection.connectorName]);
141
+ }, [isConnected, connection === null || connection === void 0 ? void 0 : connection.solanaWallet, chainId, chainNamespace, web3Auth, isInitialized, connection === null || connection === void 0 ? void 0 : connection.connectorName]);
138
142
  return client;
139
143
  }
140
144
  function SolanaProvider(_ref) {