Skip to content

Commit

Permalink
Merge pull request #321 from Apegurus/develop
Browse files Browse the repository at this point in the history
fix: Remove liquidity filter
  • Loading branch information
0xroll authored Nov 14, 2024
2 parents d8fe785 + 047c63d commit 8c3386c
Show file tree
Hide file tree
Showing 5 changed files with 403 additions and 219 deletions.
2 changes: 2 additions & 0 deletions adapters/lynex/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,13 @@
"decimal.js-light": "^2.5.1",
"fast-csv": "^5.0.1",
"jsbi": "^4.3.0",
"lodash": "^4.17.21",
"tiny-invariant": "^1.3.1",
"toformat": "^2.0.0",
"viem": "^2.8.13"
},
"devDependencies": {
"@types/lodash": "^4.17.13",
"@types/node": "^20.11.17",
"typescript": "^5.3.3"
}
Expand Down
86 changes: 30 additions & 56 deletions adapters/lynex/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import fs from "fs";
import { write } from "fast-csv";
import csv from "csv-parser";
import { getTimestampAtBlock, getUserAddresses } from "./sdk/subgraphDetails";
import {
LYNX_ADDRESS,
fetchUserPools,
fetchUserVotes,
} from "./sdk/lensDetails";
getGauges,
getTimestampAtBlock,
getUserAddresses,
} from "./sdk/subgraphDetails";
import { LYNX_ADDRESS, fetchPools, fetchVeLynx } from "./sdk/lensDetails";
import BigNumber from "bignumber.js";
import { BlockData, OutputSchemaRow } from "./sdk/types";
import {
Expand Down Expand Up @@ -80,64 +80,38 @@ export const getUserStakedTVLByBlock = async ({
blockTimestamp,
}: BlockData): Promise<OutputSchemaRow[]> => {
const result: OutputSchemaRow[] = [];
const [userAddresses] = await Promise.all([getUserAddresses(blockNumber)]);
const [userAddresses, allGauges] = await Promise.all([
getUserAddresses(blockNumber),
getGauges(blockNumber),
]);
console.log(`Block: ${blockNumber}`);
console.log("UserAddresses: ", userAddresses.length);
console.log("Gauges: ", allGauges.length);

const pools = await fetchPools(BigInt(blockNumber), allGauges);

const tokenBalanceMap = {} as {
[userAddress: string]: { [tokenAddress: string]: BigNumber };
};

let userPoolFetch = [];
let userVotesFetch = [];

const batchSize = 100;
let position = 0;
let userFetchResult: any = [];
let userVotesResult: any = [];
let userVotesResult = await fetchVeLynx(BigInt(blockNumber));

for (const user of userAddresses) {
userPoolFetch.push(
fetchUserPools(BigInt(blockNumber), user.id, user.pools)
);
userVotesFetch.push(fetchUserVotes(BigInt(blockNumber), user.id));
if (position % batchSize === 0) {
userFetchResult = [
...userFetchResult,
...(await Promise.all(userPoolFetch)),
];
userPoolFetch = [];
userVotesResult = [
...userVotesResult,
...(await Promise.all(userVotesFetch)),
];
userVotesFetch = [];
console.timeEnd("Batch");
const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms))
await delay(60000)
}
position++;
}

userVotesResult = [
...userVotesResult,
...(await Promise.all(userVotesFetch)),
];

userFetchResult = [...userFetchResult, ...(await Promise.all(userPoolFetch))];

