vega-frontend-monorepo/apps/console-lite/src/app/hooks/use-calculate-slippage.ts
macqbat d7fee66d89
feat: [console-lite] - calculate slippage (price impact) (#1173)
* feat: [console-lite] - calculate slippage (price impact)

* feat: [console-lite] - move slippage from estimates to deal-ticket-size

* feat: [console-lite] - slippage - add a bunch of unit tests

* feat: [console-lite] - slippage -

* feat: [console-lite] - slippage - fix some faillings, add enum instead text entry

* feat: [console-lite] - slippage - adjust tooltip info text

* feat: [console-lite] - slippage - fix failling cache

* feat: [console-lite] - slippage - resolve conflicts after rebase

* feat: [console-lite] - slippage - fixes after review

* feat: [console-lite] - slippage - fixes after review

* feat: [console-lite] - slippage - add memo back to the hook

* feat: [console-lite] - slippage - add back order book model outside hook

* feat: [console-lite] - slippage - adjust some int test

* feat: [console-lite] - slippage - adjust some int test

Co-authored-by: maciek <maciek@vegaprotocol.io>
2022-08-31 15:23:01 +02:00

64 lines
2.0 KiB
TypeScript

import { useMemo } from 'react';
import { Side } from '@vegaprotocol/types';
import { useOrderBookData } from '@vegaprotocol/market-depth';
import type { Order } from '@vegaprotocol/orders';
import { BigNumber } from 'bignumber.js';
import { formatNumber, toBigNum } from '@vegaprotocol/react-helpers';
interface Props {
marketId: string;
order: Order;
}
const useCalculateSlippage = ({ marketId, order }: Props) => {
const variables = useMemo(() => ({ marketId }), [marketId]);
const { data } = useOrderBookData({
variables,
resolution: 1,
throttleMilliseconds: 10000,
});
const volPriceArr =
data?.depth[order.side === Side.SIDE_BUY ? 'sell' : 'buy'] || [];
if (volPriceArr.length) {
const decimals = data?.decimalPlaces ?? 0;
const positionDecimals = data?.positionDecimalPlaces ?? 0;
const bestPrice = toBigNum(volPriceArr[0].price, decimals);
const { size } = order;
let descSize = new BigNumber(size);
let i = 0;
const volPricePairs: Array<[BigNumber, BigNumber]> = [];
while (!descSize.isZero() && i < volPriceArr.length) {
const price = toBigNum(volPriceArr[i].price, decimals);
const amount = BigNumber.min(
descSize,
toBigNum(volPriceArr[i].volume, positionDecimals)
);
volPricePairs.push([price, amount]);
descSize = BigNumber.max(0, descSize.minus(amount));
i++;
}
if (volPricePairs.length) {
const volWeightAvPricePair = volPricePairs.reduce(
(agg, item) => {
agg[0] = agg[0].plus(item[0].multipliedBy(item[1]));
agg[1] = agg[1].plus(item[1]);
return agg;
},
[new BigNumber(0), new BigNumber(0)]
);
const volWeightAvPrice = volWeightAvPricePair[0].dividedBy(
volWeightAvPricePair[1]
);
const slippage = volWeightAvPrice
.minus(bestPrice)
.absoluteValue()
.dividedBy(bestPrice)
.multipliedBy(100);
return formatNumber(slippage, 2);
}
}
return null;
};
export default useCalculateSlippage;