diff --git a/src/components/App.tsx b/src/components/App.tsx index 830a679e7..ecb98db9c 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -1,4 +1,4 @@ -import React, { ReactElement, useEffect, useState } from 'react' +import React, { ReactElement } from 'react' import Footer from './organisms/Footer' import Header from './organisms/Header' import Styles from '../global/Styles' @@ -7,15 +7,7 @@ import { useSiteMetadata } from '../hooks/useSiteMetadata' import { useOcean } from '@oceanprotocol/react' import Alert from './atoms/Alert' import { graphql, PageProps, useStaticQuery } from 'gatsby' -import { - ApolloClient, - ApolloProvider, - HttpLink, - InMemoryCache, - NormalizedCacheObject -} from '@apollo/client' -import fetch from 'cross-fetch' -import { ConfigHelperConfig } from '@oceanprotocol/lib/dist/node/utils/ConfigHelper' + const contentQuery = graphql` query AppQuery { purgatory: allFile(filter: { relativePath: { eq: "purgatory.json" } }) { @@ -45,24 +37,9 @@ export default function App({ const { warning } = useSiteMetadata() const { isInPurgatory: isAccountInPurgatory, - purgatoryData: accountPurgatory, - config + purgatoryData: accountPurgatory } = useOcean() - const [client, setClient] = useState>() - - useEffect(() => { - const newClient = new ApolloClient({ - link: new HttpLink({ - uri: `${ - (config as ConfigHelperConfig).subgraphUri - }/subgraphs/name/oceanprotocol/ocean-subgraph`, - fetch - }), - cache: new InMemoryCache() - }) - setClient(newClient) - }, [config]) return (
@@ -78,13 +55,7 @@ export default function App({ state="error" /> )} - {client ? ( - -
{children}
-
- ) : ( - <> - )} +
{children}
diff --git a/src/components/atoms/Tooltip.tsx b/src/components/atoms/Tooltip.tsx index 1719ff0a0..afb2dc489 100644 --- a/src/components/atoms/Tooltip.tsx +++ b/src/components/atoms/Tooltip.tsx @@ -28,7 +28,9 @@ export default function Tooltip({ trigger, disabled, className, - placement + placement, + link, + reference }: { content: ReactNode children?: ReactNode @@ -36,6 +38,8 @@ export default function Tooltip({ disabled?: boolean className?: string placement?: Placement + link?: string + reference?: string }): ReactElement { const [props, setSpring] = useSpring(() => animation.from) @@ -72,6 +76,7 @@ export default function Tooltip({
{content} + {link && {reference}}
diff --git a/src/components/molecules/MarketStats.module.css b/src/components/molecules/MarketStats.module.css index 1acf8ce88..61392a80b 100644 --- a/src/components/molecules/MarketStats.module.css +++ b/src/components/molecules/MarketStats.module.css @@ -12,3 +12,7 @@ color: var(--color-secondary) !important; font-size: var(--font-size-small) !important; } + +.info { + width: .85rem +} \ No newline at end of file diff --git a/src/components/molecules/MarketStats.tsx b/src/components/molecules/MarketStats.tsx index cadbbb13d..1fbbde677 100644 --- a/src/components/molecules/MarketStats.tsx +++ b/src/components/molecules/MarketStats.tsx @@ -1,83 +1,47 @@ -import { Logger } from '@oceanprotocol/lib' import React, { ReactElement, useEffect, useState } from 'react' -import PriceUnit from '../atoms/Price/PriceUnit' -import axios from 'axios' import styles from './MarketStats.module.css' -import { useInView } from 'react-intersection-observer' +import { gql, useQuery } from '@apollo/client' +import Conversion from '../atoms/Price/Conversion' +import PriceUnit from '../atoms/Price/PriceUnit' +import Tooltip from '../atoms/Tooltip' -interface MarketStatsResponse { - datasets: { - pools: number - exchanges: number - none: number - total: number +const getTotalPoolsValues = gql` + query PoolsData { + poolFactories { + totalValueLocked + totalOceanLiquidity + finalizedPoolCount + } } - owners: number - ocean: number - datatoken: number -} - -const refreshInterval = 60000 // 60 sec. +` export default function MarketStats(): ReactElement { - const [ref, inView] = useInView() - const [stats, setStats] = useState() + const [totalValueLocked, setTotalValueLocked] = useState() + const [totalOceanLiquidity, setTotalOceanLiquidity] = useState() + const [poolCount, setPoolCount] = useState() + const { data } = useQuery(getTotalPoolsValues) useEffect(() => { - const source = axios.CancelToken.source() + if (!data) return - async function getStats() { - try { - const response = await axios('https://market-stats.oceanprotocol.com', { - cancelToken: source.token - }) - if (!response || response.status !== 200) return - setStats(response.data) - } catch (error) { - if (axios.isCancel(error)) { - Logger.log(error.message) - } else { - Logger.error(error.message) - } - } - } - - // Update periodically when in viewport - const interval = setInterval(getStats, refreshInterval) - - if (!inView) { - clearInterval(interval) - } - - getStats() - - return () => { - clearInterval(interval) - source.cancel() - } - }, [inView]) + setTotalValueLocked(data.poolFactories[0].totalValueLocked) + setTotalOceanLiquidity(data.poolFactories[0].totalOceanLiquidity) + setPoolCount(data.poolFactories[0].finalizedPoolCount) + }, [data]) return ( -
- Total of {stats?.datasets.total} data sets & unique - datatokens published by {stats?.owners} accounts. -
- {' '} - and{' '} - {' '} - in {stats?.datasets.pools} data set pools. -
- {stats?.datasets.none} data sets have no price set yet. +
+ {' '} + TVL across{' '} + {poolCount} data set pools that contain{' '} + , + plus datatokens for each pool. +
) } diff --git a/src/helpers/NetworkMonitor.tsx b/src/helpers/NetworkMonitor.tsx index 994b1e9ca..6c692a666 100644 --- a/src/helpers/NetworkMonitor.tsx +++ b/src/helpers/NetworkMonitor.tsx @@ -7,6 +7,18 @@ import contractAddresses from '@oceanprotocol/contracts/artifacts/address.json' const refreshInterval = 5000 // 5 sec. +export function getDevelopmentConfig(): Partial { + return { + factoryAddress: contractAddresses.development?.DTFactory, + poolFactoryAddress: contractAddresses.development?.BFactory, + fixedRateExchangeAddress: contractAddresses.development?.FixedRateExchange, + metadataContractAddress: contractAddresses.development?.Metadata, + oceanTokenAddress: contractAddresses.development?.Ocean, + // There is no subgraph in barge so we hardcode the Rinkeby one for now + subgraphUri: 'https://subgraph.rinkeby.oceanprotocol.com' + } +} + export function NetworkMonitor(): ReactElement { const { connect, @@ -28,12 +40,7 @@ export function NetworkMonitor(): ReactElement { // add local dev values ...(chainId === '8996' && { - factoryAddress: contractAddresses.development?.DTFactory, - poolFactoryAddress: contractAddresses.development?.BFactory, - fixedRateExchangeAddress: - contractAddresses.development?.FixedRateExchange, - metadataContractAddress: contractAddresses.development?.Metadata, - oceanTokenAddress: contractAddresses.development?.Ocean + ...getDevelopmentConfig() }) } diff --git a/src/helpers/wrapRootElement.tsx b/src/helpers/wrapRootElement.tsx index 6b3506ea5..15c6be409 100644 --- a/src/helpers/wrapRootElement.tsx +++ b/src/helpers/wrapRootElement.tsx @@ -2,7 +2,7 @@ import React, { ReactElement } from 'react' import { OceanProvider } from '@oceanprotocol/react' import { ConfigHelper, Config } from '@oceanprotocol/lib' import { web3ModalOpts } from '../utils/wallet' -import { NetworkMonitor } from './NetworkMonitor' +import { getDevelopmentConfig, NetworkMonitor } from './NetworkMonitor' import appConfig from '../../app.config' import { ConfigHelperNetworkName, @@ -10,6 +10,7 @@ import { } from '@oceanprotocol/lib/dist/node/utils/ConfigHelper' import { UserPreferencesProvider } from '../providers/UserPreferences' import PricesProvider from '../providers/Prices' +import ApolloClientProvider from '../providers/ApolloClientProvider' export function getOceanConfig( network: ConfigHelperNetworkName | ConfigHelperNetworkId @@ -26,16 +27,26 @@ export default function wrapRootElement({ element: ReactElement }): ReactElement { const { network } = appConfig - const oceanInitialConfig = getOceanConfig(network) + const oceanInitialConfig = { + ...getOceanConfig(network), + + // add local dev values + ...(network === 'development' && { + ...getDevelopmentConfig() + }) + } + return ( - - - {element} - + + + + {element} + + ) } diff --git a/src/providers/ApolloClientProvider.tsx b/src/providers/ApolloClientProvider.tsx new file mode 100644 index 000000000..a3bfcb2ac --- /dev/null +++ b/src/providers/ApolloClientProvider.tsx @@ -0,0 +1,53 @@ +import { + ApolloClient, + ApolloProvider, + HttpLink, + InMemoryCache, + NormalizedCacheObject +} from '@apollo/client' +import { Logger } from '@oceanprotocol/lib' +import { ConfigHelperConfig } from '@oceanprotocol/lib/dist/node/utils/ConfigHelper' +import { useOcean } from '@oceanprotocol/react' +import fetch from 'cross-fetch' +import React, { useState, useEffect, ReactNode, ReactElement } from 'react' + +function createClient(subgraphUri: string) { + const client = new ApolloClient({ + link: new HttpLink({ + uri: `${subgraphUri}/subgraphs/name/oceanprotocol/ocean-subgraph`, + fetch + }), + cache: new InMemoryCache() + }) + + return client +} + +export default function ApolloClientProvider({ + children +}: { + children: ReactNode +}): ReactElement { + const { config } = useOcean() + const [client, setClient] = useState>() + + useEffect(() => { + if (!(config as ConfigHelperConfig)?.subgraphUri) { + Logger.error( + 'No subgraphUri defined, preventing ApolloProvider from initialization.' + ) + return + } + + const newClient = createClient((config as ConfigHelperConfig).subgraphUri) + setClient(newClient) + }, [config]) + + return client ? ( + {children} + ) : ( + <> + ) +} + +export { ApolloClientProvider }