From 7b653c46bacb1766d59dee523bd87e15a5e3687f Mon Sep 17 00:00:00 2001 From: Bogdan Fazakas Date: Tue, 20 Apr 2021 09:44:18 +0300 Subject: [PATCH] fetch asset price withoud relying on ddo.price --- src/providers/Asset.tsx | 88 +++-------------------------------------- src/utils/subgraph.ts | 79 +++++++++++++++++++++++++++++++----- 2 files changed, 76 insertions(+), 91 deletions(-) diff --git a/src/providers/Asset.tsx b/src/providers/Asset.tsx index 0f336cc6a..d6e947e57 100644 --- a/src/providers/Asset.tsx +++ b/src/providers/Asset.tsx @@ -12,11 +12,9 @@ import { PurgatoryData } from '@oceanprotocol/lib/dist/node/ddo/interfaces/Purga import getAssetPurgatoryData from '../utils/purgatory' import axios, { CancelToken } from 'axios' import { retrieveDDO } from '../utils/aquarius' +import { getPrice } from '../utils/subgraph' import { MetadataMarket } from '../@types/MetaData' import { useOcean } from './Ocean' -import { gql, useQuery } from '@apollo/client' -import { PoolPrice } from '../@types/apollo/PoolPrice' -import { FrePrice } from '../@types/apollo/FrePrice' interface AssetProviderValue { isInPurgatory: boolean @@ -33,25 +31,6 @@ interface AssetProviderValue { refreshDdo: (token?: CancelToken) => Promise } -const poolQuery = gql` - query PoolPrice($datatoken: String) { - pools(where: { datatokenAddress: $datatoken }) { - spotPrice - datatokenReserve - oceanReserve - } - } -` - -const freQuery = gql` - query FrePrice($datatoken: String) { - fixedRateExchanges(orderBy: id, where: { datatoken: $datatoken }) { - rate - id - } - } -` - const AssetContext = createContext({} as AssetProviderValue) const refreshInterval = 10000 // 10 sec. @@ -74,64 +53,6 @@ function AssetProvider({ const [owner, setOwner] = useState() const [error, setError] = useState() const [type, setType] = useState() - const [variables, setVariables] = useState({}) - - /* eslint-disable @typescript-eslint/no-unused-vars */ - const { - refetch: refetchFre, - startPolling: startPollingFre, - data: frePrice - } = useQuery(freQuery, { - variables, - skip: false - }) - const { - refetch: refetchPool, - startPolling: startPollingPool, - data: poolPrice - } = useQuery(poolQuery, { - variables, - skip: false - }) - /* eslint-enable @typescript-eslint/no-unused-vars */ - - // this is not working as expected, thus we need to fetch both pool and fre - // useEffect(() => { - // if (!ddo || !variables || variables === '') return - - // if (ddo.price.type === 'exchange') { - // refetchFre(variables) - // startPollingFre(refreshInterval) - // } else { - // refetchPool(variables) - // startPollingPool(refreshInterval) - // } - // }, [ddo, variables]) - - useEffect(() => { - if ( - !frePrice || - frePrice.fixedRateExchanges.length === 0 || - price.type !== 'exchange' - ) - return - setPrice((prevState) => ({ - ...prevState, - value: frePrice.fixedRateExchanges[0].rate, - address: frePrice.fixedRateExchanges[0].id - })) - }, [frePrice]) - - useEffect(() => { - if (!poolPrice || poolPrice.pools.length === 0 || price.type !== 'pool') - return - setPrice((prevState) => ({ - ...prevState, - value: poolPrice.pools[0].spotPrice, - ocean: poolPrice.pools[0].oceanReserve, - datatoken: poolPrice.pools[0].datatokenReserve - })) - }, [poolPrice]) const fetchDdo = async (token?: CancelToken) => { Logger.log('[asset] Init asset, get DDO') @@ -198,8 +119,11 @@ function AssetProvider({ // Set price & metadata from DDO first // TODO Hacky hack, temporary™: set isConsumable to true by default since Aquarius can't be trusted. - setPrice({ ...ddo.price, isConsumable: 'true' }) - setVariables({ datatoken: ddo?.dataToken.toLowerCase() }) + // setPrice({ ...ddo.price, isConsumable: 'true' }) + + const returnedPrice = await getPrice(ddo) + console.log('returnedPrice', returnedPrice) + setPrice({ ...returnedPrice, isConsumable: 'true' }) // Get metadata from DDO const { attributes } = ddo.findServiceByType('metadata') diff --git a/src/utils/subgraph.ts b/src/utils/subgraph.ts index 3ae3304cf..f07cfefb0 100644 --- a/src/utils/subgraph.ts +++ b/src/utils/subgraph.ts @@ -1,5 +1,5 @@ import { gql, DocumentNode, ApolloQueryResult } from '@apollo/client' -import { DDO } from '@oceanprotocol/lib' +import { DDO, BestPrice } from '@oceanprotocol/lib' import { getApolloClientInstance } from '../providers/ApolloClientProvider' import BigNumber from 'bignumber.js' @@ -7,8 +7,8 @@ export interface PriceList { [key: string]: string } -const freQuery = gql` - query AssetFrePrice($datatoken_in: [String!]) { +const FreQuery = gql` + query AssetsFrePrice($datatoken_in: [String!]) { fixedRateExchanges(orderBy: id, where: { datatoken_in: $datatoken_in }) { rate id @@ -20,8 +20,17 @@ const freQuery = gql` } ` -const poolQuery = gql` - query AssetPoolPrice($datatokenAddress_in: [String!]) { +const AssetFreQuery = gql` + query AssetFrePrice($datatoken: String) { + fixedRateExchanges(orderBy: id, where: { datatoken: $datatoken }) { + rate + id + } + } +` + +const PoolQuery = gql` + query AssetsPoolPrice($datatokenAddress_in: [String!]) { pools(where: { datatokenAddress_in: $datatokenAddress_in }) { spotPrice id @@ -30,7 +39,19 @@ const poolQuery = gql` } ` -const previousOrderQuery = gql` +const AssetPoolPriceQuerry = gql` + query AssetPoolPrice($datatokenAddress: String) { + pools(where: { datatokenAddress: $datatokenAddress }) { + id + spotPrice + datatokenReserve + oceanReserve + datatokenAddress + } + } +` + +const PreviousOrderQuery = gql` query AssetPreviousOrder($id: String!, $account: String!) { tokenOrders( first: 1 @@ -70,7 +91,7 @@ export async function getPreviousOrders( account: account } const fetchedPreviousOrders: any = await fetchData( - previousOrderQuery, + PreviousOrderQuery, variables ) if (fetchedPreviousOrders.data?.tokenOrders?.length === 0) return null @@ -104,13 +125,53 @@ export async function getAssetPrices(assets: DDO[]): Promise { const poolVariables = { datatokenAddress_in: dataTokenList } - const poolPriceResponse: any = await fetchData(poolQuery, poolVariables) + const poolPriceResponse: any = await fetchData(PoolQuery, poolVariables) for (const poolPrice of poolPriceResponse.data?.pools) { priceList[didDTMap[poolPrice.datatokenAddress]] = poolPrice.spotPrice } - const frePriceResponse: any = await fetchData(freQuery, freVariables) + const frePriceResponse: any = await fetchData(FreQuery, freVariables) for (const frePrice of frePriceResponse.data?.fixedRateExchanges) { priceList[didDTMap[frePrice.datatoken?.address]] = frePrice.rate } return priceList } + +export async function getPrice(asset: DDO): Promise { + const freVariables = { + datatoken: asset?.dataToken.toLowerCase() + } + + const poolVariables = { + datatokenAddress: asset?.dataToken.toLowerCase() + } + + const poolPriceResponse: any = await fetchData( + AssetPoolPriceQuerry, + poolVariables + ) + const frePriceResponse: any = await fetchData(AssetFreQuery, freVariables) + if (poolPriceResponse.data?.pools.length > 0) { + const price: BestPrice = { + type: 'pool', + address: poolPriceResponse.data?.pools[0]?.id, + value: poolPriceResponse.data?.pools[0]?.spotPrice, + ocean: poolPriceResponse.data?.pools[0]?.oceanReserve, + datatoken: poolPriceResponse.data?.pools[0]?.datatokenReserve, + pools: [poolPriceResponse.data?.pools[0]?.id] + } + return price + } else if (frePriceResponse.data?.fixedRateExchanges.length > 0) { + const price: BestPrice = { + type: 'exchange', + value: frePriceResponse.data?.fixedRateExchanges[0]?.rate, + address: frePriceResponse.data?.fixedRateExchanges[0]?.id, + exchange_id: frePriceResponse.data?.fixedRateExchanges[0]?.id, + ocean: 0, + datatoken: 0, + pools: [] + } + return price + } else { + return null + } +}