@web3auth/no-modal 11.0.1 → 11.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -107,6 +107,13 @@ const ANALYTICS_EVENTS = {
107
107
  MFA_ENABLEMENT_FAILED: "MFA Enablement Failed",
108
108
  MFA_MANAGEMENT_SELECTED: "MFA Management Selected",
109
109
  MFA_MANAGEMENT_FAILED: "MFA Management Failed",
110
+ // Consent Flow
111
+ USER_CONSENT_STARTED: "User Consent Started",
112
+ USER_CONSENT_ACCEPTED: "User Consent Accepted",
113
+ USER_CONSENT_DECLINED: "User Consent Declined",
114
+ USER_CONSENT_ERRORED: "User Consent Errored",
115
+ TERMS_OF_SERVICE_CLICKED: "Terms of Service Clicked",
116
+ PRIVACY_POLICY_CLICKED: "Privacy Policy Clicked",
110
117
  // Login Modal
111
118
  LOGIN_MODAL_OPENED: "Login Modal Opened",
112
119
  LOGIN_MODAL_CLOSED: "Login Modal Closed",
@@ -145,7 +145,7 @@ const getWalletServicesAnalyticsProperties = walletServicesConfig => {
145
145
  ws_default_portfolio: walletServicesConfig === null || walletServicesConfig === void 0 || (_walletServicesConfig10 = walletServicesConfig.whiteLabel) === null || _walletServicesConfig10 === void 0 ? void 0 : _walletServicesConfig10.defaultPortfolio
146
146
  };
147
147
  };
