Skip to content

Commit 9d98dd5

Browse files
authored
Peter/fix dex volumes query (#1608)
* chore: update monetary to latest 0.7.3 * fix(pools): update hook to return data on per pool basis
1 parent d8af913 commit 9d98dd5

File tree

5 files changed

+126
-181
lines changed

5 files changed

+126
-181
lines changed

src/components/PoolsTable/PoolsTable.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ const PoolsTable = ({ variant, pools, onRowAction, title }: PoolsTableProps): JS
4141
const { t } = useTranslation();
4242
const prices = useGetPrices();
4343
const titleId = useId();
44-
const { getDexTotalVolumeUSD } = useGetDexVolumes(DateRangeVolume.D7);
44+
const { getDexVolumeByPool } = useGetDexVolumes(DateRangeVolume.D7);
4545

4646
const isAccountPools = variant === 'account-pools';
4747

@@ -82,7 +82,7 @@ const PoolsTable = ({ variant, pools, onRowAction, title }: PoolsTableProps): JS
8282
// TODO: revert alignItems prop when `sevenDayVolume` is adressed
8383
const totalLiquidity = <Cell label={formatUSD(totalLiquidityUSD, { compact: true })} alignItems='flex-start' />;
8484

85-
const total7DayVolumeUSD = getDexTotalVolumeUSD(pooledCurrencies.map((pooled) => pooled.currency.ticker));
85+
const total7DayVolumeUSD = getDexVolumeByPool(data);
8686
const total7DayVolumeLabel = formatUSD(total7DayVolumeUSD, { compact: true });
8787
const sevenDayVolume = (
8888
<Cell label={total7DayVolumeLabel} alignItems={isAccountPools ? 'flex-start' : 'flex-end'} />
@@ -107,7 +107,7 @@ const PoolsTable = ({ variant, pools, onRowAction, title }: PoolsTableProps): JS
107107
accountLiquidity
108108
};
109109
}),
110-
[getDexTotalVolumeUSD, isAccountPools, onRowAction, pools, prices, variant]
110+
[getDexVolumeByPool, isAccountPools, onRowAction, pools, prices, variant]
111111
);
112112

113113
return (
Lines changed: 57 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
1-
import { CurrencyExt, newMonetaryAmount } from '@interlay/interbtc-api';
1+
import { CurrencyExt, LiquidityPool, newMonetaryAmount } from '@interlay/interbtc-api';
22
import { MonetaryAmount } from '@interlay/monetary-js';
3+
import Big from 'big.js';
34
import { subDays } from 'date-fns';
4-
import { gql, GraphQLClient } from 'graphql-request';
5+
import { GraphQLClient } from 'graphql-request';
56
import { useCallback } from 'react';
67
import { useErrorHandler } from 'react-error-boundary';
78
import { useQuery, UseQueryResult } from 'react-query';
89

9-
import { convertMonetaryAmountToValueInUSD } from '@/common/utils/utils';
10+
import { convertMonetaryAmountToBigUSD } from '@/common/utils/utils';
1011
import { SQUID_URL } from '@/constants';
12+
import { getPoolDataId, getPoolsVolumesQuery } from '@/services/queries/pools';
13+
import { CurrencySquidFormat } from '@/types/currency';
1114
import { REFETCH_INTERVAL } from '@/utils/constants/api';
1215
import { getTokenPrice } from '@/utils/helpers/prices';
1316

@@ -21,133 +24,78 @@ const graphQLClient = new GraphQLClient(SQUID_URL, {
2124
}
2225
});
2326

