Created
November 21, 2024 17:33
-
-
Save austintgriffith/ffa10c532827ac38e40ee46016c9c88b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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