Skip to content

Commit fbd4356

Browse files
committed
fix: ambient pool data
1 parent 4d5ec2e commit fbd4356

3 files changed

Lines changed: 130 additions & 115 deletions

File tree

src/cronjobs/dex/pools/ambient-pool-tasks.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ export const updateAmbientPool = async (pool: PoolExtended) => {
3636
dailyQuoteVolume: prettyNumber(bignumber(daily.quoteVolume)),
3737
// mark as just processed to avoid reprocessing
3838
processedAt: new Date(),
39+
extra: {
40+
...pool.extra,
41+
stats,
42+
},
3943
})
4044
.where(eq(poolsTable.id, pool.id));
4145

src/database/schema/pools.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export type PoolExtra = {
1717
type?: number;
1818
version?: number | null;
1919
smartToken?: string;
20+
stats?: unknown;
2021
};
2122

2223
export const poolsTable = pgTable(

src/loader/userPositionsLoader.ts

Lines changed: 125 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,9 @@ import { ethers } from 'ethers';
33
import { bignumber } from 'mathjs';
44

55
import { Chain } from './networks/chain-config';
6-
import { getErc20Balance } from './token';
76

8-
import { SdexQuery } from '~/artifacts/abis/types';
7+
import { ERC20__factory, SdexQuery } from '~/artifacts/abis/types';
98
import {
10-
aggregatePositions,
119
filterPositions,
1210
netCumulativeLiquidity,
1311
parseAmbientTokensResult,
@@ -16,6 +14,7 @@ import {
1614
weightedAverageDuration,
1715
} from '~/utils/aggregationUtils';
1816
import { calculateAPR } from '~/utils/aprCalculation';
17+
import { logger } from '~/utils/logger';
1918

2019
export enum PositionType {
2120
ambient = 'ambient',
@@ -35,118 +34,16 @@ export async function getUserPositions(
3534
const concentratedPositions = filterPositions(liquidityChanges, poolIdx, base, quote, PositionType.concentrated);
3635
const ambientPositions = filterPositions(liquidityChanges, poolIdx, base, quote, PositionType.ambient);
3736

38-
if (!ambientPositions.length || ambientPositions[0].liq === '0') {
39-
// If there are no ambient positions, try checking for LP tokens...
40-
const lpTokenAddress = await queryContract.queryPoolLpTokenAddress(base, quote, poolIdx);
41-
const lpTokenBalance = await getErc20Balance(rpc, lpTokenAddress, user).then((balance) => balance.toString());
42-
43-
if (bignumber(lpTokenBalance).gt(0)) {
44-
ambientPositions.push({
45-
id: '',
46-
changeType: 'mint',
47-
transactionHash: '',
48-
callIndex: 0,
49-
user,
50-
pool: {
51-
base,
52-
quote,
53-
poolIdx: poolIdx.toString(),
54-
},
55-
block: '',
56-
time: dayjs().unix().toString(),
57-
positionType: PositionType.ambient,
58-
liqChange: lpTokenBalance,
59-
resetRewards: '',
60-
timeFirstMint: '',
61-
bidTick: 0,
62-
askTick: 0,
63-
isBid: false,
64-
liq: lpTokenBalance,
65-
baseFlow: '0',
66-
quoteFlow: '0',
67-
pivotTime: null,
68-
aprDuration: '0',
69-
aprPostLiq: '0',
70-
aprContributedLiq: '0',
71-
aprEst: '0',
72-
lpTokenAddress,
73-
lpTokenBalance,
74-
});
75-
}
76-
}
77-
78-
if (concentratedPositions.length === 0 && ambientPositions.length === 0) {
79-
return [];
80-
}
81-
82-
let ambientPositionResults = [];
83-
if (ambientPositions.length > 0) {
84-
const ambientMints = ambientPositions.shift();
85-
86-
const ambientMulticallData = [
87-
{
88-
target: queryContract.getAddress(),
89-
callData: queryContract.interface.encodeFunctionData('queryAmbientTokens', [user, base, quote, poolIdx]),
90-
},
91-
{
92-
target: queryContract.getAddress(),
93-
callData: queryContract.interface.encodeFunctionData('queryPoolLpTokenAddress', [base, quote, poolIdx]),
94-
},
95-
];
96-
97-
const ambientMulticallResults = await chain.multicall.tryAggregate.staticCall(true, ambientMulticallData);
98-
99-
async function parseAmbientCallResults() {
100-
const ambientTokensResult = ambientMulticallResults[0];
101-
const lpTokenAddressResult = ambientMulticallResults[1];
102-
103-
if (ambientTokensResult.success && lpTokenAddressResult.success) {
104-
const ambientTokens = parseAmbientTokensResult(
105-
queryContract.interface.decodeFunctionResult('queryAmbientTokens', ambientTokensResult.returnData),
106-
);
107-
const lpTokenAddress = queryContract.interface.decodeFunctionResult(
108-
'queryPoolLpTokenAddress',
109-
lpTokenAddressResult.returnData,
110-
)[0];
111-
112-
const lpTokenBalance = await getErc20Balance(rpc, lpTokenAddress, user).then((balance) => balance.toString());
113-
114-
const ambientLiq = bignumber(ambientTokens.liq).plus(bignumber(lpTokenBalance)).toFixed(0);
115-
116-
return [
117-
{
118-
base: base,
119-
quote: quote,
120-
poolIdx: ambientMints.pool.poolIdx,
121-
ambientLiq,
122-
time: ambientMints.time,
123-
transactionHash: ambientMints.transactionHash,
124-
concLiq: '0',
125-
rewardLiq: '0',
126-
baseQty: ambientTokens.baseQty,
127-
quoteQty: ambientTokens.quoteQty,
128-
aggregatedLiquidity: ambientMints.liq,
129-
aggregatedBaseFlow: ambientMints.baseFlow,
130-
aggregatedQuoteFlow: ambientMints.quoteFlow,
131-
positionType: ambientMints.positionType,
132-
bidTick: ambientMints.bidTick,
133-
askTick: ambientMints.askTick,
134-
aprDuration: '0',
135-
aprPostLiq: '0',
136-
aprContributedLiq: '0',
137-
aprEst: '0',
138-
lpTokenAddress,
139-
lpTokenBalance,
140-
},
141-
];
142-
}
143-
return [];
144-
}
145-
146-
ambientPositionResults = await parseAmbientCallResults();
147-
}
148-
149-
const aggregatedAmbientPosition = aggregatePositions(ambientPositionResults);
37+
const aggregatedAmbientPosition = await tryAmbientPosition(
38+
queryContract,
39+
rpc,
40+
user,
41+
base,
42+
quote,
43+
poolIdx,
44+
ambientPositions,
45+
chain,
46+
);
15047

15148
// Group concentrated positions by (base, quote, poolIdx, bidTick, askTick)
15249
const groupedConcentratedPositions: { [key: string]: LiquidityChanges[] } = concentratedPositions.reduce(
@@ -249,3 +146,116 @@ export async function getUserPositions(
249146

250147
return result;
251148
}
149+
150+
async function tryAmbientPosition(
151+
queryContract: SdexQuery,
152+
rpc: ethers.JsonRpcProvider,
153+
user: string,
154+
base: string,
155+
quote: string,
156+
poolIdx: number,
157+
liquidityChanges: LiquidityChangesResponse['liquidityChanges'],
158+
chain: Chain,
159+
) {
160+
const lpTokenAddress = await queryContract.queryPoolLpTokenAddress(base, quote, poolIdx);
161+
const tokenContract = ERC20__factory.connect(lpTokenAddress, rpc);
162+
163+
const multicallData = [
164+
{
165+
target: queryContract.getAddress(),
166+
callData: queryContract.interface.encodeFunctionData('queryAmbientTokens', [user, base, quote, poolIdx]),
167+
},
168+
{
169+
target: queryContract.getAddress(),
170+
callData: queryContract.interface.encodeFunctionData('queryAmbientTokens', [
171+
lpTokenAddress,
172+
base,
173+
quote,
174+
poolIdx,
175+
]),
176+
},
177+
{
178+
target: queryContract.getAddress(),
179+
callData: queryContract.interface.encodeFunctionData('queryAmbientPosition', [
180+
lpTokenAddress,
181+
base,
182+
quote,
183+
poolIdx,
184+
]),
185+
},
186+
{
187+
target: tokenContract.getAddress(),
188+
callData: tokenContract.interface.encodeFunctionData('balanceOf', [user]),
189+
},
190+
{
191+
target: tokenContract.getAddress(),
192+
callData: tokenContract.interface.encodeFunctionData('totalSupply'),
193+
},
194+
];
195+
196+
const results = await chain.multicall.tryAggregate.staticCall(true, multicallData);
197+
198+
const userAmbientTokens = parseAmbientTokensResult(
199+
queryContract.interface.decodeFunctionResult('queryAmbientTokens', results[0].returnData),
200+
);
201+
const lpAmbientTokens = parseAmbientTokensResult(
202+
queryContract.interface.decodeFunctionResult('queryAmbientTokens', results[1].returnData),
203+
);
204+
const ambientPosition = queryContract.interface.decodeFunctionResult('queryAmbientPosition', results[2].returnData);
205+
const lpTokenBalance = tokenContract.interface.decodeFunctionResult('balanceOf', results[3].returnData)[0].toString();
206+
const lpTokenTotalSupply = tokenContract.interface
207+
.decodeFunctionResult('totalSupply', results[4].returnData)[0]
208+
.toString();
209+
210+
logger.info(
211+
{
212+
userAmbientTokens,
213+
lpAmbientTokens,
214+
lpTokenBalance,
215+
lpTokenTotalSupply,
216+
lpTokenAddress,
217+
ambientPosition,
218+
},
219+
`Fetched ambient position data for user ${user} on pool ${base}-${quote}#${poolIdx}`,
220+
);
221+
222+
const ratio = bignumber(lpTokenBalance).dividedBy(bignumber(lpTokenTotalSupply) || 1);
223+
const ambientLiq = bignumber(userAmbientTokens.liq).plus(bignumber(lpAmbientTokens.liq).mul(ratio)).toFixed(0);
224+
const baseQty = bignumber(userAmbientTokens.baseQty).plus(bignumber(lpAmbientTokens.baseQty).mul(ratio)).toFixed(0);
225+
const quoteQty = bignumber(userAmbientTokens.quoteQty)
226+
.plus(bignumber(lpAmbientTokens.quoteQty).mul(ratio))
227+
.toFixed(0);
228+
229+
if (bignumber(ambientLiq).gt(0)) {
230+
const item = liquidityChanges.shift();
231+
232+
return [
233+
{
234+
base: base,
235+
quote: quote,
236+
poolIdx: poolIdx.toString(),
237+
ambientLiq,
238+
time: item ? item.time : dayjs().unix().toString(),
239+
transactionHash: item ? item.transactionHash : '',
240+
concLiq: '0',
241+
rewardLiq: '0',
242+
baseQty: baseQty,
243+
quoteQty: quoteQty,
244+
aggregatedLiquidity: ambientLiq,
245+
aggregatedBaseFlow: '0',
246+
aggregatedQuoteFlow: '0',
247+
positionType: PositionType.ambient,
248+
bidTick: 0,
249+
askTick: 0,
250+
aprDuration: '0',
251+
aprPostLiq: '0',
252+
aprContributedLiq: '0',
253+
aprEst: '0',
254+
lpTokenAddress,
255+
lpTokenBalance,
256+
},
257+
];
258+
}
259+
260+
return [];
261+
}

0 commit comments

Comments
 (0)