@dynamic-labs/legacy-embedded-wallet-migration 0.0.0 → 5.0.0-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6718 -0
- package/LICENSE +21 -0
- package/README.md +5 -0
- package/_virtual/_tslib.js +32 -0
- package/package.js +4 -0
- package/package.json +31 -1
- package/src/index.d.ts +11 -0
- package/src/index.js +16 -0
- package/src/lib/constants.d.ts +8 -0
- package/src/lib/constants.js +12 -0
- package/src/lib/export/cleanupExport/cleanupExport.d.ts +4 -0
- package/src/lib/export/cleanupExport/cleanupExport.js +11 -0
- package/src/lib/export/cleanupExport/index.d.ts +1 -0
- package/src/lib/export/exportCredential/exportCredential.d.ts +7 -0
- package/src/lib/export/exportCredential/exportCredential.js +63 -0
- package/src/lib/export/exportCredential/index.d.ts +1 -0
- package/src/lib/export/exportEmbeddedWallet/exportEmbeddedWallet.d.ts +7 -0
- package/src/lib/export/exportEmbeddedWallet/exportEmbeddedWallet.js +21 -0
- package/src/lib/export/exportEmbeddedWallet/index.d.ts +1 -0
- package/src/lib/export/exportTurnkeyWalletCredential/exportTurnkeyWalletCredential.d.ts +9 -0
- package/src/lib/export/exportTurnkeyWalletCredential/exportTurnkeyWalletCredential.js +30 -0
- package/src/lib/export/exportTurnkeyWalletCredential/index.d.ts +1 -0
- package/src/lib/export/extractExportBundle/extractExportBundle.d.ts +5 -0
- package/src/lib/export/extractExportBundle/extractExportBundle.js +13 -0
- package/src/lib/export/extractExportBundle/index.d.ts +1 -0
- package/src/lib/export/handleExportInitCheck/handleExportInitCheck.d.ts +12 -0
- package/src/lib/export/handleExportInitCheck/handleExportInitCheck.js +34 -0
- package/src/lib/export/handleExportInitCheck/index.d.ts +1 -0
- package/src/lib/export/initExport/index.d.ts +1 -0
- package/src/lib/export/initExport/initExport.d.ts +6 -0
- package/src/lib/export/initExport/initExport.js +22 -0
- package/src/lib/getTurnkeyWalletId/getTurnkeyWalletId.d.ts +8 -0
- package/src/lib/getTurnkeyWalletId/getTurnkeyWalletId.js +27 -0
- package/src/lib/getTurnkeyWalletId/index.d.ts +1 -0
- package/src/lib/recovery/addEmailRecovery/addEmailRecovery.d.ts +7 -0
- package/src/lib/recovery/addEmailRecovery/addEmailRecovery.js +50 -0
- package/src/lib/recovery/addEmailRecovery/index.d.ts +1 -0
- package/src/lib/recovery/addNewPasskeyAuthenticator/addNewPasskeyAuthenticator.d.ts +7 -0
- package/src/lib/recovery/addNewPasskeyAuthenticator/addNewPasskeyAuthenticator.js +14 -0
- package/src/lib/recovery/addNewPasskeyAuthenticator/index.d.ts +1 -0
- package/src/lib/recovery/canRestoreEmbeddedWalletSession/canRestoreEmbeddedWalletSession.d.ts +2 -0
- package/src/lib/recovery/canRestoreEmbeddedWalletSession/canRestoreEmbeddedWalletSession.js +24 -0
- package/src/lib/recovery/canRestoreEmbeddedWalletSession/index.d.ts +1 -0
- package/src/lib/recovery/completePasskeyRecovery/completePasskeyRecovery.d.ts +7 -0
- package/src/lib/recovery/completePasskeyRecovery/completePasskeyRecovery.js +26 -0
- package/src/lib/recovery/completePasskeyRecovery/index.d.ts +1 -0
- package/src/lib/recovery/constants.d.ts +3 -0
- package/src/lib/recovery/constants.js +14 -0
- package/src/lib/recovery/index.d.ts +13 -0
- package/src/lib/recovery/initEmbeddedWalletSession/index.d.ts +1 -0
- package/src/lib/recovery/initEmbeddedWalletSession/initEmbeddedWalletSession.d.ts +11 -0
- package/src/lib/recovery/initEmbeddedWalletSession/initEmbeddedWalletSession.js +56 -0
- package/src/lib/recovery/passkeyRecoveryBundleValidation/index.d.ts +1 -0
- package/src/lib/recovery/passkeyRecoveryBundleValidation/passkeyRecoveryBundleValidation.d.ts +7 -0
- package/src/lib/recovery/passkeyRecoveryBundleValidation/passkeyRecoveryBundleValidation.js +32 -0
- package/src/lib/recovery/recoverTurnkeyWallet/index.d.ts +1 -0
- package/src/lib/recovery/recoverTurnkeyWallet/recoverTurnkeyWallet.d.ts +11 -0
- package/src/lib/recovery/recoverTurnkeyWallet/recoverTurnkeyWallet.js +72 -0
- package/src/lib/recovery/resentRecoveryEmail/index.d.ts +1 -0
- package/src/lib/recovery/resentRecoveryEmail/resentRecoveryEmail.d.ts +7 -0
- package/src/lib/recovery/resentRecoveryEmail/resentRecoveryEmail.js +43 -0
- package/src/lib/recovery/restoreEmbeddedWalletSession/index.d.ts +1 -0
- package/src/lib/recovery/restoreEmbeddedWalletSession/restoreEmbeddedWalletSession.d.ts +9 -0
- package/src/lib/recovery/restoreEmbeddedWalletSession/restoreEmbeddedWalletSession.js +33 -0
- package/src/lib/recovery/types.d.ts +5 -0
- package/src/lib/recovery/useEmbeddedWalletAuthenticator/index.d.ts +1 -0
- package/src/lib/recovery/useEmbeddedWalletAuthenticator/useEmbeddedWalletAuthenticator.d.ts +11 -0
- package/src/lib/recovery/useInitEmbeddedWalletAuthMethod/index.d.ts +1 -0
- package/src/lib/recovery/useInitEmbeddedWalletAuthMethod/useInitEmbeddedWalletAuthMethod.d.ts +29 -0
- package/src/lib/recovery/useInitEmbeddedWalletAuthMethod/useInitEmbeddedWalletAuthMethod.js +50 -0
- package/src/lib/recovery/usePasskeyRecovery/index.d.ts +1 -0
- package/src/lib/recovery/usePasskeyRecovery/usePasskeyRecovery.d.ts +32 -0
- package/src/lib/recovery/usePasskeyRecovery/usePasskeyRecovery.js +197 -0
- package/src/lib/restoreEmbeddedWallet/index.d.ts +1 -0
- package/src/lib/restoreEmbeddedWallet/restoreEmbeddedWallet.d.ts +5 -0
- package/src/lib/restoreEmbeddedWallet/restoreEmbeddedWallet.js +21 -0
- package/src/lib/sessionKeys/base64urlDecode/base64urlDecode.d.ts +1 -0
- package/src/lib/sessionKeys/base64urlDecode/base64urlDecode.js +12 -0
- package/src/lib/sessionKeys/base64urlDecode/index.d.ts +1 -0
- package/src/lib/sessionKeys/buf2hex/buf2hex.d.ts +1 -0
- package/src/lib/sessionKeys/buf2hex/buf2hex.js +7 -0
- package/src/lib/sessionKeys/buf2hex/index.d.ts +1 -0
- package/src/lib/sessionKeys/compressRawPublicKey/compressRawPublicKey.d.ts +1 -0
- package/src/lib/sessionKeys/compressRawPublicKey/compressRawPublicKey.js +15 -0
- package/src/lib/sessionKeys/compressRawPublicKey/index.d.ts +1 -0
- package/src/lib/sessionKeys/generateAndSaveSessionKey/generateAndSaveSessionKey.d.ts +7 -0
- package/src/lib/sessionKeys/generateAndSaveSessionKey/generateAndSaveSessionKey.js +19 -0
- package/src/lib/sessionKeys/generateAndSaveSessionKey/index.d.ts +1 -0
- package/src/lib/sessionKeys/generateSessionKey/generateSessionKey.d.ts +13 -0
- package/src/lib/sessionKeys/generateSessionKey/generateSessionKey.js +20 -0
- package/src/lib/sessionKeys/generateSessionKey/index.d.ts +1 -0
- package/src/lib/sessionKeys/getDecodedSessionKeys/getDecodedSessionKeys.d.ts +2 -0
- package/src/lib/sessionKeys/getDecodedSessionKeys/getDecodedSessionKeys.js +28 -0
- package/src/lib/sessionKeys/getDecodedSessionKeys/index.d.ts +1 -0
- package/src/lib/sessionKeys/getSessionNonceHeaders/getSessionNonceHeaders.d.ts +6 -0
- package/src/lib/sessionKeys/getSessionNonceHeaders/getSessionNonceHeaders.js +19 -0
- package/src/lib/sessionKeys/getSessionNonceHeaders/index.d.ts +1 -0
- package/src/lib/sessionKeys/p256Keygen/index.d.ts +1 -0
- package/src/lib/sessionKeys/p256Keygen/p256Keygen.d.ts +11 -0
- package/src/lib/sessionKeys/p256Keygen/p256Keygen.js +26 -0
- package/src/lib/sessionKeys/p256Sign/index.d.ts +1 -0
- package/src/lib/sessionKeys/p256Sign/p256Sign.d.ts +1 -0
- package/src/lib/sessionKeys/p256Sign/p256Sign.js +17 -0
- package/src/lib/sessionKeys/registerSessionKey/index.d.ts +1 -0
- package/src/lib/sessionKeys/registerSessionKey/registerSessionKey.d.ts +8 -0
- package/src/lib/sessionKeys/registerSessionKey/registerSessionKey.js +42 -0
- package/src/lib/sessionKeys/removeSessionKey/index.d.ts +1 -0
- package/src/lib/sessionKeys/removeSessionKey/removeSessionKey.d.ts +1 -0
- package/src/lib/sessionKeys/removeSessionKey/removeSessionKey.js +9 -0
- package/src/lib/sessionKeys/toEncodedFormat/index.d.ts +1 -0
- package/src/lib/sessionKeys/toEncodedFormat/toEncodedFormat.d.ts +1 -0
- package/src/lib/sessionKeys/toEncodedFormat/toEncodedFormat.js +15 -0
- package/src/lib/sessionKeys/useRegisterEmbeddedWalletSessionKey/index.d.ts +1 -0
- package/src/lib/sessionKeys/useRegisterEmbeddedWalletSessionKey/useRegisterEmbeddedWalletSessionKey.d.ts +11 -0
- package/src/lib/sessionKeys/useRegisterEmbeddedWalletSessionKey/useRegisterEmbeddedWalletSessionKey.js +101 -0
- package/src/lib/sessionKeys/useSetTurnkeyConnectorFetchers/index.d.ts +1 -0
- package/src/lib/sessionKeys/useSetTurnkeyConnectorFetchers/useSetTurnkeyConnectorFetchers.d.ts +4 -0
- package/src/lib/sessionKeys/useSetTurnkeyConnectorFetchers/useSetTurnkeyConnectorFetchers.js +18 -0
- package/src/lib/softDeleteEmbeddedWallet/index.d.ts +1 -0
- package/src/lib/softDeleteEmbeddedWallet/softDeleteEmbeddedWallet.d.ts +5 -0
- package/src/lib/softDeleteEmbeddedWallet/softDeleteEmbeddedWallet.js +21 -0
- package/src/lib/ui/AccountUpgradedView/AccountUpgradedView.d.ts +5 -0
- package/src/lib/ui/AccountUpgradedView/AccountUpgradedView.js +44 -0
- package/src/lib/ui/AccountUpgradedView/index.d.ts +1 -0
- package/src/lib/ui/LegacyEmbeddedWalletExport/LegacyEmbeddedWalletExport.d.ts +6 -0
- package/src/lib/ui/LegacyEmbeddedWalletExport/LegacyEmbeddedWalletExport.js +122 -0
- package/src/lib/ui/LegacyEmbeddedWalletExport/index.d.ts +1 -0
- package/src/lib/ui/LegacyWalletExportSheet/LegacyWalletExportSheet.d.ts +17 -0
- package/src/lib/ui/LegacyWalletExportSheet/LegacyWalletExportSheet.js +60 -0
- package/src/lib/ui/LegacyWalletExportSheet/index.d.ts +1 -0
- package/src/lib/ui/LegacyWalletMigrationContext/LegacyWalletMigrationContext.d.ts +42 -0
- package/src/lib/ui/LegacyWalletMigrationContext/LegacyWalletMigrationContext.js +109 -0
- package/src/lib/ui/LegacyWalletMigrationContext/index.d.ts +1 -0
- package/src/lib/ui/LegacyWalletMigrationModal/LegacyWalletMigrationModal.d.ts +15 -0
- package/src/lib/ui/LegacyWalletMigrationModal/LegacyWalletMigrationModal.js +51 -0
- package/src/lib/ui/LegacyWalletMigrationModal/index.d.ts +1 -0
- package/src/lib/ui/LegacyWalletMigrationRecoveryContext/LegacyWalletMigrationRecoveryContext.d.ts +25 -0
- package/src/lib/ui/LegacyWalletMigrationRecoveryContext/LegacyWalletMigrationRecoveryContext.js +213 -0
- package/src/lib/ui/LegacyWalletMigrationRecoveryContext/index.d.ts +1 -0
- package/src/lib/ui/WaasUpgradeView/WaasUpgradeView.d.ts +9 -0
- package/src/lib/ui/WaasUpgradeView/WaasUpgradeView.js +62 -0
- package/src/lib/ui/WaasUpgradeView/index.d.ts +1 -0
- package/src/lib/ui/WalletUpgradeFlowView/WalletUpgradeFlowView.d.ts +12 -0
- package/src/lib/ui/WalletUpgradeFlowView/WalletUpgradeFlowView.js +124 -0
- package/src/lib/ui/WalletUpgradeFlowView/index.d.ts +1 -0
- package/src/lib/ui/recovery/LegacyAddRecoveryEmailView/LegacyAddRecoveryEmailView.d.ts +9 -0
- package/src/lib/ui/recovery/LegacyAddRecoveryEmailView/LegacyAddRecoveryEmailView.js +21 -0
- package/src/lib/ui/recovery/LegacyAddRecoveryEmailView/index.d.ts +1 -0
- package/src/lib/ui/recovery/LegacyEmbeddedAuthChoiceView/LegacyEmbeddedAuthChoiceView.d.ts +9 -0
- package/src/lib/ui/recovery/LegacyEmbeddedAuthChoiceView/LegacyEmbeddedAuthChoiceView.js +29 -0
- package/src/lib/ui/recovery/LegacyEmbeddedAuthChoiceView/index.d.ts +1 -0
- package/src/lib/ui/recovery/LegacyPasskeyBundleRecoveryView/LegacyPasskeyBundleRecoveryView.d.ts +10 -0
- package/src/lib/ui/recovery/LegacyPasskeyBundleRecoveryView/LegacyPasskeyBundleRecoveryView.js +36 -0
- package/src/lib/ui/recovery/LegacyPasskeyBundleRecoveryView/index.d.ts +1 -0
- package/src/lib/ui/recovery/LegacyPasskeyCompleteRecoveryView/LegacyPasskeyCompleteRecoveryView.d.ts +8 -0
- package/src/lib/ui/recovery/LegacyPasskeyCompleteRecoveryView/LegacyPasskeyCompleteRecoveryView.js +22 -0
- package/src/lib/ui/recovery/LegacyPasskeyCompleteRecoveryView/index.d.ts +1 -0
- package/src/lib/ui/recovery/index.d.ts +4 -0
- package/src/lib/ui/useLegacyWalletExport/index.d.ts +1 -0
- package/src/lib/ui/useLegacyWalletExport/useLegacyWalletExport.d.ts +9 -0
- package/src/lib/ui/useLegacyWalletExport/useLegacyWalletExport.js +75 -0
- package/src/lib/upgradeToDynamicWaas/index.d.ts +1 -0
- package/src/lib/upgradeToDynamicWaas/upgradeToDynamicWaas.d.ts +13 -0
- package/src/lib/upgradeToDynamicWaas/upgradeToDynamicWaas.js +72 -0
- package/src/lib/useLegacyWalletsToMigrate/index.d.ts +2 -0
- package/src/lib/useLegacyWalletsToMigrate/useHasLegacyWalletsToMigrate.d.ts +6 -0
- package/src/lib/useLegacyWalletsToMigrate/useHasLegacyWalletsToMigrate.js +14 -0
- package/src/lib/useLegacyWalletsToMigrate/useLegacyWalletsToMigrate.d.ts +10 -0
- package/src/lib/useLegacyWalletsToMigrate/useLegacyWalletsToMigrate.js +32 -0
- package/src/lib/useUpgradeToDynamicWaas/index.d.ts +1 -0
- package/src/lib/useUpgradeToDynamicWaas/useUpgradeToDynamicWaas.d.ts +20 -0
- package/src/lib/useUpgradeToDynamicWaas/useUpgradeToDynamicWaas.js +44 -0
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
import { __awaiter } from '../../../../_virtual/_tslib.js';
|
|
3
|
+
import { useCallback } from 'react';
|
|
4
|
+
import { useDynamicContext } from '@dynamic-labs/sdk-react-core';
|
|
5
|
+
import { tracing, StorageService, InvalidEmbeddedWalletSessionKeyError } from '@dynamic-labs/utils';
|
|
6
|
+
import { logger } from '@dynamic-labs/wallet-connector-core';
|
|
7
|
+
import { SECURE_ENCLAVE_WALLET_SESSION_KEYS, SECURE_ENCLAVE_WALLET_SESSION_KEYS_STORAGE_OPTIONS } from '../../constants.js';
|
|
8
|
+
import { getTurnkeyWalletId } from '../../getTurnkeyWalletId/getTurnkeyWalletId.js';
|
|
9
|
+
import { generateAndSaveSessionKey } from '../generateAndSaveSessionKey/generateAndSaveSessionKey.js';
|
|
10
|
+
import { generateSessionKey } from '../generateSessionKey/generateSessionKey.js';
|
|
11
|
+
import { getDecodedSessionKeys } from '../getDecodedSessionKeys/getDecodedSessionKeys.js';
|
|
12
|
+
import { p256Sign } from '../p256Sign/p256Sign.js';
|
|
13
|
+
import { registerSessionKey } from '../registerSessionKey/registerSessionKey.js';
|
|
14
|
+
import { toEncodedFormat } from '../toEncodedFormat/toEncodedFormat.js';
|
|
15
|
+
|
|
16
|
+
const resolveSessionKeyForRegistration = (existing, sessionId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
17
|
+
if (!existing.registered) {
|
|
18
|
+
return {
|
|
19
|
+
prevSessionKeySignature: undefined,
|
|
20
|
+
privateKey: existing.privateKey,
|
|
21
|
+
privateKeyJwk: existing.privateKeyJwk,
|
|
22
|
+
publicKey: existing.publicKey,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
const prevSessionKeySignature = yield p256Sign(existing.privateKeyJwk, sessionId);
|
|
26
|
+
const fresh = yield generateSessionKey();
|
|
27
|
+
tracing.logEvent('session-key', 'Loaded prevSessionKeySignature', tracing.formatObject({
|
|
28
|
+
prevSessionKeySignature,
|
|
29
|
+
publicKey: fresh.publicKey,
|
|
30
|
+
}));
|
|
31
|
+
return {
|
|
32
|
+
prevSessionKeySignature,
|
|
33
|
+
privateKey: fresh.privateKey,
|
|
34
|
+
privateKeyJwk: fresh.privateKeyJwk,
|
|
35
|
+
publicKey: fresh.publicKey,
|
|
36
|
+
};
|
|
37
|
+
});
|
|
38
|
+
const safeRegisterSessionKey = (_a) => __awaiter(void 0, [_a], void 0, function* ({ handleLogOut, prevSessionKeySignature, publicKey, walletId, }) {
|
|
39
|
+
try {
|
|
40
|
+
return yield registerSessionKey({
|
|
41
|
+
prevSessionKeySignature,
|
|
42
|
+
publicKey,
|
|
43
|
+
walletId,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
if (error instanceof InvalidEmbeddedWalletSessionKeyError) {
|
|
48
|
+
logger.warn('Invalid embedded wallet session key. Re-authentication is required to create new session keys.');
|
|
49
|
+
yield handleLogOut();
|
|
50
|
+
}
|
|
51
|
+
logger.error('Error registering session key', { error });
|
|
52
|
+
throw error;
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
const useRegisterEmbeddedWalletSessionKey = () => {
|
|
56
|
+
const { user, handleLogOut } = useDynamicContext();
|
|
57
|
+
return useCallback((_a) => __awaiter(void 0, [_a], void 0, function* ({ ignoreRestore = false, walletId, }) {
|
|
58
|
+
if (!user) {
|
|
59
|
+
throw new Error('User not found');
|
|
60
|
+
}
|
|
61
|
+
let existingSessionKey = getDecodedSessionKeys();
|
|
62
|
+
tracing.logEvent('session-key', 'registerEmbeddedWalletSessionKey', tracing.formatObject({
|
|
63
|
+
hasDecodedSessionKeys: Boolean(existingSessionKey),
|
|
64
|
+
publicKey: existingSessionKey === null || existingSessionKey === void 0 ? void 0 : existingSessionKey.publicKey,
|
|
65
|
+
}));
|
|
66
|
+
if (!existingSessionKey) {
|
|
67
|
+
logger.error('Session keys not found in storage. Generating new session keys.', { userId: user.userId });
|
|
68
|
+
existingSessionKey = yield generateAndSaveSessionKey();
|
|
69
|
+
}
|
|
70
|
+
const isSessionKeyValid = existingSessionKey.registered &&
|
|
71
|
+
existingSessionKey.expirationDate &&
|
|
72
|
+
new Date() <= new Date(existingSessionKey.expirationDate) &&
|
|
73
|
+
!ignoreRestore;
|
|
74
|
+
tracing.logEvent('session-key', 'isSessionKeyValid', tracing.formatObject({ isSessionKeyValid: Boolean(isSessionKeyValid) }));
|
|
75
|
+
if (isSessionKeyValid) {
|
|
76
|
+
return existingSessionKey;
|
|
77
|
+
}
|
|
78
|
+
tracing.logEvent('session-key', 'decodedSessionKeys', tracing.formatObject({
|
|
79
|
+
publicKey: existingSessionKey.publicKey,
|
|
80
|
+
registered: existingSessionKey.registered,
|
|
81
|
+
}));
|
|
82
|
+
const { publicKey, privateKey, privateKeyJwk, prevSessionKeySignature } = yield resolveSessionKeyForRegistration(existingSessionKey, user.sessionId);
|
|
83
|
+
const turnkeyWalletId = getTurnkeyWalletId(walletId, user.verifiedCredentials);
|
|
84
|
+
const resp = yield safeRegisterSessionKey({
|
|
85
|
+
handleLogOut,
|
|
86
|
+
prevSessionKeySignature,
|
|
87
|
+
publicKey,
|
|
88
|
+
walletId: turnkeyWalletId,
|
|
89
|
+
});
|
|
90
|
+
const expirationDate = new Date(resp.expiresAt * 1000);
|
|
91
|
+
tracing.logEvent('session-key', 'Created new session key', tracing.formatObject({ expirationDate, publicKey }));
|
|
92
|
+
StorageService.setItem(SECURE_ENCLAVE_WALLET_SESSION_KEYS, toEncodedFormat(publicKey, privateKey, privateKeyJwk, true, expirationDate), SECURE_ENCLAVE_WALLET_SESSION_KEYS_STORAGE_OPTIONS);
|
|
93
|
+
return {
|
|
94
|
+
expirationDate,
|
|
95
|
+
privateKey,
|
|
96
|
+
publicKey,
|
|
97
|
+
};
|
|
98
|
+
}), [handleLogOut, user]);
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
export { useRegisterEmbeddedWalletSessionKey };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useSetTurnkeyConnectorFetchers } from './useSetTurnkeyConnectorFetchers';
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
import { useCallback } from 'react';
|
|
3
|
+
import { isSessionKeyCompatibleWalletConnector } from '@dynamic-labs/wallet-connector-core';
|
|
4
|
+
import { removeSessionKey } from '../removeSessionKey/removeSessionKey.js';
|
|
5
|
+
import { useRegisterEmbeddedWalletSessionKey } from '../useRegisterEmbeddedWalletSessionKey/useRegisterEmbeddedWalletSessionKey.js';
|
|
6
|
+
|
|
7
|
+
const useSetTurnkeyConnectorFetchers = ({ wallet, }) => {
|
|
8
|
+
const registerEmbeddedWalletSessionKey = useRegisterEmbeddedWalletSessionKey();
|
|
9
|
+
return useCallback(() => {
|
|
10
|
+
const connector = wallet === null || wallet === void 0 ? void 0 : wallet.connector;
|
|
11
|
+
if (!isSessionKeyCompatibleWalletConnector(connector))
|
|
12
|
+
return;
|
|
13
|
+
connector.setSessionKeyFetcher(registerEmbeddedWalletSessionKey);
|
|
14
|
+
connector.setSessionKeyRemoveFunction(() => removeSessionKey());
|
|
15
|
+
}, [wallet, registerEmbeddedWalletSessionKey]);
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export { useSetTurnkeyConnectorFetchers };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { softDeleteEmbeddedWallet } from './softDeleteEmbeddedWallet';
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
import { __awaiter } from '../../../_virtual/_tslib.js';
|
|
3
|
+
import { getDefaultClient, getCore, createApiClient } from '@dynamic-labs-sdk/client/core';
|
|
4
|
+
import { DynamicError } from '@dynamic-labs/utils';
|
|
5
|
+
|
|
6
|
+
const softDeleteEmbeddedWallet = (_a) => __awaiter(void 0, [_a], void 0, function* ({ walletId, }) {
|
|
7
|
+
const client = getDefaultClient();
|
|
8
|
+
const core = getCore(client);
|
|
9
|
+
const apiClient = createApiClient({}, client);
|
|
10
|
+
try {
|
|
11
|
+
yield apiClient.softDeleteEmbeddedWallet({
|
|
12
|
+
environmentId: core.environmentId,
|
|
13
|
+
walletId,
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
catch (e) {
|
|
17
|
+
throw new DynamicError('Error soft-deleting embedded wallet', 'soft_delete_embedded_wallet_failed');
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
export { softDeleteEmbeddedWallet };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
3
|
+
import { useTranslation } from 'react-i18next';
|
|
4
|
+
import { IconButton, ModalHeader, Typography, TypographyButton } from '@dynamic-labs/sdk-react-core/components';
|
|
5
|
+
import { CloseIcon, SparklesIcon } from '@dynamic-labs/sdk-react-core/icons';
|
|
6
|
+
|
|
7
|
+
const containerStyle = {
|
|
8
|
+
alignItems: 'center',
|
|
9
|
+
display: 'flex',
|
|
10
|
+
flexDirection: 'column',
|
|
11
|
+
gap: '40px',
|
|
12
|
+
padding: '32px 24px 24px 24px',
|
|
13
|
+
};
|
|
14
|
+
const contentStyle = {
|
|
15
|
+
alignItems: 'center',
|
|
16
|
+
display: 'flex',
|
|
17
|
+
flexDirection: 'column',
|
|
18
|
+
gap: '32px',
|
|
19
|
+
justifyContent: 'center',
|
|
20
|
+
};
|
|
21
|
+
const iconBackgroundStyle = {
|
|
22
|
+
alignItems: 'center',
|
|
23
|
+
background: 'var(--dynamic-brand-primary-color)',
|
|
24
|
+
borderRadius: '50%',
|
|
25
|
+
boxShadow: '0 8px 24px rgb(0 0 0 / 12%)',
|
|
26
|
+
display: 'flex',
|
|
27
|
+
height: 88,
|
|
28
|
+
justifyContent: 'center',
|
|
29
|
+
width: 88,
|
|
30
|
+
};
|
|
31
|
+
const iconStyle = { color: 'white', height: 44, width: 44 };
|
|
32
|
+
const messageStyle = {
|
|
33
|
+
lineHeight: 1.5,
|
|
34
|
+
maxWidth: 340,
|
|
35
|
+
textAlign: 'center',
|
|
36
|
+
};
|
|
37
|
+
const actionsStyle = { maxWidth: 340, width: '100%' };
|
|
38
|
+
const AccountUpgradedView = ({ onFinish, }) => {
|
|
39
|
+
const { t } = useTranslation();
|
|
40
|
+
const closeButton = (jsx(IconButton, { onClick: onFinish, type: 'button', children: jsx(CloseIcon, {}) }));
|
|
41
|
+
return (jsxs(Fragment, { children: [jsx(ModalHeader, { trailing: closeButton, displayBorder: true, children: jsx(Typography, { variant: 'title', color: 'primary', children: t('dyn_account_upgraded.title') }) }), jsxs("div", { style: containerStyle, children: [jsxs("div", { style: contentStyle, children: [jsx("div", { style: iconBackgroundStyle, children: jsx(SparklesIcon, { style: iconStyle }) }), jsx("div", { style: messageStyle, children: jsx(Typography, { variant: 'body_normal', color: 'primary', style: { textAlign: 'center' }, children: t('dyn_account_upgraded.message') }) })] }), jsx("div", { style: actionsStyle, children: jsx(TypographyButton, { onClick: onFinish, buttonVariant: 'brand-primary', expanded: true, buttonPadding: 'large', typographyProps: { color: 'white' }, dataTestId: 'account-upgraded-continue-button', children: t('dyn_account_upgraded.continue_button') }) })] })] }));
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export { AccountUpgradedView };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { AccountUpgradedView, type AccountUpgradedViewProps, } from './AccountUpgradedView';
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { FC } from 'react';
|
|
2
|
+
import { Wallet, WalletConnectorCore } from '@dynamic-labs/wallet-connector-core';
|
|
3
|
+
export type LegacyEmbeddedWalletExportProps = {
|
|
4
|
+
wallet: Wallet<WalletConnectorCore.WalletConnector>;
|
|
5
|
+
};
|
|
6
|
+
export declare const LegacyEmbeddedWalletExport: FC<LegacyEmbeddedWalletExportProps>;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
import { __awaiter } from '../../../../_virtual/_tslib.js';
|
|
3
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
4
|
+
import { useRef, useState, useEffect } from 'react';
|
|
5
|
+
import { useDynamicContext } from '@dynamic-labs/sdk-react-core';
|
|
6
|
+
import { isSessionKeyCompatibleWalletConnector, isTurnkeyWalletConnector, logger } from '@dynamic-labs/wallet-connector-core';
|
|
7
|
+
import { iframeContainerId, iframeElementId } from '../../constants.js';
|
|
8
|
+
import { cleanupExport } from '../../export/cleanupExport/cleanupExport.js';
|
|
9
|
+
import { exportTurnkeyWalletCredential } from '../../export/exportTurnkeyWalletCredential/exportTurnkeyWalletCredential.js';
|
|
10
|
+
import { initExport } from '../../export/initExport/initExport.js';
|
|
11
|
+
import { useSetTurnkeyConnectorFetchers } from '../../sessionKeys/useSetTurnkeyConnectorFetchers/useSetTurnkeyConnectorFetchers.js';
|
|
12
|
+
|
|
13
|
+
const credentialContainerStyle = {
|
|
14
|
+
alignItems: 'center',
|
|
15
|
+
display: 'flex',
|
|
16
|
+
justifyContent: 'center',
|
|
17
|
+
minHeight: 64,
|
|
18
|
+
position: 'relative',
|
|
19
|
+
width: '100%',
|
|
20
|
+
};
|
|
21
|
+
const iframeContainerStyle = {
|
|
22
|
+
background: 'var(--dynamic-base-3, #f5f5f5)',
|
|
23
|
+
borderRadius: 8,
|
|
24
|
+
minHeight: 64,
|
|
25
|
+
padding: 12,
|
|
26
|
+
width: '100%',
|
|
27
|
+
wordBreak: 'break-all',
|
|
28
|
+
};
|
|
29
|
+
const hiddenIframeContainerStyle = Object.assign(Object.assign({}, iframeContainerStyle), { visibility: 'hidden' });
|
|
30
|
+
const skeletonContainerStyle = {
|
|
31
|
+
display: 'flex',
|
|
32
|
+
flexDirection: 'column',
|
|
33
|
+
gap: 8,
|
|
34
|
+
inset: 12,
|
|
35
|
+
position: 'absolute',
|
|
36
|
+
};
|
|
37
|
+
const skeletonLineStyle = {
|
|
38
|
+
background: 'var(--dynamic-base-4, #e5e5e5)',
|
|
39
|
+
borderRadius: 4,
|
|
40
|
+
height: 12,
|
|
41
|
+
width: '100%',
|
|
42
|
+
};
|
|
43
|
+
const skeletonLineShortStyle = Object.assign(Object.assign({}, skeletonLineStyle), { width: '60%' });
|
|
44
|
+
const LegacyEmbeddedWalletExport = ({ wallet }) => {
|
|
45
|
+
const { user } = useDynamicContext();
|
|
46
|
+
const setTurnkeyConnectorFetchers = useSetTurnkeyConnectorFetchers({
|
|
47
|
+
wallet,
|
|
48
|
+
});
|
|
49
|
+
const containerRef = useRef(null);
|
|
50
|
+
const isExportingRef = useRef(false);
|
|
51
|
+
const [revealed, setRevealed] = useState(false);
|
|
52
|
+
const setContainerRef = (element) => {
|
|
53
|
+
containerRef.current = element;
|
|
54
|
+
};
|
|
55
|
+
// Store in refs so the effect doesn't re-fire when their references change.
|
|
56
|
+
const setFetchersRef = useRef(setTurnkeyConnectorFetchers);
|
|
57
|
+
setFetchersRef.current = setTurnkeyConnectorFetchers;
|
|
58
|
+
const userRef = useRef(user);
|
|
59
|
+
userRef.current = user;
|
|
60
|
+
const walletRef = useRef(wallet);
|
|
61
|
+
walletRef.current = wallet;
|
|
62
|
+
// Export flow — runs once on mount. The isExportingRef guard prevents
|
|
63
|
+
// re-entry if React re-fires the effect due to reference changes.
|
|
64
|
+
useEffect(() => {
|
|
65
|
+
const run = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
66
|
+
var _a, _b, _c;
|
|
67
|
+
const iframeContainer = containerRef.current;
|
|
68
|
+
if (!iframeContainer || iframeContainer.children.length > 0) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
if (isExportingRef.current) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
isExportingRef.current = true;
|
|
75
|
+
try {
|
|
76
|
+
setFetchersRef.current();
|
|
77
|
+
if (isSessionKeyCompatibleWalletConnector(wallet === null || wallet === void 0 ? void 0 : wallet.connector)) {
|
|
78
|
+
yield ((_a = wallet === null || wallet === void 0 ? void 0 : wallet.connector) === null || _a === void 0 ? void 0 : _a.createOrRestoreSession());
|
|
79
|
+
}
|
|
80
|
+
if (isTurnkeyWalletConnector(wallet === null || wallet === void 0 ? void 0 : wallet.connector)) {
|
|
81
|
+
yield ((_b = wallet === null || wallet === void 0 ? void 0 : wallet.connector) === null || _b === void 0 ? void 0 : _b.getTurnkeyClient());
|
|
82
|
+
}
|
|
83
|
+
// Remove any leftover iframe from a previous wallet export. The
|
|
84
|
+
// export handler is a static singleton shared across all Turnkey
|
|
85
|
+
// connectors; when switching wallets, the previous component's
|
|
86
|
+
// cleanup may not have fully completed before this effect fires,
|
|
87
|
+
// so the IframeStamper constructor would throw "already exists".
|
|
88
|
+
(_c = iframeContainer.querySelector(`#${iframeElementId}`)) === null || _c === void 0 ? void 0 : _c.remove();
|
|
89
|
+
yield initExport({
|
|
90
|
+
iframeContainer,
|
|
91
|
+
iframeElementId,
|
|
92
|
+
wallet,
|
|
93
|
+
});
|
|
94
|
+
yield exportTurnkeyWalletCredential({
|
|
95
|
+
exportPrivateKey: true,
|
|
96
|
+
user: userRef.current,
|
|
97
|
+
wallet,
|
|
98
|
+
});
|
|
99
|
+
setRevealed(true);
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
logger.error('LegacyEmbeddedWalletExport: export flow failed', error);
|
|
103
|
+
}
|
|
104
|
+
finally {
|
|
105
|
+
isExportingRef.current = false;
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
run();
|
|
109
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
110
|
+
}, [wallet]);
|
|
111
|
+
// Cleanup on unmount only — do not run on dep-change re-fires.
|
|
112
|
+
useEffect(() => () => {
|
|
113
|
+
cleanupExport({ wallet: walletRef.current }).catch(() => {
|
|
114
|
+
// Swallow — component is unmounting.
|
|
115
|
+
});
|
|
116
|
+
},
|
|
117
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
118
|
+
[]);
|
|
119
|
+
return (jsxs("div", { style: credentialContainerStyle, children: [jsx("div", { id: iframeContainerId, ref: setContainerRef, style: revealed ? iframeContainerStyle : hiddenIframeContainerStyle }), !revealed && (jsxs("div", { style: skeletonContainerStyle, children: [jsx("div", { style: skeletonLineStyle, "data-testid": 'private-key-skeleton' }), jsx("div", { style: skeletonLineStyle }), jsx("div", { style: skeletonLineShortStyle })] }))] }));
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
export { LegacyEmbeddedWalletExport };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { LegacyEmbeddedWalletExport, type LegacyEmbeddedWalletExportProps, } from './LegacyEmbeddedWalletExport';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { FC } from 'react';
|
|
2
|
+
import { Wallet, WalletConnectorCore } from '@dynamic-labs/wallet-connector-core';
|
|
3
|
+
export type LegacyWalletExportSheetProps = {
|
|
4
|
+
wallet: Wallet<WalletConnectorCore.WalletConnector>;
|
|
5
|
+
onClose: () => void;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Visible export sheet for a legacy Turnkey wallet.
|
|
9
|
+
*
|
|
10
|
+
* The exported private key lives inside a cross-origin Turnkey iframe that
|
|
11
|
+
* native code cannot read, so on React Native it must be surfaced inside the
|
|
12
|
+
* webview for the user to copy and paste back into the headless-migration
|
|
13
|
+
* screen. This wraps the shared `LegacyEmbeddedWalletExport` in a presentable
|
|
14
|
+
* overlay + close button so consumers (e.g. the webview-controller) render it
|
|
15
|
+
* directly instead of hand-rolling the chrome.
|
|
16
|
+
*/
|
|
17
|
+
export declare const LegacyWalletExportSheet: FC<LegacyWalletExportSheetProps>;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
3
|
+
import { LegacyEmbeddedWalletExport } from '../LegacyEmbeddedWalletExport/LegacyEmbeddedWalletExport.js';
|
|
4
|
+
|
|
5
|
+
const overlayStyle = {
|
|
6
|
+
alignItems: 'center',
|
|
7
|
+
background: 'var(--dynamic-overlay, rgba(0, 0, 0, 0.5))',
|
|
8
|
+
display: 'flex',
|
|
9
|
+
inset: 0,
|
|
10
|
+
justifyContent: 'center',
|
|
11
|
+
padding: 16,
|
|
12
|
+
position: 'fixed',
|
|
13
|
+
zIndex: 2147483647,
|
|
14
|
+
};
|
|
15
|
+
const sheetStyle = {
|
|
16
|
+
background: 'var(--dynamic-base-1, #ffffff)',
|
|
17
|
+
borderRadius: 16,
|
|
18
|
+
boxSizing: 'border-box',
|
|
19
|
+
display: 'flex',
|
|
20
|
+
flexDirection: 'column',
|
|
21
|
+
gap: 16,
|
|
22
|
+
maxWidth: 420,
|
|
23
|
+
padding: 24,
|
|
24
|
+
width: '100%',
|
|
25
|
+
};
|
|
26
|
+
const titleStyle = {
|
|
27
|
+
color: 'var(--dynamic-text-primary, #0a0a0a)',
|
|
28
|
+
fontSize: 18,
|
|
29
|
+
fontWeight: 600,
|
|
30
|
+
margin: 0,
|
|
31
|
+
};
|
|
32
|
+
const descriptionStyle = {
|
|
33
|
+
color: 'var(--dynamic-text-secondary, #6b6b6b)',
|
|
34
|
+
fontSize: 14,
|
|
35
|
+
margin: 0,
|
|
36
|
+
};
|
|
37
|
+
const closeButtonStyle = {
|
|
38
|
+
background: 'var(--dynamic-base-3, #f5f5f5)',
|
|
39
|
+
border: 'none',
|
|
40
|
+
borderRadius: 8,
|
|
41
|
+
color: 'var(--dynamic-text-primary, #0a0a0a)',
|
|
42
|
+
cursor: 'pointer',
|
|
43
|
+
fontSize: 16,
|
|
44
|
+
fontWeight: 600,
|
|
45
|
+
padding: '12px 16px',
|
|
46
|
+
width: '100%',
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Visible export sheet for a legacy Turnkey wallet.
|
|
50
|
+
*
|
|
51
|
+
* The exported private key lives inside a cross-origin Turnkey iframe that
|
|
52
|
+
* native code cannot read, so on React Native it must be surfaced inside the
|
|
53
|
+
* webview for the user to copy and paste back into the headless-migration
|
|
54
|
+
* screen. This wraps the shared `LegacyEmbeddedWalletExport` in a presentable
|
|
55
|
+
* overlay + close button so consumers (e.g. the webview-controller) render it
|
|
56
|
+
* directly instead of hand-rolling the chrome.
|
|
57
|
+
*/
|
|
58
|
+
const LegacyWalletExportSheet = ({ wallet, onClose, }) => (jsx("div", { style: overlayStyle, "data-testid": 'legacy-wallet-export-sheet', children: jsxs("div", { style: sheetStyle, children: [jsx("p", { style: titleStyle, children: "Export private key" }), jsx("p", { style: descriptionStyle, children: "Copy the private key below, then paste it back into the app to upgrade this wallet to Dynamic WaaS." }), jsx(LegacyEmbeddedWalletExport, { wallet: wallet }), jsx("button", { type: 'button', style: closeButtonStyle, onClick: onClose, "data-testid": 'legacy-wallet-export-close-btn', children: "Done" })] }) }));
|
|
59
|
+
|
|
60
|
+
export { LegacyWalletExportSheet };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { LegacyWalletExportSheet, type LegacyWalletExportSheetProps, } from './LegacyWalletExportSheet';
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { FC, ReactNode } from 'react';
|
|
2
|
+
import { Wallet, WalletConnectorCore } from '@dynamic-labs/wallet-connector-core';
|
|
3
|
+
import { type LegacyWalletMigrationOnUpgrade, type LegacyWalletMigrationStep } from '../LegacyWalletMigrationModal';
|
|
4
|
+
type StartUpgradeArgs = {
|
|
5
|
+
wallets?: Wallet<WalletConnectorCore.WalletConnector>[];
|
|
6
|
+
onComplete?: () => void;
|
|
7
|
+
};
|
|
8
|
+
export type LegacyWalletMigrationContextType = {
|
|
9
|
+
isOpen: boolean;
|
|
10
|
+
step: LegacyWalletMigrationStep;
|
|
11
|
+
startUpgrade: (args?: StartUpgradeArgs) => void;
|
|
12
|
+
close: () => void;
|
|
13
|
+
goToStep: (step: LegacyWalletMigrationStep) => void;
|
|
14
|
+
};
|
|
15
|
+
export declare const LegacyWalletMigrationContext: import("react").Context<LegacyWalletMigrationContextType | undefined>;
|
|
16
|
+
export type LegacyWalletMigrationProviderProps = {
|
|
17
|
+
children: ReactNode;
|
|
18
|
+
/**
|
|
19
|
+
* Handler that performs the actual upgrade for a single legacy wallet.
|
|
20
|
+
* Defaults to `useUpgradeToDynamicWaas().upgradeToDynamicWaas`, which is
|
|
21
|
+
* what virtually every consumer wants — only override to customize
|
|
22
|
+
* post-upgrade restore behavior or to inject test stubs.
|
|
23
|
+
*/
|
|
24
|
+
onUpgrade?: LegacyWalletMigrationOnUpgrade;
|
|
25
|
+
/**
|
|
26
|
+
* Controls whether the migration modal auto-opens when a legacy V1/V2
|
|
27
|
+
* Turnkey wallet is detected on the current user.
|
|
28
|
+
*
|
|
29
|
+
* When `true` (default), the modal opens automatically the first time a
|
|
30
|
+
* legacy wallet is observed — this is the standard "UI path" where the
|
|
31
|
+
* provider owns the migration UX end-to-end.
|
|
32
|
+
*
|
|
33
|
+
* Set to `false` for headless consumers that want to drive the upgrade
|
|
34
|
+
* flow themselves (e.g. React Native apps using their own native UI).
|
|
35
|
+
* The provider still registers itself so `useEnforceLegacyMigrationProvider`
|
|
36
|
+
* does not throw, and `startUpgrade()` can still be called manually.
|
|
37
|
+
*/
|
|
38
|
+
autoOpen?: boolean;
|
|
39
|
+
};
|
|
40
|
+
export declare const LegacyWalletMigrationProvider: FC<LegacyWalletMigrationProviderProps>;
|
|
41
|
+
export declare const useLegacyWalletMigration: () => LegacyWalletMigrationContextType;
|
|
42
|
+
export {};
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
|
+
import { createContext, useState, useRef, useEffect, useCallback, useMemo, useContext } from 'react';
|
|
4
|
+
import { EmbeddedWalletVersionEnum } from '@dynamic-labs/sdk-api-core';
|
|
5
|
+
import { useProjectSettings, setLegacyMigrationProviderMounted } from '@dynamic-labs/sdk-react-core';
|
|
6
|
+
import { logger } from '@dynamic-labs/wallet-connector-core';
|
|
7
|
+
import { useLegacyWalletsToMigrate } from '../../useLegacyWalletsToMigrate/useLegacyWalletsToMigrate.js';
|
|
8
|
+
import { useUpgradeToDynamicWaas } from '../../useUpgradeToDynamicWaas/useUpgradeToDynamicWaas.js';
|
|
9
|
+
import { LegacyWalletMigrationModal } from '../LegacyWalletMigrationModal/LegacyWalletMigrationModal.js';
|
|
10
|
+
import { LegacyWalletMigrationRecoveryProvider } from '../LegacyWalletMigrationRecoveryContext/LegacyWalletMigrationRecoveryContext.js';
|
|
11
|
+
|
|
12
|
+
const LegacyWalletMigrationContext = createContext(undefined);
|
|
13
|
+
const CLOSED_STATE = { open: false, step: 'select' };
|
|
14
|
+
const LegacyWalletMigrationProvider = ({ children, onUpgrade, autoOpen = true }) => {
|
|
15
|
+
var _a, _b;
|
|
16
|
+
const [state, setState] = useState(CLOSED_STATE);
|
|
17
|
+
const legacyWallets = useLegacyWalletsToMigrate();
|
|
18
|
+
const projectSettings = useProjectSettings();
|
|
19
|
+
const hasAutoOpenedRef = useRef(false);
|
|
20
|
+
const { upgradeToDynamicWaas } = useUpgradeToDynamicWaas();
|
|
21
|
+
const effectiveOnUpgrade = onUpgrade !== null && onUpgrade !== void 0 ? onUpgrade : upgradeToDynamicWaas;
|
|
22
|
+
const isV3EmbeddedWalletEnabled = ((_b = (_a = projectSettings === null || projectSettings === void 0 ? void 0 : projectSettings.sdk) === null || _a === void 0 ? void 0 : _a.embeddedWallets) === null || _b === void 0 ? void 0 : _b.defaultWalletVersion) ===
|
|
23
|
+
EmbeddedWalletVersionEnum.V3;
|
|
24
|
+
// Advertise to sdk-react-core that the migration provider is mounted so
|
|
25
|
+
// its `useEnforceLegacyMigrationProvider` does not throw when a legacy
|
|
26
|
+
// Turnkey wallet is loaded.
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
setLegacyMigrationProviderMounted(true);
|
|
29
|
+
return () => setLegacyMigrationProviderMounted(false);
|
|
30
|
+
}, []);
|
|
31
|
+
const startUpgrade = useCallback((args) => {
|
|
32
|
+
var _a;
|
|
33
|
+
setState({
|
|
34
|
+
onComplete: args === null || args === void 0 ? void 0 : args.onComplete,
|
|
35
|
+
open: true,
|
|
36
|
+
step: 'select',
|
|
37
|
+
// Default to the auto-detected legacy wallets so consumers calling
|
|
38
|
+
// `startUpgrade()` without arguments don't have to also wire
|
|
39
|
+
// `useLegacyWalletsToMigrate()` themselves.
|
|
40
|
+
wallets: (_a = args === null || args === void 0 ? void 0 : args.wallets) !== null && _a !== void 0 ? _a : legacyWallets,
|
|
41
|
+
});
|
|
42
|
+
}, [legacyWallets]);
|
|
43
|
+
// Auto-open the migration modal the first time we observe a legacy Turnkey
|
|
44
|
+
// wallet on the user. Legacy wallets have no supported runtime path other
|
|
45
|
+
// than migration, so we force the flow open without requiring the consumer
|
|
46
|
+
// to wire a trigger. Once `hasAutoOpenedRef` is set, we do not re-open after
|
|
47
|
+
// the user dismisses — the customer's app may still call `startUpgrade()`
|
|
48
|
+
// manually to re-trigger.
|
|
49
|
+
//
|
|
50
|
+
// We set the ref *before* the `state.open` short-circuit so that if the
|
|
51
|
+
// modal is already open when legacy wallets first appear (e.g. the consumer
|
|
52
|
+
// called `startUpgrade` directly), we still mark the detection as handled
|
|
53
|
+
// and don't fire again when the user closes.
|
|
54
|
+
//
|
|
55
|
+
// We also gate the auto-open on the project having V3 embedded wallets
|
|
56
|
+
// enabled — the migration upgrades to V3 WaaS via backend API calls that
|
|
57
|
+
// require V3 to be the configured default. Without that, the modal would
|
|
58
|
+
// open into an unrecoverable flow, so we surface the misconfig in the
|
|
59
|
+
// console and skip auto-opening.
|
|
60
|
+
useEffect(() => {
|
|
61
|
+
if (!autoOpen)
|
|
62
|
+
return;
|
|
63
|
+
if (legacyWallets.length === 0) {
|
|
64
|
+
hasAutoOpenedRef.current = false;
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
if (hasAutoOpenedRef.current)
|
|
68
|
+
return;
|
|
69
|
+
if (!isV3EmbeddedWalletEnabled) {
|
|
70
|
+
logger.error('Legacy embedded wallet detected, but `defaultWalletVersion` is not V3 in project settings. ' +
|
|
71
|
+
'Migration requires V3 to be the configured default. Skipping auto-open of the migration modal.');
|
|
72
|
+
hasAutoOpenedRef.current = true;
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
hasAutoOpenedRef.current = true;
|
|
76
|
+
if (state.open)
|
|
77
|
+
return;
|
|
78
|
+
startUpgrade();
|
|
79
|
+
}, [
|
|
80
|
+
autoOpen,
|
|
81
|
+
legacyWallets,
|
|
82
|
+
state.open,
|
|
83
|
+
startUpgrade,
|
|
84
|
+
isV3EmbeddedWalletEnabled,
|
|
85
|
+
]);
|
|
86
|
+
const close = useCallback(() => {
|
|
87
|
+
setState(CLOSED_STATE);
|
|
88
|
+
}, []);
|
|
89
|
+
const goToStep = useCallback((step) => {
|
|
90
|
+
setState((previous) => (Object.assign(Object.assign({}, previous), { step })));
|
|
91
|
+
}, []);
|
|
92
|
+
const value = useMemo(() => ({
|
|
93
|
+
close,
|
|
94
|
+
goToStep,
|
|
95
|
+
isOpen: state.open,
|
|
96
|
+
startUpgrade,
|
|
97
|
+
step: state.step,
|
|
98
|
+
}), [close, goToStep, startUpgrade, state.open, state.step]);
|
|
99
|
+
return (jsxs(LegacyWalletMigrationContext.Provider, { value: value, children: [children, jsx(LegacyWalletMigrationRecoveryProvider, { children: jsx(LegacyWalletMigrationModal, { open: state.open, step: state.step, onClose: close, onStepChange: goToStep, onComplete: state.onComplete, onUpgrade: effectiveOnUpgrade, wallets: state.wallets }) })] }));
|
|
100
|
+
};
|
|
101
|
+
const useLegacyWalletMigration = () => {
|
|
102
|
+
const context = useContext(LegacyWalletMigrationContext);
|
|
103
|
+
if (context === undefined) {
|
|
104
|
+
throw new Error('useLegacyWalletMigration must be used inside a LegacyWalletMigrationProvider.');
|
|
105
|
+
}
|
|
106
|
+
return context;
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
export { LegacyWalletMigrationContext, LegacyWalletMigrationProvider, useLegacyWalletMigration };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { LegacyWalletMigrationContext, LegacyWalletMigrationProvider, useLegacyWalletMigration, type LegacyWalletMigrationContextType, type LegacyWalletMigrationProviderProps, } from './LegacyWalletMigrationContext';
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { FC } from 'react';
|
|
2
|
+
import { Wallet, WalletConnectorCore } from '@dynamic-labs/wallet-connector-core';
|
|
3
|
+
import { type WalletUpgradeFlowViewOnUpgradeArgs } from '../WalletUpgradeFlowView';
|
|
4
|
+
export type LegacyWalletMigrationStep = 'select' | 'upgrade' | 'complete' | 'passkey-recovery-add-email' | 'passkey-recovery-bundle' | 'passkey-recovery-complete' | 'embedded-wallet-auth-choice';
|
|
5
|
+
export type LegacyWalletMigrationOnUpgrade = (args: WalletUpgradeFlowViewOnUpgradeArgs) => Promise<void>;
|
|
6
|
+
export type LegacyWalletMigrationModalProps = {
|
|
7
|
+
open: boolean;
|
|
8
|
+
step: LegacyWalletMigrationStep;
|
|
9
|
+
onClose: () => void;
|
|
10
|
+
onStepChange: (step: LegacyWalletMigrationStep) => void;
|
|
11
|
+
onComplete?: () => void;
|
|
12
|
+
onUpgrade: LegacyWalletMigrationOnUpgrade;
|
|
13
|
+
wallets?: Wallet<WalletConnectorCore.WalletConnector>[];
|
|
14
|
+
};
|
|
15
|
+
export declare const LegacyWalletMigrationModal: FC<LegacyWalletMigrationModalProps>;
|