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

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 (100) 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 +427 -50
  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 +811 -110
  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 +34 -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 +2 -0
  24. package/dist/lib.cjs/types/account-linking/index.d.ts +2 -0
  25. package/dist/lib.cjs/types/account-linking/interfaces.d.ts +90 -0
  26. package/dist/lib.cjs/types/account-linking/react.d.ts +19 -0
  27. package/dist/lib.cjs/types/account-linking/rest.d.ts +9 -0
  28. package/dist/lib.cjs/types/account-linking/vue.d.ts +20 -0
  29. package/dist/lib.cjs/types/base/analytics.d.ts +9 -0
  30. package/dist/lib.cjs/types/base/connector/baseConnector.d.ts +5 -0
  31. package/dist/lib.cjs/types/base/connector/constants.d.ts +2 -0
  32. package/dist/lib.cjs/types/base/connector/interfaces.d.ts +51 -6
  33. package/dist/lib.cjs/types/base/core/IWeb3Auth.d.ts +39 -2
  34. package/dist/lib.cjs/types/base/errors/index.d.ts +13 -0
  35. package/dist/lib.cjs/types/base/interfaces.d.ts +3 -1
  36. package/dist/lib.cjs/types/base/utils.d.ts +7 -1
  37. package/dist/lib.cjs/types/connectors/auth-connector/authConnector.d.ts +27 -3
  38. package/dist/lib.cjs/types/connectors/auth-connector/interface.d.ts +77 -2
  39. package/dist/lib.cjs/types/connectors/base-evm-connector/baseEvmConnector.d.ts +6 -0
  40. package/dist/lib.cjs/types/connectors/base-solana-connector/baseSolanaConnector.d.ts +6 -0
  41. package/dist/lib.cjs/types/index.d.ts +1 -0
  42. package/dist/lib.cjs/types/noModal.d.ts +104 -5
  43. package/dist/lib.cjs/types/providers/base-provider/baseProvider.d.ts +7 -0
  44. package/dist/lib.cjs/types/react/hooks/index.d.ts +1 -0
  45. package/dist/lib.cjs/types/react/hooks/useWallets.d.ts +8 -0
  46. package/dist/lib.cjs/types/vue/composables/index.d.ts +1 -0
  47. package/dist/lib.cjs/types/vue/composables/useWallets.d.ts +9 -0
  48. package/dist/lib.cjs/vue/composables/useWallets.js +52 -0
  49. package/dist/lib.cjs/vue/composables/useWeb3AuthConnect.js +2 -2
  50. package/dist/lib.cjs/vue/index.js +2 -0
  51. package/dist/lib.cjs/vue/solana/composables/useSolanaWallet.js +2 -2
  52. package/dist/lib.cjs/vue/solana/provider.js +3 -0
  53. package/dist/lib.cjs/vue/useWeb3AuthInnerContextValue.js +13 -4
  54. package/dist/lib.cjs/vue/wagmi/provider.js +19 -7
  55. package/dist/lib.esm/account-linking/index.js +1 -0
  56. package/dist/lib.esm/account-linking/react.js +74 -0
  57. package/dist/lib.esm/account-linking/rest.js +51 -0
  58. package/dist/lib.esm/account-linking/vue.js +78 -0
  59. package/dist/lib.esm/base/analytics.js +17 -2
  60. package/dist/lib.esm/base/connector/constants.js +2 -0
  61. package/dist/lib.esm/base/errors/index.js +48 -1
  62. package/dist/lib.esm/base/utils.js +16 -4
  63. package/dist/lib.esm/connectors/auth-connector/authConnector.js +386 -9
  64. package/dist/lib.esm/connectors/base-evm-connector/baseEvmConnector.js +43 -24
  65. package/dist/lib.esm/connectors/base-solana-connector/baseSolanaConnector.js +43 -26
  66. package/dist/lib.esm/connectors/coinbase-connector/coinbaseConnector.js +2 -2
  67. package/dist/lib.esm/connectors/injected-evm-connector/injectedEvmConnector.js +2 -2
  68. package/dist/lib.esm/connectors/injected-solana-connector/walletStandardConnector.js +3 -3
  69. package/dist/lib.esm/connectors/metamask-connector/metamaskConnector.js +80 -49
  70. package/dist/lib.esm/connectors/wallet-connect-v2-connector/WalletConnectV2Provider.js +2 -2
  71. package/dist/lib.esm/connectors/wallet-connect-v2-connector/walletConnectV2Connector.js +43 -15
  72. package/dist/lib.esm/connectors/wallet-connect-v2-connector/wcSolanaWallet.js +1 -1
  73. package/dist/lib.esm/index.js +4 -3
  74. package/dist/lib.esm/noModal.js +828 -119
  75. package/dist/lib.esm/plugins/wallet-services-plugin/plugin.js +3 -3
  76. package/dist/lib.esm/providers/base-provider/baseProvider.js +68 -38
  77. package/dist/lib.esm/react/context/useWeb3AuthInnerContextValue.js +36 -21
  78. package/dist/lib.esm/react/hooks/useWallets.js +33 -0
  79. package/dist/lib.esm/react/hooks/useWeb3AuthConnect.js +2 -2
  80. package/dist/lib.esm/react/index.js +1 -0
  81. package/dist/lib.esm/react/solana/hooks/useSolanaWallet.js +2 -2
  82. package/dist/lib.esm/react/solana/provider.js +4 -1
  83. package/dist/lib.esm/react/wagmi/provider.js +1 -1
  84. package/dist/lib.esm/vue/composables/useCheckout.js +1 -1
  85. package/dist/lib.esm/vue/composables/useFunding.js +1 -1
  86. package/dist/lib.esm/vue/composables/useReceive.js +1 -1
  87. package/dist/lib.esm/vue/composables/useSwap.js +1 -1
  88. package/dist/lib.esm/vue/composables/useWalletConnectScanner.js +1 -1
  89. package/dist/lib.esm/vue/composables/useWalletUI.js +1 -1
  90. package/dist/lib.esm/vue/composables/useWallets.js +35 -0
  91. package/dist/lib.esm/vue/composables/useWeb3AuthConnect.js +2 -2
  92. package/dist/lib.esm/vue/index.js +1 -0
  93. package/dist/lib.esm/vue/solana/composables/useSignAndSendTransaction.js +1 -1
  94. package/dist/lib.esm/vue/solana/composables/useSignMessage.js +1 -1
  95. package/dist/lib.esm/vue/solana/composables/useSignTransaction.js +1 -1
  96. package/dist/lib.esm/vue/solana/composables/useSolanaWallet.js +2 -2
  97. package/dist/lib.esm/vue/solana/provider.js +4 -0
  98. package/dist/lib.esm/vue/useWeb3AuthInnerContextValue.js +12 -3
  99. package/dist/lib.esm/vue/wagmi/provider.js +20 -8
  100. package/package.json +43 -19
