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