Skip to content
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@
"@ubeswap/moola": "^0.2.0",
"@ubeswap/sdk": "^2.1.2",
"@uniswap/default-token-list": "^2.0.0",
"apexcharts": "^3.33.0",
"ajv-formats": "^2.1.1",
"eventemitter3": "^4.0.7",
"graphql": "^15.6.1",
Expand All @@ -145,7 +146,11 @@
"prop-types": "^15.7.2",
"randombytes": "^2.1.0",
"rc-drawer": "^4.4.3",
"react-apexcharts": "^1.3.9",
"react-circular-progressbar": "^2.0.4",
"react-countdown": "^2.3.2",
"react-is": "^17.0.2",
"react-minimal-pie-chart": "^8.2.0",
"react-router": "^5.2.0",
"rebass": "^4.0.7",
"redux": "^4.1.0",
Expand Down
6 changes: 6 additions & 0 deletions public/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@
"liquidityProviderRewardsDesc": "Liquidity providers earn a 0.25% fee on all trades proportional to their share of the pool. Fees are added to the pool, accrue in real time and can be claimed by withdrawing your liquidity.",
"liquidityProviderRewardsReadMore": "Read more about providing liquidity",
"liquidityTokens": "liquidity tokens.",
"Liquidity": "Liquidity",
"Lists": "Lists",
"Loading": "Loading",
"manage": "Manage",
Expand Down Expand Up @@ -126,6 +127,11 @@
"poolRate": "Pool $t(rate)",
"poolTokens": "Pool Tokens",
"PoolTokensInRewardsPool": "Pool tokens in rewards pool",
"portfolio": "Portfolio",
"portfolioDistribution": "Portfolio Distribution",
"portfolioTokenHoldings": "Token Holdings",
"portfolioLiquidityHoldings": "Liquidity Holdings",
"portfolioValue": "Portfolio Value",
"priceChange": "Expected price slippage",
"rate": "rate",
"Rate": "Rate",
Expand Down
3 changes: 3 additions & 0 deletions src/components/Header/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,9 @@ export default function Header() {
<StyledNavLinkExtraSmall id={`stake-nav-link`} to={'/stake'}>
{t('stake')}
</StyledNavLinkExtraSmall>
<StyledNavLink id="portfolio-nav-link" to="/portfolio">
{t('portfolio')}
</StyledNavLink>
<ChartsMenuGroup />
</HeaderLinks>
<BurgerElement>
Expand Down
137 changes: 137 additions & 0 deletions src/components/portfolio/LiquidityCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import { LPPortfolio } from 'pages/Portfolio/usePortfolio'
import React from 'react'
import ReactApexChart from 'react-apexcharts'
import { useTranslation } from 'react-i18next'
import { useIsDarkMode } from 'state/user/hooks'
import styled from 'styled-components'

import { colors, TYPE } from '../../theme'
import { AutoColumn } from '../Column'
import DoubleCurrencyLogo from '../DoubleLogo'
import { RowBetween } from '../Row'

interface Props {
lpPortfolio: LPPortfolio
}

const DataRow = styled(RowBetween)`
flex-direction: row;
padding: 0.5em;
width: 100%;
`
const LiquidityRowLeft = styled(RowBetween)`
flex-direction: row;
justify-content: flex-start;
`

const LiquidityRowRight = styled(RowBetween)`
flex-direction: row;
justify-content: flex-end;
`

const Wrapper = styled(AutoColumn)<{ showBackground: boolean; bgColor: any }>`
border-radius: 12px;
border-style: solid;
border-width: 0px;
border-color: grey;
margin: 20px;
padding: 20px;
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
flex-grow: 1;
`

const ChartWrapper = styled(AutoColumn)`
width: 100%;
`

interface LiquidityRowProps {
lpPortfolioData: TokenPortfolioData
valueCUSD: TokenAmount
}

const LiquidityRow: React.FC<LiquidityRowProps> = ({ lpPortfolioData, valueCUSD }: LiquidityRowProps) => {
const lpFraction = parseFloat(lpPortfolioData.cusdAmount.divide(valueCUSD).toFixed(4) * 100).toFixed(2)
const valueLP = parseFloat(lpPortfolioData.cusdAmount.toFixed(2))
return (
<DataRow>
<LiquidityRowLeft>
<DoubleCurrencyLogo currency0={lpPortfolioData.pair.token0} currency1={lpPortfolioData.pair.token1} size={24} />
<TYPE.mediumHeader paddingLeft=".5em">
{lpPortfolioData.pair.token0.symbol}-{lpPortfolioData.pair.token1.symbol}
</TYPE.mediumHeader>
</LiquidityRowLeft>
<LiquidityRowRight>
<TYPE.mediumHeader paddingRight="10px">${valueLP}</TYPE.mediumHeader>
<TYPE.subHeader>({lpFraction}%)</TYPE.subHeader>
</LiquidityRowRight>
</DataRow>
)
}

export const LiquidityCard: React.FC<Props> = ({ lpPortfolio }: Props) => {
const { t } = useTranslation()

const darkMode = useIsDarkMode()
const themeColors = colors(darkMode)

if (!(lpPortfolio && lpPortfolio.tokens.length)) {
return <></>
}

const valueLP = parseFloat(lpPortfolio.valueCUSD.toFixed(2))

const sortedTokens = lpPortfolio.tokens.sort((token1, token2) => {
return token2.cusdAmount.greaterThan(token1.cusdAmount) ? 1 : -1
})

const series = lpPortfolio.tokens.map((token) => parseFloat(token.cusdAmount.toFixed(2)))

const chartOptions = {
chart: {
width: '100%',
type: 'pie',
},
labels: lpPortfolio.tokens.map((token) => `${token.pair.token0.symbol}-${token.pair.token1.symbol}`),
theme: {
monochrome: {
enabled: true,
color: themeColors.primary1,
shadeTo: 'light',
shadeIntensity: 0.6,
},
},
plotOptions: {
pie: {
dataLabels: {
offset: -5,
},
},
},
legend: {
show: false,
},
}
return (
<Wrapper>
<TYPE.largeHeader padding="10px">
{t('portfolioLiquidityHoldings')}: ${valueLP}
</TYPE.largeHeader>
<ChartWrapper>
<ReactApexChart options={chartOptions} series={series} type="pie" />
</ChartWrapper>
{sortedTokens &&
sortedTokens.map((lpPortfolioData) => {
return (
<LiquidityRow
key={lpPortfolioData.pair.liquidityToken.address}
lpPortfolioData={lpPortfolioData}
valueCUSD={lpPortfolio.valueCUSD}
/>
)
})}
</Wrapper>
)
}
111 changes: 111 additions & 0 deletions src/components/portfolio/PortfolioCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import { LPPortfolio, TokenPortfolio } from 'pages/Portfolio/usePortfolio'
import React from 'react'
import ReactApexChart from 'react-apexcharts'
import { useTranslation } from 'react-i18next'
import { useIsDarkMode } from 'state/user/hooks'
import styled from 'styled-components'

import { colors, TYPE } from '../../theme'
import { AutoColumn } from '../Column'
import { RowBetween } from '../Row'

const Wrapper = styled(AutoColumn)<{ showBackground: boolean; bgColor: any }>`
border-radius: 12px;
border-style: solid;
border-width: 0px;
border-color: grey;
margin: 20px;
padding: 20px;
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
flex-grow: 1;
`

const ChartWrapper = styled(AutoColumn)`
width: 100%;
`

interface Props {
tokenPortfolio: TokenPortfolio
lpPortfolio: LPPortfolio
}

const DataRow = styled(RowBetween)`
flex-direction: row;
padding: 0.5em;
width: 100%;
`

const DataRowRight = styled(RowBetween)`
flex-direction: row;
justify-content: flex-end;
`

export const PortfolioCard: React.FC<Props> = ({ tokenPortfolio, lpPortfolio }: Props) => {
const { t } = useTranslation()

const darkMode = useIsDarkMode()
const themeColors = colors(darkMode)

if (!(tokenPortfolio && tokenPortfolio.tokens.length) || !(lpPortfolio && lpPortfolio.tokens.length)) {
return <></>
}

const valueTokens = parseFloat(tokenPortfolio.valueCUSD.toFixed(2))
const valueLiquidity = parseFloat(lpPortfolio.valueCUSD.toFixed(2))
const totalValue = tokenPortfolio.valueCUSD.add(lpPortfolio.valueCUSD)

const fractionTokens = (parseFloat(tokenPortfolio.valueCUSD.divide(totalValue).toFixed(2)) * 100).toFixed(2)
const fractionLiquidity = (parseFloat(lpPortfolio.valueCUSD.divide(totalValue).toFixed(2)) * 100).toFixed(2)

const series = [valueTokens, valueLiquidity]

const chartOptions = {
chart: {
type: 'pie',
},
labels: [t('Tokens'), t('StakedUnstakedLiquidity')],
plotOptions: {
pie: {
dataLabels: {
offset: -5,
},
},
},
legend: {
show: false,
},
theme: {
monochrome: {
enabled: true,
color: themeColors.primary1,
shadeTo: 'light',
shadeIntensity: 0.6,
},
},
}
return (
<Wrapper>
<TYPE.largeHeader padding="10px">{t('portfolioDistribution')}</TYPE.largeHeader>
<ChartWrapper>
<ReactApexChart options={chartOptions} series={series} type="pie" />
</ChartWrapper>
<DataRow>
<TYPE.mediumHeader>{t('Tokens')}:</TYPE.mediumHeader>
<DataRowRight>
<TYPE.mediumHeader paddingRight="10px">${valueTokens}</TYPE.mediumHeader>
<TYPE.subHeader>({fractionTokens}%)</TYPE.subHeader>
</DataRowRight>
</DataRow>
<DataRow>
<TYPE.mediumHeader>{t('Liquidity')}:</TYPE.mediumHeader>
<DataRowRight>
<TYPE.mediumHeader paddingRight="10px">${valueLiquidity}</TYPE.mediumHeader>
<TYPE.subHeader>({fractionLiquidity}%)</TYPE.subHeader>
</DataRowRight>
</DataRow>
</Wrapper>
)
}
Loading