@@ -1,21 +1,23 @@
1
1
  import _objectSpread from '@babel/runtime/helpers/objectSpread2';
2
2
  import _defineProperty from '@babel/runtime/helpers/defineProperty';
3
3
  import { CITADEL_SERVER_MAP } from '@toruslabs/constants';
4
- import { put } from '@toruslabs/http-helpers';
4
+ import { get, put } from '@toruslabs/http-helpers';
5
5
  import { SecurePubSub } from '@toruslabs/secure-pub-sub';
6
6
  import { BUILD_ENV, UX_MODE, Auth, SDK_MODE, SUPPORTED_KEY_CURVES, generateRecordId, version, createHandler, PopupHandler, getUserId } from '@web3auth/auth';
7
7
  import { WS_EMBED_LOGIN_MODE } from '@web3auth/ws-embed';
8
8
  import deepmerge from 'deepmerge';
9
9
  import { generateNonce, parseToken } from '../utils.js';
10
10
  import { AuthSolanaWallet } from './authSolanaWallet.js';
11
- import { BaseConnector } from '../../base/connector/baseConnector.js';
11
+ import { WalletLoginError, WalletInitializationError, Web3AuthError, AccountLinkingError } from '../../base/errors/index.js';
12
12
  import { WALLET_CONNECTORS } from '../../base/wallet/index.js';
13
+ import { BaseConnector } from '../../base/connector/baseConnector.js';
13
14
  import { CONNECTOR_NAMESPACES } from '../../base/chain/IChainInterface.js';
14
15
  import { CONNECTOR_CATEGORY, CONNECTOR_STATUS, CONNECTOR_EVENTS } from '../../base/connector/constants.js';
15
- import { WalletInitializationError, WalletLoginError, Web3AuthError } from '../../base/errors/index.js';
16
+ import { Analytics, ANALYTICS_EVENTS } from '../../base/analytics.js';
16
17
  import { log } from '../../base/loglevel.js';
17
- import { getCaipChainId } from '../../base/utils.js';
18
+ import { citadelServerUrl, getCaipChainId, getErrorAnalyticsProperties, parseChainNamespaceFromCitadelResponse } from '../../base/utils.js';
18
19
  import { CONNECTED_STATUSES } from '../../base/connector/connectorStatus.js';
20
+ import { makeAccountLinkingRequest, makeAccountUnlinkingRequest } from '../../account-linking/rest.js';
19
21
  import { CHAIN_NAMESPACES, cloneDeep } from '@toruslabs/base-controllers';
20
22
 
