Skip to content

Commit c4e37e6

Browse files
feat: adding a getSendAmountFee function (#107)
* added getsendamountfee to wallet core, needed for updating fees in extension and mobile * added return statement to return sendFees * remove unnecessary comment * fix PR comments, reversed to previous string amount type * fix: new push to change title
1 parent d98ad5a commit c4e37e6

File tree

3 files changed

+148
-92
lines changed

3 files changed

+148
-92
lines changed

src/store/getters.ts

Lines changed: 94 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Client } from '@chainify/client';
2-
import { Nullable } from '@chainify/types';
2+
import { FeeDetails, Nullable } from '@chainify/types';
33
import { Asset, assets as cryptoassets, AssetTypes, ChainId, unitToCurrency } from '@liquality/cryptoassets';
44
import BN, { BigNumber } from 'bignumber.js';
55
import { mapValues, orderBy, uniq } from 'lodash';
@@ -201,6 +201,12 @@ export default {
201201
return account;
202202
};
203203
},
204+
assetFees(...context: GetterContext) {
205+
const { state } = rootGetterContext(context);
206+
return (asset: AssetType): FeeDetails | undefined => {
207+
return state.fees?.[state.activeNetwork]?.[state.activeWalletId]?.[asset]
208+
}
209+
},
204210
accountsWithBalance(...context: GetterContext): Account[] {
205211
const { getters } = rootGetterContext(context);
206212
const { accountsData } = getters;
@@ -226,101 +232,102 @@ export default {
226232
const { accounts, activeNetwork, activeWalletId, enabledChains } = state;
227233
const { accountFiatBalance, assetFiatBalance, assetMarketCap } = getters;
228234

235+
229236
const _accounts = accounts[activeWalletId]?.[activeNetwork]
230237
? accounts[activeWalletId]![activeNetwork].filter(
231-
(account) =>
232-
account.assets &&
233-
account.enabled &&
234-
account.assets.length > 0 &&
235-
enabledChains[activeWalletId]?.[activeNetwork]?.includes(account.chain)
236-
)
237-
.map((account) => {
238-
/*
239-
Calculate fiat balances and asset balances
240-
Sort and group assets by dollar value / token amount / market cap
241-
*/
242-
const totalFiatBalance = accountFiatBalance(activeWalletId, activeNetwork, account.id);
243-
const assetsWithFiat: AssetInfo[] = [];
244-
const assetsWithMarketCap: AssetInfo[] = [];
245-
const assetsWithTokenBalance: AssetInfo[] = [];
246-
let assetsMarketCap: CurrenciesInfo = {} as any;
247-
let hasFiat = false;
248-
let hasTokenBalance = false;
249-
let nativeAssetMarketCap = new BN(0);
250-
251-
const fiatBalances = Object.entries(account.balances).reduce((accum, [asset, balance]) => {
252-
const fiat = assetFiatBalance(asset, new BN(balance));
253-
const marketCap = assetMarketCap(asset);
254-
const tokenBalance = account.balances[asset];
255-
let type = AssetTypes.erc20;
256-
let matchingAsset;
257-
258-
if (cryptoassets[asset]) {
259-
type = cryptoassets[asset].type;
260-
matchingAsset = cryptoassets[asset].matchingAsset;
238+
(account) =>
239+
account.assets &&
240+
account.enabled &&
241+
account.assets.length > 0 &&
242+
enabledChains[activeWalletId]?.[activeNetwork]?.includes(account.chain)
243+
)
244+
.map((account) => {
245+
/*
246+
Calculate fiat balances and asset balances
247+
Sort and group assets by dollar value / token amount / market cap
248+
*/
249+
const totalFiatBalance = accountFiatBalance(activeWalletId, activeNetwork, account.id);
250+
const assetsWithFiat: AssetInfo[] = [];
251+
const assetsWithMarketCap: AssetInfo[] = [];
252+
const assetsWithTokenBalance: AssetInfo[] = [];
253+
let assetsMarketCap: CurrenciesInfo = {} as any;
254+
let hasFiat = false;
255+
let hasTokenBalance = false;
256+
let nativeAssetMarketCap = new BN(0);
257+
258+
const fiatBalances = Object.entries(account.balances).reduce((accum, [asset, balance]) => {
259+
const fiat = assetFiatBalance(asset, new BN(balance));
260+
const marketCap = assetMarketCap(asset);
261+
const tokenBalance = account.balances[asset];
262+
let type = AssetTypes.erc20;
263+
let matchingAsset;
264+
265+
if (cryptoassets[asset]) {
266+
type = cryptoassets[asset].type;
267+
matchingAsset = cryptoassets[asset].matchingAsset;
268+
}
269+
270+
if (fiat) {
271+
hasFiat = true;
272+
assetsWithFiat.push({ asset, type, amount: fiat });
273+
} else if (marketCap) {
274+
if (type === AssetTypes.native && !matchingAsset) {
275+
nativeAssetMarketCap = marketCap;
261276
}
262277

263-
if (fiat) {
264-
hasFiat = true;
265-
assetsWithFiat.push({ asset, type, amount: fiat });
266-
} else if (marketCap) {
267-
if (type === AssetTypes.native && !matchingAsset) {
268-
nativeAssetMarketCap = marketCap;
269-
}
270-
271-
assetsWithMarketCap.push({ asset, type, amount: marketCap || new BN(0) });
272-
} else {
273-
if (!hasTokenBalance) {
274-
hasTokenBalance = new BN(tokenBalance).gt(0);
275-
}
276-
277-
assetsWithTokenBalance.push({ asset, type, amount: new BN(tokenBalance) });
278+
assetsWithMarketCap.push({ asset, type, amount: marketCap || new BN(0) });
279+
} else {
280+
if (!hasTokenBalance) {
281+
hasTokenBalance = new BN(tokenBalance).gt(0);
278282
}
279283

280-
assetsMarketCap = {
281-
...assetsMarketCap,
282-
[asset]: marketCap || new BN(0),
283-
};
284-
285-
return {
286-
...accum,
287-
[asset]: fiat,
288-
};
289-
}, {});
290-
291-
const sortedAssetsByFiat = orderBy(assetsWithFiat, 'amount', 'desc');
292-
const sortedAssetsByMarketCap = orderBy(assetsWithMarketCap, 'amount', 'desc');
293-
const sortedAssetsByTokenBalance = orderBy(assetsWithTokenBalance, 'amount', 'desc');
294-
295-
const orderedAssets = orderAssets(
296-
hasFiat,
297-
hasTokenBalance,
298-
sortedAssetsByFiat,
299-
sortedAssetsByMarketCap,
300-
sortedAssetsByTokenBalance
301-
);
284+
assetsWithTokenBalance.push({ asset, type, amount: new BN(tokenBalance) });
285+
}
286+
287+
assetsMarketCap = {
288+
...assetsMarketCap,
289+
[asset]: marketCap || new BN(0),
290+
};
302291

303292
return {
304-
...account,
305-
assets: orderedAssets.length ? orderedAssets : account.assets,
306-
nativeAssetMarketCap,
307-
assetsMarketCap,
308-
fiatBalances,
309-
totalFiatBalance,
293+
...accum,
294+
[asset]: fiat,
310295
};
311-
})
312-
.sort(orderChains)
313-
.reduce((acc: { [key: string]: Account[] }, account) => {
314-
/*
315-
Group sorted assets by chain / multiaccount ordering
316-
*/
317-
const { chain } = account;
318-
319-
acc[chain] = acc[chain] ?? [];
320-
acc[chain].push(account);
321-
322-
return acc;
323-
}, {})
296+
}, {});
297+
298+
const sortedAssetsByFiat = orderBy(assetsWithFiat, 'amount', 'desc');
299+
const sortedAssetsByMarketCap = orderBy(assetsWithMarketCap, 'amount', 'desc');
300+
const sortedAssetsByTokenBalance = orderBy(assetsWithTokenBalance, 'amount', 'desc');
301+
302+
const orderedAssets = orderAssets(
303+
hasFiat,
304+
hasTokenBalance,
305+
sortedAssetsByFiat,
306+
sortedAssetsByMarketCap,
307+
sortedAssetsByTokenBalance
308+
);
309+
310+
return {
311+
...account,
312+
assets: orderedAssets.length ? orderedAssets : account.assets,
313+
nativeAssetMarketCap,
314+
assetsMarketCap,
315+
fiatBalances,
316+
totalFiatBalance,
317+
};
318+
})
319+
.sort(orderChains)
320+
.reduce((acc: { [key: string]: Account[] }, account) => {
321+
/*
322+
Group sorted assets by chain / multiaccount ordering
323+
*/
324+
const { chain } = account;
325+
326+
acc[chain] = acc[chain] ?? [];
327+
acc[chain].push(account);
328+
329+
return acc;
330+
}, {})
324331
: [];
325332
return Object.values(_accounts).flat();
326333
},

src/utils/asset.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,10 @@ export const getNativeAsset = (asset: Asset) => {
155155
};
156156

157157
export const getFeeAsset = (asset: Asset) => {
158-
return cryptoassets[asset]?.feeAsset;
158+
if (!cryptoassets[asset]) {
159+
throw new Error('Asset does not exist')
160+
}
161+
return cryptoassets[asset].feeAsset;
159162
};
160163

161164
export const getAssetColorStyle = (asset: Asset) => {

src/utils/fees.ts

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1-
import { ChainId, unitToCurrency } from '@liquality/cryptoassets';
1+
import { BitcoinBaseWalletProvider, BitcoinEsploraApiProvider } from '@chainify/bitcoin';
2+
import { Client } from '@chainify/client';
3+
import { FeeDetails } from '@chainify/types';
4+
import { ChainId, currencyToUnit, unitToCurrency } from '@liquality/cryptoassets';
25
import BN from 'bignumber.js';
3-
import { Asset } from '../store/types';
4-
import { getNativeAsset, isERC20, isEthereumChain } from './asset';
6+
import store from '../store';
7+
import { AccountId, Asset } from '../store/types';
8+
import { getFeeAsset, getNativeAsset, isERC20, isEthereumChain } from './asset';
59
import cryptoassets from './cryptoassets';
610

711
type FeeUnits = { [asset: Asset]: number };
@@ -42,4 +46,46 @@ function isEIP1559Fees(chain: ChainId) {
4246
return chain === ChainId.Ethereum || chain === ChainId.Polygon || chain === ChainId.Avalanche;
4347
}
4448

45-
export { FEE_OPTIONS, getSendFee, getTxFee, getFeeLabel, isEIP1559Fees };
49+
50+
async function getSendAmountFee(accountId: AccountId, asset: Asset, amount?: BN) {
51+
const getMax = amount === undefined
52+
const sendFees: {
53+
[speed in keyof FeeDetails]: BN
54+
} = { slow: new BN(0), average: new BN(0), fast: new BN(0), }
55+
56+
const assetFees = store.getters.assetFees(asset);
57+
const feeAsset = getFeeAsset(asset) || getNativeAsset(asset)
58+
if (assetFees) {
59+
for (const [speed, fee] of Object.entries(assetFees)) {
60+
const feePrice = fee.fee.maxPriorityFeePerGas + fee.fee.suggestedBaseFeePerGas || fee.fee
61+
sendFees[speed as keyof FeeDetails] = getSendFee(feeAsset, feePrice)
62+
}
63+
if (asset === 'BTC') {
64+
const client = store.getters.client({
65+
network: store.state.activeNetwork,
66+
walletId: store.state.activeWalletId,
67+
asset: asset,
68+
accountId: accountId
69+
}) as Client<
70+
BitcoinEsploraApiProvider,
71+
BitcoinBaseWalletProvider
72+
>;
73+
const feePerBytes = Object.values(assetFees).map((fee) => fee.fee)
74+
const value = getMax ? undefined : currencyToUnit(cryptoassets[asset], amount)
75+
try {
76+
const txs = feePerBytes.map((fee) => ({ value, fee }))
77+
78+
const totalFees = await client.wallet.getTotalFees(txs, getMax)
79+
for (const [speed, fee] of Object.entries(assetFees)) {
80+
const totalFee = unitToCurrency(cryptoassets[asset], totalFees[fee.fee])
81+
sendFees[speed as keyof FeeDetails] = totalFee
82+
}
83+
} catch (e) {
84+
console.error(e)
85+
}
86+
}
87+
return sendFees
88+
}
89+
}
90+
91+
export { FEE_OPTIONS, getSendFee, getTxFee, getFeeLabel, isEIP1559Fees, getSendAmountFee };

0 commit comments

Comments
 (0)