Skip to content

Instantly share code, notes, and snippets.

@austintgriffith
Created November 21, 2024 17:33
Show Gist options
  • Save austintgriffith/ffa10c532827ac38e40ee46016c9c88b to your computer and use it in GitHub Desktop.
Save austintgriffith/ffa10c532827ac38e40ee46016c9c88b to your computer and use it in GitHub Desktop.
import { createPublicClient, http, parseEther, formatEther } from "viem";
import { base } from "viem/chains";
// Base DAI/ETH pool address
const UNISWAP_V3_FACTORY_ON_BASE = "0x33128a8fC17869897dcE68Ed026d694621f6FDfD";
const TOKEN_WE_WANT_TO_TRADE = "0x0db510e79909666d6dec7f5e49370838c16d950f";
const WETH_ADDRESS = "0x4200000000000000000000000000000000000006";
const USDC_ADDRESS = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
// Define fee tiers array (common Uniswap V3 fee tiers)
const FEE_TIERS = [100, 500, 3000, 10000]; // 0.01%, 0.05%, 0.3%, 1%
// Initialize Viem client
const client = createPublicClient({
chain: base,
transport: http(),
});
// Add ERC20 decimals ABI
const ERC20_DECIMALS_ABI = [
{
name: "decimals",
inputs: [],
outputs: [{ type: "uint8" }],
stateMutability: "view",
type: "function",
},
];
// Add function to get token decimals
async function getTokenDecimals(tokenAddress) {
const decimals = await client.readContract({
address: tokenAddress,
abi: ERC20_DECIMALS_ABI,
functionName: "decimals",
});
return decimals;
}
// Add function to get current price
async function getPoolPrice(poolAddress) {
const slot0Data = await client.readContract({
address: poolAddress,
abi: [
{
name: "slot0",
inputs: [],
outputs: [
{ name: "sqrtPriceX96", type: "uint160" },
{ name: "tick", type: "int24" },
{ name: "observationIndex", type: "uint16" },
{ name: "observationCardinality", type: "uint16" },
{ name: "observationCardinalityNext", type: "uint16" },
{ name: "feeProtocol", type: "uint8" },
{ name: "unlocked", type: "bool" },
],
stateMutability: "view",
type: "function",
},
],
functionName: "slot0",
});
const [token0, token1] = await Promise.all([
client.readContract({
address: poolAddress,
abi: [
{
name: "token0",
inputs: [],
outputs: [{ type: "address" }],
stateMutability: "view",
type: "function",
},
],
functionName: "token0",
}),
client.readContract({
address: poolAddress,
abi: [
{
name: "token1",
inputs: [],
outputs: [{ type: "address" }],
stateMutability: "view",
type: "function",
},
],
functionName: "token1",
}),
]);
const [decimals0, decimals1] = await Promise.all([
getTokenDecimals(token0),
getTokenDecimals(token1),
]);
const token0IsWETH = token0.toLowerCase() === WETH_ADDRESS.toLowerCase();
const sqrtPriceX96 = BigInt(slot0Data[0]);
const Q96 = 2n ** 96n;
const scaleFactor = parseEther("1");
// Calculate base price maintaining precision
const basePrice = (sqrtPriceX96 * sqrtPriceX96 * scaleFactor) / (Q96 * Q96);
// Divide by 10^6 since USDC has 6 decimals
return Number(basePrice) / 1_000_000;
}
// Function to get pool address
async function getPoolAddress(tokenAddress, feeIndex = 2) {
if (feeIndex < 0 || feeIndex >= FEE_TIERS.length) {
throw new Error(
`Invalid fee index. Must be between 0 and ${FEE_TIERS.length - 1}`
);
}
const feeTier = FEE_TIERS[feeIndex];
const poolAddress = await client.readContract({
address: UNISWAP_V3_FACTORY_ON_BASE,
abi: [
{
name: "getPool",
inputs: [{ type: "address" }, { type: "address" }, { type: "uint24" }],
outputs: [{ type: "address" }],
stateMutability: "view",
type: "function",
},
],
functionName: "getPool",
args: [WETH_ADDRESS, tokenAddress, feeTier],
});
console.log(`Pool Address for ${feeTier / 10000}% fee tier:`, poolAddress);
return poolAddress;
}
// Add function to get WETH price in USD
async function getWETHPrice() {
const wethUsdcPool = await getPoolAddress(USDC_ADDRESS, 1); // Using 0.3% fee tier for WETH/USDC
console.log("WETH/USDC Pool Address:", wethUsdcPool);
const wethPriceInUsdc = await getPoolPrice(wethUsdcPool);
return wethPriceInUsdc;
}
// Modify the final section to include WETH price calculation
const wethPrice = await getWETHPrice();
console.log("WETH Price (in USDC):", wethPrice);
const poolAddress = await getPoolAddress(TOKEN_WE_WANT_TO_TRADE, 3);
console.log("Pool Address for token we want to trade:", poolAddress);
const tokenPrice = await getPoolPrice(poolAddress);
console.log("Token Price (in WETH):", tokenPrice);
console.log("Token Price (in USD):", tokenPrice / wethPrice);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment