1 import { c } from 'ttag';
3 import { type WasmApiWallet, type WasmApiWalletAccount } from '@proton/andromeda';
4 import { type DecryptedKey } from '@proton/shared/lib/interfaces';
6 import { type IWasmApiWalletData } from '../types';
7 import { decryptMnemonicWithUserKey, decryptWalletData, decryptWalletKey } from './crypto';
8 import { getPassphraseLocalStorageKey } from './localStorage';
10 export const buildMapFromWallets = (wallets: IWasmApiWalletData[] = []) => {
11 return wallets.reduce(
16 accounts: wallet.WalletAccounts.reduce(
17 (acc, walletAccount) => ({ ...acc, [walletAccount.ID]: walletAccount }),
26 export const getDefaultWalletName = (imported: boolean, wallets: IWasmApiWalletData[], index = 0): string => {
27 const indexStr = index ? ` ${index}` : '';
30 ? c('wallet_signup_2024:Wallet setup').t`My imported wallet${indexStr}`
31 : c('wallet_signup_2024:Wallet setup').t`My wallet${indexStr}`;
33 if (wallets.some((wallet) => wallet.Wallet.Name === name)) {
34 return getDefaultWalletName(imported, wallets, index + 1);
40 export const getDefaultWalletAccountName = (walletAccounts: WasmApiWalletAccount[], index = 2): string => {
41 const indexStr = index.toString();
42 const label = c('wallet_signup_2024:Wallet setup').t`Account ${indexStr}`;
44 if (walletAccounts.some((account) => account.Label === label)) {
45 return getDefaultWalletAccountName(walletAccounts, index + 1);
51 export const toWalletAccountSelectorOptions = (wallets: IWasmApiWalletData[]) =>
52 wallets?.map((wallet) => [wallet.Wallet, wallet.WalletAccounts] as [WasmApiWallet, WasmApiWalletAccount[]]) ?? [];
54 export const decryptWalletAccount = async ({
58 walletAccount: WasmApiWalletAccount;
61 const [decryptedLabel] = await decryptWalletData([walletAccount.Label], walletKey);
65 ...(decryptedLabel && { Label: decryptedLabel }),
69 export const decryptWallet = async ({
73 apiWalletData: IWasmApiWalletData;
74 userKeys: DecryptedKey[];
76 // A wallet normally cannot be created without a wallet key
77 if (!apiWalletData.WalletKey || !apiWalletData.WalletSettings) {
81 const { Wallet, WalletKey, WalletSettings, WalletAccounts } = apiWalletData;
84 const decryptedWalletKey = await decryptWalletKey(WalletKey.WalletKey, WalletKey.WalletKeySignature, userKeys);
86 const encryptedPassphrase = Wallet.Fingerprint
87 ? localStorage.getItem(getPassphraseLocalStorageKey(Wallet.Fingerprint))
90 // Backward compatibility with mnemonic encrypted with user key in addition to the wallet key
91 const encryptedMnemonic = Wallet.Legacy
92 ? await decryptMnemonicWithUserKey(Wallet.Mnemonic, userKeys)
94 const [decryptedMnemonic, decryptedWalletName, decryptedPublickey, decryptedPassphrase] =
95 await decryptWalletData(
96 [encryptedMnemonic, Wallet.Name, Wallet.PublicKey, encryptedPassphrase],
100 const decryptedWallet = {
102 ...(decryptedWalletName && { Name: decryptedWalletName }),
103 ...(decryptedMnemonic && { Mnemonic: decryptedMnemonic }),
104 ...(decryptedPublickey && { PublicKey: decryptedPublickey }),
105 ...(decryptedPassphrase && { Passphrase: decryptedPassphrase }),
108 const decryptedAccounts = await Promise.all(
109 WalletAccounts.map((account) =>
110 decryptWalletAccount({ walletAccount: account, walletKey: decryptedWalletKey })
114 const data: IWasmApiWalletData = {
115 Wallet: decryptedWallet,
116 WalletAccounts: decryptedAccounts,
117 WalletKey: { ...WalletKey, DecryptedKey: decryptedWalletKey },
118 WalletSettings: WalletSettings,
123 const data: IWasmApiWalletData = {
128 IsNotDecryptable: true,