Use source loader for email sprite icons
[ProtonMail-WebClient.git] / packages / wallet / store / slices / networkFees.ts
blob85f0bd5ffe8f704ed0f8c029c97cd4d13ec9e79d
1 import { createSlice } from '@reduxjs/toolkit';
3 import { type ModelState, getInitialModelState } from '@proton/account';
4 import { WasmBlockchainClient } from '@proton/andromeda';
5 import { createAsyncModelThunk, handleAsyncModel, previousSelector } from '@proton/redux-utilities';
7 import type { WalletThunkArguments } from '../thunk';
9 const name = 'network_fees' as const;
11 type BlockTarget = number;
12 type FeeRate = number;
14 export type FeeRateByBlockTarget = [BlockTarget, FeeRate];
16 export interface FeeSettings {
17     feesMap: Map<string, number>;
18     feesList: FeeRateByBlockTarget[];
19     minimumBroadcastFee: number;
20     minimumIncrementalFee: number;
23 export interface NetworkFeesState {
24     [name]: ModelState<FeeSettings>;
27 type SliceState = NetworkFeesState[typeof name];
28 type Model = NonNullable<SliceState['value']>;
30 export const selectNetworkFees = (state: NetworkFeesState) => state[name];
32 export const DEFAULT_FEE_SETTINGS = {
33     feesMap: new Map(),
34     feesList: [],
35     minimumBroadcastFee: 1.0,
36     minimumIncrementalFee: 1.0,
38 const initialState = getInitialModelState<Model>(DEFAULT_FEE_SETTINGS);
40 const feesMapToList = (feesMap: Map<string, number>) => {
41     return (
42         [...feesMap.entries()]
43             // We need to round feeRate because bdk expects a BigInt
44             .map(([block, feeRate]): FeeRateByBlockTarget => [Number(block), Math.round(feeRate)])
45             .filter(([block]) => Number.isFinite(block))
46             .sort(([a], [b]) => a - b)
47     );
50 const modelThunk = createAsyncModelThunk<Model, NetworkFeesState, WalletThunkArguments>(`${name}/fetch`, {
51     miss: async ({ extraArgument }) => {
52         const isMinFeeEnabled = await extraArgument.unleashClient.isEnabled('WalletMinFee');
54         const blockchainClient = new WasmBlockchainClient(extraArgument.walletApi);
56         const feesMap = await blockchainClient.getFeesEstimation();
57         const { MinimumBroadcastFee: minimumBroadcastFee, MinimumIncrementalFee: minimumIncrementalFee } =
58             isMinFeeEnabled
59                 ? await blockchainClient.getMininumFees()
60                 : { MinimumBroadcastFee: 1.0, MinimumIncrementalFee: 1.0 };
62         const feesList = feesMapToList(feesMap);
64         return { feesMap, feesList, minimumBroadcastFee, minimumIncrementalFee };
65     },
66     previous: previousSelector(selectNetworkFees),
67 });
69 const slice = createSlice({
70     name,
71     initialState,
72     reducers: {},
73     extraReducers: (builder) => {
74         handleAsyncModel(builder, modelThunk);
75     },
76 });
78 export const networkFeesReducer = { [name]: slice.reducer };
79 export const networkFeesThunk = modelThunk.thunk;