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

215 lines
6.3 KiB
TypeScript

import React, { ReactElement, useEffect, useState } from 'react'
import { useOcean, useMetadata, usePricing } from '@oceanprotocol/react'
import { DDO, Logger } from '@oceanprotocol/lib'
import styles from './index.module.css'
import stylesActions from './Actions.module.css'
import PriceUnit from '../../../atoms/Price/PriceUnit'
import Loader from '../../../atoms/Loader'
import Button from '../../../atoms/Button'
import Add from './Add'
import Remove from './Remove'
import Tooltip from '../../../atoms/Tooltip'
import Conversion from '../../../atoms/Price/Conversion'
import EtherscanLink from '../../../atoms/EtherscanLink'
import Token from './Token'
import TokenList from './TokenList'
import { graphql, useStaticQuery } from 'gatsby'
export interface Balance {
ocean: number
datatoken: number
}
const contentQuery = graphql`
query PoolQuery {
content: allFile(filter: { relativePath: { eq: "price.json" } }) {
edges {
node {
childContentJson {
pool {
tooltips {
price
liquidity
}
}
}
}
}
}
}
`
export default function Pool({ ddo }: { ddo: DDO }): ReactElement {
const data = useStaticQuery(contentQuery)
const content = data.content.edges[0].node.childContentJson.pool
const { ocean, accountId } = useOcean()
const { price } = useMetadata(ddo)
const { dtSymbol } = usePricing(ddo)
const [poolTokens, setPoolTokens] = useState<string>()
const [totalPoolTokens, setTotalPoolTokens] = useState<string>()
const [userLiquidity, setUserLiquidity] = useState<Balance>()
const [swapFee, setSwapFee] = useState<string>()
const [showAdd, setShowAdd] = useState(false)
const [showRemove, setShowRemove] = useState(false)
const [isLoading, setIsLoading] = useState(true)
// TODO: put all these variables behind some useEffect
// to prevent unneccessary updating on every render
const hasAddedLiquidity =
userLiquidity && (userLiquidity.ocean > 0 || userLiquidity.datatoken > 0)
const poolShare =
price?.ocean &&
price?.datatoken &&
userLiquidity &&
((Number(poolTokens) / Number(totalPoolTokens)) * 100).toFixed(2)
const totalUserLiquidityInOcean =
userLiquidity?.ocean + userLiquidity?.datatoken * price?.value
const totalLiquidityInOcean = price?.ocean + price?.datatoken * price?.value
useEffect(() => {
if (!ocean || !accountId || !price || !price.value) return
async function init() {
setIsLoading(true)
try {
//
// Get everything which is in the pool
//
const totalPoolTokens = await ocean.pool.getPoolSharesTotalSupply(
price.address
)
setTotalPoolTokens(totalPoolTokens)
//
// Get everything the user has put into the pool
//
const poolTokens = await ocean.pool.sharesBalance(
accountId,
price.address
)
setPoolTokens(poolTokens)
// calculate user's provided liquidity based on pool tokens
const userOceanBalance =
(Number(poolTokens) / Number(totalPoolTokens)) * price.ocean
const userDtBalance =
(Number(poolTokens) / Number(totalPoolTokens)) * price.datatoken
const userLiquidity = {
ocean: userOceanBalance,
datatoken: userDtBalance
}
setUserLiquidity(userLiquidity)
// Get swap fee
// swapFee is tricky: to get 0.1% you need to convert from 0.001
const swapFee = await ocean.pool.getSwapFee(price.address)
setSwapFee(`${Number(swapFee) * 100}`)
} catch (error) {
Logger.error(error.message)
} finally {
setIsLoading(false)
}
}
init()
}, [ocean, accountId, price, ddo.dataToken])
return (
<>
{isLoading && !userLiquidity ? (
<Loader message="Retrieving pools..." />
) : showAdd ? (
<Add
setShowAdd={setShowAdd}
poolAddress={price.address}
totalPoolTokens={totalPoolTokens}
totalBalance={{ ocean: price.ocean, datatoken: price.datatoken }}
swapFee={swapFee}
dtSymbol={dtSymbol}
dtAddress={ddo.dataToken}
/>
) : showRemove ? (
<Remove
setShowRemove={setShowRemove}
poolAddress={price.address}
poolTokens={poolTokens}
dtSymbol={dtSymbol}
/>
) : (
<>
<div className={styles.dataToken}>
<PriceUnit price="1" symbol={dtSymbol} /> ={' '}
<PriceUnit price={`${price.value}`} />
<Conversion price={`${price.value}`} />
<Tooltip content={content.tooltips.price} />
<div className={styles.dataTokenLinks}>
<EtherscanLink
network="rinkeby"
path={`address/${price.address}`}
>
Pool
</EtherscanLink>
<EtherscanLink network="rinkeby" path={`token/${ddo.dataToken}`}>
Datatoken
</EtherscanLink>
</div>
</div>
<TokenList
title={
<>
Your Liquidity
<Tooltip content={content.tooltips.liquidity} />
</>
}
ocean={`${userLiquidity.ocean}`}
dt={`${userLiquidity.datatoken}`}
dtSymbol={dtSymbol}
poolShares={poolTokens}
conversion={totalUserLiquidityInOcean}
highlight
>
<Token symbol="% of pool" balance={poolShare} noIcon />
</TokenList>
<TokenList
title="Pool Statistics"
ocean={`${price.ocean}`}
dt={`${price.datatoken}`}
dtSymbol={dtSymbol}
poolShares={totalPoolTokens}
conversion={totalLiquidityInOcean}
>
<Token symbol="% swap fee" balance={swapFee} noIcon />
</TokenList>
<div className={stylesActions.actions}>
<Button
style="primary"
size="small"
onClick={() => setShowAdd(true)}
>
Add Liquidity
</Button>
{hasAddedLiquidity && (
<Button size="small" onClick={() => setShowRemove(true)}>
Remove
</Button>
)}
</div>
</>
)}
</>
)
}