utils#formatNumber TypeScript Examples
The following examples show how to use
utils#formatNumber.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: AreaChart.tsx From interface-v2 with GNU General Public License v3.0 | 4 votes |
AreaChart: React.FC<AreaChartProps> = ({
backgroundColor = '#004ce6',
categories = [],
data = [],
dates = [],
yAxisValues,
width = 500,
height = 200,
}) => {
const dark = useIsDarkMode();
const strokeColor = '#00dced';
const gradientColor = dark ? '#64fbd3' : '#D4F8FB';
const yMax = yAxisValues
? Math.max(...yAxisValues.map((val) => Number(val)))
: 0;
const yMin = yAxisValues
? Math.min(...yAxisValues.map((val) => Number(val)))
: 0;
const options = {
chart: {
sparkline: {
enabled: false,
},
toolbar: {
show: false,
},
width: '100%',
zoom: {
enabled: false,
},
},
dataLabels: {
enabled: false,
},
stroke: {
width: 2,
colors: [strokeColor],
curve: 'smooth' as any,
},
markers: {
colors: [strokeColor],
strokeWidth: 0,
},
fill: {
type: 'gradient',
colors: [gradientColor],
gradient: {
gradientToColors: [backgroundColor],
shadeIntensity: 1,
opacityFrom: 0.5,
opacityTo: 0.15,
stops: [0, 100],
},
},
xaxis: {
categories: categories.map(() => ''),
axisBorder: {
show: false,
},
tooltip: {
enabled: false,
},
axisTicks: {
show: false,
},
labels: {
style: {
colors: new Array(categories.length).fill(
dark ? '#646464' : '#CACED3',
),
},
},
},
yaxis: {
show: false,
min: yAxisValues ? yMin : undefined,
max: yAxisValues ? yMax : undefined,
tickAmount: yAxisValues?.length,
},
grid: {
show: false,
padding: {
left: 0,
right: 0,
},
xaxis: {
lines: {
show: false,
},
},
},
legend: {
show: false,
},
tooltip: {
enabled: true,
theme: dark ? 'dark' : 'light',
fillSeriesColor: false,
custom: ({ series, seriesIndex, dataPointIndex }: any) => {
return (
`<div class="tooltip" style="display: flex; flex-direction: column; box-shadow: none; border-radius: 12px; background: transparent;">` +
`<span style="padding: 0.5rem; border: 1px solid ${
dark ? 'rgba(255, 255, 255, 0.15)' : 'rgba(0, 0, 0, 0.15)'
}; border-radius: 12px 12px 0 0; background: ${
dark ? 'rgba(0, 0, 0, 0.91)' : 'rgba(255, 255, 255, 0.91)'
}; color: ${dark ? '#646464' : '#8D97A0'};">` +
dayjs(dates[dataPointIndex] * 1000).format('MMM DD, YYYY') +
'</span>' +
`<span style="padding: 0.5rem; border: 1px solid ${
dark ? 'rgba(255, 255, 255, 0.15)' : 'rgba(0, 0, 0, 0.15)'
}; border-top: none; border-radius: 0 0 12px 12px; background: ${
dark ? 'rgba(0, 0, 0, 0.91)' : 'rgba(255, 255, 255, 0.91)'
}; color: ${dark ? '#646464' : '#8D97A0'};"><b style="color: ${
dark ? 'white' : 'rgba(0, 0, 0, 0.91)'
};">$` +
formatCompact(series[seriesIndex][dataPointIndex]) +
'</b></span>' +
'</div>'
);
},
},
};
const series = [
{
name: 'Prices',
data,
},
];
const classes = useStyles();
return (
<Box display='flex' mt={2.5} width={width}>
<Box className={classes.chartContainer}>
<Chart
options={options}
series={series}
type='area'
width='100%'
height={height}
/>
<Box className={classes.categoryValues}>
{categories.map((val, ind) => (
<Typography key={ind}>{val}</Typography>
))}
</Box>
</Box>
{yAxisValues && (
<Box className={classes.yAxis}>
{yAxisValues.map((value, index) => (
<Typography key={index}>
$
{// this is to show small numbers less than 0.0001
value > 0.0001 ? formatCompact(value) : formatNumber(value)}
</Typography>
))}
</Box>
)}
</Box>
);
}
Example #2
Source File: FarmCardDetails.tsx From interface-v2 with GNU General Public License v3.0 | 4 votes |
FarmCardDetails: React.FC<{
stakingInfo: StakingInfo | DualStakingInfo;
stakingAPY: number;
isLPFarm?: boolean;
}> = ({ stakingInfo, stakingAPY, isLPFarm }) => {
const classes = useStyles();
const { t } = useTranslation();
const { palette, breakpoints } = useTheme();
const isMobile = useMediaQuery(breakpoints.down('xs'));
const [stakeAmount, setStakeAmount] = useState('');
const [attemptStaking, setAttemptStaking] = useState(false);
const [attemptUnstaking, setAttemptUnstaking] = useState(false);
const [attemptClaiming, setAttemptClaiming] = useState(false);
const [approving, setApproving] = useState(false);
const [unstakeAmount, setUnStakeAmount] = useState('');
const lpStakingInfo = stakingInfo as StakingInfo;
const dualStakingInfo = stakingInfo as DualStakingInfo;
const token0 = stakingInfo ? stakingInfo.tokens[0] : undefined;
const token1 = stakingInfo ? stakingInfo.tokens[1] : undefined;
const { account, library } = useActiveWeb3React();
const addTransaction = useTransactionAdder();
const currency0 = token0 ? unwrappedToken(token0) : undefined;
const currency1 = token1 ? unwrappedToken(token1) : undefined;
const userLiquidityUnstaked = useTokenBalance(
account ?? undefined,
stakingInfo.stakedAmount?.token,
);
const stakedAmounts = getStakedAmountStakingInfo(
stakingInfo,
userLiquidityUnstaked,
);
let apyWithFee: number | string = 0;
if (
stakingInfo &&
stakingInfo.perMonthReturnInRewards &&
stakingAPY &&
stakingAPY > 0
) {
apyWithFee = formatAPY(
getAPYWithFee(stakingInfo.perMonthReturnInRewards, stakingAPY),
);
}
const stakingContract = useStakingContract(stakingInfo?.stakingRewardAddress);
const { parsedAmount: unstakeParsedAmount } = useDerivedStakeInfo(
unstakeAmount,
stakingInfo.stakedAmount?.token,
stakingInfo.stakedAmount,
);
const onWithdraw = async () => {
if (stakingInfo && stakingContract && unstakeParsedAmount) {
setAttemptUnstaking(true);
await stakingContract
.withdraw(`0x${unstakeParsedAmount.raw.toString(16)}`, {
gasLimit: 300000,
})
.then(async (response: TransactionResponse) => {
addTransaction(response, {
summary: t('withdrawliquidity'),
});
try {
await response.wait();
setAttemptUnstaking(false);
} catch (error) {
setAttemptUnstaking(false);
}
})
.catch((error: any) => {
setAttemptUnstaking(false);
console.log(error);
});
}
};
const onClaimReward = async () => {
if (stakingContract && stakingInfo && stakingInfo.stakedAmount) {
setAttemptClaiming(true);
await stakingContract
.getReward({ gasLimit: 350000 })
.then(async (response: TransactionResponse) => {
addTransaction(response, {
summary: t('claimrewards'),
});
try {
await response.wait();
setAttemptClaiming(false);
} catch (error) {
setAttemptClaiming(false);
}
})
.catch((error: any) => {
setAttemptClaiming(false);
console.log(error);
});
}
};
const { parsedAmount } = useDerivedStakeInfo(
stakeAmount,
stakingInfo.stakedAmount?.token,
userLiquidityUnstaked,
);
const deadline = useTransactionDeadline();
const [approval, approveCallback] = useApproveCallback(
parsedAmount,
stakingInfo?.stakingRewardAddress,
);
const dummyPair = stakingInfo
? new Pair(
new TokenAmount(stakingInfo.tokens[0], '0'),
new TokenAmount(stakingInfo.tokens[1], '0'),
)
: null;
const pairContract = usePairContract(
stakingInfo && stakingInfo.lp && stakingInfo.lp !== ''
? stakingInfo.lp
: dummyPair?.liquidityToken.address,
);
const onStake = async () => {
if (stakingContract && parsedAmount && deadline) {
setAttemptStaking(true);
stakingContract
.stake(`0x${parsedAmount.raw.toString(16)}`, {
gasLimit: 350000,
})
.then(async (response: TransactionResponse) => {
addTransaction(response, {
summary: t('depositliquidity'),
});
try {
await response.wait();
setAttemptStaking(false);
} catch (error) {
setAttemptStaking(false);
}
})
.catch((error: any) => {
setAttemptStaking(false);
console.log(error);
});
} else {
throw new Error(t('stakewithoutapproval'));
}
};
const onAttemptToApprove = async () => {
if (!pairContract || !library || !deadline)
throw new Error(t('missingdependencies'));
const liquidityAmount = parsedAmount;
if (!liquidityAmount) throw new Error(t('missingliquidity'));
setApproving(true);
try {
await approveCallback();
setApproving(false);
} catch (e) {
setApproving(false);
}
};
const earnedUSDStr = isLPFarm
? getEarnedUSDLPFarm(lpStakingInfo)
: getEarnedUSDDualFarm(dualStakingInfo);
const tvl = getTVLStaking(
stakedAmounts?.totalStakedUSD,
stakedAmounts?.totalStakedBase,
);
const lpRewards = lpStakingInfo.rate * lpStakingInfo.rewardTokenPrice;
const lpPoolRate = getRewardRate(
lpStakingInfo.totalRewardRate,
lpStakingInfo.rewardToken,
);
const dualRewards =
dualStakingInfo.rateA * dualStakingInfo.rewardTokenAPrice +
dualStakingInfo.rateB * Number(dualStakingInfo.rewardTokenBPrice);
const dualPoolRateA = getRewardRate(
dualStakingInfo.totalRewardRateA,
dualStakingInfo.rewardTokenA,
);
const dualPoolRateB = getRewardRate(
dualStakingInfo.totalRewardRateB,
dualStakingInfo.rewardTokenB,
);
const mainRewardRate = isLPFarm
? lpStakingInfo.rewardRate
: dualStakingInfo.rewardRateA;
const stakeEnabled =
!approving &&
!attemptStaking &&
Number(stakeAmount) > 0 &&
Number(stakeAmount) <= getExactTokenAmount(userLiquidityUnstaked);
const unstakeEnabled =
!attemptUnstaking &&
Number(unstakeAmount) > 0 &&
Number(unstakeAmount) <= getExactTokenAmount(stakingInfo.stakedAmount);
const claimEnabled =
!attemptClaiming &&
(isLPFarm
? lpStakingInfo.earnedAmount &&
lpStakingInfo.earnedAmount.greaterThan('0')
: dualStakingInfo.earnedAmountA &&
dualStakingInfo.earnedAmountA.greaterThan('0'));
return (
<>
<Box
width='100%'
p={2}
display='flex'
flexDirection='row'
flexWrap='wrap'
borderTop='1px solid #444444'
alignItems='center'
justifyContent={stakingInfo?.ended ? 'flex-end' : 'space-between'}
>
{stakingInfo && (
<>
{isMobile && (
<>
<Box
mt={2}
width={1}
display='flex'
justifyContent='space-between'
>
<Typography variant='body2' color='textSecondary'>
{t('tvl')}
</Typography>
<Typography variant='body2'>{tvl}</Typography>
</Box>
<Box
mt={2}
width={1}
display='flex'
justifyContent='space-between'
>
<Typography variant='body2' color='textSecondary'>
{t('rewards')}
</Typography>
<Box textAlign='right'>
<Typography variant='body2'>
${(isLPFarm ? lpRewards : dualRewards).toLocaleString()} /
{t('day')}
</Typography>
{isLPFarm ? (
<Typography variant='body2'>{lpPoolRate}</Typography>
) : (
<>
<Typography variant='body2'>{dualPoolRateA}</Typography>
<Typography variant='body2'>{dualPoolRateB}</Typography>
</>
)}
</Box>
</Box>
<Box
mt={2}
width={1}
display='flex'
justifyContent='space-between'
>
<Box display='flex' alignItems='center'>
<Typography variant='body2' color='textSecondary'>
{t('apy')}
</Typography>
<Box ml={0.5} height={16}>
<img src={CircleInfoIcon} alt={'arrow up'} />
</Box>
</Box>
<Box color={palette.success.main}>
<Typography variant='body2'>{apyWithFee}%</Typography>
</Box>
</Box>
</>
)}
{!stakingInfo.ended && (
<Box className={classes.buttonWrapper} mt={isMobile ? 2 : 0}>
<Box display='flex' justifyContent='space-between'>
<Typography variant='body2'>{t('inwallet')}:</Typography>
<Box
display='flex'
flexDirection='column'
alignItems='flex-end'
justifyContent='flex-start'
>
<Typography variant='body2'>
{formatTokenAmount(userLiquidityUnstaked)} {t('lp')}{' '}
<span>({getUSDString(stakedAmounts?.unStakedUSD)})</span>
</Typography>
<Link
to={`/pools?currency0=${getTokenAddress(
token0,
)}¤cy1=${getTokenAddress(token1)}`}
style={{ color: palette.primary.main }}
>
{t('get')} {currency0?.symbol} / {currency1?.symbol}{' '}
{t('lp')}
</Link>
</Box>
</Box>
<Box className={classes.inputVal} mb={2} mt={2} p={2}>
<NumericalInput
placeholder='0.00'
value={stakeAmount}
fontSize={16}
onUserInput={(value) => {
setStakeAmount(value);
}}
/>
<Typography
variant='body2'
style={{
color:
userLiquidityUnstaked &&
userLiquidityUnstaked.greaterThan('0')
? palette.primary.main
: palette.text.hint,
}}
onClick={() => {
if (
userLiquidityUnstaked &&
userLiquidityUnstaked.greaterThan('0')
) {
setStakeAmount(userLiquidityUnstaked.toExact());
} else {
setStakeAmount('');
}
}}
>
{t('max')}
</Typography>
</Box>
<Box
className={
stakeEnabled ? classes.buttonClaim : classes.buttonToken
}
mt={2}
p={2}
onClick={async () => {
if (stakeEnabled) {
if (approval === ApprovalState.APPROVED) {
onStake();
} else {
onAttemptToApprove();
}
}
}}
>
<Typography variant='body1'>
{attemptStaking
? t('stakingLPTokens')
: approval === ApprovalState.APPROVED
? t('stakeLPTokens')
: approving
? t('approving')
: t('approve')}
</Typography>
</Box>
</Box>
)}
<Box className={classes.buttonWrapper} mx={isMobile ? 0 : 2} my={2}>
<Box display='flex' justifyContent='space-between'>
<Typography variant='body2'>{t('mydeposits')}:</Typography>
<Typography variant='body2'>
{formatTokenAmount(stakingInfo.stakedAmount)} {t('lp')}{' '}
<span>({getUSDString(stakedAmounts?.myStakedUSD)})</span>
</Typography>
</Box>
<Box className={classes.inputVal} mb={2} mt={4.5} p={2}>
<NumericalInput
placeholder='0.00'
value={unstakeAmount}
fontSize={16}
onUserInput={(value) => {
setUnStakeAmount(value);
}}
/>
<Typography
variant='body2'
style={{
color:
stakingInfo.stakedAmount &&
stakingInfo.stakedAmount.greaterThan('0')
? palette.primary.main
: palette.text.hint,
}}
onClick={() => {
if (
stakingInfo.stakedAmount &&
stakingInfo.stakedAmount.greaterThan('0')
) {
setUnStakeAmount(stakingInfo.stakedAmount.toExact());
} else {
setUnStakeAmount('');
}
}}
>
{t('max')}
</Typography>
</Box>
<Box
className={
unstakeEnabled ? classes.buttonClaim : classes.buttonToken
}
mt={2}
p={2}
onClick={() => {
if (unstakeEnabled) {
onWithdraw();
}
}}
>
<Typography variant='body1'>
{attemptUnstaking
? t('unstakingLPTokens')
: t('unstakeLPTokens')}
</Typography>
</Box>
</Box>
<Box className={classes.buttonWrapper}>
<Box
display='flex'
flexDirection='column'
alignItems='center'
justifyContent='space-between'
>
<Box mb={1}>
<Typography variant='body2'>
{t('unclaimedRewards')}:
</Typography>
</Box>
{isLPFarm ? (
<>
<Box mb={1}>
<CurrencyLogo currency={lpStakingInfo.rewardToken} />
</Box>
<Box mb={1} textAlign='center'>
<Typography variant='body1' color='textSecondary'>
{formatTokenAmount(lpStakingInfo.earnedAmount)}
<span> {lpStakingInfo.rewardToken.symbol}</span>
</Typography>
<Typography variant='body2'>{earnedUSDStr}</Typography>
</Box>
</>
) : (
<>
<Box mb={1} display='flex'>
<CurrencyLogo
currency={unwrappedToken(dualStakingInfo.rewardTokenA)}
/>
<CurrencyLogo
currency={unwrappedToken(dualStakingInfo.rewardTokenB)}
/>
</Box>
<Box mb={1} textAlign='center'>
<Typography variant='body1'>{earnedUSDStr}</Typography>
<Typography variant='body1' color='textSecondary'>
{formatTokenAmount(dualStakingInfo.earnedAmountA)}
<span> {dualStakingInfo.rewardTokenA.symbol}</span>
</Typography>
<Typography variant='body1' color='textSecondary'>
{formatTokenAmount(dualStakingInfo.earnedAmountB)}
<span> {dualStakingInfo.rewardTokenB.symbol}</span>
</Typography>
</Box>
</>
)}
</Box>
<Box
className={
claimEnabled ? classes.buttonClaim : classes.buttonToken
}
p={2}
onClick={() => {
if (claimEnabled) {
onClaimReward();
}
}}
>
<Typography variant='body1'>
{attemptClaiming ? t('claiming') : t('claim')}
</Typography>
</Box>
</Box>
</>
)}
</Box>
{mainRewardRate?.greaterThan('0') && (
<Box className={classes.dailyRateWrapper}>
<Box
display='flex'
alignItems='center'
justifyContent={isMobile ? 'space-between' : 'flex-start'}
mr={isMobile ? 0 : 1.5}
width={isMobile ? 1 : 'auto'}
mb={isMobile ? 1 : 0}
flexWrap='wrap'
>
<Box display='flex' mr={1}>
<Typography variant='body2' color='textSecondary'>
{t('yourRate', {
symbol: isLPFarm ? '' : dualStakingInfo.rewardTokenA.symbol,
})}
:
</Typography>
</Box>
<Typography variant='body2' color='textPrimary'>
{formatMulDivTokenAmount(
mainRewardRate,
GlobalConst.utils.ONEDAYSECONDS,
)}{' '}
{isLPFarm
? lpStakingInfo.rewardToken.symbol
: dualStakingInfo.rewardTokenA.symbol}{' '}
/ {t('day')}
</Typography>
</Box>
{!isLPFarm && (
<Box
display='flex'
alignItems='center'
justifyContent={isMobile ? 'space-between' : 'flex-start'}
mr={isMobile ? 0 : 1.5}
width={isMobile ? 1 : 'auto'}
mb={isMobile ? 1 : 0}
flexWrap='wrap'
>
<Box display='flex' mr={1}>
<Typography variant='body2' color='textSecondary'>
{t('yourRate', {
symbol: dualStakingInfo.rewardTokenB.symbol,
})}
:
</Typography>
</Box>
<Typography variant='body2' color='textPrimary'>
{formatMulDivTokenAmount(
dualStakingInfo.rewardRateB,
GlobalConst.utils.ONEDAYSECONDS,
)}{' '}
{dualStakingInfo.rewardTokenB.symbol} / {t('day')}
</Typography>
</Box>
)}
<Box
display='flex'
justifyContent={isMobile ? 'space-between' : 'flex-start'}
alignItems='center'
width={isMobile ? 1 : 'auto'}
flexWrap='wrap'
>
<Box display='flex' mr={1}>
<Typography variant='body2' color='textSecondary'>
{t('yourFees')}:
</Typography>
</Box>
<Typography variant='body2' color='textPrimary'>
${formatNumber(stakingInfo.accountFee)} / {t('day')}
</Typography>
</Box>
</Box>
)}
</>
);
}
Example #3
Source File: StakeSyrupModal.tsx From interface-v2 with GNU General Public License v3.0 | 4 votes |
StakeSyrupModal: React.FC<StakeSyrupModalProps> = ({
open,
onClose,
syrup,
}) => {
const classes = useStyles();
const { palette } = useTheme();
const [attempting, setAttempting] = useState(false);
const [hash, setHash] = useState('');
const { account, chainId, library } = useActiveWeb3React();
const addTransaction = useTransactionAdder();
const finalizedTransaction = useTransactionFinalizer();
const userLiquidityUnstaked = useTokenBalance(
account ?? undefined,
syrup.stakedAmount?.token,
);
const [typedValue, setTypedValue] = useState('');
const [stakePercent, setStakePercent] = useState(0);
const [approving, setApproving] = useState(false);
const maxAmountInput = maxAmountSpend(userLiquidityUnstaked);
const { parsedAmount, error } = useDerivedSyrupInfo(
typedValue,
syrup.stakedAmount?.token,
userLiquidityUnstaked,
);
const parsedAmountWrapped = wrappedCurrencyAmount(parsedAmount, chainId);
let hypotheticalRewardRate = syrup.rewardRate
? new TokenAmount(syrup.rewardRate.token, '0')
: undefined;
if (parsedAmountWrapped && parsedAmountWrapped.greaterThan('0')) {
hypotheticalRewardRate =
syrup.stakedAmount && syrup.totalStakedAmount
? syrup.getHypotheticalRewardRate(
syrup.stakedAmount.add(parsedAmountWrapped),
syrup.totalStakedAmount.add(parsedAmountWrapped),
)
: undefined;
}
const deadline = useTransactionDeadline();
const [approval, approveCallback] = useApproveCallback(
parsedAmount,
syrup.stakingRewardAddress,
);
const [signatureData, setSignatureData] = useState<{
v: number;
r: string;
s: string;
deadline: number;
} | null>(null);
const stakingContract = useStakingContract(syrup.stakingRewardAddress);
const onAttemptToApprove = async () => {
if (!library || !deadline) throw new Error('missing dependencies');
const liquidityAmount = parsedAmount;
if (!liquidityAmount) throw new Error('missing liquidity amount');
return approveCallback();
};
const onStake = async () => {
setAttempting(true);
if (stakingContract && parsedAmount && deadline) {
if (approval === ApprovalState.APPROVED) {
stakingContract
.stake(`0x${parsedAmount.raw.toString(16)}`, { gasLimit: 350000 })
.then(async (response: TransactionResponse) => {
addTransaction(response, {
summary: `Deposit ${syrup.stakingToken.symbol}`,
});
try {
const receipt = await response.wait();
finalizedTransaction(receipt, {
summary: `Deposit ${syrup.stakingToken.symbol}`,
});
setAttempting(false);
setStakePercent(0);
setTypedValue('');
} catch (e) {
setAttempting(false);
setStakePercent(0);
setTypedValue('');
}
})
.catch((error: any) => {
setAttempting(false);
console.log(error);
});
} else if (signatureData) {
stakingContract
.stakeWithPermit(
`0x${parsedAmount.raw.toString(16)}`,
signatureData.deadline,
signatureData.v,
signatureData.r,
signatureData.s,
{ gasLimit: 350000 },
)
.then((response: TransactionResponse) => {
addTransaction(response, {
summary: `Deposit liquidity`,
});
setHash(response.hash);
})
.catch((error: any) => {
setAttempting(false);
console.log(error);
});
} else {
setAttempting(false);
throw new Error(
'Attempting to stake without approval or a signature. Please contact support.',
);
}
}
};
return (
<CustomModal open={open} onClose={onClose}>
<Box paddingX={3} paddingY={4}>
<Box display='flex' alignItems='center' justifyContent='space-between'>
<Typography variant='h5'>
Stake {syrup.stakingToken.symbol}
</Typography>
<CloseIcon style={{ cursor: 'pointer' }} onClick={onClose} />
</Box>
<Box
mt={3}
bgcolor={palette.background.default}
border='1px solid rgba(105, 108, 128, 0.12)'
borderRadius='10px'
padding='16px'
>
<Box
display='flex'
alignItems='center'
justifyContent='space-between'
>
<Typography variant='body2'>{syrup.stakingToken.symbol}</Typography>
<Typography variant='body2'>
Balance: {formatTokenAmount(maxAmountInput)}
</Typography>
</Box>
<Box mt={2} display='flex' alignItems='center'>
<NumericalInput
placeholder='0'
value={typedValue}
fontSize={28}
onUserInput={(value) => {
setSignatureData(null);
const totalBalance = getExactTokenAmount(maxAmountInput);
const exactTypedValue = getValueTokenDecimals(
value,
syrup.stakedAmount?.token,
);
// this is to avoid input amount more than balance
if (Number(exactTypedValue) <= totalBalance) {
setTypedValue(exactTypedValue);
setStakePercent(
totalBalance > 0
? (Number(exactTypedValue) / totalBalance) * 100
: 0,
);
}
}}
/>
<Typography
variant='caption'
style={{
color: palette.primary.main,
fontWeight: 'bold',
cursor: 'pointer',
}}
onClick={() => {
setTypedValue(maxAmountInput ? maxAmountInput.toExact() : '0');
setStakePercent(100);
}}
>
MAX
</Typography>
</Box>
<Box display='flex' alignItems='center'>
<Box flex={1} mr={2} mt={0.5}>
<ColoredSlider
min={1}
max={100}
step={1}
value={stakePercent}
onChange={(_, value) => {
const percent = value as number;
setStakePercent(percent);
setTypedValue(getPartialTokenAmount(percent, maxAmountInput));
}}
/>
</Box>
<Typography variant='body2'>
{Math.min(stakePercent, 100).toLocaleString()}%
</Typography>
</Box>
</Box>
<Box
mt={2}
display='flex'
alignItems='center'
justifyContent='space-between'
>
<Typography variant='body1'>Daily Rewards</Typography>
<Typography variant='body1'>
{hypotheticalRewardRate
? formatNumber(
Number(hypotheticalRewardRate.toExact()) * getSecondsOneDay(),
)
: '-'}{' '}
{syrup.token.symbol} / day
</Typography>
</Box>
<Box
mt={3}
display='flex'
justifyContent='space-between'
alignItems='center'
>
<Button
className={classes.stakeButton}
disabled={approving || approval !== ApprovalState.NOT_APPROVED}
onClick={async () => {
setApproving(true);
try {
await onAttemptToApprove();
setApproving(false);
} catch (e) {
setApproving(false);
}
}}
>
{approving ? 'Approving...' : 'Approve'}
</Button>
<Button
className={classes.stakeButton}
disabled={
!!error || attempting || approval !== ApprovalState.APPROVED
}
onClick={onStake}
>
{attempting ? 'Staking...' : 'Stake'}
</Button>
</Box>
</Box>
</CustomModal>
);
}
Example #4
Source File: SwapTokenDetails.tsx From interface-v2 with GNU General Public License v3.0 | 4 votes |
SwapTokenDetails: React.FC<{
token: Token;
}> = ({ token }) => {
const classes = useStyles();
const currency = unwrappedToken(token);
const tokenAddress = token.address;
const { palette } = useTheme();
const latestBlock = useBlockNumber();
const { tokenDetails, updateTokenDetails } = useTokenDetails();
const [tokenData, setTokenData] = useState<any>(null);
const [priceData, setPriceData] = useState<any>(null);
const priceUp = Number(tokenData?.priceChangeUSD) > 0;
const priceUpPercent = Number(tokenData?.priceChangeUSD).toFixed(2);
const [isCopied, setCopied] = useCopyClipboard();
const prices = priceData ? priceData.map((price: any) => price.close) : [];
useEffect(() => {
async function fetchTokenData() {
const tokenDetail = tokenDetails.find(
(item) => item.address === tokenAddress,
);
setTokenData(tokenDetail?.tokenData);
setPriceData(tokenDetail?.priceData);
const currentTime = dayjs.utc();
const startTime = currentTime
.subtract(1, 'day')
.startOf('hour')
.unix();
const tokenPriceData = await getIntervalTokenData(
tokenAddress,
startTime,
3600,
latestBlock,
);
setPriceData(tokenPriceData);
const [newPrice, oneDayPrice] = await getEthPrice();
const tokenInfo = await getTokenInfo(newPrice, oneDayPrice, tokenAddress);
if (tokenInfo) {
const token0 = tokenInfo[0];
setTokenData(token0);
const tokenDetailToUpdate = {
address: tokenAddress,
tokenData: token0,
priceData: tokenPriceData,
};
updateTokenDetails(tokenDetailToUpdate);
}
}
fetchTokenData();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [tokenAddress]);
return (
<Box>
<Box
display='flex'
alignItems='center'
justifyContent='space-between'
px={2}
py={1.5}
>
<Box display='flex' alignItems='center'>
<CurrencyLogo currency={currency} size='28px' />
<Box ml={1}>
<Typography variant='body2'>{currency.symbol}</Typography>
{tokenData ? (
<Box display='flex' alignItems='center'>
<Typography variant='body2'>
${formatNumber(tokenData.priceUSD)}
</Typography>
<Box
ml={0.5}
display='flex'
alignItems='center'
className={priceUp ? classes.success : classes.danger}
>
{priceUp ? <ArrowDropUp /> : <ArrowDropDown />}
<Typography variant='body2'>{priceUpPercent}%</Typography>
</Box>
</Box>
) : (
<Skeleton variant='rect' width={100} height={20} />
)}
</Box>
</Box>
{tokenData && priceData ? (
<Box width={88} height={47} position='relative'>
<Box position='absolute' top={-30} width={1}>
{prices.length > 0 && (
<LineChart
data={prices}
width='100%'
height={120}
color={priceUp ? palette.success.main : palette.error.main}
/>
)}
</Box>
</Box>
) : (
<Skeleton variant='rect' width={88} height={47} />
)}
</Box>
<Box
borderTop={`1px solid ${palette.secondary.light}`}
borderBottom={`1px solid ${palette.secondary.light}`}
px={2}
>
<Grid container>
<Grid item xs={6}>
<Box borderRight={`1px solid ${palette.secondary.light}`} py={1}>
{tokenData ? (
<Typography
variant='body2'
style={{ color: palette.text.secondary }}
>
TVL: {formatCompact(tokenData?.totalLiquidityUSD)}
</Typography>
) : (
<Skeleton variant='rect' width={100} height={16} />
)}
</Box>
</Grid>
<Grid item xs={6}>
<Box py={1} pl={2}>
{tokenData ? (
<Typography
variant='body2'
style={{ color: palette.text.secondary }}
>
24h VOL: {formatCompact(tokenData?.oneDayVolumeUSD)}
</Typography>
) : (
<Skeleton variant='rect' width={100} height={16} />
)}
</Box>
</Grid>
</Grid>
</Box>
<Box
display='flex'
justifyContent='space-between'
alignItems='center'
py={1}
px={2}
>
<a
href={`https://polygonscan.com/token/${tokenAddress}`}
target='_blank'
rel='noopener noreferrer'
style={{ textDecoration: 'none' }}
>
<Typography variant='body2' style={{ color: palette.primary.main }}>
{shortenAddress(tokenAddress)}
</Typography>
</a>
<Box
display='flex'
style={{ cursor: 'pointer', opacity: isCopied ? 0.5 : 1 }}
onClick={() => {
setCopied(tokenAddress);
}}
>
<CopyIcon />
</Box>
</Box>
</Box>
);
}
Example #5
Source File: TokensTable.tsx From interface-v2 with GNU General Public License v3.0 | 4 votes |
TokensTable: React.FC<TokensTableProps> = ({ data }) => {
const tokenHeadCells = headCells();
const classes = useStyles();
const { palette } = useTheme();
const {
bookmarkTokens,
addBookmarkToken,
removeBookmarkToken,
} = useBookmarkTokens();
const mobileHTML = (token: any, index: number) => {
const tokenCurrency = new Token(
ChainId.MATIC,
getAddress(token.id),
Number(token.decimals),
token.symbol,
token.name,
);
const priceColor = getPriceColor(Number(token.priceChangeUSD), palette);
return (
<Box mt={index === 0 ? 0 : 3}>
<Box display='flex' alignItems='center' mb={1}>
<Box
display='flex'
mr={1}
onClick={() => {
const tokenIndex = bookmarkTokens.indexOf(token.id);
if (tokenIndex === -1) {
addBookmarkToken(token.id);
} else {
removeBookmarkToken(token.id);
}
}}
>
{bookmarkTokens.indexOf(token.id) > -1 ? (
<StarChecked />
) : (
<StarUnchecked />
)}
</Box>
<Link
to={`/analytics/token/${tokenCurrency.address}`}
style={{ textDecoration: 'none' }}
>
<Box display='flex' alignItems='center'>
<CurrencyLogo currency={tokenCurrency} size='28px' />
<Box ml={1}>
<Typography
variant='body1'
style={{ color: palette.text.primary }}
>
{token.name}{' '}
<span style={{ color: palette.text.hint }}>
({token.symbol})
</span>
</Typography>
</Box>
</Box>
</Link>
</Box>
<Divider />
<Box className={classes.mobileRow}>
<Typography variant='body1'>Price</Typography>
<Typography variant='body1'>
${formatNumber(token.priceUSD)}
</Typography>
</Box>
<Box className={classes.mobileRow}>
<Typography variant='body1'>24H %</Typography>
<Box
className={classes.priceChangeWrapper}
bgcolor={priceColor.bgColor}
color={priceColor.textColor}
>
<Typography variant='body2'>
{getFormattedPrice(Number(token.priceChangeUSD))}%
</Typography>
</Box>
</Box>
<Box className={classes.mobileRow}>
<Typography variant='body1'>24H Volume</Typography>
<Typography variant='body1'>
${Number(token.oneDayVolumeUSD).toLocaleString()}
</Typography>
</Box>
<Box className={classes.mobileRow}>
<Typography variant='body1'>Liquidity</Typography>
<Typography variant='body1'>
${Number(token.totalLiquidityUSD).toLocaleString()}
</Typography>
</Box>
</Box>
);
};
const desktopHTML = (token: any) => {
const tokenCurrency = new Token(
ChainId.MATIC,
getAddress(token.id),
Number(token.decimals),
token.symbol,
token.name,
);
const priceColor = getPriceColor(Number(token.priceChangeUSD), palette);
return [
{
html: (
<Box display='flex' alignItems='center'>
<Box
display='flex'
mr={1}
onClick={() => {
const tokenIndex = bookmarkTokens.indexOf(token.id);
if (tokenIndex === -1) {
addBookmarkToken(token.id);
} else {
removeBookmarkToken(token.id);
}
}}
>
{bookmarkTokens.indexOf(token.id) > -1 ? (
<StarChecked />
) : (
<StarUnchecked />
)}
</Box>
<Link
to={`/analytics/token/${tokenCurrency.address}`}
style={{ textDecoration: 'none' }}
>
<Box display='flex' alignItems='center'>
<CurrencyLogo currency={tokenCurrency} size='28px' />
<Box ml={1}>
<Typography
variant='body1'
style={{ color: palette.text.primary }}
>
{token.name}{' '}
<span style={{ color: palette.text.hint }}>
({token.symbol})
</span>
</Typography>
</Box>
</Box>
</Link>
</Box>
),
},
{
html: (
<Box>
<Typography>${Number(token.priceUSD).toLocaleString()}</Typography>
</Box>
),
},
{
html: (
<Box
className={classes.priceChangeWrapper}
mr={2}
bgcolor={priceColor.bgColor}
color={priceColor.textColor}
>
<Typography variant='body2'>
{getFormattedPrice(Number(token.priceChangeUSD))}%
</Typography>
</Box>
),
},
{
html: (
<Box>
<Typography>
${Number(token.oneDayVolumeUSD).toLocaleString()}
</Typography>
</Box>
),
},
{
html: (
<Box>
<Typography>
${Number(token.totalLiquidityUSD).toLocaleString()}
</Typography>
</Box>
),
},
];
};
return (
<CustomTable
defaultOrderBy={tokenHeadCells[liquidityHeadCellIndex]}
defaultOrder='desc'
showPagination={data.length > GlobalConst.utils.ROWSPERPAGE}
headCells={tokenHeadCells}
rowsPerPage={GlobalConst.utils.ROWSPERPAGE}
data={data}
mobileHTML={mobileHTML}
desktopHTML={desktopHTML}
/>
);
}
Example #6
Source File: TopMovers.tsx From interface-v2 with GNU General Public License v3.0 | 4 votes |
TopMovers: React.FC<TopMoversProps> = ({
background,
hideArrow = false,
}) => {
const classes = useStyles();
const { palette, breakpoints } = useTheme();
const [topTokens, updateTopTokens] = useState<any[] | null>(null);
const smallWindowSize = useMediaQuery(breakpoints.down('xs'));
const topMoverTokens = useMemo(
() => (topTokens && topTokens.length >= 5 ? topTokens.slice(0, 5) : null),
[topTokens],
);
useEffect(() => {
async function fetchTopTokens() {
const [newPrice, oneDayPrice] = await getEthPrice();
const topTokensData = await getTopTokens(newPrice, oneDayPrice, 5);
if (topTokensData) {
updateTopTokens(topTokensData);
}
}
fetchTopTokens();
}, [updateTopTokens]);
return (
<Box
width='100%'
display='flex'
flexWrap='wrap'
flexDirection='column'
justifyContent='center'
alignItems={smallWindowSize ? 'center' : 'flex-start'}
bgcolor={background}
border={`1px solid ${
background === 'transparent' ? palette.background.paper : 'transparent'
}`}
borderRadius={10}
px={2.5}
pt={2.5}
pb={0.5}
>
<Typography variant='h6' style={{ color: palette.text.secondary }}>
24h TOP MOVERS
</Typography>
<Box width={1} pb={2} style={{ overflowX: 'auto' }}>
{topMoverTokens ? (
<Box className={classes.content}>
{topMoverTokens.map((token: any, index: number) => {
const currency = new Token(
ChainId.MATIC,
getAddress(token.id),
token.decimals,
);
const priceColor = getPriceColor(
Number(token.priceChangeUSD),
palette,
);
const priceUp = Number(token.priceChangeUSD) > 0;
const priceDown = Number(token.priceChangeUSD) < 0;
const priceUpPercent = Number(token.priceChangeUSD).toFixed(2);
return (
<Box
mr={index < topMoverTokens.length ? 2 : 0}
width={smallWindowSize ? 180 : 'unset'}
mt={2}
key={token.id}
display='flex'
flexDirection='row'
justifyContent={smallWindowSize ? 'flex-start' : 'center'}
alignItems='center'
>
<CurrencyLogo currency={currency} size='28px' />
<Box ml={1}>
<Typography variant='body2' style={{ fontWeight: 'bold' }}>
{token.symbol}
</Typography>
<Box
display='flex'
flexDirection='row'
justifyContent='center'
alignItems='center'
>
<Typography variant='body2'>
${formatNumber(token.priceUSD)}
</Typography>
<Box
ml={hideArrow ? 1 : 0}
display='flex'
flexDirection='row'
justifyContent='center'
alignItems='center'
px={0.75}
py={0.25}
borderRadius={12}
bgcolor={
!hideArrow ? 'transparent' : priceColor.bgColor
}
color={priceColor.textColor}
>
{!hideArrow && priceUp && <ArrowDropUp />}
{!hideArrow && priceDown && <ArrowDropDown />}
<Typography variant='caption'>
{hideArrow && priceUp ? '+' : ''}
{priceUpPercent}%
</Typography>
</Box>
</Box>
</Box>
</Box>
);
})}
</Box>
) : (
<Skeleton variant='rect' width='100%' height={100} />
)}
</Box>
</Box>
);
}
Example #7
Source File: TransactionsTable.tsx From interface-v2 with GNU General Public License v3.0 | 4 votes |
TransactionsTable: React.FC<TransactionsTableProps> = ({ data }) => {
const [txFilter, setTxFilter] = useState(-1);
const txHeadCells = headCells(txFilter, setTxFilter);
const classes = useStyles();
const { chainId } = useActiveWeb3React();
const { palette, breakpoints } = useTheme();
const isMobile = useMediaQuery(breakpoints.down('xs'));
const { t } = useTranslation();
const getTxString = (txn: any) => {
const messageData = {
token0Symbol: txn.pair.token1.symbol,
token1Symbol: txn.pair.token0.symbol,
};
if (txn.type === TxnType.SWAP) {
return t('txnSwapMessage', messageData);
} else if (txn.type === TxnType.ADD) {
return t('txnAddMessage', messageData);
} else if (txn.type === TxnType.REMOVE) {
return t('txnRemoveMessage', messageData);
}
return '';
};
const mobileHTML = (txn: any, index: number) => {
return (
<Box mt={index === 0 ? 0 : 3} key={index}>
<Box mb={1}>
{chainId ? (
<a
href={getEtherscanLink(
chainId,
txn.transaction.id,
'transaction',
)}
target='_blank'
rel='noopener noreferrer'
style={{ textDecoration: 'none' }}
>
<Typography
variant='body1'
style={{ color: palette.primary.main }}
>
{getTxString(txn)}
</Typography>
</a>
) : (
<Typography variant='body1' style={{ color: palette.primary.main }}>
{getTxString(txn)}
</Typography>
)}
</Box>
<Divider />
<Box className={classes.mobileRow}>
<Typography variant='body1'>Total Value</Typography>
<Typography variant='body1' color='textPrimary'>
${Number(txn.amountUSD).toLocaleString()}
</Typography>
</Box>
<Box className={classes.mobileRow}>
<Typography variant='body1'>Token Amount</Typography>
<Typography variant='body1' color='textPrimary'>
{formatNumber(txn.amount0)} {txn.pair.token0.symbol}
</Typography>
</Box>
<Box className={classes.mobileRow}>
<Typography variant='body1'>Token Amount</Typography>
<Typography variant='body1' color='textPrimary'>
{formatNumber(txn.amount1)} {txn.pair.token1.symbol}
</Typography>
</Box>
<Box className={classes.mobileRow}>
<Typography variant='body1'>TXN</Typography>
{chainId ? (
<a
href={getEtherscanLink(
chainId,
txn.transaction.id,
'transaction',
)}
target='_blank'
rel='noopener noreferrer'
style={{ textDecoration: 'none' }}
>
<Typography
variant='body1'
style={{ color: palette.primary.main }}
>
{shortenTx(txn.transaction.id)}
</Typography>
</a>
) : (
<Typography variant='body1' style={{ color: palette.primary.main }}>
{shortenTx(txn.transaction.id)}
</Typography>
)}
</Box>
<Box className={classes.mobileRow}>
<Typography variant='body1'>Time</Typography>
<Typography variant='body1' color='textPrimary'>
{dayjs(Number(txn.transaction.timestamp) * 1000).fromNow()}
</Typography>
</Box>
</Box>
);
};
const desktopHTML = (txn: any) => {
return [
{
html: chainId ? (
<a
href={getEtherscanLink(chainId, txn.transaction.id, 'transaction')}
target='_blank'
rel='noopener noreferrer'
style={{ textDecoration: 'none' }}
>
<Typography variant='body1' style={{ color: palette.primary.main }}>
{getTxString(txn)}
</Typography>
</a>
) : (
<Typography variant='body1' style={{ color: palette.primary.main }}>
{getTxString(txn)}
</Typography>
),
},
{
html: (
<Typography variant='body1' color='textPrimary'>
${Number(txn.amountUSD).toLocaleString()}
</Typography>
),
},
{
html: (
<Typography variant='body1' color='textPrimary'>
{formatNumber(txn.amount1)} {txn.pair.token1.symbol}
</Typography>
),
},
{
html: (
<Typography variant='body1' color='textPrimary'>
{formatNumber(txn.amount0)} {txn.pair.token0.symbol}
</Typography>
),
},
{
html: chainId ? (
<a
href={getEtherscanLink(chainId, txn.transaction.id, 'transaction')}
target='_blank'
rel='noopener noreferrer'
style={{ textDecoration: 'none' }}
>
<Typography variant='body1' style={{ color: palette.primary.main }}>
{shortenTx(txn.transaction.id)}
</Typography>
</a>
) : (
<Typography variant='body1' style={{ color: palette.primary.main }}>
{shortenTx(txn.transaction.id)}
</Typography>
),
},
{
html: (
<Typography variant='body1' color='textPrimary'>
{dayjs(Number(txn.transaction.timestamp) * 1000).fromNow()}
</Typography>
),
},
];
};
return (
<Box position='relative'>
{isMobile && (
<Box
display='flex'
alignItems='center'
position='absolute'
top={-48}
right={0}
>
<Box padding={1} onClick={() => setTxFilter(-1)}>
<Typography
variant='body1'
color={txFilter === -1 ? 'textPrimary' : 'textSecondary'}
>
All
</Typography>
</Box>
<Box padding={1} onClick={() => setTxFilter(TxnType.SWAP)}>
<Typography
variant='body1'
color={
txFilter === TxnType.SWAP ? 'textPrimary' : 'textSecondary'
}
>
Swap
</Typography>
</Box>
<Box padding={1} onClick={() => setTxFilter(TxnType.ADD)}>
<Typography
variant='body1'
color={txFilter === TxnType.ADD ? 'textPrimary' : 'textSecondary'}
>
Add
</Typography>
</Box>
<Box padding={1} onClick={() => setTxFilter(TxnType.REMOVE)}>
<Typography
variant='body1'
color={
txFilter === TxnType.REMOVE ? 'textPrimary' : 'textSecondary'
}
>
Remove
</Typography>
</Box>
</Box>
)}
<CustomTable
showPagination={data.length > 10}
headCells={txHeadCells}
defaultOrderBy={txHeadCells[5]}
rowsPerPage={10}
data={data.filter((item) =>
txFilter === -1 ? true : item.type === txFilter,
)}
mobileHTML={mobileHTML}
desktopHTML={desktopHTML}
/>
</Box>
);
}
Example #8
Source File: AnalyticsTokenChart.tsx From interface-v2 with GNU General Public License v3.0 | 4 votes |
AnalyticsTokenChart: React.FC<{ token: any }> = ({ token }) => {
const classes = useStyles();
const { palette } = useTheme();
const match = useRouteMatch<{ id: string }>();
const tokenAddress = match.params.id;
const [tokenChartData, updateTokenChartData] = useState<any>(null);
const chartIndexes = [CHART_VOLUME, CHART_LIQUIDITY, CHART_PRICE];
const chartIndexTexts = ['Volume', 'Liquidity', 'Price'];
const [chartIndex, setChartIndex] = useState(CHART_VOLUME);
const [durationIndex, setDurationIndex] = useState(
GlobalConst.analyticChart.ONE_MONTH_CHART,
);
const chartData = useMemo(() => {
if (!tokenChartData) return;
return tokenChartData.map((item: any) => {
switch (chartIndex) {
case CHART_VOLUME:
return Number(item.dailyVolumeUSD);
case CHART_LIQUIDITY:
return Number(item.totalLiquidityUSD);
case CHART_PRICE:
return Number(item.priceUSD);
default:
return;
}
});
}, [tokenChartData, chartIndex]);
const currentData = useMemo(() => {
if (!token) return;
switch (chartIndex) {
case CHART_VOLUME:
return token.oneDayVolumeUSD;
case CHART_LIQUIDITY:
return token.totalLiquidityUSD;
case CHART_PRICE:
return token.priceUSD;
default:
return;
}
}, [token, chartIndex]);
const currentPercent = useMemo(() => {
if (!token) return;
switch (chartIndex) {
case CHART_VOLUME:
return token.volumeChangeUSD;
case CHART_LIQUIDITY:
return token.liquidityChangeUSD;
case CHART_PRICE:
return token.priceChangeUSD;
default:
return;
}
}, [token, chartIndex]);
useEffect(() => {
async function fetchTokenChartData() {
updateTokenChartData(null);
const chartData = await getTokenChartData(
tokenAddress,
durationIndex === GlobalConst.analyticChart.ALL_CHART
? 0
: getChartStartTime(durationIndex),
);
if (chartData) {
const newChartData = getLimitedData(
chartData,
GlobalConst.analyticChart.CHART_COUNT,
);
updateTokenChartData(newChartData);
}
}
fetchTokenChartData();
}, [updateTokenChartData, tokenAddress, durationIndex]);
const currentPercentColor = getPriceColor(Number(currentPercent), palette);
return (
<>
<Box display='flex' flexWrap='wrap' justifyContent='space-between'>
<Box mt={1.5}>
<Typography variant='caption'>
{chartIndexTexts[chartIndex]}
</Typography>
<Box mt={1}>
{currentData && currentPercent ? (
<>
<Box display='flex' alignItems='center'>
<Typography
variant='h4'
style={{ color: palette.text.primary }}
>
$
{currentData > 100000
? formatCompact(currentData)
: formatNumber(currentData)}
</Typography>
<Box
className={classes.priceChangeWrapper}
ml={1}
bgcolor={currentPercentColor.bgColor}
color={currentPercentColor.textColor}
>
<Typography variant='body2'>
{getFormattedPrice(Number(currentPercent))}%
</Typography>
</Box>
</Box>
<Box>
<Typography variant='caption'>
{dayjs().format('MMM DD, YYYY')}
</Typography>
</Box>
</>
) : (
<Skeleton variant='rect' width='120px' height='30px' />
)}
</Box>
</Box>
<Box display='flex' flexDirection='column' alignItems='flex-end'>
<Box mt={1.5}>
<ChartType
chartTypes={chartIndexes}
typeTexts={chartIndexTexts}
chartType={chartIndex}
setChartType={setChartIndex}
/>
</Box>
<Box mt={1.5}>
<ChartType
chartTypes={GlobalData.analytics.CHART_DURATIONS}
typeTexts={GlobalData.analytics.CHART_DURATION_TEXTS}
chartType={durationIndex}
setChartType={setDurationIndex}
/>
</Box>
</Box>
</Box>
<Box mt={2} width={1}>
{tokenChartData ? (
<AreaChart
data={chartData}
yAxisValues={getYAXISValuesAnalytics(chartData)}
dates={tokenChartData.map((value: any) =>
dayjs(value.date * 1000)
.add(1, 'day')
.unix(),
)}
width='100%'
height={240}
categories={getChartDates(tokenChartData, durationIndex)}
/>
) : (
<Skeleton variant='rect' width='100%' height={217} />
)}
</Box>
</>
);
}
Example #9
Source File: AnalyticsTokenDetails.tsx From interface-v2 with GNU General Public License v3.0 | 4 votes |
AnalyticsTokenDetails: React.FC = () => {
const classes = useStyles();
const { palette, breakpoints } = useTheme();
const isMobile = useMediaQuery(breakpoints.down('xs'));
const history = useHistory();
const match = useRouteMatch<{ id: string }>();
const tokenAddress = match.params.id;
const [token, setToken] = useState<any>(null);
const { chainId } = useActiveWeb3React();
const currency = token
? new Token(ChainId.MATIC, getAddress(token.id), token.decimals)
: undefined;
const [tokenPairs, updateTokenPairs] = useState<any>(null);
const {
bookmarkTokens,
addBookmarkToken,
removeBookmarkToken,
} = useBookmarkTokens();
useEffect(() => {
async function fetchTokenInfo() {
const [newPrice, oneDayPrice] = await getEthPrice();
const tokenInfo = await getTokenInfo(newPrice, oneDayPrice, tokenAddress);
if (tokenInfo) {
setToken(tokenInfo[0]);
}
}
fetchTokenInfo();
}, [tokenAddress]);
useEffect(() => {
async function fetchTokenPairs() {
const [newPrice] = await getEthPrice();
const tokenPairs = await getTokenPairs2(tokenAddress);
const formattedPairs = tokenPairs
? tokenPairs.map((pair: any) => {
return pair.id;
})
: [];
const pairData = await getBulkPairData(formattedPairs, newPrice);
if (pairData) {
updateTokenPairs(pairData);
}
}
fetchTokenPairs();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [updateTokenPairs, tokenAddress]);
const tokenPercentColor = getPriceColor(
token ? Number(token.priceChangeUSD) : 0,
palette,
);
return (
<>
<AnalyticsHeader type='token' data={token} />
{token ? (
<>
<Box
width={1}
display='flex'
flexWrap='wrap'
justifyContent='space-between'
>
<Box display='flex'>
<CurrencyLogo currency={currency} size='32px' />
<Box ml={1.5}>
<Box display='flex' alignItems='center'>
<Box display='flex' alignItems='flex-end' mr={0.5}>
<Typography className={classes.heading1}>
{token.name}{' '}
</Typography>
<Typography className={classes.heading2}>
({token.symbol})
</Typography>
</Box>
{bookmarkTokens.includes(token.id) ? (
<StarChecked
onClick={() => removeBookmarkToken(token.id)}
/>
) : (
<StarUnchecked onClick={() => addBookmarkToken(token.id)} />
)}
</Box>
<Box mt={1.25} display='flex' alignItems='center'>
<Typography
variant='h5'
style={{ color: palette.text.primary }}
>
${formatNumber(token.priceUSD)}
</Typography>
<Box
className={classes.priceChangeWrapper}
ml={2}
bgcolor={tokenPercentColor.bgColor}
color={tokenPercentColor.textColor}
>
<Typography variant='body2'>
{getFormattedPrice(Number(token.priceChangeUSD))}%
</Typography>
</Box>
</Box>
</Box>
</Box>
<Box my={2} display='flex'>
<Box
className={classes.button}
mr={1.5}
border={`1px solid ${palette.primary.main}`}
onClick={() => {
history.push(`/pools?currency0=${token.id}¤cy1=ETH`);
}}
>
<Typography variant='body2'>Add Liquidity</Typography>
</Box>
<Box
className={cx(classes.button, classes.filledButton)}
onClick={() => {
history.push(`/swap?currency0=${token.id}¤cy1=ETH`);
}}
>
<Typography variant='body2'>Swap</Typography>
</Box>
</Box>
</Box>
<Box width={1} className={classes.panel} mt={4}>
<Grid container>
<Grid item xs={12} sm={12} md={6}>
<AnalyticsTokenChart token={token} />
</Grid>
<Grid item xs={12} sm={12} md={6}>
<Box
my={2}
height={1}
display='flex'
flexDirection='column'
alignItems='center'
justifyContent='center'
>
<Box
width={isMobile ? 1 : 0.8}
display='flex'
justifyContent='space-between'
>
<Box width={180}>
<Typography
variant='caption'
style={{ color: palette.text.disabled }}
>
TOTAL LIQUIDITY
</Typography>
<Typography variant={isMobile ? 'body1' : 'h5'}>
${token.totalLiquidityUSD.toLocaleString()}
</Typography>
</Box>
<Box width={140}>
<Typography
variant='caption'
style={{ color: palette.text.disabled }}
>
7d Trading Vol
</Typography>
<Typography variant={isMobile ? 'body1' : 'h5'}>
${token.oneWeekVolumeUSD.toLocaleString()}
</Typography>
</Box>
</Box>
<Box
width={isMobile ? 1 : 0.8}
mt={4}
display='flex'
justifyContent='space-between'
>
<Box width={180}>
<Typography
variant='caption'
style={{ color: palette.text.disabled }}
>
24h Trading Vol
</Typography>
<Typography variant={isMobile ? 'body1' : 'h5'}>
${token.oneDayVolumeUSD.toLocaleString()}
</Typography>
</Box>
<Box width={140}>
<Typography
variant='caption'
style={{ color: palette.text.disabled }}
>
24h FEES
</Typography>
<Typography variant={isMobile ? 'body1' : 'h5'}>
$
{(
token.oneDayVolumeUSD * GlobalConst.utils.FEEPERCENT
).toLocaleString()}
</Typography>
</Box>
</Box>
<Box
width={isMobile ? 1 : 0.8}
mt={4}
display='flex'
justifyContent='space-between'
>
<Box width={180}>
<Typography
variant='caption'
style={{ color: palette.text.disabled }}
>
Contract Address
</Typography>
<Typography
variant='h5'
style={{ color: palette.primary.main }}
>
{chainId ? (
<a
href={getEtherscanLink(
chainId,
token.id,
'address',
)}
target='_blank'
rel='noopener noreferrer'
style={{
color: palette.primary.main,
textDecoration: 'none',
}}
>
{shortenAddress(token.id)}
</a>
) : (
shortenAddress(token.id)
)}
</Typography>
</Box>
</Box>
</Box>
</Grid>
</Grid>
</Box>
<Box width={1} mt={5}>
<Typography variant='body1'>{token.symbol} Pools</Typography>
</Box>
<Box width={1} className={classes.panel} mt={4}>
{tokenPairs ? (
<PairTable data={tokenPairs} />
) : (
<Skeleton variant='rect' width='100%' height={150} />
)}
</Box>
</>
) : (
<Skeleton width='100%' height={100} />
)}
</>
);
}