diff --git a/packages/state/query/queries/token.ts b/packages/state/query/queries/token.ts index 8814eae2f..aabbbe53f 100644 --- a/packages/state/query/queries/token.ts +++ b/packages/state/query/queries/token.ts @@ -1,20 +1,15 @@ import { QueryClient, queryOptions } from '@tanstack/react-query' import { - AstroportToken, ChainId, GenericToken, GenericTokenSource, GenericTokenWithUsdPrice, TokenType, - WhiteWhalePool, } from '@dao-dao/types' import { FanToken } from '@dao-dao/types/protobuf/codegen/bitsong/fantoken/v1beta1/fantoken' import { - ASTROPORT_PRICES_API, MAINNET, - OSMOSIS_API_BASE, - WHITE_WHALE_PRICES_API, bitsongProtoRpcClientRouter, convertChainRegistryAssetToGenericToken, getChainForChainName, @@ -24,7 +19,6 @@ import { ibcProtoRpcClientRouter, isSecretNetwork, isValidUrl, - objectMatchesStructure, transformIpfsUrlToHttpsIfNecessary, } from '@dao-dao/utils' @@ -444,155 +438,31 @@ export const fetchBitSongFantoken = async ({ } /** - * Fetch the Coin Gecko price for a token. + * Fetch the USD price for a token from Snapper. */ -export const fetchCoinGeckoPrice = async ( +export const fetchUsdPrice = async ( queryClient: QueryClient, options: GenericTokenSource ): Promise => { - const token = await queryClient.fetchQuery( - tokenQueries.info(queryClient, options) - ) - - const asset = await queryClient.fetchQuery( - skipQueries.asset(queryClient, options) - ) - - if (!asset?.coingecko_id) { - throw new Error('No Coin Gecko ID found') - } - - const usdPrice: number | null = await queryClient.fetchQuery( - indexerQueries.snapper({ - query: 'coingecko-price', - parameters: { - id: asset.coingecko_id, - }, - }) - ) - - if (usdPrice === null) { - throw new Error('No Coin Gecko price found') - } - - return { - token, - usdPrice, - timestamp: new Date(), + if (!MAINNET) { + throw new Error('USD prices are only available on mainnet') } -} -/** - * Fetch the Osmosis price for a token. - */ -export const fetchOsmosisPrice = async ( - queryClient: QueryClient, - options: GenericTokenSource -): Promise => { const token = await queryClient.fetchQuery( tokenQueries.info(queryClient, options) ) - const { price } = await ( - await fetch(OSMOSIS_API_BASE + '/tokens/v2/price/' + token.symbol) - ).json() - - if (typeof price !== 'number') { - throw new Error('No Osmosis price found') - } - - return { - token, - usdPrice: price, - timestamp: new Date(), - } -} - -/** - * Fetch the Astroport price for a token. - */ -export const fetchAstroportPrice = async ( - queryClient: QueryClient, - options: GenericTokenSource -): Promise => { - let denom = options.denomOrAddress - if (options.chainId !== ChainId.NeutronMainnet) { - const asset = await queryClient.fetchQuery( - skipQueries.recommendedAssetForGenericToken(queryClient, { - fromChainId: options.chainId, - toChainId: ChainId.NeutronMainnet, - type: options.type, - denomOrAddress: options.denomOrAddress, + const usdPrice = + (await queryClient.fetchQuery( + indexerQueries.snapper({ + query: 'daodao-price', + parameters: { + chainId: options.chainId, + denom: options.denomOrAddress, + cw20: (options.type === TokenType.Cw20).toString(), + }, }) - ) - if (!asset) { - throw new Error('No Neutron asset found for Astroport price') - } - denom = asset.denom - } - - const token = await queryClient.fetchQuery( - tokenQueries.info(queryClient, options) - ) - - const response = await fetch(ASTROPORT_PRICES_API.replace('DENOM', denom)) - if (response.status !== 200) { - throw new Error('No Astroport price found') - } - - const astroportToken: AstroportToken = await response.json() - if ( - !objectMatchesStructure(astroportToken, { - priceUSD: {}, - }) - ) { - throw new Error('No Astroport price found') - } - - return { - token, - usdPrice: astroportToken.priceUSD, - timestamp: new Date(), - } -} - -/** - * Fetch the White Whale price for a token. - */ -export const fetchWhiteWhalePrice = async ( - queryClient: QueryClient, - options: GenericTokenSource -): Promise => { - // Get WHALE USD price from Osmosis. - const whaleUsdPrice = await queryClient.fetchQuery( - tokenQueries.osmosisPrice(queryClient, { - type: TokenType.Native, - chainId: ChainId.MigalooMainnet, - denomOrAddress: 'uwhale', - }) - ) - - if (whaleUsdPrice.usdPrice === undefined) { - throw new Error('No Osmosis WHALE price found') - } - - const token = await queryClient.fetchQuery( - tokenQueries.info(queryClient, options) - ) - - const pools: WhiteWhalePool[] = await ( - await fetch(WHITE_WHALE_PRICES_API) - ).json() - - // Find SYMBOL-WHALE pool. - const pool = pools.find((pool) => pool.pool_id === `${token.symbol}-WHALE`) - if (!pool) { - throw new Error('No White Whale pool found') - } - - // Amount of WHALE for 1 token. - const priceInWhale = Number(pool.Price) - const usdPrice = priceInWhale * whaleUsdPrice.usdPrice + )) ?? undefined return { token, @@ -601,44 +471,6 @@ export const fetchWhiteWhalePrice = async ( } } -/** - * Fetch the USD price for a token. - */ -export const fetchUsdPrice = async ( - queryClient: QueryClient, - options: GenericTokenSource -): Promise => { - if (!MAINNET) { - throw new Error('USD prices are only available on mainnet') - } - - const priceQueries = [ - tokenQueries.coinGeckoPrice, - tokenQueries.osmosisPrice, - tokenQueries.astroportPrice, - tokenQueries.whiteWhalePrice, - ] - - const errors: Error[] = [] - - // Return the first successful price query. - return await Promise.race( - priceQueries.map((query) => - queryClient.fetchQuery(query(queryClient, options)).catch((error) => { - errors.push(error) - - // If this is the last query and it failed, throw the aggregate error. - if (errors.length === priceQueries.length) { - throw new AggregateError(errors, 'All price queries failed') - } - - // Return a never-resolving promise to keep the race going. - return new Promise(() => {}) - }) - ) - ) -} - export const tokenQueries = { /** * Fetch info for a token. @@ -682,50 +514,6 @@ export const tokenQueries = { queryKey: ['token', 'bitSongFantoken', options], queryFn: () => fetchBitSongFantoken(options), }), - /** - * Fetch the Coin Gecko price for a token. - */ - coinGeckoPrice: ( - queryClient: QueryClient, - options: Parameters[1] - ) => - queryOptions({ - queryKey: ['token', 'coinGeckoPrice', options], - queryFn: () => fetchCoinGeckoPrice(queryClient, options), - }), - /** - * Fetch the Osmosis price for a token. - */ - osmosisPrice: ( - queryClient: QueryClient, - options: Parameters[1] - ) => - queryOptions({ - queryKey: ['token', 'osmosisPrice', options], - queryFn: () => fetchOsmosisPrice(queryClient, options), - }), - /** - * Fetch the Astroport price for a token. - */ - astroportPrice: ( - queryClient: QueryClient, - options: Parameters[1] - ) => - queryOptions({ - queryKey: ['token', 'astroportPrice', options], - queryFn: () => fetchAstroportPrice(queryClient, options), - }), - /** - * Fetch the White Whale price for a token. - */ - whiteWhalePrice: ( - queryClient: QueryClient, - options: Parameters[1] - ) => - queryOptions({ - queryKey: ['token', 'whiteWhalePrice', options], - queryFn: () => fetchWhiteWhalePrice(queryClient, options), - }), /** * Fetch the USD price for a token. */