@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,51 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
import { __awaiter } from '../../../../_virtual/_tslib.js';
|
|
3
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
4
|
+
import { useState } from 'react';
|
|
5
|
+
import { Portal, Modal, ModalCard } from '@dynamic-labs/sdk-react-core/components';
|
|
6
|
+
import { logger } from '@dynamic-labs/wallet-connector-core';
|
|
7
|
+
import { AccountUpgradedView } from '../AccountUpgradedView/AccountUpgradedView.js';
|
|
8
|
+
import { useLegacyWalletMigrationRecovery } from '../LegacyWalletMigrationRecoveryContext/LegacyWalletMigrationRecoveryContext.js';
|
|
9
|
+
import { LegacyAddRecoveryEmailView } from '../recovery/LegacyAddRecoveryEmailView/LegacyAddRecoveryEmailView.js';
|
|
10
|
+
import { LegacyPasskeyBundleRecoveryView } from '../recovery/LegacyPasskeyBundleRecoveryView/LegacyPasskeyBundleRecoveryView.js';
|
|
11
|
+
import { LegacyPasskeyCompleteRecoveryView } from '../recovery/LegacyPasskeyCompleteRecoveryView/LegacyPasskeyCompleteRecoveryView.js';
|
|
12
|
+
import { LegacyEmbeddedAuthChoiceView } from '../recovery/LegacyEmbeddedAuthChoiceView/LegacyEmbeddedAuthChoiceView.js';
|
|
13
|
+
import { WalletUpgradeFlowView } from '../WalletUpgradeFlowView/WalletUpgradeFlowView.js';
|
|
14
|
+
import { WaasUpgradeView } from '../WaasUpgradeView/WaasUpgradeView.js';
|
|
15
|
+
|
|
16
|
+
const LegacyWalletMigrationModal = ({ open, step, onClose, onStepChange, onComplete, onUpgrade, wallets }) => {
|
|
17
|
+
const { addRecoveryEmail, bundleValidationError, completeRecovery, completeRecoveryError, initPasskeyRecoveryProcess, isCompletingRecovery, isValidatingBundle, recoveryEmail, resendRecoveryEmail, shouldInitRecovery, supportedAuthenticators, validateRecoveryBundle, } = useLegacyWalletMigrationRecovery();
|
|
18
|
+
const [isGatingUpgrade, setIsGatingUpgrade] = useState(false);
|
|
19
|
+
const goToUpgrade = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
20
|
+
setIsGatingUpgrade(true);
|
|
21
|
+
try {
|
|
22
|
+
if (yield shouldInitRecovery()) {
|
|
23
|
+
yield initPasskeyRecoveryProcess();
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
onStepChange('upgrade');
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
logger.error('Failed to gate upgrade on recovery', err);
|
|
30
|
+
}
|
|
31
|
+
finally {
|
|
32
|
+
setIsGatingUpgrade(false);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
const goToComplete = () => onStepChange('complete');
|
|
36
|
+
const finish = () => {
|
|
37
|
+
onComplete === null || onComplete === void 0 ? void 0 : onComplete();
|
|
38
|
+
onClose();
|
|
39
|
+
};
|
|
40
|
+
// Force-migration UX: once we have legacy wallets to migrate, the user
|
|
41
|
+
// must complete the flow. Backdrop click / Escape key are no-ops; the
|
|
42
|
+
// only way out is finishing the migration (or the consumer-side explicit
|
|
43
|
+
// `close()` if they're driving the flow).
|
|
44
|
+
const hasLegacyWalletsToMigrate = (wallets !== null && wallets !== void 0 ? wallets : []).length > 0;
|
|
45
|
+
const handlePortalClose = hasLegacyWalletsToMigrate
|
|
46
|
+
? () => undefined
|
|
47
|
+
: onClose;
|
|
48
|
+
return (jsx(Portal, { isShown: open, handleClose: handlePortalClose, children: jsx(Modal, { children: jsx(ModalCard, { children: jsxs("div", { className: 'legacy-wallet-migration-modal', "data-testid": 'legacy-wallet-migration-modal', children: [step === 'select' && (jsx("div", { "data-testid": 'legacy-wallet-migration-step-select', children: jsx(WaasUpgradeView, { wallets: wallets !== null && wallets !== void 0 ? wallets : [], onContinue: goToUpgrade, onCancel: onClose, isLoading: isGatingUpgrade }) })), step === 'upgrade' && (jsx("div", { "data-testid": 'legacy-wallet-migration-step-upgrade', children: jsx(WalletUpgradeFlowView, { wallets: wallets !== null && wallets !== void 0 ? wallets : [], onUpgrade: onUpgrade, onFinish: goToComplete }) })), step === 'complete' && (jsx("div", { "data-testid": 'legacy-wallet-migration-step-complete', children: jsx(AccountUpgradedView, { onFinish: finish }) })), step === 'passkey-recovery-add-email' && (jsx("div", { "data-testid": 'legacy-wallet-migration-step-passkey-recovery-add-email', children: jsx(LegacyAddRecoveryEmailView, { onSubmit: addRecoveryEmail, onCancel: onClose }) })), step === 'passkey-recovery-bundle' && (jsx("div", { "data-testid": 'legacy-wallet-migration-step-passkey-recovery-bundle', children: jsx(LegacyPasskeyBundleRecoveryView, { email: recoveryEmail, onSubmit: validateRecoveryBundle, onResend: resendRecoveryEmail, onCancel: onClose, isSubmitting: isValidatingBundle, errorMessage: bundleValidationError === null || bundleValidationError === void 0 ? void 0 : bundleValidationError.message }) })), step === 'passkey-recovery-complete' && (jsx("div", { "data-testid": 'legacy-wallet-migration-step-passkey-recovery-complete', children: jsx(LegacyPasskeyCompleteRecoveryView, { onSubmit: completeRecovery, onCancel: onClose, isSubmitting: isCompletingRecovery, errorMessage: completeRecoveryError === null || completeRecoveryError === void 0 ? void 0 : completeRecoveryError.message }) })), step === 'embedded-wallet-auth-choice' && (jsx("div", { "data-testid": 'legacy-wallet-migration-step-embedded-wallet-auth-choice', children: jsx(LegacyEmbeddedAuthChoiceView, { supportedAuthenticators: supportedAuthenticators, onSelect: initPasskeyRecoveryProcess, onCancel: onClose }) }))] }) }) }) }));
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export { LegacyWalletMigrationModal };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { LegacyWalletMigrationModal, type LegacyWalletMigrationModalProps, type LegacyWalletMigrationOnUpgrade, type LegacyWalletMigrationStep, } from './LegacyWalletMigrationModal';
|
package/src/lib/ui/LegacyWalletMigrationRecoveryContext/LegacyWalletMigrationRecoveryContext.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { FC, ReactNode } from 'react';
|
|
2
|
+
import { AuthenticatorType } from '@dynamic-labs/wallet-connector-core';
|
|
3
|
+
import { usePasskeyRecovery } from '../../recovery';
|
|
4
|
+
type RecoveryHandlers = ReturnType<typeof usePasskeyRecovery>;
|
|
5
|
+
export type LegacyWalletMigrationRecoveryContextType = RecoveryHandlers & {
|
|
6
|
+
iframeContainer: HTMLDivElement | null;
|
|
7
|
+
supportedAuthenticators: AuthenticatorType[];
|
|
8
|
+
resolveEmailVerification: (wasSuccessful: boolean) => void;
|
|
9
|
+
recoveryEmail: string | undefined;
|
|
10
|
+
recoveryAuthenticatorType: AuthenticatorType | undefined;
|
|
11
|
+
validateRecoveryBundle: (bundleInput: string) => Promise<void>;
|
|
12
|
+
resendRecoveryEmail: () => Promise<void>;
|
|
13
|
+
isValidatingBundle: boolean;
|
|
14
|
+
bundleValidationError: Error | undefined;
|
|
15
|
+
completeRecovery: () => Promise<void>;
|
|
16
|
+
isCompletingRecovery: boolean;
|
|
17
|
+
completeRecoveryError: Error | undefined;
|
|
18
|
+
};
|
|
19
|
+
export declare const LegacyWalletMigrationRecoveryContext: import("react").Context<LegacyWalletMigrationRecoveryContextType | undefined>;
|
|
20
|
+
export type LegacyWalletMigrationRecoveryProviderProps = {
|
|
21
|
+
children: ReactNode;
|
|
22
|
+
};
|
|
23
|
+
export declare const LegacyWalletMigrationRecoveryProvider: FC<LegacyWalletMigrationRecoveryProviderProps>;
|
|
24
|
+
export declare const useLegacyWalletMigrationRecovery: () => LegacyWalletMigrationRecoveryContextType;
|
|
25
|
+
export {};
|
package/src/lib/ui/LegacyWalletMigrationRecoveryContext/LegacyWalletMigrationRecoveryContext.js
ADDED
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
import { __awaiter } from '../../../../_virtual/_tslib.js';
|
|
3
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
4
|
+
import { createContext, useMemo, useState, useRef, useEffect, useCallback, useContext } from 'react';
|
|
5
|
+
import { JwtVerifiedCredentialFormatEnum } from '@dynamic-labs/sdk-api-core';
|
|
6
|
+
import { useDynamicContext, useProjectSettings } from '@dynamic-labs/sdk-react-core';
|
|
7
|
+
import { DynamicError } from '@dynamic-labs/utils';
|
|
8
|
+
import { logger } from '@dynamic-labs/wallet-connector-core';
|
|
9
|
+
import '@dynamic-labs-sdk/client/core';
|
|
10
|
+
import { iframeContainerId } from '../../recovery/constants.js';
|
|
11
|
+
import { completePasskeyRecovery } from '../../recovery/completePasskeyRecovery/completePasskeyRecovery.js';
|
|
12
|
+
import { passkeyRecoveryBundleValidation } from '../../recovery/passkeyRecoveryBundleValidation/passkeyRecoveryBundleValidation.js';
|
|
13
|
+
import { resentRecoveryEmail } from '../../recovery/resentRecoveryEmail/resentRecoveryEmail.js';
|
|
14
|
+
import { usePasskeyRecovery } from '../../recovery/usePasskeyRecovery/usePasskeyRecovery.js';
|
|
15
|
+
import { useSetTurnkeyConnectorFetchers } from '../../sessionKeys/useSetTurnkeyConnectorFetchers/useSetTurnkeyConnectorFetchers.js';
|
|
16
|
+
import { useLegacyWalletsToMigrate } from '../../useLegacyWalletsToMigrate/useLegacyWalletsToMigrate.js';
|
|
17
|
+
import { useLegacyWalletMigration } from '../LegacyWalletMigrationContext/LegacyWalletMigrationContext.js';
|
|
18
|
+
|
|
19
|
+
const LegacyWalletMigrationRecoveryContext = createContext(undefined);
|
|
20
|
+
const iframeHostStyle = {
|
|
21
|
+
height: 0,
|
|
22
|
+
left: 0,
|
|
23
|
+
overflow: 'hidden',
|
|
24
|
+
position: 'absolute',
|
|
25
|
+
top: 0,
|
|
26
|
+
visibility: 'hidden',
|
|
27
|
+
width: 0,
|
|
28
|
+
};
|
|
29
|
+
const AUTHENTICATOR_KEYS = ['passkey', 'email'];
|
|
30
|
+
const GENERIC_BUNDLE_ERROR = 'Failed to validate the recovery code. Please try again.';
|
|
31
|
+
const GENERIC_COMPLETE_RECOVERY_ERROR = 'Failed to complete recovery. Please try again.';
|
|
32
|
+
// Only DynamicError instances carry user-facing copy. Wrap anything else in a
|
|
33
|
+
// generic message so internal stack traces / API details are not leaked to
|
|
34
|
+
// the UI (full error is still logged via logger.error).
|
|
35
|
+
const sanitizeUserFacingError = (err, fallback) => err instanceof DynamicError ? err : new Error(fallback);
|
|
36
|
+
const LegacyWalletMigrationRecoveryProvider = ({ children }) => {
|
|
37
|
+
var _a, _b, _c, _d, _e, _f;
|
|
38
|
+
const { user, primaryWallet } = useDynamicContext();
|
|
39
|
+
const projectSettings = useProjectSettings();
|
|
40
|
+
const { goToStep } = useLegacyWalletMigration();
|
|
41
|
+
const legacyWallets = useLegacyWalletsToMigrate();
|
|
42
|
+
// When the primary wallet has already been migrated to DynamicWaaS (no
|
|
43
|
+
// longer a turnkey connector), recovery operations must target the first
|
|
44
|
+
// available legacy Turnkey wallet instead. Without this, shouldInitRecovery
|
|
45
|
+
// returns false (wallet connector isn't passkey-compatible) and the email
|
|
46
|
+
// OTP flow is skipped, leaving V1 wallets unable to export their keys.
|
|
47
|
+
const recoveryWallet = useMemo(() => {
|
|
48
|
+
var _a, _b, _c;
|
|
49
|
+
if ((_b = (_a = primaryWallet === null || primaryWallet === void 0 ? void 0 : primaryWallet.connector) === null || _a === void 0 ? void 0 : _a.key) === null || _b === void 0 ? void 0 : _b.startsWith('turnkey')) {
|
|
50
|
+
return primaryWallet;
|
|
51
|
+
}
|
|
52
|
+
return (_c = legacyWallets[0]) !== null && _c !== void 0 ? _c : primaryWallet;
|
|
53
|
+
}, [primaryWallet, legacyWallets]);
|
|
54
|
+
const [iframeContainer, setIframeContainer] = useState(null);
|
|
55
|
+
const [recoveryAuthenticatorType, setRecoveryAuthenticatorType] = useState();
|
|
56
|
+
const [isValidatingBundle, setIsValidatingBundle] = useState(false);
|
|
57
|
+
const [bundleValidationError, setBundleValidationError] = useState();
|
|
58
|
+
const [isCompletingRecovery, setIsCompletingRecovery] = useState(false);
|
|
59
|
+
const [completeRecoveryError, setCompleteRecoveryError] = useState();
|
|
60
|
+
const emailVerificationResolverRef = useRef(null);
|
|
61
|
+
// Wire the Turnkey session key fetchers so that the connector can create a
|
|
62
|
+
// session when the export step (LegacyEmbeddedWalletExport) calls
|
|
63
|
+
// createOrRestoreSession(). Without this, the connector never gets its
|
|
64
|
+
// fetcher on v5 (the isSessionKeyCompatibleWalletConnector branch was
|
|
65
|
+
// removed from useSetWalletConnectorFetchers during the Turnkey strip).
|
|
66
|
+
// We intentionally do NOT call createOrRestoreSession or getTurnkeyClient
|
|
67
|
+
// here — the export component handles those in the correct sequence.
|
|
68
|
+
const setTurnkeyConnectorFetchers = useSetTurnkeyConnectorFetchers({
|
|
69
|
+
wallet: recoveryWallet,
|
|
70
|
+
});
|
|
71
|
+
useEffect(() => {
|
|
72
|
+
const connector = recoveryWallet === null || recoveryWallet === void 0 ? void 0 : recoveryWallet.connector;
|
|
73
|
+
if (!connector)
|
|
74
|
+
return;
|
|
75
|
+
setTurnkeyConnectorFetchers();
|
|
76
|
+
}, [recoveryWallet, setTurnkeyConnectorFetchers]);
|
|
77
|
+
const awaitEmailVerification = useCallback(() => new Promise((resolve) => {
|
|
78
|
+
emailVerificationResolverRef.current = resolve;
|
|
79
|
+
}), []);
|
|
80
|
+
const resolveEmailVerification = useCallback((wasSuccessful) => {
|
|
81
|
+
var _a;
|
|
82
|
+
(_a = emailVerificationResolverRef.current) === null || _a === void 0 ? void 0 : _a.call(emailVerificationResolverRef, wasSuccessful);
|
|
83
|
+
emailVerificationResolverRef.current = null;
|
|
84
|
+
}, []);
|
|
85
|
+
// Derived from useIsTurnkeyWallet (sdk-react-core internal) — duplicated
|
|
86
|
+
// inline so the migration package doesn't depend on the internal hook.
|
|
87
|
+
// The original counts an "unclaimed turnkey signer of an SCW" as a Turnkey
|
|
88
|
+
// wallet too; we ignore that branch here because the migration flow only
|
|
89
|
+
// covers wallets where the user holds the connector directly.
|
|
90
|
+
const turnkeyVC = useMemo(() => {
|
|
91
|
+
var _a;
|
|
92
|
+
if (!user || !recoveryWallet)
|
|
93
|
+
return undefined;
|
|
94
|
+
if (!recoveryWallet.connector.key.startsWith('turnkey'))
|
|
95
|
+
return undefined;
|
|
96
|
+
return (_a = user.verifiedCredentials) === null || _a === void 0 ? void 0 : _a.find((vc) => vc.id === recoveryWallet.id);
|
|
97
|
+
}, [user, recoveryWallet]);
|
|
98
|
+
const isTurnkeyWalletWithoutAuthenticator = Boolean(turnkeyVC && !((_a = turnkeyVC.walletProperties) === null || _a === void 0 ? void 0 : _a.isAuthenticatorAttached));
|
|
99
|
+
const hasRecoveryEmail = Boolean(turnkeyVC &&
|
|
100
|
+
((_b = user === null || user === void 0 ? void 0 : user.verifiedCredentials) === null || _b === void 0 ? void 0 : _b.some(({ format }) => format === JwtVerifiedCredentialFormatEnum.Email)));
|
|
101
|
+
const supportedSecurityMethods = (_d = (_c = projectSettings === null || projectSettings === void 0 ? void 0 : projectSettings.sdk) === null || _c === void 0 ? void 0 : _c.embeddedWallets) === null || _d === void 0 ? void 0 : _d.supportedSecurityMethods;
|
|
102
|
+
const supportedAuthenticators = useMemo(() => AUTHENTICATOR_KEYS.filter((key) => { var _a; return (_a = supportedSecurityMethods === null || supportedSecurityMethods === void 0 ? void 0 : supportedSecurityMethods[key]) === null || _a === void 0 ? void 0 : _a.isEnabled; }), [supportedSecurityMethods]);
|
|
103
|
+
const onEmailRecoveryComplete = useCallback(() => goToStep('passkey-recovery-complete'), [goToStep]);
|
|
104
|
+
const onShowEmailBundle = useCallback(({ authenticatorType }) => {
|
|
105
|
+
setRecoveryAuthenticatorType(authenticatorType);
|
|
106
|
+
setBundleValidationError(undefined);
|
|
107
|
+
goToStep('passkey-recovery-bundle');
|
|
108
|
+
}, [goToStep]);
|
|
109
|
+
const validateRecoveryBundle = useCallback((bundleInput) => __awaiter(void 0, void 0, void 0, function* () {
|
|
110
|
+
setIsValidatingBundle(true);
|
|
111
|
+
setBundleValidationError(undefined);
|
|
112
|
+
try {
|
|
113
|
+
yield passkeyRecoveryBundleValidation({
|
|
114
|
+
bundleInput,
|
|
115
|
+
user,
|
|
116
|
+
wallet: recoveryWallet,
|
|
117
|
+
});
|
|
118
|
+
if (recoveryAuthenticatorType === 'passkey') {
|
|
119
|
+
goToStep('passkey-recovery-complete');
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
// Email recovery is done — the user is authenticated for the new
|
|
123
|
+
// session, so continue into the upgrade step.
|
|
124
|
+
goToStep('upgrade');
|
|
125
|
+
}
|
|
126
|
+
catch (err) {
|
|
127
|
+
setBundleValidationError(sanitizeUserFacingError(err, GENERIC_BUNDLE_ERROR));
|
|
128
|
+
logger.error('Failed to validate recovery bundle', err);
|
|
129
|
+
}
|
|
130
|
+
finally {
|
|
131
|
+
setIsValidatingBundle(false);
|
|
132
|
+
}
|
|
133
|
+
}), [user, recoveryWallet, recoveryAuthenticatorType, goToStep]);
|
|
134
|
+
const resendRecoveryEmail = useCallback(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
135
|
+
if (!recoveryAuthenticatorType)
|
|
136
|
+
return;
|
|
137
|
+
try {
|
|
138
|
+
yield resentRecoveryEmail({
|
|
139
|
+
authenticatorType: recoveryAuthenticatorType,
|
|
140
|
+
user,
|
|
141
|
+
wallet: recoveryWallet,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
catch (err) {
|
|
145
|
+
logger.error('Failed to resend recovery email', err);
|
|
146
|
+
}
|
|
147
|
+
}), [recoveryAuthenticatorType, user, recoveryWallet]);
|
|
148
|
+
const completeRecovery = useCallback(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
149
|
+
setIsCompletingRecovery(true);
|
|
150
|
+
setCompleteRecoveryError(undefined);
|
|
151
|
+
try {
|
|
152
|
+
yield completePasskeyRecovery({ user, wallet: recoveryWallet });
|
|
153
|
+
goToStep('upgrade');
|
|
154
|
+
}
|
|
155
|
+
catch (err) {
|
|
156
|
+
setCompleteRecoveryError(sanitizeUserFacingError(err, GENERIC_COMPLETE_RECOVERY_ERROR));
|
|
157
|
+
logger.error('Failed to complete passkey recovery', err);
|
|
158
|
+
}
|
|
159
|
+
finally {
|
|
160
|
+
setIsCompletingRecovery(false);
|
|
161
|
+
}
|
|
162
|
+
}), [user, recoveryWallet, goToStep]);
|
|
163
|
+
const recovery = usePasskeyRecovery({
|
|
164
|
+
awaitEmailVerification,
|
|
165
|
+
hasRecoveryEmail,
|
|
166
|
+
iframeContainer,
|
|
167
|
+
isTurnkeyWalletWithoutAuthenticator,
|
|
168
|
+
onAuthMethodComplete: () => goToStep('passkey-recovery-complete'),
|
|
169
|
+
onEmailRecoveryComplete,
|
|
170
|
+
onShowAddRecoveryEmail: () => goToStep('passkey-recovery-add-email'),
|
|
171
|
+
onShowAuthChoice: () => goToStep('embedded-wallet-auth-choice'),
|
|
172
|
+
onShowEmailBundle,
|
|
173
|
+
primaryWallet: recoveryWallet,
|
|
174
|
+
sessionKeyDuration: (_f = (_e = projectSettings === null || projectSettings === void 0 ? void 0 : projectSettings.sdk) === null || _e === void 0 ? void 0 : _e.embeddedWallets) === null || _f === void 0 ? void 0 : _f.sessionKeyDuration,
|
|
175
|
+
supportedSecurityMethods,
|
|
176
|
+
user,
|
|
177
|
+
wallet: recoveryWallet,
|
|
178
|
+
});
|
|
179
|
+
const value = useMemo(() => (Object.assign(Object.assign({}, recovery), { bundleValidationError,
|
|
180
|
+
completeRecovery,
|
|
181
|
+
completeRecoveryError,
|
|
182
|
+
iframeContainer,
|
|
183
|
+
isCompletingRecovery,
|
|
184
|
+
isValidatingBundle,
|
|
185
|
+
recoveryAuthenticatorType, recoveryEmail: user === null || user === void 0 ? void 0 : user.email, resendRecoveryEmail,
|
|
186
|
+
resolveEmailVerification,
|
|
187
|
+
supportedAuthenticators,
|
|
188
|
+
validateRecoveryBundle })), [
|
|
189
|
+
recovery,
|
|
190
|
+
bundleValidationError,
|
|
191
|
+
completeRecovery,
|
|
192
|
+
completeRecoveryError,
|
|
193
|
+
iframeContainer,
|
|
194
|
+
isCompletingRecovery,
|
|
195
|
+
isValidatingBundle,
|
|
196
|
+
recoveryAuthenticatorType,
|
|
197
|
+
user === null || user === void 0 ? void 0 : user.email,
|
|
198
|
+
resendRecoveryEmail,
|
|
199
|
+
resolveEmailVerification,
|
|
200
|
+
supportedAuthenticators,
|
|
201
|
+
validateRecoveryBundle,
|
|
202
|
+
]);
|
|
203
|
+
return (jsxs(LegacyWalletMigrationRecoveryContext.Provider, { value: value, children: [jsx("div", { id: iframeContainerId, ref: setIframeContainer, style: iframeHostStyle, "data-testid": 'legacy-wallet-migration-recovery-iframe-container' }), children] }));
|
|
204
|
+
};
|
|
205
|
+
const useLegacyWalletMigrationRecovery = () => {
|
|
206
|
+
const context = useContext(LegacyWalletMigrationRecoveryContext);
|
|
207
|
+
if (context === undefined) {
|
|
208
|
+
throw new Error('useLegacyWalletMigrationRecovery must be used inside a LegacyWalletMigrationRecoveryProvider.');
|
|
209
|
+
}
|
|
210
|
+
return context;
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
export { LegacyWalletMigrationRecoveryContext, LegacyWalletMigrationRecoveryProvider, useLegacyWalletMigrationRecovery };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { LegacyWalletMigrationRecoveryContext, LegacyWalletMigrationRecoveryProvider, useLegacyWalletMigrationRecovery, type LegacyWalletMigrationRecoveryContextType, type LegacyWalletMigrationRecoveryProviderProps, } from './LegacyWalletMigrationRecoveryContext';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { FC } from 'react';
|
|
2
|
+
import { Wallet, WalletConnectorCore } from '@dynamic-labs/wallet-connector-core';
|
|
3
|
+
export type WaasUpgradeViewProps = {
|
|
4
|
+
wallets: Wallet<WalletConnectorCore.WalletConnector>[];
|
|
5
|
+
onContinue: () => void;
|
|
6
|
+
onCancel: () => void;
|
|
7
|
+
isLoading?: boolean;
|
|
8
|
+
};
|
|
9
|
+
export declare const WaasUpgradeView: FC<WaasUpgradeViewProps>;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
|
+
import { useTranslation } from 'react-i18next';
|
|
4
|
+
import { ModalHeader, Typography, TypographyButton } from '@dynamic-labs/sdk-react-core/components';
|
|
5
|
+
import { UpgradeIcon } from '@dynamic-labs/sdk-react-core/icons';
|
|
6
|
+
|
|
7
|
+
const containerStyle = {
|
|
8
|
+
display: 'flex',
|
|
9
|
+
flexDirection: 'column',
|
|
10
|
+
};
|
|
11
|
+
const contentStyle = {
|
|
12
|
+
alignItems: 'center',
|
|
13
|
+
display: 'flex',
|
|
14
|
+
flexDirection: 'column',
|
|
15
|
+
gap: '24px',
|
|
16
|
+
padding: '24px',
|
|
17
|
+
};
|
|
18
|
+
const illustrationStyle = {
|
|
19
|
+
alignItems: 'center',
|
|
20
|
+
color: 'var(--dynamic-brand-primary-color)',
|
|
21
|
+
display: 'flex',
|
|
22
|
+
height: 80,
|
|
23
|
+
justifyContent: 'center',
|
|
24
|
+
width: 200,
|
|
25
|
+
};
|
|
26
|
+
const descriptionStyle = {
|
|
27
|
+
maxWidth: 340,
|
|
28
|
+
textAlign: 'center',
|
|
29
|
+
};
|
|
30
|
+
const walletsSectionStyle = {
|
|
31
|
+
display: 'flex',
|
|
32
|
+
flexDirection: 'column',
|
|
33
|
+
gap: '8px',
|
|
34
|
+
width: '100%',
|
|
35
|
+
};
|
|
36
|
+
const walletsListStyle = {
|
|
37
|
+
display: 'flex',
|
|
38
|
+
flexDirection: 'column',
|
|
39
|
+
gap: '8px',
|
|
40
|
+
};
|
|
41
|
+
const walletItemStyle = {
|
|
42
|
+
alignItems: 'center',
|
|
43
|
+
borderRadius: 8,
|
|
44
|
+
display: 'flex',
|
|
45
|
+
gap: '12px',
|
|
46
|
+
padding: '12px',
|
|
47
|
+
};
|
|
48
|
+
const actionsStyle = {
|
|
49
|
+
display: 'flex',
|
|
50
|
+
flexDirection: 'column',
|
|
51
|
+
gap: '8px',
|
|
52
|
+
marginTop: '8px',
|
|
53
|
+
width: '100%',
|
|
54
|
+
};
|
|
55
|
+
const shortenAddress = (address) => `${address.slice(0, 6)}...${address.slice(-4)}`;
|
|
56
|
+
const WaasUpgradeView = ({ wallets, onContinue, onCancel, isLoading = false, }) => {
|
|
57
|
+
const { t } = useTranslation();
|
|
58
|
+
const hasWallets = wallets.length > 0;
|
|
59
|
+
return (jsxs("div", { style: containerStyle, children: [jsx(ModalHeader, { children: jsx(Typography, { as: 'h1', variant: 'title', color: 'primary', children: t('dyn_upgrade_wallet.title') }) }), jsxs("div", { style: contentStyle, children: [jsx("div", { style: illustrationStyle, children: jsx(UpgradeIcon, {}) }), jsx(Typography, { as: 'p', variant: 'body_normal', color: 'primary', style: descriptionStyle, children: t('dyn_upgrade_wallet.description') }), hasWallets ? (jsxs("div", { style: walletsSectionStyle, children: [jsx(Typography, { color: 'primary', children: t('dyn_upgrade_wallet.eligible_wallets') }), jsx("div", { style: walletsListStyle, "data-testid": 'waas-upgrade-view-wallets-list', children: wallets.map((wallet) => (jsxs("div", { style: walletItemStyle, "data-testid": 'waas-upgrade-view-wallet-item', children: [jsx(Typography, { color: 'primary', children: wallet.chain }), jsx(Typography, { color: 'primary', children: shortenAddress(wallet.address) })] }, wallet.id))) })] })) : (jsx(Typography, { color: 'secondary', style: descriptionStyle, copykey: 'dyn_upgrade_wallet.no_legacy_wallets', "data-testid": 'waas-upgrade-view-no-legacy-wallets', children: t('dyn_upgrade_wallet.no_legacy_wallets') })), jsx("div", { style: actionsStyle, children: hasWallets ? (jsx(TypographyButton, { buttonVariant: 'brand-primary', onClick: onContinue, disabled: isLoading, loading: isLoading, copykey: 'dyn_upgrade_wallet.upgrade', typographyProps: { color: 'inherit' }, dataTestId: 'waas-upgrade-view-continue-button', children: t('dyn_upgrade_wallet.upgrade') })) : (jsx(TypographyButton, { buttonVariant: 'tertiary', onClick: onCancel, dataTestId: 'waas-upgrade-view-close-button', children: t('dyn_upgrade_wallet.close') })) })] })] }));
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export { WaasUpgradeView };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { WaasUpgradeView, type WaasUpgradeViewProps } from './WaasUpgradeView';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { FC } from 'react';
|
|
2
|
+
import { Wallet, WalletConnectorCore } from '@dynamic-labs/wallet-connector-core';
|
|
3
|
+
export type WalletUpgradeFlowViewOnUpgradeArgs = {
|
|
4
|
+
wallet: Wallet<WalletConnectorCore.WalletConnector>;
|
|
5
|
+
privateKey: string;
|
|
6
|
+
};
|
|
7
|
+
export type WalletUpgradeFlowViewProps = {
|
|
8
|
+
wallets: Wallet<WalletConnectorCore.WalletConnector>[];
|
|
9
|
+
onUpgrade: (args: WalletUpgradeFlowViewOnUpgradeArgs) => Promise<void>;
|
|
10
|
+
onFinish: () => void;
|
|
11
|
+
};
|
|
12
|
+
export declare const WalletUpgradeFlowView: FC<WalletUpgradeFlowViewProps>;
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
import { __awaiter } from '../../../../_virtual/_tslib.js';
|
|
3
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
4
|
+
import { useState } from 'react';
|
|
5
|
+
import { useTranslation } from 'react-i18next';
|
|
6
|
+
import { ModalHeader, Typography, ErrorContainer, Textarea, TypographyButton } from '@dynamic-labs/sdk-react-core/components';
|
|
7
|
+
import { LegacyEmbeddedWalletExport } from '../LegacyEmbeddedWalletExport/LegacyEmbeddedWalletExport.js';
|
|
8
|
+
|
|
9
|
+
const containerStyle = {
|
|
10
|
+
display: 'flex',
|
|
11
|
+
flexDirection: 'column',
|
|
12
|
+
};
|
|
13
|
+
const stepperStyle = {
|
|
14
|
+
alignItems: 'center',
|
|
15
|
+
display: 'flex',
|
|
16
|
+
flexWrap: 'wrap',
|
|
17
|
+
gap: 12,
|
|
18
|
+
justifyContent: 'center',
|
|
19
|
+
padding: '16px 24px',
|
|
20
|
+
width: '100%',
|
|
21
|
+
};
|
|
22
|
+
const stepStyle = {
|
|
23
|
+
alignItems: 'center',
|
|
24
|
+
display: 'flex',
|
|
25
|
+
gap: 8,
|
|
26
|
+
};
|
|
27
|
+
const stepSeparatorStyle = {
|
|
28
|
+
background: 'var(--dynamic-border-color)',
|
|
29
|
+
height: 1,
|
|
30
|
+
width: 16,
|
|
31
|
+
};
|
|
32
|
+
const contentStyle = {
|
|
33
|
+
display: 'flex',
|
|
34
|
+
flexDirection: 'column',
|
|
35
|
+
gap: 24,
|
|
36
|
+
padding: '24px',
|
|
37
|
+
};
|
|
38
|
+
const sectionStyle = {
|
|
39
|
+
display: 'flex',
|
|
40
|
+
flexDirection: 'column',
|
|
41
|
+
gap: 12,
|
|
42
|
+
};
|
|
43
|
+
const titleSectionStyle = {
|
|
44
|
+
display: 'flex',
|
|
45
|
+
flexDirection: 'column',
|
|
46
|
+
gap: 8,
|
|
47
|
+
};
|
|
48
|
+
const actionsStyle = {
|
|
49
|
+
display: 'flex',
|
|
50
|
+
flexDirection: 'column',
|
|
51
|
+
gap: 12,
|
|
52
|
+
padding: '0 24px 24px 24px',
|
|
53
|
+
};
|
|
54
|
+
const baseStepIndicatorStyle = {
|
|
55
|
+
alignItems: 'center',
|
|
56
|
+
borderRadius: '50%',
|
|
57
|
+
borderStyle: 'solid',
|
|
58
|
+
borderWidth: 1,
|
|
59
|
+
display: 'flex',
|
|
60
|
+
fontSize: 12,
|
|
61
|
+
fontWeight: 600,
|
|
62
|
+
height: 24,
|
|
63
|
+
justifyContent: 'center',
|
|
64
|
+
width: 24,
|
|
65
|
+
};
|
|
66
|
+
const getStepIndicatorStyle = (current, completed) => {
|
|
67
|
+
if (completed || current) {
|
|
68
|
+
return Object.assign(Object.assign({}, baseStepIndicatorStyle), { background: 'var(--dynamic-brand-primary-color)', borderColor: 'var(--dynamic-brand-primary-color)', color: 'white' });
|
|
69
|
+
}
|
|
70
|
+
return Object.assign(Object.assign({}, baseStepIndicatorStyle), { background: 'transparent', borderColor: 'var(--dynamic-border-color)', color: 'var(--dynamic-text-secondary)' });
|
|
71
|
+
};
|
|
72
|
+
const WalletUpgradeFlowView = ({ wallets, onUpgrade, onFinish, }) => {
|
|
73
|
+
const { t } = useTranslation();
|
|
74
|
+
const [currentIndex, setCurrentIndex] = useState(0);
|
|
75
|
+
const [privateKeyInput, setPrivateKeyInput] = useState('');
|
|
76
|
+
const [isUpgrading, setIsUpgrading] = useState(false);
|
|
77
|
+
const [errorMessage, setErrorMessage] = useState(null);
|
|
78
|
+
const currentWallet = wallets[currentIndex];
|
|
79
|
+
if (!currentWallet) {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
const totalSteps = wallets.length;
|
|
83
|
+
const isLastWallet = currentIndex === totalSteps - 1;
|
|
84
|
+
const trimmedPrivateKey = privateKeyInput.trim();
|
|
85
|
+
const handleUpgrade = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
86
|
+
setIsUpgrading(true);
|
|
87
|
+
setErrorMessage(null);
|
|
88
|
+
try {
|
|
89
|
+
yield onUpgrade({
|
|
90
|
+
privateKey: trimmedPrivateKey,
|
|
91
|
+
wallet: currentWallet,
|
|
92
|
+
});
|
|
93
|
+
setPrivateKeyInput('');
|
|
94
|
+
if (isLastWallet) {
|
|
95
|
+
onFinish();
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
setCurrentIndex((previous) => previous + 1);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
setErrorMessage(error instanceof Error
|
|
103
|
+
? error.message
|
|
104
|
+
: t('dyn_wallet_upgrade_flow.upgrade_failed'));
|
|
105
|
+
}
|
|
106
|
+
finally {
|
|
107
|
+
setIsUpgrading(false);
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
return (jsxs("div", { style: containerStyle, "data-testid": 'wallet-upgrade-flow-view', children: [jsx(ModalHeader, { children: totalSteps > 1 && (jsx("div", { style: stepperStyle, children: wallets.map((wallet, index) => {
|
|
111
|
+
var _a, _b;
|
|
112
|
+
const completed = index < currentIndex;
|
|
113
|
+
const current = index === currentIndex;
|
|
114
|
+
return (jsxs("div", { style: stepStyle, children: [jsx("div", Object.assign({ style: getStepIndicatorStyle(current, completed) }, (current
|
|
115
|
+
? {
|
|
116
|
+
'data-testid': 'wallet-upgrade-step-current',
|
|
117
|
+
}
|
|
118
|
+
: {}), { children: completed ? '✓' : index + 1 })), jsx(Typography, { variant: 'body_small', color: index <= currentIndex ? 'primary' : 'secondary', children: t('dyn_wallet_upgrade_flow.step_wallet_upgrade', {
|
|
119
|
+
walletName: (_a = wallet.chain) !== null && _a !== void 0 ? _a : 'Wallet',
|
|
120
|
+
}) }), index < totalSteps - 1 && jsx("div", { style: stepSeparatorStyle })] }, (_b = wallet.id) !== null && _b !== void 0 ? _b : index));
|
|
121
|
+
}) })) }), jsxs("div", { style: contentStyle, children: [errorMessage && jsx(ErrorContainer, { children: errorMessage }), jsxs("div", { style: titleSectionStyle, children: [jsx(Typography, { as: 'h1', variant: 'title', color: 'primary', children: t('dyn_wallet_upgrade_flow.title') }), jsx(Typography, { color: 'secondary', children: t('dyn_wallet_upgrade_flow.copy_private_key_subtitle') })] }), jsxs("div", { style: sectionStyle, children: [jsx(Typography, { variant: 'body_normal', weight: 'bold', color: 'primary', children: t('dyn_wallet_upgrade_flow.copy_private_key_title') }), jsx(LegacyEmbeddedWalletExport, { wallet: currentWallet }, `wallet-export-${currentIndex}-${currentWallet.id}`)] }), jsxs("div", { style: sectionStyle, children: [jsx(Typography, { variant: 'body_normal', weight: 'bold', color: 'primary', children: t('dyn_wallet_upgrade_flow.step_2_upgrade_description') }), jsx(Textarea, { id: 'wallet-upgrade-flow-private-key', value: privateKeyInput, onChange: (event) => setPrivateKeyInput(event.target.value), variant: 'regular', label: '', "data-testid": 'paste-private-key-input' })] })] }), jsx("div", { style: actionsStyle, children: jsx(TypographyButton, { buttonVariant: 'brand-primary', onClick: handleUpgrade, disabled: !trimmedPrivateKey || isUpgrading, loading: isUpgrading, expanded: true, dataTestId: 'wallet-upgrade-flow-upgrade-button', typographyProps: { color: 'inherit' }, children: t('dyn_wallet_upgrade_flow.upgrade_wallet') }) })] }));
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
export { WalletUpgradeFlowView };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { WalletUpgradeFlowView, type WalletUpgradeFlowViewProps, type WalletUpgradeFlowViewOnUpgradeArgs, } from './WalletUpgradeFlowView';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { FC } from 'react';
|
|
2
|
+
export type LegacyAddRecoveryEmailViewProps = {
|
|
3
|
+
onSubmit: (email: string) => Promise<void> | void;
|
|
4
|
+
onCancel: () => void;
|
|
5
|
+
defaultEmail?: string;
|
|
6
|
+
isSubmitting?: boolean;
|
|
7
|
+
errorMessage?: string;
|
|
8
|
+
};
|
|
9
|
+
export declare const LegacyAddRecoveryEmailView: FC<LegacyAddRecoveryEmailViewProps>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
3
|
+
import { useTranslation } from 'react-i18next';
|
|
4
|
+
import { IconButton, ModalHeader, Typography, EmailForm } from '@dynamic-labs/sdk-react-core/components';
|
|
5
|
+
import { CloseIcon } from '@dynamic-labs/sdk-react-core/icons';
|
|
6
|
+
|
|
7
|
+
const EMAIL_SUBMIT_COPY_KEY = 'dyn_passkey_recovery.add_email.confirm_button';
|
|
8
|
+
const containerStyle = {
|
|
9
|
+
display: 'flex',
|
|
10
|
+
flexDirection: 'column',
|
|
11
|
+
gap: 24,
|
|
12
|
+
padding: 24,
|
|
13
|
+
};
|
|
14
|
+
const descriptionStyle = { maxWidth: 360 };
|
|
15
|
+
const LegacyAddRecoveryEmailView = ({ onSubmit, onCancel, defaultEmail, isSubmitting, errorMessage }) => {
|
|
16
|
+
const { t } = useTranslation();
|
|
17
|
+
const closeButton = (jsx(IconButton, { onClick: onCancel, type: 'button', children: jsx(CloseIcon, {}) }));
|
|
18
|
+
return (jsxs(Fragment, { children: [jsx(ModalHeader, { trailing: closeButton, children: jsx(Typography, { variant: 'title', color: 'primary', children: t('dyn_passkey_recovery.add_email.title') }) }), jsxs("div", { style: containerStyle, children: [jsx(Typography, { variant: 'body_normal', color: 'secondary', style: descriptionStyle, children: t('dyn_passkey_recovery.add_email.description') }), errorMessage && (jsx(Typography, { variant: 'body_small', color: 'error-1', children: errorMessage })), jsx(EmailForm, { onSubmit: onSubmit, isLoading: Boolean(isSubmitting), currentEmail: defaultEmail, buttonCopyKey: EMAIL_SUBMIT_COPY_KEY })] })] }));
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export { LegacyAddRecoveryEmailView };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { LegacyAddRecoveryEmailView, type LegacyAddRecoveryEmailViewProps, } from './LegacyAddRecoveryEmailView';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { FC } from 'react';
|
|
2
|
+
import { AuthenticatorType } from '@dynamic-labs/wallet-connector-core';
|
|
3
|
+
export type LegacyEmbeddedAuthChoiceViewProps = {
|
|
4
|
+
supportedAuthenticators: AuthenticatorType[];
|
|
5
|
+
onSelect: (authenticatorType: AuthenticatorType) => Promise<void> | void;
|
|
6
|
+
onCancel: () => void;
|
|
7
|
+
isSubmitting?: boolean;
|
|
8
|
+
};
|
|
9
|
+
export declare const LegacyEmbeddedAuthChoiceView: FC<LegacyEmbeddedAuthChoiceViewProps>;
|
|
@@ -0,0 +1,29 @@
|
|
|
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 } from '@dynamic-labs/sdk-react-core/icons';
|
|
6
|
+
|
|
7
|
+
const containerStyle = {
|
|
8
|
+
display: 'flex',
|
|
9
|
+
flexDirection: 'column',
|
|
10
|
+
gap: 24,
|
|
11
|
+
padding: 24,
|
|
12
|
+
};
|
|
13
|
+
const buttonGroupStyle = {
|
|
14
|
+
display: 'flex',
|
|
15
|
+
flexDirection: 'column',
|
|
16
|
+
gap: 12,
|
|
17
|
+
};
|
|
18
|
+
// Stub — the cards-based selector UX is wired in PR C.2 alongside the
|
|
19
|
+
// usePasskeyRecovery hook integration. For now this view renders one button
|
|
20
|
+
// per supported authenticator so the step machine can be exercised.
|
|
21
|
+
const LegacyEmbeddedAuthChoiceView = ({ supportedAuthenticators, onSelect, onCancel, isSubmitting }) => {
|
|
22
|
+
const { t } = useTranslation();
|
|
23
|
+
const closeButton = (jsx(IconButton, { onClick: onCancel, type: 'button', children: jsx(CloseIcon, {}) }));
|
|
24
|
+
return (jsxs(Fragment, { children: [jsx(ModalHeader, { trailing: closeButton, children: jsx(Typography, { variant: 'title', color: 'primary', children: t('dyn_embedded_authenticator.title') }) }), jsxs("div", { style: containerStyle, children: [jsx(Typography, { variant: 'body_normal', color: 'secondary', children: t('dyn_embedded_authenticator.description') }), jsx("div", { style: buttonGroupStyle, children: supportedAuthenticators.map((authenticatorType) => (jsx(TypographyButton, { dataTestId: `legacy-auth-choice-${authenticatorType}`, onClick: () => onSelect(authenticatorType), buttonVariant: 'brand-primary', expanded: true, disabled: isSubmitting, typographyProps: { color: 'white' }, children: authenticatorType === 'passkey'
|
|
25
|
+
? t('dyn_embedded_authenticator.passkey.title')
|
|
26
|
+
: t('dyn_embedded_authenticator.email.title') }, authenticatorType))) })] })] }));
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export { LegacyEmbeddedAuthChoiceView };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { LegacyEmbeddedAuthChoiceView, type LegacyEmbeddedAuthChoiceViewProps, } from './LegacyEmbeddedAuthChoiceView';
|
package/src/lib/ui/recovery/LegacyPasskeyBundleRecoveryView/LegacyPasskeyBundleRecoveryView.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { FC } from 'react';
|
|
2
|
+
export type LegacyPasskeyBundleRecoveryViewProps = {
|
|
3
|
+
email: string | undefined;
|
|
4
|
+
onSubmit: (bundleInput: string) => Promise<void> | void;
|
|
5
|
+
onResend: () => Promise<void> | void;
|
|
6
|
+
onCancel: () => void;
|
|
7
|
+
isSubmitting?: boolean;
|
|
8
|
+
errorMessage?: string;
|
|
9
|
+
};
|
|
10
|
+
export declare const LegacyPasskeyBundleRecoveryView: FC<LegacyPasskeyBundleRecoveryViewProps>;
|