@dynamic-labs/sdk-react-core 4.92.0 → 4.92.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.
- package/CHANGELOG.md +11 -0
- package/package.cjs +1 -1
- package/package.js +1 -1
- package/package.json +12 -12
- package/src/lib/context/ErrorContext/ErrorContext.cjs +20 -3
- package/src/lib/context/ErrorContext/ErrorContext.d.ts +13 -0
- package/src/lib/context/ErrorContext/ErrorContext.js +19 -4
- package/src/lib/context/PhantomRedirectContext/useResponseHandlers.cjs +10 -1
- package/src/lib/context/PhantomRedirectContext/useResponseHandlers.js +11 -2
- package/src/lib/utils/hooks/useSocialAuth/useSocialAuth.cjs +7 -1
- package/src/lib/utils/hooks/useSocialAuth/useSocialAuth.js +7 -1
- package/src/lib/utils/hooks/useSwitchWallet/useSwitchWallet.cjs +14 -0
- package/src/lib/utils/hooks/useSwitchWallet/useSwitchWallet.js +14 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
|
|
2
|
+
### [4.92.1](https://github.com/dynamic-labs/dynamic-auth/compare/v4.92.0...v4.92.1) (2026-07-09)
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
### Bug Fixes
|
|
6
|
+
|
|
7
|
+
* **ethereum:** fire in-app-browser redirect on sign for injected EVM wallets that use in-app-browser experience ([#11888](https://github.com/dynamic-labs/dynamic-auth/issues/11888)) ([5116d91](https://github.com/dynamic-labs/dynamic-auth/commit/5116d91ab2c71000a490d72c5d278549d4d8ae9a))
|
|
8
|
+
* **sdk-react-core:** show clear message for Phantom redirect signing failures (v4 backport) ([#11886](https://github.com/dynamic-labs/dynamic-auth/issues/11886)) ([60ac897](https://github.com/dynamic-labs/dynamic-auth/commit/60ac897ba81f7758ccd7a05f97b619785e1f50a7))
|
|
9
|
+
* **social:** use redirect strategy for step-up OAuth on mobile [V4 backport] ([#11881](https://github.com/dynamic-labs/dynamic-auth/issues/11881)) ([42a202e](https://github.com/dynamic-labs/dynamic-auth/commit/42a202e6255de8db73df02eff37c0b10b24fef1a))
|
|
10
|
+
* **solana:** fire in-app-browser redirect on sign and wallet switch ([#11871](https://github.com/dynamic-labs/dynamic-auth/issues/11871)) ([4e2d6b7](https://github.com/dynamic-labs/dynamic-auth/commit/4e2d6b7ac8fdef5bf7c62b8a726ecaef1c6210ec))
|
|
11
|
+
* **solana:** resolve Phantom/Backpack provider collision and Backpack >=0.10.x connect hangs ([#11856](https://github.com/dynamic-labs/dynamic-auth/issues/11856)) ([#11882](https://github.com/dynamic-labs/dynamic-auth/issues/11882)) ([5784aff](https://github.com/dynamic-labs/dynamic-auth/commit/5784aff9641bbc85445fb466f3ab1d6a14331e73))
|
|
12
|
+
|
|
2
13
|
## [4.92.0](https://github.com/dynamic-labs/dynamic-auth/compare/v4.91.6...v4.92.0) (2026-07-08)
|
|
3
14
|
|
|
4
15
|
|
package/package.cjs
CHANGED
package/package.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dynamic-labs/sdk-react-core",
|
|
3
|
-
"version": "4.92.
|
|
3
|
+
"version": "4.92.1",
|
|
4
4
|
"dependencies": {
|
|
5
5
|
"@dynamic-labs/sdk-api-core": "0.0.1067",
|
|
6
6
|
"@dynamic-labs-sdk/client": "1.18.0",
|
|
@@ -18,17 +18,17 @@
|
|
|
18
18
|
"react-i18next": "13.5.0",
|
|
19
19
|
"react-international-phone": "4.5.0",
|
|
20
20
|
"yup": "0.32.11",
|
|
21
|
-
"@dynamic-labs/assert-package-version": "4.92.
|
|
22
|
-
"@dynamic-labs/iconic": "4.92.
|
|
23
|
-
"@dynamic-labs/locale": "4.92.
|
|
24
|
-
"@dynamic-labs/logger": "4.92.
|
|
25
|
-
"@dynamic-labs/multi-wallet": "4.92.
|
|
26
|
-
"@dynamic-labs/rpc-providers": "4.92.
|
|
27
|
-
"@dynamic-labs/store": "4.92.
|
|
28
|
-
"@dynamic-labs/types": "4.92.
|
|
29
|
-
"@dynamic-labs/utils": "4.92.
|
|
30
|
-
"@dynamic-labs/wallet-book": "4.92.
|
|
31
|
-
"@dynamic-labs/wallet-connector-core": "4.92.
|
|
21
|
+
"@dynamic-labs/assert-package-version": "4.92.1",
|
|
22
|
+
"@dynamic-labs/iconic": "4.92.1",
|
|
23
|
+
"@dynamic-labs/locale": "4.92.1",
|
|
24
|
+
"@dynamic-labs/logger": "4.92.1",
|
|
25
|
+
"@dynamic-labs/multi-wallet": "4.92.1",
|
|
26
|
+
"@dynamic-labs/rpc-providers": "4.92.1",
|
|
27
|
+
"@dynamic-labs/store": "4.92.1",
|
|
28
|
+
"@dynamic-labs/types": "4.92.1",
|
|
29
|
+
"@dynamic-labs/utils": "4.92.1",
|
|
30
|
+
"@dynamic-labs/wallet-book": "4.92.1",
|
|
31
|
+
"@dynamic-labs/wallet-connector-core": "4.92.1",
|
|
32
32
|
"eventemitter3": "5.0.1"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
@@ -16,6 +16,14 @@ const UNLOCK_WALLET_MESSAGE = 'Please unlock your wallet extension and try again
|
|
|
16
16
|
const INTERNAL_ERROR_MESSAGE = 'There was an internal error. Please try again.';
|
|
17
17
|
const AUTHENTICATION_FAILED_MESSAGE = 'Authentication failed. Please try again.';
|
|
18
18
|
const SESSION_TIMEOUT_MESSAGE = 'Session time out. Please try again.';
|
|
19
|
+
const PHANTOM_SIGNING_FAILED_MESSAGE = "Phantom couldn't sign with the selected account. Switch accounts in Phantom or update the app, then try again.";
|
|
20
|
+
/**
|
|
21
|
+
* Error code used when Phantom relays an internal signing failure via its
|
|
22
|
+
* deep-link redirect (e.g. the active account has no usable key to sign).
|
|
23
|
+
* Phantom's own code for these is generic (e.g. `500`), so we normalize to
|
|
24
|
+
* this key to surface an actionable message instead of the default fallback.
|
|
25
|
+
*/
|
|
26
|
+
const PHANTOM_SIGNING_FAILED_ERROR_CODE = 'phantom_signing_failed';
|
|
19
27
|
let _errorMessageMap;
|
|
20
28
|
const getErrorMessageMap = () => {
|
|
21
29
|
if (!_errorMessageMap) {
|
|
@@ -32,13 +40,14 @@ const getErrorMessageMap = () => {
|
|
|
32
40
|
4900: INTERNAL_ERROR_MESSAGE,
|
|
33
41
|
5001: MESSAGE_SIGNATURE_DENIED,
|
|
34
42
|
5002: MESSAGE_SIGNATURE_DENIED,
|
|
35
|
-
|
|
43
|
+
[PHANTOM_SIGNING_FAILED_ERROR_CODE]: PHANTOM_SIGNING_FAILED_MESSAGE,
|
|
36
44
|
[utils.SdkErrorCode.CONNECTION_REJECTED]: 'Connection rejected. Please try again.',
|
|
37
|
-
|
|
45
|
+
account_already_linked_to_different_profile: 'This social account is already linked to a different profile.',
|
|
38
46
|
[utils.SdkErrorCode.INVALID_EMAIL_VERIFICATION]: 'The verification link is no longer valid. Please start again.',
|
|
47
|
+
general_error: DEFAULT_ERROR_MESSAGE,
|
|
39
48
|
invalid_provider: 'This sign-in provider is not supported.',
|
|
40
|
-
metamask_timeout: 'Whoops. Looks like something went wrong. Please try again.',
|
|
41
49
|
[utils.SdkErrorCode.MISSING_NONCE]: DEFAULT_ERROR_MESSAGE,
|
|
50
|
+
metamask_timeout: 'Whoops. Looks like something went wrong. Please try again.',
|
|
42
51
|
'missing-public-address': 'Connection cancelled. Please try again',
|
|
43
52
|
no_account_linked: 'No linked account was found for this provider.',
|
|
44
53
|
no_auth_code: AUTHENTICATION_FAILED_MESSAGE,
|
|
@@ -64,6 +73,12 @@ const getErrorMessageMap = () => {
|
|
|
64
73
|
}
|
|
65
74
|
return _errorMessageMap;
|
|
66
75
|
};
|
|
76
|
+
/**
|
|
77
|
+
* Returns the mapped, user-facing message for a given error code, or
|
|
78
|
+
* `undefined` when the code is not recognized. Exported so callers can decide
|
|
79
|
+
* whether to normalize an unmapped code before displaying it.
|
|
80
|
+
*/
|
|
81
|
+
const getMappedErrorMessage = (status) => getErrorMessageMap()[status];
|
|
67
82
|
const ErrorContext = React.createContext(undefined);
|
|
68
83
|
const ErrorContextProvider = ({ children }) => {
|
|
69
84
|
/** The error message as a string, used as a fallback if translation is not available */
|
|
@@ -117,4 +132,6 @@ const useErrorContext = createProviderHook.createProviderHook(ErrorContext, 'Err
|
|
|
117
132
|
|
|
118
133
|
exports.ErrorContext = ErrorContext;
|
|
119
134
|
exports.ErrorContextProvider = ErrorContextProvider;
|
|
135
|
+
exports.PHANTOM_SIGNING_FAILED_ERROR_CODE = PHANTOM_SIGNING_FAILED_ERROR_CODE;
|
|
136
|
+
exports.getMappedErrorMessage = getMappedErrorMessage;
|
|
120
137
|
exports.useErrorContext = useErrorContext;
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
2
|
import { ErrorCode } from '@dynamic-labs/utils';
|
|
3
|
+
/**
|
|
4
|
+
* Error code used when Phantom relays an internal signing failure via its
|
|
5
|
+
* deep-link redirect (e.g. the active account has no usable key to sign).
|
|
6
|
+
* Phantom's own code for these is generic (e.g. `500`), so we normalize to
|
|
7
|
+
* this key to surface an actionable message instead of the default fallback.
|
|
8
|
+
*/
|
|
9
|
+
export declare const PHANTOM_SIGNING_FAILED_ERROR_CODE = "phantom_signing_failed";
|
|
3
10
|
interface ErrorContextProps {
|
|
4
11
|
error: string | undefined;
|
|
5
12
|
errorCode: ErrorCode | string | undefined;
|
|
@@ -8,6 +15,12 @@ interface ErrorContextProps {
|
|
|
8
15
|
setDefaultError: (error?: unknown) => void;
|
|
9
16
|
clearError(): void;
|
|
10
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* Returns the mapped, user-facing message for a given error code, or
|
|
20
|
+
* `undefined` when the code is not recognized. Exported so callers can decide
|
|
21
|
+
* whether to normalize an unmapped code before displaying it.
|
|
22
|
+
*/
|
|
23
|
+
export declare const getMappedErrorMessage: (status: string) => string | undefined;
|
|
11
24
|
export declare const ErrorContext: import("react").Context<ErrorContextProps | undefined>;
|
|
12
25
|
export declare const ErrorContextProvider: ({ children }: {
|
|
13
26
|
children: ReactNode;
|
|
@@ -12,6 +12,14 @@ const UNLOCK_WALLET_MESSAGE = 'Please unlock your wallet extension and try again
|
|
|
12
12
|
const INTERNAL_ERROR_MESSAGE = 'There was an internal error. Please try again.';
|
|
13
13
|
const AUTHENTICATION_FAILED_MESSAGE = 'Authentication failed. Please try again.';
|
|
14
14
|
const SESSION_TIMEOUT_MESSAGE = 'Session time out. Please try again.';
|
|
15
|
+
const PHANTOM_SIGNING_FAILED_MESSAGE = "Phantom couldn't sign with the selected account. Switch accounts in Phantom or update the app, then try again.";
|
|
16
|
+
/**
|
|
17
|
+
* Error code used when Phantom relays an internal signing failure via its
|
|
18
|
+
* deep-link redirect (e.g. the active account has no usable key to sign).
|
|
19
|
+
* Phantom's own code for these is generic (e.g. `500`), so we normalize to
|
|
20
|
+
* this key to surface an actionable message instead of the default fallback.
|
|
21
|
+
*/
|
|
22
|
+
const PHANTOM_SIGNING_FAILED_ERROR_CODE = 'phantom_signing_failed';
|
|
15
23
|
let _errorMessageMap;
|
|
16
24
|
const getErrorMessageMap = () => {
|
|
17
25
|
if (!_errorMessageMap) {
|
|
@@ -28,13 +36,14 @@ const getErrorMessageMap = () => {
|
|
|
28
36
|
4900: INTERNAL_ERROR_MESSAGE,
|
|
29
37
|
5001: MESSAGE_SIGNATURE_DENIED,
|
|
30
38
|
5002: MESSAGE_SIGNATURE_DENIED,
|
|
31
|
-
|
|
39
|
+
[PHANTOM_SIGNING_FAILED_ERROR_CODE]: PHANTOM_SIGNING_FAILED_MESSAGE,
|
|
32
40
|
[SdkErrorCode.CONNECTION_REJECTED]: 'Connection rejected. Please try again.',
|
|
33
|
-
|
|
41
|
+
account_already_linked_to_different_profile: 'This social account is already linked to a different profile.',
|
|
34
42
|
[SdkErrorCode.INVALID_EMAIL_VERIFICATION]: 'The verification link is no longer valid. Please start again.',
|
|
43
|
+
general_error: DEFAULT_ERROR_MESSAGE,
|
|
35
44
|
invalid_provider: 'This sign-in provider is not supported.',
|
|
36
|
-
metamask_timeout: 'Whoops. Looks like something went wrong. Please try again.',
|
|
37
45
|
[SdkErrorCode.MISSING_NONCE]: DEFAULT_ERROR_MESSAGE,
|
|
46
|
+
metamask_timeout: 'Whoops. Looks like something went wrong. Please try again.',
|
|
38
47
|
'missing-public-address': 'Connection cancelled. Please try again',
|
|
39
48
|
no_account_linked: 'No linked account was found for this provider.',
|
|
40
49
|
no_auth_code: AUTHENTICATION_FAILED_MESSAGE,
|
|
@@ -60,6 +69,12 @@ const getErrorMessageMap = () => {
|
|
|
60
69
|
}
|
|
61
70
|
return _errorMessageMap;
|
|
62
71
|
};
|
|
72
|
+
/**
|
|
73
|
+
* Returns the mapped, user-facing message for a given error code, or
|
|
74
|
+
* `undefined` when the code is not recognized. Exported so callers can decide
|
|
75
|
+
* whether to normalize an unmapped code before displaying it.
|
|
76
|
+
*/
|
|
77
|
+
const getMappedErrorMessage = (status) => getErrorMessageMap()[status];
|
|
63
78
|
const ErrorContext = createContext(undefined);
|
|
64
79
|
const ErrorContextProvider = ({ children }) => {
|
|
65
80
|
/** The error message as a string, used as a fallback if translation is not available */
|
|
@@ -111,4 +126,4 @@ const ErrorContextProvider = ({ children }) => {
|
|
|
111
126
|
};
|
|
112
127
|
const useErrorContext = createProviderHook(ErrorContext, 'ErrorContextProvider');
|
|
113
128
|
|
|
114
|
-
export { ErrorContext, ErrorContextProvider, useErrorContext };
|
|
129
|
+
export { ErrorContext, ErrorContextProvider, PHANTOM_SIGNING_FAILED_ERROR_CODE, getMappedErrorMessage, useErrorContext };
|
|
@@ -379,8 +379,17 @@ const useResponseHandlers = () => {
|
|
|
379
379
|
return;
|
|
380
380
|
}
|
|
381
381
|
instrumentAuthLoginFailed.instrumentAuthLoginFailed({ code: errorCode, message: errorMessage }, { authOrigin: 'phantom-redirect' });
|
|
382
|
-
setErrorMessage(errorCode, undefined, 'phantom-redirect');
|
|
383
382
|
const method = phantomRedirectConnector.consumeMethod();
|
|
383
|
+
// Phantom relays its own signing failures back through the redirect URL
|
|
384
|
+
// (e.g. the active account has no usable key to sign). These come with a
|
|
385
|
+
// generic, unmapped code, which would otherwise surface the default
|
|
386
|
+
// "Something went wrong" message. When the failed operation was a signing
|
|
387
|
+
// request, normalize unmapped codes to an actionable Phantom message.
|
|
388
|
+
const isUnmappedSigningError = method !== undefined && ErrorContext.getMappedErrorMessage(errorCode) === undefined;
|
|
389
|
+
const errorMessageKey = isUnmappedSigningError
|
|
390
|
+
? ErrorContext.PHANTOM_SIGNING_FAILED_ERROR_CODE
|
|
391
|
+
: errorCode;
|
|
392
|
+
setErrorMessage(errorMessageKey, errorMessage, 'phantom-redirect');
|
|
384
393
|
logger.logger.logVerboseTroubleshootingMessage('[PhantomRedirect handleErrorResponse] consumed method, emitting error', { errorCode, errorMessage, method });
|
|
385
394
|
switch (method) {
|
|
386
395
|
case 'signAndSendTransaction':
|
|
@@ -10,7 +10,7 @@ import '../DynamicContext/useDynamicContext/useDynamicContext.js';
|
|
|
10
10
|
import { useInternalDynamicContext } from '../DynamicContext/useDynamicContext/useInternalDynamicContext/useInternalDynamicContext.js';
|
|
11
11
|
import { useCaptchaContext } from '../CaptchaContext/CaptchaContext.js';
|
|
12
12
|
import '@dynamic-labs/sdk-api-core';
|
|
13
|
-
import { useErrorContext } from '../ErrorContext/ErrorContext.js';
|
|
13
|
+
import { useErrorContext, getMappedErrorMessage, PHANTOM_SIGNING_FAILED_ERROR_CODE } from '../ErrorContext/ErrorContext.js';
|
|
14
14
|
import { useViewContext } from '../ViewContext/ViewContext.js';
|
|
15
15
|
import '@dynamic-labs/iconic';
|
|
16
16
|
import 'react/jsx-runtime';
|
|
@@ -375,8 +375,17 @@ const useResponseHandlers = () => {
|
|
|
375
375
|
return;
|
|
376
376
|
}
|
|
377
377
|
instrumentAuthLoginFailed({ code: errorCode, message: errorMessage }, { authOrigin: 'phantom-redirect' });
|
|
378
|
-
setErrorMessage(errorCode, undefined, 'phantom-redirect');
|
|
379
378
|
const method = phantomRedirectConnector.consumeMethod();
|
|
379
|
+
// Phantom relays its own signing failures back through the redirect URL
|
|
380
|
+
// (e.g. the active account has no usable key to sign). These come with a
|
|
381
|
+
// generic, unmapped code, which would otherwise surface the default
|
|
382
|
+
// "Something went wrong" message. When the failed operation was a signing
|
|
383
|
+
// request, normalize unmapped codes to an actionable Phantom message.
|
|
384
|
+
const isUnmappedSigningError = method !== undefined && getMappedErrorMessage(errorCode) === undefined;
|
|
385
|
+
const errorMessageKey = isUnmappedSigningError
|
|
386
|
+
? PHANTOM_SIGNING_FAILED_ERROR_CODE
|
|
387
|
+
: errorCode;
|
|
388
|
+
setErrorMessage(errorMessageKey, errorMessage, 'phantom-redirect');
|
|
380
389
|
logger.logVerboseTroubleshootingMessage('[PhantomRedirect handleErrorResponse] consumed method, emitting error', { errorCode, errorMessage, method });
|
|
381
390
|
switch (method) {
|
|
382
391
|
case 'signAndSendTransaction':
|
|
@@ -394,7 +394,13 @@ const useSocialAuth = ({ onSettled, onError, onFarcasterUrl, }) => {
|
|
|
394
394
|
}
|
|
395
395
|
const isMobile = utils.isMobile();
|
|
396
396
|
try {
|
|
397
|
-
|
|
397
|
+
// Step-up normally forces a popup, but on mobile browsers popups
|
|
398
|
+
// opened after an async gap (e.g. captcha verification) lose user
|
|
399
|
+
// activation and are blocked (notably iOS Safari). Fall back to the
|
|
400
|
+
// configured strategy (redirect) on mobile so the flow can resume.
|
|
401
|
+
const effectiveStrategy = (authMode === 'stepup' && !isMobile) || forcePopup
|
|
402
|
+
? 'popup'
|
|
403
|
+
: strategy;
|
|
398
404
|
const authCode = yield utils.Oauth2Service.getOauthCode({
|
|
399
405
|
apiProvider: getProviderByType.getProviderByType((_k = projectSettings === null || projectSettings === void 0 ? void 0 : projectSettings.providers) !== null && _k !== void 0 ? _k : [], provider),
|
|
400
406
|
getOAuthResultFromApi: () => oauth.getOAuthResult(environmentId, provider, {
|
|
@@ -390,7 +390,13 @@ const useSocialAuth = ({ onSettled, onError, onFarcasterUrl, }) => {
|
|
|
390
390
|
}
|
|
391
391
|
const isMobile$1 = isMobile();
|
|
392
392
|
try {
|
|
393
|
-
|
|
393
|
+
// Step-up normally forces a popup, but on mobile browsers popups
|
|
394
|
+
// opened after an async gap (e.g. captcha verification) lose user
|
|
395
|
+
// activation and are blocked (notably iOS Safari). Fall back to the
|
|
396
|
+
// configured strategy (redirect) on mobile so the flow can resume.
|
|
397
|
+
const effectiveStrategy = (authMode === 'stepup' && !isMobile$1) || forcePopup
|
|
398
|
+
? 'popup'
|
|
399
|
+
: strategy;
|
|
394
400
|
const authCode = yield Oauth2Service.getOauthCode({
|
|
395
401
|
apiProvider: getProviderByType((_k = projectSettings === null || projectSettings === void 0 ? void 0 : projectSettings.providers) !== null && _k !== void 0 ? _k : [], provider),
|
|
396
402
|
getOAuthResultFromApi: () => getOAuthResult(environmentId, provider, {
|
|
@@ -5,6 +5,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
5
5
|
|
|
6
6
|
var _tslib = require('../../../../../_virtual/_tslib.cjs');
|
|
7
7
|
var React = require('react');
|
|
8
|
+
var utils = require('@dynamic-labs/utils');
|
|
8
9
|
var walletConnectorCore = require('@dynamic-labs/wallet-connector-core');
|
|
9
10
|
require('../../../context/DynamicContext/useDynamicContext/useDynamicContext.cjs');
|
|
10
11
|
var useInternalDynamicContext = require('../../../context/DynamicContext/useDynamicContext/useInternalDynamicContext/useInternalDynamicContext.cjs');
|
|
@@ -49,6 +50,19 @@ const useSwitchWallet = () => {
|
|
|
49
50
|
if (!wallet.connector.isAvailable) {
|
|
50
51
|
throw new Error("Cannot make this wallet active, since this wallet doesn't have a compatible connector on this device.");
|
|
51
52
|
}
|
|
53
|
+
// On mobile, an in-app-browser wallet that isn't injected on the current
|
|
54
|
+
// browser (e.g. switching to a linked Phantom on mobile web) has no
|
|
55
|
+
// provider to sign with. Trigger the wallet's in-app-browser redirect up
|
|
56
|
+
// front so the user lands inside the wallet app, instead of the switch
|
|
57
|
+
// silently succeeding and every later signature failing. The connector
|
|
58
|
+
// self-gates: this is a no-op for installed, embedded, or redirect-only
|
|
59
|
+
// wallets.
|
|
60
|
+
if (utils.isMobile()) {
|
|
61
|
+
const didOpenInAppBrowser = wallet.connector.openInAppBrowserIfRequired();
|
|
62
|
+
if (didOpenInAppBrowser) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
52
66
|
const eoaWallet = getEOAWallet(wallet);
|
|
53
67
|
if (eoaWallet && walletConnectorCore.isTurnkeyWalletConnector(eoaWallet.connector)) {
|
|
54
68
|
const sortedVcs = (_b = (_a = eoaWallet.connector) === null || _a === void 0 ? void 0 : _a.verifiedCredentials) === null || _b === void 0 ? void 0 : _b.reduce((acc, vc) => {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
import { __awaiter } from '../../../../../_virtual/_tslib.js';
|
|
3
3
|
import { useCallback } from 'react';
|
|
4
|
+
import { isMobile } from '@dynamic-labs/utils';
|
|
4
5
|
import { isTurnkeyWalletConnector, isEmailWalletConnector } from '@dynamic-labs/wallet-connector-core';
|
|
5
6
|
import '../../../context/DynamicContext/useDynamicContext/useDynamicContext.js';
|
|
6
7
|
import { useInternalDynamicContext } from '../../../context/DynamicContext/useDynamicContext/useInternalDynamicContext/useInternalDynamicContext.js';
|
|
@@ -45,6 +46,19 @@ const useSwitchWallet = () => {
|
|
|
45
46
|
if (!wallet.connector.isAvailable) {
|
|
46
47
|
throw new Error("Cannot make this wallet active, since this wallet doesn't have a compatible connector on this device.");
|
|
47
48
|
}
|
|
49
|
+
// On mobile, an in-app-browser wallet that isn't injected on the current
|
|
50
|
+
// browser (e.g. switching to a linked Phantom on mobile web) has no
|
|
51
|
+
// provider to sign with. Trigger the wallet's in-app-browser redirect up
|
|
52
|
+
// front so the user lands inside the wallet app, instead of the switch
|
|
53
|
+
// silently succeeding and every later signature failing. The connector
|
|
54
|
+
// self-gates: this is a no-op for installed, embedded, or redirect-only
|
|
55
|
+
// wallets.
|
|
56
|
+
if (isMobile()) {
|
|
57
|
+
const didOpenInAppBrowser = wallet.connector.openInAppBrowserIfRequired();
|
|
58
|
+
if (didOpenInAppBrowser) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
48
62
|
const eoaWallet = getEOAWallet(wallet);
|
|
49
63
|
if (eoaWallet && isTurnkeyWalletConnector(eoaWallet.connector)) {
|
|
50
64
|
const sortedVcs = (_b = (_a = eoaWallet.connector) === null || _a === void 0 ? void 0 : _a.verifiedCredentials) === null || _b === void 0 ? void 0 : _b.reduce((acc, vc) => {
|