Files
sre-06-oracles/packages/hardhat/scripts/fetchPriceFromUniswap.ts
2026-01-23 20:20:58 +07:00

69 lines
2.7 KiB
TypeScript

import { ethers } from "hardhat";
import * as dotenv from "dotenv";
dotenv.config();
import { config as hardhatConfig } from "hardhat";
import { getConfig, updatePriceCache } from "./utils";
import { parseEther, formatEther } from "ethers";
const UNISWAP_V2_PAIR_ABI = [
"function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast)",
"function token0() external view returns (address)",
"function token1() external view returns (address)",
];
const DAI_ADDRESS = "0x6B175474E89094C44Da98b954EedeAC495271d0F";
const WETH_ADDRESS = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2";
const UNISWAP_V2_FACTORY = "0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f";
const mainnet = hardhatConfig.networks.mainnet;
const MAINNET_RPC = "url" in mainnet ? mainnet.url : "";
export const fetchPriceFromUniswap = async (): Promise<bigint> => {
const config = getConfig();
const cachedPrice = config.PRICE.CACHEDPRICE;
const timestamp = config.PRICE.TIMESTAMP;
if (Date.now() - timestamp < 1000 * 60 * 60) {
return parseEther(cachedPrice.toString());
}
console.log("Cache expired or missing, fetching fresh price from Uniswap...");
try {
const provider = new ethers.JsonRpcProvider(MAINNET_RPC);
const tokenAddress = WETH_ADDRESS; // Always use WETH for mainnet
// Get pair address from Uniswap V2 Factory
const factory = new ethers.Contract(
UNISWAP_V2_FACTORY,
["function getPair(address tokenA, address tokenB) external view returns (address pair)"],
provider,
);
const pairAddress = await factory.getPair(tokenAddress, DAI_ADDRESS);
if (pairAddress === ethers.ZeroAddress) {
throw new Error("No liquidity pair found");
}
const pairContract = new ethers.Contract(pairAddress, UNISWAP_V2_PAIR_ABI, provider);
const [reserves, token0Address] = await Promise.all([pairContract.getReserves(), pairContract.token0()]);
// Determine which reserve is token and which is DAI
const isToken0 = token0Address.toLowerCase() === tokenAddress.toLowerCase();
const tokenReserve = isToken0 ? reserves[0] : reserves[1];
const daiReserve = isToken0 ? reserves[1] : reserves[0];
// Calculate price (DAI per token)
const price = BigInt(Math.floor((Number(daiReserve) / Number(tokenReserve)) * 1e18));
// Update cache with fresh price
const pricePerEther = parseFloat(formatEther(price));
updatePriceCache(pricePerEther, Date.now());
console.log(`Fresh price fetched and cached: ${formatEther(price)} ETH`);
return price;
} catch (error) {
console.error("Error fetching ETH price from Uniswap: ", error);
return parseEther(cachedPrice.toString());
}
};