mirror of
https://github.com/oceanprotocol/market.git
synced 2024-12-02 05:57:29 +01:00
Liquidity & price history graph (#248)
* graph prototype * switch items * liquidity history graph prototype * more graph styling * epoch times conversion * get data in root component * redraw fix * more graph styling * loading fix * re-render fixes * re-render fixes * new Aquarius responses * price graph and switch buttons * spacing tweaks
This commit is contained in:
parent
f8a0ff41c3
commit
461fcaf8ae
44
package-lock.json
generated
44
package-lock.json
generated
@ -5333,6 +5333,15 @@
|
|||||||
"@types/responselike": "*"
|
"@types/responselike": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/chart.js": {
|
||||||
|
"version": "2.9.27",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/chart.js/-/chart.js-2.9.27.tgz",
|
||||||
|
"integrity": "sha512-b3ho2RpPLWzLzOXKkFwpvlRDEVWQrCknu2/p90mLY5v2DO8owk0OwWkv4MqAC91kJL52bQGXkVw/De+N/0/1+A==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"moment": "^2.10.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/classnames": {
|
"@types/classnames": {
|
||||||
"version": "2.2.11",
|
"version": "2.2.11",
|
||||||
"resolved": "https://registry.npmjs.org/@types/classnames/-/classnames-2.2.11.tgz",
|
"resolved": "https://registry.npmjs.org/@types/classnames/-/classnames-2.2.11.tgz",
|
||||||
@ -10398,6 +10407,32 @@
|
|||||||
"resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
|
||||||
"integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA=="
|
"integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA=="
|
||||||
},
|
},
|
||||||
|
"chart.js": {
|
||||||
|
"version": "2.9.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/chart.js/-/chart.js-2.9.4.tgz",
|
||||||
|
"integrity": "sha512-B07aAzxcrikjAPyV+01j7BmOpxtQETxTSlQ26BEYJ+3iUkbNKaOJ/nDbT6JjyqYxseM0ON12COHYdU2cTIjC7A==",
|
||||||
|
"requires": {
|
||||||
|
"chartjs-color": "^2.1.0",
|
||||||
|
"moment": "^2.10.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"chartjs-color": {
|
||||||
|
"version": "2.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/chartjs-color/-/chartjs-color-2.4.1.tgz",
|
||||||
|
"integrity": "sha512-haqOg1+Yebys/Ts/9bLo/BqUcONQOdr/hoEr2LLTRl6C5LXctUdHxsCYfvQVg5JIxITrfCNUDr4ntqmQk9+/0w==",
|
||||||
|
"requires": {
|
||||||
|
"chartjs-color-string": "^0.6.0",
|
||||||
|
"color-convert": "^1.9.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"chartjs-color-string": {
|
||||||
|
"version": "0.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/chartjs-color-string/-/chartjs-color-string-0.6.0.tgz",
|
||||||
|
"integrity": "sha512-TIB5OKn1hPJvO7JcteW4WY/63v6KwEdt6udfnDE9iCAZgy+V4SrbSxoIbTw/xkUIapjEI4ExGtD0+6D3KyFd7A==",
|
||||||
|
"requires": {
|
||||||
|
"color-name": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"checkpoint-store": {
|
"checkpoint-store": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/checkpoint-store/-/checkpoint-store-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/checkpoint-store/-/checkpoint-store-1.1.0.tgz",
|
||||||
@ -27540,6 +27575,15 @@
|
|||||||
"vanilla-swipe": "^2.2.0"
|
"vanilla-swipe": "^2.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"react-chartjs-2": {
|
||||||
|
"version": "2.11.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-2.11.1.tgz",
|
||||||
|
"integrity": "sha512-G7cNq/n2Bkh/v4vcI+GKx7Q1xwZexKYhOSj2HmrFXlvNeaURWXun6KlOUpEQwi1cv9Tgs4H3kGywDWMrX2kxfA==",
|
||||||
|
"requires": {
|
||||||
|
"lodash": "^4.17.19",
|
||||||
|
"prop-types": "^15.7.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"react-color": {
|
"react-color": {
|
||||||
"version": "2.19.3",
|
"version": "2.19.3",
|
||||||
"resolved": "https://registry.npmjs.org/react-color/-/react-color-2.19.3.tgz",
|
"resolved": "https://registry.npmjs.org/react-color/-/react-color-2.19.3.tgz",
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
"@vercel/node": "^1.8.4",
|
"@vercel/node": "^1.8.4",
|
||||||
"@walletconnect/web3-provider": "^1.3.1",
|
"@walletconnect/web3-provider": "^1.3.1",
|
||||||
"axios": "^0.21.0",
|
"axios": "^0.21.0",
|
||||||
|
"chart.js": "^2.9.4",
|
||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
"date-fns": "^2.16.1",
|
"date-fns": "^2.16.1",
|
||||||
"decimal.js": "^10.2.1",
|
"decimal.js": "^10.2.1",
|
||||||
@ -66,6 +67,7 @@
|
|||||||
"query-string": "^6.13.7",
|
"query-string": "^6.13.7",
|
||||||
"react": "^17.0.1",
|
"react": "^17.0.1",
|
||||||
"react-alice-carousel": "^2.0.2",
|
"react-alice-carousel": "^2.0.2",
|
||||||
|
"react-chartjs-2": "^2.11.1",
|
||||||
"react-data-table-component": "^6.11.5",
|
"react-data-table-component": "^6.11.5",
|
||||||
"react-datepicker": "^3.3.0",
|
"react-datepicker": "^3.3.0",
|
||||||
"react-dom": "^17.0.1",
|
"react-dom": "^17.0.1",
|
||||||
@ -95,6 +97,7 @@
|
|||||||
"@svgr/webpack": "^5.4.0",
|
"@svgr/webpack": "^5.4.0",
|
||||||
"@testing-library/jest-dom": "^5.11.5",
|
"@testing-library/jest-dom": "^5.11.5",
|
||||||
"@testing-library/react": "^11.1.1",
|
"@testing-library/react": "^11.1.1",
|
||||||
|
"@types/chart.js": "^2.9.27",
|
||||||
"@types/jest": "^26.0.15",
|
"@types/jest": "^26.0.15",
|
||||||
"@types/loadable__component": "^5.13.1",
|
"@types/loadable__component": "^5.13.1",
|
||||||
"@types/lodash.debounce": "^4.0.3",
|
"@types/lodash.debounce": "^4.0.3",
|
||||||
|
@ -8,6 +8,15 @@ import Badge from '../Badge'
|
|||||||
|
|
||||||
const cx = classNames.bind(styles)
|
const cx = classNames.bind(styles)
|
||||||
|
|
||||||
|
export function formatPrice(price: string, locale: string): string {
|
||||||
|
return formatCurrency(Number(price), '', locale, false, {
|
||||||
|
// Not exactly clear what `significant figures` are for this library,
|
||||||
|
// but setting this seems to give us the formatting we want.
|
||||||
|
// See https://github.com/oceanprotocol/market/issues/70
|
||||||
|
significantFigures: 4
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
export default function PriceUnit({
|
export default function PriceUnit({
|
||||||
price,
|
price,
|
||||||
className,
|
className,
|
||||||
@ -34,14 +43,7 @@ export default function PriceUnit({
|
|||||||
return (
|
return (
|
||||||
<div className={styleClasses}>
|
<div className={styleClasses}>
|
||||||
<div>
|
<div>
|
||||||
{Number.isNaN(Number(price))
|
{Number.isNaN(Number(price)) ? '-' : formatPrice(price, locale)}{' '}
|
||||||
? '-'
|
|
||||||
: formatCurrency(Number(price), '', locale, false, {
|
|
||||||
// Not exactly clear what `significant figures` are for this library,
|
|
||||||
// but setting this seems to give us the formatting we want.
|
|
||||||
// See https://github.com/oceanprotocol/market/issues/70
|
|
||||||
significantFigures: 4
|
|
||||||
})}{' '}
|
|
||||||
<span className={styles.symbol}>{symbol || 'OCEAN'}</span>
|
<span className={styles.symbol}>{symbol || 'OCEAN'}</span>
|
||||||
{type && type === 'pool' && (
|
{type && type === 'pool' && (
|
||||||
<Badge label="pool" className={styles.badge} />
|
<Badge label="pool" className={styles.badge} />
|
||||||
|
37
src/components/organisms/AssetActions/Pool/Graph.module.css
Normal file
37
src/components/organisms/AssetActions/Pool/Graph.module.css
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
.graphWrap {
|
||||||
|
min-height: 97px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin: calc(var(--spacer) / 6) -2rem calc(var(--spacer) / 1.5) -2rem;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.graphWrap canvas {
|
||||||
|
position: relative;
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.type {
|
||||||
|
position: absolute;
|
||||||
|
bottom: -10px;
|
||||||
|
z-index: 1;
|
||||||
|
text-align: center;
|
||||||
|
padding: 5px var(--spacer);
|
||||||
|
}
|
||||||
|
|
||||||
|
.button,
|
||||||
|
.button:hover {
|
||||||
|
display: inline-block;
|
||||||
|
color: var(--color-secondary);
|
||||||
|
font-size: var(--font-size-mini);
|
||||||
|
border: 1px solid transparent;
|
||||||
|
border-radius: var(--border-radius);
|
||||||
|
padding: calc(var(--spacer) / 16) calc(var(--spacer) / 4) !important;
|
||||||
|
transform: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button.active {
|
||||||
|
color: var(--font-color-text);
|
||||||
|
border-color: var(--border-color);
|
||||||
|
}
|
184
src/components/organisms/AssetActions/Pool/Graph.tsx
Normal file
184
src/components/organisms/AssetActions/Pool/Graph.tsx
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
import React, { ChangeEvent, ReactElement, useEffect, useState } from 'react'
|
||||||
|
import { Line, defaults } from 'react-chartjs-2'
|
||||||
|
import {
|
||||||
|
ChartData,
|
||||||
|
ChartDataSets,
|
||||||
|
ChartOptions,
|
||||||
|
ChartTooltipItem,
|
||||||
|
ChartTooltipOptions
|
||||||
|
} from 'chart.js'
|
||||||
|
import styles from './Graph.module.css'
|
||||||
|
import Loader from '../../../atoms/Loader'
|
||||||
|
import { formatPrice } from '../../../atoms/Price/PriceUnit'
|
||||||
|
import { useUserPreferences } from '../../../../providers/UserPreferences'
|
||||||
|
import useDarkMode from 'use-dark-mode'
|
||||||
|
import { darkModeConfig } from '../../../../../app.config'
|
||||||
|
import Button from '../../../atoms/Button'
|
||||||
|
import { Logger } from '@oceanprotocol/lib'
|
||||||
|
|
||||||
|
export interface ChartDataLiqudity {
|
||||||
|
oceanAddRemove: ChartData[]
|
||||||
|
datatokenAddRemove: ChartData[]
|
||||||
|
oceanReserveHistory: ChartData[]
|
||||||
|
datatokenReserveHistory: ChartData[]
|
||||||
|
datatokenPriceHistory: ChartData[]
|
||||||
|
}
|
||||||
|
|
||||||
|
declare type GraphType = 'liquidity' | 'price'
|
||||||
|
|
||||||
|
// Chart.js global defaults
|
||||||
|
defaults.global.defaultFontFamily = `'Sharp Sans', -apple-system, BlinkMacSystemFont,
|
||||||
|
'Segoe UI', Helvetica, Arial, sans-serif`
|
||||||
|
defaults.global.animation = { easing: 'easeInOutQuart', duration: 800 }
|
||||||
|
|
||||||
|
const lineStyle: Partial<ChartDataSets> = {
|
||||||
|
fill: false,
|
||||||
|
lineTension: 0.1,
|
||||||
|
borderWidth: 2,
|
||||||
|
pointBorderWidth: 0,
|
||||||
|
pointRadius: 0,
|
||||||
|
pointHoverRadius: 4,
|
||||||
|
pointHoverBorderWidth: 0,
|
||||||
|
pointHitRadius: 2,
|
||||||
|
pointHoverBackgroundColor: '#ff4092'
|
||||||
|
}
|
||||||
|
|
||||||
|
const tooltipOptions: Partial<ChartTooltipOptions> = {
|
||||||
|
intersect: false,
|
||||||
|
titleFontStyle: 'normal',
|
||||||
|
titleFontSize: 10,
|
||||||
|
bodyFontSize: 12,
|
||||||
|
bodyFontStyle: 'bold',
|
||||||
|
displayColors: false,
|
||||||
|
xPadding: 10,
|
||||||
|
yPadding: 10,
|
||||||
|
cornerRadius: 3,
|
||||||
|
borderWidth: 1,
|
||||||
|
caretSize: 7
|
||||||
|
}
|
||||||
|
|
||||||
|
function constructGraphData(data: ChartData[]): ChartData {
|
||||||
|
const timestamps = data.map((item: any) => {
|
||||||
|
// convert timestamps from epoch to locale date & time string
|
||||||
|
const date = new Date(item[1] * 1000)
|
||||||
|
return `${date.toLocaleDateString()} ${date.toLocaleTimeString()}`
|
||||||
|
})
|
||||||
|
const values = data.map((item: any) => item[0])
|
||||||
|
|
||||||
|
return {
|
||||||
|
labels: timestamps,
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
...lineStyle,
|
||||||
|
label: 'Liquidity (OCEAN)',
|
||||||
|
data: values,
|
||||||
|
borderColor: `#8b98a9`,
|
||||||
|
pointBackgroundColor: `#8b98a9`
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getOptions(locale: string, isDarkMode: boolean): ChartOptions {
|
||||||
|
return {
|
||||||
|
layout: {
|
||||||
|
padding: {
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
top: 0,
|
||||||
|
bottom: 10
|
||||||
|
}
|
||||||
|
},
|
||||||
|
tooltips: {
|
||||||
|
...tooltipOptions,
|
||||||
|
backgroundColor: isDarkMode ? `#141414` : `#fff`,
|
||||||
|
titleFontColor: isDarkMode ? `#e2e2e2` : `#303030`,
|
||||||
|
bodyFontColor: isDarkMode ? `#fff` : `#141414`,
|
||||||
|
borderColor: isDarkMode ? `#41474e` : `#e2e2e2`,
|
||||||
|
callbacks: {
|
||||||
|
label: (tooltipItem: ChartTooltipItem) =>
|
||||||
|
`${formatPrice(`${tooltipItem.yLabel}`, locale)} OCEAN`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
display: false
|
||||||
|
},
|
||||||
|
scales: {
|
||||||
|
yAxes: [
|
||||||
|
{
|
||||||
|
display: false
|
||||||
|
// gridLines: {
|
||||||
|
// drawBorder: false,
|
||||||
|
// color: isDarkMode ? '#303030' : '#e2e2e2',
|
||||||
|
// zeroLineColor: isDarkMode ? '#303030' : '#e2e2e2'
|
||||||
|
// },
|
||||||
|
// ticks: { display: false }
|
||||||
|
}
|
||||||
|
],
|
||||||
|
xAxes: [{ display: false, gridLines: { display: true } }]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const graphTypes = ['Liquidity', 'Price']
|
||||||
|
|
||||||
|
export default function Graph({
|
||||||
|
data
|
||||||
|
}: {
|
||||||
|
data: ChartDataLiqudity
|
||||||
|
}): ReactElement {
|
||||||
|
const { locale } = useUserPreferences()
|
||||||
|
const darkMode = useDarkMode(false, darkModeConfig)
|
||||||
|
|
||||||
|
const [graphData, setGraphData] = useState<ChartData>()
|
||||||
|
const [options, setOptions] = useState<ChartOptions>()
|
||||||
|
const [graphType, setGraphType] = useState<GraphType>('liquidity')
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
Logger.log('Fired GraphOptions!')
|
||||||
|
const options = getOptions(locale, darkMode.value)
|
||||||
|
setOptions(options)
|
||||||
|
}, [locale, darkMode.value])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!data) return
|
||||||
|
Logger.log('Fired GraphData!')
|
||||||
|
const graphData =
|
||||||
|
graphType === 'liquidity'
|
||||||
|
? constructGraphData(data.oceanReserveHistory)
|
||||||
|
: constructGraphData(data.datatokenPriceHistory)
|
||||||
|
setGraphData(graphData)
|
||||||
|
}, [data, graphType])
|
||||||
|
|
||||||
|
function handleGraphTypeSwitch(e: ChangeEvent<HTMLButtonElement>) {
|
||||||
|
e.preventDefault()
|
||||||
|
setGraphType(e.currentTarget.textContent.toLowerCase() as GraphType)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.graphWrap}>
|
||||||
|
{graphData ? (
|
||||||
|
<>
|
||||||
|
<nav className={styles.type}>
|
||||||
|
{graphTypes.map((type: GraphType) => (
|
||||||
|
<Button
|
||||||
|
key={type}
|
||||||
|
style="text"
|
||||||
|
size="small"
|
||||||
|
onClick={handleGraphTypeSwitch}
|
||||||
|
className={`${styles.button} ${
|
||||||
|
graphType === type.toLowerCase() ? styles.active : null
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{type}
|
||||||
|
</Button>
|
||||||
|
))}
|
||||||
|
</nav>
|
||||||
|
<Line height={70} data={graphData} options={options} />
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<Loader />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
@ -18,6 +18,8 @@ import Token from './Token'
|
|||||||
import TokenList from './TokenList'
|
import TokenList from './TokenList'
|
||||||
import { graphql, useStaticQuery } from 'gatsby'
|
import { graphql, useStaticQuery } from 'gatsby'
|
||||||
import Transactions from './Transactions'
|
import Transactions from './Transactions'
|
||||||
|
import Graph, { ChartDataLiqudity } from './Graph'
|
||||||
|
import axios from 'axios'
|
||||||
|
|
||||||
export interface Balance {
|
export interface Balance {
|
||||||
ocean: number
|
ocean: number
|
||||||
@ -49,7 +51,7 @@ export default function Pool({ ddo }: { ddo: DDO }): ReactElement {
|
|||||||
const data = useStaticQuery(contentQuery)
|
const data = useStaticQuery(contentQuery)
|
||||||
const content = data.content.edges[0].node.childContentJson.pool
|
const content = data.content.edges[0].node.childContentJson.pool
|
||||||
|
|
||||||
const { ocean, accountId, networkId } = useOcean()
|
const { ocean, accountId, networkId, config } = useOcean()
|
||||||
const { price, refreshPrice, owner } = useMetadata(ddo)
|
const { price, refreshPrice, owner } = useMetadata(ddo)
|
||||||
const { dtSymbol } = usePricing(ddo)
|
const { dtSymbol } = usePricing(ddo)
|
||||||
const { isInPurgatory } = useAsset()
|
const { isInPurgatory } = useAsset()
|
||||||
@ -77,6 +79,8 @@ export default function Pool({ ddo }: { ddo: DDO }): ReactElement {
|
|||||||
const [creatorLiquidity, setCreatorLiquidity] = useState<Balance>()
|
const [creatorLiquidity, setCreatorLiquidity] = useState<Balance>()
|
||||||
const [creatorPoolTokens, setCreatorPoolTokens] = useState<string>()
|
const [creatorPoolTokens, setCreatorPoolTokens] = useState<string>()
|
||||||
const [creatorPoolShare, setCreatorPoolShare] = useState<string>()
|
const [creatorPoolShare, setCreatorPoolShare] = useState<string>()
|
||||||
|
const [graphData, setGraphData] = useState<ChartDataLiqudity>()
|
||||||
|
|
||||||
// the purpose of the value is just to trigger the effect
|
// the purpose of the value is just to trigger the effect
|
||||||
const [refreshPool, setRefreshPool] = useState(false)
|
const [refreshPool, setRefreshPool] = useState(false)
|
||||||
|
|
||||||
@ -195,6 +199,34 @@ export default function Pool({ ddo }: { ddo: DDO }): ReactElement {
|
|||||||
return () => clearInterval(interval)
|
return () => clearInterval(interval)
|
||||||
}, [ocean, accountId, price, ddo, refreshPool, owner])
|
}, [ocean, accountId, price, ddo, refreshPool, owner])
|
||||||
|
|
||||||
|
// Get graph history data
|
||||||
|
useEffect(() => {
|
||||||
|
if (!price?.address || !price?.ocean || !price?.value) return
|
||||||
|
|
||||||
|
const source = axios.CancelToken.source()
|
||||||
|
const url = `${config.metadataCacheUri}/api/v1/aquarius/pools/history/${price.address}`
|
||||||
|
|
||||||
|
async function getData() {
|
||||||
|
Logger.log('Fired GetGraphData!')
|
||||||
|
try {
|
||||||
|
const response = await axios(url, { cancelToken: source.token })
|
||||||
|
if (!response || response.status !== 200) return
|
||||||
|
setGraphData(response.data)
|
||||||
|
} catch (error) {
|
||||||
|
if (axios.isCancel(error)) {
|
||||||
|
Logger.log(error.message)
|
||||||
|
} else {
|
||||||
|
Logger.error(error.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getData()
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
source.cancel()
|
||||||
|
}
|
||||||
|
}, [config.metadataCacheUri, price?.address, price?.ocean, price?.value])
|
||||||
|
|
||||||
const refreshInfo = async () => {
|
const refreshInfo = async () => {
|
||||||
setRefreshPool(!refreshPool)
|
setRefreshPool(!refreshPool)
|
||||||
await refreshPrice()
|
await refreshPrice()
|
||||||
@ -284,6 +316,7 @@ export default function Pool({ ddo }: { ddo: DDO }): ReactElement {
|
|||||||
{weightOcean}/{weightDt}
|
{weightOcean}/{weightDt}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
|
<Graph data={graphData} />
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
ocean={`${price?.ocean}`}
|
ocean={`${price?.ocean}`}
|
||||||
|
Loading…
Reference in New Issue
Block a user