Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4fd71ce884 | ||
|
|
0ee22e2ecb | ||
|
|
3e94fe3cc9 | ||
|
|
5977846b70 | ||
|
|
8bae4d5dd5 |
@@ -26,11 +26,7 @@ import {
|
||||
EST_TOTAL_MARGIN_TOOLTIP_TEXT,
|
||||
MARGIN_ACCOUNT_TOOLTIP_TEXT,
|
||||
} from '../../constants';
|
||||
import {
|
||||
sumFees,
|
||||
sumFeesDiscounts,
|
||||
useEstimateFees,
|
||||
} from '../../hooks/use-estimate-fees';
|
||||
import { useEstimateFees } from '../../hooks/use-estimate-fees';
|
||||
import { KeyValue } from './key-value';
|
||||
import {
|
||||
Accordion,
|
||||
@@ -44,6 +40,7 @@ import {
|
||||
import classNames from 'classnames';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import { FeesBreakdown } from '../fees-breakdown';
|
||||
import { getTotalDiscountFactor, getDiscountedFee } from '../discounts';
|
||||
|
||||
const emptyValue = '-';
|
||||
|
||||
@@ -63,48 +60,49 @@ export const DealTicketFeeDetails = ({
|
||||
const feeEstimate = useEstimateFees(order, isMarketInAuction);
|
||||
const asset = getAsset(market);
|
||||
const { decimals: assetDecimals, quantum } = asset;
|
||||
const totalFees = feeEstimate?.fees && sumFees(feeEstimate?.fees);
|
||||
const feesDiscounts =
|
||||
feeEstimate?.fees && sumFeesDiscounts(feeEstimate?.fees);
|
||||
|
||||
const totalPercentageDiscount =
|
||||
feesDiscounts &&
|
||||
totalFees &&
|
||||
feesDiscounts.total !== '0' &&
|
||||
totalFees !== '0' &&
|
||||
new BigNumber(feesDiscounts.total)
|
||||
.dividedBy(BigNumber.sum(totalFees, feesDiscounts.total))
|
||||
.times(100);
|
||||
const totalDiscountFactor = getTotalDiscountFactor(feeEstimate);
|
||||
const totalDiscountedFeeAmount =
|
||||
feeEstimate?.totalFeeAmount &&
|
||||
getDiscountedFee(
|
||||
feeEstimate.totalFeeAmount,
|
||||
feeEstimate.referralDiscountFactor,
|
||||
feeEstimate.volumeDiscountFactor
|
||||
).discountedFee;
|
||||
|
||||
return (
|
||||
<KeyValue
|
||||
label={t('Fees')}
|
||||
value={
|
||||
feeEstimate?.totalFeeAmount &&
|
||||
`~${formatValue(feeEstimate?.totalFeeAmount, assetDecimals)}`
|
||||
totalDiscountedFeeAmount &&
|
||||
`~${formatValue(totalDiscountedFeeAmount, assetDecimals)}`
|
||||
}
|
||||
formattedValue={
|
||||
<>
|
||||
{totalPercentageDiscount && (
|
||||
{totalDiscountFactor && (
|
||||
<Pill size="xxs" intent={Intent.Warning} className="mr-1">
|
||||
-{formatNumberPercentage(totalPercentageDiscount, 2)}
|
||||
-
|
||||
{formatNumberPercentage(
|
||||
new BigNumber(totalDiscountFactor).multipliedBy(100),
|
||||
2
|
||||
)}
|
||||
</Pill>
|
||||
)}
|
||||
{feeEstimate?.totalFeeAmount &&
|
||||
`~${formatValue(
|
||||
feeEstimate?.totalFeeAmount,
|
||||
assetDecimals,
|
||||
quantum
|
||||
)}`}
|
||||
{totalDiscountedFeeAmount &&
|
||||
`~${formatValue(totalDiscountedFeeAmount, assetDecimals, quantum)}`}
|
||||
</>
|
||||
}
|
||||
labelDescription={
|
||||
<>
|
||||
<span>
|
||||
<p className="mb-2">
|
||||
{t(
|
||||
`An estimate of the most you would be expected to pay in fees, in the market's settlement asset ${assetSymbol}. Fees estimated are "taker" fees and will only be payable if the order trades aggressively. Rebate equal to the maker portion will be paid to the trader if the order trades passively.`
|
||||
)}
|
||||
</span>
|
||||
</p>
|
||||
<FeesBreakdown
|
||||
totalFeeAmount={feeEstimate?.totalFeeAmount}
|
||||
referralDiscountFactor={feeEstimate?.referralDiscountFactor}
|
||||
volumeDiscountFactor={feeEstimate?.volumeDiscountFactor}
|
||||
fees={feeEstimate?.fees}
|
||||
feeFactors={market.fees.factors}
|
||||
symbol={assetSymbol}
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
import { getDiscountedFee, getTotalDiscountFactor } from './discounts';
|
||||
|
||||
describe('getDiscountedFee', () => {
|
||||
it('calculates values if volumeDiscount or referralDiscount is undefined', () => {
|
||||
expect(getDiscountedFee('100')).toEqual({
|
||||
discountedFee: '100',
|
||||
volumeDiscount: '0',
|
||||
referralDiscount: '0',
|
||||
});
|
||||
expect(getDiscountedFee('100', undefined, '0.1')).toEqual({
|
||||
discountedFee: '90',
|
||||
volumeDiscount: '10',
|
||||
referralDiscount: '0',
|
||||
});
|
||||
expect(getDiscountedFee('100', '0.1', undefined)).toEqual({
|
||||
discountedFee: '90',
|
||||
volumeDiscount: '0',
|
||||
referralDiscount: '10',
|
||||
});
|
||||
});
|
||||
|
||||
it('calculates values using volumeDiscount or referralDiscount', () => {
|
||||
expect(getDiscountedFee('', '0.1', '0.2')).toEqual({
|
||||
discountedFee: '',
|
||||
volumeDiscount: '0',
|
||||
referralDiscount: '0',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('getTotalDiscountFactor', () => {
|
||||
it('returns 0 if discounts are 0', () => {
|
||||
expect(
|
||||
getTotalDiscountFactor({
|
||||
volumeDiscountFactor: '0',
|
||||
referralDiscountFactor: '0',
|
||||
})
|
||||
).toEqual(0);
|
||||
});
|
||||
|
||||
it('returns volumeDiscountFactor if referralDiscountFactor is 0', () => {
|
||||
expect(
|
||||
getTotalDiscountFactor({
|
||||
volumeDiscountFactor: '0.1',
|
||||
referralDiscountFactor: '0',
|
||||
})
|
||||
).toEqual(0.1);
|
||||
});
|
||||
it('returns referralDiscountFactor if volumeDiscountFactor is 0', () => {
|
||||
expect(
|
||||
getTotalDiscountFactor({
|
||||
volumeDiscountFactor: '0',
|
||||
referralDiscountFactor: '0.1',
|
||||
})
|
||||
).toEqual(0.1);
|
||||
});
|
||||
|
||||
it('calculates discount using referralDiscountFactor and volumeDiscountFactor', () => {
|
||||
expect(
|
||||
getTotalDiscountFactor({
|
||||
volumeDiscountFactor: '0.2',
|
||||
referralDiscountFactor: '0.1',
|
||||
})
|
||||
).toBeCloseTo(0.28);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,54 @@
|
||||
import BigNumber from 'bignumber.js';
|
||||
|
||||
export const getDiscountedFee = (
|
||||
feeAmount: string,
|
||||
referralDiscountFactor?: string,
|
||||
volumeDiscountFactor?: string
|
||||
) => {
|
||||
if (
|
||||
((!referralDiscountFactor || referralDiscountFactor === '0') &&
|
||||
(!volumeDiscountFactor || volumeDiscountFactor === '0')) ||
|
||||
!feeAmount ||
|
||||
feeAmount === '0'
|
||||
) {
|
||||
return {
|
||||
discountedFee: feeAmount,
|
||||
volumeDiscount: '0',
|
||||
referralDiscount: '0',
|
||||
};
|
||||
}
|
||||
const referralDiscount = new BigNumber(referralDiscountFactor || '0')
|
||||
.multipliedBy(feeAmount)
|
||||
.toFixed(0, BigNumber.ROUND_FLOOR);
|
||||
const volumeDiscount = new BigNumber(volumeDiscountFactor || '0')
|
||||
.multipliedBy((BigInt(feeAmount) - BigInt(referralDiscount)).toString())
|
||||
.toFixed(0, BigNumber.ROUND_FLOOR);
|
||||
const discountedFee = (
|
||||
BigInt(feeAmount || '0') -
|
||||
BigInt(referralDiscount) -
|
||||
BigInt(volumeDiscount)
|
||||
).toString();
|
||||
return {
|
||||
referralDiscount,
|
||||
volumeDiscount,
|
||||
discountedFee,
|
||||
};
|
||||
};
|
||||
|
||||
export const getTotalDiscountFactor = (feeEstimate?: {
|
||||
volumeDiscountFactor?: string;
|
||||
referralDiscountFactor?: string;
|
||||
}) => {
|
||||
if (!feeEstimate) {
|
||||
return 0;
|
||||
}
|
||||
const volumeFactor = Number(feeEstimate?.volumeDiscountFactor) || 0;
|
||||
const referralFactor = Number(feeEstimate?.referralDiscountFactor) || 0;
|
||||
if (!volumeFactor) {
|
||||
return referralFactor;
|
||||
}
|
||||
if (!referralFactor) {
|
||||
return volumeFactor;
|
||||
}
|
||||
return 1 - (1 - volumeFactor) * (1 - referralFactor);
|
||||
};
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
} from '@vegaprotocol/utils';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import { sumFees, sumFeesDiscounts } from '../../hooks';
|
||||
import { getDiscountedFee } from '../discounts';
|
||||
|
||||
const formatValue = (
|
||||
value: string | number | null | undefined,
|
||||
@@ -24,7 +24,7 @@ const FeesBreakdownItem = ({
|
||||
decimals,
|
||||
}: {
|
||||
label: string;
|
||||
factor?: BigNumber;
|
||||
factor?: string;
|
||||
value: string;
|
||||
symbol?: string;
|
||||
decimals: number;
|
||||
@@ -43,76 +43,86 @@ const FeesBreakdownItem = ({
|
||||
);
|
||||
|
||||
export const FeesBreakdown = ({
|
||||
totalFeeAmount,
|
||||
fees,
|
||||
feeFactors,
|
||||
symbol,
|
||||
decimals,
|
||||
referralDiscountFactor,
|
||||
volumeDiscountFactor,
|
||||
}: {
|
||||
totalFeeAmount?: string;
|
||||
fees?: TradeFee;
|
||||
feeFactors?: FeeFactors;
|
||||
symbol?: string;
|
||||
decimals: number;
|
||||
referralDiscountFactor?: string;
|
||||
volumeDiscountFactor?: string;
|
||||
}) => {
|
||||
if (!fees) return null;
|
||||
const totalFees = sumFees(fees);
|
||||
const {
|
||||
total: totalDiscount,
|
||||
referral: referralDiscount,
|
||||
volume: volumeDiscount,
|
||||
} = sumFeesDiscounts(fees);
|
||||
if (totalFees === '0') return null;
|
||||
if (!fees || !totalFeeAmount || totalFeeAmount === '0') return null;
|
||||
|
||||
const { discountedFee: discountedInfrastructureFee } = getDiscountedFee(
|
||||
fees.infrastructureFee,
|
||||
referralDiscountFactor,
|
||||
volumeDiscountFactor
|
||||
);
|
||||
|
||||
const { discountedFee: discountedLiquidityFee } = getDiscountedFee(
|
||||
fees.liquidityFee,
|
||||
referralDiscountFactor,
|
||||
volumeDiscountFactor
|
||||
);
|
||||
|
||||
const { discountedFee: discountedMakerFee } = getDiscountedFee(
|
||||
fees.makerFee,
|
||||
referralDiscountFactor,
|
||||
volumeDiscountFactor
|
||||
);
|
||||
|
||||
const { volumeDiscount, referralDiscount } = getDiscountedFee(
|
||||
totalFeeAmount,
|
||||
referralDiscountFactor,
|
||||
volumeDiscountFactor
|
||||
);
|
||||
|
||||
return (
|
||||
<dl className="grid grid-cols-6">
|
||||
<FeesBreakdownItem
|
||||
label={t('Infrastructure fee')}
|
||||
factor={
|
||||
feeFactors?.infrastructureFee
|
||||
? new BigNumber(feeFactors?.infrastructureFee)
|
||||
: undefined
|
||||
}
|
||||
value={fees.infrastructureFee}
|
||||
factor={feeFactors?.infrastructureFee}
|
||||
value={discountedInfrastructureFee}
|
||||
symbol={symbol}
|
||||
decimals={decimals}
|
||||
/>
|
||||
|
||||
<FeesBreakdownItem
|
||||
label={t('Liquidity fee')}
|
||||
factor={
|
||||
feeFactors?.liquidityFee
|
||||
? new BigNumber(feeFactors?.liquidityFee)
|
||||
: undefined
|
||||
}
|
||||
value={fees.liquidityFee}
|
||||
factor={feeFactors?.liquidityFee}
|
||||
value={discountedLiquidityFee}
|
||||
symbol={symbol}
|
||||
decimals={decimals}
|
||||
/>
|
||||
|
||||
<FeesBreakdownItem
|
||||
label={t('Maker fee')}
|
||||
factor={
|
||||
feeFactors?.makerFee ? new BigNumber(feeFactors?.makerFee) : undefined
|
||||
}
|
||||
value={fees.makerFee}
|
||||
factor={feeFactors?.makerFee}
|
||||
value={discountedMakerFee}
|
||||
symbol={symbol}
|
||||
decimals={decimals}
|
||||
/>
|
||||
{volumeDiscount && volumeDiscount !== '0' && (
|
||||
{volumeDiscountFactor && volumeDiscount !== '0' && (
|
||||
<FeesBreakdownItem
|
||||
label={t('Volume discount')}
|
||||
factor={new BigNumber(volumeDiscount).dividedBy(
|
||||
BigNumber.sum(totalFees, totalDiscount)
|
||||
)}
|
||||
factor={volumeDiscountFactor}
|
||||
value={volumeDiscount}
|
||||
symbol={symbol}
|
||||
decimals={decimals}
|
||||
/>
|
||||
)}
|
||||
{referralDiscount && referralDiscount !== '0' && (
|
||||
{referralDiscountFactor && referralDiscount !== '0' && (
|
||||
<FeesBreakdownItem
|
||||
label={t('Referral discount')}
|
||||
factor={new BigNumber(referralDiscount).dividedBy(
|
||||
BigNumber.sum(totalFees, totalDiscount)
|
||||
)}
|
||||
factor={referralDiscountFactor}
|
||||
value={referralDiscount}
|
||||
symbol={symbol}
|
||||
decimals={decimals}
|
||||
@@ -120,8 +130,8 @@ export const FeesBreakdown = ({
|
||||
)}
|
||||
<FeesBreakdownItem
|
||||
label={t('Total fees')}
|
||||
factor={feeFactors ? sumFeesFactors(feeFactors) : undefined}
|
||||
value={totalFees}
|
||||
factor={feeFactors ? sumFeesFactors(feeFactors)?.toString() : undefined}
|
||||
value={totalFeeAmount}
|
||||
symbol={symbol}
|
||||
decimals={decimals}
|
||||
/>
|
||||
|
||||
@@ -31,4 +31,25 @@ query EstimateFees(
|
||||
}
|
||||
totalFeeAmount
|
||||
}
|
||||
epoch {
|
||||
id
|
||||
}
|
||||
volumeDiscountStats(partyId: $partyId, pagination: { last: 1 }) {
|
||||
edges {
|
||||
node {
|
||||
atEpoch
|
||||
discountFactor
|
||||
runningVolume
|
||||
}
|
||||
}
|
||||
}
|
||||
referralSetStats(partyId: $partyId, pagination: { last: 1 }) {
|
||||
edges {
|
||||
node {
|
||||
atEpoch
|
||||
discountFactor
|
||||
referralSetRunningNotionalTakerVolume
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+22
-1
@@ -15,7 +15,7 @@ export type EstimateFeesQueryVariables = Types.Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type EstimateFeesQuery = { __typename?: 'Query', estimateFees: { __typename?: 'FeeEstimate', totalFeeAmount: string, fees: { __typename?: 'TradeFee', makerFee: string, infrastructureFee: string, liquidityFee: string, makerFeeReferralDiscount?: string | null, makerFeeVolumeDiscount?: string | null, infrastructureFeeReferralDiscount?: string | null, infrastructureFeeVolumeDiscount?: string | null, liquidityFeeReferralDiscount?: string | null, liquidityFeeVolumeDiscount?: string | null } } };
|
||||
export type EstimateFeesQuery = { __typename?: 'Query', estimateFees: { __typename?: 'FeeEstimate', totalFeeAmount: string, fees: { __typename?: 'TradeFee', makerFee: string, infrastructureFee: string, liquidityFee: string, makerFeeReferralDiscount?: string | null, makerFeeVolumeDiscount?: string | null, infrastructureFeeReferralDiscount?: string | null, infrastructureFeeVolumeDiscount?: string | null, liquidityFeeReferralDiscount?: string | null, liquidityFeeVolumeDiscount?: string | null } }, epoch: { __typename?: 'Epoch', id: string }, volumeDiscountStats: { __typename?: 'VolumeDiscountStatsConnection', edges: Array<{ __typename?: 'VolumeDiscountStatsEdge', node: { __typename?: 'VolumeDiscountStats', atEpoch: number, discountFactor: string, runningVolume: string } } | null> }, referralSetStats: { __typename?: 'ReferralSetStatsConnection', edges: Array<{ __typename?: 'ReferralSetStatsEdge', node: { __typename?: 'ReferralSetStats', atEpoch: number, discountFactor: string, referralSetRunningNotionalTakerVolume: string } } | null> } };
|
||||
|
||||
|
||||
export const EstimateFeesDocument = gql`
|
||||
@@ -43,6 +43,27 @@ export const EstimateFeesDocument = gql`
|
||||
}
|
||||
totalFeeAmount
|
||||
}
|
||||
epoch {
|
||||
id
|
||||
}
|
||||
volumeDiscountStats(partyId: $partyId, pagination: {last: 1}) {
|
||||
edges {
|
||||
node {
|
||||
atEpoch
|
||||
discountFactor
|
||||
runningVolume
|
||||
}
|
||||
}
|
||||
}
|
||||
referralSetStats(partyId: $partyId, pagination: {last: 1}) {
|
||||
edges {
|
||||
node {
|
||||
atEpoch
|
||||
discountFactor
|
||||
referralSetRunningNotionalTakerVolume
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
|
||||
@@ -6,6 +6,15 @@ export const estimateFeesQuery = (
|
||||
override?: PartialDeep<EstimateFeesQuery>
|
||||
): EstimateFeesQuery => {
|
||||
const defaultResult: EstimateFeesQuery = {
|
||||
epoch: {
|
||||
id: '1',
|
||||
},
|
||||
referralSetStats: {
|
||||
edges: [],
|
||||
},
|
||||
volumeDiscountStats: {
|
||||
edges: [],
|
||||
},
|
||||
estimateFees: {
|
||||
__typename: 'FeeEstimate',
|
||||
totalFeeAmount: '0.0006',
|
||||
|
||||
@@ -5,6 +5,31 @@ import { Side, OrderTimeInForce, OrderType } from '@vegaprotocol/types';
|
||||
import type { EstimateFeesQuery } from './__generated__/EstimateOrder';
|
||||
|
||||
const data: EstimateFeesQuery = {
|
||||
epoch: {
|
||||
id: '2',
|
||||
},
|
||||
volumeDiscountStats: {
|
||||
edges: [
|
||||
{
|
||||
node: {
|
||||
atEpoch: 1,
|
||||
discountFactor: '0.1',
|
||||
runningVolume: '100',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
referralSetStats: {
|
||||
edges: [
|
||||
{
|
||||
node: {
|
||||
atEpoch: 1,
|
||||
discountFactor: '0.2',
|
||||
referralSetRunningNotionalTakerVolume: '100',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
estimateFees: {
|
||||
totalFeeAmount: '120',
|
||||
fees: {
|
||||
@@ -54,6 +79,8 @@ describe('useEstimateFees', () => {
|
||||
liquidityFee: '0',
|
||||
makerFee: '0',
|
||||
},
|
||||
referralDiscountFactor: '0',
|
||||
volumeDiscountFactor: '0',
|
||||
});
|
||||
expect(mockUseEstimateFeesQuery.mock.lastCall?.[0].skip).toBeTruthy();
|
||||
});
|
||||
@@ -85,6 +112,46 @@ describe('useEstimateFees', () => {
|
||||
makerFeeReferralDiscount: '5',
|
||||
makerFeeVolumeDiscount: '6',
|
||||
},
|
||||
referralDiscountFactor: '0',
|
||||
volumeDiscountFactor: '0',
|
||||
});
|
||||
});
|
||||
|
||||
it('returns 0 discounts if discount stats are not at the current epoch', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useEstimateFees(
|
||||
{
|
||||
marketId: 'marketId',
|
||||
side: Side.SIDE_BUY,
|
||||
size: '1',
|
||||
price: '1',
|
||||
timeInForce: OrderTimeInForce.TIME_IN_FORCE_FOK,
|
||||
type: OrderType.TYPE_LIMIT,
|
||||
},
|
||||
true
|
||||
)
|
||||
);
|
||||
expect(result.current?.referralDiscountFactor).toEqual('0');
|
||||
expect(result.current?.volumeDiscountFactor).toEqual('0');
|
||||
});
|
||||
|
||||
it('returns discounts', () => {
|
||||
data.epoch.id = '1';
|
||||
const { result } = renderHook(() =>
|
||||
useEstimateFees(
|
||||
{
|
||||
marketId: 'marketId',
|
||||
side: Side.SIDE_BUY,
|
||||
size: '1',
|
||||
price: '1',
|
||||
timeInForce: OrderTimeInForce.TIME_IN_FORCE_FOK,
|
||||
type: OrderType.TYPE_LIMIT,
|
||||
},
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
expect(result.current?.referralDiscountFactor).toEqual('0.2');
|
||||
expect(result.current?.volumeDiscountFactor).toEqual('0.1');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5,39 +5,22 @@ import type { EstimateFeesQuery } from './__generated__/EstimateOrder';
|
||||
import { useEstimateFeesQuery } from './__generated__/EstimateOrder';
|
||||
|
||||
const divideByTwo = (n: string) => (BigInt(n) / BigInt(2)).toString();
|
||||
export const sumFeesDiscounts = (
|
||||
fees: EstimateFeesQuery['estimateFees']['fees']
|
||||
) => {
|
||||
const volume = (
|
||||
BigInt(fees.makerFeeVolumeDiscount || '0') +
|
||||
BigInt(fees.infrastructureFeeVolumeDiscount || '0') +
|
||||
BigInt(fees.liquidityFeeVolumeDiscount || '0')
|
||||
).toString();
|
||||
const referral = (
|
||||
BigInt(fees.makerFeeReferralDiscount || '0') +
|
||||
BigInt(fees.infrastructureFeeReferralDiscount || '0') +
|
||||
BigInt(fees.liquidityFeeReferralDiscount || '0')
|
||||
).toString();
|
||||
return {
|
||||
volume,
|
||||
referral,
|
||||
total: (BigInt(volume) + BigInt(referral)).toString(),
|
||||
};
|
||||
};
|
||||
|
||||
export const sumFees = (fees: EstimateFeesQuery['estimateFees']['fees']) =>
|
||||
(
|
||||
BigInt(fees.makerFee || '0') +
|
||||
BigInt(fees.infrastructureFee || '0') +
|
||||
BigInt(fees.liquidityFee || '0')
|
||||
).toString();
|
||||
|
||||
export const useEstimateFees = (
|
||||
order?: OrderSubmissionBody['orderSubmission'],
|
||||
isMarketInAuction?: boolean
|
||||
): EstimateFeesQuery['estimateFees'] | undefined => {
|
||||
):
|
||||
| (EstimateFeesQuery['estimateFees'] & {
|
||||
referralDiscountFactor: string;
|
||||
volumeDiscountFactor: string;
|
||||
})
|
||||
| undefined => {
|
||||
const { pubKey } = useVegaWallet();
|
||||
const { data } = useEstimateFeesQuery({
|
||||
const {
|
||||
data: currentData,
|
||||
previousData,
|
||||
loading,
|
||||
} = useEstimateFeesQuery({
|
||||
variables: order && {
|
||||
marketId: order.marketId,
|
||||
partyId: pubKey || '',
|
||||
@@ -50,8 +33,21 @@ export const useEstimateFees = (
|
||||
fetchPolicy: 'no-cache',
|
||||
skip: !pubKey || !order?.size || !order?.price || order.postOnly,
|
||||
});
|
||||
const data = loading ? currentData || previousData : currentData;
|
||||
const volumeDiscountFactor =
|
||||
(data?.volumeDiscountStats.edges[0]?.node.atEpoch.toString() ===
|
||||
data?.epoch.id &&
|
||||
data?.volumeDiscountStats.edges[0]?.node.discountFactor) ||
|
||||
'0';
|
||||
const referralDiscountFactor =
|
||||
(data?.referralSetStats.edges[0]?.node.atEpoch.toString() ===
|
||||
data?.epoch.id &&
|
||||
data?.referralSetStats.edges[0]?.node.discountFactor) ||
|
||||
'0';
|
||||
if (order?.postOnly) {
|
||||
return {
|
||||
volumeDiscountFactor,
|
||||
referralDiscountFactor,
|
||||
totalFeeAmount: '0',
|
||||
fees: {
|
||||
infrastructureFee: '0',
|
||||
@@ -60,8 +56,13 @@ export const useEstimateFees = (
|
||||
},
|
||||
};
|
||||
}
|
||||
return isMarketInAuction && data?.estimateFees
|
||||
if (!data?.estimateFees) {
|
||||
return undefined;
|
||||
}
|
||||
return isMarketInAuction
|
||||
? {
|
||||
volumeDiscountFactor,
|
||||
referralDiscountFactor,
|
||||
totalFeeAmount: divideByTwo(data.estimateFees.totalFeeAmount),
|
||||
fees: {
|
||||
infrastructureFee: divideByTwo(
|
||||
@@ -91,5 +92,9 @@ export const useEstimateFees = (
|
||||
divideByTwo(data.estimateFees.fees.makerFeeVolumeDiscount),
|
||||
},
|
||||
}
|
||||
: data?.estimateFees;
|
||||
: {
|
||||
volumeDiscountFactor,
|
||||
referralDiscountFactor,
|
||||
...data.estimateFees,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -3,6 +3,7 @@ import type { Market, MarketMaybeWithDataAndCandles } from './markets-provider';
|
||||
import {
|
||||
calcTradedFactor,
|
||||
filterAndSortMarkets,
|
||||
sumFeesFactors,
|
||||
totalFeesFactorsPercentage,
|
||||
} from './market-utils';
|
||||
const { MarketState, MarketTradingMode } = Schema;
|
||||
@@ -132,3 +133,15 @@ describe('calcTradedFactor', () => {
|
||||
expect(fa > fb).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('sumFeesFactors', () => {
|
||||
it('does not result in flop errors', () => {
|
||||
expect(
|
||||
sumFeesFactors({
|
||||
makerFee: '0.1',
|
||||
infrastructureFee: '0.2',
|
||||
liquidityFee: '0.3',
|
||||
})
|
||||
).toEqual(0.6);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -50,16 +50,19 @@ export const getQuoteName = (market: Partial<Market>) => {
|
||||
};
|
||||
|
||||
export const sumFeesFactors = (fees: Market['fees']['factors']) => {
|
||||
return fees
|
||||
? new BigNumber(fees.makerFee)
|
||||
.plus(fees.liquidityFee)
|
||||
.plus(fees.infrastructureFee)
|
||||
: undefined;
|
||||
if (!fees) return;
|
||||
|
||||
return new BigNumber(fees.makerFee)
|
||||
.plus(fees.liquidityFee)
|
||||
.plus(fees.infrastructureFee)
|
||||
.toNumber();
|
||||
};
|
||||
|
||||
export const totalFeesFactorsPercentage = (fees: Market['fees']['factors']) => {
|
||||
const total = fees && sumFeesFactors(fees);
|
||||
return total ? formatNumberPercentage(total.times(100)) : undefined;
|
||||
return total
|
||||
? formatNumberPercentage(new BigNumber(total).times(100))
|
||||
: undefined;
|
||||
};
|
||||
|
||||
export const filterAndSortMarkets = (markets: MarketMaybeWithData[]) => {
|
||||
|
||||
Reference in New Issue
Block a user