1 import { createAction } from '@reduxjs/toolkit';
2 import compact from 'lodash/compact';
4 import type { WasmApiWalletAccount, WasmApiWalletKey, WasmApiWalletSettings } from '@proton/andromeda';
5 import { EVENT_ACTIONS } from '@proton/shared/lib/constants';
6 import { type CreateEventItemUpdate } from '@proton/shared/lib/helpers/updateCollection';
7 import { type DecryptedKey } from '@proton/shared/lib/interfaces';
9 import type { IWasmApiWalletData } from '../types';
10 import type { WalletAccountEvent, WalletEvent, WalletEventLoop } from '../types/eventLoop';
11 import { replaceAt } from './array';
12 import { decryptWallet } from './wallet';
14 export const eventLoopEvent = createAction<WalletEventLoop>('server event');
16 const findCreatedWalletKeyFromEvents = (walletID: string, events: WalletEventLoop) => {
17 return events.WalletKeys?.find(
18 (walletKeyAction): walletKeyAction is CreateEventItemUpdate<WasmApiWalletKey, 'WalletKey'> =>
19 walletKeyAction.Action === EVENT_ACTIONS.CREATE && walletKeyAction.WalletKey.WalletID === walletID
23 const findCreatedWalletSettingsFromEvents = (walletID: string, events: WalletEventLoop) => {
24 return events.WalletSettings?.find(
25 (walletKeyAction): walletKeyAction is CreateEventItemUpdate<WasmApiWalletSettings, 'WalletSettings'> =>
26 walletKeyAction.Action === EVENT_ACTIONS.CREATE && walletKeyAction.WalletSettings.WalletID === walletID
30 const findCreatedWalletAccountsFromEvents = (walletID: string, events: WalletEventLoop) => {
32 events.WalletAccounts?.filter(
35 ): walletAccountsAction is CreateEventItemUpdate<WasmApiWalletAccount, 'WalletAccount'> =>
36 walletAccountsAction.Action === EVENT_ACTIONS.CREATE &&
37 walletAccountsAction.WalletAccount.WalletID === walletID
38 ).map((walletAccountsAction) => walletAccountsAction.WalletAccount) ?? []
42 export const stateFromWalletEvent = (
43 walletEvent: WalletEvent,
44 eventLoop: WalletEventLoop,
45 currentApiWalletsData: IWasmApiWalletData[],
46 userKeys: DecryptedKey[]
47 ): Promise<IWasmApiWalletData[]> => {
48 switch (walletEvent.Action) {
49 case EVENT_ACTIONS.CREATE:
51 if (currentApiWalletsData.some((data) => data.Wallet.ID === walletEvent.ID)) {
52 return currentApiWalletsData;
55 // WalletKey and WalletSettings should be create at the same time
56 const walletKey = findCreatedWalletKeyFromEvents(walletEvent.ID, eventLoop);
57 const walletSettings = findCreatedWalletSettingsFromEvents(walletEvent.ID, eventLoop);
58 const walletAccounts = findCreatedWalletAccountsFromEvents(walletEvent.ID, eventLoop);
60 const apiWalletData = {
61 Wallet: walletEvent.Wallet,
63 WalletSettings: walletSettings,
64 WalletAccounts: walletAccounts,
67 const wallet = await decryptWallet({
72 return compact([...currentApiWalletsData, wallet]);
74 case EVENT_ACTIONS.UPDATE:
76 const index = currentApiWalletsData.findIndex((wallet) => wallet.Wallet.ID === walletEvent.ID);
78 const apiWalletData = {
79 ...currentApiWalletsData[index],
80 Wallet: { ...currentApiWalletsData[index].Wallet, ...walletEvent.Wallet },
83 const wallet = await decryptWallet({
88 if (index && index > -1) {
89 return compact(replaceAt(currentApiWalletsData, index, wallet));
92 return compact(currentApiWalletsData);
94 case EVENT_ACTIONS.DELETE:
95 return Promise.resolve(
96 currentApiWalletsData.filter((walletData) => walletData.Wallet.ID != walletEvent.ID)
99 return Promise.resolve(currentApiWalletsData);
103 export const stateFromWalletAccountEvent = (
104 walletAccountEvent: WalletAccountEvent,
105 currentWallets: IWasmApiWalletData[],
106 userKeys: DecryptedKey[]
107 ): Promise<IWasmApiWalletData[]> => {
108 switch (walletAccountEvent.Action) {
109 case EVENT_ACTIONS.CREATE:
110 return (async () => {
111 const index = currentWallets.findIndex(
112 (wallet) => wallet.Wallet.ID === walletAccountEvent.WalletAccount.WalletID
115 const apiWalletData = {
116 ...currentWallets[index],
117 WalletAccounts: [...currentWallets[index].WalletAccounts, walletAccountEvent.WalletAccount],
120 const wallet = await decryptWallet({
125 if (index && index > -1) {
126 replaceAt(currentWallets, index, wallet);
129 return Promise.resolve(currentWallets);
131 case EVENT_ACTIONS.UPDATE:
132 return (async () => {
133 const walletIndex = currentWallets.findIndex(
134 (wallet) => wallet.Wallet.ID === walletAccountEvent.WalletAccount.WalletID
137 const walletAtIndex = currentWallets[walletIndex];
140 const accountIndex = walletAtIndex.WalletAccounts.findIndex(
141 (walletAccount) => walletAccount.ID === walletAccountEvent.ID
144 const apiWalletData = {
146 WalletAccounts: replaceAt(walletAtIndex.WalletAccounts, accountIndex, {
147 ...walletAtIndex.WalletAccounts[accountIndex],
148 ...walletAccountEvent.WalletAccount,
152 const wallet = await decryptWallet({
157 if (accountIndex > -1) {
158 return compact(replaceAt(currentWallets, walletIndex, wallet));
162 return Promise.resolve(currentWallets);
164 case EVENT_ACTIONS.DELETE:
165 return Promise.resolve(
166 currentWallets.map(({ WalletAccounts, ...rest }) => ({
168 WalletAccounts: WalletAccounts.filter(
169 (walletAccount) => walletAccount.ID !== walletAccountEvent.ID