24-
// TODO: add this to a dedicated schemas folder
25-
const AMOUNT_FIELDS = gql`
26-
fragment AmountFields on PooledAmount {
27-
amount
28-
amountHuman
29-
token {
30-
... on NativeToken {
31-
__typename
32-
token
33-
}
34-
... on ForeignAsset {
35-
__typename
36-
asset
37-
}
38-
... on StableLpToken {
39-
__typename
40-
poolId
41-
}
42-
}
43-
}
44-
`;
45-
46-
// TODO: add this to a dedicated schemas folder
47-
const GET_DEX_VOLUMES = gql`
48-
${AMOUNT_FIELDS}
49-
query poolVolumes($start: DateTime, $end: DateTime) {
50-
startVolumes: cumulativeDexTradingVolumes(
51-
limit: 1
52-
orderBy: tillTimestamp_ASC
53-
where: { tillTimestamp_gte: $start }
54-
) {
55-
tillTimestamp
56-
amounts {
57-
...AmountFields
58-
}
59-
}
60-
endVolumes: cumulativeDexTradingVolumes(
61-
limit: 1
62-
orderBy: tillTimestamp_DESC
63-
where: { tillTimestamp_lte: $end, tillTimestamp_gte: $start }
64-
) {
65-
tillTimestamp
66-
amounts {
67-
...AmountFields
68-
}
69-
}
70-
}
71-
`;
72-
7327
enum DateRangeVolume {
7428
H24,
7529
D7
7630
}
7731

