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