Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[LW-9499] New wallet manager migration #833

Draft
wants to merge 27 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
ec20f46
chore: update cardano-sdk packages
mchappell Nov 29, 2023
81d41e0
refactor: update lace based on cardano-sdk breaking changes
mchappell Nov 29, 2023
035160c
chore: bump sdk versions (#782)
renanvalentin Dec 13, 2023
86ef8d0
chore: bump sdk version
renanvalentin Dec 14, 2023
d3df0f6
refactor(extension): use message sender to get dapp information
renanvalentin Dec 14, 2023
661bf0d
refactor(extension): [LW-9094] use new wallet manager
mkazlauskas Jan 4, 2024
fb127d1
feat: add lock and key angent data migration
Jan 11, 2024
95da612
feat: check if wallet already exists in repository
Jan 12, 2024
e0436a7
feat: activate wallet
Jan 15, 2024
0a49a4e
feat: handle locked wallet case
Jan 15, 2024
48fc319
feat: reset lock
Jan 16, 2024
8859572
fix: remove unused
Jan 16, 2024
eb48539
fixup! refactor(extension): [LW-9094] use new wallet manager
mkazlauskas Jan 17, 2024
aa44aba
fixup! refactor(extension): [LW-9094] use new wallet manager
mkazlauskas Jan 17, 2024
2e1feb6
fixup! refactor(extension): [LW-9094] use new wallet manager
mkazlauskas Jan 17, 2024
3947c1b
fixup! refactor(extension): [LW-9094] use new wallet manager
mkazlauskas Jan 17, 2024
450f961
feat: add metadata to wallet
Jan 17, 2024
80b1fe0
fixup! refactor(extension): [LW-9094] use new wallet manager
mkazlauskas Jan 17, 2024
b0083fe
ci: set higher memory limit for running ci unit tests
mkazlauskas Jan 17, 2024
15088d3
chore: empty commit, unblock ci
mkazlauskas Jan 17, 2024
aa9adbc
fixup! refactor(extension): [LW-9094] use new wallet manager
mkazlauskas Jan 18, 2024
5f032b3
fixup! refactor(extension): [LW-9094] use new wallet manager
mkazlauskas Jan 18, 2024
daa9f96
Merge branch 'LW-9094-new-wallet-manager' into feat/lw-9499-migration
Jan 18, 2024
eef60ea
fix: wallet name
Jan 18, 2024
fe614f5
feat: remove old wallet metadata
Jan 18, 2024
0b2b8ab
feat: remove wallet in rollback
Jan 18, 2024
1c0b289
fix: add no wallets check
Jan 18, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ jobs:
env:
AVAILABLE_CHAINS: 'Preprod,Preview,Mainnet'
DEFAULT_CHAIN: 'Preprod'
NODE_OPTIONS: '--max_old_space_size=8192'
run: yarn test:coverage --maxWorkers=2
- name: Upload build
uses: actions/upload-artifact@v3
Expand Down
4 changes: 2 additions & 2 deletions apps/browser-extension-wallet/.env.defaults
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ POSTHOG_DEV_TOKEN_PREVIEW=phc_e8SaOOWpXpNE59TnpLumeUjWm4iv024AWjhQqU406jr

# Cardano Services
CARDANO_SERVICES_URL_MAINNET=https://backend.live-mainnet.eks.lw.iog.io
CARDANO_SERVICES_URL_PREPROD=https://backend.live-preprod.eks.lw.iog.io
CARDANO_SERVICES_URL_PREVIEW=https://backend.live-preview.eks.lw.iog.io
CARDANO_SERVICES_URL_PREPROD=https://backend.dev-preprod.eks.lw.iog.io
CARDANO_SERVICES_URL_PREVIEW=https://backend.dev-preview.eks.lw.iog.io

# Explorer URLs
CEXPLORER_URL_MAINNET=https://cexplorer.io
Expand Down
16 changes: 8 additions & 8 deletions apps/browser-extension-wallet/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,14 @@
},
"dependencies": {
"@ant-design/icons": "^4.7.0",
"@cardano-sdk/cardano-services-client": "0.14.4",
"@cardano-sdk/core": "0.21.0",
"@cardano-sdk/dapp-connector": "0.11.1",
"@cardano-sdk/input-selection": "0.12.4",
"@cardano-sdk/tx-construction": "0.14.2",
"@cardano-sdk/util": "0.14.2",
"@cardano-sdk/wallet": "0.25.1",
"@cardano-sdk/web-extension": "0.16.3",
"@cardano-sdk/cardano-services-client": "0.16.6",
"@cardano-sdk/core": "0.23.1",
"@cardano-sdk/dapp-connector": "0.12.2",
"@cardano-sdk/input-selection": "0.12.13",
"@cardano-sdk/tx-construction": "0.17.3",
"@cardano-sdk/util": "0.14.5",
"@cardano-sdk/wallet": "0.30.0",
"@cardano-sdk/web-extension": "0.22.0",
"@emurgo/cip14-js": "~3.0.1",
"@koralabs/handles-public-api-interfaces": "^1.6.6",
"@lace/cardano": "0.1.0",
Expand Down
4 changes: 3 additions & 1 deletion apps/browser-extension-wallet/src/api/mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,9 @@ const getDetailsForAll = (): PoolDetails => ({
livePledge: BigInt('2000000000'),
saturation: Percent(0.95),
size: undefined,
stake: undefined
stake: undefined,
ros: Percent(0.69),
lastRos: Percent(0.88)
},
relays: undefined,
rewardAccount: Wallet.Cardano.RewardAccount('stake_test1uqrw9tjymlm8wrwq7jk68n6v7fs9qz8z0tkdkve26dylmfc2ux2hj'),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import RefreshIcon from '@assets/icons/refresh.component.svg';
import WarningIcon from '@assets/icons/warning.component.svg';
import styles from '@components/MainLoader/MainLoader.module.scss';
import { Loader, toast } from '@lace/common';
import { AddressesDiscoveryStatus } from '@lib/communication';
import { AddressesDiscoveryStatus } from '@lib/communication/addresses-discoverer';
import { useWalletStore } from '@stores';
import { WarningModal } from '@views/browser/components';
import React, { FC, useEffect, useState } from 'react';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { AppMode } from '@src/utils/constants';
import { MainLoader } from '@components/MainLoader';
import { CorruptedData } from './CorruptedData';
import { DataCheckDispatcher, useDataCheck } from '@hooks/useDataCheck';
import { walletRepository } from '@lib/wallet-api-ui';

const isFeatureEnabled = process.env.USE_DATA_CHECK === 'true';

Expand All @@ -21,7 +22,7 @@ export const DataCheckContainer = ({

useEffect(() => {
// Run only on mount
if (isFeatureEnabled) performDataCheck();
if (isFeatureEnabled) performDataCheck(walletRepository);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
import React from 'react';
import React, { useMemo } from 'react';
import { useWalletManager } from '@hooks';
import { useWalletStore } from '@src/stores';
import { Menu } from 'antd';
import { useTranslation } from 'react-i18next';
import styles from '../DropdownMenuOverlay.module.scss';
import { useAnalyticsContext } from '@providers';
import { PostHogAction } from '@providers/AnalyticsProvider/analyticsTracker';
import { Wallet } from '@lace/cardano';

export const LockWallet = (): React.ReactElement => {
const { t } = useTranslation();
const { lockWallet } = useWalletManager();
const { walletLock } = useWalletStore();
const { getKeyAgentType } = useWalletStore();
const analytics = useAnalyticsContext();
const isInMemoryWallet = useMemo(
() => getKeyAgentType() === Wallet.KeyManagement.KeyAgentType.InMemory,
[getKeyAgentType]
);

const handleLockWallet = () => {
analytics.sendEventToPostHog(PostHogAction.UserWalletProfileLockWalletClick);
Expand All @@ -23,7 +28,7 @@ export const LockWallet = (): React.ReactElement => {
data-testid="header-menu-lock"
onClick={handleLockWallet}
className={styles.menuItem}
disabled={!walletLock}
disabled={!isInMemoryWallet}
>
{t('browserView.topNavigationBar.links.lockWallet')}
</Menu.Item>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ export const ResetDataError = ({
buttonLabel
}: ResetDataErrorProps): React.ReactElement => {
const { deleteWallet } = useWalletManager();
const { walletManagerUi, setDeletingWallet } = useWalletStore();
const { walletManager, setDeletingWallet } = useWalletStore();
const { theme } = useTheme();
const backgroundService = useBackgroundServiceAPIContext();

const Layout = appMode === 'browser' ? WalletSetupLayout : React.Fragment;

const resetData = async () => {
if (walletManagerUi) {
if (walletManager) {
setDeletingWallet(true);
await deleteWallet();
}
Expand Down
52 changes: 22 additions & 30 deletions apps/browser-extension-wallet/src/dapp-connector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,7 @@ import { StoreProvider } from '@stores';
import '@lib/i18n';
import 'antd/dist/antd.css';
import { CurrencyStoreProvider } from '@providers/currency';
import {
DatabaseProvider,
AxiosClientProvider,
AppSettingsProvider,
CardanoWalletManagerProvider,
AnalyticsProvider
} from '@providers';
import { DatabaseProvider, AxiosClientProvider, AppSettingsProvider, AnalyticsProvider } from '@providers';
import { HashRouter } from 'react-router-dom';
import { ThemeProvider } from '@providers/ThemeProvider';
import { BackgroundServiceAPIProvider } from '@providers/BackgroundServiceAPI';
Expand All @@ -23,29 +17,27 @@ import { AddressesDiscoveryOverlay } from 'components/AddressesDiscoveryOverlay'
const App = (): React.ReactElement => (
<BackgroundServiceAPIProvider>
<AppSettingsProvider>
<CardanoWalletManagerProvider>
<DatabaseProvider>
<StoreProvider appMode={APP_MODE_POPUP}>
<AxiosClientProvider>
<CurrencyStoreProvider>
<HashRouter>
<PostHogClientProvider>
<ExperimentsProvider>
<AnalyticsProvider>
<ThemeProvider>
<AddressesDiscoveryOverlay>
<DappConnectorView />
</AddressesDiscoveryOverlay>
</ThemeProvider>
</AnalyticsProvider>
</ExperimentsProvider>
</PostHogClientProvider>
</HashRouter>
</CurrencyStoreProvider>
</AxiosClientProvider>
</StoreProvider>
</DatabaseProvider>
</CardanoWalletManagerProvider>
<DatabaseProvider>
<StoreProvider appMode={APP_MODE_POPUP}>
<AxiosClientProvider>
<CurrencyStoreProvider>
<HashRouter>
<PostHogClientProvider>
<ExperimentsProvider>
<AnalyticsProvider>
<ThemeProvider>
<AddressesDiscoveryOverlay>
<DappConnectorView />
</AddressesDiscoveryOverlay>
</ThemeProvider>
</AnalyticsProvider>
</ExperimentsProvider>
</PostHogClientProvider>
</HashRouter>
</CurrencyStoreProvider>
</AxiosClientProvider>
</StoreProvider>
</DatabaseProvider>
</AppSettingsProvider>
</BackgroundServiceAPIProvider>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,20 @@ import { sectionTitle, DAPP_VIEWS } from '../config';
import styles from './ConfirmData.module.scss';
import { useViewsFlowContext } from '@providers/ViewFlowProvider';
import { DappInfo } from '@lace/core';
import { consumeRemoteApi, exposeApi, RemoteApiPropertyType } from '@cardano-sdk/web-extension';
import { exposeApi, RemoteApiPropertyType, WalletType } from '@cardano-sdk/web-extension';
import { runtime } from 'webextension-polyfill';
import { DAPP_CHANNELS } from '@src/utils/constants';
import { UserPromptService } from '@lib/scripts/background/services/dappService';
import type { UserPromptService } from '@lib/scripts/background/services/dappService';
import { of } from 'rxjs';
import { HexBlob } from '@cardano-sdk/util';
import { DappDataService } from '@lib/scripts/types';
import { Skeleton } from 'antd';
import { useRedirection } from '@hooks';
import { dAppRoutePaths } from '@routes';
import { useWalletStore } from '@stores';
import * as HardwareLedger from '../../../../../../node_modules/@cardano-sdk/hardware-ledger/dist/cjs';
import { useAnalyticsContext } from '@providers';
import { TX_CREATION_TYPE_KEY, TxCreationType } from '@providers/AnalyticsProvider/analyticsTracker';
import { senderOrigin } from '@cardano-sdk/dapp-connector';
import { signingCoordinator } from '@lib/wallet-api-ui';

const INDENT_SPACING = 2;
const DAPP_TOAST_DURATION = 50;
Expand All @@ -40,7 +40,8 @@ const hasJsonStructure = (str: string): boolean => {

export const DappConfirmData = (): React.ReactElement => {
const {
utils: { setNextView }
utils: { setNextView },
signDataRequest: { request: req, set: setSignDataRequest }
} = useViewsFlowContext();
const { getKeyAgentType } = useWalletStore();
const { t } = useTranslation();
Expand All @@ -59,79 +60,73 @@ export const DappConfirmData = (): React.ReactElement => {
dataToSign: string;
}>();

const cancelTransaction = useCallback(() => {
exposeApi<Pick<UserPromptService, 'allowSignData'>>(
const cancelTransaction = useCallback(async () => {
await req.reject('User rejected to sign');
setTimeout(() => window.close(), DAPP_TOAST_DURATION);
}, [req]);

window.addEventListener('beforeunload', cancelTransaction);

useEffect(() => {
const subscription = signingCoordinator.signDataRequest$.subscribe((r) => {
setDappInfo({
logo: r.signContext.sender.tab.favIconUrl,
url: senderOrigin(r.signContext.sender),
name: r.signContext.sender.tab.title
});
setSignDataRequest(r);
});

const api = exposeApi<Pick<UserPromptService, 'allowSignTx'>>(
{
api$: of({
async allowSignData(): Promise<boolean> {
return Promise.reject();
async allowSignTx(): Promise<boolean> {
return Promise.resolve(true);
}
}),
baseChannel: DAPP_CHANNELS.userPrompt,
properties: { allowSignData: RemoteApiPropertyType.MethodReturningPromise }
properties: { allowSignTx: RemoteApiPropertyType.MethodReturningPromise }
},
{ logger: console, runtime }
);
setTimeout(() => window.close(), DAPP_TOAST_DURATION);
}, []);

window.addEventListener('beforeunload', cancelTransaction);
return () => {
subscription.unsubscribe();
api.shutdown();
};
}, [setSignDataRequest]);

useEffect(() => {
const dappDataApi = consumeRemoteApi<Pick<DappDataService, 'getSignDataData'>>(
{
baseChannel: DAPP_CHANNELS.dappData,
properties: {
getSignDataData: RemoteApiPropertyType.MethodReturningPromise
}
},
{ logger: console, runtime }
);

dappDataApi
.getSignDataData()
.then(({ sign: backgroundData, dappInfo: backgroundDappInfo }) => {
const dataFromHex = fromHex(backgroundData.payload);
const txDataAddress = backgroundData.addr.toString();
const jsonStructureOrHexString = {
address: txDataAddress,
dataToSign: hasJsonStructure(dataFromHex)
? JSON.stringify(JSON.parse(dataFromHex), undefined, INDENT_SPACING)
: dataFromHex
};
setDappInfo(backgroundDappInfo);
setFormattedData(jsonStructureOrHexString);
})
.catch((error) => {
console.error(error);
});
}, []);
const dataFromHex = fromHex(req.blob);
// TODO: address is currently not available in sign request,
// only the derivation path of key to sign with.
// We can probably add it to sign request, or we can match it against wallet addresses$
const txDataAddress = `${req.derivationPath.role}/${req.derivationPath.index}`;
const jsonStructureOrHexString = {
address: txDataAddress,
dataToSign: hasJsonStructure(dataFromHex)
? JSON.stringify(JSON.parse(dataFromHex), undefined, INDENT_SPACING)
: dataFromHex
};
setFormattedData(jsonStructureOrHexString);
}, [req]);

const signWithHardwareWallet = useCallback(async () => {
setIsConfirmingTx(true);
try {
HardwareLedger.LedgerKeyAgent.establishDeviceConnection(Wallet.KeyManagement.CommunicationType.Web)
.then(() => {
exposeApi<Pick<UserPromptService, 'allowSignTx'>>(
{
api$: of({
async allowSignTx(): Promise<boolean> {
return Promise.resolve(true);
}
}),
baseChannel: DAPP_CHANNELS.userPrompt,
properties: { allowSignTx: RemoteApiPropertyType.MethodReturningPromise }
},
{ logger: console, runtime }
);
})
.catch((error) => {
throw error;
});
} catch {
if (req.walletType !== WalletType.Ledger && req.walletType !== WalletType.Trezor) {
throw new Error('Invalid state: expected hw wallet');
}
await req.sign();
redirectToSignSuccess();
} catch (error) {
console.error('error', error);
cancelTransaction();
redirectToSignFailure();
}
}, [setIsConfirmingTx, redirectToSignFailure, redirectToSignSuccess]);

setIsConfirmingTx(true);
}, [setIsConfirmingTx, redirectToSignFailure, redirectToSignSuccess, cancelTransaction, req]);

const confirmationCallback = useCallback(() => {
analytics?.sendEventToPostHog(PostHogAction.SendTransactionDataReviewTransactionClick, {
Expand Down
Loading
Loading