From 3609c222b2971f7c6538bca22aafd16276c0d1bd Mon Sep 17 00:00:00 2001 From: Joel Carter Date: Tue, 22 Apr 2025 19:32:59 -0500 Subject: [PATCH 1/5] Use IStateView ABI --- .../market/packages/uniswap/src/lib/v4/getExchangeRate.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/payloadset/packages/crypto/packages/market/packages/uniswap/src/lib/v4/getExchangeRate.ts b/packages/payloadset/packages/crypto/packages/market/packages/uniswap/src/lib/v4/getExchangeRate.ts index 92b6067d1..c49a36b7e 100644 --- a/packages/payloadset/packages/crypto/packages/market/packages/uniswap/src/lib/v4/getExchangeRate.ts +++ b/packages/payloadset/packages/crypto/packages/market/packages/uniswap/src/lib/v4/getExchangeRate.ts @@ -4,6 +4,7 @@ import { Contract } from "ethers/contract" import { Provider } from "ethers/providers" import { getPoolId } from "./getPoolId.ts" import { getPriceFromSqrtX96 } from "./getPriceFromSqrtX96.ts" +import { IStateView, IStateView__factory } from "@xyo-network/uniswap-typechain/v4-periphery" const STATE_VIEW_ADDRESS = "0x7ffe42c4a5deea5b0fec41c94c136cf115597227" // State view contract address @@ -26,7 +27,7 @@ export const getExchangeRate = async ( provider: Provider ): Promise => { const hooks = hookAddress || ZeroAddress - const stateView = new Contract(STATE_VIEW_ADDRESS, STATE_VIEW_ABI, provider) + const stateView = new Contract(STATE_VIEW_ADDRESS, IStateView__factory.abi, provider) const [token0, token1] = tokenA.sortsBefore(tokenB) ? [tokenA, tokenB] : [tokenB, tokenA] From 2b5170cc729764fd65ec8d490a247f1ecf28fc37 Mon Sep 17 00:00:00 2001 From: Joel Carter Date: Tue, 22 Apr 2025 19:38:36 -0500 Subject: [PATCH 2/5] Remove generic contract in favor of factory --- .../market/packages/uniswap/src/lib/v4/getExchangeRate.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/payloadset/packages/crypto/packages/market/packages/uniswap/src/lib/v4/getExchangeRate.ts b/packages/payloadset/packages/crypto/packages/market/packages/uniswap/src/lib/v4/getExchangeRate.ts index c49a36b7e..a75819acc 100644 --- a/packages/payloadset/packages/crypto/packages/market/packages/uniswap/src/lib/v4/getExchangeRate.ts +++ b/packages/payloadset/packages/crypto/packages/market/packages/uniswap/src/lib/v4/getExchangeRate.ts @@ -1,15 +1,12 @@ import { Token } from "@uniswap/sdk-core" import { ZeroAddress } from "ethers/constants" -import { Contract } from "ethers/contract" import { Provider } from "ethers/providers" import { getPoolId } from "./getPoolId.ts" import { getPriceFromSqrtX96 } from "./getPriceFromSqrtX96.ts" -import { IStateView, IStateView__factory } from "@xyo-network/uniswap-typechain/v4-periphery" +import { IStateView__factory } from "@xyo-network/uniswap-typechain/v4-periphery" const STATE_VIEW_ADDRESS = "0x7ffe42c4a5deea5b0fec41c94c136cf115597227" // State view contract address -const STATE_VIEW_ABI = [{"inputs":[{"internalType":"contract IPoolManager","name":"_poolManager","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"bytes32"}],"name":"getFeeGrowthGlobals","outputs":[{"internalType":"uint256","name":"feeGrowthGlobal0","type":"uint256"},{"internalType":"uint256","name":"feeGrowthGlobal1","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"bytes32"},{"internalType":"int24","name":"tickLower","type":"int24"},{"internalType":"int24","name":"tickUpper","type":"int24"}],"name":"getFeeGrowthInside","outputs":[{"internalType":"uint256","name":"feeGrowthInside0X128","type":"uint256"},{"internalType":"uint256","name":"feeGrowthInside1X128","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"bytes32"}],"name":"getLiquidity","outputs":[{"internalType":"uint128","name":"liquidity","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"bytes32"},{"internalType":"bytes32","name":"positionId","type":"bytes32"}],"name":"getPositionInfo","outputs":[{"internalType":"uint128","name":"liquidity","type":"uint128"},{"internalType":"uint256","name":"feeGrowthInside0LastX128","type":"uint256"},{"internalType":"uint256","name":"feeGrowthInside1LastX128","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"bytes32"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"int24","name":"tickLower","type":"int24"},{"internalType":"int24","name":"tickUpper","type":"int24"},{"internalType":"bytes32","name":"salt","type":"bytes32"}],"name":"getPositionInfo","outputs":[{"internalType":"uint128","name":"liquidity","type":"uint128"},{"internalType":"uint256","name":"feeGrowthInside0LastX128","type":"uint256"},{"internalType":"uint256","name":"feeGrowthInside1LastX128","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"bytes32"},{"internalType":"bytes32","name":"positionId","type":"bytes32"}],"name":"getPositionLiquidity","outputs":[{"internalType":"uint128","name":"liquidity","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"bytes32"}],"name":"getSlot0","outputs":[{"internalType":"uint160","name":"sqrtPriceX96","type":"uint160"},{"internalType":"int24","name":"tick","type":"int24"},{"internalType":"uint24","name":"protocolFee","type":"uint24"},{"internalType":"uint24","name":"lpFee","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"bytes32"},{"internalType":"int16","name":"tick","type":"int16"}],"name":"getTickBitmap","outputs":[{"internalType":"uint256","name":"tickBitmap","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"bytes32"},{"internalType":"int24","name":"tick","type":"int24"}],"name":"getTickFeeGrowthOutside","outputs":[{"internalType":"uint256","name":"feeGrowthOutside0X128","type":"uint256"},{"internalType":"uint256","name":"feeGrowthOutside1X128","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"bytes32"},{"internalType":"int24","name":"tick","type":"int24"}],"name":"getTickInfo","outputs":[{"internalType":"uint128","name":"liquidityGross","type":"uint128"},{"internalType":"int128","name":"liquidityNet","type":"int128"},{"internalType":"uint256","name":"feeGrowthOutside0X128","type":"uint256"},{"internalType":"uint256","name":"feeGrowthOutside1X128","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"bytes32"},{"internalType":"int24","name":"tick","type":"int24"}],"name":"getTickLiquidity","outputs":[{"internalType":"uint128","name":"liquidityGross","type":"uint128"},{"internalType":"int128","name":"liquidityNet","type":"int128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolManager","outputs":[{"internalType":"contract IPoolManager","name":"","type":"address"}],"stateMutability":"view","type":"function"}] - /** * Returns the price of the token pair in the Uniswap V4 pool. * @param tokenA The first token in the pair. @@ -27,7 +24,7 @@ export const getExchangeRate = async ( provider: Provider ): Promise => { const hooks = hookAddress || ZeroAddress - const stateView = new Contract(STATE_VIEW_ADDRESS, IStateView__factory.abi, provider) + const stateView = IStateView__factory.connect(STATE_VIEW_ADDRESS, provider) const [token0, token1] = tokenA.sortsBefore(tokenB) ? [tokenA, tokenB] : [tokenB, tokenA] From 7a6379449685108d5fb72f3f2fc2c1cf07928b3c Mon Sep 17 00:00:00 2001 From: Joel Carter Date: Tue, 22 Apr 2025 19:52:30 -0500 Subject: [PATCH 3/5] Simplify call via contract --- .../market/packages/uniswap/src/lib/v4/getExchangeRate.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/payloadset/packages/crypto/packages/market/packages/uniswap/src/lib/v4/getExchangeRate.ts b/packages/payloadset/packages/crypto/packages/market/packages/uniswap/src/lib/v4/getExchangeRate.ts index a75819acc..1026bcb18 100644 --- a/packages/payloadset/packages/crypto/packages/market/packages/uniswap/src/lib/v4/getExchangeRate.ts +++ b/packages/payloadset/packages/crypto/packages/market/packages/uniswap/src/lib/v4/getExchangeRate.ts @@ -28,11 +28,9 @@ export const getExchangeRate = async ( const [token0, token1] = tokenA.sortsBefore(tokenB) ? [tokenA, tokenB] : [tokenB, tokenA] - const poolId: string = getPoolId(token0, token1, fee, 60, hooks) if (poolId === ZeroAddress) throw new Error("Invalid poolId") const response = await stateView.getSlot0(poolId) - const sqrtPriceX96 = response[0] - const price = getPriceFromSqrtX96(sqrtPriceX96, token1.decimals, token0.decimals) + const price = getPriceFromSqrtX96(response.sqrtPriceX96, token1.decimals, token0.decimals) return price } From 0e89ba921788c6da24d41401b051bf2368e48014 Mon Sep 17 00:00:00 2001 From: Joel Carter Date: Tue, 22 Apr 2025 20:07:22 -0500 Subject: [PATCH 4/5] Add contract address map --- .../uniswap/src/lib/v4/UniswapV4ContractAddresses.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 packages/payloadset/packages/crypto/packages/market/packages/uniswap/src/lib/v4/UniswapV4ContractAddresses.ts diff --git a/packages/payloadset/packages/crypto/packages/market/packages/uniswap/src/lib/v4/UniswapV4ContractAddresses.ts b/packages/payloadset/packages/crypto/packages/market/packages/uniswap/src/lib/v4/UniswapV4ContractAddresses.ts new file mode 100644 index 000000000..28ed4d5c0 --- /dev/null +++ b/packages/payloadset/packages/crypto/packages/market/packages/uniswap/src/lib/v4/UniswapV4ContractAddresses.ts @@ -0,0 +1,11 @@ +// https://docs.uniswap.org/contracts/v4/deployments#mainnet-deployments +export const UniswapV4ContractAddresses = { + Ethereum: { + PoolManager: "0x000000000004444c5dc75cB358380D2e3dE08A90", + PositionDescriptor: "0xd1428ba554f4c8450b763a0b2040a4935c63f06c", + PositionManager: "0xbd216513d74c8cf14cf4747e6aaa6420ff64ee9e", + Quoter: "0x52f0e24d1c21c8a0cb1e5a5dd6198556bd9e1203", + StateView: "0x7ffe42c4a5deea5b0fec41c94c136cf115597227", + UniversalRouter: "0x66a9893cc07d91d95644aedd05d03f95e1dba8af", + } +} \ No newline at end of file From 545128ec2b3079b39f84e97877ae017ba37f5e48 Mon Sep 17 00:00:00 2001 From: Joel Carter Date: Tue, 22 Apr 2025 20:07:34 -0500 Subject: [PATCH 5/5] Use contract address from map --- .../market/packages/uniswap/src/lib/v4/getExchangeRate.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/payloadset/packages/crypto/packages/market/packages/uniswap/src/lib/v4/getExchangeRate.ts b/packages/payloadset/packages/crypto/packages/market/packages/uniswap/src/lib/v4/getExchangeRate.ts index 1026bcb18..8c3a77632 100644 --- a/packages/payloadset/packages/crypto/packages/market/packages/uniswap/src/lib/v4/getExchangeRate.ts +++ b/packages/payloadset/packages/crypto/packages/market/packages/uniswap/src/lib/v4/getExchangeRate.ts @@ -4,8 +4,7 @@ import { Provider } from "ethers/providers" import { getPoolId } from "./getPoolId.ts" import { getPriceFromSqrtX96 } from "./getPriceFromSqrtX96.ts" import { IStateView__factory } from "@xyo-network/uniswap-typechain/v4-periphery" - -const STATE_VIEW_ADDRESS = "0x7ffe42c4a5deea5b0fec41c94c136cf115597227" // State view contract address +import { UniswapV4ContractAddresses } from "./UniswapV4ContractAddresses.ts" /** * Returns the price of the token pair in the Uniswap V4 pool. @@ -24,7 +23,7 @@ export const getExchangeRate = async ( provider: Provider ): Promise => { const hooks = hookAddress || ZeroAddress - const stateView = IStateView__factory.connect(STATE_VIEW_ADDRESS, provider) + const stateView = IStateView__factory.connect(UniswapV4ContractAddresses.Ethereum.StateView, provider) const [token0, token1] = tokenA.sortsBefore(tokenB) ? [tokenA, tokenB] : [tokenB, tokenA]