21
23
  class AuthConnector extends BaseConnector {
@@ -36,6 +38,7 @@ class AuthConnector extends BaseConnector {
36
38
  _defineProperty(this, "authConnectionConfig", []);
37
39
  _defineProperty(this, "wsEmbedInstancePromise", null);
38
40
  _defineProperty(this, "_solanaWallet", null);
41
+ _defineProperty(this, "analytics", void 0);
39
42
  this.authOptions = params.connectorSettings;
40
43
  this.loginSettings = params.loginSettings || {
41
44
  authConnection: ""
@@ -44,6 +47,7 @@ class AuthConnector extends BaseConnector {
44
47
  loginMode: WS_EMBED_LOGIN_MODE.PLUGIN
45
48
  };
46
49
  this.authConnectionConfig = params.authConnectionConfig || [];
50
+ this.analytics = params.analytics || new Analytics();
47
51
  }
48
52
  get provider() {
49
53
  if (this.status !== CONNECTOR_STATUS.NOT_READY) {
@@ -245,7 +249,9 @@ class AuthConnector extends BaseConnector {
245
249
  }
246
250
  this.rehydrated = false;
247
251
  this._solanaWallet = null;
248
- this.emit(CONNECTOR_EVENTS.DISCONNECTED);
252
+ this.emit(CONNECTOR_EVENTS.DISCONNECTED, {
253
+ connector: WALLET_CONNECTORS.AUTH
254
+ });
249
255
  }
250
256
  async getAuthTokenInfo() {
251
257
  if (!this.canAuthorize) throw WalletLoginError.notConnectedError("Not connected with wallet, Please login/connect first");
@@ -273,8 +279,24 @@ class AuthConnector extends BaseConnector {
273
279
  async getUserInfo() {
274
280
  if (!this.canAuthorize) throw WalletLoginError.notConnectedError("Not connected with wallet");
275
281
  if (!this.authInstance) throw WalletInitializationError.notReady("authInstance is not ready");
276
- const userInfo = this.authInstance.getUserInfo();
277
- return userInfo;
282
+ const [userInfo, linkedAccounts] = await Promise.all([this.authInstance.getUserInfo(), this.getLinkedAccounts()]);
283
+ return _objectSpread(_objectSpread({}, userInfo), {}, {
284
+ linkedAccounts
285
+ });
286
+ }
287
+ async getLinkedAccounts() {
288
+ const accessToken = await this.authInstance.authSessionManager.getAccessToken();
289
+ if (!accessToken) throw WalletLoginError.connectionError("Could not obtain an access token from the current AUTH session.");
290
+ const citadelUserInfo = await get(`${citadelServerUrl(this.coreOptions.authBuildEnv)}/v1/user`, {
291
+ headers: {
292
+ Authorization: `Bearer ${accessToken}`
293
+ }
294
+ });
295
+ const linkedAccounts = (citadelUserInfo === null || citadelUserInfo === void 0 ? void 0 : citadelUserInfo.accounts) || [];
296
+ return linkedAccounts.map(account => _objectSpread(_objectSpread({}, account), {}, {
297
+ // by default, the primary account is the active account
298
+ active: account.isPrimary
299
+ }));
278
300
  }
279
301
  async switchChain(params, init = false) {
280
302
  super.checkSwitchChainRequirements(params, init);
@@ -327,6 +349,347 @@ class AuthConnector extends BaseConnector {
327
349
  });
328
350
  return providerConfig;
329
351
  }
352
+ async generateChallengeAndSign() {
353
+ // we do not support this for auth connector, as of now. since auth login returns a valid idToken
354
+ throw new Error("Not implemented");
355
+ }
356
+ async switchAccount(account, context) {
357
+ if (!CONNECTED_STATUSES.includes(this.status)) {
358
+ throw WalletLoginError.notConnectedError("No wallet is connected. Connect with AUTH before switching accounts.");
359
+ }
360
+ try {
361
+ var _userInfo$linkedAccou;
362
+ const userInfo = await this.getUserInfo();
363
+ const linkedAccounts = (_userInfo$linkedAccou = userInfo.linkedAccounts) !== null && _userInfo$linkedAccou !== void 0 ? _userInfo$linkedAccou : [];
364
+ const targetAccount = linkedAccounts.find(candidate => candidate.id === account.id);
365
+ if (!targetAccount) {
366
+ throw AccountLinkingError.requestFailed(`No connected wallet matches account id "${account.id}". Refresh user info and try again.`);
367
+ }
368
+ const currentActiveAccount = context.activeAccount;
369
+ const isTargetAlreadyActive = currentActiveAccount ? currentActiveAccount.id === targetAccount.id : targetAccount.isPrimary;
370
+ if (isTargetAlreadyActive) {
371
+ return;
372
+ }
373
+ this.analytics.track(ANALYTICS_EVENTS.ACCOUNT_SWITCH_STARTED, this.getSwitchAccountTrackData(targetAccount));
374
+ if (targetAccount.connector === WALLET_CONNECTORS.AUTH && targetAccount.isPrimary) {
375
+ var _this$provider$chainI, _this$provider;
376
+ const activeChainId = this.getChainIdForLinkedAccount(targetAccount, (_this$provider$chainI = (_this$provider = this.provider) === null || _this$provider === void 0 ? void 0 : _this$provider.chainId) !== null && _this$provider$chainI !== void 0 ? _this$provider$chainI : context.currentChainId);
377
+ const ethereumProvider = this.provider;
378
+ const solanaWallet = this.solanaWallet;
379
+ if (!ethereumProvider && !solanaWallet) {
380
+ throw AccountLinkingError.requestFailed("Failed to restore the primary AUTH session for account switch.");
381
+ }
382
+ return {
383
+ kind: "primary",
384
+ targetAccount,
385
+ activeAccount: null,
386
+ activeChainId,
387
+ connectorName: this.name,
388
+ connectorNamespace: this.connectorNamespace,
389
+ ethereumProvider,
390
+ solanaWallet
391
+ };
392
+ }
393
+ return {
394
+ kind: "external",
395
+ targetAccount,
396
+ activeAccount: targetAccount,
397
+ activeChainId: this.getChainIdForLinkedAccount(targetAccount, context.currentChainId)
398
+ };
399
+ } catch (error) {
400
+ await this.trackSwitchAccountFailed(account, error);
401
+ throw error;
402
+ }
403
+ }
404
+ async trackSwitchAccountCompleted(account) {
405
+ await this.analytics.track(ANALYTICS_EVENTS.ACCOUNT_SWITCH_COMPLETED, _objectSpread(_objectSpread({}, this.getSwitchAccountTrackData(account)), {}, {
406
+ connector: account.connector
407
+ }));
408
+ }
409
+ async trackSwitchAccountFailed(account, error) {
410
+ await this.analytics.track(ANALYTICS_EVENTS.ACCOUNT_SWITCH_FAILED, _objectSpread(_objectSpread({}, this.getSwitchAccountTrackData(account)), getErrorAnalyticsProperties(error)));
411
+ }
412
+ async linkAccount(params) {
413
+ if (!CONNECTED_STATUSES.includes(this.status)) {
414
+ throw WalletLoginError.notConnectedError("No wallet is connected. Connect with AUTH before linking an account.");
415
+ }
416
+ const {
417
+ connectorName,
418
+ chainId,
419
+ walletConnector
420
+ } = params;
421
+ try {
422
+ if (!walletConnector.connected) {
423
+ const connection = await walletConnector.connect({
424
+ chainId,
425
+ isAccountLinking: true
426
+ });
427
+ if (!connection) {
428
+ throw AccountLinkingError.walletProofFailed(`Failed to connect to "${params.connectorName}" for account linking.`);
429
+ }
430
+ }
431
+ } catch (error) {
432
+ if (error instanceof AccountLinkingError) {
433
+ throw error;
434
+ }
435
+ throw AccountLinkingError.walletProofFailed(error instanceof Error ? error.message : String(error), error);
436
+ }
437
+ const trackData = {
438
+ connector: this.name,
439
+ linking_connector: connectorName,
440
+ chain_id: params.chainId
441
+ };
442
+ try {
443
+ await this.analytics.track(ANALYTICS_EVENTS.ACCOUNT_LINKING_STARTED, trackData);
444
+ const {
445
+ accessToken,
446
+ idToken
447
+ } = await this.getPrimaryAuthSession(params.authSessionTokens);
448
+ const walletProof = await this.createWalletLinkingProof(params.walletConnector);
449
+ const authServerUrl = citadelServerUrl(this.coreOptions.authBuildEnv);
450
+ const result = await makeAccountLinkingRequest(authServerUrl, accessToken, {
451
+ idToken,
452
+ network: walletProof.network,
453
+ connector: params.connectorName,
454
+ message: walletProof.challenge,
455
+ signature: {
456
+ s: walletProof.signature,
457
+ t: walletProof.signatureType
458
+ }
459
+ });
460
+ this.analytics.track(ANALYTICS_EVENTS.ACCOUNT_LINKING_COMPLETED, _objectSpread(_objectSpread({}, trackData), {}, {
461
+ linked_address: walletProof.address
462
+ }));
463
+ return result;
464
+ } catch (error) {
465
+ this.analytics.track(ANALYTICS_EVENTS.ACCOUNT_LINKING_FAILED, _objectSpread(_objectSpread({}, trackData), getErrorAnalyticsProperties(error)));
466
+
467
+ // disconnect the wallet connector to avoid any leftover state
468
+ try {
469
+ await walletConnector.disconnect({
470
+ cleanup: true
471
+ });
472
+ } catch (disconnectError) {
473
+ log.debug("Failed to disconnect wallet connector after linking failure", disconnectError);
474
+ }
475
+ throw error;
476
+ }
477
+ }
478
+ async unlinkAccount(params) {
479
+ if (!CONNECTED_STATUSES.includes(this.status)) {
480
+ throw WalletLoginError.notConnectedError("No wallet is connected. Connect with AUTH before unlinking an account.");
481
+ }
482
+ const {
483
+ address,
484
+ authSessionTokens
485
+ } = params;
486
+ const trackData = {
487
+ connector: this.name,
488
+ address
489
+ };
490
+ await this.analytics.track(ANALYTICS_EVENTS.ACCOUNT_UNLINKING_STARTED, trackData);
491
+ try {
492
+ const {
493
+ accessToken,
494
+ idToken,
495
+ linkedAccounts
496
+ } = await this.getPrimaryAuthSession(authSessionTokens, {
497
+ includeLinkedAccounts: true
498
+ });
499
+ const network = this.getNetworkForUnlinkAddress(linkedAccounts, address);
500
+ const authServerUrl = citadelServerUrl(this.coreOptions.authBuildEnv);
501
+ const result = await makeAccountUnlinkingRequest(authServerUrl, accessToken, {
502
+ idToken,
503
+ address,
504
+ network
505
+ });
506
+ await this.analytics.track(ANALYTICS_EVENTS.ACCOUNT_UNLINKING_COMPLETED, _objectSpread(_objectSpread({}, trackData), {}, {
507
+ linked_address: address
508
+ }));
509
+ return result;
510
+ } catch (error) {
511
+ await this.analytics.track(ANALYTICS_EVENTS.ACCOUNT_UNLINKING_FAILED, _objectSpread(_objectSpread({}, trackData), getErrorAnalyticsProperties(error)));
512
+ throw error;
513
+ }
514
+ }
515
+ getChainIdForLinkedAccount(account, preferredChainId) {
516
+ const accountChainNamespace = account.chainNamespace ? parseChainNamespaceFromCitadelResponse(account.chainNamespace) : null;
517
+ if (preferredChainId) {
518
+ const preferredChain = this.coreOptions.chains.find(chain => chain.chainId === preferredChainId);
519
+ if (preferredChain && (!accountChainNamespace || preferredChain.chainNamespace === accountChainNamespace)) {
520
+ return preferredChainId;
521
+ }
522
+ }
523
+ if (accountChainNamespace) {
524
+ const namespaceChain = this.coreOptions.chains.find(chain => chain.chainNamespace === accountChainNamespace);
525
+ if (namespaceChain) {
526
+ return namespaceChain.chainId;
527
+ }
528
+ }
529
+ throw WalletInitializationError.invalidParams(`No compatible chainId found for connector "${account.connector}".`);
530
+ }
531
+ async assertSwitchAccountConnectorMatchesTarget(connector, account) {
532
+ if (!account.chainNamespace) {
533
+ throw AccountLinkingError.requestFailed(`Could not determine the chain namespace for linked account "${account.eoaAddress}".`);
534
+ }
535
+ const chainNamespace = parseChainNamespaceFromCitadelResponse(account.chainNamespace);
536
+ let connectedAddress = null;
537
+ if (chainNamespace === CHAIN_NAMESPACES.EIP155) {
538
+ var _accounts$;
539
+ const accounts = connector.provider ? await connector.provider.request({
540
+ method: "eth_accounts"
541
+ }) : [];
542
+ connectedAddress = (_accounts$ = accounts === null || accounts === void 0 ? void 0 : accounts[0]) !== null && _accounts$ !== void 0 ? _accounts$ : null;
543
+ } else if (chainNamespace === CHAIN_NAMESPACES.SOLANA) {
544
+ var _connector$solanaWall, _connector$solanaWall2;
545
+ connectedAddress = (_connector$solanaWall = (_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) !== null && _connector$solanaWall !== void 0 ? _connector$solanaWall : null;
546
+ } else {
547
+ throw AccountLinkingError.requestFailed(`Unsupported chain namespace "${account.chainNamespace}" for linked account "${account.eoaAddress}".`);
548
+ }
549
+ if (!connectedAddress) {
550
+ throw AccountLinkingError.requestFailed(`Connector "${account.connector}" is not connected to linked account "${account.eoaAddress}". Connect the intended wallet account and try again.`);
551
+ }
552
+ const isExpectedAddress = chainNamespace === CHAIN_NAMESPACES.EIP155 ? connectedAddress.toLowerCase() === account.eoaAddress.toLowerCase() : connectedAddress === account.eoaAddress;
553
+ if (!isExpectedAddress) {
554
+ throw AccountLinkingError.requestFailed(`Connector "${account.connector}" is connected to "${connectedAddress}" instead of linked account "${account.eoaAddress}". Connect the intended wallet account and try again.`);
555
+ }
556
+ }
557
+ toSwitchAccountConnectorError(account, error) {
558
+ if (error instanceof AccountLinkingError && error.code === 5401) {
559
+ return error;
560
+ }
561
+ const message = error instanceof Error ? error.message : String(error);
562
+ const isUnavailableConnectorError = error instanceof AccountLinkingError && error.code === 5405 || /not available|not initialized|not ready/i.test(message);
563
+ if (isUnavailableConnectorError) {
564
+ return AccountLinkingError.requestFailed(`Connector "${account.connector}" is not available for linked account "${account.eoaAddress}". Make sure the wallet is installed, unlocked, and accessible, then try again.`, error);
565
+ }
566
+ return AccountLinkingError.requestFailed(`Failed to connect connector "${account.connector}" for linked account "${account.eoaAddress}". ${message}`, error);
567
+ }
568
+ getSwitchAccountTrackData(account) {
569
+ var _account$eoaAddress;
570
+ return {
571
+ connector: this.name,
572
+ account_id: account.id,
573
+ account_type: account.accountType,
574
+ switched_to_address: (_account$eoaAddress = account.eoaAddress) !== null && _account$eoaAddress !== void 0 ? _account$eoaAddress : null
575
+ };
576
+ }
577
+ async getPrimaryAuthSession(authSessionTokens, options = {}) {
578
+ const {
579
+ accessToken: cachedAccessToken,
580
+ idToken: cachedIdToken
581
+ } = authSessionTokens;
582
+ const {
583
+ includeLinkedAccounts = false
584
+ } = options;
585
+ let accessToken = cachedAccessToken;
586
+ let idToken = cachedIdToken;
587
+ let linkedAccounts = [];
588
+ if (includeLinkedAccounts) {
589
+ const userInfoPromise = this.getUserInfo();
590
+ if (!accessToken || !idToken) {
591
+ var _userInfo$linkedAccou2;
592
+ const [tokenInfo, userInfo] = await Promise.all([this.getAuthTokenInfo(), userInfoPromise]);
593
+ accessToken = tokenInfo.accessToken;
594
+ idToken = tokenInfo.idToken;
595
+ linkedAccounts = (_userInfo$linkedAccou2 = userInfo.linkedAccounts) !== null && _userInfo$linkedAccou2 !== void 0 ? _userInfo$linkedAccou2 : [];
596
+ } else {
597
+ var _userInfo$linkedAccou3;
598
+ const userInfo = await userInfoPromise;
599
+ linkedAccounts = (_userInfo$linkedAccou3 = userInfo.linkedAccounts) !== null && _userInfo$linkedAccou3 !== void 0 ? _userInfo$linkedAccou3 : [];
600
+ }
601
+ } else if (!accessToken || !idToken) {
602
+ const tokenInfo = await this.getAuthTokenInfo();
603
+ accessToken = tokenInfo.accessToken;
604
+ idToken = tokenInfo.idToken;
605
+ }
606
+ if (!accessToken || !idToken) {
607
+ throw AccountLinkingError.primaryTokenNotAvailable("Could not obtain an identity token from the current AUTH session.");
608
+ }
609
+ return {
610
+ accessToken,
611
+ idToken,
612
+ linkedAccounts
613
+ };
614
+ }
615
+ getNetworkForUnlinkAddress(accounts, address) {
616
+ const matchedAccount = accounts.find(account => {
617
+ var _account$address, _account$eoaAddress2;
618
+ if (!account.chainNamespace || parseChainNamespaceFromCitadelResponse(account.chainNamespace) !== CHAIN_NAMESPACES.EIP155) {
619
+ return false;
620
+ }
621
+ const normalizedAddress = address.toLowerCase();
622
+ return ((_account$address = account.address) === null || _account$address === void 0 ? void 0 : _account$address.toLowerCase()) === normalizedAddress || ((_account$eoaAddress2 = account.eoaAddress) === null || _account$eoaAddress2 === void 0 ? void 0 : _account$eoaAddress2.toLowerCase()) === normalizedAddress;
623
+ });
624
+ if (!matchedAccount) {
625
+ throw AccountLinkingError.requestFailed(`No connected wallet matches address "${address}".`);
626
+ }
627
+ if (!matchedAccount.chainNamespace) {
628
+ throw AccountLinkingError.requestFailed(`Could not determine the chain namespace for address "${address}".`);
629
+ }
630
+ const chainNamespace = parseChainNamespaceFromCitadelResponse(matchedAccount.chainNamespace);
631
+ if (chainNamespace === CHAIN_NAMESPACES.EIP155) {
632
+ return "ethereum";
633
+ }
634
+ if (chainNamespace === CHAIN_NAMESPACES.SOLANA) {
635
+ return "solana";
636
+ }
637
+ throw AccountLinkingError.requestFailed(`Unsupported chain namespace "${matchedAccount.chainNamespace}" for address "${address}".`);
638
+ }
639
+ async createWalletLinkingProof(connector) {
640
+ // Notify listeners that the linking wallet is about to be asked for a signature so the UI
641
+ // (e.g. modal) can switch from a "connecting" loader to an "authorizing" prompt while the
642
+ // user reviews the signature request inside their wallet. Emitted on the isolated wallet
643
+ // connector (not the auth connector) so it doesn't mutate the global SDK status.
644
+ connector.emit(CONNECTOR_EVENTS.AUTHORIZING, {
645
+ connector: connector.name
646
+ });
647
+ const {
648
+ challenge,
649
+ signature,
650
+ chainNamespace
651
+ } = await connector.generateChallengeAndSign();
652
+ const address = await this.getLinkingWalletAddress(connector, chainNamespace);
653
+ if (chainNamespace === CHAIN_NAMESPACES.EIP155) {
654
+ return {
655
+ address,
656
+ challenge,
657
+ signature,
658
+ signatureType: "eip191",
659
+ network: "ethereum"
660
+ };
661
+ }
662
+ if (chainNamespace === CHAIN_NAMESPACES.SOLANA) {
663
+ return {
664
+ address,
665
+ challenge,
666
+ signature,
667
+ signatureType: "sip99",
668
+ network: "solana"
669
+ };
670
+ }
671
+ throw AccountLinkingError.unsupportedConnector(`Connector "${connector.name}" returned unsupported chain namespace "${chainNamespace}".`);
672
+ }
673
+ async getLinkingWalletAddress(connector, chainNamespace) {
674
+ if (chainNamespace === CHAIN_NAMESPACES.SOLANA) {
675
+ var _connector$solanaWall3;
676
+ const address = (_connector$solanaWall3 = connector.solanaWallet) === null || _connector$solanaWall3 === void 0 || (_connector$solanaWall3 = _connector$solanaWall3.accounts) === null || _connector$solanaWall3 === void 0 || (_connector$solanaWall3 = _connector$solanaWall3[0]) === null || _connector$solanaWall3 === void 0 ? void 0 : _connector$solanaWall3.address;
677
+ if (!address) {
678
+ throw AccountLinkingError.walletProofFailed("No connected Solana account found for account linking.");
679
+ }
680
+ return address;
681
+ }
682
+ if (!connector.provider) {
683
+ throw AccountLinkingError.walletProofFailed("No connected EVM account found for account linking.");
684
+ }
685
+ const accounts = await connector.provider.request({
686
+ method: "eth_accounts"
687
+ });
688
+ if (!(accounts !== null && accounts !== void 0 && accounts.length)) {
689
+ throw AccountLinkingError.walletProofFailed("No connected EVM account found for account linking.");
690
+ }
691
+ return accounts[0];
692
+ }
330
693
  setupSolanaWallet() {
331
694
  const solanaChains = this.coreOptions.chains.filter(c => c.chainNamespace === CHAIN_NAMESPACES.SOLANA);
332
695
  if (solanaChains.length === 0 || !this.provider) return;
@@ -653,7 +1016,8 @@ class AuthConnector extends BaseConnector {
653
1016
  const authConnector = params => {
654
1017
  return ({
655
1018
  projectConfig,
656
- coreOptions
1019
+ coreOptions,
1020
+ analytics
657
1021
  }) => {
658
1022
  var _coreOptions$uiConfig, _coreOptions$walletSe, _coreOptions$walletSe2, _coreOptions$walletSe3;
659
1023
  // Connector settings
@@ -698,9 +1062,22 @@ const authConnector = params => {
698
1062
  mfaLevel: coreOptions.mfaLevel
699
1063
  }),
700
1064
  coreOptions,
1065
+ analytics,
701
1066
  authConnectionConfig: projectConfig.embeddedWalletAuth
702
1067
  });
703
1068
  };
704
1069
  };
1070
+ function isAuthConnector(connector) {
1071
+ if (!connector || connector.name !== WALLET_CONNECTORS.AUTH) {
1072
+ return false;
1073
+ }
1074
+ const maybeAuthConnector = connector;
1075
+ return typeof maybeAuthConnector.switchAccount === "function" && typeof maybeAuthConnector.linkAccount === "function" && typeof maybeAuthConnector.unlinkAccount === "function";
1076
+ }
1077
+ function assertAuthConnector(connector, errorMessage = "Account linking is only supported when connected with the AUTH connector.") {
1078
+ if (!isAuthConnector(connector)) {
1079
+ throw WalletLoginError.unsupportedOperation(errorMessage);
1080
+ }
1081
+ }
705
1082
 
706
- export { authConnector };
1083
+ export { assertAuthConnector, authConnector, isAuthConnector };
@@ -2,9 +2,9 @@ import { signChallenge } from '@toruslabs/base-controllers';
2
2
  import { bytesToHexPrefixedString, utf8ToBytes } from '@toruslabs/metadata-helpers';
3
3
  import { EVM_METHOD_TYPES } from '@web3auth/ws-embed';
4
4
  import { generateSiweNonce } from 'viem/siwe';
5
+ import { WalletLoginError, WalletInitializationError } from '../../base/errors/index.js';
5
6
  import { citadelServerUrl } from '../../base/utils.js';
6
7
  import { BaseConnector } from '../../base/connector/baseConnector.js';
7
- import { WalletLoginError, WalletInitializationError } from '../../base/errors/index.js';
8
8
  import { CONNECTOR_STATUS, CONNECTOR_EVENTS } from '../../base/connector/constants.js';
9
9
 
10
10
  class BaseEvmConnector extends BaseConnector {
@@ -22,39 +22,58 @@ class BaseEvmConnector extends BaseConnector {
22
22
  if (accounts && accounts.length > 0) {
23
23
  const cached = await this.getCachedOrNullAuthTokenInfo(accounts[0]);
24
24
  if (cached) return cached;
25
- const chainId = await this.provider.request({
26
- method: "eth_chainId"
27
- });
28
- const currentChainConfig = this.coreOptions.chains.find(x => x.chainId === chainId);
29
- if (!currentChainConfig) throw WalletInitializationError.invalidParams("chainConfig is required before authentication");
25
+ const authServer = citadelServerUrl(this.coreOptions.authBuildEnv);
30
26
  const {
27
+ challenge,
28
+ signature,
31
29
  chainNamespace
32
- } = currentChainConfig;
33
- const authServer = citadelServerUrl(this.coreOptions.authBuildEnv);
34
- const payload = {
35
- domain: window.location.origin,
36
- uri: window.location.href,
37
- address: accounts[0],
38
- chainId: parseInt(chainId, 16),
39
- version: "1",
40
- nonce: generateSiweNonce(),
41
- issuedAt: new Date().toISOString()
42
- };
43
- const challenge = await signChallenge(payload, chainNamespace, authServer);
44
- const hexChallenge = bytesToHexPrefixedString(utf8ToBytes(challenge));
45
- const signedMessage = await this.provider.request({
46
- method: EVM_METHOD_TYPES.PERSONAL_SIGN,
47
- params: [hexChallenge, accounts[0]]
48
- });
30
+ } = await this.generateChallengeAndSign(authServer, accounts);
49
31
  return this.verifyAndAuthorize({
50
32
  chainNamespace,
51
- signedMessage,
33
+ signedMessage: signature,
52
34
  challenge,
53
35
  authServer
54
36
  });
55
37
  }
56
38
  throw WalletLoginError.notConnectedError("Not connected with wallet, Please login/connect first");
57
39
  }
40
+ async generateChallengeAndSign(authServerUrl, accounts) {
41
+ const accountsToUse = accounts || (await this.provider.request({
42
+ method: EVM_METHOD_TYPES.GET_ACCOUNTS
43
+ }));
44
+ if (!accountsToUse || accountsToUse.length === 0) {
45
+ throw WalletLoginError.notConnectedError("No accounts found in the connected wallet");
46
+ }
47
+ const chainId = await this.provider.request({
48
+ method: "eth_chainId"
49
+ });
50
+ const currentChainConfig = this.coreOptions.chains.find(x => x.chainId === chainId);
51
+ if (!currentChainConfig) throw WalletInitializationError.invalidParams("chainConfig is required before authentication");
52
+ const {
53
+ chainNamespace
54
+ } = currentChainConfig;
55
+ const authServer = authServerUrl || citadelServerUrl(this.coreOptions.authBuildEnv);
56
+ const payload = {
57
+ domain: window.location.origin,
58
+ uri: window.location.href,
59
+ address: accountsToUse[0],
60
+ chainId: parseInt(chainId, 16),
61
+ version: "1",
62
+ nonce: generateSiweNonce(),
63
+ issuedAt: new Date().toISOString()
64
+ };
65
+ const challenge = await signChallenge(payload, chainNamespace, authServer);
66
+ const hexChallenge = bytesToHexPrefixedString(utf8ToBytes(challenge));
67
+ const signature = await this.provider.request({
68
+ method: EVM_METHOD_TYPES.PERSONAL_SIGN,
69
+ params: [hexChallenge, accountsToUse[0]]
70
+ });
71
+ return {
72
+ challenge,
73
+ signature,
74
+ chainNamespace
75
+ };
76
+ }
58
77
  async disconnectSession() {
59
78
  super.checkDisconnectionRequirements();
60
79
  await this.clearWalletSession();
@@ -1,10 +1,10 @@
1
1
  import { CHAIN_NAMESPACES, signChallenge } from '@toruslabs/base-controllers';
2
2
  import { generateSiweNonce } from 'viem/siwe';
3
+ import { WalletLoginError, WalletInitializationError } from '../../base/errors/index.js';
4
+ import { citadelServerUrl } from '../../base/utils.js';
3
5
  import { getSolanaChainByChainConfig, walletSignMessage } from '../../base/wallet/solana.js';
4
6
  import { BaseConnector } from '../../base/connector/baseConnector.js';
5
- import { WalletLoginError, WalletInitializationError } from '../../base/errors/index.js';
6
7
  import { CONNECTOR_STATUS, CONNECTOR_EVENTS } from '../../base/connector/constants.js';
7
- import { citadelServerUrl } from '../../base/utils.js';
8
8
 
9
9
  class BaseSolanaConnector extends BaseConnector {
10
10
  async init(_) {}
@@ -19,40 +19,57 @@ class BaseSolanaConnector extends BaseConnector {
19
19
  if (accounts.length > 0) {
20
20
  const cached = await this.getCachedOrNullAuthTokenInfo(accounts[0]);
21
21
  if (cached) return cached;
22
- const walletChains = new Set(this.solanaWallet.chains);
23
- const currentChainConfig = this.coreOptions.chains.find(c => {
24
- if (c.chainNamespace !== CHAIN_NAMESPACES.SOLANA) return false;
25
- const id = getSolanaChainByChainConfig(c);
26
- return id != null && walletChains.has(id);
27
- });
28
- if (!currentChainConfig) {
29
- throw WalletInitializationError.invalidParams("No Solana chain in common between the connected wallet and Web3Auth chain configuration");
30
- }
22
+ const authServer = citadelServerUrl(this.coreOptions.authBuildEnv);
31
23
  const {
32
- chainId,
24
+ challenge,
25
+ signature,
33
26
  chainNamespace
34
- } = currentChainConfig;
35
- const authServer = citadelServerUrl(this.coreOptions.authBuildEnv);
36
- const payload = {
37
- domain: window.location.origin,
38
- uri: window.location.href,
39
- address: accounts[0],
40
- chainId: parseInt(chainId, 16),
41
- version: "1",
42
- nonce: generateSiweNonce(),
43
- issuedAt: new Date().toISOString()
44
- };
45
- const challenge = await signChallenge(payload, chainNamespace, authServer);
46
- const signedMessage = await walletSignMessage(this.solanaWallet, challenge, accounts[0]);
27
+ } = await this.generateChallengeAndSign(authServer);
47
28
  return this.verifyAndAuthorize({
48
29
  chainNamespace,
49
- signedMessage,
30
+ signedMessage: signature,
50
31
  challenge,
51
32
  authServer
52
33
  });
53
34
  }
54
35
  throw WalletLoginError.notConnectedError("Not connected with wallet, Please login/connect first");
55
36
  }
37
+ async generateChallengeAndSign(authServerUrl, accounts) {
38
+ const accountsToUse = accounts || this.solanaWallet.accounts.map(a => a.address);
39
+ if (!accountsToUse || accountsToUse.length === 0) {
40
+ throw WalletLoginError.notConnectedError("No accounts found in the connected wallet");
41
+ }
42
+ const walletChains = new Set(this.solanaWallet.chains);
43
+ const currentChainConfig = this.coreOptions.chains.find(c => {
44
+ if (c.chainNamespace !== CHAIN_NAMESPACES.SOLANA) return false;
45
+ const id = getSolanaChainByChainConfig(c);
46
+ return id != null && walletChains.has(id);
47
+ });
48
+ if (!currentChainConfig) {
49
+ throw WalletInitializationError.invalidParams("No Solana chain in common between the connected wallet and Web3Auth chain configuration");
50
+ }
51
+ const {
52
+ chainId,
53
+ chainNamespace
54
+ } = currentChainConfig;
55
+ const authServer = authServerUrl || citadelServerUrl(this.coreOptions.authBuildEnv);
56
+ const payload = {
57
+ domain: window.location.origin,
58
+ uri: window.location.href,
59
+ address: accountsToUse[0],
60
+ chainId: parseInt(chainId, 16),
61
+ version: "1",
62
+ nonce: generateSiweNonce(),
63
+ issuedAt: new Date().toISOString()
64
+ };
65
+ const challenge = await signChallenge(payload, chainNamespace, authServer);
66
+ const signedMessage = await walletSignMessage(this.solanaWallet, challenge, accountsToUse[0]);
67
+ return {
68
+ challenge,
69
+ signature: signedMessage,
70
+ chainNamespace
71
+ };
72
+ }
56
73
  async disconnectSession() {
57
74
  super.checkDisconnectionRequirements();
58
75
  await this.clearWalletSession();
@@ -2,10 +2,10 @@ import _objectSpread from '@babel/runtime/helpers/objectSpread2';
2
2
  import _defineProperty from '@babel/runtime/helpers/defineProperty';
3
3
  import { BaseEvmConnector } from '../base-evm-connector/baseEvmConnector.js';
4
4
  import { CONNECTOR_NAMESPACES } from '../../base/chain/IChainInterface.js';
5
- import { CHAIN_NAMESPACES } from '@toruslabs/base-controllers';
6
- import { CONNECTOR_CATEGORY, CONNECTOR_STATUS, CONNECTOR_EVENTS } from '../../base/connector/constants.js';
7
5
  import { WALLET_CONNECTORS } from '../../base/wallet/index.js';
8
6
  import { WalletLoginError, Web3AuthError } from '../../base/errors/index.js';
7
+ import { CHAIN_NAMESPACES } from '@toruslabs/base-controllers';
8
+ import { CONNECTOR_CATEGORY, CONNECTOR_STATUS, CONNECTOR_EVENTS } from '../../base/connector/constants.js';
9
9
 
10
10
  class CoinbaseConnector extends BaseEvmConnector {
11
11
  constructor(connectorOptions) {
@@ -2,10 +2,10 @@ import _defineProperty from '@babel/runtime/helpers/defineProperty';
2
2
  import { normalizeWalletName } from '../../base/utils.js';
3
3
  import { BaseEvmConnector } from '../base-evm-connector/baseEvmConnector.js';
4
4
  import { CONNECTOR_NAMESPACES } from '../../base/chain/IChainInterface.js';
5
- import { CHAIN_NAMESPACES } from '@toruslabs/base-controllers';
6
- import { CONNECTOR_CATEGORY, CONNECTOR_STATUS, CONNECTOR_EVENTS } from '../../base/connector/constants.js';
7
5
  import { log } from '../../base/loglevel.js';
8
6
  import { WalletLoginError, Web3AuthError } from '../../base/errors/index.js';
7
+ import { CHAIN_NAMESPACES } from '@toruslabs/base-controllers';
8
+ import { CONNECTOR_CATEGORY, CONNECTOR_STATUS, CONNECTOR_EVENTS } from '../../base/connector/constants.js';
9
9
 
10
10
  class InjectedEvmConnector extends BaseEvmConnector {
11
11
  constructor(options) {