Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(pools): speed up cmd by only querying relevant zrc20 pools #143

Merged
merged 7 commits into from
May 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 88 additions & 26 deletions packages/client/src/getPools.ts
Original file line number Diff line number Diff line change
@@ -1,53 +1,115 @@
import UniswapV2Factory from "@uniswap/v2-core/build/UniswapV2Factory.json";
import UniswapV2Pair from "@uniswap/v2-core/build/UniswapV2Pair.json";
import { getAddress, ParamChainName } from "@zetachain/protocol-contracts";
import SystemContract from "@zetachain/protocol-contracts/abi/zevm/SystemContract.sol/SystemContract.json";
import { ethers } from "ethers";

import { ZetaChainClient } from "./client";

export const getPools = async function (this: ZetaChainClient) {
const rpc = this.getEndpoint("evm", `zeta_${this.network}`);
const provider = new ethers.providers.StaticJsonRpcProvider(rpc);

const uniswapV2FactoryAddress = getAddress(
"uniswapV2Factory",
`zeta_${this.network}` as ParamChainName
);
const zetaNetwork = `zeta_${this.network}` as ParamChainName;
const uniswapV2FactoryAddress = getAddress("uniswapV2Factory", zetaNetwork);

if (!uniswapV2FactoryAddress) {
throw new Error("uniswapV2Factory is not defined");
}

const UniswapV2FactoryContract = new ethers.Contract(
uniswapV2FactoryAddress,
UniswapV2Factory.abi,
const systemContractAddress = getAddress("systemContract", zetaNetwork);
if (!systemContractAddress) {
throw new Error("System contract is not defined");
}

const systemContract = new ethers.Contract(
systemContractAddress,
SystemContract.abi,
provider
);

const totalPairs = await UniswapV2FactoryContract.allPairsLength();
let pairs = [];
for (let i = 0; i < totalPairs; i++) {
pairs.push(await UniswapV2FactoryContract.allPairs(i));
const zetaTokenAddress = getAddress("zetaToken", zetaNetwork);
if (!zetaTokenAddress) {
throw new Error("ZETA token address is not defined");
}

const poolPromises = pairs.map(async (pair: any) => {
let pool = {
pair,
t0: {},
t1: {},
} as any;
const pairContract = new ethers.Contract(pair, UniswapV2Pair.abi, provider);
const foreignCoins = await this.getForeignCoins();
const tokenAddresses = foreignCoins.map(
(coin: any) => coin.zrc20_contract_address
);
tokenAddresses.push(zetaTokenAddress);

const uniquePairs = tokenAddresses.reduce(
(pairs: any, tokenA: string, i: any) => {
tokenAddresses.slice(i + 1).forEach((tokenB: any) => {
const pairKey = [tokenA, tokenB].sort().join("-");
if (!pairs.some((p: any) => p.key === pairKey)) {
pairs.push({ key: pairKey, tokenA, tokenB });
}
});
return pairs;
},
[]
);

const poolPromises = uniquePairs.map(async ({ tokenA, tokenB }: any) => {
const pair = await systemContract.uniswapv2PairFor(
uniswapV2FactoryAddress,
tokenA,
tokenB
);

if (pair === ethers.constants.AddressZero) return null;

try {
const pairContract = new ethers.Contract(
pair,
UniswapV2Pair.abi,
provider
);
const [token0, token1] = await Promise.all([
pairContract.token0(),
pairContract.token1(),
]);
const reserves = await pairContract.getReserves();

return {
pair,
t0: { address: token0, reserve: reserves[0] },
t1: { address: token1, reserve: reserves[1] },
};
} catch (error) {
return null;
}
});

pool.t0.address = await pairContract.token0();
pool.t1.address = await pairContract.token1();
let pools = (await Promise.all(poolPromises)).filter((pool) => pool !== null);

const reserves = await pairContract.getReserves();
pool.t0.reserve = reserves[0];
pool.t1.reserve = reserves[1];
const zrc20Details = foreignCoins.reduce((acc: any, coin: any) => {
acc[coin.zrc20_contract_address.toLowerCase()] = {
decimals: coin.decimals,
symbol: coin.symbol,
};
return acc;
}, {});

return pool;
pools = pools.map((t: any) => {
const zeta = { decimals: 18, symbol: "WZETA" };
const t0 = t.t0.address.toLowerCase();
const t1 = t.t1.address.toLowerCase();
const t0ZETA = t0 === zetaTokenAddress.toLowerCase() && zeta;
const t1ZETA = t1 === zetaTokenAddress.toLowerCase() && zeta;
return {
...t,
t0: {
...t.t0,
...(zrc20Details[t0] || t0ZETA),
},
t1: {
...t.t1,
...(zrc20Details[t1] || t1ZETA),
},
};
});

const pools = await Promise.all(poolPromises);
return pools;
};
45 changes: 13 additions & 32 deletions packages/tasks/src/pools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,45 +10,26 @@ const main = async (args: any, hre: HardhatRuntimeEnvironment) => {
network: args.mainnet ? "mainnet" : "testnet",
});

const foreignCoins = await client.getForeignCoins();
const pools = await client.getPools();

const addressToInfo = foreignCoins.reduce((acc: any, coin: any) => {
acc[coin.zrc20_contract_address.toLowerCase()] = {
decimals: coin.decimals,
symbol: coin.symbol,
};
return acc;
}, {});

const wzeta = getAddress(
"zetaToken",
`zeta_${client.network}` as ParamChainName
);
if (!wzeta) {
throw new Error("Could not find the WZETA address");
}
const WZETA_ADDRESS = wzeta.toLowerCase();
addressToInfo[WZETA_ADDRESS] = { decimals: 18, symbol: "WZETA" };

const poolsWithSymbolsAndDecimals = pools.map((pool: any) => {
const placeholder = { decimals: 18, symbol: "Unknown" };
const t0Info = addressToInfo[pool.t0.address.toLowerCase()] || placeholder;
const t1Info = addressToInfo[pool.t1.address.toLowerCase()] || placeholder;
pool.t0.reserve = formatUnits(pool.t0.reserve, t0Info.decimals);
pool.t1.reserve = formatUnits(pool.t1.reserve, t1Info.decimals);

const poolsDisplay = pools.map((pool: any) => {
return {
...pool,
t0: { ...pool.t0, ...t0Info },
t1: { ...pool.t1, ...t1Info },
t0: {
...pool.t0,
reserve: formatUnits(pool.t0.reserve, pool.t0.decimals),
},
t1: {
...pool.t1,
reserve: formatUnits(pool.t1.reserve, pool.t1.decimals),
},
};
});

const tableData = {} as any;
poolsWithSymbolsAndDecimals.forEach((pool: any) => {
const r0 = parseFloat(pool.t0.reserve).toFixed(2);
const r1 = parseFloat(pool.t1.reserve).toFixed(2);
poolsDisplay.forEach((pool: any) => {
const r0 = parseFloat(pool.t0.reserve);
const r1 = parseFloat(pool.t1.reserve);

tableData[pool.pair] = {
Pool: `${pool.t0.symbol} / ${pool.t1.symbol}`,
Expand All @@ -57,7 +38,7 @@ const main = async (args: any, hre: HardhatRuntimeEnvironment) => {
});

if (args.json) {
console.log(poolsWithSymbolsAndDecimals);
console.log(pools);
} else {
console.table(tableData);
}
Expand Down
Loading