148
- const sdkVersion = "11.0.1";
148
+ const sdkVersion = "11.1.0";
149
149
  const getErrorAnalyticsProperties = error => {
150
150
  try {
151
151
  const code = error instanceof index.Web3AuthError ? error.code : error === null || error === void 0 ? void 0 : error.code;
@@ -372,11 +372,9 @@ class AuthConnector extends baseConnector.BaseConnector {
372
372
  }
373
373
  }
374
374
  async cleanup() {
375
- if (!this.authInstance) throw index.WalletInitializationError.notReady("authInstance is not ready");
376
- await this.authInstance.cleanup();
377
- if (this.wsEmbedInstance) {
378
- this.wsEmbedInstance.clearInit();
379
- }
375
+ var _this$authInstance, _this$wsEmbedInstance2;
376
+ await ((_this$authInstance = this.authInstance) === null || _this$authInstance === void 0 ? void 0 : _this$authInstance.cleanup());
377
+ (_this$wsEmbedInstance2 = this.wsEmbedInstance) === null || _this$wsEmbedInstance2 === void 0 || _this$wsEmbedInstance2.clearInit();
380
378
  this._solanaWallet = null;
381
379
  this.unbindWsEmbedProviderEvents();
382
380
  }
@@ -492,7 +490,7 @@ class AuthConnector extends baseConnector.BaseConnector {
492
490
  accessToken,
493
491
  idToken
494
492
  } = await this.getPrimaryAuthSession(params.authSessionTokens);
495
- const walletProof = await this.createWalletLinkingProof(params.connectorToLink);
493
+ const walletProof = await this.createWalletLinkingProof(params.connectorToLink, chainId);
496
494
  const authServerUrl = utils.citadelServerUrl(this.coreOptions.authBuildEnv);
497
495
  const result = await rest.makeAccountLinkingRequest(authServerUrl, accessToken, {
498
496
  idToken,
@@ -684,7 +682,7 @@ class AuthConnector extends baseConnector.BaseConnector {
684
682
  }
685
683
  throw errors.AccountLinkingError.requestFailed(`Unsupported chain namespace "${matchedAccount.chainNamespace}" for address "${address}".`);
686
684
  }
687
- async createWalletLinkingProof(connector) {
685
+ async createWalletLinkingProof(connector, chainId) {
688
686
  // Notify listeners that the linking wallet is about to be asked for a signature so the UI
689
687
  // (e.g. modal) can switch from a "connecting" loader to an "authorizing" prompt while the
690
688
  // user reviews the signature request inside their wallet. Emitted on the isolated wallet
@@ -692,11 +690,13 @@ class AuthConnector extends baseConnector.BaseConnector {
692
690
  connector.emit(constants.CONNECTOR_EVENTS.AUTHORIZING, {
693
691
  connector: connector.name
694
692
  });
693
+ // Reuse the caller's target chain so multichain wallets generate the linking
694
+ // proof for the same namespace they were connected for.
695
695
  const {
696
696
  challenge,
697
697
  signature,
698
698
  chainNamespace
699
- } = await connector.generateChallengeAndSign();
699
+ } = await connector.generateChallengeAndSign(undefined, undefined, chainId);
700
700
  const address = await this.getLinkingWalletAddress(connector, chainNamespace);
701
701
  if (chainNamespace === baseControllers.CHAIN_NAMESPACES.EIP155) {
702
702
  return {
@@ -739,8 +739,8 @@ class AuthConnector extends baseConnector.BaseConnector {
739
739
  return accounts[0];
740
740
  }
741
741
  getWsEmbedProvider() {
742
- var _this$wsEmbedInstance2, _this$wsEmbedInstance3;
743
- return (_this$wsEmbedInstance2 = (_this$wsEmbedInstance3 = this.wsEmbedInstance) === null || _this$wsEmbedInstance3 === void 0 ? void 0 : _this$wsEmbedInstance3.provider) !== null && _this$wsEmbedInstance2 !== void 0 ? _this$wsEmbedInstance2 : null;
742
+ var _this$wsEmbedInstance3, _this$wsEmbedInstance4;
743
+ return (_this$wsEmbedInstance3 = (_this$wsEmbedInstance4 = this.wsEmbedInstance) === null || _this$wsEmbedInstance4 === void 0 ? void 0 : _this$wsEmbedInstance4.provider) !== null && _this$wsEmbedInstance3 !== void 0 ? _this$wsEmbedInstance3 : null;
744
744
  }
745
745
  bindWsEmbedProviderEvents() {
746
746
  const rawProvider = this.getWsEmbedProvider();
@@ -785,7 +785,7 @@ class AuthConnector extends baseConnector.BaseConnector {
785
785
  return finalPrivKey;
786
786
  }
787
787
  async connectWithProvider(params) {
788
- var _this$authInstance, _params$extraLoginOpt, _this$authInstance2, _this$authInstance3;
788
+ var _this$authInstance2, _params$extraLoginOpt, _this$authInstance3, _this$authInstance4;
789
789
  if (!this.authInstance) throw index.WalletInitializationError.notReady("authInstance is not ready");
790
790
  const chainConfig = this.coreOptions.chains.find(x => x.chainId === params.chainId);
791
791
  if (!chainConfig) throw index.WalletLoginError.connectionError("Chain config is not available");
@@ -793,7 +793,7 @@ class AuthConnector extends baseConnector.BaseConnector {
793
793
  chainNamespace
794
794
  } = chainConfig;
795
795
  // if not logged in then login
796
- const keyAvailable = chainNamespace === baseControllers.CHAIN_NAMESPACES.EIP155 || chainNamespace === baseControllers.CHAIN_NAMESPACES.SOLANA ? (_this$authInstance = this.authInstance) === null || _this$authInstance === void 0 ? void 0 : _this$authInstance.sessionId : this._getFinalPrivKey();
796
+ const keyAvailable = chainNamespace === baseControllers.CHAIN_NAMESPACES.EIP155 || chainNamespace === baseControllers.CHAIN_NAMESPACES.SOLANA ? (_this$authInstance2 = this.authInstance) === null || _this$authInstance2 === void 0 ? void 0 : _this$authInstance2.sessionId : this._getFinalPrivKey();
797
797
  if (params.idToken) params.extraLoginOptions = _objectSpread(_objectSpread({}, params.extraLoginOptions), {}, {
798
798
  id_token: params.idToken
799
799
  });
@@ -809,7 +809,7 @@ class AuthConnector extends baseConnector.BaseConnector {
809
809
  }
810
810
  }
811
811
  // if useSFAKey is true and privKey is available but coreKitKey is not available, throw an error
812
- if (this.coreOptions.useSFAKey && (_this$authInstance2 = this.authInstance) !== null && _this$authInstance2 !== void 0 && _this$authInstance2.privKey && !((_this$authInstance3 = this.authInstance) !== null && _this$authInstance3 !== void 0 && _this$authInstance3.coreKitKey)) {
812
+ if (this.coreOptions.useSFAKey && (_this$authInstance3 = this.authInstance) !== null && _this$authInstance3 !== void 0 && _this$authInstance3.privKey && !((_this$authInstance4 = this.authInstance) !== null && _this$authInstance4 !== void 0 && _this$authInstance4.coreKitKey)) {
813
813
  // If the user is already logged in, logout and throw an error
814
814
  if (this.authInstance.sessionId) {
815
815
  await this.authInstance.logout();
@@ -140,7 +140,12 @@ class MetaMaskConnector extends baseConnector.BaseConnector {
140
140
  this.disconnect();
141
141
  }
142
142
  },
143
- chainChanged: _chainId => {},
143
+ chainChanged: _chainId => {
144
+ // Keep Web3Auth state aligned with the wallet's actual EVM chain after connect/switch.
145
+ this.updateConnectorData({
146
+ chainId: _chainId
147
+ });
148
+ },
144
149
  connect: _result => {},
145
150
  disconnect: () => {
146
151
  if (this.connected) {
@@ -196,7 +201,7 @@ class MetaMaskConnector extends baseConnector.BaseConnector {
196
201
  ethereumProvider: this.evmProvider,
197
202
  solanaWallet: this.solanaProvider
198
203
  });
199
- if (options.getAuthTokenInfo) await this.getAuthTokenInfo();
204
+ if (options.getAuthTokenInfo) await this.getAuthTokenInfo(options.chainId);
200
205
  } else if (coreStatus === "connected" || coreStatus === "loaded" || coreStatus === "disconnected" || coreStatus === "pending") {
201
206
  this.status = constants.CONNECTOR_STATUS.READY;
202
207
  this.emit(constants.CONNECTOR_EVENTS.READY, index.WALLET_CONNECTORS.METAMASK);
@@ -259,13 +264,9 @@ class MetaMaskConnector extends baseConnector.BaseConnector {
259
264
  await evmConnectedPromise;
260
265
  }
261
266
  }
262
- // // Switch EVM chain if not connected to the right one (Solana chains are handled by the wallet-standard provider)
263
- // if (chainConfig.chainNamespace === CHAIN_NAMESPACES.EIP155) {
264
- // const currentChainId = this.evmClient!.getChainId();
265
- // if (currentChainId !== chainId) {
266
- // await this.switchChain(chainConfig, true);
267
- // }
268
- // }
267
+ // sync the chain state after connect
268
+ // metamask might not be connected to the requested chain, so we need to sync the chain state to/from Web3Auth state after connect.
269
+ await this.syncChainStateAfterConnect(chainConfig);
269
270
  // check if connected
270
271
  if (this.multichainClient.status !== "connected") {
271
272
  throw index$1.WalletLoginError.notConnectedError("Failed to connect with MetaMask wallet");
@@ -286,7 +287,7 @@ class MetaMaskConnector extends baseConnector.BaseConnector {
286
287
  solanaWallet: this.solanaProvider
287
288
  });
288
289
  if (getAuthTokenInfo) {
289
- await this.getAuthTokenInfo();
290
+ await this.getAuthTokenInfo(chainId);
290
291
  }
291
292
  return {
292
293
  ethereumProvider: this.evmProvider,
@@ -336,13 +337,11 @@ class MetaMaskConnector extends baseConnector.BaseConnector {
336
337
  connector: index.WALLET_CONNECTORS.METAMASK
337
338
  });
338
339
  }
339
- async getAuthTokenInfo() {
340
- var _this$evmProvider2, _this$coreOptions$cha;
340
+ async getAuthTokenInfo(chainId) {
341
341
  if (!this.canAuthorize) throw index$1.WalletLoginError.notConnectedError();
342
- // Determine the active chain: prefer Solana if no EVM provider, otherwise use EVM provider's chain
343
- const evmChainId = ((_this$evmProvider2 = this.evmProvider) === null || _this$evmProvider2 === void 0 ? void 0 : _this$evmProvider2.chainId) || ((_this$coreOptions$cha = this.coreOptions.chains.find(x => x.chainNamespace === baseControllers.CHAIN_NAMESPACES.EIP155)) === null || _this$coreOptions$cha === void 0 ? void 0 : _this$coreOptions$cha.chainId);
344
- const isSolanaOnly = !this.evmProvider && !!this.solanaProvider;
345
- const activeChainConfig = isSolanaOnly ? this.coreOptions.chains.find(x => x.chainNamespace === baseControllers.CHAIN_NAMESPACES.SOLANA) : this.evmProvider ? this.coreOptions.chains.find(x => x.chainId === evmChainId) : undefined;
342
+ // In multichain sessions both providers can exist at the same time, so auth must
343
+ // follow the caller-selected chain instead of inferring from provider availability.
344
+ const activeChainConfig = this.resolveAuthChainConfig(chainId);
346
345
  if (!activeChainConfig) throw index$1.WalletLoginError.connectionError("Chain config is not available");
347
346
  const {
348
347
  chainNamespace
@@ -362,7 +361,7 @@ class MetaMaskConnector extends baseConnector.BaseConnector {
362
361
  const {
363
362
  challenge,
364
363
  signature
365
- } = await this.generateChallengeAndSign(authServer, accounts);
364
+ } = await this.generateChallengeAndSign(authServer, accounts, activeChainConfig.chainId);
366
365
  return this.verifyAndAuthorize({
367
366
  chainNamespace,
368
367
  signedMessage: signature,
@@ -403,11 +402,8 @@ class MetaMaskConnector extends baseConnector.BaseConnector {
403
402
  chainConfiguration
404
403
  });
405
404
  }
406
- async generateChallengeAndSign(authServerUrl, accounts) {
407
- var _this$evmProvider3, _this$coreOptions$cha2;
408
- const evmChainId = ((_this$evmProvider3 = this.evmProvider) === null || _this$evmProvider3 === void 0 ? void 0 : _this$evmProvider3.chainId) || ((_this$coreOptions$cha2 = this.coreOptions.chains.find(x => x.chainNamespace === baseControllers.CHAIN_NAMESPACES.EIP155)) === null || _this$coreOptions$cha2 === void 0 ? void 0 : _this$coreOptions$cha2.chainId);
409
- const isSolanaOnly = !this.evmProvider && !!this.solanaProvider;
410
- const activeChainConfig = isSolanaOnly ? this.coreOptions.chains.find(x => x.chainNamespace === baseControllers.CHAIN_NAMESPACES.SOLANA) : this.evmProvider ? this.coreOptions.chains.find(x => x.chainId === evmChainId) : undefined;
405
+ async generateChallengeAndSign(authServerUrl, accounts, chainId) {
406
+ const activeChainConfig = this.resolveAuthChainConfig(chainId);
411
407
  if (!activeChainConfig) throw index$1.WalletLoginError.connectionError("Chain config is not available");
412
408
  const {
413
409
  chainNamespace
@@ -462,6 +458,47 @@ class MetaMaskConnector extends baseConnector.BaseConnector {
462
458
  }
463
459
  await this.initializationPromise;
464
460
  }
461
+ async syncChainStateAfterConnect(chainConfig) {
462
+ var _this$evmProvider2;
463
+ // EVM connectors can switch chains, so align the wallet with the requested chain
464
+ // before Web3Auth persists the active chain in controller state.
465
+ if (chainConfig.chainNamespace === baseControllers.CHAIN_NAMESPACES.EIP155 && ((_this$evmProvider2 = this.evmProvider) === null || _this$evmProvider2 === void 0 ? void 0 : _this$evmProvider2.chainId) !== chainConfig.chainId) {
466
+ await this.switchChain({
467
+ chainId: chainConfig.chainId
468
+ }, true);
469
+ } else if (chainConfig.chainNamespace === baseControllers.CHAIN_NAMESPACES.SOLANA) {
470
+ // For solana case, metamask connect the first available scope in priority order: mainnet > devnet > testnet.
471
+ // So, if the user requested chain is different from the connected chain,
472
+ // we need to update the connector data with the connected chain id to keep the Web3Auth state aligned.
473
+ if ("scope" in this.solanaProvider && typeof this.solanaProvider.scope === "string") {
474
+ var _this$coreOptions$cha;
475
+ const connectedSolChain = this.solanaProvider.scope;
476
+ const connectedChainConfig = (_this$coreOptions$cha = this.coreOptions.chains) === null || _this$coreOptions$cha === void 0 ? void 0 : _this$coreOptions$cha.find(chain => {
477
+ return utils.getCaipChainId(chain) === connectedSolChain && chain.chainNamespace === baseControllers.CHAIN_NAMESPACES.SOLANA;
478
+ });
479
+ if (!connectedChainConfig) {
480
+ throw index$1.WalletLoginError.connectionError("Connected chain is not available in the chains config");
481
+ }
482
+ if (connectedChainConfig.chainId !== chainConfig.chainId) {
483
+ // since, switchChain is not supported for solana (in metamask connect),
484
+ // we will make use of the connector data to update the Web3Auth state.
485
+ this.updateConnectorData({
486
+ chainId: connectedChainConfig.chainId
487
+ });
488
+ }
489
+ }
490
+ }
491
+ }
492
+ resolveAuthChainConfig(chainId) {
493
+ var _this$evmProvider3, _this$coreOptions$cha2;
494
+ if (chainId) {
495
+ return this.coreOptions.chains.find(x => x.chainId === chainId);
496
+ }
497
+ const evmChainId = ((_this$evmProvider3 = this.evmProvider) === null || _this$evmProvider3 === void 0 ? void 0 : _this$evmProvider3.chainId) || ((_this$coreOptions$cha2 = this.coreOptions.chains.find(x => x.chainNamespace === baseControllers.CHAIN_NAMESPACES.EIP155)) === null || _this$coreOptions$cha2 === void 0 ? void 0 : _this$coreOptions$cha2.chainId);
498
+ const isSolanaOnly = !this.evmProvider && !!this.solanaProvider;
499
+ // Keep the old fallback for callers that do not pass a chainId yet.
500
+ return isSolanaOnly ? this.coreOptions.chains.find(x => x.chainNamespace === baseControllers.CHAIN_NAMESPACES.SOLANA) : this.evmProvider ? this.coreOptions.chains.find(x => x.chainId === evmChainId) : undefined;
501
+ }
465
502
  }
466
503
  /**
467
504
  * Factory function to create a MetaMask connector
@@ -258,7 +258,10 @@ class Web3AuthNoModal extends auth.SafeEventEmitter {
258
258
  }
259
259
  async cleanup() {
260
260
  for (const connector of this.connectors) {
261
- if (connector.cleanup) await connector.cleanup();
261
+ // if the connector is not ready, we don't need to cleanup
262
+ // this means that we load the connector (coz of the dashboard config) but the clients did not use it (i.e. with `showOnModal` set to false)
263
+ // example use case: external wallet **ONLY** login mode but the ClientID has enabled Auth connection in dashboard.
264
+ if (connector.cleanup && connector.status !== constants.CONNECTOR_STATUS.NOT_READY) await connector.cleanup();
262
265
  }
263
266
  }
264
267
  async switchChain(params) {
@@ -482,7 +485,9 @@ class Web3AuthNoModal extends auth.SafeEventEmitter {
482
485
  };
483
486
  try {
484
487
  this.analytics.track(analytics.ANALYTICS_EVENTS.IDENTITY_TOKEN_STARTED, trackData);
485
- const authTokenInfo = await this.primaryConnector.getAuthTokenInfo();
488
+ // Thread the controller's active chain into connector auth so multichain
489
+ // connectors sign for the same chain the app/session is currently using.
490
+ const authTokenInfo = await this.primaryConnector.getAuthTokenInfo(this.currentChainId);
486
491
  this.analytics.track(analytics.ANALYTICS_EVENTS.IDENTITY_TOKEN_COMPLETED, trackData);
487
492
  return {
488
493
  idToken: authTokenInfo.idToken
@@ -519,7 +524,9 @@ class Web3AuthNoModal extends auth.SafeEventEmitter {
519
524
  if (!(params !== null && params !== void 0 && params.connectorName)) {
520
525
  throw index.WalletInitializationError.invalidParams("connectorName is required when calling linkAccount on the no-modal SDK");
521
526
  }
522
- const chainId = this.resolveLinkAccountChainId(params.chainId);
527
+ const {
528
+ chainId
529
+ } = this.resolveLinkAccountChainConfig(params.chainId);
523
530
  const isolatedConnector = await this.createLinkingWalletConnector(params.connectorName, chainId);
524
531
  return this.linkAccountWithConnector(params.connectorName, chainId, isolatedConnector);
525
532
  }
@@ -911,11 +918,15 @@ class Web3AuthNoModal extends auth.SafeEventEmitter {
911
918
  }));
912
919
  this.setActiveWalletConnectorKey();
913
920
  this.connectionReconnected = data.reconnected;
921
+ const {
922
+ activeAccount,
923
+ currentChainId
924
+ } = this.state;
914
925
  // when ssr is enabled, we need to get the idToken from the connector.
915
926
  if (this.coreOptions.ssr) {
916
927
  try {
917
928
  var _data$accessToken, _data$refreshToken;
918
- const data = await connector.getAuthTokenInfo();
929
+ const data = await connector.getAuthTokenInfo(currentChainId);
919
930
  if (!data.idToken) throw index.WalletLoginError.connectionError("No idToken found");
920
931
  await this.setState({
921
932
  idToken: data.idToken,
@@ -932,10 +943,6 @@ class Web3AuthNoModal extends auth.SafeEventEmitter {
932
943
  }
933
944
  }
934
945
  // The following block only hits during rehydration
935
- const {
936
- activeAccount,
937
- currentChainId
938
- } = this.state;
939
946
  let rehydrateWithLinkedAccount = false;
940
947
  // for rehydration, if the active account is not the primary account, i.e. not `null`, create an isolated connector and connect to the chain
941
948
  if (activeAccount && !activeAccount.isPrimary && activeAccount.connector !== index$1.WALLET_CONNECTORS.AUTH) {
@@ -982,7 +989,7 @@ class Web3AuthNoModal extends auth.SafeEventEmitter {
982
989
  const pendingUserConsent = this.consentRequired && !this.state.hasUserConsent;
983
990
  if (pendingUserConsent && !isConnectAndSign) {
984
991
  this.status = constants.CONNECTOR_STATUS.CONSENT_REQUIRING;
985
- this.emit(constants.CONNECTOR_EVENTS.CONSENT_REQUIRING);
992
+ this.emit(constants.CONNECTOR_EVENTS.CONSENT_REQUIRING, _objectSpread({}, data));
986
993
  loglevel.log.debug("consent_requiring", this.status, this.primaryConnectorName);
987
994
  } else {
988
995
  // In CONNECT_AND_SIGN mode the AUTHORIZED handler can run before this point (e.g. when `ssr=true`
@@ -1102,7 +1109,13 @@ class Web3AuthNoModal extends auth.SafeEventEmitter {
1102
1109
  await this.clearCache();
1103
1110
  this.emit(constants.CONNECTOR_EVENTS.REHYDRATION_ERROR, error);
1104
1111
  });
1105
- connector.on(constants.CONNECTOR_EVENTS.CONNECTOR_DATA_UPDATED, data => {
1112
+ connector.on(constants.CONNECTOR_EVENTS.CONNECTOR_DATA_UPDATED, async data => {
1113
+ if (this.shouldIgnoreInactiveConnectorEvent(connector, constants.CONNECTOR_EVENTS.CONNECTOR_DATA_UPDATED)) return;
1114
+ // External wallets can resolve to a different active chain than the requested one,
1115
+ // so let connector-reported chain updates reconcile Web3Auth state after connect.
1116
+ if (typeof (data === null || data === void 0 ? void 0 : data.data) === "object" && (data === null || data === void 0 ? void 0 : data.data) !== null && "chainId" in data.data && typeof data.data.chainId === "string") {
1117
+ await this.setCurrentChain(data.data.chainId);
1118
+ }
1106
1119
  loglevel.log.debug("connector data updated", data);
1107
1120
  this.emit(constants.CONNECTOR_EVENTS.CONNECTOR_DATA_UPDATED, data);
1108
1121
  });
@@ -1139,7 +1152,9 @@ class Web3AuthNoModal extends auth.SafeEventEmitter {
1139
1152
  // if the user has not consented yet, we will ask for consent
1140
1153
  if (this.consentRequired && this.connection && !this.state.hasUserConsent) {
1141
1154
  this.status = constants.CONNECTOR_STATUS.CONSENT_REQUIRING;
1142
- this.emit(constants.CONNECTOR_EVENTS.CONSENT_REQUIRING);
1155
+ this.emit(constants.CONNECTOR_EVENTS.CONSENT_REQUIRING, {
1156
+ connectorName: data.connector
1157
+ });
1143
1158
  loglevel.log.debug("consent_requiring", this.status, this.primaryConnectorName);
1144
1159
  } else {
1145
1160
  this.status = constants.CONNECTOR_STATUS.AUTHORIZED;
@@ -1201,12 +1216,14 @@ class Web3AuthNoModal extends auth.SafeEventEmitter {
1201
1216
  reconnected: this.connectionReconnected
1202
1217
  });
1203
1218
  }
1204
- resolveLinkAccountChainId(chainId) {
1219
+ resolveLinkAccountChainConfig(chainId) {
1220
+ var _this$coreOptions$cha7;
1205
1221
  const finalChainId = chainId || this.state.currentChainId;
1206
- if (!finalChainId) {
1222
+ const chainConfig = (_this$coreOptions$cha7 = this.coreOptions.chains) === null || _this$coreOptions$cha7 === void 0 ? void 0 : _this$coreOptions$cha7.find(chain => chain.chainId === finalChainId);
1223
+ if (!chainConfig) {
1207
1224
  throw errors.AccountLinkingError.walletProofFailed("No chainId is available. Please specify chainId in LinkAccountParams or ensure the SDK has an active chain.");
1208
1225
  }
1209
- return finalChainId;
1226
+ return chainConfig;
1210
1227
  }
1211
1228
  /**
1212
1229
  * Resolves the chain ID for a switch account operation.
@@ -26,6 +26,12 @@ export declare const ANALYTICS_EVENTS: {
26
26
  MFA_ENABLEMENT_FAILED: string;
27
27
  MFA_MANAGEMENT_SELECTED: string;
28
28
  MFA_MANAGEMENT_FAILED: string;
29
+ USER_CONSENT_STARTED: string;
30
+ USER_CONSENT_ACCEPTED: string;
31
+ USER_CONSENT_DECLINED: string;
32
+ USER_CONSENT_ERRORED: string;
33
+ TERMS_OF_SERVICE_CLICKED: string;
34
+ PRIVACY_POLICY_CLICKED: string;
29
35
  LOGIN_MODAL_OPENED: string;
30
36
  LOGIN_MODAL_CLOSED: string;
31
37
  SOCIAL_LOGIN_SELECTED: string;
@@ -102,8 +102,12 @@ export interface IConnector<T> extends SafeEventEmitter {
102
102
  switchChain(params: {
103
103
  chainId: string;
104
104
  }): Promise<void>;
105
- getAuthTokenInfo(): Promise<AuthTokenInfo>;
106
- generateChallengeAndSign(authServerUrl?: string, accounts?: string[]): Promise<{
105
+ /**
106
+ * `chainId` is optional to keep the connector API backward compatible while still
107
+ * allowing multichain connectors to bind auth/signing to the caller's selected chain.
108
+ */
109
+ getAuthTokenInfo(chainId?: string): Promise<AuthTokenInfo>;
110
+ generateChallengeAndSign(authServerUrl?: string, accounts?: string[], chainId?: string): Promise<{
107
111
  challenge: string;
108
112
  signature: string;
109
113
  chainNamespace: ChainNamespaceType;
@@ -227,13 +227,14 @@ export type SDK_CONNECTED_EVENT_DATA = CONNECTED_EVENT_DATA & {
227
227
  loginMode: LoginModeType;
228
228
  pendingUserConsent?: boolean;
229
229
  };
230
- export type SDK_CONSENT_ACCEPTED_EVENT_DATA = {
230
+ export type SDK_CONSENT_ACCEPTED_EVENT_DATA = Partial<CONNECTED_EVENT_DATA> & {
231
231
  reconnected: boolean;
232
232
  };
233
+ export type SDK_CONSENT_REQUIRING_EVENT_DATA = Partial<CONNECTED_EVENT_DATA>;
233
234
  export type Web3AuthNoModalEvents = Omit<ConnectorEvents, "connected" | "errored" | "ready" | "consent_requiring" | "consent_accepted"> & {
234
235
  [CONNECTOR_EVENTS.READY]: () => void;
235
236
  [CONNECTOR_EVENTS.CONNECTED]: (data: SDK_CONNECTED_EVENT_DATA) => void;
236
- [CONNECTOR_EVENTS.CONSENT_REQUIRING]: () => void;
237
+ [CONNECTOR_EVENTS.CONSENT_REQUIRING]: (data: SDK_CONSENT_REQUIRING_EVENT_DATA) => void;
237
238
  [CONNECTOR_EVENTS.CONSENT_ACCEPTED]: (data: SDK_CONSENT_ACCEPTED_EVENT_DATA) => void;
238
239
  [CONNECTOR_EVENTS.ERRORED]: (error: Web3AuthError, loginMode: LoginModeType) => void;
239
240
  [CONNECTOR_EVENTS.CONNECTION_UPDATED]: (data: CONNECTION_UPDATED_EVENT_DATA) => void;
@@ -95,7 +95,7 @@ export declare class Web3AuthNoModal extends SafeEventEmitter<Web3AuthNoModalEve
95
95
  */
96
96
  protected getInitialChainIdForConnector(connector: IConnector<unknown>): CustomChainConfig;
97
97
  protected completeConsentAcceptance(): Promise<void>;
98
- protected resolveLinkAccountChainId(chainId?: string | null): string;
98
+ protected resolveLinkAccountChainConfig(chainId?: string | null): CustomChainConfig;
99
99
  /**
100
100
  * Resolves the chain ID for a switch account operation.
101
101
  * If the account's chain namespace is the same as the current chain namespace, return the current chain ID.
@@ -106,6 +106,13 @@ const ANALYTICS_EVENTS = {
106
106
  MFA_ENABLEMENT_FAILED: "MFA Enablement Failed",
107
107
  MFA_MANAGEMENT_SELECTED: "MFA Management Selected",
108
108
  MFA_MANAGEMENT_FAILED: "MFA Management Failed",
109
+ // Consent Flow
110
+ USER_CONSENT_STARTED: "User Consent Started",
111
+ USER_CONSENT_ACCEPTED: "User Consent Accepted",
112
+ USER_CONSENT_DECLINED: "User Consent Declined",
113
+ USER_CONSENT_ERRORED: "User Consent Errored",
114
+ TERMS_OF_SERVICE_CLICKED: "Terms of Service Clicked",
115
+ PRIVACY_POLICY_CLICKED: "Privacy Policy Clicked",
109
116
  // Login Modal
110
117
  LOGIN_MODAL_OPENED: "Login Modal Opened",
111
118
  LOGIN_MODAL_CLOSED: "Login Modal Closed",
@@ -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.1";
152
+ const sdkVersion = "11.1.0";
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;
@@ -370,11 +370,9 @@ class AuthConnector extends BaseConnector {
370
370
  }
371
371
  }
372
372
  async cleanup() {
373
- if (!this.authInstance) throw WalletInitializationError.notReady("authInstance is not ready");
374
- await this.authInstance.cleanup();
375
- if (this.wsEmbedInstance) {
376
- this.wsEmbedInstance.clearInit();
377
- }
373
+ var _this$authInstance, _this$wsEmbedInstance2;
374
+ await ((_this$authInstance = this.authInstance) === null || _this$authInstance === void 0 ? void 0 : _this$authInstance.cleanup());
375
+ (_this$wsEmbedInstance2 = this.wsEmbedInstance) === null || _this$wsEmbedInstance2 === void 0 || _this$wsEmbedInstance2.clearInit();
378
376
  this._solanaWallet = null;
379
377
  this.unbindWsEmbedProviderEvents();
380
378
  }
@@ -490,7 +488,7 @@ class AuthConnector extends BaseConnector {
490
488
  accessToken,
491
489
  idToken
492
490
  } = await this.getPrimaryAuthSession(params.authSessionTokens);
493
- const walletProof = await this.createWalletLinkingProof(params.connectorToLink);
491
+ const walletProof = await this.createWalletLinkingProof(params.connectorToLink, chainId);
494
492
  const authServerUrl = citadelServerUrl(this.coreOptions.authBuildEnv);
495
493
  const result = await makeAccountLinkingRequest(authServerUrl, accessToken, {
496
494
  idToken,
@@ -683,7 +681,7 @@ class AuthConnector extends BaseConnector {
683
681
  }
684
682
  throw AccountLinkingError.requestFailed(`Unsupported chain namespace "${matchedAccount.chainNamespace}" for address "${address}".`);
685
683
  }
686
- async createWalletLinkingProof(connector) {
684
+ async createWalletLinkingProof(connector, chainId) {
687
685
  // Notify listeners that the linking wallet is about to be asked for a signature so the UI
688
686
  // (e.g. modal) can switch from a "connecting" loader to an "authorizing" prompt while the
689
687
  // user reviews the signature request inside their wallet. Emitted on the isolated wallet
@@ -691,11 +689,13 @@ class AuthConnector extends BaseConnector {
691
689
  connector.emit(CONNECTOR_EVENTS.AUTHORIZING, {
692
690
  connector: connector.name
693
691
  });
692
+ // Reuse the caller's target chain so multichain wallets generate the linking
693
+ // proof for the same namespace they were connected for.
694
694
  const {
695
695
  challenge,
696
696
  signature,
697
697
  chainNamespace
698
- } = await connector.generateChallengeAndSign();
698
+ } = await connector.generateChallengeAndSign(undefined, undefined, chainId);
699
699
  const address = await this.getLinkingWalletAddress(connector, chainNamespace);
700
700
  if (chainNamespace === CHAIN_NAMESPACES.EIP155) {
701
701
  return {
@@ -738,8 +738,8 @@ class AuthConnector extends BaseConnector {
738
738
  return accounts[0];
739
739
  }
740
740
  getWsEmbedProvider() {
741
- var _ref, _this$wsEmbedInstance2;
742
- return (_ref = (_this$wsEmbedInstance2 = this.wsEmbedInstance) === null || _this$wsEmbedInstance2 === void 0 ? void 0 : _this$wsEmbedInstance2.provider) !== null && _ref !== void 0 ? _ref : null;
741
+ var _ref, _this$wsEmbedInstance3;
742
+ return (_ref = (_this$wsEmbedInstance3 = this.wsEmbedInstance) === null || _this$wsEmbedInstance3 === void 0 ? void 0 : _this$wsEmbedInstance3.provider) !== null && _ref !== void 0 ? _ref : null;
743
743
  }
744
744
  bindWsEmbedProviderEvents() {
745
745
  const rawProvider = this.getWsEmbedProvider();
@@ -784,7 +784,7 @@ class AuthConnector extends BaseConnector {
784
784
  return finalPrivKey;
785
785
  }
786
786
  async connectWithProvider(params) {
787
- var _this$authInstance, _params$extraLoginOpt, _this$authInstance2, _this$authInstance3;
787
+ var _this$authInstance2, _params$extraLoginOpt, _this$authInstance3, _this$authInstance4;
788
788
  if (!this.authInstance) throw WalletInitializationError.notReady("authInstance is not ready");
789
789
  const chainConfig = this.coreOptions.chains.find(x => x.chainId === params.chainId);
790
790
  if (!chainConfig) throw WalletLoginError.connectionError("Chain config is not available");
@@ -793,7 +793,7 @@ class AuthConnector extends BaseConnector {
793
793
  } = chainConfig;
794
794
 
795
795
  // if not logged in then login
796
- const keyAvailable = chainNamespace === CHAIN_NAMESPACES.EIP155 || chainNamespace === CHAIN_NAMESPACES.SOLANA ? (_this$authInstance = this.authInstance) === null || _this$authInstance === void 0 ? void 0 : _this$authInstance.sessionId : this._getFinalPrivKey();
796
+ const keyAvailable = chainNamespace === CHAIN_NAMESPACES.EIP155 || chainNamespace === CHAIN_NAMESPACES.SOLANA ? (_this$authInstance2 = this.authInstance) === null || _this$authInstance2 === void 0 ? void 0 : _this$authInstance2.sessionId : this._getFinalPrivKey();
797
797
  if (params.idToken) params.extraLoginOptions = _objectSpread(_objectSpread({}, params.extraLoginOptions), {}, {
798
798
  id_token: params.idToken
799
799
  });
@@ -810,7 +810,7 @@ class AuthConnector extends BaseConnector {
810
810
  }
811
811
 
812
812
  // if useSFAKey is true and privKey is available but coreKitKey is not available, throw an error
813
- if (this.coreOptions.useSFAKey && (_this$authInstance2 = this.authInstance) !== null && _this$authInstance2 !== void 0 && _this$authInstance2.privKey && !((_this$authInstance3 = this.authInstance) !== null && _this$authInstance3 !== void 0 && _this$authInstance3.coreKitKey)) {
813
+ if (this.coreOptions.useSFAKey && (_this$authInstance3 = this.authInstance) !== null && _this$authInstance3 !== void 0 && _this$authInstance3.privKey && !((_this$authInstance4 = this.authInstance) !== null && _this$authInstance4 !== void 0 && _this$authInstance4.coreKitKey)) {
814
814
  // If the user is already logged in, logout and throw an error
815
815
  if (this.authInstance.sessionId) {
816
816
  await this.authInstance.logout();
@@ -141,7 +141,12 @@ class MetaMaskConnector extends BaseConnector {
141
141
  this.disconnect();
142
142
  }
143
143
  },
144
- chainChanged: _chainId => {},
144
+ chainChanged: _chainId => {
145
+ // Keep Web3Auth state aligned with the wallet's actual EVM chain after connect/switch.
146
+ this.updateConnectorData({
147
+ chainId: _chainId
148
+ });
149
+ },
145
150
  connect: _result => {},
146
151
  disconnect: () => {
147
152
  if (this.connected) {
@@ -198,7 +203,7 @@ class MetaMaskConnector extends BaseConnector {
198
203
  ethereumProvider: this.evmProvider,
199
204
  solanaWallet: this.solanaProvider
200
205
  });
201
- if (options.getAuthTokenInfo) await this.getAuthTokenInfo();
206
+ if (options.getAuthTokenInfo) await this.getAuthTokenInfo(options.chainId);
202
207
  } else if (coreStatus === "connected" || coreStatus === "loaded" || coreStatus === "disconnected" || coreStatus === "pending") {
203
208
  this.status = CONNECTOR_STATUS.READY;
204
209
  this.emit(CONNECTOR_EVENTS.READY, WALLET_CONNECTORS.METAMASK);
@@ -266,13 +271,9 @@ class MetaMaskConnector extends BaseConnector {
266
271
  }
267
272
  }
268
273
 
269
- // // Switch EVM chain if not connected to the right one (Solana chains are handled by the wallet-standard provider)
270
- // if (chainConfig.chainNamespace === CHAIN_NAMESPACES.EIP155) {
271
- // const currentChainId = this.evmClient!.getChainId();
272
- // if (currentChainId !== chainId) {
273
- // await this.switchChain(chainConfig, true);
274
- // }
275
- // }
274
+ // sync the chain state after connect
275
+ // metamask might not be connected to the requested chain, so we need to sync the chain state to/from Web3Auth state after connect.
276
+ await this.syncChainStateAfterConnect(chainConfig);
276
277
 
277
278
  // check if connected
278
279
  if (this.multichainClient.status !== "connected") {
@@ -295,7 +296,7 @@ class MetaMaskConnector extends BaseConnector {
295
296
  solanaWallet: this.solanaProvider
296
297
  });
297
298
  if (getAuthTokenInfo) {
298
- await this.getAuthTokenInfo();
299
+ await this.getAuthTokenInfo(chainId);
299
300
  }
300
301
  return {
301
302
  ethereumProvider: this.evmProvider,
@@ -347,14 +348,11 @@ class MetaMaskConnector extends BaseConnector {
347
348
  connector: WALLET_CONNECTORS.METAMASK
348
349
  });
349
350
  }
350
- async getAuthTokenInfo() {
351
- var _this$evmProvider2, _this$coreOptions$cha;
351
+ async getAuthTokenInfo(chainId) {
352
352
  if (!this.canAuthorize) throw WalletLoginError.notConnectedError();
353
-
354
- // Determine the active chain: prefer Solana if no EVM provider, otherwise use EVM provider's chain
355
- const evmChainId = ((_this$evmProvider2 = this.evmProvider) === null || _this$evmProvider2 === void 0 ? void 0 : _this$evmProvider2.chainId) || ((_this$coreOptions$cha = this.coreOptions.chains.find(x => x.chainNamespace === CHAIN_NAMESPACES.EIP155)) === null || _this$coreOptions$cha === void 0 ? void 0 : _this$coreOptions$cha.chainId);
356
- const isSolanaOnly = !this.evmProvider && !!this.solanaProvider;
357
- const activeChainConfig = isSolanaOnly ? this.coreOptions.chains.find(x => x.chainNamespace === CHAIN_NAMESPACES.SOLANA) : this.evmProvider ? this.coreOptions.chains.find(x => x.chainId === evmChainId) : undefined;
353
+ // In multichain sessions both providers can exist at the same time, so auth must
354
+ // follow the caller-selected chain instead of inferring from provider availability.
355
+ const activeChainConfig = this.resolveAuthChainConfig(chainId);
358
356
  if (!activeChainConfig) throw WalletLoginError.connectionError("Chain config is not available");
359
357
  const {
360
358
  chainNamespace
@@ -374,7 +372,7 @@ class MetaMaskConnector extends BaseConnector {
374
372
  const {
375
373
  challenge,
376
374
  signature
377
- } = await this.generateChallengeAndSign(authServer, accounts);
375
+ } = await this.generateChallengeAndSign(authServer, accounts, activeChainConfig.chainId);
378
376
  return this.verifyAndAuthorize({
379
377
  chainNamespace,
380
378
  signedMessage: signature,
@@ -415,11 +413,8 @@ class MetaMaskConnector extends BaseConnector {
415
413
  chainConfiguration
416
414
  });
417
415
  }
418
- async generateChallengeAndSign(authServerUrl, accounts) {
419
- var _this$evmProvider3, _this$coreOptions$cha2;
420
- const evmChainId = ((_this$evmProvider3 = this.evmProvider) === null || _this$evmProvider3 === void 0 ? void 0 : _this$evmProvider3.chainId) || ((_this$coreOptions$cha2 = this.coreOptions.chains.find(x => x.chainNamespace === CHAIN_NAMESPACES.EIP155)) === null || _this$coreOptions$cha2 === void 0 ? void 0 : _this$coreOptions$cha2.chainId);
421
- const isSolanaOnly = !this.evmProvider && !!this.solanaProvider;
422
- const activeChainConfig = isSolanaOnly ? this.coreOptions.chains.find(x => x.chainNamespace === CHAIN_NAMESPACES.SOLANA) : this.evmProvider ? this.coreOptions.chains.find(x => x.chainId === evmChainId) : undefined;
416
+ async generateChallengeAndSign(authServerUrl, accounts, chainId) {
417
+ const activeChainConfig = this.resolveAuthChainConfig(chainId);
423
418
  if (!activeChainConfig) throw WalletLoginError.connectionError("Chain config is not available");
424
419
  const {
425
420
  chainNamespace
@@ -475,6 +470,48 @@ class MetaMaskConnector extends BaseConnector {
475
470
  }
476
471
  await this.initializationPromise;
477
472
  }
473
+ async syncChainStateAfterConnect(chainConfig) {
474
+ var _this$evmProvider2;
475
+ // EVM connectors can switch chains, so align the wallet with the requested chain
476
+ // before Web3Auth persists the active chain in controller state.
477
+ if (chainConfig.chainNamespace === CHAIN_NAMESPACES.EIP155 && ((_this$evmProvider2 = this.evmProvider) === null || _this$evmProvider2 === void 0 ? void 0 : _this$evmProvider2.chainId) !== chainConfig.chainId) {
478
+ await this.switchChain({
479
+ chainId: chainConfig.chainId
480
+ }, true);
481
+ } else if (chainConfig.chainNamespace === CHAIN_NAMESPACES.SOLANA) {
482
+ // For solana case, metamask connect the first available scope in priority order: mainnet > devnet > testnet.
483
+ // So, if the user requested chain is different from the connected chain,
484
+ // we need to update the connector data with the connected chain id to keep the Web3Auth state aligned.
485
+ if ("scope" in this.solanaProvider && typeof this.solanaProvider.scope === "string") {
486
+ var _this$coreOptions$cha;
487
+ const connectedSolChain = this.solanaProvider.scope;
488
+ const connectedChainConfig = (_this$coreOptions$cha = this.coreOptions.chains) === null || _this$coreOptions$cha === void 0 ? void 0 : _this$coreOptions$cha.find(chain => {
489
+ return getCaipChainId(chain) === connectedSolChain && chain.chainNamespace === CHAIN_NAMESPACES.SOLANA;
490
+ });
491
+ if (!connectedChainConfig) {
492
+ throw WalletLoginError.connectionError("Connected chain is not available in the chains config");
493
+ }
494
+ if (connectedChainConfig.chainId !== chainConfig.chainId) {
495
+ // since, switchChain is not supported for solana (in metamask connect),
496
+ // we will make use of the connector data to update the Web3Auth state.
497
+ this.updateConnectorData({
498
+ chainId: connectedChainConfig.chainId
499
+ });
500
+ }
501
+ }
502
+ }
503
+ }
504
+ resolveAuthChainConfig(chainId) {
505
+ var _this$evmProvider3, _this$coreOptions$cha2;
506
+ if (chainId) {
507
+ return this.coreOptions.chains.find(x => x.chainId === chainId);
508
+ }
509
+ const evmChainId = ((_this$evmProvider3 = this.evmProvider) === null || _this$evmProvider3 === void 0 ? void 0 : _this$evmProvider3.chainId) || ((_this$coreOptions$cha2 = this.coreOptions.chains.find(x => x.chainNamespace === CHAIN_NAMESPACES.EIP155)) === null || _this$coreOptions$cha2 === void 0 ? void 0 : _this$coreOptions$cha2.chainId);
510
+ const isSolanaOnly = !this.evmProvider && !!this.solanaProvider;
511
+
512
+ // Keep the old fallback for callers that do not pass a chainId yet.
513
+ return isSolanaOnly ? this.coreOptions.chains.find(x => x.chainNamespace === CHAIN_NAMESPACES.SOLANA) : this.evmProvider ? this.coreOptions.chains.find(x => x.chainId === evmChainId) : undefined;
514
+ }
478
515
  }
479
516
 
480
517
  /**
@@ -261,7 +261,10 @@ class Web3AuthNoModal extends SafeEventEmitter {
261
261
  }
262
262
  async cleanup() {
263
263
  for (const connector of this.connectors) {
264
- if (connector.cleanup) await connector.cleanup();
264
+ // if the connector is not ready, we don't need to cleanup
265
+ // this means that we load the connector (coz of the dashboard config) but the clients did not use it (i.e. with `showOnModal` set to false)
266
+ // example use case: external wallet **ONLY** login mode but the ClientID has enabled Auth connection in dashboard.
267
+ if (connector.cleanup && connector.status !== CONNECTOR_STATUS.NOT_READY) await connector.cleanup();
265
268
  }
266
269
  }
267
270
  async switchChain(params) {
@@ -489,7 +492,9 @@ class Web3AuthNoModal extends SafeEventEmitter {
489
492
  };
490
493
  try {
491
494
  this.analytics.track(ANALYTICS_EVENTS.IDENTITY_TOKEN_STARTED, trackData);
492
- const authTokenInfo = await this.primaryConnector.getAuthTokenInfo();
495
+ // Thread the controller's active chain into connector auth so multichain
496
+ // connectors sign for the same chain the app/session is currently using.
497
+ const authTokenInfo = await this.primaryConnector.getAuthTokenInfo(this.currentChainId);
493
498
  this.analytics.track(ANALYTICS_EVENTS.IDENTITY_TOKEN_COMPLETED, trackData);
494
499
  return {
495
500
  idToken: authTokenInfo.idToken
@@ -526,7 +531,9 @@ class Web3AuthNoModal extends SafeEventEmitter {
526
531
  if (!(params !== null && params !== void 0 && params.connectorName)) {
527
532
  throw WalletInitializationError.invalidParams("connectorName is required when calling linkAccount on the no-modal SDK");
528
533
  }
529
- const chainId = this.resolveLinkAccountChainId(params.chainId);
534
+ const {
535
+ chainId
536
+ } = this.resolveLinkAccountChainConfig(params.chainId);
530
537
  const isolatedConnector = await this.createLinkingWalletConnector(params.connectorName, chainId);
531
538
  return this.linkAccountWithConnector(params.connectorName, chainId, isolatedConnector);
532
539
  }
@@ -928,12 +935,16 @@ class Web3AuthNoModal extends SafeEventEmitter {
928
935
  }));
929
936
  this.setActiveWalletConnectorKey();
930
937
  this.connectionReconnected = data.reconnected;
938
+ const {
939
+ activeAccount,
940
+ currentChainId
941
+ } = this.state;
931
942
 
932
943
  // when ssr is enabled, we need to get the idToken from the connector.
933
944
  if (this.coreOptions.ssr) {
934
945
  try {
935
946
  var _data$accessToken, _data$refreshToken;
936
- const data = await connector.getAuthTokenInfo();
947
+ const data = await connector.getAuthTokenInfo(currentChainId);
937
948
  if (!data.idToken) throw WalletLoginError.connectionError("No idToken found");
938
949
  await this.setState({
939
950
  idToken: data.idToken,
@@ -951,10 +962,6 @@ class Web3AuthNoModal extends SafeEventEmitter {
951
962
  }
952
963
  // The following block only hits during rehydration
953
964
 
954
- const {
955
- activeAccount,
956
- currentChainId
957
- } = this.state;
958
965
  let rehydrateWithLinkedAccount = false;
959
966
  // for rehydration, if the active account is not the primary account, i.e. not `null`, create an isolated connector and connect to the chain
960
967
  if (activeAccount && !activeAccount.isPrimary && activeAccount.connector !== WALLET_CONNECTORS.AUTH) {
@@ -1001,7 +1008,7 @@ class Web3AuthNoModal extends SafeEventEmitter {
1001
1008
  const pendingUserConsent = this.consentRequired && !this.state.hasUserConsent;
1002
1009
  if (pendingUserConsent && !isConnectAndSign) {
1003
1010
  this.status = CONNECTOR_STATUS.CONSENT_REQUIRING;
1004
- this.emit(CONNECTOR_EVENTS.CONSENT_REQUIRING);
1011
+ this.emit(CONNECTOR_EVENTS.CONSENT_REQUIRING, _objectSpread({}, data));
1005
1012
  log.debug("consent_requiring", this.status, this.primaryConnectorName);
1006
1013
  } else {
1007
1014
  // In CONNECT_AND_SIGN mode the AUTHORIZED handler can run before this point (e.g. when `ssr=true`
@@ -1124,7 +1131,13 @@ class Web3AuthNoModal extends SafeEventEmitter {
1124
1131
  await this.clearCache();
1125
1132
  this.emit(CONNECTOR_EVENTS.REHYDRATION_ERROR, error);
1126
1133
  });
1127
- connector.on(CONNECTOR_EVENTS.CONNECTOR_DATA_UPDATED, data => {
1134
+ connector.on(CONNECTOR_EVENTS.CONNECTOR_DATA_UPDATED, async data => {
1135
+ if (this.shouldIgnoreInactiveConnectorEvent(connector, CONNECTOR_EVENTS.CONNECTOR_DATA_UPDATED)) return;
1136
+ // External wallets can resolve to a different active chain than the requested one,
1137
+ // so let connector-reported chain updates reconcile Web3Auth state after connect.
1138
+ if (typeof (data === null || data === void 0 ? void 0 : data.data) === "object" && (data === null || data === void 0 ? void 0 : data.data) !== null && "chainId" in data.data && typeof data.data.chainId === "string") {
1139
+ await this.setCurrentChain(data.data.chainId);
1140
+ }
1128
1141
  log.debug("connector data updated", data);
1129
1142
  this.emit(CONNECTOR_EVENTS.CONNECTOR_DATA_UPDATED, data);
1130
1143
  });
@@ -1162,7 +1175,9 @@ class Web3AuthNoModal extends SafeEventEmitter {
1162
1175
  // if the user has not consented yet, we will ask for consent
1163
1176
  if (this.consentRequired && this.connection && !this.state.hasUserConsent) {
1164
1177
  this.status = CONNECTOR_STATUS.CONSENT_REQUIRING;
1165
- this.emit(CONNECTOR_EVENTS.CONSENT_REQUIRING);
1178
+ this.emit(CONNECTOR_EVENTS.CONSENT_REQUIRING, {
1179
+ connectorName: data.connector
1180
+ });
1166
1181
  log.debug("consent_requiring", this.status, this.primaryConnectorName);
1167
1182
  } else {
1168
1183
  this.status = CONNECTOR_STATUS.AUTHORIZED;
@@ -1226,12 +1241,14 @@ class Web3AuthNoModal extends SafeEventEmitter {
1226
1241
  reconnected: this.connectionReconnected
1227
1242
  });
1228
1243
  }
1229
- resolveLinkAccountChainId(chainId) {
1244
+ resolveLinkAccountChainConfig(chainId) {
1245
+ var _this$coreOptions$cha7;
1230
1246
  const finalChainId = chainId || this.state.currentChainId;
1231
- if (!finalChainId) {
1247
+ const chainConfig = (_this$coreOptions$cha7 = this.coreOptions.chains) === null || _this$coreOptions$cha7 === void 0 ? void 0 : _this$coreOptions$cha7.find(chain => chain.chainId === finalChainId);
1248
+ if (!chainConfig) {
1232
1249
  throw AccountLinkingError.walletProofFailed("No chainId is available. Please specify chainId in LinkAccountParams or ensure the SDK has an active chain.");
1233
1250
  }
1234
- return finalChainId;
1251
+ return chainConfig;
1235
1252
  }
1236
1253
 
1237
1254
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@web3auth/no-modal",
3
- "version": "11.0.1",
3
+ "version": "11.1.0",
4
4
  "description": "Multi chain wallet aggregator for web3Auth",
5
5
  "keywords": [
6
6
  "web3Auth/no-modal",
@@ -65,9 +65,9 @@
65
65
  }
66
66
  },
67
67
  "dependencies": {
68
- "@metamask/connect-evm": "^1.4.0",
69
- "@metamask/connect-multichain": "^0.15.0",
70
- "@metamask/connect-solana": "^1.2.0",
68
+ "@metamask/connect-evm": "^2.0.0",
69
+ "@metamask/connect-multichain": "^1.0.0",
70
+ "@metamask/connect-solana": "^2.0.0",
71
71
  "@segment/analytics-next": "^1.84.0",
72
72
  "@solana/client": "^1.7.0",
73
73
  "@solana/kit": "^6.9.0",
@@ -75,7 +75,7 @@
75
75
  "@toruslabs/base-controllers": "^9.10.0",
76
76
  "@toruslabs/constants": "^16.1.1",
77
77
  "@toruslabs/eccrypto": "^7.0.0",
78
- "@toruslabs/ethereum-controllers": "^9.10.0",
78
+ "@toruslabs/ethereum-controllers": "^9.11.0",
79
79
  "@toruslabs/http-helpers": "^9.0.0",
80
80
  "@toruslabs/loglevel-sentry": "^9.0.0",
81
81
  "@toruslabs/metadata-helpers": "^8.2.0",
@@ -88,7 +88,7 @@
88
88
  "@walletconnect/types": "^2.23.9",
89
89
  "@walletconnect/utils": "^2.23.9",
90
90
  "@web3auth/auth": "^11.8.1",
91
- "@web3auth/ws-embed": "^6.0.4",
91
+ "@web3auth/ws-embed": "^6.1.0",
92
92
  "bignumber.js": "~9.3.1",
93
93
  "deepmerge": "^4.3.1",
94
94
  "ethers": "^6.16.0",
@@ -252,5 +252,5 @@
252
252
  "node": ">=22.x",
253
253
  "npm": ">=10.x"
254
254
  },
255
- "gitHead": "83f7a5e2ead574c15f74b63f19e83ea13098da61"
255
+ "gitHead": "50c16e16f234a5934ce51f56e30b5ab48cad72ae"
256
256
  }