for (const userFetchedPools of userFetchResult) {
for (const userPool of userFetchedPools) {
const user_address = userPool.result.userAddress.toLowerCase();
const totalLPBalance = userPool.result.account_gauge_balance;
for (const userPool of user.liquidityPositions) {
const currentPool = pools[userPool.gauge.pool.toLowerCase()]
? pools[userPool.gauge.pool.toLowerCase()][0]
: undefined;
if (currentPool) {
const user_address = user.id.toLowerCase();
const totalLPBalance = BigInt(userPool.amount);
const total0 =
(totalLPBalance * userPool.result.reserve0) /
userPool.result.total_supply;
(totalLPBalance * BigInt(currentPool.reserve0)) /
BigInt(currentPool.total_supply);
const total1 =
(totalLPBalance * userPool.result.reserve1) /
userPool.result.total_supply;
const token0Address = userPool.result.token0.toLowerCase();
const token1Address = userPool.result.token1.toLowerCase();
(totalLPBalance * BigInt(currentPool.reserve1)) /
BigInt(currentPool.total_supply);
const token0Address = currentPool.token0.toLowerCase();
const token1Address = currentPool.token1.toLowerCase();

// Aggregate tokens
tokenBalanceMap[user_address] = tokenBalanceMap[user_address] ?? {};
Expand All @@ -148,18 +122,18 @@ export const getUserStakedTVLByBlock = async ({
tokenBalanceMap[user_address][token1Address] = BigNumber(
tokenBalanceMap[user_address][token1Address] ?? 0
).plus(total1.toString());
}
}
}

for (const userFecthedVotes of userVotesResult) {
for (const userVote of userFecthedVotes) {
for (const userVote of userVotesResult) {
if (!userVote.result?.userAddress) continue;
const user_address = userVote.result.userAddress.toLowerCase();
const token0Address = LYNX_ADDRESS.toLowerCase();
tokenBalanceMap[user_address] = tokenBalanceMap[user_address] ?? {};
tokenBalanceMap[user_address][token0Address] = BigNumber(
tokenBalanceMap[user_address][token0Address] ?? 0
).plus(userVote.result.amount?.toString() ?? '0');
}
).plus(userVote.result.amount?.toString() ?? "0");
}

Object.entries(tokenBalanceMap).forEach(([user_address, balances]) => {
Expand Down
116 changes: 116 additions & 0 deletions adapters/lynex/src/sdk/lensDetails.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import {
import { client, PROBLEM_POOLS } from "./config";
import lensABI from "./abis/PairAPIABI.json";
import veLYNXAbi from "./abis/veLYNX.json";
import { Gauge } from "./subgraphDetails";
import { chunk, flatten, groupBy } from 'lodash';

export const LENS_ADDRESS = "0x6c84329CC8c37376eb32db50a17F3bFc917c3665"; // PairAPI
export const VE_LYNX_ADDRESS = "0x8d95f56b0bac46e8ac1d3a3f12fb1e5bc39b4c0c"; // veLYNX
Expand Down Expand Up @@ -53,6 +55,10 @@ export interface LensResponseWithBlock {
result: LensResponse;
}

export interface PoolsLensResponseWithBlock {
[key: string]: LensResponse[];
}

export interface VoteRequest {
userAddress: string;
amount: bigint;
Expand Down Expand Up @@ -94,6 +100,41 @@ export const fetchUserPools = async (
}) as LensResponseWithBlock[];
};

export const fetchPools = async (
blockNumber: bigint,
allGauges: Gauge[],
): Promise<PoolsLensResponseWithBlock> => {
const publicClient = client;
const validPools = allGauges.filter(
(gauge) =>
PROBLEM_POOLS[gauge.pool] === undefined ||
PROBLEM_POOLS[gauge.pool] > blockNumber,
);

const calls = validPools.map((gauge: Gauge) => {
return {
address: LENS_ADDRESS,
name: 'getPair',
params: [gauge.pool, '0x0000000000000000000000000000000000000000'],
};
});

const res = await multicall(
publicClient,
lensABI as Abi,
calls,
blockNumber,
);

const mapped = res.map((r: any) => {
return { ...r.result, pair_address: r.result.pair_address.toLowerCase() };
});

const grouped = groupBy(mapped, 'pair_address');

return grouped;
};

export const fetchUserVotes = async (
blockNumber: bigint,
userAddress: string
Expand Down Expand Up @@ -152,6 +193,81 @@ export const fetchUserVotes = async (
}) as VoteResponse[];
};

export const fetchVeLynx = async (
blockNumber: bigint,
): Promise<VoteResponse[]> => {
const publicClient = client;

const totalNftIdsCall = await multicall(
publicClient,
veLYNXAbi as Abi,
[
{
address: VE_LYNX_ADDRESS,
name: "totalNftsMinted",
},
],
blockNumber
);

const totalNftIds = parseInt(totalNftIdsCall[0].result as string)

const calls = [];
for (let i = 2; i <= totalNftIds; i++) {
calls.push({
address: VE_LYNX_ADDRESS,
name: "ownerOf",
params: [i],
});
}

const addressCalls = await multicallChunk(
publicClient,
veLYNXAbi as Abi,
calls,
blockNumber,
3000
);

const detailsCall = addressCalls.map((call, i) => {
return {
address: VE_LYNX_ADDRESS,
name: "lockDetails",
params: [i + 2],
};
});

const res = (await multicallChunk(
publicClient,
veLYNXAbi as Abi,
detailsCall,
blockNumber,
3000
)) as any;
const result = res.map((r: any, i: number) => {
return { result: { ...r.result, userAddress: addressCalls[i].result } };
}) as VoteResponse[];
return result
};

async function multicallChunk(
publicClient: PublicClient,
abi: Abi,
calls: any[],
blockNumber: bigint,
size = 100
) {
const chunked = chunk(calls, size);
const callsPromises = [];
for (let i = 0; i < chunked.length; i++) {
callsPromises.push(
multicall(publicClient, abi, chunked[i], blockNumber),
);
}
const res = await Promise.all(callsPromises);
return flatten(res);
}

function multicall(
publicClient: PublicClient,
abi: Abi,
Expand Down
Loading

0 comments on commit 8c3386c

Please sign in to comment.