@web3auth/no-modal 11.0.0-beta.0 → 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.
Files changed (101) hide show
  1. package/dist/lib.cjs/account-linking/index.js +8 -0
  2. package/dist/lib.cjs/account-linking/react.js +95 -0
  3. package/dist/lib.cjs/account-linking/rest.js +54 -0
  4. package/dist/lib.cjs/account-linking/vue.js +98 -0
  5. package/dist/lib.cjs/base/analytics.js +17 -2
  6. package/dist/lib.cjs/base/connector/constants.js +2 -0
  7. package/dist/lib.cjs/base/errors/index.js +48 -0
  8. package/dist/lib.cjs/base/utils.js +15 -3
  9. package/dist/lib.cjs/connectors/auth-connector/authConnector.js +501 -70
  10. package/dist/lib.cjs/connectors/base-evm-connector/baseEvmConnector.js +42 -23
  11. package/dist/lib.cjs/connectors/base-solana-connector/baseSolanaConnector.js +41 -24
  12. package/dist/lib.cjs/connectors/metamask-connector/metamaskConnector.js +76 -45
  13. package/dist/lib.cjs/connectors/wallet-connect-v2-connector/walletConnectV2Connector.js +41 -13
  14. package/dist/lib.cjs/index.js +20 -13
  15. package/dist/lib.cjs/noModal.js +834 -117
  16. package/dist/lib.cjs/plugins/wallet-services-plugin/plugin.js +1 -1
  17. package/dist/lib.cjs/providers/base-provider/baseProvider.js +65 -33
  18. package/dist/lib.cjs/react/context/useWeb3AuthInnerContextValue.js +43 -20
  19. package/dist/lib.cjs/react/hooks/useWallets.js +51 -0
  20. package/dist/lib.cjs/react/hooks/useWeb3AuthConnect.js +2 -2
  21. package/dist/lib.cjs/react/index.js +2 -0
  22. package/dist/lib.cjs/react/solana/hooks/useSolanaWallet.js +2 -2
  23. package/dist/lib.cjs/react/solana/provider.js +7 -1
  24. package/dist/lib.cjs/react/wagmi/provider.js +37 -5
  25. package/dist/lib.cjs/types/account-linking/index.d.ts +2 -0
  26. package/dist/lib.cjs/types/account-linking/interfaces.d.ts +90 -0
  27. package/dist/lib.cjs/types/account-linking/react.d.ts +19 -0
  28. package/dist/lib.cjs/types/account-linking/rest.d.ts +9 -0
  29. package/dist/lib.cjs/types/account-linking/vue.d.ts +20 -0
  30. package/dist/lib.cjs/types/base/analytics.d.ts +9 -0
  31. package/dist/lib.cjs/types/base/connector/baseConnector.d.ts +5 -0
  32. package/dist/lib.cjs/types/base/connector/constants.d.ts +2 -0
  33. package/dist/lib.cjs/types/base/connector/interfaces.d.ts +51 -6
  34. package/dist/lib.cjs/types/base/core/IWeb3Auth.d.ts +39 -2
  35. package/dist/lib.cjs/types/base/errors/index.d.ts +13 -0
  36. package/dist/lib.cjs/types/base/interfaces.d.ts +3 -1
  37. package/dist/lib.cjs/types/base/utils.d.ts +7 -1
  38. package/dist/lib.cjs/types/connectors/auth-connector/authConnector.d.ts +33 -3
  39. package/dist/lib.cjs/types/connectors/auth-connector/interface.d.ts +77 -2
  40. package/dist/lib.cjs/types/connectors/base-evm-connector/baseEvmConnector.d.ts +6 -0
  41. package/dist/lib.cjs/types/connectors/base-solana-connector/baseSolanaConnector.d.ts +6 -0
  42. package/dist/lib.cjs/types/index.d.ts +1 -0
  43. package/dist/lib.cjs/types/noModal.d.ts +104 -5
  44. package/dist/lib.cjs/types/providers/base-provider/baseProvider.d.ts +7 -0
  45. package/dist/lib.cjs/types/react/hooks/index.d.ts +1 -0
  46. package/dist/lib.cjs/types/react/hooks/useWallets.d.ts +8 -0
  47. package/dist/lib.cjs/types/vue/composables/index.d.ts +1 -0
  48. package/dist/lib.cjs/types/vue/composables/useWallets.d.ts +9 -0
  49. package/dist/lib.cjs/vue/composables/useWallets.js +52 -0
  50. package/dist/lib.cjs/vue/composables/useWeb3AuthConnect.js +2 -2
  51. package/dist/lib.cjs/vue/index.js +2 -0
  52. package/dist/lib.cjs/vue/solana/composables/useSolanaWallet.js +2 -2
  53. package/dist/lib.cjs/vue/solana/provider.js +50 -23
  54. package/dist/lib.cjs/vue/useWeb3AuthInnerContextValue.js +13 -4
  55. package/dist/lib.cjs/vue/wagmi/provider.js +35 -7
  56. package/dist/lib.esm/account-linking/index.js +1 -0
  57. package/dist/lib.esm/account-linking/react.js +74 -0
  58. package/dist/lib.esm/account-linking/rest.js +51 -0
  59. package/dist/lib.esm/account-linking/vue.js +78 -0
  60. package/dist/lib.esm/base/analytics.js +17 -2
  61. package/dist/lib.esm/base/connector/constants.js +2 -0
  62. package/dist/lib.esm/base/errors/index.js +48 -1
  63. package/dist/lib.esm/base/utils.js +16 -4
  64. package/dist/lib.esm/connectors/auth-connector/authConnector.js +462 -31
  65. package/dist/lib.esm/connectors/base-evm-connector/baseEvmConnector.js +43 -24
  66. package/dist/lib.esm/connectors/base-solana-connector/baseSolanaConnector.js +43 -26
  67. package/dist/lib.esm/connectors/coinbase-connector/coinbaseConnector.js +2 -2
  68. package/dist/lib.esm/connectors/injected-evm-connector/injectedEvmConnector.js +2 -2
  69. package/dist/lib.esm/connectors/injected-solana-connector/walletStandardConnector.js +3 -3
  70. package/dist/lib.esm/connectors/metamask-connector/metamaskConnector.js +80 -49
  71. package/dist/lib.esm/connectors/wallet-connect-v2-connector/WalletConnectV2Provider.js +2 -2
  72. package/dist/lib.esm/connectors/wallet-connect-v2-connector/walletConnectV2Connector.js +43 -15
  73. package/dist/lib.esm/connectors/wallet-connect-v2-connector/wcSolanaWallet.js +1 -1
  74. package/dist/lib.esm/index.js +4 -3
  75. package/dist/lib.esm/noModal.js +851 -126
  76. package/dist/lib.esm/plugins/wallet-services-plugin/plugin.js +3 -3
  77. package/dist/lib.esm/providers/base-provider/baseProvider.js +68 -38
  78. package/dist/lib.esm/react/context/useWeb3AuthInnerContextValue.js +45 -21
  79. package/dist/lib.esm/react/hooks/useWallets.js +33 -0
  80. package/dist/lib.esm/react/hooks/useWeb3AuthConnect.js +2 -2
  81. package/dist/lib.esm/react/index.js +1 -0
  82. package/dist/lib.esm/react/solana/hooks/useSolanaWallet.js +2 -2
  83. package/dist/lib.esm/react/solana/provider.js +9 -2
  84. package/dist/lib.esm/react/wagmi/provider.js +39 -7
  85. package/dist/lib.esm/vue/composables/useCheckout.js +1 -1
  86. package/dist/lib.esm/vue/composables/useFunding.js +1 -1
  87. package/dist/lib.esm/vue/composables/useReceive.js +1 -1
  88. package/dist/lib.esm/vue/composables/useSwap.js +1 -1
  89. package/dist/lib.esm/vue/composables/useWalletConnectScanner.js +1 -1
  90. package/dist/lib.esm/vue/composables/useWalletUI.js +1 -1
  91. package/dist/lib.esm/vue/composables/useWallets.js +35 -0
  92. package/dist/lib.esm/vue/composables/useWeb3AuthConnect.js +2 -2
  93. package/dist/lib.esm/vue/index.js +1 -0
  94. package/dist/lib.esm/vue/solana/composables/useSignAndSendTransaction.js +1 -1
  95. package/dist/lib.esm/vue/solana/composables/useSignMessage.js +1 -1
  96. package/dist/lib.esm/vue/solana/composables/useSignTransaction.js +1 -1
  97. package/dist/lib.esm/vue/solana/composables/useSolanaWallet.js +2 -2
  98. package/dist/lib.esm/vue/solana/provider.js +51 -24
  99. package/dist/lib.esm/vue/useWeb3AuthInnerContextValue.js +12 -3
  100. package/dist/lib.esm/vue/wagmi/provider.js +36 -8
  101. package/package.json +44 -20
@@ -6,23 +6,24 @@ import { SMART_ACCOUNT_EIP_STANDARD, EIP7702_SUPPORTED_SMART_ACCOUNT_TYPES } fro
6
6
  import { SafeEventEmitter, serializeError, UX_MODE, cloneDeep, CookieStorage, LocalStorageAdapter, MemoryStorage } from '@web3auth/auth';
7
7
  import deepmerge from 'deepmerge';
8
8
  import { deserialize } from './base/deserialize.js';
9
+ import { WalletInitializationError, WalletLoginError, AccountLinkingError } from './base/errors/index.js';
9
10
  import { LOGIN_MODE, SMART_ACCOUNT_WALLET_SCOPE, WEB3AUTH_STATE_STORAGE_KEY } from './base/constants.js';
11
+ import { log } from './base/loglevel.js';
10
12
  import { CONNECTOR_STATUS, CONNECTOR_INITIAL_AUTHENTICATION_MODE, CONNECTOR_EVENTS } from './base/connector/constants.js';
11
13
  import { Analytics, ANALYTICS_INTEGRATION_TYPE, ANALYTICS_SDK_TYPE, ANALYTICS_EVENTS } from './base/analytics.js';
12
- import { sdkVersion, fetchProjectConfig, withAbort, getErrorAnalyticsProperties, getCaipChainId, isHexStrict, getHostname, getWhitelabelAnalyticsProperties, getAaAnalyticsProperties, getWalletServicesAnalyticsProperties, isBrowser } from './base/utils.js';
14
+ import { sdkVersion, fetchProjectConfig, withAbort, getErrorAnalyticsProperties, getCaipChainId, isHexStrict, getHostname, getWhitelabelAnalyticsProperties, getAaAnalyticsProperties, getWalletServicesAnalyticsProperties, isBrowser, parseChainNamespaceFromCitadelResponse, normalizeWalletName } from './base/utils.js';
15
+ import { WALLET_CONNECTORS } from './base/wallet/index.js';
16
+ import { CONNECTOR_NAMESPACES } from './base/chain/IChainInterface.js';
13
17
  import { CONNECTED_STATUSES, CAN_LOGOUT_STATUSES, CAN_AUTHORIZE_STATUSES } from './base/connector/connectorStatus.js';
18
+ import { assertAuthConnector, authConnector, isAuthConnector } from './connectors/auth-connector/authConnector.js';
14
19
  import { CommonJRPCProvider } from './providers/base-provider/CommonJRPCProvider.js';
15
- import { authConnector } from './connectors/auth-connector/authConnector.js';
16
20
  import { walletServicesPlugin } from './plugins/wallet-services-plugin/plugin.js';
17
- import { storageAvailable } from './base/connector/utils.js';
18
21
  import { metaMaskConnector } from './connectors/metamask-connector/metamaskConnector.js';