78-
type DexCurrencyVolume = {
79-
amount: MonetaryAmount<CurrencyExt>;
80-
usd: number;
32+
type DexVolumesData = Record<string, Big>;
33+
34+
type UseGetCurrenciesResult = UseQueryResult<DexVolumesData> & {
35+
getDexVolumeByPool: (pool: LiquidityPool | undefined) => number;
8136
};
8237

83-
type DexVolumesData = Record<string, DexCurrencyVolume>;
38+
const getVolumes = (
39+
volumes: any,
40+
dataId: string,
41+
getCurrencyFromSquidFormat: (currencySquid: CurrencySquidFormat) => CurrencyExt
42+
): Array<MonetaryAmount<CurrencyExt>> => {
43+
const startVolumes = volumes[`${dataId}__startVolumes`];
44+
const endVolumes = volumes[`${dataId}__endVolumes`];
45+
if (startVolumes.length === 0 || endVolumes.length === 0) {
46+
return [];
47+
}
8448

85-
type UseGetCurrenciesResult = UseQueryResult<DexVolumesData> & {
86-
getDexVolumeByTicker: (ticker: string) => DexCurrencyVolume | undefined;
87-
getDexTotalVolumeUSD: (tickers: string[]) => number;
49+
return startVolumes[0].amounts.map((amount: any, index: number) => {
50+
const currency = getCurrencyFromSquidFormat(amount.token);
51+
const endAmount = Big(endVolumes[0].amounts[index].amount);
52+
const amountDelta = endAmount.sub(Big(amount.amount));
53+
54+
return newMonetaryAmount(amountDelta, currency);
55+
});
8856
};
8957

9058
const useGetDexVolumes = (range: DateRangeVolume): UseGetCurrenciesResult => {
91-
const { getCurrencyFromTicker, getForeignCurrencyFromId } = useGetCurrencies(true);
92-
const { getStableLiquidityPoolById } = useGetLiquidityPools();
59+
const { getCurrencyFromSquidFormat } = useGetCurrencies(true);
60+
const { data: pools } = useGetLiquidityPools();
9361
const prices = useGetPrices();
9462

9563
const getDexVolumes = useCallback(
9664
async (range: DateRangeVolume): Promise<DexVolumesData> => {
65+
if (!pools) {
66+
return {};
67+
}
68+
9769
const start = subDays(new Date(), range === DateRangeVolume.D7 ? 7 : 1);
9870
const end = new Date();
9971

100-
const data = await graphQLClient.request(GET_DEX_VOLUMES, { start, end });
72+
const query = getPoolsVolumesQuery(pools);
10173

102-
if (!data.startVolumes.length || !data.endVolumes.length) {
103-
return {};
104-
}
74+
const data = await graphQLClient.request(query, { start, end });
10575

106-
const [startVolumes] = data.startVolumes;
107-
const [endVolumes] = data.endVolumes;
108-
109-
return startVolumes.amounts.reduce((acc: DexVolumesData, item: any) => {
110-
let currency: CurrencyExt;
111-
let endVolume;
112-
113-
switch (item.token.__typename) {
114-
case 'NativeToken': {
115-
const { token } = item.token;
116-
currency = getCurrencyFromTicker(token);
117-
endVolume = endVolumes.amounts.find((endAmount: any) => endAmount.token.token === token);
118-
break;
119-
}
120-
case 'ForeignAsset': {
121-
const { asset } = item.token;
122-
currency = getForeignCurrencyFromId(asset);
123-
endVolume = endVolumes.amounts.find((endAmount: any) => endAmount.token.asset === asset);
124-
break;
125-
}
126-
case 'StableLpToken': {
127-
const { poolId } = item.token;
128-
currency = getStableLiquidityPoolById(poolId).lpToken;
129-
endVolume = endVolumes.amounts.find((endAmount: any) => endAmount.token.poolId === poolId);
130-
break;
131-
}
132-
default:
133-
return acc;
134-
}
76+
const result = pools.map((pool: LiquidityPool) => {
77+
const dataId = getPoolDataId(pool);
13578

136-
if (!endVolume) {
137-
return acc;
79+
const volumes = getVolumes(data, dataId, getCurrencyFromSquidFormat);
80+
if (volumes.length === 0) {
81+
return { [dataId]: Big(0) };
13882
}
13983

140-
const volumeAmount = newMonetaryAmount(endVolume.amount - item.amount, currency);
84+
const totalVolumeInUSD = volumes
85+
.reduce(
86+
(total, amount) =>
87+
total.add(convertMonetaryAmountToBigUSD(amount, getTokenPrice(prices, amount.currency.ticker)?.usd)),
88+
Big(0)
89+
)
90+
// Divide by amount of pooled currencies.
91+
.div(pool.pooledCurrencies.length);
14192

142-
const volume: DexCurrencyVolume = {
143-
amount: volumeAmount,
144-
usd: convertMonetaryAmountToValueInUSD(volumeAmount, getTokenPrice(prices, currency.ticker)?.usd) || 0
145-
};
93+
return { [dataId]: totalVolumeInUSD };
94+
});
14695

147-
return { ...acc, [currency.ticker]: volume };
148-
}, {});
96+
return result.reduce((result, pool) => ({ ...result, ...pool }));
14997
},
150-
[getCurrencyFromTicker, getForeignCurrencyFromId, getStableLiquidityPoolById, prices]
98+
[pools, getCurrencyFromSquidFormat, prices]
15199
);
152100

153101
const queryResult = useQuery({
@@ -156,16 +104,15 @@ const useGetDexVolumes = (range: DateRangeVolume): UseGetCurrenciesResult => {
156104
refetchInterval: REFETCH_INTERVAL.MINUTE
157105
});
158106

159-
const getDexVolumeByTicker = useCallback((ticker: string) => queryResult.data?.[ticker], [queryResult.data]);
160-
161-
const getDexTotalVolumeUSD = useCallback(
162-
(tickers: string[]) => tickers.reduce((sum, ticker) => sum + (getDexVolumeByTicker(ticker)?.usd || 0), 0),
163-
[getDexVolumeByTicker]
107+
const getDexVolumeByPool = useCallback(
108+
(pool: LiquidityPool | undefined) =>
109+
queryResult.data && pool ? queryResult.data[getPoolDataId(pool)].toNumber() : 0,
110+
[queryResult]
164111
);
165112

166113
useErrorHandler(queryResult.error);
167114

168-
return { ...queryResult, getDexTotalVolumeUSD, getDexVolumeByTicker };
115+
return { ...queryResult, getDexVolumeByPool };
169116
};
170117

171118
export { DateRangeVolume, useGetDexVolumes };

src/hooks/api/use-get-pools-trading-apr.tsx

Lines changed: 3 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,13 @@
1-
import {
2-
CurrencyExt,
3-
isForeignAsset,
4-
LiquidityPool,
5-
newMonetaryAmount,
6-
PooledCurrencies,
7-
TickerToData
8-
} from '@interlay/interbtc-api';
1+
import { CurrencyExt, LiquidityPool, newMonetaryAmount, TickerToData } from '@interlay/interbtc-api';
92
import { MonetaryAmount } from '@interlay/monetary-js';
103
import Big from 'big.js';
11-
import { gql, GraphQLClient } from 'graphql-request';
4+
import { GraphQLClient } from 'graphql-request';
125
import { useCallback } from 'react';
136
import { useQuery } from 'react-query';
147

158
import { convertMonetaryAmountToBigUSD } from '@/common/utils/utils';
169
import { SQUID_URL } from '@/constants';
10+
import { getPoolDataId, getPoolsVolumesQuery } from '@/services/queries/pools';
1711
import { CurrencySquidFormat } from '@/types/currency';
1812
import { MILLISECONDS_PER_DAY } from '@/utils/constants/date-time';
1913
import { calculateTotalLiquidityUSD } from '@/utils/helpers/pool';
@@ -29,63 +23,6 @@ const graphQLClient = new GraphQLClient(SQUID_URL, {
2923
}
3024
});
3125

32-
const getPoolDataId = (pool: LiquidityPool): string =>
33-
`${pool.type}_${pool.pooledCurrencies.map(({ currency }) => currency.ticker).join('_')}`;
34-
35-
const getPooledCurrenciesCondition = (pooledCurrencies: PooledCurrencies) =>
36-
`${pooledCurrencies
37-
.map(({ currency }) => {
38-
const currencyId = isForeignAsset(currency) ? currency.foreignAsset.id.toString() : currency.ticker;
39-
return `AND: {poolId_contains: "${currencyId}"`;
40-
})
41-
.join()}${pooledCurrencies.map((_) => '}').join('')}`;
42-
43-
const getPoolsVolumesQuery = (pools: Array<LiquidityPool>): string => gql`
44-
fragment AmountFields on PooledAmount {
45-
amount
46-
amountHuman
47-
token {
48-
... on NativeToken {
49-
__typename
50-
token
51-
}
52-
... on ForeignAsset {
53-
__typename
54-
asset
55-
}
56-
... on StableLpToken {
57-
__typename
58-
poolId
59-
}
60-
}
61-
}
62-
63-
fragment PoolVolumeFields on CumulativeDexTradingVolumePerPool {
64-
poolId
65-
poolType
66-
tillTimestamp
67-
amounts {
68-
...AmountFields
69-
}
70-
}
71-
72-
query poolVolumes($start: DateTime, $end: DateTime) {
73-
${pools
74-
.map((pool: LiquidityPool) => {
75-
const poolDataId = getPoolDataId(pool);
76-
const pooledCurrenciesCondition = getPooledCurrenciesCondition(pool.pooledCurrencies);
77-
return `${poolDataId}__startVolumes: cumulativeDexTradingVolumePerPools(limit: 1, orderBy: tillTimestamp_ASC, where: {tillTimestamp_gte: $start, ${pooledCurrenciesCondition}}) {
78-
...PoolVolumeFields
79-
}
80-
${poolDataId}__endVolumes:cumulativeDexTradingVolumePerPools(limit: 1, orderBy: tillTimestamp_DESC, where: {tillTimestamp_lte: $end, ${pooledCurrenciesCondition}}) {
81-
...PoolVolumeFields
82-
}
83-
`;
84-
})
85-
.join('\n')}
86-
}
87-
`;
88-
8926
const getYearlyVolume = (
9027
volumes: any,
9128
dataId: string,

src/pages/Swap/components/SwapLiquidity/SwapLiquidity.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ type SwapLiquidityProps = Props & InheritAttrs;
1818

1919
const SwapLiquidity = ({ input, output, liquidityPool, ...props }: SwapLiquidityProps): JSX.Element | null => {
2020
const prices = useGetPrices();
21-
const { getDexTotalVolumeUSD } = useGetDexVolumes(DateRangeVolume.H24);
21+
const { getDexVolumeByPool } = useGetDexVolumes(DateRangeVolume.H24);
2222

23-
const h24Volume = getDexTotalVolumeUSD([input.ticker, output.ticker]);
23+
const h24Volume = getDexVolumeByPool(liquidityPool);
2424
const h24VolumeLabel = formatUSD(h24Volume, { compact: true });
2525

2626
const liquidity = liquidityPool && calculateTotalLiquidityUSD(liquidityPool.pooledCurrencies, prices);

0 commit comments

Comments
 (0)