diff --git a/packages/server/src/queries/complex/assets/price/index.ts b/packages/server/src/queries/complex/assets/price/index.ts index ec1abe35f2..d05ea20884 100644 --- a/packages/server/src/queries/complex/assets/price/index.ts +++ b/packages/server/src/queries/complex/assets/price/index.ts @@ -13,8 +13,6 @@ import { getPriceFromSidecar } from "./providers/sidecar"; /** Provides a price (no caching) given a valid asset from asset list and a fiat currency code. * @throws if there's an issue getting the price. */ export type PriceProvider = ( - assetLists: AssetList[], - chainList: Chain[], asset: Asset, currency?: CoingeckoVsCurrencies ) => Promise; @@ -25,7 +23,6 @@ const pricesCache = new LRUCache(DEFAULT_LRU_OPTIONS); * @throws If the asset is not found in the asset list registry or the asset's price info is not found (missing in asset list or can't get price). */ export async function getAssetPrice({ assetLists, - chainList, asset, currency = "usd", priceProvider = getPriceFromSidecar, @@ -34,7 +31,6 @@ export async function getAssetPrice({ assetLists: AssetList[]; asset: { coinDenom?: string } & ( | { coinMinimalDenom: string } - | { sourceDenom: string } | { chainId: number | string; address: string } | { coinGeckoId: string } ); @@ -43,7 +39,6 @@ export async function getAssetPrice({ }): Promise { const coinMinimalDenom = "coinMinimalDenom" in asset ? asset.coinMinimalDenom : undefined; - const sourceDenom = "sourceDenom" in asset ? asset.sourceDenom : undefined; const { chainId, address } = "chainId" in asset && "address" in asset ? asset @@ -56,7 +51,6 @@ export async function getAssetPrice({ .find( (asset) => (coinMinimalDenom && asset.coinMinimalDenom === coinMinimalDenom) || - (sourceDenom && asset.sourceDenom === sourceDenom) || (chainId && address && asset.counterparty.some( @@ -77,7 +71,7 @@ export async function getAssetPrice({ if (!foundAsset) throw new Error( `Asset ${ - asset.coinDenom ?? coinMinimalDenom ?? sourceDenom + asset.coinDenom ?? coinMinimalDenom } not found in asset list registry.` ); @@ -85,8 +79,7 @@ export async function getAssetPrice({ key: `asset-price-${foundAsset.coinMinimalDenom}`, cache: pricesCache, ttl: 1000 * 10, // 10 seconds - getFreshValue: () => - priceProvider(assetLists, chainList, foundAsset, currency), + getFreshValue: () => priceProvider(foundAsset, currency), }); } diff --git a/packages/server/src/queries/complex/assets/price/providers/pools.ts b/packages/server/src/queries/complex/assets/price/providers/pools.ts deleted file mode 100644 index a147492ea3..0000000000 --- a/packages/server/src/queries/complex/assets/price/providers/pools.ts +++ /dev/null @@ -1,157 +0,0 @@ -import { Dec, DecUtils, IntPretty } from "@keplr-wallet/unit"; -import { makeStaticPoolFromRaw, PoolRaw } from "@osmosis-labs/pools"; -import { Asset, AssetList, Chain } from "@osmosis-labs/types"; -import { getAssetFromAssetList, isNil } from "@osmosis-labs/utils"; - -import { CoingeckoVsCurrencies } from "../../../../coingecko"; -import { queryPaginatedPools } from "../../../../complex/pools/providers/indexer"; -import { getCoingeckoPrice, getPriceFromCoinGecko } from "./coingecko"; - -/** Calculates prices by querying pools and finding spot prices through routes in those pools. Falls back to CoinGecko if price not found. - * @throws if there's no price info for that asset, or there's an issue calculating the price. */ -export async function getPriceFromPools( - assetLists: AssetList[], - chainList: Chain[], - asset: Asset, - currency: CoingeckoVsCurrencies = "usd" -): Promise { - if (asset.price) { - return await calculatePriceThroughPools({ - assetLists, - chainList, - asset, - currency, - }); - } - - return await getPriceFromCoinGecko(asset, currency); -} - -/** - * Calculates the price of a pool price info. - * - * To calculate the price it: - * 1. Finds the pool price route - * 2. Gets the spot price of the pool - * 3. Calculated the price of the destination coin recursively (i.e. usd-coin or another pool like uosmo) - * - * Note: For now only "usd" is supported. - * - * @throws If the asset is not found in the asset list registry or the asset's price info is not found. Or if there's an issue getting the price from CoinGecko. - */ -async function calculatePriceThroughPools({ - assetLists, - chainList, - asset, - currency, -}: { - assetLists: AssetList[]; - chainList: Chain[]; - asset: Pick; - currency: "usd"; -}): Promise { - if (!asset.price && !asset.coingeckoId) - throw new Error( - "No price info or coingecko id for " + asset.coinMinimalDenom - ); - - /** - * Fetch directly from coingecko if there's no price info. - */ - if (!asset.price && asset.coingeckoId) { - return await getCoingeckoPrice({ - coinGeckoId: asset.coingeckoId, - currency, - }); - } - - if (!asset.price) - throw new Error("No price info for " + asset.coinMinimalDenom); - - const poolPriceRoute = { - destCoinMinimalDenom: asset.price.denom, - poolId: asset.price.poolId, - sourceCoinMinimalDenom: asset.coinMinimalDenom, - }; - - if (!poolPriceRoute) - throw new Error("No pool price route for " + asset.coinMinimalDenom); - - const tokenInIbc = poolPriceRoute.sourceCoinMinimalDenom; - const tokenOutIbc = poolPriceRoute.destCoinMinimalDenom; - - const tokenInAsset = getAssetFromAssetList({ - coinMinimalDenom: poolPriceRoute.sourceCoinMinimalDenom, - assetLists, - }); - - const tokenOutAsset = getAssetFromAssetList({ - coinMinimalDenom: poolPriceRoute.destCoinMinimalDenom, - assetLists, - }); - - if (!tokenInAsset) - throw new Error( - poolPriceRoute.sourceCoinMinimalDenom + - " price source coin not in asset list." - ); - - if (!tokenOutAsset) - throw new Error( - poolPriceRoute.destCoinMinimalDenom + - " price dest coin not in asset list." - ); - - const rawPool: PoolRaw = ( - await queryPaginatedPools({ - chainList, - poolId: poolPriceRoute.poolId, - }) - )?.pools[0]; - - if (!rawPool) - throw new Error( - "Pool " + poolPriceRoute.poolId + " not found for calculating price." - ); - - const pool = makeStaticPoolFromRaw(rawPool); - - if (isNil(tokenOutAsset.decimals) || isNil(tokenInAsset.decimals)) - throw new Error( - "Invalid decimals in " + - tokenOutAsset.symbol + - " or " + - tokenInAsset.symbol - ); - - const multiplication = DecUtils.getTenExponentN( - tokenOutAsset.decimals - tokenInAsset.decimals - ); - - // TODO: get spot price from token amounts instead - // of instantiating pool models with client - // side simulation logic. - const inSpotPrice = new IntPretty( - pool - .getSpotPriceInOverOutWithoutSwapFee(tokenInIbc, tokenOutIbc) - .mulTruncate(multiplication) - ); - - const spotPriceDec = inSpotPrice.toDec().equals(new Dec(0)) - ? new Dec(0) - : new Dec(1).quo(inSpotPrice.toDec()); - - const destCoinPrice = await calculatePriceThroughPools({ - assetLists, - chainList, - asset: tokenOutAsset.rawAsset, - currency, - }); - - if (!destCoinPrice) - throw new Error( - "No destination coin price found for " + tokenOutAsset.symbol - ); - - return spotPriceDec.mul(destCoinPrice); -} diff --git a/packages/server/src/queries/complex/assets/price/providers/sidecar.ts b/packages/server/src/queries/complex/assets/price/providers/sidecar.ts index 50bf5e1b9c..90c72c30b8 100644 --- a/packages/server/src/queries/complex/assets/price/providers/sidecar.ts +++ b/packages/server/src/queries/complex/assets/price/providers/sidecar.ts @@ -1,5 +1,5 @@ import { Dec } from "@keplr-wallet/unit"; -import { Asset, AssetList, Chain } from "@osmosis-labs/types"; +import { Asset } from "@osmosis-labs/types"; import cachified, { CacheEntry } from "cachified"; import { LRUCache } from "lru-cache"; @@ -9,26 +9,14 @@ import { } from "../../../../../queries/sidecar/prices"; import { EdgeDataLoader } from "../../../../../utils/batching"; import { LARGE_LRU_OPTIONS } from "../../../../../utils/cache"; -import { captureError } from "../../../../../utils/error"; -import { getPriceFromPools } from "./pools"; const sidecarCache = new LRUCache(LARGE_LRU_OPTIONS); /** Gets price from SQS query server. Currently only supports prices in USDC with decimals. Falls back to pools then querying CoinGecko if not available. * @throws if there's an issue getting the price. */ -export function getPriceFromSidecar( - assetLists: AssetList[], - chainList: Chain[], - asset: Asset -) { +export function getPriceFromSidecar(asset: Asset) { return getBatchLoader().then((loader) => - loader - .load(asset.coinMinimalDenom) - .then((price) => new Dec(price)) - .catch((e) => { - captureError(e); - return getPriceFromPools(assetLists, chainList, asset); - }) + loader.load(asset.coinMinimalDenom).then((price) => new Dec(price)) ); } diff --git a/packages/web/server/api/routers/bridge-transfer.ts b/packages/web/server/api/routers/bridge-transfer.ts index 2ade64c0f5..470ed2ba49 100644 --- a/packages/web/server/api/routers/bridge-transfer.ts +++ b/packages/web/server/api/routers/bridge-transfer.ts @@ -145,7 +145,6 @@ export const bridgeTransferRouter = createTRPCRouter({ ...ctx, asset: { coinMinimalDenom: input.toAsset.address, - sourceDenom: input.toAsset.address, chainId: input.toChain.chainId, address: input.toAsset.address, coinGeckoId: input.toAsset.coinGeckoId, @@ -169,7 +168,6 @@ export const bridgeTransferRouter = createTRPCRouter({ ...ctx, asset: { coinMinimalDenom: input.fromAsset.address, - sourceDenom: input.fromAsset.address, chainId: input.fromChain.chainId, address: input.fromAsset.address, coinGeckoId: input.fromAsset.coinGeckoId, @@ -180,7 +178,6 @@ export const bridgeTransferRouter = createTRPCRouter({ ...ctx, asset: { coinMinimalDenom: feeCoin.address, - sourceDenom: feeCoin.address, chainId: quote.transferFee.chainId, address: quote.transferFee.address, coinGeckoId: quote.transferFee.coinGeckoId, @@ -194,7 +191,6 @@ export const bridgeTransferRouter = createTRPCRouter({ { bridge: input.bridge, coinMinimalDenom: feeCoin.address, - sourceDenom: feeCoin.address, chainId: quote.transferFee.chainId, address: quote.transferFee.address, coinGeckoId: quote.transferFee.coinGeckoId, @@ -208,7 +204,6 @@ export const bridgeTransferRouter = createTRPCRouter({ ...ctx, asset: { coinMinimalDenom: quote.estimatedGasFee.address, - sourceDenom: quote.estimatedGasFee.address, chainId: quote.fromChain.chainId, address: quote.estimatedGasFee.address, coinGeckoId: quote.estimatedGasFee.coinGeckoId,