mirror of
https://github.com/oceanprotocol/market.git
synced 2024-12-02 05:57:29 +01:00
Merge branch 'v4' of github.com:oceanprotocol/market into v4
This commit is contained in:
commit
d61f9c7940
16
content/footer.json
Normal file
16
content/footer.json
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"links": [
|
||||||
|
{
|
||||||
|
"name": "Docs",
|
||||||
|
"url": "https://docs.oceanprotocol.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "GitHub",
|
||||||
|
"url": "https://github.com/oceanprotocol"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Discord",
|
||||||
|
"url": "https://discord.gg/TnXjkR5"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -59,13 +59,7 @@ function PoolProvider({ children }: { children: ReactNode }): ReactElement {
|
|||||||
const [userPoolShares, setUserPoolShares] = useState('0')
|
const [userPoolShares, setUserPoolShares] = useState('0')
|
||||||
|
|
||||||
const fetchAllData = useCallback(async () => {
|
const fetchAllData = useCallback(async () => {
|
||||||
if (
|
if (!asset?.chainId || !asset?.accessDetails?.addressOrId || !owner) return
|
||||||
!accountId ||
|
|
||||||
!asset?.chainId ||
|
|
||||||
!asset?.accessDetails?.addressOrId ||
|
|
||||||
!owner
|
|
||||||
)
|
|
||||||
return
|
|
||||||
|
|
||||||
const response = await getPoolData(
|
const response = await getPoolData(
|
||||||
asset.chainId,
|
asset.chainId,
|
||||||
|
@ -65,9 +65,7 @@ export default function InputElement({
|
|||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
multiple={multiple}
|
multiple={multiple}
|
||||||
>
|
>
|
||||||
{field !== undefined && field.value === '' && (
|
{field !== undefined && field.value === '' && <option value="" />}
|
||||||
<option value="">---</option>
|
|
||||||
)}
|
|
||||||
{sortedOptions &&
|
{sortedOptions &&
|
||||||
(sortedOptions as string[]).map((option: string, index: number) => (
|
(sortedOptions as string[]).map((option: string, index: number) => (
|
||||||
<option key={index} value={option}>
|
<option key={index} value={option}>
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
.token {
|
.token {
|
||||||
font-weight: var(--font-weight-bold);
|
font-weight: var(--font-weight-bold);
|
||||||
margin-bottom: calc(var(--spacer) / 4);
|
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,6 +25,21 @@
|
|||||||
height: var(--font-size-base);
|
height: var(--font-size-base);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.conversion {
|
||||||
|
composes: token;
|
||||||
|
margin-bottom: 0;
|
||||||
|
font-weight: var(--font-weight-base) !important;
|
||||||
|
font-size: var(--font-size-small);
|
||||||
|
padding-left: var(--font-size-base);
|
||||||
|
padding-top: calc(var(--spacer) / 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
.conversion strong {
|
||||||
|
font-size: var(--font-size-base);
|
||||||
|
color: var(--font-color-heading);
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Data Token Icon Style */
|
/* Data Token Icon Style */
|
||||||
.icon:not([class*='OCEAN']) path {
|
.icon:not([class*='OCEAN']) path {
|
||||||
fill: var(--brand-violet);
|
fill: var(--brand-violet);
|
40
src/components/@shared/Token/index.tsx
Normal file
40
src/components/@shared/Token/index.tsx
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import React, { ReactElement } from 'react'
|
||||||
|
import styles from './index.module.css'
|
||||||
|
import PriceUnit from '@shared/Price/PriceUnit'
|
||||||
|
import Logo from '@shared/atoms/Logo'
|
||||||
|
import Decimal from 'decimal.js'
|
||||||
|
import Conversion from '@shared/Price/Conversion'
|
||||||
|
import { MAX_DECIMALS } from '@utils/constants'
|
||||||
|
|
||||||
|
export default function Token({
|
||||||
|
symbol,
|
||||||
|
balance,
|
||||||
|
conversion,
|
||||||
|
noIcon,
|
||||||
|
size
|
||||||
|
}: {
|
||||||
|
symbol: string
|
||||||
|
balance: string
|
||||||
|
conversion?: Decimal
|
||||||
|
noIcon?: boolean
|
||||||
|
size?: 'small' | 'mini'
|
||||||
|
}): ReactElement {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className={`${styles.token} ${size ? styles[size] : ''}`}>
|
||||||
|
<figure
|
||||||
|
className={`${styles.icon} ${symbol} ${noIcon ? styles.noIcon : ''}`}
|
||||||
|
>
|
||||||
|
<Logo noWordmark />
|
||||||
|
</figure>
|
||||||
|
<PriceUnit price={balance} symbol={symbol} size={size} />
|
||||||
|
</div>
|
||||||
|
{conversion?.greaterThan(0) && (
|
||||||
|
<Conversion
|
||||||
|
price={conversion.toDecimalPlaces(MAX_DECIMALS).toString()}
|
||||||
|
className={styles.conversion}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
@ -1,6 +1,5 @@
|
|||||||
.actions {
|
.actions {
|
||||||
composes: container from './Pool/index.module.css';
|
composes: section from './Pool/Section/index.module.css';
|
||||||
border-top: 1px solid var(--border-color);
|
|
||||||
margin-top: calc(var(--spacer) / 1.5);
|
margin-top: calc(var(--spacer) / 1.5);
|
||||||
padding: calc(var(--spacer) / 1.5);
|
padding: calc(var(--spacer) / 1.5);
|
||||||
background: var(--background-highlight);
|
background: var(--background-highlight);
|
||||||
@ -12,7 +11,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
composes: title from './Pool/index.module.css';
|
composes: title from './Pool/Section/Title.module.css';
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React, { ReactElement, useState } from 'react'
|
import React, { ReactElement, useState } from 'react'
|
||||||
import Loader from '@shared/atoms/Loader'
|
import Loader from '@shared/atoms/Loader'
|
||||||
import Button from '@shared/atoms/Button'
|
import Button from '@shared/atoms/Button'
|
||||||
import styles from './Actions.module.css'
|
import styles from './index.module.css'
|
||||||
import ExplorerLink from '@shared/ExplorerLink'
|
import ExplorerLink from '@shared/ExplorerLink'
|
||||||
import SuccessConfetti from '@shared/SuccessConfetti'
|
import SuccessConfetti from '@shared/SuccessConfetti'
|
||||||
import { useWeb3 } from '@context/Web3'
|
import { useWeb3 } from '@context/Web3'
|
@ -14,29 +14,21 @@ import { useWeb3 } from '@context/Web3'
|
|||||||
import { isValidNumber } from '@utils/numbers'
|
import { isValidNumber } from '@utils/numbers'
|
||||||
import Decimal from 'decimal.js'
|
import Decimal from 'decimal.js'
|
||||||
import { useAsset } from '@context/Asset'
|
import { useAsset } from '@context/Asset'
|
||||||
import { LoggerInstance, Pool } from '@oceanprotocol/lib'
|
import { Pool } from '@oceanprotocol/lib'
|
||||||
|
import { usePool } from '@context/Pool'
|
||||||
|
|
||||||
export default function FormAdd({
|
export default function FormAdd({
|
||||||
tokenInAddress,
|
|
||||||
tokenInSymbol,
|
|
||||||
amountMax,
|
amountMax,
|
||||||
totalPoolTokens,
|
|
||||||
totalBalance,
|
|
||||||
poolAddress,
|
|
||||||
setNewPoolTokens,
|
setNewPoolTokens,
|
||||||
setNewPoolShare
|
setNewPoolShare
|
||||||
}: {
|
}: {
|
||||||
tokenInAddress: string
|
|
||||||
tokenInSymbol: string
|
|
||||||
amountMax: string
|
amountMax: string
|
||||||
totalPoolTokens: string
|
|
||||||
totalBalance: PoolBalance
|
|
||||||
poolAddress: string
|
|
||||||
setNewPoolTokens: (value: string) => void
|
setNewPoolTokens: (value: string) => void
|
||||||
setNewPoolShare: (value: string) => void
|
setNewPoolShare: (value: string) => void
|
||||||
}): ReactElement {
|
}): ReactElement {
|
||||||
const { balance, web3 } = useWeb3()
|
const { balance, web3 } = useWeb3()
|
||||||
const { isAssetNetwork } = useAsset()
|
const { isAssetNetwork } = useAsset()
|
||||||
|
const { poolData, poolInfo } = usePool()
|
||||||
|
|
||||||
// Connect with form
|
// Connect with form
|
||||||
const {
|
const {
|
||||||
@ -47,9 +39,9 @@ export default function FormAdd({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function calculatePoolShares() {
|
async function calculatePoolShares() {
|
||||||
if (!web3) return
|
if (!web3 || !poolData?.id || !poolInfo?.totalPoolTokens) return
|
||||||
|
|
||||||
if (!values.amount || !tokenInAddress) {
|
if (!values.amount || !poolInfo?.baseTokenAddress) {
|
||||||
setNewPoolTokens('0')
|
setNewPoolTokens('0')
|
||||||
setNewPoolShare('0')
|
setNewPoolShare('0')
|
||||||
return
|
return
|
||||||
@ -59,31 +51,32 @@ export default function FormAdd({
|
|||||||
const poolInstance = new Pool(web3)
|
const poolInstance = new Pool(web3)
|
||||||
|
|
||||||
const poolTokens = await poolInstance.calcPoolOutGivenSingleIn(
|
const poolTokens = await poolInstance.calcPoolOutGivenSingleIn(
|
||||||
poolAddress,
|
poolData.id,
|
||||||
tokenInAddress,
|
poolInfo.baseTokenAddress,
|
||||||
values.amount
|
values.amount
|
||||||
)
|
)
|
||||||
setNewPoolTokens(poolTokens)
|
setNewPoolTokens(poolTokens)
|
||||||
const newPoolShareDecimal =
|
const newPoolShareDecimal =
|
||||||
isValidNumber(poolTokens) && isValidNumber(totalPoolTokens)
|
isValidNumber(poolTokens) && isValidNumber(poolInfo.totalPoolTokens)
|
||||||
? new Decimal(poolTokens)
|
? new Decimal(poolTokens)
|
||||||
.dividedBy(
|
.dividedBy(
|
||||||
new Decimal(totalPoolTokens).plus(new Decimal(poolTokens))
|
new Decimal(poolInfo.totalPoolTokens).plus(
|
||||||
|
new Decimal(poolTokens)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
.mul(100)
|
.mul(100)
|
||||||
.toString()
|
.toString()
|
||||||
: '0'
|
: '0'
|
||||||
totalBalance && setNewPoolShare(newPoolShareDecimal)
|
setNewPoolShare(newPoolShareDecimal)
|
||||||
}
|
}
|
||||||
calculatePoolShares()
|
calculatePoolShares()
|
||||||
}, [
|
}, [
|
||||||
tokenInAddress,
|
poolInfo?.baseTokenAddress,
|
||||||
web3,
|
web3,
|
||||||
values.amount,
|
values.amount,
|
||||||
totalBalance,
|
poolInfo?.totalPoolTokens,
|
||||||
totalPoolTokens,
|
|
||||||
amountMax,
|
amountMax,
|
||||||
poolAddress,
|
poolData?.id,
|
||||||
setNewPoolTokens,
|
setNewPoolTokens,
|
||||||
setNewPoolShare
|
setNewPoolShare
|
||||||
])
|
])
|
||||||
@ -93,7 +86,7 @@ export default function FormAdd({
|
|||||||
<UserLiquidity
|
<UserLiquidity
|
||||||
amount={balance.ocean}
|
amount={balance.ocean}
|
||||||
amountMax={amountMax}
|
amountMax={amountMax}
|
||||||
symbol={tokenInSymbol}
|
symbol={poolInfo?.baseTokenSymbol}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Field name="amount">
|
<Field name="amount">
|
||||||
@ -111,7 +104,7 @@ export default function FormAdd({
|
|||||||
min="0"
|
min="0"
|
||||||
value={values.amount}
|
value={values.amount}
|
||||||
step="any"
|
step="any"
|
||||||
prefix={tokenInSymbol}
|
prefix={poolInfo?.baseTokenSymbol}
|
||||||
placeholder="0"
|
placeholder="0"
|
||||||
field={field}
|
field={field}
|
||||||
form={form}
|
form={form}
|
||||||
|
@ -1,60 +1,24 @@
|
|||||||
import { FormikContextType, useFormikContext } from 'formik'
|
import React, { ReactElement } from 'react'
|
||||||
import React, { ReactElement, useEffect, useState } from 'react'
|
|
||||||
import { FormAddLiquidity } from '.'
|
|
||||||
import FormHelp from '@shared/FormInput/Help'
|
import FormHelp from '@shared/FormInput/Help'
|
||||||
import Token from '../Token'
|
import Token from '../../../../@shared/Token'
|
||||||
import styles from './Output.module.css'
|
import styles from './Output.module.css'
|
||||||
import Decimal from 'decimal.js'
|
|
||||||
import content from '../../../../../../content/price.json'
|
import content from '../../../../../../content/price.json'
|
||||||
|
import { usePool } from '@context/Pool'
|
||||||
|
|
||||||
export default function Output({
|
export default function Output({
|
||||||
newPoolTokens,
|
newPoolTokens,
|
||||||
newPoolShare,
|
newPoolShare
|
||||||
swapFee,
|
|
||||||
datatokenSymbol,
|
|
||||||
totalPoolTokens,
|
|
||||||
totalBalance
|
|
||||||
}: {
|
}: {
|
||||||
newPoolTokens: string
|
newPoolTokens: string
|
||||||
newPoolShare: string
|
newPoolShare: string
|
||||||
swapFee: string
|
|
||||||
datatokenSymbol: string
|
|
||||||
totalPoolTokens: string
|
|
||||||
totalBalance: PoolBalance
|
|
||||||
}): ReactElement {
|
}): ReactElement {
|
||||||
const { help, titleIn, titleOut } = content.pool.add.output
|
const { help, titleIn } = content.pool.add.output
|
||||||
|
const { poolInfo } = usePool()
|
||||||
// Connect with form
|
|
||||||
const { values }: FormikContextType<FormAddLiquidity> = useFormikContext()
|
|
||||||
|
|
||||||
const [poolOcean, setPoolOcean] = useState('0')
|
|
||||||
const [poolDatatoken, setPoolDatatoken] = useState('0')
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!values.amount || !totalBalance || !totalPoolTokens || !newPoolTokens)
|
|
||||||
return
|
|
||||||
const newPoolSupply = new Decimal(totalPoolTokens).plus(newPoolTokens)
|
|
||||||
const ratio = new Decimal(newPoolTokens).div(newPoolSupply)
|
|
||||||
const newOceanReserve = new Decimal(totalBalance.baseToken).plus(
|
|
||||||
values.amount
|
|
||||||
)
|
|
||||||
const newDtReserve = new Decimal(totalBalance.datatoken)
|
|
||||||
const poolOcean = newOceanReserve.mul(ratio).toString()
|
|
||||||
const poolDatatoken = newDtReserve.mul(ratio).toString()
|
|
||||||
setPoolOcean(poolOcean)
|
|
||||||
setPoolDatatoken(poolDatatoken)
|
|
||||||
}, [
|
|
||||||
values.amount,
|
|
||||||
totalBalance,
|
|
||||||
totalPoolTokens,
|
|
||||||
newPoolShare,
|
|
||||||
newPoolTokens
|
|
||||||
])
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<FormHelp className={styles.help}>
|
<FormHelp className={styles.help}>
|
||||||
{help.replace('SWAPFEE', swapFee)}
|
{help.replace('SWAPFEE', poolInfo?.liquidityProviderSwapFee)}
|
||||||
</FormHelp>
|
</FormHelp>
|
||||||
<div className={styles.output}>
|
<div className={styles.output}>
|
||||||
<p>{titleIn}</p>
|
<p>{titleIn}</p>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React, { ReactElement, useState, useEffect } from 'react'
|
import React, { ReactElement, useState, useEffect } from 'react'
|
||||||
import Header from '../Header'
|
import Header from '../Actions/Header'
|
||||||
import { toast } from 'react-toastify'
|
import { toast } from 'react-toastify'
|
||||||
import Actions from '../Actions'
|
import Actions from '../Actions'
|
||||||
import * as Yup from 'yup'
|
import * as Yup from 'yup'
|
||||||
@ -25,28 +25,15 @@ const initialValues: FormAddLiquidity = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function Add({
|
export default function Add({
|
||||||
setShowAdd,
|
setShowAdd
|
||||||
poolAddress,
|
|
||||||
totalPoolTokens,
|
|
||||||
totalBalance,
|
|
||||||
swapFee,
|
|
||||||
datatokenSymbol,
|
|
||||||
tokenInSymbol,
|
|
||||||
tokenInAddress
|
|
||||||
}: {
|
}: {
|
||||||
setShowAdd: (show: boolean) => void
|
setShowAdd: (show: boolean) => void
|
||||||
poolAddress: string
|
|
||||||
totalPoolTokens: string
|
|
||||||
totalBalance: PoolBalance
|
|
||||||
swapFee: string
|
|
||||||
datatokenSymbol: string
|
|
||||||
tokenInSymbol: string
|
|
||||||
tokenInAddress: string
|
|
||||||
}): ReactElement {
|
}): ReactElement {
|
||||||
const { accountId, balance, web3 } = useWeb3()
|
const { accountId, balance, web3 } = useWeb3()
|
||||||
const { isAssetNetwork } = useAsset()
|
const { isAssetNetwork } = useAsset()
|
||||||
const { fetchAllData } = usePool()
|
const { poolData, poolInfo, fetchAllData } = usePool()
|
||||||
const { debug } = useUserPreferences()
|
const { debug } = useUserPreferences()
|
||||||
|
|
||||||
const [txId, setTxId] = useState<string>()
|
const [txId, setTxId] = useState<string>()
|
||||||
const [amountMax, setAmountMax] = useState<string>()
|
const [amountMax, setAmountMax] = useState<string>()
|
||||||
const [newPoolTokens, setNewPoolTokens] = useState('0')
|
const [newPoolTokens, setNewPoolTokens] = useState('0')
|
||||||
@ -67,15 +54,22 @@ export default function Add({
|
|||||||
|
|
||||||
// Get maximum amount for OCEAN
|
// Get maximum amount for OCEAN
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!web3 || !accountId || !isAssetNetwork || !poolAddress) return
|
if (
|
||||||
|
!web3 ||
|
||||||
|
!accountId ||
|
||||||
|
!isAssetNetwork ||
|
||||||
|
!poolData?.id ||
|
||||||
|
!poolInfo?.baseTokenAddress
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
async function getMaximum() {
|
async function getMaximum() {
|
||||||
try {
|
try {
|
||||||
const poolInstance = new Pool(web3)
|
const poolInstance = new Pool(web3)
|
||||||
|
|
||||||
const poolReserve = await poolInstance.getReserve(
|
const poolReserve = await poolInstance.getReserve(
|
||||||
poolAddress,
|
poolData.id,
|
||||||
tokenInAddress
|
poolInfo.baseTokenAddress
|
||||||
)
|
)
|
||||||
|
|
||||||
const amountMaxPool = calcMaxExactIn(poolReserve)
|
const amountMaxPool = calcMaxExactIn(poolReserve)
|
||||||
@ -93,8 +87,8 @@ export default function Add({
|
|||||||
web3,
|
web3,
|
||||||
accountId,
|
accountId,
|
||||||
isAssetNetwork,
|
isAssetNetwork,
|
||||||
poolAddress,
|
poolData?.id,
|
||||||
tokenInAddress,
|
poolInfo?.baseTokenAddress,
|
||||||
balance?.ocean
|
balance?.ocean
|
||||||
])
|
])
|
||||||
|
|
||||||
@ -106,7 +100,7 @@ export default function Add({
|
|||||||
try {
|
try {
|
||||||
const result = await poolInstance.joinswapExternAmountIn(
|
const result = await poolInstance.joinswapExternAmountIn(
|
||||||
accountId,
|
accountId,
|
||||||
poolAddress,
|
poolData?.id,
|
||||||
amount,
|
amount,
|
||||||
minPoolAmountOut
|
minPoolAmountOut
|
||||||
)
|
)
|
||||||
@ -141,12 +135,7 @@ export default function Add({
|
|||||||
<div className={styles.addInput}>
|
<div className={styles.addInput}>
|
||||||
{isWarningAccepted ? (
|
{isWarningAccepted ? (
|
||||||
<FormAdd
|
<FormAdd
|
||||||
tokenInAddress={tokenInAddress}
|
|
||||||
tokenInSymbol={tokenInSymbol}
|
|
||||||
amountMax={amountMax}
|
amountMax={amountMax}
|
||||||
totalPoolTokens={totalPoolTokens}
|
|
||||||
totalBalance={totalBalance}
|
|
||||||
poolAddress={poolAddress}
|
|
||||||
setNewPoolTokens={setNewPoolTokens}
|
setNewPoolTokens={setNewPoolTokens}
|
||||||
setNewPoolShare={setNewPoolShare}
|
setNewPoolShare={setNewPoolShare}
|
||||||
/>
|
/>
|
||||||
@ -166,14 +155,7 @@ export default function Add({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Output
|
<Output newPoolTokens={newPoolTokens} newPoolShare={newPoolShare} />
|
||||||
newPoolTokens={newPoolTokens}
|
|
||||||
newPoolShare={newPoolShare}
|
|
||||||
swapFee={swapFee}
|
|
||||||
datatokenSymbol={datatokenSymbol}
|
|
||||||
totalPoolTokens={totalPoolTokens}
|
|
||||||
totalBalance={totalBalance}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Actions
|
<Actions
|
||||||
isDisabled={
|
isDisabled={
|
||||||
@ -189,8 +171,8 @@ export default function Add({
|
|||||||
actionName={content.pool.add.action}
|
actionName={content.pool.add.action}
|
||||||
action={submitForm}
|
action={submitForm}
|
||||||
amount={values.amount}
|
amount={values.amount}
|
||||||
tokenAddress={tokenInAddress}
|
tokenAddress={poolInfo?.baseTokenAddress}
|
||||||
tokenSymbol={tokenInSymbol}
|
tokenSymbol={poolInfo?.baseTokenSymbol}
|
||||||
txId={txId}
|
txId={txId}
|
||||||
setSubmitting={setSubmitting}
|
setSubmitting={setSubmitting}
|
||||||
/>
|
/>
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
.type {
|
.type {
|
||||||
position: absolute;
|
position: relative;
|
||||||
bottom: -10px;
|
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
width: 100%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 5px var(--spacer);
|
padding: 5px var(--spacer);
|
||||||
|
border-top: 1px solid var(--border-color);
|
||||||
|
border-bottom: 1px solid var(--border-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.button,
|
.button,
|
||||||
|
@ -1,19 +1,17 @@
|
|||||||
.graphWrap {
|
.graphWrap {
|
||||||
|
composes: container from '../Section/index.module.css';
|
||||||
|
|
||||||
|
padding: 0;
|
||||||
|
grid-column: full;
|
||||||
min-height: 120px;
|
min-height: 120px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
margin: calc(var(--spacer) / 6) -1.35rem calc(var(--spacer) / 1.5) -1.35rem;
|
flex-direction: column;
|
||||||
|
margin-bottom: calc(var(--spacer) / 2);
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 40rem) {
|
|
||||||
.graphWrap {
|
|
||||||
margin-left: -2rem;
|
|
||||||
margin-right: -2rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.graphWrap canvas {
|
.graphWrap canvas {
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
|
@ -11,17 +11,14 @@ import Decimal from 'decimal.js'
|
|||||||
import { 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'
|
|
||||||
import { usePrices } from '@context/Prices'
|
import { usePrices } from '@context/Prices'
|
||||||
import { MAX_DECIMALS } from '@utils/constants'
|
import { MAX_DECIMALS } from '@utils/constants'
|
||||||
|
import { usePool } from '@context/Pool'
|
||||||
|
|
||||||
export default function Graph({
|
export default function Graph(): ReactElement {
|
||||||
poolSnapshots
|
|
||||||
}: {
|
|
||||||
poolSnapshots: PoolDataPoolSnapshots[]
|
|
||||||
}): ReactElement {
|
|
||||||
const { locale, currency } = useUserPreferences()
|
const { locale, currency } = useUserPreferences()
|
||||||
const { prices } = usePrices()
|
const { prices } = usePrices()
|
||||||
|
const { poolSnapshots } = usePool()
|
||||||
const darkMode = useDarkMode(false, darkModeConfig)
|
const darkMode = useDarkMode(false, darkModeConfig)
|
||||||
|
|
||||||
const [options, setOptions] = useState<ChartOptions<any>>()
|
const [options, setOptions] = useState<ChartOptions<any>>()
|
||||||
@ -104,13 +101,13 @@ export default function Graph({
|
|||||||
<Loader />
|
<Loader />
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<Nav graphType={graphType} setGraphType={setGraphType} />
|
|
||||||
|
|
||||||
{graphType === 'volume' ? (
|
{graphType === 'volume' ? (
|
||||||
<Bar width={416} height={120} data={graphData} options={options} />
|
<Bar width={416} height={120} data={graphData} options={options} />
|
||||||
) : (
|
) : (
|
||||||
<Line width={416} height={120} data={graphData} options={options} />
|
<Line width={416} height={120} data={graphData} options={options} />
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<Nav graphType={graphType} setGraphType={setGraphType} />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
19
src/components/Asset/AssetActions/Pool/Remove/_utils.ts
Normal file
19
src/components/Asset/AssetActions/Pool/Remove/_utils.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import { calcMaxExactOut } from '@oceanprotocol/lib'
|
||||||
|
import Decimal from 'decimal.js'
|
||||||
|
|
||||||
|
export async function getMax(poolTokens: string, totalPoolTokens: string) {
|
||||||
|
const poolTokensAmount = !poolTokens || poolTokens === '0' ? '1' : poolTokens
|
||||||
|
const maxTokensToRemoveFromPool = calcMaxExactOut(totalPoolTokens)
|
||||||
|
const poolTokensDecimal = new Decimal(poolTokensAmount)
|
||||||
|
const maxTokensToRemoveForUser = maxTokensToRemoveFromPool.greaterThan(
|
||||||
|
poolTokensDecimal
|
||||||
|
)
|
||||||
|
? poolTokensDecimal
|
||||||
|
: maxTokensToRemoveFromPool
|
||||||
|
|
||||||
|
const maxPercent = new Decimal(100)
|
||||||
|
.mul(maxTokensToRemoveForUser)
|
||||||
|
.div(poolTokensDecimal)
|
||||||
|
|
||||||
|
return maxPercent.toDecimalPlaces(0, Decimal.ROUND_DOWN).toString()
|
||||||
|
}
|
@ -6,11 +6,11 @@ import React, {
|
|||||||
useRef
|
useRef
|
||||||
} from 'react'
|
} from 'react'
|
||||||
import styles from './index.module.css'
|
import styles from './index.module.css'
|
||||||
import Header from '../Header'
|
import Header from '../Actions/Header'
|
||||||
import { toast } from 'react-toastify'
|
import { toast } from 'react-toastify'
|
||||||
import Actions from '../Actions'
|
import Actions from '../Actions'
|
||||||
import { LoggerInstance, Pool, calcMaxExactOut } from '@oceanprotocol/lib'
|
import { LoggerInstance, Pool } from '@oceanprotocol/lib'
|
||||||
import Token from '../Token'
|
import Token from '../../../../@shared/Token'
|
||||||
import FormHelp from '@shared/FormInput/Help'
|
import FormHelp from '@shared/FormInput/Help'
|
||||||
import Button from '@shared/atoms/Button'
|
import Button from '@shared/atoms/Button'
|
||||||
import debounce from 'lodash.debounce'
|
import debounce from 'lodash.debounce'
|
||||||
@ -21,27 +21,18 @@ import Decimal from 'decimal.js'
|
|||||||
import { useAsset } from '@context/Asset'
|
import { useAsset } from '@context/Asset'
|
||||||
import content from '../../../../../../content/price.json'
|
import content from '../../../../../../content/price.json'
|
||||||
import { usePool } from '@context/Pool'
|
import { usePool } from '@context/Pool'
|
||||||
|
import { getMax } from './_utils'
|
||||||
|
|
||||||
const slippagePresets = ['5', '10', '15', '25', '50']
|
const slippagePresets = ['5', '10', '15', '25', '50']
|
||||||
|
|
||||||
export default function Remove({
|
export default function Remove({
|
||||||
setShowRemove,
|
setShowRemove
|
||||||
poolAddress,
|
|
||||||
poolTokens,
|
|
||||||
totalPoolTokens,
|
|
||||||
tokenOutAddress,
|
|
||||||
tokenOutSymbol
|
|
||||||
}: {
|
}: {
|
||||||
setShowRemove: (show: boolean) => void
|
setShowRemove: (show: boolean) => void
|
||||||
poolAddress: string
|
|
||||||
poolTokens: string
|
|
||||||
totalPoolTokens: string
|
|
||||||
tokenOutAddress: string
|
|
||||||
tokenOutSymbol: string
|
|
||||||
}): ReactElement {
|
}): ReactElement {
|
||||||
const { accountId, web3 } = useWeb3()
|
const { accountId, web3 } = useWeb3()
|
||||||
const { isAssetNetwork } = useAsset()
|
const { isAssetNetwork } = useAsset()
|
||||||
const { fetchAllData } = usePool()
|
const { poolData, poolInfo, poolInfoUser, fetchAllData } = usePool()
|
||||||
|
|
||||||
const [amountPercent, setAmountPercent] = useState('0')
|
const [amountPercent, setAmountPercent] = useState('0')
|
||||||
const [amountMaxPercent, setAmountMaxPercent] = useState('100')
|
const [amountMaxPercent, setAmountMaxPercent] = useState('100')
|
||||||
@ -62,7 +53,7 @@ export default function Remove({
|
|||||||
try {
|
try {
|
||||||
const result = await poolInstance.exitswapPoolAmountIn(
|
const result = await poolInstance.exitswapPoolAmountIn(
|
||||||
accountId,
|
accountId,
|
||||||
poolAddress,
|
poolData?.id,
|
||||||
amountPoolShares,
|
amountPoolShares,
|
||||||
minOceanAmount
|
minOceanAmount
|
||||||
)
|
)
|
||||||
@ -81,35 +72,23 @@ export default function Remove({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Calculate and set maximum shares user is able to remove
|
||||||
|
//
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!accountId || !poolTokens) return
|
if (!accountId || !poolInfoUser?.poolShares || !poolInfo?.totalPoolTokens)
|
||||||
|
return
|
||||||
|
|
||||||
async function getMax() {
|
getMax(poolInfoUser.poolShares, poolInfo.totalPoolTokens).then((max) =>
|
||||||
const poolTokensAmount =
|
setAmountMaxPercent(max)
|
||||||
!poolTokens || poolTokens === '0' ? '1' : poolTokens
|
)
|
||||||
const maxTokensToRemoveFromPool = calcMaxExactOut(totalPoolTokens)
|
}, [accountId, poolInfoUser?.poolShares, poolInfo?.totalPoolTokens])
|
||||||
const poolTokensDecimal = new Decimal(poolTokensAmount)
|
|
||||||
const maxTokensToRemoveForUser = maxTokensToRemoveFromPool.greaterThan(
|
|
||||||
poolTokensDecimal
|
|
||||||
)
|
|
||||||
? poolTokensDecimal
|
|
||||||
: maxTokensToRemoveFromPool
|
|
||||||
|
|
||||||
const maxPercent = new Decimal(100)
|
|
||||||
.mul(maxTokensToRemoveForUser)
|
|
||||||
.div(poolTokensDecimal)
|
|
||||||
setAmountMaxPercent(
|
|
||||||
maxPercent.toDecimalPlaces(0, Decimal.ROUND_DOWN).toString()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
getMax()
|
|
||||||
}, [accountId, poolAddress, poolTokens, totalPoolTokens])
|
|
||||||
|
|
||||||
const getValues = useRef(
|
const getValues = useRef(
|
||||||
debounce(async (newAmountPoolShares) => {
|
debounce(async (newAmountPoolShares) => {
|
||||||
const newAmountOcean = await poolInstance.calcSingleOutGivenPoolIn(
|
const newAmountOcean = await poolInstance.calcSingleOutGivenPoolIn(
|
||||||
poolAddress,
|
poolData?.id,
|
||||||
tokenOutAddress,
|
poolInfo?.baseTokenAddress,
|
||||||
newAmountPoolShares
|
newAmountPoolShares
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -119,9 +98,21 @@ export default function Remove({
|
|||||||
|
|
||||||
// Check and set outputs when amountPoolShares changes
|
// Check and set outputs when amountPoolShares changes
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!accountId || !poolTokens) return
|
if (
|
||||||
|
!accountId ||
|
||||||
|
!poolInfoUser?.poolShares ||
|
||||||
|
!poolInfo?.totalPoolTokens ||
|
||||||
|
!poolData?.id
|
||||||
|
)
|
||||||
|
return
|
||||||
getValues.current(amountPoolShares)
|
getValues.current(amountPoolShares)
|
||||||
}, [amountPoolShares, accountId, poolTokens, poolAddress, totalPoolTokens])
|
}, [
|
||||||
|
amountPoolShares,
|
||||||
|
accountId,
|
||||||
|
poolInfoUser?.poolShares,
|
||||||
|
poolData?.id,
|
||||||
|
poolInfo?.totalPoolTokens
|
||||||
|
])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!amountOcean || amountPercent === '0') {
|
if (!amountOcean || amountPercent === '0') {
|
||||||
@ -135,16 +126,16 @@ export default function Remove({
|
|||||||
.toString()
|
.toString()
|
||||||
|
|
||||||
setMinOceanAmount(minOceanAmount.slice(0, 18))
|
setMinOceanAmount(minOceanAmount.slice(0, 18))
|
||||||
}, [slippage, amountOcean])
|
}, [slippage, amountOcean, amountPercent])
|
||||||
|
|
||||||
// Set amountPoolShares based on set slider value
|
// Set amountPoolShares based on set slider value
|
||||||
function handleAmountPercentChange(e: ChangeEvent<HTMLInputElement>) {
|
function handleAmountPercentChange(e: ChangeEvent<HTMLInputElement>) {
|
||||||
setAmountPercent(e.target.value)
|
setAmountPercent(e.target.value)
|
||||||
if (!poolTokens) return
|
if (!poolInfoUser?.poolShares) return
|
||||||
|
|
||||||
const amountPoolShares = new Decimal(e.target.value)
|
const amountPoolShares = new Decimal(e.target.value)
|
||||||
.dividedBy(100)
|
.dividedBy(100)
|
||||||
.mul(new Decimal(poolTokens))
|
.mul(new Decimal(poolInfoUser.poolShares))
|
||||||
.toString()
|
.toString()
|
||||||
|
|
||||||
setAmountPoolShares(`${amountPoolShares.slice(0, 18)}`)
|
setAmountPoolShares(`${amountPoolShares.slice(0, 18)}`)
|
||||||
@ -156,7 +147,7 @@ export default function Remove({
|
|||||||
|
|
||||||
const amountPoolShares = new Decimal(amountMaxPercent)
|
const amountPoolShares = new Decimal(amountMaxPercent)
|
||||||
.dividedBy(100)
|
.dividedBy(100)
|
||||||
.mul(new Decimal(poolTokens))
|
.mul(new Decimal(poolInfoUser?.poolShares))
|
||||||
.toString()
|
.toString()
|
||||||
|
|
||||||
setAmountPoolShares(`${amountPoolShares.slice(0, 18)}`)
|
setAmountPoolShares(`${amountPoolShares.slice(0, 18)}`)
|
||||||
@ -177,7 +168,7 @@ export default function Remove({
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<form className={styles.removeInput}>
|
<form className={styles.removeInput}>
|
||||||
<UserLiquidity amount={poolTokens} symbol="pool shares" />
|
<UserLiquidity amount={poolInfoUser?.poolShares} symbol="pool shares" />
|
||||||
<div className={styles.range}>
|
<div className={styles.range}>
|
||||||
<h3>{amountPercent}%</h3>
|
<h3>{amountPercent}%</h3>
|
||||||
<div className={styles.slider}>
|
<div className={styles.slider}>
|
||||||
@ -206,7 +197,7 @@ export default function Remove({
|
|||||||
<div className={styles.output}>
|
<div className={styles.output}>
|
||||||
<div>
|
<div>
|
||||||
<p>{content.pool.remove.output.titleOut} minimum</p>
|
<p>{content.pool.remove.output.titleOut} minimum</p>
|
||||||
<Token symbol={tokenOutSymbol} balance={minOceanAmount} />
|
<Token symbol={poolInfo?.baseTokenSymbol} balance={minOceanAmount} />
|
||||||
</div>
|
</div>
|
||||||
{/* <div>
|
{/* <div>
|
||||||
<p>{content.pool.remove.output.titleIn}</p>
|
<p>{content.pool.remove.output.titleIn}</p>
|
||||||
@ -237,11 +228,11 @@ export default function Remove({
|
|||||||
!isAssetNetwork ||
|
!isAssetNetwork ||
|
||||||
amountPercent === '0' ||
|
amountPercent === '0' ||
|
||||||
amountOcean === '0' ||
|
amountOcean === '0' ||
|
||||||
poolTokens === '0'
|
poolInfo?.totalPoolTokens === '0'
|
||||||
}
|
}
|
||||||
txId={txId}
|
txId={txId}
|
||||||
tokenAddress={tokenOutAddress}
|
tokenAddress={poolInfo?.baseTokenAddress}
|
||||||
tokenSymbol={tokenOutSymbol}
|
tokenSymbol={poolInfo?.baseTokenSymbol}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
@ -0,0 +1,13 @@
|
|||||||
|
.title {
|
||||||
|
font-size: var(--font-size-base);
|
||||||
|
margin-bottom: calc(var(--spacer) / 3);
|
||||||
|
color: var(--color-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.titlePostfix {
|
||||||
|
font-size: var(--font-size-mini);
|
||||||
|
font-family: var(--font-family-base);
|
||||||
|
font-weight: var(--font-weight-base);
|
||||||
|
display: inline-block;
|
||||||
|
margin-left: 0.3rem;
|
||||||
|
}
|
26
src/components/Asset/AssetActions/Pool/Section/Title.tsx
Normal file
26
src/components/Asset/AssetActions/Pool/Section/Title.tsx
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import Tooltip from '@shared/atoms/Tooltip'
|
||||||
|
import React from 'react'
|
||||||
|
import styles from './Title.module.css'
|
||||||
|
|
||||||
|
export default function Title({
|
||||||
|
title,
|
||||||
|
tooltip,
|
||||||
|
titlePostfix,
|
||||||
|
titlePostfixTitle
|
||||||
|
}: {
|
||||||
|
title: string
|
||||||
|
tooltip?: string
|
||||||
|
titlePostfix?: string
|
||||||
|
titlePostfixTitle?: string
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<h3 className={styles.title}>
|
||||||
|
{title} {tooltip && <Tooltip content={tooltip} />}{' '}
|
||||||
|
{titlePostfix && (
|
||||||
|
<span className={styles.titlePostfix} title={titlePostfixTitle}>
|
||||||
|
{titlePostfix}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</h3>
|
||||||
|
)
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
.container {
|
||||||
|
margin-left: calc(-1 * var(--spacer) / 1.5);
|
||||||
|
margin-right: calc(-1 * var(--spacer) / 1.5);
|
||||||
|
padding: calc(var(--spacer) / 1.5) calc(var(--spacer) / 1.5)
|
||||||
|
calc(var(--spacer) / 2) calc(var(--spacer) / 1.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 40rem) {
|
||||||
|
.container {
|
||||||
|
padding-left: var(--spacer);
|
||||||
|
padding-right: var(--spacer);
|
||||||
|
margin-left: calc(-1 * var(--spacer));
|
||||||
|
margin-right: calc(-1 * var(--spacer));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.section {
|
||||||
|
composes: container;
|
||||||
|
|
||||||
|
border-top: 1px solid var(--border-color);
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section.highlight {
|
||||||
|
background: var(--background-highlight);
|
||||||
|
}
|
||||||
|
|
||||||
|
.section:first-child {
|
||||||
|
padding-top: 0;
|
||||||
|
border-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid {
|
||||||
|
display: grid;
|
||||||
|
gap: calc(var(--spacer) / 2);
|
||||||
|
grid-template-columns:
|
||||||
|
[full-start] minmax(13rem, 1fr) [break] minmax(7rem, 1fr)
|
||||||
|
[full-end];
|
||||||
|
}
|
39
src/components/Asset/AssetActions/Pool/Section/index.tsx
Normal file
39
src/components/Asset/AssetActions/Pool/Section/index.tsx
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import React, { ReactElement, ReactNode } from 'react'
|
||||||
|
import styles from './index.module.css'
|
||||||
|
import Title from './Title'
|
||||||
|
|
||||||
|
export default function PoolSection({
|
||||||
|
title,
|
||||||
|
tooltip,
|
||||||
|
titlePostfix,
|
||||||
|
titlePostfixTitle,
|
||||||
|
children,
|
||||||
|
highlight,
|
||||||
|
className
|
||||||
|
}: {
|
||||||
|
title?: string
|
||||||
|
children: ReactNode
|
||||||
|
tooltip?: string
|
||||||
|
titlePostfix?: string
|
||||||
|
titlePostfixTitle?: string
|
||||||
|
highlight?: boolean
|
||||||
|
className?: string
|
||||||
|
}): ReactElement {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={`${styles.section} ${highlight ? styles.highlight : ''} ${
|
||||||
|
className || ''
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{title && (
|
||||||
|
<Title
|
||||||
|
title={title}
|
||||||
|
tooltip={tooltip}
|
||||||
|
titlePostfix={titlePostfix}
|
||||||
|
titlePostfixTitle={titlePostfixTitle}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<div className={styles.grid}>{children}</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
.update {
|
||||||
|
font-size: var(--font-size-mini);
|
||||||
|
color: var(--color-secondary);
|
||||||
|
text-align: center;
|
||||||
|
padding-top: calc(var(--spacer) / 4);
|
||||||
|
padding-bottom: calc(var(--spacer) / 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* .update:before {
|
||||||
|
content: '';
|
||||||
|
width: 6px;
|
||||||
|
height: 6px;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: inline-block;
|
||||||
|
border: 1px solid var(--brand-alert-green);
|
||||||
|
margin-right: 0.2rem;
|
||||||
|
margin-top: -0.1rem;
|
||||||
|
vertical-align: middle;
|
||||||
|
animation: pulse 2s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes pulse {
|
||||||
|
0% {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
background: var(--brand-alert-green);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
} */
|
17
src/components/Asset/AssetActions/Pool/Sections/Update.tsx
Normal file
17
src/components/Asset/AssetActions/Pool/Sections/Update.tsx
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { usePool } from '@context/Pool'
|
||||||
|
import Button from '@shared/atoms/Button'
|
||||||
|
import React from 'react'
|
||||||
|
import styles from './Update.module.css'
|
||||||
|
|
||||||
|
export default function Update() {
|
||||||
|
const { fetchAllData } = usePool()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.update}>
|
||||||
|
<Button style="text" size="small" onClick={() => fetchAllData()}>
|
||||||
|
Refresh Data
|
||||||
|
</Button>
|
||||||
|
{/* Fetching every {refreshInterval / 1000} sec. */}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
.dataToken {
|
||||||
|
font-size: var(--font-size-large);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dataToken > div {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dataTokenLinks {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: var(--font-size-small);
|
||||||
|
margin-top: calc(var(--spacer) / 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dataTokenLinks a {
|
||||||
|
margin-left: calc(var(--spacer) / 3);
|
||||||
|
margin-right: calc(var(--spacer) / 3);
|
||||||
|
}
|
130
src/components/Asset/AssetActions/Pool/Sections/index.tsx
Normal file
130
src/components/Asset/AssetActions/Pool/Sections/index.tsx
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
import { useAsset } from '@context/Asset'
|
||||||
|
import { usePool } from '@context/Pool'
|
||||||
|
import Tooltip from '@shared/atoms/Tooltip'
|
||||||
|
import ExplorerLink from '@shared/ExplorerLink'
|
||||||
|
import PriceUnit from '@shared/Price/PriceUnit'
|
||||||
|
import React from 'react'
|
||||||
|
import Graph from '../Graph'
|
||||||
|
import PoolSection from '../Section'
|
||||||
|
import Token from '../../../../@shared/Token'
|
||||||
|
import content from '../../../../../../content/price.json'
|
||||||
|
import styles from './index.module.css'
|
||||||
|
import Update from './Update'
|
||||||
|
|
||||||
|
export default function PoolSections() {
|
||||||
|
const { asset } = useAsset()
|
||||||
|
const { poolData, poolInfo, poolInfoUser, poolInfoOwner } = usePool()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<PoolSection className={styles.dataToken}>
|
||||||
|
<PriceUnit price="1" symbol={poolInfo?.datatokenSymbol} size="large" />{' '}
|
||||||
|
={' '}
|
||||||
|
<PriceUnit
|
||||||
|
price={`${poolData?.spotPrice}`}
|
||||||
|
symbol={poolInfo?.baseTokenSymbol}
|
||||||
|
size="large"
|
||||||
|
/>
|
||||||
|
<Tooltip content={content.pool.tooltips.price} />
|
||||||
|
<div className={styles.dataTokenLinks}>
|
||||||
|
<ExplorerLink
|
||||||
|
networkId={asset?.chainId}
|
||||||
|
path={`address/${asset?.accessDetails?.addressOrId}`}
|
||||||
|
>
|
||||||
|
Pool
|
||||||
|
</ExplorerLink>
|
||||||
|
<ExplorerLink
|
||||||
|
networkId={asset?.chainId}
|
||||||
|
path={
|
||||||
|
asset?.chainId === 2021000 || asset?.chainId === 1287
|
||||||
|
? `tokens/${asset?.services[0].datatokenAddress}`
|
||||||
|
: `token/${asset?.services[0].datatokenAddress}`
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Datatoken
|
||||||
|
</ExplorerLink>
|
||||||
|
</div>
|
||||||
|
</PoolSection>
|
||||||
|
|
||||||
|
<PoolSection
|
||||||
|
title="Your Value Locked"
|
||||||
|
titlePostfix={
|
||||||
|
poolInfoUser?.poolShare && `${poolInfoUser?.poolShare}% of pool`
|
||||||
|
}
|
||||||
|
tooltip={content.pool.tooltips.liquidity.replace(
|
||||||
|
'SWAPFEE',
|
||||||
|
poolInfo?.liquidityProviderSwapFee
|
||||||
|
)}
|
||||||
|
highlight
|
||||||
|
>
|
||||||
|
<Token
|
||||||
|
symbol={poolInfo?.baseTokenSymbol}
|
||||||
|
balance={poolInfoUser?.liquidity.toString()}
|
||||||
|
conversion={poolInfoUser?.liquidity}
|
||||||
|
/>
|
||||||
|
</PoolSection>
|
||||||
|
|
||||||
|
<PoolSection
|
||||||
|
title="Owner Value Locked"
|
||||||
|
titlePostfix={`${poolInfoOwner?.poolShare}% of pool`}
|
||||||
|
>
|
||||||
|
<Token
|
||||||
|
symbol={poolInfo?.baseTokenSymbol}
|
||||||
|
balance={poolInfoOwner?.liquidity.toString()}
|
||||||
|
conversion={poolInfoOwner?.liquidity}
|
||||||
|
/>
|
||||||
|
</PoolSection>
|
||||||
|
|
||||||
|
<PoolSection title="Total Value Locked">
|
||||||
|
<Token
|
||||||
|
symbol={poolInfo?.baseTokenSymbol}
|
||||||
|
balance={poolInfo?.totalLiquidityInOcean.toString()}
|
||||||
|
conversion={poolInfo?.totalLiquidityInOcean}
|
||||||
|
/>
|
||||||
|
</PoolSection>
|
||||||
|
|
||||||
|
<PoolSection
|
||||||
|
title="Pool Statistics"
|
||||||
|
titlePostfix={
|
||||||
|
poolInfo?.weightDt &&
|
||||||
|
`${poolInfo?.weightBaseToken}/${poolInfo?.weightDt}`
|
||||||
|
}
|
||||||
|
titlePostfixTitle={`Weight of ${poolInfo?.weightBaseToken}% ${poolInfo?.baseTokenSymbol} & ${poolInfo?.weightDt}% ${poolInfo?.datatokenSymbol}`}
|
||||||
|
>
|
||||||
|
<Graph />
|
||||||
|
|
||||||
|
<Token
|
||||||
|
symbol={poolInfo?.baseTokenSymbol}
|
||||||
|
balance={`${poolData?.baseTokenLiquidity}`}
|
||||||
|
size="mini"
|
||||||
|
/>
|
||||||
|
<Token
|
||||||
|
symbol={poolInfo?.datatokenSymbol}
|
||||||
|
balance={`${poolData?.datatokenLiquidity}`}
|
||||||
|
size="mini"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Token
|
||||||
|
symbol="% pool fee"
|
||||||
|
balance={poolInfo?.liquidityProviderSwapFee}
|
||||||
|
noIcon
|
||||||
|
size="mini"
|
||||||
|
/>
|
||||||
|
<Token
|
||||||
|
symbol="% market fee"
|
||||||
|
balance={poolInfo?.publishMarketSwapFee}
|
||||||
|
noIcon
|
||||||
|
size="mini"
|
||||||
|
/>
|
||||||
|
<Token
|
||||||
|
symbol="% OPF fee"
|
||||||
|
balance={poolInfo?.opcFee}
|
||||||
|
noIcon
|
||||||
|
size="mini"
|
||||||
|
/>
|
||||||
|
</PoolSection>
|
||||||
|
|
||||||
|
<Update />
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
@ -1,27 +0,0 @@
|
|||||||
import React, { ReactElement } from 'react'
|
|
||||||
import styles from './Token.module.css'
|
|
||||||
import PriceUnit from '@shared/Price/PriceUnit'
|
|
||||||
import Logo from '@shared/atoms/Logo'
|
|
||||||
|
|
||||||
export default function Token({
|
|
||||||
symbol,
|
|
||||||
balance,
|
|
||||||
noIcon,
|
|
||||||
size
|
|
||||||
}: {
|
|
||||||
symbol: string
|
|
||||||
balance: string
|
|
||||||
noIcon?: boolean
|
|
||||||
size?: 'small' | 'mini'
|
|
||||||
}): ReactElement {
|
|
||||||
return (
|
|
||||||
<div className={`${styles.token} ${size ? styles[size] : ''}`}>
|
|
||||||
<figure
|
|
||||||
className={`${styles.icon} ${symbol} ${noIcon ? styles.noIcon : ''}`}
|
|
||||||
>
|
|
||||||
<Logo noWordmark />
|
|
||||||
</figure>
|
|
||||||
<PriceUnit price={balance} symbol={symbol} size={size} />
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
@ -1,43 +0,0 @@
|
|||||||
.tokenlist {
|
|
||||||
margin-left: -2rem;
|
|
||||||
margin-right: -2rem;
|
|
||||||
padding: calc(var(--spacer) / 1.5) calc(var(--spacer) / 1.5)
|
|
||||||
calc(var(--spacer) / 2) calc(var(--spacer) / 1.5);
|
|
||||||
border-top: 1px solid var(--border-color);
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 40rem) {
|
|
||||||
.tokenlist {
|
|
||||||
padding-left: var(--spacer);
|
|
||||||
padding-right: var(--spacer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.tokenlist.highlight {
|
|
||||||
background: var(--background-highlight);
|
|
||||||
}
|
|
||||||
|
|
||||||
.tokens {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
|
||||||
composes: title from './index.module.css';
|
|
||||||
}
|
|
||||||
|
|
||||||
.totalLiquidity {
|
|
||||||
composes: token from './Token.module.css';
|
|
||||||
margin-bottom: 0;
|
|
||||||
font-weight: var(--font-weight-base) !important;
|
|
||||||
font-size: var(--font-size-small);
|
|
||||||
padding-left: var(--font-size-base);
|
|
||||||
padding-top: calc(var(--spacer) / 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
.totalLiquidity strong {
|
|
||||||
font-size: var(--font-size-base);
|
|
||||||
color: var(--font-color-heading);
|
|
||||||
line-height: 1;
|
|
||||||
}
|
|
@ -1,51 +0,0 @@
|
|||||||
import Conversion from '@shared/Price/Conversion'
|
|
||||||
import React, { ReactElement, ReactNode } from 'react'
|
|
||||||
import Token from './Token'
|
|
||||||
import styles from './TokenList.module.css'
|
|
||||||
import Decimal from 'decimal.js'
|
|
||||||
|
|
||||||
export default function TokenList({
|
|
||||||
title,
|
|
||||||
children,
|
|
||||||
baseTokenValue,
|
|
||||||
baseTokenSymbol,
|
|
||||||
datatokenValue,
|
|
||||||
datatokenSymbol,
|
|
||||||
conversion,
|
|
||||||
highlight,
|
|
||||||
size = 'small'
|
|
||||||
}: {
|
|
||||||
title?: string | ReactNode
|
|
||||||
children?: ReactNode
|
|
||||||
baseTokenValue: string
|
|
||||||
baseTokenSymbol: string
|
|
||||||
datatokenValue?: string
|
|
||||||
datatokenSymbol?: string
|
|
||||||
conversion?: Decimal
|
|
||||||
highlight?: boolean
|
|
||||||
size?: 'small' | 'mini'
|
|
||||||
}): ReactElement {
|
|
||||||
return (
|
|
||||||
<div className={`${styles.tokenlist} ${highlight ? styles.highlight : ''}`}>
|
|
||||||
{title && <h3 className={styles.title}>{title}</h3>}
|
|
||||||
<div className={styles.tokens}>
|
|
||||||
<Token symbol={baseTokenSymbol} balance={baseTokenValue} size={size} />
|
|
||||||
|
|
||||||
{conversion?.greaterThan(0) && (
|
|
||||||
<Conversion
|
|
||||||
price={conversion.toString()}
|
|
||||||
className={styles.totalLiquidity}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{datatokenValue && (
|
|
||||||
<Token
|
|
||||||
symbol={datatokenSymbol}
|
|
||||||
balance={datatokenValue}
|
|
||||||
size={size}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
@ -1,75 +0,0 @@
|
|||||||
.container {
|
|
||||||
margin-left: -2rem;
|
|
||||||
margin-right: -2rem;
|
|
||||||
padding-left: calc(var(--spacer) / 1.5);
|
|
||||||
padding-right: calc(var(--spacer) / 1.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
.dataToken {
|
|
||||||
composes: container;
|
|
||||||
padding-bottom: calc(var(--spacer) / 1.5);
|
|
||||||
font-size: var(--font-size-large);
|
|
||||||
text-align: center;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dataTokenLinks {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
font-size: var(--font-size-small);
|
|
||||||
margin-top: calc(var(--spacer) / 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
.dataTokenLinks a {
|
|
||||||
margin-left: calc(var(--spacer) / 3);
|
|
||||||
margin-right: calc(var(--spacer) / 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
|
||||||
font-size: var(--font-size-base);
|
|
||||||
margin-bottom: calc(var(--spacer) / 3);
|
|
||||||
color: var(--color-secondary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.titleInfo {
|
|
||||||
font-size: var(--font-size-mini);
|
|
||||||
font-family: var(--font-family-base);
|
|
||||||
font-weight: var(--font-weight-base);
|
|
||||||
display: inline-block;
|
|
||||||
margin-left: 0.3rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.update {
|
|
||||||
composes: container;
|
|
||||||
font-size: var(--font-size-mini);
|
|
||||||
color: var(--color-secondary);
|
|
||||||
text-align: center;
|
|
||||||
border-top: 1px solid var(--border-color);
|
|
||||||
padding-top: calc(var(--spacer) / 4);
|
|
||||||
padding-bottom: calc(var(--spacer) / 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* .update:before {
|
|
||||||
content: '';
|
|
||||||
width: 6px;
|
|
||||||
height: 6px;
|
|
||||||
border-radius: 50%;
|
|
||||||
display: inline-block;
|
|
||||||
border: 1px solid var(--brand-alert-green);
|
|
||||||
margin-right: 0.2rem;
|
|
||||||
margin-top: -0.1rem;
|
|
||||||
vertical-align: middle;
|
|
||||||
animation: pulse 2s ease-in-out infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes pulse {
|
|
||||||
0% {
|
|
||||||
background: transparent;
|
|
||||||
}
|
|
||||||
50% {
|
|
||||||
background: var(--brand-alert-green);
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
background: transparent;
|
|
||||||
}
|
|
||||||
} */
|
|
@ -1,37 +1,20 @@
|
|||||||
import React, { ReactElement, useState } from 'react'
|
import React, { ReactElement, useState } from 'react'
|
||||||
import styles from './index.module.css'
|
import stylesActions from './Actions/index.module.css'
|
||||||
import stylesActions from './Actions.module.css'
|
|
||||||
import PriceUnit from '@shared/Price/PriceUnit'
|
|
||||||
import Button from '@shared/atoms/Button'
|
import Button from '@shared/atoms/Button'
|
||||||
import Add from './Add'
|
import Add from './Add'
|
||||||
import Remove from './Remove'
|
import Remove from './Remove'
|
||||||
import Tooltip from '@shared/atoms/Tooltip'
|
|
||||||
import ExplorerLink from '@shared/ExplorerLink'
|
|
||||||
import TokenList from './TokenList'
|
|
||||||
import AssetActionHistoryTable from '../AssetActionHistoryTable'
|
import AssetActionHistoryTable from '../AssetActionHistoryTable'
|
||||||
import Graph from './Graph'
|
|
||||||
import { useAsset } from '@context/Asset'
|
import { useAsset } from '@context/Asset'
|
||||||
import { useWeb3 } from '@context/Web3'
|
import { useWeb3 } from '@context/Web3'
|
||||||
import PoolTransactions from '@shared/PoolTransactions'
|
import PoolTransactions from '@shared/PoolTransactions'
|
||||||
import Decimal from 'decimal.js'
|
|
||||||
import content from '../../../../../content/price.json'
|
|
||||||
import { usePool } from '@context/Pool'
|
import { usePool } from '@context/Pool'
|
||||||
import Token from './Token'
|
import PoolSections from './Sections'
|
||||||
|
|
||||||
export default function Pool(): ReactElement {
|
export default function Pool(): ReactElement {
|
||||||
const { accountId } = useWeb3()
|
|
||||||
const { isInPurgatory, asset, isAssetNetwork } = useAsset()
|
const { isInPurgatory, asset, isAssetNetwork } = useAsset()
|
||||||
const {
|
const { hasUserAddedLiquidity, isRemoveDisabled } = usePool()
|
||||||
poolData,
|
const { accountId } = useWeb3()
|
||||||
poolInfo,
|
|
||||||
poolInfoUser,
|
|
||||||
poolInfoOwner,
|
|
||||||
poolSnapshots,
|
|
||||||
hasUserAddedLiquidity,
|
|
||||||
isRemoveDisabled,
|
|
||||||
fetchAllData
|
|
||||||
// refreshInterval
|
|
||||||
} = usePool()
|
|
||||||
|
|
||||||
const [showAdd, setShowAdd] = useState(false)
|
const [showAdd, setShowAdd] = useState(false)
|
||||||
const [showRemove, setShowRemove] = useState(false)
|
const [showRemove, setShowRemove] = useState(false)
|
||||||
@ -39,150 +22,13 @@ export default function Pool(): ReactElement {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{showAdd ? (
|
{showAdd ? (
|
||||||
<Add
|
<Add setShowAdd={setShowAdd} />
|
||||||
setShowAdd={setShowAdd}
|
|
||||||
poolAddress={asset?.accessDetails?.addressOrId}
|
|
||||||
totalPoolTokens={poolInfo?.totalPoolTokens}
|
|
||||||
totalBalance={{
|
|
||||||
baseToken: new Decimal(poolData?.baseTokenLiquidity).toString(),
|
|
||||||
datatoken: new Decimal(poolData?.datatokenLiquidity).toString()
|
|
||||||
}}
|
|
||||||
swapFee={poolInfo?.liquidityProviderSwapFee}
|
|
||||||
datatokenSymbol={poolInfo?.datatokenSymbol}
|
|
||||||
tokenInAddress={poolInfo?.baseTokenAddress}
|
|
||||||
tokenInSymbol={poolInfo?.baseTokenSymbol}
|
|
||||||
/>
|
|
||||||
) : showRemove ? (
|
) : showRemove ? (
|
||||||
<Remove
|
<Remove setShowRemove={setShowRemove} />
|
||||||
setShowRemove={setShowRemove}
|
|
||||||
poolAddress={asset?.accessDetails?.addressOrId}
|
|
||||||
poolTokens={poolInfoUser?.poolShares}
|
|
||||||
totalPoolTokens={poolInfo?.totalPoolTokens}
|
|
||||||
tokenOutAddress={poolInfo?.baseTokenAddress}
|
|
||||||
tokenOutSymbol={poolInfo?.baseTokenSymbol}
|
|
||||||
/>
|
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<div className={styles.dataToken}>
|
<PoolSections />
|
||||||
<PriceUnit
|
|
||||||
price="1"
|
|
||||||
symbol={poolInfo?.datatokenSymbol}
|
|
||||||
size="large"
|
|
||||||
/>{' '}
|
|
||||||
={' '}
|
|
||||||
<PriceUnit
|
|
||||||
price={`${poolData?.spotPrice}`}
|
|
||||||
symbol={poolInfo?.baseTokenSymbol}
|
|
||||||
size="large"
|
|
||||||
/>
|
|
||||||
<Tooltip content={content.pool.tooltips.price} />
|
|
||||||
<div className={styles.dataTokenLinks}>
|
|
||||||
<ExplorerLink
|
|
||||||
networkId={asset?.chainId}
|
|
||||||
path={`address/${asset?.accessDetails?.addressOrId}`}
|
|
||||||
>
|
|
||||||
Pool
|
|
||||||
</ExplorerLink>
|
|
||||||
<ExplorerLink
|
|
||||||
networkId={asset?.chainId}
|
|
||||||
path={
|
|
||||||
asset?.chainId === 2021000 || asset?.chainId === 1287
|
|
||||||
? `tokens/${asset?.services[0].datatokenAddress}`
|
|
||||||
: `token/${asset?.services[0].datatokenAddress}`
|
|
||||||
}
|
|
||||||
>
|
|
||||||
Datatoken
|
|
||||||
</ExplorerLink>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<TokenList
|
|
||||||
title={
|
|
||||||
<>
|
|
||||||
Your Value Locked
|
|
||||||
<Tooltip
|
|
||||||
content={content.pool.tooltips.liquidity.replace(
|
|
||||||
'SWAPFEE',
|
|
||||||
poolInfo?.liquidityProviderSwapFee
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
{poolInfoUser?.poolShare && (
|
|
||||||
<span className={styles.titleInfo}>
|
|
||||||
{poolInfoUser?.poolShare}% of pool
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
baseTokenValue={poolInfoUser?.liquidity.toString()}
|
|
||||||
baseTokenSymbol={poolInfo?.baseTokenSymbol}
|
|
||||||
conversion={poolInfoUser?.liquidity}
|
|
||||||
highlight
|
|
||||||
/>
|
|
||||||
<TokenList
|
|
||||||
title={
|
|
||||||
<>
|
|
||||||
Owner Value Locked
|
|
||||||
<span className={styles.titleInfo}>
|
|
||||||
{poolInfoOwner?.poolShare}% of pool
|
|
||||||
</span>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
baseTokenValue={poolInfoOwner?.liquidity.toString()}
|
|
||||||
baseTokenSymbol={poolInfo?.baseTokenSymbol}
|
|
||||||
conversion={poolInfoOwner?.liquidity}
|
|
||||||
/>
|
|
||||||
<TokenList
|
|
||||||
title={
|
|
||||||
<>
|
|
||||||
Pool Statistics
|
|
||||||
{poolInfo?.weightDt && (
|
|
||||||
<span
|
|
||||||
className={styles.titleInfo}
|
|
||||||
title={`Weight of ${poolInfo?.weightBaseToken}% ${poolInfo?.baseTokenSymbol} & ${poolInfo?.weightDt}% ${poolInfo?.datatokenSymbol}`}
|
|
||||||
>
|
|
||||||
{poolInfo?.weightBaseToken}/{poolInfo?.weightDt}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
<Graph poolSnapshots={poolSnapshots} />
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
baseTokenValue={`${poolInfo?.totalLiquidityInOcean}`}
|
|
||||||
baseTokenSymbol={poolInfo?.baseTokenSymbol}
|
|
||||||
conversion={poolInfo?.totalLiquidityInOcean}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<TokenList
|
|
||||||
size="mini"
|
|
||||||
baseTokenValue={`${poolData?.baseTokenLiquidity}`}
|
|
||||||
baseTokenSymbol={poolInfo?.baseTokenSymbol}
|
|
||||||
datatokenValue={`${poolData?.datatokenLiquidity}`}
|
|
||||||
datatokenSymbol={poolInfo?.datatokenSymbol}
|
|
||||||
>
|
|
||||||
<Token
|
|
||||||
symbol="% pool fee"
|
|
||||||
balance={poolInfo?.liquidityProviderSwapFee}
|
|
||||||
noIcon
|
|
||||||
size="mini"
|
|
||||||
/>
|
|
||||||
<Token
|
|
||||||
symbol="% market fee"
|
|
||||||
balance={poolInfo?.publishMarketSwapFee}
|
|
||||||
noIcon
|
|
||||||
size="mini"
|
|
||||||
/>
|
|
||||||
<Token
|
|
||||||
symbol="% OPF fee"
|
|
||||||
balance={poolInfo?.opcFee}
|
|
||||||
noIcon
|
|
||||||
size="mini"
|
|
||||||
/>
|
|
||||||
</TokenList>
|
|
||||||
|
|
||||||
<div className={styles.update}>
|
|
||||||
<Button style="text" size="small" onClick={() => fetchAllData()}>
|
|
||||||
Refresh Data
|
|
||||||
</Button>
|
|
||||||
{/* Fetching every {refreshInterval / 1000} sec. */}
|
|
||||||
</div>
|
|
||||||
<div className={stylesActions.actions}>
|
<div className={stylesActions.actions}>
|
||||||
<Button
|
<Button
|
||||||
style="primary"
|
style="primary"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { FormikContextType, useFormikContext } from 'formik'
|
import { FormikContextType, useFormikContext } from 'formik'
|
||||||
import React, { ReactElement, useEffect, useState } from 'react'
|
import React, { ReactElement, useEffect, useState } from 'react'
|
||||||
import { useAsset } from '@context/Asset'
|
import { useAsset } from '@context/Asset'
|
||||||
import Token from '../Pool/Token'
|
import Token from '../../../@shared/Token'
|
||||||
import styles from './Output.module.css'
|
import styles from './Output.module.css'
|
||||||
|
|
||||||
import Decimal from 'decimal.js'
|
import Decimal from 'decimal.js'
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
.buildId {
|
.buildId {
|
||||||
display: inline-block;
|
display: block;
|
||||||
font-size: var(--font-size-mini);
|
font-size: var(--font-size-mini);
|
||||||
margin-bottom: var(--spacer);
|
margin-bottom: var(--spacer);
|
||||||
font-family: var(--font-family-monospace);
|
font-family: var(--font-family-monospace);
|
||||||
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
@ -1,38 +1,57 @@
|
|||||||
.content {
|
.footer {
|
||||||
padding: var(--spacer) calc(var(--spacer) / 2);
|
padding: var(--spacer) calc(var(--spacer) / 2);
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
max-width: var(--layout-max-width);
|
max-width: var(--layout-max-width);
|
||||||
|
color: var(--brand-grey-light);
|
||||||
|
font-size: var(--font-size-small);
|
||||||
}
|
}
|
||||||
|
|
||||||
.content a,
|
.footer a,
|
||||||
.content button {
|
.footer button {
|
||||||
color: inherit;
|
color: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content button {
|
.footer button {
|
||||||
text-transform: none;
|
text-transform: none;
|
||||||
transform: none !important;
|
transform: none !important;
|
||||||
font-weight: var(--font-weight-normal);
|
font-weight: var(--font-weight-normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
.content a:hover,
|
.footer a:hover,
|
||||||
.content a:focus,
|
.footer a:focus,
|
||||||
.content button:hover,
|
.footer button:hover,
|
||||||
.content button:focus {
|
.footer button:focus {
|
||||||
color: var(--color-primary);
|
color: var(--color-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.content p {
|
.copyright > div,
|
||||||
|
.copyright > div > p {
|
||||||
display: inline;
|
display: inline;
|
||||||
}
|
}
|
||||||
|
|
||||||
.copyright div {
|
.copyright,
|
||||||
display: inline-block;
|
.grid > div:first-child {
|
||||||
}
|
|
||||||
|
|
||||||
.footer {
|
|
||||||
color: var(--brand-grey-light);
|
|
||||||
font-size: var(--font-size-small);
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.grid {
|
||||||
|
display: grid;
|
||||||
|
gap: var(--spacer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 40rem) {
|
||||||
|
.grid {
|
||||||
|
display: grid;
|
||||||
|
gap: var(--spacer);
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid > div:first-child {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -2,56 +2,23 @@ import React, { ReactElement } from 'react'
|
|||||||
import styles from './Footer.module.css'
|
import styles from './Footer.module.css'
|
||||||
import Markdown from '@shared/Markdown'
|
import Markdown from '@shared/Markdown'
|
||||||
import { useSiteMetadata } from '@hooks/useSiteMetadata'
|
import { useSiteMetadata } from '@hooks/useSiteMetadata'
|
||||||
import Link from 'next/link'
|
|
||||||
import MarketStats from './MarketStats'
|
import MarketStats from './MarketStats'
|
||||||
import BuildId from './BuildId'
|
import BuildId from './BuildId'
|
||||||
import { useUserPreferences } from '@context/UserPreferences'
|
import Links from './Links'
|
||||||
import Button from '@shared/atoms/Button'
|
|
||||||
import { useGdprMetadata } from '@hooks/useGdprMetadata'
|
|
||||||
|
|
||||||
export default function Footer(): ReactElement {
|
export default function Footer(): ReactElement {
|
||||||
const { copyright, appConfig } = useSiteMetadata()
|
const { copyright } = useSiteMetadata()
|
||||||
const { setShowPPC } = useUserPreferences()
|
|
||||||
const { privacyPolicySlug } = useUserPreferences()
|
|
||||||
|
|
||||||
const cookies = useGdprMetadata()
|
|
||||||
|
|
||||||
const year = new Date().getFullYear()
|
const year = new Date().getFullYear()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<footer className={styles.footer}>
|
<footer className={styles.footer}>
|
||||||
<div className={styles.content}>
|
<BuildId />
|
||||||
<BuildId />
|
<MarketStats />
|
||||||
<MarketStats />
|
|
||||||
|
<div className={styles.grid}>
|
||||||
|
<Links />
|
||||||
<div className={styles.copyright}>
|
<div className={styles.copyright}>
|
||||||
© {year} <Markdown text={copyright} />
|
© {year} <Markdown text={copyright} />
|
||||||
<br />
|
|
||||||
<Link href="/imprint">
|
|
||||||
<a>Imprint</a>
|
|
||||||
</Link>
|
|
||||||
{' — '}
|
|
||||||
<Link href="/terms">
|
|
||||||
<a>Terms</a>
|
|
||||||
</Link>
|
|
||||||
{' — '}
|
|
||||||
<Link href={privacyPolicySlug}>
|
|
||||||
<a>Privacy</a>
|
|
||||||
</Link>
|
|
||||||
{appConfig.privacyPreferenceCenter === 'true' && (
|
|
||||||
<>
|
|
||||||
{' — '}
|
|
||||||
<Button
|
|
||||||
style="text"
|
|
||||||
size="small"
|
|
||||||
className="link"
|
|
||||||
onClick={() => {
|
|
||||||
setShowPPC(true)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{cookies.optionalCookies ? 'Cookie Settings' : 'Cookies'}
|
|
||||||
</Button>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
|
12
src/components/Footer/Links.module.css
Normal file
12
src/components/Footer/Links.module.css
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
.links a {
|
||||||
|
text-transform: none;
|
||||||
|
font-family: var(--font-family-base);
|
||||||
|
font-weight: var(--font-weight-base);
|
||||||
|
}
|
||||||
|
|
||||||
|
.links svg {
|
||||||
|
display: inline;
|
||||||
|
fill: currentColor;
|
||||||
|
width: 0.6em;
|
||||||
|
height: 0.6em;
|
||||||
|
}
|
55
src/components/Footer/Links.tsx
Normal file
55
src/components/Footer/Links.tsx
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import { useUserPreferences } from '@context/UserPreferences'
|
||||||
|
import { useGdprMetadata } from '@hooks/useGdprMetadata'
|
||||||
|
import { useSiteMetadata } from '@hooks/useSiteMetadata'
|
||||||
|
import Button from '@shared/atoms/Button'
|
||||||
|
import Link from 'next/link'
|
||||||
|
import React from 'react'
|
||||||
|
import content from '../../../content/footer.json'
|
||||||
|
import External from '@images/external.svg'
|
||||||
|
import styles from './Links.module.css'
|
||||||
|
|
||||||
|
export default function Links() {
|
||||||
|
const { appConfig } = useSiteMetadata()
|
||||||
|
const { setShowPPC, privacyPolicySlug } = useUserPreferences()
|
||||||
|
const cookies = useGdprMetadata()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.links}>
|
||||||
|
{content.links.map(({ name, url }) => (
|
||||||
|
<>
|
||||||
|
<Button style="text" size="small" href={url}>
|
||||||
|
{name} <External />
|
||||||
|
</Button>
|
||||||
|
{' — '}
|
||||||
|
</>
|
||||||
|
))}
|
||||||
|
|
||||||
|
<Link href="/imprint">
|
||||||
|
<a>Imprint</a>
|
||||||
|
</Link>
|
||||||
|
{' — '}
|
||||||
|
<Link href="/terms">
|
||||||
|
<a>Terms</a>
|
||||||
|
</Link>
|
||||||
|
{' — '}
|
||||||
|
<Link href={privacyPolicySlug}>
|
||||||
|
<a>Privacy</a>
|
||||||
|
</Link>
|
||||||
|
{appConfig.privacyPreferenceCenter === 'true' && (
|
||||||
|
<>
|
||||||
|
{' — '}
|
||||||
|
<Button
|
||||||
|
style="text"
|
||||||
|
size="small"
|
||||||
|
className="link"
|
||||||
|
onClick={() => {
|
||||||
|
setShowPPC(true)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{cookies.optionalCookies ? 'Cookie Settings' : 'Cookies'}
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
.stats {
|
.stats {
|
||||||
margin-bottom: calc(var(--spacer) * 2);
|
margin-bottom: calc(var(--spacer) * 2);
|
||||||
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* specificity sledgehammer override without !important */
|
/* specificity sledgehammer override without !important */
|
||||||
|
@ -44,7 +44,7 @@ const Account = React.forwardRef((props, ref: any) => {
|
|||||||
// the Tippy to show in this state.
|
// the Tippy to show in this state.
|
||||||
ref={ref}
|
ref={ref}
|
||||||
>
|
>
|
||||||
Connect <span>Wallet</span>
|
Connect <span>Wallet</span>
|
||||||
</button>
|
</button>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import Conversion from '@shared/Price/Conversion'
|
import Conversion from '@shared/Price/Conversion'
|
||||||
import styles from './Liquidity.module.css'
|
import styles from './Liquidity.module.css'
|
||||||
import Token from '../../../Asset/AssetActions/Pool/Token'
|
import Token from '../../../@shared/Token'
|
||||||
import { isValidNumber } from '@utils/numbers'
|
import { isValidNumber } from '@utils/numbers'
|
||||||
import Decimal from 'decimal.js'
|
import Decimal from 'decimal.js'
|
||||||
import { AssetPoolShare } from './index'
|
import { AssetPoolShare } from './index'
|
||||||
|
Loading…
Reference in New Issue
Block a user