vega-frontend-monorepo/apps/trading/components/fees-container/utils.ts

110 lines
3.1 KiB
TypeScript
Raw Normal View History

2023-10-25 21:59:30 +00:00
import { getUserLocale } from '@vegaprotocol/utils';
import BigNumber from 'bignumber.js';
/**
* Convert a number between 0-1 into a percentage value between 0-100
*
* Not using formatNumberPercentage from vegaprotocol/utils as this
* returns a string and includes extra 0s on the end. We need these
* values in aggrid as numbers for sorting
*/
export const formatPercentage = (num: number) => {
const pct = new BigNumber(num).times(100);
const dps = pct.decimalPlaces();
const formatter = new Intl.NumberFormat(getUserLocale(), {
2023-11-09 15:50:50 +00:00
// set to 0 in order to remove the "trailing zeroes" for numbers such as:
// 0.123456789 -non-zero-min-> 12.3456800% -zero-min-> 12.34568%
minimumFractionDigits: 0,
2023-10-25 21:59:30 +00:00
maximumFractionDigits: dps || 0,
});
return formatter.format(parseFloat(pct.toFixed(5)));
};
/**
* Return the index of the benefit tier for volume discounts. A user
* only needs to fulfill a minimum volume requirement for the tier
*/
export const getVolumeTier = (
volume: number,
tiers: Array<{
minimumRunningNotionalTakerVolume: string;
}>
) => {
return tiers.findIndex((tier, i) => {
const nextTier = tiers[i + 1];
const validVolume =
volume >= Number(tier.minimumRunningNotionalTakerVolume);
if (nextTier) {
return (
validVolume &&
volume < Number(nextTier.minimumRunningNotionalTakerVolume)
);
}
return validVolume;
});
};
/**
* Return the index of the benefit tiers for referrals. A user must
* fulfill both the minimum epochs in the referral set, and the set
* must reach the combined total volume
*/
export const getReferralBenefitTier = (
epochsInSet: number,
volume: number,
tiers: Array<{
minimumRunningNotionalTakerVolume: string;
minimumEpochs: number;
}>
) => {
const indexByEpoch = tiers.findIndex((tier, i) => {
const nextTier = tiers[i + 1];
const validEpochs = epochsInSet >= tier.minimumEpochs;
if (nextTier) {
return validEpochs && epochsInSet < nextTier.minimumEpochs;
}
return validEpochs;
});
const indexByVolume = tiers.findIndex((tier, i) => {
const nextTier = tiers[i + 1];
const validVolume =
volume >= Number(tier.minimumRunningNotionalTakerVolume);
if (nextTier) {
return (
validVolume &&
volume < Number(nextTier.minimumRunningNotionalTakerVolume)
);
}
return validVolume;
});
return Math.min(indexByEpoch, indexByVolume);
};
/**
* Given a set of fees and a set of discounts return
* the adjusted fee factor
*
* Formula for calculating the adjusted fees
* total_discount_factor = 1 - (1 - volumeDiscount) * (1 - referralDiscount)
2023-10-25 21:59:30 +00:00
*/
export const getAdjustedFee = (fees: BigNumber[], discounts: BigNumber[]) => {
const totalFee = fees.reduce((sum, f) => sum.plus(f), new BigNumber(0));
const combinedFactors = discounts.reduce((acc, d) => {
return acc.times(new BigNumber(1).minus(d));
}, new BigNumber(1));
const totalFactor = new BigNumber(1).minus(combinedFactors);
2023-11-09 15:50:50 +00:00
return totalFee
.times(new BigNumber(1).minus(BigNumber.max(0, totalFactor)))
.toNumber();
2023-10-25 21:59:30 +00:00
};