I’d like to improvement my understanding for the blockchain, it’s use cases and usage day by day. At the moment I’m creating an price oracle for Uniswap v2/v3 and my personal usage. Basically what the moralis getPrice() API is doing. I’m able to fetch the price for a given pair (e.g. DUBBZ/WETH) on Uniswap v2 and v3 (pseudo code below). I also compared the results to the getPrice() API and they’re identical.
One problem left.
Let’s me give you an example.
There are two pools for $PAAL. One on Uniswap v2 and one on Uniswap v3.
The price difference is about 0.002$. How to identify programmatically the most suitable pool for the price discovery? By liquidity? If so how?
@cryptokid @johnversus Could you please tell me how moralis solves this task?
Oracle
async function getAmountsOut(amountIn, path, blockTag = 'latest') {
let len = path.length;
let amounts = [amountIn];
for(let i = 0; i < len - 1; i++) {
const amountOut = await getAmountOut(amounts[i], path[i], path[i + 1], blockTag);
if (!amountOut) return undefined;
amounts[i + 1] = amountOut;
}
return amounts[amounts.length - 1];
}
async function getAmountOut(amountIn, srcToken, destToken, blockTag = 'latest') {
for (const oracle of ORACLES) {
const amountOut = await oracle.getAmountOut(amountIn, srcToken, destToken, blockTag);
if (!amountOut) continue;
return amountOut;
}
return undefined;
}
Uniswap v2
async function getAmountOut(amountIn, srcToken, destToken, blockTag = 'latest') {
const address = await getPool(srcToken, destToken, blockTag);
if (!address) return undefined;
const token0 = srcToken < destToken ? srcToken : destToken;
const [reserve0, reserve1] = await getReserves(address, blockTag);
if (reserve0 < 1n || reserve1 < 1n) return undefined;
const [reserveIn, reserveOut] = srcToken == token0 ? [reserve0, reserve1] : [reserve1, reserve0];
return (amountIn * reserveOut) / reserveIn;
}
Uniswap v3
const Q192 = 2n ** 192n;
async function getAmountOut(amountIn, srcToken, destToken, blockTag = 'latest') {
const token0 = srcToken < destToken ? srcToken : destToken;
for (const fee of [500, 3000, 10000]) {
const address = await getPool(srcToken, destToken, fee, blockTag);
if (!address) continue;
const [ sqrtPriceX96 ] = await slot0(address);
if (token0 == srcToken) {
return (amountIn * sqrtPriceX96 ** 2n) / Q192;
}
else {
return (amountIn * Q192) / (sqrtPriceX96 ** 2n);
}
}
return undefined;
}