19
- import { WalletInitializationError, WalletLoginError } from './base/errors/index.js';
20
- import { log } from './base/loglevel.js';
21
- import { WALLET_CONNECTORS } from './base/wallet/index.js';
22
- import { CONNECTOR_NAMESPACES } from './base/chain/IChainInterface.js';
22
+ import { storageAvailable } from './base/connector/utils.js';
23
23
  import { PLUGIN_STATUS, PLUGIN_NAMESPACES } from './base/plugin/IPlugin.js';
24
24
 
25
25
  const _excluded = ["walletScope", "eipStandard"];
26
+ const PRIMARY_CONNECTED_WALLET_KEY = "__primary__";
26
27
  class Web3AuthNoModal extends SafeEventEmitter {
27
28
  constructor(options, initialState) {
28
29
  super();
@@ -35,16 +36,20 @@ class Web3AuthNoModal extends SafeEventEmitter {
35
36
  _defineProperty(this, "analytics", void 0);
36
37
  _defineProperty(this, "plugins", {});
37
38
  _defineProperty(this, "consentRequired", false);
39
+ _defineProperty(this, "projectConfig", null);
38
40
  _defineProperty(this, "storage", void 0);
39
- _defineProperty(this, "currentConnection", null);
40
- _defineProperty(this, "currentConnectionReconnected", false);
41
+ _defineProperty(this, "connectionReconnected", false);
42
+ /** Connected wallet state keyed by linked account id; the primary session uses a reserved key. */
43
+ _defineProperty(this, "connectedWalletConnectorMap", new Map());
44
+ _defineProperty(this, "activeWalletConnectorKey", PRIMARY_CONNECTED_WALLET_KEY);
41
45
  _defineProperty(this, "state", {
42
- connectedConnectorName: null,
46
+ primaryConnectorName: null,
43
47
  cachedConnector: null,
44
48
  currentChainId: null,
45
49
  idToken: null,
46
50
  accessToken: null,
47
- refreshToken: null
51
+ refreshToken: null,
52
+ activeAccount: null
48
53
  });
49
54
  if (!options.clientId) throw WalletInitializationError.invalidParams("Please provide a valid clientId in constructor");
50
55
  if (options.enableLogging) log.enableAll();else log.setLevel("error");
@@ -52,6 +57,9 @@ class Web3AuthNoModal extends SafeEventEmitter {
52
57
  this.coreOptions = options;
53
58
  this.storage = this.getStorageMethod();
54
59
  this.analytics = new Analytics();
60
+ if (options.disableAnalytics) {
61
+ this.analytics.disable();
62
+ }
55
63
  this.analytics.setGlobalProperties({
56
64
  integration_type: ANALYTICS_INTEGRATION_TYPE.NATIVE_SDK
57
65
  });
@@ -68,13 +76,13 @@ class Web3AuthNoModal extends SafeEventEmitter {
68
76
  return (_this$coreOptions$cha = this.coreOptions.chains) === null || _this$coreOptions$cha === void 0 ? void 0 : _this$coreOptions$cha.find(chain => chain.chainId === this.currentChainId);
69
77
  }
70
78
  get connected() {
71
- return Boolean(this.connectedConnector);
79
+ return Boolean(this.primaryConnector);
72
80
  }
73
81
  get connection() {
74
- return this.currentConnection;
82
+ return this.getConnectedWalletConnectionByKey(this.activeWalletConnectorKey);
75
83
  }
76
- get connectedConnectorName() {
77
- return this.state.connectedConnectorName;
84
+ get primaryConnectorName() {
85
+ return this.state.primaryConnectorName;
78
86
  }
79
87
  get cachedConnector() {
80
88
  return this.state.cachedConnector;
@@ -83,9 +91,13 @@ class Web3AuthNoModal extends SafeEventEmitter {
83
91
  var _this$coreOptions$cha2;
84
92
  return this.state.currentChainId || this.coreOptions.defaultChainId || ((_this$coreOptions$cha2 = this.coreOptions.chains) === null || _this$coreOptions$cha2 === void 0 || (_this$coreOptions$cha2 = _this$coreOptions$cha2[0]) === null || _this$coreOptions$cha2 === void 0 ? void 0 : _this$coreOptions$cha2.chainId) || null;
85
93
  }
86
- get connectedConnector() {
94
+
95
+ /**
96
+ * This is always the primary connector that is connected to the user.
97
+ */
98
+ get primaryConnector() {
87
99
  var _this$currentChain;
88
- return this.getConnector(this.connectedConnectorName, (_this$currentChain = this.currentChain) === null || _this$currentChain === void 0 ? void 0 : _this$currentChain.chainNamespace);
100
+ return this.getConnector(this.primaryConnectorName, (_this$currentChain = this.currentChain) === null || _this$currentChain === void 0 ? void 0 : _this$currentChain.chainNamespace);
89
101
  }
90
102
  get accountAbstractionProvider() {
91
103
  return this.aaProvider;
@@ -93,6 +105,29 @@ class Web3AuthNoModal extends SafeEventEmitter {
93
105
  get idToken() {
94
106
  return this.state.idToken || null;
95
107
  }
108
+ get accessToken() {
109
+ return this.state.accessToken || null;
110
+ }
111
+ get refreshToken() {
112
+ return this.state.refreshToken || null;
113
+ }
114
+ get activeAccount() {
115
+ return this.state.activeAccount;
116
+ }
117
+
118
+ /**
119
+ * This is the current active connector.
120
+ */
121
+ get activeConnector() {
122
+ const activeConnectedWallet = this.getConnectedWalletConnectorStateByKey(this.activeWalletConnectorKey);
123
+ if (activeConnectedWallet) {
124
+ return activeConnectedWallet.connector;
125
+ }
126
+ if (this.activeWalletConnectorKey !== PRIMARY_CONNECTED_WALLET_KEY) {
127
+ throw new Error(`Signing connector not found for account "${this.activeWalletConnectorKey}".`);
128
+ }
129
+ return this.primaryConnector;
130
+ }
96
131
  set provider(_) {
97
132
  throw new Error("Not implemented");
98
133
  }
@@ -135,6 +170,7 @@ class Web3AuthNoModal extends SafeEventEmitter {
135
170
  }
136
171
 
137
172
  // init config
173
+ this.projectConfig = projectConfig;
138
174
  this.initAccountAbstractionConfig(projectConfig);
139
175
  this.initChainsConfig(projectConfig);
140
176
  await this.initCachedConnectorAndChainId();
@@ -206,13 +242,17 @@ class Web3AuthNoModal extends SafeEventEmitter {
206
242
  }) || null;
207
243
  }
208
244
  async clearCache() {
245
+ this.connectedWalletConnectorMap.clear();
246
+ this.activeWalletConnectorKey = PRIMARY_CONNECTED_WALLET_KEY;
247
+ this.connectionReconnected = false;
209
248
  await this.setState({
210
- connectedConnectorName: null,
249
+ primaryConnectorName: null,
211
250
  cachedConnector: null,
212
251
  currentChainId: null,
213
252
  idToken: null,
214
253
  accessToken: null,
215
254
  refreshToken: null,
255
+ activeAccount: null,
216
256
  hasUserConsent: undefined
217
257
  });
218
258
  }
@@ -226,14 +266,16 @@ class Web3AuthNoModal extends SafeEventEmitter {
226
266
  if (params.chainId === ((_this$currentChain2 = this.currentChain) === null || _this$currentChain2 === void 0 ? void 0 : _this$currentChain2.chainId)) return;
227
267
  const newChainConfig = this.coreOptions.chains.find(x => x.chainId === params.chainId);
228
268
  if (!newChainConfig) throw WalletInitializationError.invalidParams("Invalid chainId");
229
- if (CONNECTED_STATUSES.includes(this.status) && this.connectedConnector) {
230
- var _this$currentChain3;
269
+ if (CONNECTED_STATUSES.includes(this.status)) {
270
+ const activeConnector = this.activeConnector;
271
+ if (!activeConnector) throw WalletInitializationError.notReady("Active signing connector is not ready");
272
+
231
273
  // Single-namespace connectors cannot cross namespace boundaries — MULTICHAIN connectors
232
274
  // (Auth, WC) enforce their own switchChain policy internally.
233
- if (this.connectedConnector.connectorNamespace !== CONNECTOR_NAMESPACES.MULTICHAIN && ((_this$currentChain3 = this.currentChain) === null || _this$currentChain3 === void 0 ? void 0 : _this$currentChain3.chainNamespace) !== newChainConfig.chainNamespace) {
234
- throw WalletLoginError.connectionError(`Cannot switch between chain namespaces with ${this.connectedConnector.name}. Disconnect and reconnect with the target chain.`);
275
+ if (activeConnector.connectorNamespace !== CONNECTOR_NAMESPACES.MULTICHAIN && activeConnector.connectorNamespace !== newChainConfig.chainNamespace) {
276
+ throw WalletLoginError.connectionError(`Cannot switch between chain namespaces with ${activeConnector.name}. Disconnect and reconnect with the target chain.`);
235
277
  }
236
- await this.connectedConnector.switchChain(params);
278
+ await activeConnector.switchChain(params);
237
279
  return;
238
280
  }
239
281
  if (this.commonJRPCProvider) {
@@ -321,7 +363,7 @@ class Web3AuthNoModal extends SafeEventEmitter {
321
363
  const completeConnection = async () => {
322
364
  try {
323
365
  // track connection completed event
324
- const userInfo = await connector.getUserInfo();
366
+ const userInfo = await this.getUserInfo();
325
367
  this.analytics.track(ANALYTICS_EVENTS.CONNECTION_COMPLETED, _objectSpread(_objectSpread({}, eventData), {}, {
326
368
  is_mfa_enabled: userInfo === null || userInfo === void 0 ? void 0 : userInfo.isMfaEnabled,
327
369
  duration: Date.now() - startTime
@@ -361,28 +403,60 @@ class Web3AuthNoModal extends SafeEventEmitter {
361
403
  async logout(options = {
362
404
  cleanup: false
363
405
  }) {
364
- if (!CAN_LOGOUT_STATUSES.includes(this.status) || !this.connectedConnector) throw WalletLoginError.notConnectedError(`No wallet is connected`);
365
- if (this.connectedConnector.status === CONNECTOR_STATUS.DISCONNECTING) return;
366
- await this.connectedConnector.disconnect(options);
406
+ if (!CAN_LOGOUT_STATUSES.includes(this.status) || !this.primaryConnector) throw WalletLoginError.notConnectedError(`No wallet is connected`);
407
+ if (this.primaryConnector.status === CONNECTOR_STATUS.DISCONNECTING) return;
408
+ await this.primaryConnector.disconnect(options);
367
409
  }
368
410
  async getUserInfo() {
369
- var _this$connectedConnec;
370
- log.debug("Getting user info", this.status, (_this$connectedConnec = this.connectedConnector) === null || _this$connectedConnec === void 0 ? void 0 : _this$connectedConnec.name);
371
- if (!CAN_AUTHORIZE_STATUSES.includes(this.status) || !this.connectedConnector) throw WalletLoginError.notConnectedError(`No wallet is connected`);
372
- return this.connectedConnector.getUserInfo();
411
+ var _this$primaryConnecto, _userInfo$linkedAccou, _userInfo$linkedAccou2;
412
+ log.debug("Getting user info", this.status, (_this$primaryConnecto = this.primaryConnector) === null || _this$primaryConnecto === void 0 ? void 0 : _this$primaryConnecto.name);
413
+ if (!CAN_AUTHORIZE_STATUSES.includes(this.status) || !this.primaryConnector) throw WalletLoginError.notConnectedError(`No wallet is connected`);
414
+ const userInfo = await this.primaryConnector.getUserInfo();
415
+ const linkedAccounts = (_userInfo$linkedAccou = (_userInfo$linkedAccou2 = userInfo.linkedAccounts) === null || _userInfo$linkedAccou2 === void 0 ? void 0 : _userInfo$linkedAccou2.map(account => _objectSpread(_objectSpread({}, account), {}, {
416
+ active: this.state.activeAccount ? account.id === this.state.activeAccount.id : account.isPrimary
417
+ }))) !== null && _userInfo$linkedAccou !== void 0 ? _userInfo$linkedAccou : [];
418
+ this.syncConnectedWalletLinkedAccounts(linkedAccounts);
419
+ return _objectSpread(_objectSpread({}, userInfo), {}, {
420
+ linkedAccounts
421
+ });
422
+ }
423
+ async getLinkedAccounts() {
424
+ if (!CAN_AUTHORIZE_STATUSES.includes(this.status) || !this.primaryConnector) throw WalletLoginError.notConnectedError(`No wallet is connected`);
425
+ assertAuthConnector(this.primaryConnector, "Linked accounts can only be fetched when connected with the AUTH connector.");
426
+ const linkedAccounts = await this.primaryConnector.getLinkedAccounts();
427
+ const resolvedLinkedAccounts = linkedAccounts.map(account => _objectSpread(_objectSpread({}, account), {}, {
428
+ active: this.state.activeAccount ? account.id === this.state.activeAccount.id : account.isPrimary
429
+ }));
430
+ this.syncConnectedWalletLinkedAccounts(resolvedLinkedAccounts);
431
+ return resolvedLinkedAccounts;
432
+ }
433
+ getConnectedAccountsWithProviders() {
434
+ if (!CONNECTED_STATUSES.includes(this.status) || !this.primaryConnector) throw WalletLoginError.notConnectedError(`No wallet is connected`);
435
+ if (this.status !== CONNECTOR_STATUS.AUTHORIZED) {
436
+ // before the wallet is authorized, we don't have the user info, so we return an empty array
437
+ return [];
438
+ }
439
+ const connectedAccounts = [];
440
+ for (const [, value] of this.connectedWalletConnectorMap.entries()) {
441
+ const hasWalletProvider = Boolean(value.signingProvider || value.solanaWallet);
442
+ if (hasWalletProvider && this.hasUsableConnectedSwitchConnector(value.connector)) {
443
+ connectedAccounts.push(value);
444
+ }
445
+ }
446
+ return connectedAccounts;
373
447
  }
374
448
  async enableMFA(loginParams) {
375
449
  var _authConnector$authIn2;
376
- if (!CONNECTED_STATUSES.includes(this.status) || !this.connectedConnector) throw WalletLoginError.notConnectedError(`No wallet is connected`);
377
- if (this.connectedConnector.name !== WALLET_CONNECTORS.AUTH) throw WalletLoginError.unsupportedOperation(`EnableMFA is not supported for this connector.`);
378
- const authConnector = this.connectedConnector;
450
+ if (!CONNECTED_STATUSES.includes(this.status) || !this.primaryConnector) throw WalletLoginError.notConnectedError(`No wallet is connected`);
451
+ if (this.primaryConnector.name !== WALLET_CONNECTORS.AUTH) throw WalletLoginError.unsupportedOperation(`EnableMFA is not supported for this connector.`);
452
+ const authConnector = this.primaryConnector;
379
453
  const trackData = {
380
- connector: this.connectedConnector.name,
454
+ connector: this.primaryConnector.name,
381
455
  auth_ux_mode: (_authConnector$authIn2 = authConnector.authInstance) === null || _authConnector$authIn2 === void 0 || (_authConnector$authIn2 = _authConnector$authIn2.options) === null || _authConnector$authIn2 === void 0 ? void 0 : _authConnector$authIn2.uxMode
382
456
  };
383
457
  try {
384
458
  this.analytics.track(ANALYTICS_EVENTS.MFA_ENABLEMENT_STARTED, trackData);
385
- await this.connectedConnector.enableMFA(loginParams);
459
+ await this.primaryConnector.enableMFA(loginParams);
386
460
  } catch (error) {
387
461
  this.analytics.track(ANALYTICS_EVENTS.MFA_ENABLEMENT_FAILED, _objectSpread(_objectSpread({}, trackData), getErrorAnalyticsProperties(error)));
388
462
  throw error;
@@ -390,29 +464,29 @@ class Web3AuthNoModal extends SafeEventEmitter {
390
464
  }
391
465
  async manageMFA(loginParams) {
392
466
  var _authConnector$authIn3;
393
- if (!CONNECTED_STATUSES.includes(this.status) || !this.connectedConnector) throw WalletLoginError.notConnectedError(`No wallet is connected`);
394
- if (this.connectedConnector.name !== WALLET_CONNECTORS.AUTH) throw WalletLoginError.unsupportedOperation(`ManageMFA is not supported for this connector.`);
395
- const authConnector = this.connectedConnector;
467
+ if (!CONNECTED_STATUSES.includes(this.status) || !this.primaryConnector) throw WalletLoginError.notConnectedError(`No wallet is connected`);
468
+ if (this.primaryConnector.name !== WALLET_CONNECTORS.AUTH) throw WalletLoginError.unsupportedOperation(`ManageMFA is not supported for this connector.`);
469
+ const authConnector = this.primaryConnector;
396
470
  const trackData = {
397
- connector: this.connectedConnector.name,
471
+ connector: this.primaryConnector.name,
398
472
  auth_ux_mode: (_authConnector$authIn3 = authConnector.authInstance) === null || _authConnector$authIn3 === void 0 || (_authConnector$authIn3 = _authConnector$authIn3.options) === null || _authConnector$authIn3 === void 0 ? void 0 : _authConnector$authIn3.uxMode
399
473
  };
400
474
  try {
401
475
  this.analytics.track(ANALYTICS_EVENTS.MFA_MANAGEMENT_SELECTED, trackData);
402
- await this.connectedConnector.manageMFA(loginParams);
476
+ await this.primaryConnector.manageMFA(loginParams);
403
477
  } catch (error) {
404
478
  this.analytics.track(ANALYTICS_EVENTS.MFA_MANAGEMENT_FAILED, _objectSpread(_objectSpread({}, trackData), getErrorAnalyticsProperties(error)));
405
479
  throw error;
406
480
  }
407
481
  }
408
482
  async getAuthTokenInfo() {
409
- if (!CAN_AUTHORIZE_STATUSES.includes(this.status) || !this.connectedConnector) throw WalletLoginError.notConnectedError(`No wallet is connected`);
483
+ if (!CAN_AUTHORIZE_STATUSES.includes(this.status) || !this.primaryConnector) throw WalletLoginError.notConnectedError(`No wallet is connected`);
410
484
  const trackData = {
411
- connector: this.connectedConnector.name
485
+ connector: this.primaryConnector.name
412
486
  };
413
487
  try {
414
488
  this.analytics.track(ANALYTICS_EVENTS.IDENTITY_TOKEN_STARTED, trackData);
415
- const authTokenInfo = await this.connectedConnector.getAuthTokenInfo();
489
+ const authTokenInfo = await this.primaryConnector.getAuthTokenInfo();
416
490
  this.analytics.track(ANALYTICS_EVENTS.IDENTITY_TOKEN_COMPLETED, trackData);
417
491
  return {
418
492
  idToken: authTokenInfo.idToken
@@ -425,6 +499,76 @@ class Web3AuthNoModal extends SafeEventEmitter {
425
499
  getPlugin(name) {
426
500
  return this.plugins[name] || null;
427
501
  }
502
+ async switchAccount(account) {
503
+ const authConnector = this.getMainAuthConnector();
504
+ const switchResult = await authConnector.switchAccount(account, {
505
+ activeAccount: this.state.activeAccount,
506
+ currentChainId: this.currentChainId
507
+ });
508
+ if (!switchResult) {
509
+ return;
510
+ }
511
+ try {
512
+ var _this$projectConfig;
513
+ await this.processSwitchAccountResult(authConnector, switchResult, {
514
+ projectConfig: (_this$projectConfig = this.projectConfig) !== null && _this$projectConfig !== void 0 ? _this$projectConfig : undefined
515
+ });
516
+ await authConnector.trackSwitchAccountCompleted(switchResult.targetAccount);
517
+ } catch (error) {
518
+ await authConnector.trackSwitchAccountFailed(switchResult.targetAccount, error);
519
+ throw error;
520
+ }
521
+ }
522
+ async linkAccount(params) {
523
+ if (!(params !== null && params !== void 0 && params.connectorName)) {
524
+ throw WalletInitializationError.invalidParams("connectorName is required when calling linkAccount on the no-modal SDK");
525
+ }
526
+ const chainId = this.resolveLinkAccountChainId(params.chainId);
527
+ const isolatedConnector = await this.createLinkingWalletConnector(params.connectorName, chainId);
528
+ return this.linkAccountWithConnector(params.connectorName, chainId, isolatedConnector);
529
+ }
530
+ async unlinkAccount(address) {
531
+ var _await$authConnector$, _this$state$activeAcc;
532
+ const authConnector = this.getMainAuthConnector();
533
+ const linkedAccounts = (_await$authConnector$ = (await authConnector.getUserInfo()).linkedAccounts) !== null && _await$authConnector$ !== void 0 ? _await$authConnector$ : [];
534
+ const targetAccount = this.findLinkedAccountByAddress(linkedAccounts, address);
535
+ if (!targetAccount) {
536
+ throw AccountLinkingError.accountNotLinked(`Account with address "${address}" is not linked`);
537
+ }
538
+ if (targetAccount.connector === WALLET_CONNECTORS.AUTH || targetAccount.isPrimary) {
539
+ throw AccountLinkingError.cannotUnlinkPrimaryAccount();
540
+ }
541
+ if (((_this$state$activeAcc = this.state.activeAccount) === null || _this$state$activeAcc === void 0 ? void 0 : _this$state$activeAcc.id) === targetAccount.id) {
542
+ throw AccountLinkingError.cannotUnlinkActiveAccount();
543
+ }
544
+ const result = await authConnector.unlinkAccount({
545
+ address,
546
+ authSessionTokens: {
547
+ accessToken: this.accessToken,
548
+ idToken: this.idToken
549
+ }
550
+ });
551
+ await this.setState({
552
+ idToken: result.idToken
553
+ });
554
+
555
+ // disconnect the connector for unlinked account
556
+ const connectorToDisconnect = this.getConnectedWalletConnector(targetAccount);
557
+ if (connectorToDisconnect) {
558
+ try {
559
+ if (connectorToDisconnect.connected) {
560
+ await connectorToDisconnect.disconnect({
561
+ cleanup: true
562
+ });
563
+ }
564
+ } catch (error) {
565
+ log.debug(`Failed to disconnect linked account "${targetAccount.id}" during unlink`, error);
566
+ } finally {
567
+ this.deleteConnectedWalletConnector(targetAccount);
568
+ }
569
+ }
570
+ return result;
571
+ }
428
572
  setAnalyticsProperties(properties) {
429
573
  this.analytics.setGlobalProperties(properties);
430
574
  }
@@ -762,23 +906,25 @@ class Web3AuthNoModal extends SafeEventEmitter {
762
906
  }
763
907
  subscribeToConnectorEvents(connector) {
764
908
  connector.on(CONNECTOR_EVENTS.CONNECTED, async data => {
909
+ if (this.primaryConnectorName && this.primaryConnectorName !== data.connectorName) {
910
+ // Ignore registered connectors that are not the active primary session connector.
911
+ return;
912
+ }
765
913
  if (!this.commonJRPCProvider) throw WalletInitializationError.notFound(`CommonJrpcProvider not found`);
766
914
  const {
767
915
  ethereumProvider,
768
916
  solanaWallet
769
917
  } = data;
770
- const isSolanaOnly = connector.connectorNamespace === CHAIN_NAMESPACES.SOLANA;
771
-
772
- // Set connection and consent status SYNCHRONOUSLY before any await so the
773
- // AUTHORIZED handler (which may fire during async work below) can detect the
774
- // consent-required state. Create a deferred promise the AUTHORIZED handler
775
- // will await to ensure consent userId + pre-approval are resolved first.
776
- this.currentConnection = {
777
- ethereumProvider: isSolanaOnly ? null : ethereumProvider ? this.commonJRPCProvider : null,
778
- solanaWallet: solanaWallet !== null && solanaWallet !== void 0 ? solanaWallet : null,
779
- connectorName: data.connectorName
780
- };
781
- this.currentConnectionReconnected = data.reconnected;
918
+ // Seed the primary connector synchronously so AUTHORIZED can resolve a connection
919
+ // even while we are still restoring a previously active linked wallet.
920
+ this.setConnectedWalletConnectorState(this.buildImmediateConnectedWalletConnectorState({
921
+ connector,
922
+ ethereumProvider,
923
+ solanaWallet,
924
+ usePrimaryProxy: true
925
+ }));
926
+ this.setActiveWalletConnectorKey();
927
+ this.connectionReconnected = data.reconnected;
782
928
 
783
929
  // when ssr is enabled, we need to get the idToken from the connector.
784
930
  if (this.coreOptions.ssr) {
@@ -793,74 +939,119 @@ class Web3AuthNoModal extends SafeEventEmitter {
793
939
  });
794
940
  } catch (error) {
795
941
  log.error(error);
796
- this.currentConnection = null;
942
+ this.deleteConnectedWalletConnector();
943
+ this.setActiveWalletConnectorKey();
797
944
  this.status = CONNECTOR_STATUS.ERRORED;
798
945
  this.emit(CONNECTOR_EVENTS.ERRORED, error, this.loginMode);
799
946
  return;
800
947
  }
801
948
  }
949
+ // The following block only hits during rehydration
802
950
 
803
- // setup AA provider if AA is enabled (skip for EIP-7702; 7702 uses EOA + 5792/7702 RPC only)
804
- if (ethereumProvider) {
805
- var _this$currentChain4, _accountAbstractionCo;
806
- let finalProvider = (ethereumProvider === null || ethereumProvider === void 0 ? void 0 : ethereumProvider.provider) || ethereumProvider;
807
- const {
808
- accountAbstractionConfig
809
- } = this.coreOptions;
810
- const is7702 = (accountAbstractionConfig === null || accountAbstractionConfig === void 0 ? void 0 : accountAbstractionConfig.smartAccountEipStandard) === SMART_ACCOUNT_EIP_STANDARD["EIP_7702"];
811
- const isAaSupportedForCurrentChain = ((_this$currentChain4 = this.currentChain) === null || _this$currentChain4 === void 0 ? void 0 : _this$currentChain4.chainNamespace) === CHAIN_NAMESPACES.EIP155 && (accountAbstractionConfig === null || accountAbstractionConfig === void 0 || (_accountAbstractionCo = accountAbstractionConfig.chains) === null || _accountAbstractionCo === void 0 ? void 0 : _accountAbstractionCo.some(chain => {
812
- var _this$currentChain5;
813
- return chain.chainId === ((_this$currentChain5 = this.currentChain) === null || _this$currentChain5 === void 0 ? void 0 : _this$currentChain5.chainId);
814
- }));
815
- if (!is7702 && isAaSupportedForCurrentChain && (data.connectorName === WALLET_CONNECTORS.AUTH || this.coreOptions.useAAWithExternalWallet)) {
816
- var _accountAbstractionCo2;
817
- const {
818
- accountAbstractionProvider,
819
- toEoaProvider
820
- } = await import('./providers/account-abstraction-provider/index.js');
821
- // for embedded wallets, we use ws-embed provider which is AA provider, need to derive EOA provider
822
- const eoaProvider = data.connectorName === WALLET_CONNECTORS.AUTH ? await toEoaProvider(ethereumProvider) : ethereumProvider;
823
- const aaChainIds = new Set((accountAbstractionConfig === null || accountAbstractionConfig === void 0 || (_accountAbstractionCo2 = accountAbstractionConfig.chains) === null || _accountAbstractionCo2 === void 0 ? void 0 : _accountAbstractionCo2.map(chain => chain.chainId)) || []);
824
- const aaProvider = await accountAbstractionProvider({
825
- accountAbstractionConfig,
826
- provider: eoaProvider,
827
- chain: this.currentChain,
828
- chains: this.coreOptions.chains.filter(chain => aaChainIds.has(chain.chainId)),
829
- useProviderAsTransport: data.connectorName === WALLET_CONNECTORS.AUTH
951
+ const {
952
+ activeAccount,
953
+ currentChainId
954
+ } = this.state;
955
+ // if the active account is not the primary account, i.e. not `null`, create an isolated connector and connect to the chain
956
+ if (activeAccount && !activeAccount.isPrimary && activeAccount.connector !== WALLET_CONNECTORS.AUTH) {
957
+ var _ref3, _walletConnector$prov, _linkedAccountConnect, _ref4, _walletConnector$sola, _linkedAccountConnect2;
958
+ const accountLinkingConnector = isAuthConnector(connector) ? connector : this.getConnector(WALLET_CONNECTORS.AUTH);
959
+ assertAuthConnector(accountLinkingConnector, "Account switching requires the AUTH connector to be available.");
960
+ const targetChainId = accountLinkingConnector.getChainIdForLinkedAccount(activeAccount, currentChainId);
961
+ const walletConnector = await this.createIsolatedWalletConnector(activeAccount.connector, targetChainId);
962
+ let linkedAccountConnection = null;
963
+ if (!this.hasUsableConnectedSwitchConnector(walletConnector)) {
964
+ linkedAccountConnection = await walletConnector.connect({
965
+ chainId: targetChainId
830
966
  });
831
- this.aaProvider = aaProvider;
832
-
833
- // if external wallet is used and AA is enabled for external wallets, use AA provider
834
- // for embedded wallets, we use ws-embed provider which already supports AA
835
- if (data.connectorName !== WALLET_CONNECTORS.AUTH && this.coreOptions.useAAWithExternalWallet) {
836
- finalProvider = this.aaProvider;
967
+ if (!linkedAccountConnection) {
968
+ throw AccountLinkingError.requestFailed(`Failed to connect isolated connector "${activeAccount.connector}" for account switch.`);
837
969
  }
838
970
  }
839
- this.commonJRPCProvider.updateProviderEngineProxy(finalProvider);
971
+ const connectedWalletState = await this.resolveConnectedWalletConnectorState({
972
+ connector: walletConnector,
973
+ ethereumProvider: (_ref3 = (_walletConnector$prov = walletConnector.provider) !== null && _walletConnector$prov !== void 0 ? _walletConnector$prov : (_linkedAccountConnect = linkedAccountConnection) === null || _linkedAccountConnect === void 0 ? void 0 : _linkedAccountConnect.ethereumProvider) !== null && _ref3 !== void 0 ? _ref3 : null,
974
+ solanaWallet: (_ref4 = (_walletConnector$sola = walletConnector.solanaWallet) !== null && _walletConnector$sola !== void 0 ? _walletConnector$sola : (_linkedAccountConnect2 = linkedAccountConnection) === null || _linkedAccountConnect2 === void 0 ? void 0 : _linkedAccountConnect2.solanaWallet) !== null && _ref4 !== void 0 ? _ref4 : null,
975
+ usePrimaryProxy: false,
976
+ account: activeAccount
977
+ });
978
+ this.setConnectedWalletConnectorState(connectedWalletState, activeAccount);
979
+ this.setActiveWalletConnectorKey(activeAccount);
980
+ }
981
+ if (ethereumProvider) {
982
+ await this.bindPrimaryEthereumSigningProxy(ethereumProvider, data.connectorName);
840
983
  }
984
+ const primaryConnectedWalletState = await this.resolveConnectedWalletConnectorState({
985
+ connector,
986
+ ethereumProvider,
987
+ solanaWallet,
988
+ usePrimaryProxy: true
989
+ });
990
+ this.setConnectedWalletConnectorState(primaryConnectedWalletState);
841
991
  await this.setState({
842
- connectedConnectorName: data.connectorName
992
+ primaryConnectorName: data.connectorName
843
993
  });
844
994
  this.cacheWallet(data.connectorName);
845
995
  const isConnectAndSign = this.coreOptions.initialAuthenticationMode === CONNECTOR_INITIAL_AUTHENTICATION_MODE.CONNECT_AND_SIGN;
846
- if (this.consentRequired && !isConnectAndSign && !this.state.hasUserConsent) {
996
+ const pendingUserConsent = this.consentRequired && !this.state.hasUserConsent;
997
+ if (pendingUserConsent && !isConnectAndSign) {
847
998
  this.status = CONNECTOR_STATUS.CONSENT_REQUIRING;
848
999
  this.emit(CONNECTOR_EVENTS.CONSENT_REQUIRING);
849
- log.debug("consent_requiring", this.status, this.connectedConnectorName);
1000
+ log.debug("consent_requiring", this.status, this.primaryConnectorName);
850
1001
  } else {
851
- this.status = CONNECTOR_STATUS.CONNECTED;
852
- log.debug("connected", this.status, this.connectedConnectorName);
853
- this.connectToPlugins(_objectSpread(_objectSpread({}, data), {}, {
854
- connector: data.connectorName
855
- }));
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
+ }
1009
+ log.debug("connected", this.status, this.primaryConnectorName);
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.
856
1019
  this.emit(CONNECTOR_EVENTS.CONNECTED, _objectSpread(_objectSpread({}, data), {}, {
857
- loginMode: this.loginMode
1020
+ loginMode: this.loginMode,
1021
+ pendingUserConsent
858
1022
  }));
859
1023
  }
860
1024
  });
861
- connector.on(CONNECTOR_EVENTS.DISCONNECTED, async () => {
862
- this.currentConnection = null;
863
- this.currentConnectionReconnected = false;
1025
+ connector.on(CONNECTOR_EVENTS.DISCONNECTED, async data => {
1026
+ if (this.shouldIgnoreInactiveConnectorEvent(connector, CONNECTOR_EVENTS.DISCONNECTED)) return;
1027
+ const disconnectedConnector = data === null || data === void 0 ? void 0 : data.connector;
1028
+ const {
1029
+ activeAccount
1030
+ } = this.state;
1031
+ if (!activeAccount || activeAccount && activeAccount.isPrimary || disconnectedConnector === WALLET_CONNECTORS.AUTH) {
1032
+ // If the primary session disconnects, tear down every other connected wallet connector
1033
+ // and clear the entire map.
1034
+ await Promise.all(Array.from(this.connectedWalletConnectorMap.entries()).map(async ([accountId, connectedWallet]) => {
1035
+ if (connectedWallet.connector === connector) {
1036
+ this.connectedWalletConnectorMap.delete(accountId);
1037
+ return;
1038
+ }
1039
+ try {
1040
+ if (connectedWallet.connected && connectedWallet.connector.connected) {
1041
+ await connectedWallet.connector.disconnect({
1042
+ cleanup: true
1043
+ });
1044
+ }
1045
+ } catch (error) {
1046
+ log.debug("Connected wallet connector disconnect on primary disconnect", error);
1047
+ } finally {
1048
+ this.connectedWalletConnectorMap.delete(accountId);
1049
+ }
1050
+ }));
1051
+ }
1052
+ this.connectedWalletConnectorMap.clear();
1053
+ this.activeWalletConnectorKey = PRIMARY_CONNECTED_WALLET_KEY;
1054
+ this.connectionReconnected = false;
864
1055
  // re-setup commonJRPCProvider
865
1056
  this.commonJRPCProvider.removeAllListeners();
866
1057
  this.setupCommonJRPCProvider();
@@ -868,10 +1059,10 @@ class Web3AuthNoModal extends SafeEventEmitter {
868
1059
  // get back to ready state for rehydrating.
869
1060
  this.status = CONNECTOR_STATUS.READY;
870
1061
  const cachedConnector = this.state.cachedConnector;
871
- if (this.connectedConnectorName === cachedConnector) {
1062
+ if (this.primaryConnectorName === cachedConnector) {
872
1063
  await this.clearCache();
873
1064
  }
874
- log.debug("disconnected", this.status, this.connectedConnectorName);
1065
+ log.debug("disconnected", this.status, this.primaryConnectorName);
875
1066
  await Promise.all(Object.values(this.plugins).map(async plugin => {
876
1067
  if (!plugin.SUPPORTED_CONNECTORS.includes(connector.name)) return;
877
1068
  if (plugin.status !== PLUGIN_STATUS.CONNECTED) return;
@@ -885,23 +1076,38 @@ class Web3AuthNoModal extends SafeEventEmitter {
885
1076
  });
886
1077
  }));
887
1078
  await this.setState({
888
- connectedConnectorName: null,
889
- hasUserConsent: undefined
1079
+ primaryConnectorName: null,
1080
+ hasUserConsent: undefined,
1081
+ activeAccount: null
890
1082
  });
891
1083
  this.emit(CONNECTOR_EVENTS.DISCONNECTED);
892
1084
  });
893
1085
  connector.on(CONNECTOR_EVENTS.CONNECTING, data => {
894
1086
  this.status = CONNECTOR_STATUS.CONNECTING;
895
1087
  this.emit(CONNECTOR_EVENTS.CONNECTING, data);
896
- log.debug("connecting", this.status, this.connectedConnectorName);
1088
+ log.debug("connecting", this.status, this.primaryConnectorName);
897
1089
  });
898
1090
  connector.on(CONNECTOR_EVENTS.ERRORED, async data => {
1091
+ if (this.shouldIgnoreInactiveConnectorEvent(connector, CONNECTOR_EVENTS.ERRORED)) {
1092
+ log.error("Inactive connector emitted errored event", {
1093
+ connector: connector.name,
1094
+ error: data
1095
+ });
1096
+ return;
1097
+ }
899
1098
  this.status = CONNECTOR_STATUS.ERRORED;
900
1099
  await this.clearCache();
901
1100
  this.emit(CONNECTOR_EVENTS.ERRORED, data, this.loginMode);
902
- log.debug("errored", this.status, this.connectedConnectorName);
1101
+ log.debug("errored", this.status, this.primaryConnectorName);
903
1102
  });
904
1103
  connector.on(CONNECTOR_EVENTS.REHYDRATION_ERROR, async error => {
1104
+ if (this.shouldIgnoreInactiveConnectorEvent(connector, CONNECTOR_EVENTS.REHYDRATION_ERROR)) {
1105
+ log.error("Inactive connector emitted rehydration error", {
1106
+ connector: connector.name,
1107
+ error
1108
+ });
1109
+ return;
1110
+ }
905
1111
  this.status = CONNECTOR_STATUS.READY;
906
1112
  await this.clearCache();
907
1113
  this.emit(CONNECTOR_EVENTS.REHYDRATION_ERROR, error);
@@ -911,18 +1117,19 @@ class Web3AuthNoModal extends SafeEventEmitter {
911
1117
  this.emit(CONNECTOR_EVENTS.CONNECTOR_DATA_UPDATED, data);
912
1118
  });
913
1119
  connector.on(CONNECTOR_EVENTS.CACHE_CLEAR, async data => {
1120
+ if (this.shouldIgnoreInactiveConnectorEvent(connector, CONNECTOR_EVENTS.CACHE_CLEAR)) return;
914
1121
  log.debug("connector cache clear", data);
915
1122
  await this.clearCache();
916
1123
  });
917
1124
  connector.on(CONNECTOR_EVENTS.MFA_ENABLED, isMFAEnabled => {
918
1125
  var _authConnector$authIn4;
919
1126
  log.debug("mfa enabled", isMFAEnabled);
920
- const authConnector = this.connectedConnector;
1127
+ const authConnector = this.primaryConnector;
921
1128
 
922
1129
  // mfa_enabled event is only emitted when using "popup" ux_mode
923
1130
  // TODO: handle mfa_enabled event when using "redirect" ux_mode
924
1131
  this.analytics.track(ANALYTICS_EVENTS.MFA_ENABLEMENT_COMPLETED, {
925
- connector: this.connectedConnector.name,
1132
+ connector: this.primaryConnector.name,
926
1133
  auth_ux_mode: (_authConnector$authIn4 = authConnector.authInstance) === null || _authConnector$authIn4 === void 0 || (_authConnector$authIn4 = _authConnector$authIn4.options) === null || _authConnector$authIn4 === void 0 ? void 0 : _authConnector$authIn4.uxMode,
927
1134
  is_mfa_enabled: isMFAEnabled
928
1135
  });
@@ -931,7 +1138,7 @@ class Web3AuthNoModal extends SafeEventEmitter {
931
1138
  connector.on(CONNECTOR_EVENTS.AUTHORIZING, data => {
932
1139
  this.status = CONNECTOR_STATUS.AUTHORIZING;
933
1140
  this.emit(CONNECTOR_EVENTS.AUTHORIZING, data);
934
- log.debug("authorizing", this.status, this.connectedConnectorName);
1141
+ log.debug("authorizing", this.status, this.primaryConnectorName);
935
1142
  });
936
1143
  connector.on(CONNECTOR_EVENTS.AUTHORIZED, async data => {
937
1144
  var _data$authTokenInfo$a, _data$authTokenInfo$r;
@@ -941,14 +1148,14 @@ class Web3AuthNoModal extends SafeEventEmitter {
941
1148
  refreshToken: (_data$authTokenInfo$r = data.authTokenInfo.refreshToken) !== null && _data$authTokenInfo$r !== void 0 ? _data$authTokenInfo$r : null
942
1149
  });
943
1150
  // if the user has not consented yet, we will ask for consent
944
- if (this.consentRequired && this.currentConnection && !this.state.hasUserConsent) {
1151
+ if (this.consentRequired && this.connection && !this.state.hasUserConsent) {
945
1152
  this.status = CONNECTOR_STATUS.CONSENT_REQUIRING;
946
1153
  this.emit(CONNECTOR_EVENTS.CONSENT_REQUIRING);
947
- log.debug("consent_requiring", this.status, this.connectedConnectorName);
1154
+ log.debug("consent_requiring", this.status, this.primaryConnectorName);
948
1155
  } else {
949
1156
  this.status = CONNECTOR_STATUS.AUTHORIZED;
950
1157
  this.emit(CONNECTOR_EVENTS.AUTHORIZED, data);
951
- log.debug("authorized", this.status, this.connectedConnectorName);
1158
+ log.debug("authorized", this.status, this.primaryConnectorName);
952
1159
  }
953
1160
  });
954
1161
  }
@@ -956,9 +1163,9 @@ class Web3AuthNoModal extends SafeEventEmitter {
956
1163
  if (this.status === CONNECTOR_STATUS.READY) throw WalletInitializationError.notReady("Connector is already initialized");
957
1164
  }
958
1165
  checkIfAutoConnect(connector) {
959
- var _this$currentChain6;
1166
+ var _this$currentChain3;
960
1167
  let autoConnect = this.cachedConnector === connector.name;
961
- if (autoConnect && (_this$currentChain6 = this.currentChain) !== null && _this$currentChain6 !== void 0 && _this$currentChain6.chainNamespace) {
1168
+ if (autoConnect && (_this$currentChain3 = this.currentChain) !== null && _this$currentChain3 !== void 0 && _this$currentChain3.chainNamespace) {
962
1169
  if (connector.connectorNamespace === CONNECTOR_NAMESPACES.MULTICHAIN) autoConnect = true;else autoConnect = connector.connectorNamespace === this.currentChain.chainNamespace;
963
1170
  }
964
1171
  return autoConnect;
@@ -978,7 +1185,7 @@ class Web3AuthNoModal extends SafeEventEmitter {
978
1185
  return initialChain;
979
1186
  }
980
1187
  async completeConsentAcceptance() {
981
- const connection = this.currentConnection;
1188
+ const connection = this.connection;
982
1189
  if (!connection) {
983
1190
  throw WalletLoginError.connectionError("Cannot accept consent: no active connection");
984
1191
  }
@@ -991,29 +1198,400 @@ class Web3AuthNoModal extends SafeEventEmitter {
991
1198
  const isConnectAndSign = this.coreOptions.initialAuthenticationMode === CONNECTOR_INITIAL_AUTHENTICATION_MODE.CONNECT_AND_SIGN;
992
1199
  if (isConnectAndSign && this.state.idToken) {
993
1200
  this.status = CONNECTOR_STATUS.AUTHORIZED;
994
- log.debug("consent accepted, authorized", this.status, this.connectedConnectorName);
1201
+ log.debug("consent accepted, authorized", this.status, this.primaryConnectorName);
995
1202
  } else {
996
1203
  this.status = CONNECTOR_STATUS.CONNECTED;
997
- log.debug("consent accepted, connected", this.status, this.connectedConnectorName);
1204
+ log.debug("consent accepted, connected", this.status, this.primaryConnectorName);
998
1205
  }
999
1206
 
1000
1207
  // connect to wallet-service plugin
1001
- if (this.connectedConnectorName === WALLET_CONNECTORS.AUTH) {
1208
+ if (this.primaryConnectorName === WALLET_CONNECTORS.AUTH) {
1002
1209
  this.connectToPlugins({
1003
- connector: this.connectedConnectorName
1210
+ connector: this.primaryConnectorName
1004
1211
  });
1005
1212
  }
1006
1213
  this.emit(CONNECTOR_EVENTS.CONSENT_ACCEPTED, {
1007
- reconnected: this.currentConnectionReconnected
1214
+ reconnected: this.connectionReconnected
1008
1215
  });
1009
1216
  }
1217
+ resolveLinkAccountChainId(chainId) {
1218
+ const finalChainId = chainId || this.state.currentChainId;
1219
+ if (!finalChainId) {
1220
+ throw AccountLinkingError.walletProofFailed("No chainId is available. Please specify chainId in LinkAccountParams or ensure the SDK has an active chain.");
1221
+ }
1222
+ return finalChainId;
1223
+ }
1224
+
1225
+ /**
1226
+ * Resolves the chain ID for a switch account operation.
1227
+ * If the account's chain namespace is the same as the current chain namespace, return the current chain ID.
1228
+ * If the account's chain namespace is different from the current chain namespace, return the chainId the account was linked in.
1229
+ *
1230
+ * @param account - The account to switch to.
1231
+ * @param activeChainId - The current active chain ID.
1232
+ * @returns The resolved chain ID.
1233
+ */
1234
+ resolveSwitchAccountChainId(account, activeChainId) {
1235
+ const targetChainNamespace = account.chainNamespace ? parseChainNamespaceFromCitadelResponse(account.chainNamespace) : null;
1236
+ if (targetChainNamespace && this.currentChain.chainNamespace === targetChainNamespace) {
1237
+ return this.currentChain.chainId;
1238
+ }
1239
+ return activeChainId;
1240
+ }
1241
+ async createLinkingWalletConnector(connectorName, chainId, config) {
1242
+ return this.createIsolatedWalletConnector(connectorName, chainId, config);
1243
+ }
1244
+ async createSwitchingWalletConnector(connectorName, chainId, config) {
1245
+ return this.createIsolatedWalletConnector(connectorName, chainId, config);
1246
+ }
1247
+ getConnectedWalletConnector(account) {
1248
+ var _this$getConnectedWal, _this$getConnectedWal2;
1249
+ return (_this$getConnectedWal = (_this$getConnectedWal2 = this.getConnectedWalletConnectorState(account)) === null || _this$getConnectedWal2 === void 0 ? void 0 : _this$getConnectedWal2.connector) !== null && _this$getConnectedWal !== void 0 ? _this$getConnectedWal : null;
1250
+ }
1251
+ getConnectedWalletConnectorState(account) {
1252
+ return this.getConnectedWalletConnectorStateByKey(this.getConnectedWalletConnectorKey(account));
1253
+ }
1254
+ setConnectedWalletConnectorState(connectedWallet, account) {
1255
+ this.connectedWalletConnectorMap.set(this.getConnectedWalletConnectorKey(account), connectedWallet);
1256
+ }
1257
+ setConnectedWalletConnector(connector, account) {
1258
+ var _connector$solanaWall;
1259
+ this.setConnectedWalletConnectorState(_objectSpread(_objectSpread({}, this.getConnectedWalletLinkedAccountInfo(account)), {}, {
1260
+ connector,
1261
+ signingProvider: connector.provider,
1262
+ solanaWallet: (_connector$solanaWall = connector.solanaWallet) !== null && _connector$solanaWall !== void 0 ? _connector$solanaWall : null,
1263
+ connected: connector.connected || connector.status === CONNECTOR_STATUS.CONNECTED
1264
+ }), account);
1265
+ }
1266
+ deleteConnectedWalletConnector(account) {
1267
+ this.connectedWalletConnectorMap.delete(this.getConnectedWalletConnectorKey(account));
1268
+ }
1269
+ getConnectedWalletConnection(account) {
1270
+ return this.getConnectedWalletConnectionByKey(this.getConnectedWalletConnectorKey(account));
1271
+ }
1272
+ hasUsableConnectedSwitchConnector(connector) {
1273
+ if (!connector) return false;
1274
+ const isConnected = connector.connected || connector.status === CONNECTOR_STATUS.CONNECTED;
1275
+ return Boolean(isConnected && (connector.provider || connector.solanaWallet));
1276
+ }
1277
+ setActiveWalletConnectorKey(account) {
1278
+ this.activeWalletConnectorKey = this.getConnectedWalletConnectorKey(account);
1279
+ }
1280
+ getConnectedWalletConnectorKey(account) {
1281
+ return !account || account.isPrimary ? PRIMARY_CONNECTED_WALLET_KEY : account.id;
1282
+ }
1283
+ getConnectedWalletConnectorStateByKey(accountKey) {
1284
+ var _this$connectedWallet;
1285
+ return (_this$connectedWallet = this.connectedWalletConnectorMap.get(accountKey)) !== null && _this$connectedWallet !== void 0 ? _this$connectedWallet : null;
1286
+ }
1287
+ isLinkedAccountInfo(account) {
1288
+ return Boolean(account && "connector" in account);
1289
+ }
1290
+ toConnectedWalletLinkedAccountInfo(account) {
1291
+ return {
1292
+ id: account.id,
1293
+ isPrimary: account.isPrimary,
1294
+ eoaAddress: account.eoaAddress,
1295
+ aaAddress: account.aaAddress,
1296
+ aaProvider: account.aaProvider,
1297
+ active: account.active,
1298
+ accountType: account.accountType,
1299
+ address: account.address,
1300
+ authConnectionId: account.authConnectionId,
1301
+ groupedAuthConnectionId: account.groupedAuthConnectionId,
1302
+ chainNamespace: account.chainNamespace
1303
+ };
1304
+ }
1305
+ getConnectedWalletLinkedAccountInfo(account) {
1306
+ const existingConnectedWallet = this.getConnectedWalletConnectorState(account);
1307
+ const resolvedAccount = this.isLinkedAccountInfo(account) ? account : existingConnectedWallet;
1308
+ if (resolvedAccount) {
1309
+ return this.toConnectedWalletLinkedAccountInfo(resolvedAccount);
1310
+ }
1311
+ const isPrimaryAccount = !account || account.isPrimary;
1312
+ const accountId = account && !account.isPrimary ? account.id : PRIMARY_CONNECTED_WALLET_KEY;
1313
+ return {
1314
+ id: accountId,
1315
+ isPrimary: isPrimaryAccount,
1316
+ eoaAddress: "",
1317
+ aaAddress: undefined,
1318
+ aaProvider: undefined,
1319
+ active: this.state.activeAccount ? this.state.activeAccount.id === accountId : isPrimaryAccount,
1320
+ accountType: "",
1321
+ address: null,
1322
+ authConnectionId: null,
1323
+ groupedAuthConnectionId: null,
1324
+ chainNamespace: null
1325
+ };
1326
+ }
1327
+ syncConnectedWalletLinkedAccounts(linkedAccounts) {
1328
+ for (const linkedAccount of linkedAccounts) {
1329
+ const accountKey = this.getConnectedWalletConnectorKey(linkedAccount);
1330
+ const connectedWallet = this.connectedWalletConnectorMap.get(accountKey);
1331
+ if (!connectedWallet) {
1332
+ continue;
1333
+ }
1334
+ this.connectedWalletConnectorMap.set(accountKey, _objectSpread(_objectSpread({}, connectedWallet), this.toConnectedWalletLinkedAccountInfo(linkedAccount)));
1335
+ }
1336
+ }
1337
+ refreshConnectedWalletActiveStates(activeAccount) {
1338
+ for (const [accountKey, connectedWallet] of this.connectedWalletConnectorMap.entries()) {
1339
+ const isPrimaryAccount = accountKey === PRIMARY_CONNECTED_WALLET_KEY || connectedWallet.isPrimary;
1340
+ this.connectedWalletConnectorMap.set(accountKey, _objectSpread(_objectSpread({}, connectedWallet), {}, {
1341
+ active: activeAccount ? connectedWallet.id === activeAccount.id : isPrimaryAccount
1342
+ }));
1343
+ }
1344
+ }
1345
+ getConnectedWalletConnectionByKey(accountKey) {
1346
+ const connectedWallet = this.getConnectedWalletConnectorStateByKey(accountKey);
1347
+ if (!connectedWallet) {
1348
+ return null;
1349
+ }
1350
+ if (!connectedWallet.signingProvider && !connectedWallet.solanaWallet) {
1351
+ throw new Error(`Connected connector "${connectedWallet.connector.name}" is not ready.`);
1352
+ }
1353
+ return this.buildConnectionFromConnectedWalletConnectorState(connectedWallet);
1354
+ }
1355
+ buildConnectionFromConnectedWalletConnectorState(connectedWallet) {
1356
+ var _connectedWallet$sola;
1357
+ return {
1358
+ ethereumProvider: connectedWallet.signingProvider,
1359
+ solanaWallet: (_connectedWallet$sola = connectedWallet.solanaWallet) !== null && _connectedWallet$sola !== void 0 ? _connectedWallet$sola : null,
1360
+ connectorName: connectedWallet.connector.name
1361
+ };
1362
+ }
1363
+ buildImmediateConnectedWalletConnectorState(params) {
1364
+ var _this$commonJRPCProvi;
1365
+ const {
1366
+ connector,
1367
+ ethereumProvider,
1368
+ solanaWallet,
1369
+ usePrimaryProxy,
1370
+ account
1371
+ } = params;
1372
+ const isSolanaOnly = connector.connectorNamespace === CHAIN_NAMESPACES.SOLANA;
1373
+ const connectedWallet = _objectSpread(_objectSpread({}, this.getConnectedWalletLinkedAccountInfo(account)), {}, {
1374
+ connector,
1375
+ signingProvider: isSolanaOnly ? null : ethereumProvider ? usePrimaryProxy ? (_this$commonJRPCProvi = this.commonJRPCProvider) !== null && _this$commonJRPCProvi !== void 0 ? _this$commonJRPCProvi : ethereumProvider : ethereumProvider : null,
1376
+ solanaWallet: solanaWallet !== null && solanaWallet !== void 0 ? solanaWallet : null,
1377
+ connected: connector.connected || connector.status === CONNECTOR_STATUS.CONNECTED || connector.status === CONNECTOR_STATUS.AUTHORIZED
1378
+ });
1379
+ return connectedWallet;
1380
+ }
1381
+ async resolveConnectedWalletConnectorState(params) {
1382
+ const {
1383
+ connector,
1384
+ ethereumProvider,
1385
+ solanaWallet,
1386
+ usePrimaryProxy,
1387
+ account
1388
+ } = params;
1389
+ return this.buildImmediateConnectedWalletConnectorState({
1390
+ connector,
1391
+ ethereumProvider,
1392
+ solanaWallet,
1393
+ usePrimaryProxy,
1394
+ account
1395
+ });
1396
+ }
1397
+ async linkAccountWithConnector(connectorName, chainId, connectorToLink) {
1398
+ const authConnector = this.getMainAuthConnector();
1399
+ const result = await authConnector.linkAccount({
1400
+ connectorName,
1401
+ chainId,
1402
+ connectorToLink,
1403
+ authSessionTokens: {
1404
+ accessToken: this.accessToken,
1405
+ idToken: this.idToken
1406
+ }
1407
+ });
1408
+ await this.setState({
1409
+ idToken: result.idToken
1410
+ });
1411
+ await this.cacheConnectedLinkedWalletConnector(authConnector, connectorToLink);
1412
+ return result;
1413
+ }
1414
+ getMainAuthConnector() {
1415
+ if (!CONNECTED_STATUSES.includes(this.status) || !this.primaryConnector) {
1416
+ throw WalletLoginError.notConnectedError("No wallet is connected. Connect with AUTH before unlinking an account.");
1417
+ }
1418
+ const mainConnector = this.primaryConnector;
1419
+ assertAuthConnector(mainConnector, "Account linking is only supported when connected with the AUTH connector.");
1420
+ return mainConnector;
1421
+ }
1422
+
1423
+ /**
1424
+ * Processes the result of a switch account operation.
1425
+ *
1426
+ * - If the target account is a primary account, we will switch back to the primary account.
1427
+ * - If the target account is an external account and already connected (i.e. connector is available with connected state), we will just switch to it without re-connecting again.
1428
+ * - If the target account is an external account and not connected (i.e. connector is not available with connected state), we will create a new isolated connector and connect to it.
1429
+ * @param authConnector - The main auth connector to use.
1430
+ * @param switchResult - The result of the switch account operation.
1431
+ * @param options - The options for the switch account operation.
1432
+ * @returns A promise that resolves when the switch account operation is complete.
1433
+ */
1434
+ async processSwitchAccountResult(authConnector, switchResult, options = {}) {
1435
+ const resolvedSwitchChainId = this.resolveSwitchAccountChainId(switchResult.targetAccount, switchResult.activeChainId);
1436
+ if (switchResult.kind === "primary") {
1437
+ var _primaryConnectedWall, _this$commonJRPCProvi2, _switchResult$solanaW;
1438
+ const existingPrimaryConnectedWalletState = this.getConnectedWalletConnectorState();
1439
+ const primaryConnectedWalletState = existingPrimaryConnectedWalletState !== null && existingPrimaryConnectedWalletState !== void 0 ? existingPrimaryConnectedWalletState : await this.resolveConnectedWalletConnectorState({
1440
+ connector: authConnector,
1441
+ ethereumProvider: switchResult.ethereumProvider,
1442
+ solanaWallet: switchResult.solanaWallet,
1443
+ usePrimaryProxy: true,
1444
+ account: switchResult.targetAccount
1445
+ });
1446
+ this.setConnectedWalletConnectorState(_objectSpread(_objectSpread({}, primaryConnectedWalletState), {}, {
1447
+ connector: authConnector,
1448
+ signingProvider: (_primaryConnectedWall = primaryConnectedWalletState.signingProvider) !== null && _primaryConnectedWall !== void 0 ? _primaryConnectedWall : switchResult.ethereumProvider ? (_this$commonJRPCProvi2 = this.commonJRPCProvider) !== null && _this$commonJRPCProvi2 !== void 0 ? _this$commonJRPCProvi2 : switchResult.ethereumProvider : null,
1449
+ solanaWallet: (_switchResult$solanaW = switchResult.solanaWallet) !== null && _switchResult$solanaW !== void 0 ? _switchResult$solanaW : primaryConnectedWalletState.solanaWallet,
1450
+ connected: authConnector.connected || authConnector.status === CONNECTOR_STATUS.CONNECTED
1451
+ }));
1452
+ this.setActiveWalletConnectorKey();
1453
+ } else {
1454
+ var _ref5, _options$walletConnec;
1455
+ const walletConnector = (_ref5 = (_options$walletConnec = options.walletConnector) !== null && _options$walletConnec !== void 0 ? _options$walletConnec : this.getConnectedWalletConnector(switchResult.targetAccount)) !== null && _ref5 !== void 0 ? _ref5 : await this.createSwitchingWalletConnector(switchResult.targetAccount.connector, resolvedSwitchChainId, options.projectConfig);
1456
+ let linkedAccountConnection = null;
1457
+ try {
1458
+ var _ref6, _walletConnector$prov2, _linkedAccountConnect3, _ref7, _walletConnector$sola2, _linkedAccountConnect4;
1459
+ if (!this.hasUsableConnectedSwitchConnector(walletConnector)) {
1460
+ const switchChainConfig = this.coreOptions.chains.find(c => c.chainId === resolvedSwitchChainId);
1461
+ if (!switchChainConfig) {
1462
+ throw WalletLoginError.connectionError(`Chain config is not available for chain ${resolvedSwitchChainId}`);
1463
+ }
1464
+ const caipChainId = getCaipChainId(switchChainConfig);
1465
+ const caipAccountId = `${caipChainId}:${switchResult.targetAccount.eoaAddress}`;
1466
+ linkedAccountConnection = await walletConnector.connect({
1467
+ chainId: resolvedSwitchChainId,
1468
+ caipAccountIds: [caipAccountId]
1469
+ });
1470
+ if (!linkedAccountConnection) {
1471
+ throw AccountLinkingError.requestFailed(`Failed to connect isolated connector "${switchResult.targetAccount.connector}" for account switch.`);
1472
+ }
1473
+ }
1474
+ await authConnector.assertSwitchAccountConnectorMatchesTarget(walletConnector, switchResult.targetAccount);
1475
+ const connectedWalletState = await this.resolveConnectedWalletConnectorState({
1476
+ connector: walletConnector,
1477
+ ethereumProvider: (_ref6 = (_walletConnector$prov2 = walletConnector.provider) !== null && _walletConnector$prov2 !== void 0 ? _walletConnector$prov2 : (_linkedAccountConnect3 = linkedAccountConnection) === null || _linkedAccountConnect3 === void 0 ? void 0 : _linkedAccountConnect3.ethereumProvider) !== null && _ref6 !== void 0 ? _ref6 : null,
1478
+ solanaWallet: (_ref7 = (_walletConnector$sola2 = walletConnector.solanaWallet) !== null && _walletConnector$sola2 !== void 0 ? _walletConnector$sola2 : (_linkedAccountConnect4 = linkedAccountConnection) === null || _linkedAccountConnect4 === void 0 ? void 0 : _linkedAccountConnect4.solanaWallet) !== null && _ref7 !== void 0 ? _ref7 : null,
1479
+ usePrimaryProxy: false,
1480
+ account: switchResult.targetAccount
1481
+ });
1482
+ this.setConnectedWalletConnectorState(connectedWalletState, switchResult.targetAccount);
1483
+ this.setActiveWalletConnectorKey(switchResult.targetAccount);
1484
+ } catch (error) {
1485
+ throw authConnector.toSwitchAccountConnectorError(switchResult.targetAccount, error);
1486
+ }
1487
+ }
1488
+ await this.setCurrentChain(resolvedSwitchChainId);
1489
+ await this.setState({
1490
+ activeAccount: switchResult.activeAccount
1491
+ });
1492
+ this.syncConnectedWalletLinkedAccounts([switchResult.targetAccount]);
1493
+ this.refreshConnectedWalletActiveStates(switchResult.activeAccount);
1494
+ const connection = this.connection;
1495
+ if (!connection) {
1496
+ throw WalletLoginError.connectionError("Failed to resolve the active connection after switching accounts.");
1497
+ }
1498
+ this.emit(CONNECTOR_EVENTS.CONNECTION_UPDATED, {
1499
+ ethereumProvider: connection.ethereumProvider,
1500
+ solanaWallet: connection.solanaWallet,
1501
+ connectorName: connection.connectorName
1502
+ });
1503
+ }
1504
+ isActiveConnectorEventSource(connector) {
1505
+ if (!this.primaryConnectorName) return true;
1506
+ const activeConnector = this.primaryConnector;
1507
+ if (activeConnector) return activeConnector === connector;
1508
+ return connector.name === this.primaryConnectorName;
1509
+ }
1510
+ shouldIgnoreInactiveConnectorEvent(connector, event) {
1511
+ if (this.isActiveConnectorEventSource(connector)) return false;
1512
+ log.debug("Ignoring connector lifecycle event from inactive connector", {
1513
+ event,
1514
+ sourceConnector: connector.name,
1515
+ activeConnector: this.primaryConnectorName
1516
+ });
1517
+ return true;
1518
+ }
1519
+ findLinkedAccountByAddress(linkedAccounts, address) {
1520
+ var _linkedAccounts$find;
1521
+ const normalizedAddress = address.toLowerCase();
1522
+ return (_linkedAccounts$find = linkedAccounts.find(account => {
1523
+ var _account$address, _account$eoaAddress;
1524
+ if (!account.chainNamespace || parseChainNamespaceFromCitadelResponse(account.chainNamespace) !== CHAIN_NAMESPACES.EIP155) {
1525
+ return false;
1526
+ }
1527
+ return ((_account$address = account.address) === null || _account$address === void 0 ? void 0 : _account$address.toLowerCase()) === normalizedAddress || ((_account$eoaAddress = account.eoaAddress) === null || _account$eoaAddress === void 0 ? void 0 : _account$eoaAddress.toLowerCase()) === normalizedAddress;
1528
+ })) !== null && _linkedAccounts$find !== void 0 ? _linkedAccounts$find : null;
1529
+ }
1530
+ findLinkedAccountByWalletAddress(linkedAccounts, address) {
1531
+ var _linkedAccounts$find2;
1532
+ return (_linkedAccounts$find2 = linkedAccounts.find(account => {
1533
+ if (!account.chainNamespace) {
1534
+ return false;
1535
+ }
1536
+ const chainNamespace = parseChainNamespaceFromCitadelResponse(account.chainNamespace);
1537
+ if (chainNamespace === CHAIN_NAMESPACES.EIP155) {
1538
+ var _account$address2, _account$eoaAddress2;
1539
+ const normalizedAddress = address.toLowerCase();
1540
+ return ((_account$address2 = account.address) === null || _account$address2 === void 0 ? void 0 : _account$address2.toLowerCase()) === normalizedAddress || ((_account$eoaAddress2 = account.eoaAddress) === null || _account$eoaAddress2 === void 0 ? void 0 : _account$eoaAddress2.toLowerCase()) === normalizedAddress;
1541
+ }
1542
+ if (chainNamespace === CHAIN_NAMESPACES.SOLANA) {
1543
+ return account.address === address || account.eoaAddress === address;
1544
+ }
1545
+ return false;
1546
+ })) !== null && _linkedAccounts$find2 !== void 0 ? _linkedAccounts$find2 : null;
1547
+ }
1548
+ async getConnectedWalletAddress(connector) {
1549
+ var _connector$solanaWall2, _accounts$;
1550
+ const solanaAddress = (_connector$solanaWall2 = connector.solanaWallet) === null || _connector$solanaWall2 === void 0 || (_connector$solanaWall2 = _connector$solanaWall2.accounts) === null || _connector$solanaWall2 === void 0 || (_connector$solanaWall2 = _connector$solanaWall2[0]) === null || _connector$solanaWall2 === void 0 ? void 0 : _connector$solanaWall2.address;
1551
+ if (solanaAddress) {
1552
+ return solanaAddress;
1553
+ }
1554
+ if (!connector.provider) {
1555
+ return null;
1556
+ }
1557
+ const accounts = await connector.provider.request({
1558
+ method: "eth_accounts"
1559
+ });
1560
+ return (_accounts$ = accounts === null || accounts === void 0 ? void 0 : accounts[0]) !== null && _accounts$ !== void 0 ? _accounts$ : null;
1561
+ }
1562
+ async cacheConnectedLinkedWalletConnector(authConnector, walletConnector) {
1563
+ try {
1564
+ var _await$authConnector$2;
1565
+ const connectedWalletAddress = await this.getConnectedWalletAddress(walletConnector);
1566
+ if (!connectedWalletAddress) {
1567
+ return;
1568
+ }
1569
+ const linkedAccounts = (_await$authConnector$2 = await authConnector.getLinkedAccounts()) !== null && _await$authConnector$2 !== void 0 ? _await$authConnector$2 : [];
1570
+ const linkedAccount = this.findLinkedAccountByWalletAddress(linkedAccounts, connectedWalletAddress);
1571
+ if (linkedAccount && !linkedAccount.isPrimary) {
1572
+ const connectedWalletState = await this.resolveConnectedWalletConnectorState({
1573
+ connector: walletConnector,
1574
+ ethereumProvider: walletConnector.provider,
1575
+ solanaWallet: walletConnector.solanaWallet,
1576
+ usePrimaryProxy: false,
1577
+ account: linkedAccount
1578
+ });
1579
+ this.setConnectedWalletConnectorState(connectedWalletState, linkedAccount);
1580
+ }
1581
+ } catch (error) {
1582
+ log.debug("Failed to cache connected linked wallet connector", error);
1583
+ }
1584
+ }
1010
1585
  async cacheWallet(walletName) {
1011
1586
  await this.setState({
1012
1587
  cachedConnector: walletName
1013
1588
  });
1014
1589
  }
1015
1590
  async setCurrentChain(chainId) {
1016
- if (chainId === this.currentChainId) return;
1591
+ const {
1592
+ currentChainId
1593
+ } = this.state;
1594
+ if (chainId === currentChainId) return;
1017
1595
  const newChain = this.coreOptions.chains.find(chain => chain.chainId === chainId);
1018
1596
  if (!newChain) throw WalletInitializationError.invalidParams(`Invalid chainId: ${chainId}`);
1019
1597
  await this.setState({
@@ -1023,11 +1601,11 @@ class Web3AuthNoModal extends SafeEventEmitter {
1023
1601
  connectToPlugins(data) {
1024
1602
  Object.values(this.plugins).map(async plugin => {
1025
1603
  try {
1026
- var _this$currentChain7;
1604
+ var _this$currentChain4;
1027
1605
  // skip if it's not compatible with the connector
1028
1606
  if (!plugin.SUPPORTED_CONNECTORS.includes(data.connector)) return;
1029
1607
  // skip if it's not compatible with the current chain
1030
- if (plugin.pluginNamespace !== PLUGIN_NAMESPACES.MULTICHAIN && plugin.pluginNamespace !== ((_this$currentChain7 = this.currentChain) === null || _this$currentChain7 === void 0 ? void 0 : _this$currentChain7.chainNamespace)) return;
1608
+ if (plugin.pluginNamespace !== PLUGIN_NAMESPACES.MULTICHAIN && plugin.pluginNamespace !== ((_this$currentChain4 = this.currentChain) === null || _this$currentChain4 === void 0 ? void 0 : _this$currentChain4.chainNamespace)) return;
1031
1609
  // skip if it's already connected
1032
1610
  if (plugin.status === PLUGIN_STATUS.CONNECTED) return;
1033
1611
  await plugin.initWithWeb3Auth(this, this.coreOptions.uiConfig, this.analytics);
@@ -1041,6 +1619,153 @@ class Web3AuthNoModal extends SafeEventEmitter {
1041
1619
  }
1042
1620
  });
1043
1621
  }
1622
+ async bindPrimaryEthereumSigningProxy(ethereumProvider, connectorName) {
1623
+ var _this$currentChain5, _accountAbstractionCo;
1624
+ if (!this.commonJRPCProvider) throw WalletInitializationError.notFound(`CommonJrpcProvider not found`);
1625
+ let finalProvider = (ethereumProvider === null || ethereumProvider === void 0 ? void 0 : ethereumProvider.provider) || ethereumProvider;
1626
+ const {
1627
+ accountAbstractionConfig
1628
+ } = this.coreOptions;
1629
+ const is7702 = (accountAbstractionConfig === null || accountAbstractionConfig === void 0 ? void 0 : accountAbstractionConfig.smartAccountEipStandard) === SMART_ACCOUNT_EIP_STANDARD["EIP_7702"];
1630
+ const isAaSupportedForCurrentChain = ((_this$currentChain5 = this.currentChain) === null || _this$currentChain5 === void 0 ? void 0 : _this$currentChain5.chainNamespace) === CHAIN_NAMESPACES.EIP155 && (accountAbstractionConfig === null || accountAbstractionConfig === void 0 || (_accountAbstractionCo = accountAbstractionConfig.chains) === null || _accountAbstractionCo === void 0 ? void 0 : _accountAbstractionCo.some(chain => {
1631
+ var _this$currentChain6;
1632
+ return chain.chainId === ((_this$currentChain6 = this.currentChain) === null || _this$currentChain6 === void 0 ? void 0 : _this$currentChain6.chainId);
1633
+ }));
1634
+
1635
+ // setup AA provider if AA is enabled (skip for EIP-7702; 7702 uses EOA + 5792/7702 RPC only)
1636
+ if (!is7702 && isAaSupportedForCurrentChain && (connectorName === WALLET_CONNECTORS.AUTH || this.coreOptions.useAAWithExternalWallet)) {
1637
+ var _accountAbstractionCo2;
1638
+ const {
1639
+ accountAbstractionProvider,
1640
+ toEoaProvider
1641
+ } = await import('./providers/account-abstraction-provider/index.js');
1642
+ const eoaProvider = connectorName === WALLET_CONNECTORS.AUTH ? await toEoaProvider(ethereumProvider) : ethereumProvider;
1643
+ const aaChainIds = new Set((accountAbstractionConfig === null || accountAbstractionConfig === void 0 || (_accountAbstractionCo2 = accountAbstractionConfig.chains) === null || _accountAbstractionCo2 === void 0 ? void 0 : _accountAbstractionCo2.map(chain => chain.chainId)) || []);
1644
+ const aaProvider = await accountAbstractionProvider({
1645
+ accountAbstractionConfig,
1646
+ provider: eoaProvider,
1647
+ chain: this.currentChain,
1648
+ chains: this.coreOptions.chains.filter(chain => aaChainIds.has(chain.chainId)),
1649
+ useProviderAsTransport: connectorName === WALLET_CONNECTORS.AUTH
1650
+ });
1651
+ this.aaProvider = aaProvider;
1652
+ if (connectorName !== WALLET_CONNECTORS.AUTH && this.coreOptions.useAAWithExternalWallet) {
1653
+ finalProvider = this.aaProvider;
1654
+ }
1655
+ }
1656
+ this.commonJRPCProvider.updateProviderEngineProxy(finalProvider);
1657
+ }
1658
+ getChainConfigForIsolatedConnector(chainId) {
1659
+ const chainConfig = this.coreOptions.chains.find(chain => chain.chainId === chainId);
1660
+ if (!chainConfig) {
1661
+ throw WalletInitializationError.invalidParams(`Chain config is not available for chain ${chainId}`);
1662
+ }
1663
+ return chainConfig;
1664
+ }
1665
+ async resolveInstalledDiscoveredWalletConnector(params) {
1666
+ const {
1667
+ connectorName,
1668
+ chainConfig,
1669
+ config,
1670
+ isMipdEnabled
1671
+ } = params;
1672
+ if (!isBrowser() || !isMipdEnabled) return null;
1673
+ if (chainConfig.chainNamespace === CHAIN_NAMESPACES.EIP155) {
1674
+ const {
1675
+ createMipd,
1676
+ injectedEvmConnector
1677
+ } = await import('./connectors/injected-evm-connector/index.js');
1678
+ const providerDetail = createMipd().getProviders().find(detail => normalizeWalletName(detail.info.name) === connectorName);
1679
+ if (providerDetail) {
1680
+ return injectedEvmConnector(providerDetail)(config);
1681
+ }
1682
+ return null;
1683
+ }
1684
+ if (chainConfig.chainNamespace === CHAIN_NAMESPACES.SOLANA) {
1685
+ const {
1686
+ createSolanaMipd,
1687
+ hasSolanaWalletStandardFeatures,
1688
+ walletStandardConnector
1689
+ } = await import('./connectors/injected-solana-connector/index.js');
1690
+ const wallet = createSolanaMipd().get().find(candidate => hasSolanaWalletStandardFeatures(candidate) && normalizeWalletName(candidate.name) === connectorName);
1691
+ if (wallet) {
1692
+ return walletStandardConnector(wallet)(config);
1693
+ }
1694
+ }
1695
+ return null;
1696
+ }
1697
+ async resolveDiscoveredWalletConnector(connectorName, chainId, config, effectiveProjectConfig) {
1698
+ var _this$coreOptions$mul2;
1699
+ const chainConfig = this.getChainConfigForIsolatedConnector(chainId);
1700
+ const isExternalWalletEnabled = Boolean(effectiveProjectConfig === null || effectiveProjectConfig === void 0 ? void 0 : effectiveProjectConfig.externalWalletAuth);
1701
+ const isMipdEnabled = isExternalWalletEnabled && ((_this$coreOptions$mul2 = this.coreOptions.multiInjectedProviderDiscovery) !== null && _this$coreOptions$mul2 !== void 0 ? _this$coreOptions$mul2 : true);
1702
+ const installedConnector = await this.resolveInstalledDiscoveredWalletConnector({
1703
+ connectorName,
1704
+ chainConfig,
1705
+ config,
1706
+ isMipdEnabled
1707
+ });
1708
+ if (installedConnector) {
1709
+ return installedConnector;
1710
+ }
1711
+ const isBuiltInConnectorName = Object.values(WALLET_CONNECTORS).includes(connectorName);
1712
+ const supportsWalletConnectFallback = chainConfig.chainNamespace === CHAIN_NAMESPACES.EIP155 || chainConfig.chainNamespace === CHAIN_NAMESPACES.SOLANA;
1713
+
1714
+ // Named discovered wallets (for example Phantom) can reuse WalletConnect as a transport fallback
1715
+ // when an injected connector for the target chain namespace is unavailable.
1716
+ if (!isBuiltInConnectorName && isExternalWalletEnabled && supportsWalletConnectFallback) {
1717
+ const {
1718
+ walletConnectV2Connector
1719
+ } = await import('./connectors/wallet-connect-v2-connector/index.js');
1720
+ return walletConnectV2Connector()(config);
1721
+ }
1722
+ throw AccountLinkingError.unsupportedConnector(`Connector "${connectorName}" does not support automatic wallet linking. ` + `Use ${WALLET_CONNECTORS.METAMASK}, ${WALLET_CONNECTORS.WALLET_CONNECT_V2}, or an installed compatible wallet.`);
1723
+ }
1724
+
1725
+ /**
1726
+ * Create a new connector instance that is NOT registered in this.connectors and NOT
1727
+ * subscribed to the main SDK event loop. Its lifecycle events are therefore isolated
1728
+ * and will not mutate any global SDK state (connectedConnectorName, connection, idToken).
1729
+ */
1730
+ async createIsolatedWalletConnector(connectorName, chainId, projectConfig) {
1731
+ var _ref8;
1732
+ const effectiveProjectConfig = (_ref8 = projectConfig !== null && projectConfig !== void 0 ? projectConfig : this.projectConfig) !== null && _ref8 !== void 0 ? _ref8 : undefined;
1733
+ const config = {
1734
+ projectConfig: effectiveProjectConfig,
1735
+ coreOptions: this.coreOptions,
1736
+ analytics: this.analytics
1737
+ };
1738
+ let connector;
1739
+ switch (connectorName) {
1740
+ case WALLET_CONNECTORS.METAMASK:
1741
+ connector = metaMaskConnector()(config);
1742
+ break;
1743
+ case WALLET_CONNECTORS.WALLET_CONNECT_V2:
1744
+ {
1745
+ const {
1746
+ walletConnectV2Connector
1747
+ } = await import('./connectors/wallet-connect-v2-connector/index.js');
1748
+ connector = walletConnectV2Connector()(config);
1749
+ break;
1750
+ }
1751
+ case WALLET_CONNECTORS.AUTH:
1752
+ throw AccountLinkingError.unsupportedConnector(`Connector "${connectorName}" does not support automatic wallet linking.`);
1753
+ default:
1754
+ {
1755
+ connector = await this.resolveDiscoveredWalletConnector(connectorName, chainId, config, effectiveProjectConfig);
1756
+ break;
1757
+ }
1758
+ }
1759
+
1760
+ // Init the isolated connector WITHOUT subscribing to the main event loop.
1761
+ // This is the key difference from setupConnector(), which calls subscribeToConnectorEvents().
1762
+ // autoConnect: false ensures the connector does not attempt to rehydrate a previous session.
1763
+ await connector.init({
1764
+ chainId,
1765
+ autoConnect: false
1766
+ });
1767
+ return connector;
1768
+ }
1044
1769
  async setState(newState) {
1045
1770
  this.state = _objectSpread(_objectSpread({}, this.state), newState);
1046
1771
  await this.storage.set(WEB3AUTH_STATE_STORAGE_KEY, JSON.stringify(this.state));