1
0
mirror of https://github.com/oceanprotocol/market.git synced 2024-12-02 05:57:29 +01:00

merge all the pool data subgraph queries into one

This commit is contained in:
Matthias Kretschmann 2022-01-25 15:30:56 +00:00
parent 1e24972aa7
commit 1e54a9d573
Signed by: m
GPG Key ID: 606EEEF3C479A91F
4 changed files with 55 additions and 137 deletions

View File

@ -25,7 +25,7 @@ import {
} from '../@types/subgraph/PoolShares' } from '../@types/subgraph/PoolShares'
import { OrdersData_orders as OrdersData } from '../@types/subgraph/OrdersData' import { OrdersData_orders as OrdersData } from '../@types/subgraph/OrdersData'
import { UserSalesQuery as UsersSalesList } from '../@types/subgraph/UserSalesQuery' import { UserSalesQuery as UsersSalesList } from '../@types/subgraph/UserSalesQuery'
import { PoolLiquidity } from 'src/@types/subgraph/PoolLiquidity' import { PoolData } from 'src/@types/subgraph/PoolData'
export interface UserLiquidity { export interface UserLiquidity {
price: string price: string
@ -285,9 +285,9 @@ const TopSalesQuery = gql`
} }
` `
const poolLiquidityQuery = gql` const poolDataQuery = gql`
query PoolLiquidity($pool: ID!, $owner: String!) { query PoolData($pool: ID!, $owner: String!, $user: String) {
pool(id: $pool) { poolData: pool(id: $pool) {
id id
totalShares totalShares
poolFee poolFee
@ -310,16 +310,20 @@ const poolLiquidityQuery = gql`
shares shares
} }
} }
}
`
const userPoolShareQuery = gql` poolDataUser: pool(id: $pool) {
query PoolShare($pool: ID!, $user: String!) {
pool(id: $pool) {
shares(where: { user: $user }) { shares(where: { user: $user }) {
shares shares
} }
} }
poolSnapshots(first: 1000, where: { pool: $pool }, orderBy: date) {
date
spotPrice
baseTokenLiquidity
datatokenLiquidity
swapVolume
}
} }
` `
@ -822,33 +826,19 @@ export async function getTopAssetsPublishers(
export async function getPoolData( export async function getPoolData(
chainId: number, chainId: number,
pool: string, pool: string,
owner: string owner: string,
user: string
) { ) {
const queryVariables = { const queryVariables = {
pool: pool.toLowerCase(), pool: pool.toLowerCase(),
owner: owner.toLowerCase() owner: owner.toLowerCase(),
user: user.toLowerCase()
} }
const response: OperationResult<PoolLiquidity> = await fetchData(
poolLiquidityQuery,
queryVariables,
getQueryContext(chainId)
)
return response?.data?.pool
}
export async function getUserPoolShareBalance( const response: OperationResult<PoolData> = await fetchData(
chainId: number, poolDataQuery,
pool: string,
accountId: string
): Promise<string> {
const queryVariables = {
pool: pool.toLowerCase(),
user: accountId.toLowerCase()
}
const response: OperationResult<PoolLiquidity> = await fetchData(
userPoolShareQuery,
queryVariables, queryVariables,
getQueryContext(chainId) getQueryContext(chainId)
) )
return response?.data?.pool?.shares[0]?.shares || '0' return response?.data
} }

View File

@ -12,24 +12,11 @@ import {
TooltipOptions, TooltipOptions,
defaults defaults
} from 'chart.js' } from 'chart.js'
import { gql } from 'urql'
export declare type GraphType = 'liquidity' | 'price' | 'volume' export declare type GraphType = 'liquidity' | 'price' | 'volume'
export const graphTypes = ['Liquidity', 'Price', 'Volume'] export const graphTypes = ['Liquidity', 'Price', 'Volume']
export const poolHistoryQuery = gql`
query PoolHistory($id: String!) {
poolSnapshots(first: 1000, where: { pool: $id }, orderBy: date) {
date
spotPrice
baseTokenLiquidity
datatokenLiquidity
swapVolume
}
}
`
// Chart.js global defaults // Chart.js global defaults
ChartJS.register( ChartJS.register(
LineElement, LineElement,

View File

@ -1,71 +1,29 @@
import React, { ReactElement, useCallback, useEffect, useState } from 'react' import React, { ReactElement, useEffect, useState } from 'react'
import { ChartData, ChartOptions } from 'chart.js' import { ChartData, ChartOptions } from 'chart.js'
import { Bar, Chart, Line } from 'react-chartjs-2' import { Bar, Line } from 'react-chartjs-2'
import Loader from '@shared/atoms/Loader' import Loader from '@shared/atoms/Loader'
import { useUserPreferences } from '@context/UserPreferences' import { useUserPreferences } from '@context/UserPreferences'
import useDarkMode from 'use-dark-mode' import useDarkMode from 'use-dark-mode'
import { darkModeConfig } from '../../../../../../app.config' import { darkModeConfig } from '../../../../../../app.config'
import { LoggerInstance } from '@oceanprotocol/lib' import { LoggerInstance } from '@oceanprotocol/lib'
import { useAsset } from '@context/Asset'
import { OperationResult } from 'urql'
import { PoolHistory } from '../../../../../@types/subgraph/PoolHistory'
import { fetchData, getQueryContext } from '@utils/subgraph'
import styles from './index.module.css' import styles from './index.module.css'
import Decimal from 'decimal.js' import Decimal from 'decimal.js'
import { poolHistoryQuery, lineStyle, GraphType } from './_constants' import { lineStyle, GraphType } from './_constants'
import Nav from './Nav' import Nav from './Nav'
import { getOptions } from './_utils' import { getOptions } from './_utils'
import { PoolData_poolSnapshots as PoolDataPoolSnapshots } from 'src/@types/subgraph/PoolData'
export default function Graph(): ReactElement { export default function Graph({
poolSnapshots
}: {
poolSnapshots: PoolDataPoolSnapshots[]
}): ReactElement {
const { locale } = useUserPreferences() const { locale } = useUserPreferences()
const { price, ddo, refreshInterval } = useAsset()
const darkMode = useDarkMode(false, darkModeConfig) const darkMode = useDarkMode(false, darkModeConfig)
const [options, setOptions] = useState<ChartOptions<any>>() const [options, setOptions] = useState<ChartOptions<any>>()
const [graphType, setGraphType] = useState<GraphType>('liquidity') const [graphType, setGraphType] = useState<GraphType>('liquidity')
const [error, setError] = useState<Error>()
const [isLoading, setIsLoading] = useState(true)
const [dataHistory, setDataHistory] = useState<PoolHistory>()
const [graphData, setGraphData] = useState<ChartData<any>>() const [graphData, setGraphData] = useState<ChartData<any>>()
const [graphFetchInterval, setGraphFetchInterval] = useState<NodeJS.Timeout>()
// Helper: fetch pool snapshots data
const fetchPoolHistory = useCallback(async () => {
try {
const queryResult: OperationResult<PoolHistory> = await fetchData(
poolHistoryQuery,
{ id: price.address.toLowerCase() },
getQueryContext(ddo.chainId)
)
setDataHistory(queryResult?.data)
setIsLoading(false)
LoggerInstance.log(
`[pool graph] Fetched pool snapshots:`,
queryResult?.data
)
} catch (error) {
LoggerInstance.error('[pool graph] Error fetchData: ', error.message)
setError(error)
}
}, [ddo?.chainId, price?.address])
// Helper: start interval fetching
const initFetchInterval = useCallback(() => {
if (graphFetchInterval) return
const newInterval = setInterval(() => {
fetchPoolHistory()
LoggerInstance.log(
`[pool graph] Refetch interval fired after ${refreshInterval / 1000}s`
)
}, refreshInterval)
setGraphFetchInterval(newInterval)
}, [fetchPoolHistory, graphFetchInterval, refreshInterval])
useEffect(() => {
return () => clearInterval(graphFetchInterval)
}, [graphFetchInterval])
// //
// 0 Get Graph options // 0 Get Graph options
@ -77,38 +35,28 @@ export default function Graph(): ReactElement {
}, [locale, darkMode.value, graphType]) }, [locale, darkMode.value, graphType])
// //
// 1 Fetch all the data on mount // 1 Data manipulation
// All further effects depend on the fetched data
// and only do further data checking and manipulation.
// //
useEffect(() => { useEffect(() => {
fetchPoolHistory() if (!poolSnapshots) return
initFetchInterval()
}, [fetchPoolHistory, initFetchInterval])
// const timestamps = poolSnapshots.map((item) => {
// 2 Data manipulation
//
useEffect(() => {
if (!dataHistory?.poolSnapshots) return
const timestamps = dataHistory.poolSnapshots.map((item) => {
const date = new Date(item.date * 1000) const date = new Date(item.date * 1000)
return `${date.toLocaleDateString()} ${date.toLocaleTimeString()}` return `${date.toLocaleDateString()} ${date.toLocaleTimeString()}`
}) })
let baseTokenLiquidityCumulative = '0' let baseTokenLiquidityCumulative = '0'
const liquidityHistory = dataHistory.poolSnapshots.map((item) => { const liquidityHistory = poolSnapshots.map((item) => {
baseTokenLiquidityCumulative = new Decimal(baseTokenLiquidityCumulative) baseTokenLiquidityCumulative = new Decimal(baseTokenLiquidityCumulative)
.add(item.baseTokenLiquidity) .add(item.baseTokenLiquidity)
.toString() .toString()
return baseTokenLiquidityCumulative return baseTokenLiquidityCumulative
}) })
const priceHistory = dataHistory.poolSnapshots.map((item) => item.spotPrice) const priceHistory = poolSnapshots.map((item) => item.spotPrice)
let volumeCumulative = '0' let volumeCumulative = '0'
const volumeHistory = dataHistory.poolSnapshots.map((item) => { const volumeHistory = poolSnapshots.map((item) => {
volumeCumulative = new Decimal(volumeCumulative) volumeCumulative = new Decimal(volumeCumulative)
.add(item.swapVolume) .add(item.swapVolume)
.toString() .toString()
@ -133,15 +81,13 @@ export default function Graph(): ReactElement {
datasets: [{ ...lineStyle, data, borderColor: `#8b98a9` }] datasets: [{ ...lineStyle, data, borderColor: `#8b98a9` }]
} }
setGraphData(newGraphData) setGraphData(newGraphData)
LoggerInstance.log('[pool graph] New graph data:', newGraphData) LoggerInstance.log('[pool graph] New graph data created:', newGraphData)
}, [dataHistory?.poolSnapshots, graphType]) }, [poolSnapshots, graphType])
return ( return (
<div className={styles.graphWrap}> <div className={styles.graphWrap}>
{isLoading ? ( {!graphData ? (
<Loader /> <Loader />
) : error ? (
<small>{error.message}</small>
) : ( ) : (
<> <>
<Nav graphType={graphType} setGraphType={setGraphType} /> <Nav graphType={graphType} setGraphType={setGraphType} />

View File

@ -19,7 +19,8 @@ import PoolTransactions from '@shared/PoolTransactions'
import { isValidNumber } from '@utils/numbers' import { isValidNumber } from '@utils/numbers'
import Decimal from 'decimal.js' import Decimal from 'decimal.js'
import content from '../../../../../content/price.json' import content from '../../../../../content/price.json'
import { getPoolData, getUserPoolShareBalance } from '@utils/subgraph' import { getPoolData } from '@utils/subgraph'
import { PoolData_poolSnapshots as PoolDataPoolSnapshots } from 'src/@types/subgraph/PoolData'
Decimal.set({ toExpNeg: -18, precision: 18, rounding: 1 }) Decimal.set({ toExpNeg: -18, precision: 18, rounding: 1 })
@ -70,6 +71,7 @@ export default function Pool(): ReactElement {
const [poolInfoUser, setPoolInfoUser] = useState<PoolInfoUser>( const [poolInfoUser, setPoolInfoUser] = useState<PoolInfoUser>(
initialPoolInfoUser as PoolInfoUser initialPoolInfoUser as PoolInfoUser
) )
const [poolSnapshots, setPoolSnapshots] = useState<PoolDataPoolSnapshots[]>()
const [hasUserAddedLiquidity, setUserHasAddedLiquidity] = useState(false) const [hasUserAddedLiquidity, setUserHasAddedLiquidity] = useState(false)
const [showAdd, setShowAdd] = useState(false) const [showAdd, setShowAdd] = useState(false)
@ -77,34 +79,27 @@ export default function Pool(): ReactElement {
const [isRemoveDisabled, setIsRemoveDisabled] = useState(false) const [isRemoveDisabled, setIsRemoveDisabled] = useState(false)
const [fetchInterval, setFetchInterval] = useState<NodeJS.Timeout>() const [fetchInterval, setFetchInterval] = useState<NodeJS.Timeout>()
const fetchPoolData = useCallback(async () => { const fetchAllData = useCallback(async () => {
if (!ddo?.chainId || !price?.address || !owner) return if (!ddo?.chainId || !price?.address || !owner) return
const poolData = await getPoolData(ddo.chainId, price.address, owner) const response = await getPoolData(
setPoolData(poolData)
LoggerInstance.log('[pool] Fetched pool data:', poolData)
}, [ddo?.chainId, price?.address, owner])
const fetchUserShares = useCallback(async () => {
if (!ddo?.chainId || !price?.address || !accountId) return
const userShares = await getUserPoolShareBalance(
ddo.chainId, ddo.chainId,
price.address, price.address,
accountId owner,
accountId || ''
) )
if (!response) return
setPoolData(response.poolData)
setPoolInfoUser((prevState) => ({ setPoolInfoUser((prevState) => ({
...prevState, ...prevState,
poolShares: userShares poolShares: response.poolDataUser?.shares[0]?.shares
})) }))
LoggerInstance.log(`[pool] Fetched user shares: ${userShares}`) setPoolSnapshots(response.poolSnapshots)
}, [ddo?.chainId, price?.address, accountId]) LoggerInstance.log('[pool] Fetched pool data:', response.poolData)
LoggerInstance.log('[pool] Fetched user data:', response.poolDataUser)
// Helper: fetch everything LoggerInstance.log('[pool] Fetched pool snapshots:', response.poolSnapshots)
const fetchAllData = useCallback(() => { }, [ddo?.chainId, price?.address, owner, accountId])
fetchPoolData()
fetchUserShares()
}, [fetchPoolData, fetchUserShares])
// Helper: start interval fetching // Helper: start interval fetching
const initFetchInterval = useCallback(() => { const initFetchInterval = useCallback(() => {
@ -443,7 +438,7 @@ export default function Pool(): ReactElement {
{poolInfo?.weightBaseToken}/{poolInfo?.weightDt} {poolInfo?.weightBaseToken}/{poolInfo?.weightDt}
</span> </span>
)} )}
<Graph /> <Graph poolSnapshots={poolSnapshots} />
</> </>
} }
baseTokenValue={`${price?.ocean}`} baseTokenValue={`${price?.ocean}`}