Skip to content

Commit 57cf49a

Browse files
feat: unify Midnight wallet onboarding flow
- Add Midnight to "Select Blockchain" screen (create/restore wallet) - Remove separate AddNewMidnightWalletLink from dropdown menu - Add useLMP hook with startMidnightCreate/Restore methods
1 parent f56930f commit 57cf49a

File tree

20 files changed

+404
-149
lines changed

20 files changed

+404
-149
lines changed

v1/apps/browser-extension-wallet/src/components/MainMenu/DropdownMenuOverlay/DropdownMenuOverlay.tsx

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,8 @@ import { getBackgroundStorage, setBackgroundStorage } from '@lib/scripts/backgro
3434
import { useBackgroundServiceAPIContext } from '@providers';
3535
import { WarningModal } from '@src/views/browser-view/components';
3636
import { useTranslation } from 'react-i18next';
37-
import { useCurrentWallet, useWalletManager, useLMP } from '@hooks';
37+
import { useCurrentWallet, useWalletManager } from '@hooks';
3838
import { useCurrentBlockchain } from '@src/multichain';
39-
import { AddNewMidnightWalletLink } from './components/AddNewMidnightWalletLink';
4039

4140
interface Props extends MenuProps {
4241
isPopup?: boolean;
@@ -61,10 +60,8 @@ export const DropdownMenuOverlay: VFC<Props> = ({
6160
const { walletRepository } = useWalletManager();
6261
const currentWallet = useCurrentWallet();
6362
const wallets = useObservable(walletRepository.wallets$);
64-
const { midnightWallets } = useLMP();
6563

6664
const sharedWalletsEnabled = posthog?.isFeatureFlagEnabled('shared-wallets');
67-
const midnightWalletsEnabled = posthog?.isFeatureFlagEnabled('midnight-wallets');
6865
const [currentSection, setCurrentSection] = useState<Sections>(Sections.Main);
6966
const { environmentName, setManageAccountsWallet, walletType, isSharedWallet } = useWalletStore();
7067
const { blockchain } = useCurrentBlockchain();
@@ -140,7 +137,6 @@ export const DropdownMenuOverlay: VFC<Props> = ({
140137
!isBitcoinWallet &&
141138
wallets?.some((w) => w.type === WalletType.Script && w.ownSigners[0].walletId === currentWallet?.walletId);
142139
const showAddSharedWalletLink = sharedWalletsEnabled && !isSharedWallet && !hasLinkedSharedWallet;
143-
const showAddMidnightWalletLink = midnightWalletsEnabled && midnightWallets && midnightWallets.length === 0;
144140

145141
const handleNamiModeChange = async (activated: boolean) => {
146142
const mode = activated ? 'nami' : 'lace';
@@ -195,7 +191,6 @@ export const DropdownMenuOverlay: VFC<Props> = ({
195191
<AddNewWalletLink isPopup={isPopup} sendAnalyticsEvent={sendAnalyticsEvent} />
196192
)}
197193
{!isBitcoinWallet && showAddSharedWalletLink && <AddSharedWalletLink isPopup={isPopup} />}
198-
{showAddMidnightWalletLink && <AddNewMidnightWalletLink />}
199194
{!isBitcoinWallet && <AddressBookLink />}
200195
<SettingsLink />
201196
<Separator />

v1/apps/browser-extension-wallet/src/components/MainMenu/DropdownMenuOverlay/components/AddNewMidnightWalletLink.tsx

Lines changed: 0 additions & 26 deletions
This file was deleted.

v1/apps/browser-extension-wallet/src/components/MainMenu/DropdownMenuOverlay/components/AddNewWalletLink.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,15 @@ import { walletRoutePaths } from '@routes';
33
import { Menu } from 'antd';
44
import { useTranslation } from 'react-i18next';
55
import { Link, useLocation } from 'react-router-dom';
6+
import { storage } from 'webextension-polyfill';
67
import styles from '../DropdownMenuOverlay.module.scss';
78
import { useBackgroundServiceAPIContext } from '@providers';
89
import { BrowserViewSections } from '@lib/scripts/types';
910
import { useBackgroundPage } from '@providers/BackgroundPageProvider';
1011
import { PostHogAction } from '@lace/common';
1112

13+
const CAME_FROM_LMP_KEY = 'lace-came-from-lmp';
14+
1215
interface Props {
1316
isPopup?: boolean;
1417
sendAnalyticsEvent?: (event: PostHogAction) => void;
@@ -22,6 +25,7 @@ export const AddNewWalletLink = ({ isPopup, sendAnalyticsEvent }: Props): React.
2225

2326
const openNewWallet = () => {
2427
sendAnalyticsEvent(PostHogAction.UserWalletProfileAddNewWalletClick);
28+
void storage.local.remove(CAME_FROM_LMP_KEY);
2529
if (isPopup) {
2630
backgroundServices.handleOpenBrowser({ section: BrowserViewSections.NEW_WALLET });
2731
} else {
Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
import { consumeRemoteApi } from '@cardano-sdk/web-extension';
22
import { logger, useObservable } from '@lace/common';
3-
import { APP_MODE, bundleAppApiProps, lmpApiBaseChannel, LmpBundleWallet, lmpModeStorage } from '@src/utils/lmp';
3+
import {
4+
APP_MODE,
5+
bundleAppApiProps,
6+
lmpApiBaseChannel,
7+
LmpBundleWallet,
8+
lmpModeStorage,
9+
onboardingParamsStorage,
10+
setPendingMnemonic
11+
} from '@src/utils/lmp';
412
import { runtime } from 'webextension-polyfill';
513

614
const lmpApi = consumeRemoteApi(
@@ -11,18 +19,44 @@ const lmpApi = consumeRemoteApi(
1119
{ logger, runtime }
1220
);
1321

22+
const navigateToLMP = (): void => {
23+
if (window.location.pathname.startsWith('/popup.html')) {
24+
chrome.tabs.create({ url: '/tab.html' });
25+
} else {
26+
window.location.href = '/tab.html';
27+
}
28+
};
29+
1430
const switchToLMP = (): void =>
1531
void (async () => {
1632
await lmpModeStorage.set(APP_MODE.LMP);
17-
if (window.location.pathname.startsWith('/popup.html')) {
18-
chrome.tabs.create({ url: '/tab.html' });
19-
} else {
20-
window.location.href = '/tab.html';
21-
}
33+
navigateToLMP();
34+
})();
35+
36+
const startMidnightCreate = (): void =>
37+
void (async () => {
38+
await onboardingParamsStorage.set({ mode: 'create' });
39+
await lmpModeStorage.set(APP_MODE.LMP);
40+
navigateToLMP();
41+
})();
42+
43+
const startMidnightRestore = (): void =>
44+
void (async () => {
45+
await onboardingParamsStorage.set({ mode: 'restore' });
46+
await lmpModeStorage.set(APP_MODE.LMP);
47+
navigateToLMP();
48+
})();
49+
50+
const startMidnightRestoreReuse = (mnemonic: string[]): void =>
51+
void (async () => {
52+
await setPendingMnemonic(mnemonic);
53+
await onboardingParamsStorage.set({ mode: 'restore-reuse' });
54+
await lmpModeStorage.set(APP_MODE.LMP);
55+
navigateToLMP();
2256
})();
2357

2458
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
2559
export const useLMP = () => {
2660
const midnightWallets = useObservable<LmpBundleWallet[] | undefined>(lmpApi.wallets$);
27-
return { midnightWallets, switchToLMP };
61+
return { midnightWallets, switchToLMP, startMidnightCreate, startMidnightRestore, startMidnightRestoreReuse };
2862
};

v1/apps/browser-extension-wallet/src/lib/scripts/background/services/lmpService.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* eslint-disable @typescript-eslint/no-var-requires */
2-
import { BundleAppApi, LmpBundleWallet, v1ApiGlobalProperty } from '@src/utils/lmp';
2+
import { BundleAppApi, LmpBundleWallet, v1ApiGlobalProperty, getPendingMnemonic } from '@src/utils/lmp';
33
import { BehaviorSubject, firstValueFrom, map } from 'rxjs';
44
import { bitcoinWalletManager, walletManager, walletRepository } from '../wallet';
55
import { AnyBip32Wallet, AnyWallet, InMemoryWallet, WalletType } from '@cardano-sdk/web-extension';
@@ -113,7 +113,8 @@ const api: BundleAppApi = {
113113
language$.next(language);
114114
await setBackgroundStorage({ languageChoice: language });
115115
requestMessage$.next({ type: MessageTypes.CHANGE_LANGUAGE, data: language });
116-
}
116+
},
117+
getPendingMnemonic: async (): Promise<string[] | undefined> => await getPendingMnemonic()
117118
};
118119

119120
// eslint-disable-next-line @typescript-eslint/no-explicit-any

v1/apps/browser-extension-wallet/src/utils/lmp.ts

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,45 @@ export type BundleAppApi = {
2020
activate(walletId: string): Promise<void>;
2121
language$: Observable<Language>;
2222
setLanguage(language: Language): Promise<void>;
23+
getPendingMnemonic(): Promise<string[] | undefined>;
2324
};
2425
export const bundleAppApiProps: RemoteApiProperties<BundleAppApi> = {
2526
wallets$: RemoteApiPropertyType.HotObservable,
2627
activate: RemoteApiPropertyType.MethodReturningPromise,
2728
language$: RemoteApiPropertyType.HotObservable,
28-
setLanguage: RemoteApiPropertyType.MethodReturningPromise
29+
setLanguage: RemoteApiPropertyType.MethodReturningPromise,
30+
getPendingMnemonic: RemoteApiPropertyType.MethodReturningPromise
2931
};
32+
33+
const PENDING_MNEMONIC_KEY = 'lace-pending-mnemonic';
34+
35+
export const setPendingMnemonic = async (mnemonic: string[]): Promise<void> => {
36+
await storage.local.set({ [PENDING_MNEMONIC_KEY]: mnemonic });
37+
};
38+
39+
export const getPendingMnemonic = async (): Promise<string[] | undefined> => {
40+
const result = await storage.local.get(PENDING_MNEMONIC_KEY);
41+
const mnemonic = result[PENDING_MNEMONIC_KEY] as string[] | undefined;
42+
await storage.local.remove(PENDING_MNEMONIC_KEY);
43+
return mnemonic;
44+
};
45+
3046
export const lmpApiBaseChannel = 'bundle-lmp';
3147
export const v1ApiGlobalProperty = 'bundleV1';
3248
export const STORAGE_KEY = {
33-
APP_MODE: 'lace-app-mode'
49+
APP_MODE: 'lace-app-mode',
50+
ONBOARDING_PARAMS: 'lace-lmp-onboarding-params'
51+
};
52+
53+
export type OnboardingParams = { mode: 'create' } | { mode: 'restore' } | { mode: 'restore-reuse' };
54+
55+
export const onboardingParamsStorage = {
56+
set: (params: OnboardingParams): Promise<void> => storage.local.set({ [STORAGE_KEY.ONBOARDING_PARAMS]: params }),
57+
get: async (): Promise<OnboardingParams | undefined> => {
58+
const result = await storage.local.get(STORAGE_KEY.ONBOARDING_PARAMS);
59+
return result[STORAGE_KEY.ONBOARDING_PARAMS] as OnboardingParams | undefined;
60+
},
61+
clear: (): Promise<void> => storage.local.remove(STORAGE_KEY.ONBOARDING_PARAMS)
3462
};
3563
export enum APP_MODE {
3664
LMP = 'LMP',

v1/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/MultiWallet.tsx

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,30 +3,51 @@ import { NavigationButton } from '@lace/common';
33
import { WalletSetupConfirmationDialogProvider, WalletSetupFlow, WalletSetupFlowProvider } from '@lace/core';
44
import { useBackgroundPage } from '@providers/BackgroundPageProvider';
55
import { walletRoutePaths } from '@routes';
6-
import React, { useCallback } from 'react';
6+
import React, { useCallback, useEffect, useState } from 'react';
77
import { useHistory } from 'react-router-dom';
8+
import { storage } from 'webextension-polyfill';
89
import styles from './MultiWallet.module.scss';
910
import { WalletOnboardingFlows } from './WalletOnboardingFlows';
1011
import { postHogMultiWalletActions } from '@providers/AnalyticsProvider/analyticsTracker';
1112
import { Home } from './Home';
1213
import { usePostHogClientContext } from '@providers/PostHogClientProvider';
1314
import { WalletSetupLayout } from '@views/browser/components';
1415
import { Portal } from '@views/browser/features/wallet-setup/components/Portal';
16+
import { APP_MODE, lmpModeStorage } from '@src/utils/lmp';
17+
18+
const CAME_FROM_LMP_KEY = 'lace-came-from-lmp';
1519

1620
export const MultiWallet = (): JSX.Element => {
1721
const history = useHistory();
1822
const posthogClient = usePostHogClientContext();
1923
const { page, setBackgroundPage } = useBackgroundPage();
24+
const [cameFromLMP, setCameFromLMP] = useState(false);
25+
26+
useEffect(() => {
27+
const checkCameFromLMP = async () => {
28+
const result = await storage.local.get(CAME_FROM_LMP_KEY);
29+
if (result[CAME_FROM_LMP_KEY]) {
30+
setCameFromLMP(true);
31+
}
32+
};
33+
void checkCameFromLMP();
34+
}, []);
2035

2136
const handleOnCancel = useCallback(
2237
(withConfirmationDialog: (callback: () => void) => () => void) => {
23-
withConfirmationDialog(() => {
38+
withConfirmationDialog(async () => {
39+
if (cameFromLMP) {
40+
await storage.local.remove(CAME_FROM_LMP_KEY);
41+
await lmpModeStorage.set(APP_MODE.LMP);
42+
window.location.href = '/tab.html';
43+
return;
44+
}
2445
setBackgroundPage();
2546
history.push(page);
2647
window.location.reload();
2748
})();
2849
},
29-
[history, page, setBackgroundPage]
50+
[history, page, setBackgroundPage, cameFromLMP]
3051
);
3152

3253
return (

0 commit comments

Comments
 (0)