components#DoubleCurrencyLogo TypeScript Examples
The following examples show how to use
components#DoubleCurrencyLogo.
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: RewardSliderItem.tsx From interface-v2 with GNU General Public License v3.0 | 5 votes |
RewardSliderItem: React.FC<RewardSliderItemProps> = ({
info,
stakingAPY,
}) => {
const classes = useStyles();
const history = useHistory();
const stakedAmounts = getStakedAmountStakingInfo(info);
const tvl = getTVLStaking(
stakedAmounts?.totalStakedUSD,
stakedAmounts?.totalStakedBase,
);
const rewards = info.rate * info.rewardTokenPrice;
let apyWithFee;
if (stakingAPY && stakingAPY > 0) {
apyWithFee = formatAPY(
getAPYWithFee(info.perMonthReturnInRewards ?? 0, stakingAPY),
);
}
return (
<Box className={classes.rewardsSliderItem}>
<Box mb={4}>
<Box className='rewardIcon'>
<DoubleCurrencyLogo
currency0={info.tokens[0]}
currency1={info.tokens[1]}
size={32}
/>
</Box>
<Typography variant='h5'>
{info.tokens[0].symbol?.toUpperCase()}-
{info.tokens[1].symbol?.toUpperCase()}
</Typography>
</Box>
<Box className='row'>
<Typography>24h Fees</Typography>
<Typography component='h4'>
${(info?.oneDayFee ?? 0).toLocaleString()}
</Typography>
</Box>
<Box className='row'>
<Typography>Rewards</Typography>
<Typography component='h4'>
${rewards.toLocaleString()} / day
</Typography>
</Box>
<Box className='row'>
<Typography>TVL</Typography>
<Typography component='h4'>{tvl}</Typography>
</Box>
<Box className='row'>
<Typography>
APR
<HelpIcon />
</Typography>
<Typography component='h5'>{apyWithFee}%</Typography>
</Box>
<Button
fullWidth
style={{ marginTop: '30px' }}
onClick={() => {
history.push(
`/pools?currency0=${info.tokens[0].address}¤cy1=${info.tokens[1].address}`,
);
}}
>
Deposit LP Tokens
</Button>
</Box>
);
}
Example #2
Source File: AddLiquidity.tsx From interface-v2 with GNU General Public License v3.0 | 4 votes |
AddLiquidity: React.FC<{
currency0?: Currency;
currency1?: Currency;
currencyBg?: string;
}> = ({ currency0, currency1, currencyBg }) => {
const classes = useStyles({});
const { palette } = useTheme();
const { t } = useTranslation();
const [addLiquidityErrorMessage, setAddLiquidityErrorMessage] = useState<
string | null
>(null);
const { account, chainId, library } = useActiveWeb3React();
const [showConfirm, setShowConfirm] = useState(false);
const [attemptingTxn, setAttemptingTxn] = useState(false);
const [txPending, setTxPending] = useState(false);
const [allowedSlippage] = useUserSlippageTolerance();
const deadline = useTransactionDeadline();
const [txHash, setTxHash] = useState('');
const addTransaction = useTransactionAdder();
const finalizedTransaction = useTransactionFinalizer();
const { independentField, typedValue, otherTypedValue } = useMintState();
const expertMode = useIsExpertMode();
const {
dependentField,
currencies,
pair,
pairState,
currencyBalances,
parsedAmounts,
price,
noLiquidity,
liquidityMinted,
poolTokenPercentage,
error,
} = useDerivedMintInfo();
const liquidityTokenData = {
amountA: formatTokenAmount(parsedAmounts[Field.CURRENCY_A]),
symbolA: currencies[Field.CURRENCY_A]?.symbol,
amountB: formatTokenAmount(parsedAmounts[Field.CURRENCY_B]),
symbolB: currencies[Field.CURRENCY_B]?.symbol,
};
const pendingText = t('supplyingTokens', liquidityTokenData);
const {
onFieldAInput,
onFieldBInput,
onCurrencySelection,
} = useMintActionHandlers(noLiquidity);
const maxAmounts: { [field in Field]?: TokenAmount } = [
Field.CURRENCY_A,
Field.CURRENCY_B,
].reduce((accumulator, field) => {
return {
...accumulator,
[field]: maxAmountSpend(currencyBalances[field]),
};
}, {});
const formattedAmounts = {
[independentField]: typedValue,
[dependentField]: noLiquidity
? otherTypedValue
: parsedAmounts[dependentField]?.toExact() ?? '',
};
const { ethereum } = window as any;
const toggleWalletModal = useWalletModalToggle();
const [approvingA, setApprovingA] = useState(false);
const [approvingB, setApprovingB] = useState(false);
const [approvalA, approveACallback] = useApproveCallback(
parsedAmounts[Field.CURRENCY_A],
chainId ? GlobalConst.addresses.ROUTER_ADDRESS[chainId] : undefined,
);
const [approvalB, approveBCallback] = useApproveCallback(
parsedAmounts[Field.CURRENCY_B],
chainId ? GlobalConst.addresses.ROUTER_ADDRESS[chainId] : undefined,
);
const userPoolBalance = useTokenBalance(
account ?? undefined,
pair?.liquidityToken,
);
const atMaxAmounts: { [field in Field]?: TokenAmount } = [
Field.CURRENCY_A,
Field.CURRENCY_B,
].reduce((accumulator, field) => {
return {
...accumulator,
[field]: maxAmounts[field]?.equalTo(parsedAmounts[field] ?? '0'),
};
}, {});
const handleCurrencyASelect = useCallback(
(currencyA: Currency) => {
onCurrencySelection(Field.CURRENCY_A, currencyA);
},
[onCurrencySelection],
);
const handleCurrencyBSelect = useCallback(
(currencyB: Currency) => {
onCurrencySelection(Field.CURRENCY_B, currencyB);
},
[onCurrencySelection],
);
useEffect(() => {
if (currency0) {
onCurrencySelection(Field.CURRENCY_A, currency0);
} else {
onCurrencySelection(Field.CURRENCY_A, Token.ETHER);
}
if (currency1) {
onCurrencySelection(Field.CURRENCY_B, currency1);
} else {
onCurrencySelection(Field.CURRENCY_B, returnTokenFromKey('QUICK'));
}
}, [onCurrencySelection, currency0, currency1]);
const onAdd = () => {
if (expertMode) {
onAddLiquidity();
} else {
setShowConfirm(true);
}
};
const router = useRouterContract();
const onAddLiquidity = async () => {
if (!chainId || !library || !account || !router) return;
const {
[Field.CURRENCY_A]: parsedAmountA,
[Field.CURRENCY_B]: parsedAmountB,
} = parsedAmounts;
if (
!parsedAmountA ||
!parsedAmountB ||
!currencies[Field.CURRENCY_A] ||
!currencies[Field.CURRENCY_B] ||
!deadline
) {
return;
}
const amountsMin = {
[Field.CURRENCY_A]: calculateSlippageAmount(
parsedAmountA,
noLiquidity ? 0 : allowedSlippage,
)[0],
[Field.CURRENCY_B]: calculateSlippageAmount(
parsedAmountB,
noLiquidity ? 0 : allowedSlippage,
)[0],
};
let estimate,
method: (...args: any) => Promise<TransactionResponse>,
args: Array<string | string[] | number>,
value: BigNumber | null;
if (
currencies[Field.CURRENCY_A] === ETHER ||
currencies[Field.CURRENCY_B] === ETHER
) {
const tokenBIsETH = currencies[Field.CURRENCY_B] === ETHER;
estimate = router.estimateGas.addLiquidityETH;
method = router.addLiquidityETH;
args = [
wrappedCurrency(
tokenBIsETH
? currencies[Field.CURRENCY_A]
: currencies[Field.CURRENCY_B],
chainId,
)?.address ?? '', // token
(tokenBIsETH ? parsedAmountA : parsedAmountB).raw.toString(), // token desired
amountsMin[
tokenBIsETH ? Field.CURRENCY_A : Field.CURRENCY_B
].toString(), // token min
amountsMin[
tokenBIsETH ? Field.CURRENCY_B : Field.CURRENCY_A
].toString(), // eth min
account,
deadline.toHexString(),
];
value = BigNumber.from(
(tokenBIsETH ? parsedAmountB : parsedAmountA).raw.toString(),
);
} else {
estimate = router.estimateGas.addLiquidity;
method = router.addLiquidity;
args = [
wrappedCurrency(currencies[Field.CURRENCY_A], chainId)?.address ?? '',
wrappedCurrency(currencies[Field.CURRENCY_B], chainId)?.address ?? '',
parsedAmountA.raw.toString(),
parsedAmountB.raw.toString(),
amountsMin[Field.CURRENCY_A].toString(),
amountsMin[Field.CURRENCY_B].toString(),
account,
deadline.toHexString(),
];
value = null;
}
setAttemptingTxn(true);
await estimate(...args, value ? { value } : {})
.then((estimatedGasLimit) =>
method(...args, {
...(value ? { value } : {}),
gasLimit: calculateGasMargin(estimatedGasLimit),
}).then(async (response) => {
setAttemptingTxn(false);
setTxPending(true);
const summary = t('addLiquidityTokens', liquidityTokenData);
addTransaction(response, {
summary,
});
setTxHash(response.hash);
try {
const receipt = await response.wait();
finalizedTransaction(receipt, {
summary,
});
setTxPending(false);
} catch (error) {
setTxPending(false);
setAddLiquidityErrorMessage(t('errorInTx'));
}
ReactGA.event({
category: 'Liquidity',
action: 'Add',
label: [
currencies[Field.CURRENCY_A]?.symbol,
currencies[Field.CURRENCY_B]?.symbol,
].join('/'),
});
}),
)
.catch((error) => {
setAttemptingTxn(false);
setAddLiquidityErrorMessage(t('txRejected'));
// we only care if the error is something _other_ than the user rejected the tx
if (error?.code !== 4001) {
console.error(error);
}
});
};
const connectWallet = () => {
if (ethereum && !isSupportedNetwork(ethereum)) {
addMaticToMetamask();
} else {
toggleWalletModal();
}
};
const handleDismissConfirmation = useCallback(() => {
setShowConfirm(false);
// if there was a tx hash, we want to clear the input
if (txHash) {
onFieldAInput('');
}
setTxHash('');
}, [onFieldAInput, txHash]);
const buttonText = useMemo(() => {
if (account) {
return error ?? t('supply');
} else if (ethereum && !isSupportedNetwork(ethereum)) {
return t('switchPolygon');
}
return t('connectWallet');
}, [account, ethereum, error, t]);
const modalHeader = () => {
return (
<Box>
<Box mt={10} mb={3} display='flex' justifyContent='center'>
<DoubleCurrencyLogo
currency0={currencies[Field.CURRENCY_A]}
currency1={currencies[Field.CURRENCY_B]}
size={48}
/>
</Box>
<Box mb={6} color={palette.text.primary} textAlign='center'>
<Typography variant='h6'>
{t('supplyingTokens', liquidityTokenData)}
<br />
{t('receiveLPTokens', {
amount: formatTokenAmount(liquidityMinted),
symbolA: currencies[Field.CURRENCY_A]?.symbol,
symbolB: currencies[Field.CURRENCY_B]?.symbol,
})}
</Typography>
</Box>
<Box mb={3} color={palette.text.secondary} textAlign='center'>
<Typography variant='body2'>
{t('outputEstimated', { slippage: allowedSlippage / 100 })}
</Typography>
</Box>
<Box className={classes.swapButtonWrapper}>
<Button onClick={onAddLiquidity}>{t('confirmSupply')}</Button>
</Box>
</Box>
);
};
return (
<Box>
{showConfirm && (
<TransactionConfirmationModal
isOpen={showConfirm}
onDismiss={handleDismissConfirmation}
attemptingTxn={attemptingTxn}
txPending={txPending}
hash={txHash}
content={() =>
addLiquidityErrorMessage ? (
<TransactionErrorContent
onDismiss={handleDismissConfirmation}
message={addLiquidityErrorMessage}
/>
) : (
<ConfirmationModalContent
title={t('supplyingliquidity')}
onDismiss={handleDismissConfirmation}
content={modalHeader}
/>
)
}
pendingText={pendingText}
modalContent={
txPending ? t('submittedTxLiquidity') : t('successAddedliquidity')
}
/>
)}
<CurrencyInput
id='add-liquidity-input-tokena'
title={`${t('token')} 1:`}
currency={currencies[Field.CURRENCY_A]}
showHalfButton={Boolean(maxAmounts[Field.CURRENCY_A])}
showMaxButton={!atMaxAmounts[Field.CURRENCY_A]}
onMax={() =>
onFieldAInput(maxAmounts[Field.CURRENCY_A]?.toExact() ?? '')
}
onHalf={() =>
onFieldAInput(
maxAmounts[Field.CURRENCY_A]
? (Number(maxAmounts[Field.CURRENCY_A]?.toExact()) / 2).toString()
: '',
)
}
handleCurrencySelect={handleCurrencyASelect}
amount={formattedAmounts[Field.CURRENCY_A]}
setAmount={onFieldAInput}
bgColor={currencyBg}
/>
<Box className={classes.exchangeSwap}>
<AddLiquidityIcon />
</Box>
<CurrencyInput
id='add-liquidity-input-tokenb'
title={`${t('token')} 2:`}
showHalfButton={Boolean(maxAmounts[Field.CURRENCY_B])}
currency={currencies[Field.CURRENCY_B]}
showMaxButton={!atMaxAmounts[Field.CURRENCY_B]}
onHalf={() =>
onFieldBInput(
maxAmounts[Field.CURRENCY_B]
? (Number(maxAmounts[Field.CURRENCY_B]?.toExact()) / 2).toString()
: '',
)
}
onMax={() =>
onFieldBInput(maxAmounts[Field.CURRENCY_B]?.toExact() ?? '')
}
handleCurrencySelect={handleCurrencyBSelect}
amount={formattedAmounts[Field.CURRENCY_B]}
setAmount={onFieldBInput}
bgColor={currencyBg}
/>
{currencies[Field.CURRENCY_A] &&
currencies[Field.CURRENCY_B] &&
pairState !== PairState.INVALID &&
price && (
<Box my={2}>
<Box className={classes.swapPrice}>
<Typography variant='body2'>
1 {currencies[Field.CURRENCY_A]?.symbol} ={' '}
{price.toSignificant(3)} {currencies[Field.CURRENCY_B]?.symbol}{' '}
</Typography>
<Typography variant='body2'>
1 {currencies[Field.CURRENCY_B]?.symbol} ={' '}
{price.invert().toSignificant(3)}{' '}
{currencies[Field.CURRENCY_A]?.symbol}{' '}
</Typography>
</Box>
<Box className={classes.swapPrice}>
<Typography variant='body2'>{t('yourPoolShare')}:</Typography>
<Typography variant='body2'>
{poolTokenPercentage
? poolTokenPercentage.toSignificant(6) + '%'
: '-'}
</Typography>
</Box>
<Box className={classes.swapPrice}>
<Typography variant='body2'>{t('lpTokenReceived')}:</Typography>
<Typography variant='body2'>
{formatTokenAmount(userPoolBalance)} {t('lpTokens')}
</Typography>
</Box>
</Box>
)}
<Box className={classes.swapButtonWrapper}>
{(approvalA === ApprovalState.NOT_APPROVED ||
approvalA === ApprovalState.PENDING ||
approvalB === ApprovalState.NOT_APPROVED ||
approvalB === ApprovalState.PENDING) &&
!error && (
<Box className={classes.approveButtons}>
{approvalA !== ApprovalState.APPROVED && (
<Box
width={approvalB !== ApprovalState.APPROVED ? '48%' : '100%'}
>
<Button
onClick={async () => {
setApprovingA(true);
try {
await approveACallback();
setApprovingA(false);
} catch (e) {
setApprovingA(false);
}
}}
disabled={approvingA || approvalA === ApprovalState.PENDING}
>
{approvalA === ApprovalState.PENDING
? `${t('approving')} ${
currencies[Field.CURRENCY_A]?.symbol
}`
: `${t('approve')} ${
currencies[Field.CURRENCY_A]?.symbol
}`}
</Button>
</Box>
)}
{approvalB !== ApprovalState.APPROVED && (
<Box
width={approvalA !== ApprovalState.APPROVED ? '48%' : '100%'}
>
<Button
onClick={async () => {
setApprovingB(true);
try {
await approveBCallback();
setApprovingB(false);
} catch (e) {
setApprovingB(false);
}
}}
disabled={approvingB || approvalB === ApprovalState.PENDING}
>
{approvalB === ApprovalState.PENDING
? `${t('approving')} ${
currencies[Field.CURRENCY_B]?.symbol
}`
: `${t('approve')} ${
currencies[Field.CURRENCY_B]?.symbol
}`}
</Button>
</Box>
)}
</Box>
)}
<Button
disabled={
Boolean(account) &&
(Boolean(error) ||
approvalA !== ApprovalState.APPROVED ||
approvalB !== ApprovalState.APPROVED)
}
onClick={account ? onAdd : connectWallet}
>
{buttonText}
</Button>
</Box>
</Box>
);
}
Example #3
Source File: SwapModalHeader.tsx From interface-v2 with GNU General Public License v3.0 | 4 votes |
SwapModalHeader: React.FC<SwapModalHeaderProps> = ({
trade,
allowedSlippage,
showAcceptChanges,
onAcceptChanges,
onConfirm,
}) => {
const classes = useStyles();
const slippageAdjustedAmounts = useMemo(
() => computeSlippageAdjustedAmounts(trade, allowedSlippage),
[trade, allowedSlippage],
);
const usdPrice = useUSDCPrice(trade.inputAmount.currency);
return (
<Box>
<Box mt={10} display='flex' justifyContent='center'>
<DoubleCurrencyLogo
currency0={trade.inputAmount.currency}
currency1={trade.outputAmount.currency}
size={48}
/>
</Box>
<Box className={classes.swapContent}>
<Typography variant='body1'>
Swap {formatTokenAmount(trade.inputAmount)}{' '}
{trade.inputAmount.currency.symbol} ($
{Number(usdPrice?.toSignificant()) *
Number(trade.inputAmount.toSignificant(2))}
)
</Typography>
<ArrowDownIcon />
<Typography variant='body1'>
{formatTokenAmount(trade.outputAmount)}{' '}
{trade.outputAmount.currency.symbol}
</Typography>
</Box>
{showAcceptChanges && (
<Box className={classes.priceUpdate}>
<Box>
<AlertTriangle
size={20}
style={{ marginRight: '8px', minWidth: 24 }}
/>
<Typography> Price Updated</Typography>
</Box>
<Button
style={{
padding: '.5rem',
width: 'fit-content',
fontSize: '0.825rem',
borderRadius: '12px',
}}
onClick={onAcceptChanges}
>
Accept
</Button>
</Box>
)}
<Box className={classes.transactionText}>
{trade.tradeType === TradeType.EXACT_INPUT ? (
<Typography variant='body2'>
{`Output is estimated. You will receive at least `}
{formatTokenAmount(slippageAdjustedAmounts[Field.OUTPUT])}{' '}
{trade.outputAmount.currency.symbol}
{' or the transaction will revert.'}
</Typography>
) : (
<Typography variant='body2'>
{`Input is estimated. You will sell at most `}
{formatTokenAmount(slippageAdjustedAmounts[Field.INPUT])}{' '}
{trade.inputAmount.currency.symbol}
{' or the transaction will revert.'}
</Typography>
)}
<Button onClick={onConfirm} className={classes.swapButton}>
Confirm Swap
</Button>
</Box>
</Box>
);
}
Example #4
Source File: FarmCard.tsx From interface-v2 with GNU General Public License v3.0 | 4 votes |
FarmCard: React.FC<{
stakingInfo: StakingInfo | DualStakingInfo;
stakingAPY: number;
isLPFarm?: boolean;
}> = ({ stakingInfo, stakingAPY, isLPFarm }) => {
const classes = useStyles();
const { palette, breakpoints } = useTheme();
const isMobile = useMediaQuery(breakpoints.down('xs'));
const [isExpandCard, setExpandCard] = useState(false);
const lpStakingInfo = stakingInfo as StakingInfo;
const dualStakingInfo = stakingInfo as DualStakingInfo;
const token0 = stakingInfo.tokens[0];
const token1 = stakingInfo.tokens[1];
const currency0 = unwrappedToken(token0);
const currency1 = unwrappedToken(token1);
const stakedAmounts = getStakedAmountStakingInfo(stakingInfo);
let apyWithFee: number | string = 0;
if (stakingAPY && stakingAPY > 0 && stakingInfo.perMonthReturnInRewards) {
apyWithFee = formatAPY(
getAPYWithFee(stakingInfo.perMonthReturnInRewards, stakingAPY),
);
}
const tvl = getTVLStaking(
stakedAmounts?.totalStakedUSD,
stakedAmounts?.totalStakedBase,
);
const lpPoolRate = getRewardRate(
lpStakingInfo.totalRewardRate,
lpStakingInfo.rewardToken,
);
const dualPoolRateA = getRewardRate(
dualStakingInfo.totalRewardRateA,
dualStakingInfo.rewardTokenA,
);
const dualPoolRateB = getRewardRate(
dualStakingInfo.totalRewardRateB,
dualStakingInfo.rewardTokenB,
);
const earnedUSDStr = isLPFarm
? getEarnedUSDLPFarm(lpStakingInfo)
: getEarnedUSDDualFarm(dualStakingInfo);
const lpRewards = lpStakingInfo.rewardTokenPrice * lpStakingInfo.rate;
const dualRewards =
dualStakingInfo.rateA * dualStakingInfo.rewardTokenAPrice +
dualStakingInfo.rateB * dualStakingInfo.rewardTokenBPrice;
const renderPool = (width: number) => (
<Box display='flex' alignItems='center' width={width}>
<DoubleCurrencyLogo
currency0={currency0}
currency1={currency1}
size={28}
/>
<Box ml={1.5}>
<Typography variant='body2'>
{currency0.symbol} / {currency1.symbol} LP
</Typography>
</Box>
</Box>
);
return (
<Box
className={cx(
classes.farmLPCard,
isExpandCard && classes.highlightedCard,
)}
>
<Box
className={classes.farmLPCardUp}
onClick={() => setExpandCard(!isExpandCard)}
>
{isMobile ? (
<>
{renderPool(isExpandCard ? 0.95 : 0.7)}
{!isExpandCard && (
<Box width={0.25}>
<Box display='flex' alignItems='center'>
<Typography variant='caption' color='textSecondary'>
APY
</Typography>
<Box ml={0.5} height={16}>
<img src={CircleInfoIcon} alt={'arrow up'} />
</Box>
</Box>
<Box mt={0.5} color={palette.success.main}>
<Typography variant='body2'>{apyWithFee}%</Typography>
</Box>
</Box>
)}
<Box
width={0.05}
display='flex'
justifyContent='flex-end'
color={palette.primary.main}
>
{isExpandCard ? <KeyboardArrowUp /> : <KeyboardArrowDown />}
</Box>
</>
) : (
<>
{renderPool(0.3)}
<Box width={0.2} textAlign='center'>
<Typography variant='body2'>{tvl}</Typography>
</Box>
<Box width={0.25} textAlign='center'>
<Typography variant='body2'>
${(isLPFarm ? lpRewards : dualRewards).toLocaleString()} / day
</Typography>
{isLPFarm ? (
<Typography variant='body2'>{lpPoolRate}</Typography>
) : (
<>
<Typography variant='body2'>{dualPoolRateA}</Typography>
<Typography variant='body2'>{dualPoolRateB}</Typography>
</>
)}
</Box>
<Box
width={0.15}
display='flex'
justifyContent='center'
alignItems='center'
color={palette.success.main}
>
<Typography variant='body2'>{apyWithFee}%</Typography>
<Box ml={0.5} height={16}>
<img src={CircleInfoIcon} alt={'arrow up'} />
</Box>
</Box>
<Box width={0.2} textAlign='right'>
<Typography variant='body2'>{earnedUSDStr}</Typography>
{isLPFarm ? (
<Box
display='flex'
alignItems='center'
justifyContent='flex-end'
>
<CurrencyLogo
currency={lpStakingInfo.rewardToken}
size='16px'
/>
<Typography variant='body2' style={{ marginLeft: 5 }}>
{formatTokenAmount(lpStakingInfo.earnedAmount)}
<span> {lpStakingInfo.rewardToken.symbol}</span>
</Typography>
</Box>
) : (
<>
<Box
display='flex'
alignItems='center'
justifyContent='flex-end'
>
<CurrencyLogo
currency={unwrappedToken(dualStakingInfo.rewardTokenA)}
size='16px'
/>
<Typography variant='body2' style={{ marginLeft: 5 }}>
{formatTokenAmount(dualStakingInfo.earnedAmountA)}
<span> {dualStakingInfo.rewardTokenA.symbol}</span>
</Typography>
</Box>
<Box
display='flex'
alignItems='center'
justifyContent='flex-end'
>
<CurrencyLogo
currency={unwrappedToken(dualStakingInfo.rewardTokenB)}
size='16px'
/>
<Typography variant='body2' style={{ marginLeft: 5 }}>
{formatTokenAmount(dualStakingInfo.earnedAmountB)}
<span> {dualStakingInfo.rewardTokenB.symbol}</span>
</Typography>
</Box>
</>
)}
</Box>
</>
)}
</Box>
{isExpandCard && (
<FarmCardDetails
stakingInfo={stakingInfo}
stakingAPY={stakingAPY}
isLPFarm={isLPFarm}
/>
)}
</Box>
);
}
Example #5
Source File: PairsTable.tsx From interface-v2 with GNU General Public License v3.0 | 4 votes |
PairTable: React.FC<TokensTableProps> = ({ data }) => {
const pairHeadCells = headCells();
const {
bookmarkPairs,
addBookmarkPair,
removeBookmarkPair,
} = useBookmarkPairs();
const mobileHTML = (pair: any, index: number) => {
const token0 = new Token(
ChainId.MATIC,
getAddress(pair.token0.id),
Number(pair.token0.decimals),
pair.token0.symbol,
);
const token1 = new Token(
ChainId.MATIC,
getAddress(pair.token1.id),
Number(pair.token1.decimals),
pair.token1.symbol,
);
const liquidity = pair.trackedReserveUSD
? pair.trackedReserveUSD
: pair.reserveUSD;
const oneDayVolume = pair.oneDayVolumeUSD
? pair.oneDayVolumeUSD
: pair.oneDayVolumeUntracked;
const oneWeekVolume = pair.oneWeekVolumeUSD
? pair.oneWeekVolumeUSD
: pair.oneWeekVolumeUntracked;
const oneDayFee = (
Number(oneDayVolume) * GlobalConst.utils.FEEPERCENT
).toLocaleString();
return (
<Box mt={index === 0 ? 0 : 3}>
<Box display='flex' alignItems='center' mb={1}>
<Box
display='flex'
mr={1}
onClick={() => {
const pairIndex = bookmarkPairs.indexOf(pair.id);
if (pairIndex === -1) {
addBookmarkPair(pair.id);
} else {
removeBookmarkPair(pair.id);
}
}}
>
{bookmarkPairs.indexOf(pair.id) > -1 ? (
<StarChecked />
) : (
<StarUnchecked />
)}
</Box>
<Link
to={`/analytics/pair/${pair.id}`}
style={{ textDecoration: 'none' }}
>
<Box display='flex' alignItems='center'>
<DoubleCurrencyLogo
currency0={token0}
currency1={token1}
size={28}
/>
<Box ml={1}>
<Typography variant='body1' color='textPrimary'>
{token0.symbol} / {token1.symbol}
</Typography>
</Box>
</Box>
</Link>
</Box>
<Divider />
<Box
mt={1}
display='flex'
alignItems='center'
justifyContent='space-between'
>
<Typography variant='body1'>Liquidity</Typography>
<Typography variant='body1'>
${Number(liquidity).toLocaleString()}
</Typography>
</Box>
<Box
mt={1}
display='flex'
alignItems='center'
justifyContent='space-between'
>
<Typography variant='body1'>24h Volume</Typography>
<Typography variant='body1'>
${Number(oneDayVolume).toLocaleString()}
</Typography>
</Box>
<Box
mt={1}
display='flex'
alignItems='center'
justifyContent='space-between'
>
<Typography variant='body1'>7d Volume</Typography>
<Typography variant='body1'>
${Number(oneWeekVolume).toLocaleString()}
</Typography>
</Box>
<Box
mt={1}
display='flex'
alignItems='center'
justifyContent='space-between'
>
<Typography variant='body1'>24h Fees</Typography>
<Typography variant='body1'>
${Number(oneDayFee).toLocaleString()}
</Typography>
</Box>
</Box>
);
};
const desktopHTML = (pair: any) => {
const token0 = new Token(
ChainId.MATIC,
getAddress(pair.token0.id),
Number(pair.token0.decimals),
pair.token0.symbol,
);
const token1 = new Token(
ChainId.MATIC,
getAddress(pair.token1.id),
Number(pair.token1.decimals),
pair.token1.symbol,
);
const liquidity = pair.trackedReserveUSD
? pair.trackedReserveUSD
: pair.reserveUSD;
const oneDayVolume =
pair.oneDayVolumeUSD && !isNaN(pair.oneDayVolumeUSD)
? pair.oneDayVolumeUSD
: pair.oneDayVolumeUntracked && !isNaN(pair.oneDayVolumeUntracked)
? pair.oneDayVolumeUntracked
: 0;
const oneWeekVolume =
pair.oneWeekVolumeUSD && !isNaN(pair.oneWeekVolumeUSD)
? pair.oneWeekVolumeUSD
: pair.oneWeekVolumeUntracked && !isNaN(pair.oneWeekVolumeUntracked)
? pair.oneWeekVolumeUntracked
: 0;
const oneDayFee = (
Number(oneDayVolume) * GlobalConst.utils.FEEPERCENT
).toLocaleString();
return [
{
html: (
<Box display='flex' alignItems='center'>
<Box
display='flex'
mr={1}
onClick={() => {
const pairIndex = bookmarkPairs.indexOf(pair.id);
if (pairIndex === -1) {
addBookmarkPair(pair.id);
} else {
removeBookmarkPair(pair.id);
}
}}
>
{bookmarkPairs.indexOf(pair.id) > -1 ? (
<StarChecked />
) : (
<StarUnchecked />
)}
</Box>
<Link
to={`/analytics/pair/${pair.id}`}
style={{ textDecoration: 'none' }}
>
<Box display='flex' alignItems='center'>
<DoubleCurrencyLogo
currency0={token0}
currency1={token1}
size={28}
/>
<Box ml={1}>
<Typography variant='body1' color='textPrimary'>
{token0.symbol} / {token1.symbol}
</Typography>
</Box>
</Box>
</Link>
</Box>
),
},
{
html: (
<Typography variant='body1'>
${Number(liquidity).toLocaleString()}
</Typography>
),
},
{
html: (
<Typography variant='body1'>
${Number(oneDayVolume).toLocaleString()}
</Typography>
),
},
{
html: (
<Typography variant='body1'>
${Number(oneWeekVolume).toLocaleString()}
</Typography>
),
},
{
html: <Typography variant='body1'>${oneDayFee}</Typography>,
},
];
};
return (
<CustomTable
defaultOrderBy={pairHeadCells[liquidityHeadCellIndex]}
defaultOrder='desc'
showPagination={data.length > GlobalConst.utils.ROWSPERPAGE}
headCells={pairHeadCells}
rowsPerPage={GlobalConst.utils.ROWSPERPAGE}
data={data}
mobileHTML={mobileHTML}
desktopHTML={desktopHTML}
/>
);
}
Example #6
Source File: PoolPositionCard.tsx From interface-v2 with GNU General Public License v3.0 | 4 votes |
PoolPositionCard: React.FC<{ pair: Pair }> = ({ pair }) => {
const [bulkPairData, setBulkPairData] = useState<any>(null);
const { palette, breakpoints } = useTheme();
const isMobile = useMediaQuery(breakpoints.down('xs'));
const currency0 = unwrappedToken(pair.token0);
const currency1 = unwrappedToken(pair.token1);
const stakingInfos = useStakingInfo(pair);
const dualStakingInfos = useDualStakingInfo(pair);
const stakingInfo = useMemo(
() =>
stakingInfos && stakingInfos.length > 0
? stakingInfos[0]
: dualStakingInfos && dualStakingInfos.length > 0
? dualStakingInfos[0]
: null,
[stakingInfos, dualStakingInfos],
);
const pairId = pair.liquidityToken.address;
useEffect(() => {
const pairLists = [pairId];
getBulkPairData(pairLists).then((data) => setBulkPairData(data));
return () => setBulkPairData(null);
}, [pairId]);
const [showMore, setShowMore] = useState(false);
const apyWithFee = useMemo(() => {
if (stakingInfo && bulkPairData) {
const dayVolume = bulkPairData[stakingInfo.pair]?.oneDayVolumeUSD;
const reserveUSD = bulkPairData[stakingInfo.pair]?.reserveUSD;
const oneYearFee =
dayVolume && reserveUSD ? getOneYearFee(dayVolume, reserveUSD) : 0;
return formatAPY(
getAPYWithFee(stakingInfo.perMonthReturnInRewards ?? 0, oneYearFee),
);
}
}, [stakingInfo, bulkPairData]);
return (
<Box
width={1}
border={`1px solid ${palette.secondary.dark}`}
borderRadius={10}
bgcolor={showMore ? palette.secondary.dark : 'transparent'}
style={{ overflow: 'hidden' }}
>
<Box
paddingX={isMobile ? 1.5 : 3}
paddingY={isMobile ? 2 : 3}
display='flex'
alignItems='center'
justifyContent='space-between'
>
<Box display='flex' alignItems='center'>
<DoubleCurrencyLogo
currency0={currency0}
currency1={currency1}
margin={true}
size={28}
/>
<Typography
variant='h6'
style={{ color: palette.text.primary, marginLeft: 16 }}
>
{!currency0 || !currency1
? 'Loading'
: `${currency0.symbol}/${currency1.symbol}`}
</Typography>
</Box>
<Box
display='flex'
alignItems='center'
color={palette.primary.main}
style={{ cursor: 'pointer' }}
onClick={() => setShowMore(!showMore)}
>
<Typography variant='body1' style={{ marginRight: 8 }}>
Manage
</Typography>
{showMore ? <ChevronUp size='20' /> : <ChevronDown size='20' />}
</Box>
</Box>
{showMore && <PoolPositionCardDetails pair={pair} />}
{stakingInfo && !stakingInfo.ended && apyWithFee && (
<Box bgcolor='#404557' paddingY={0.75} paddingX={isMobile ? 2 : 3}>
<Typography variant='body2'>
Earn{' '}
<span style={{ color: palette.success.main }}>
{apyWithFee}% APY
</span>{' '}
by staking your LP tokens in {currency0.symbol?.toUpperCase()} /{' '}
{currency1.symbol?.toUpperCase()} Farm
</Typography>
</Box>
)}
</Box>
);
}
Example #7
Source File: PositionCard.tsx From interface-v2 with GNU General Public License v3.0 | 4 votes |
MinimalPositionCard: React.FC<PositionCardProps> = ({
pair,
border,
showUnwrapped = false,
}) => {
const { account } = useActiveWeb3React();
const classes = useStyles();
const currency0 = showUnwrapped ? pair.token0 : unwrappedToken(pair.token0);
const currency1 = showUnwrapped ? pair.token1 : unwrappedToken(pair.token1);
const [showMore, setShowMore] = useState(false);
const userPoolBalance = useTokenBalance(
account ?? undefined,
pair.liquidityToken,
);
const totalPoolTokens = useTotalSupply(pair.liquidityToken);
const poolTokenPercentage =
!!userPoolBalance &&
!!totalPoolTokens &&
JSBI.greaterThanOrEqual(totalPoolTokens.raw, userPoolBalance.raw)
? new Percent(userPoolBalance.raw, totalPoolTokens.raw)
: undefined;
const [token0Deposited, token1Deposited] =
!!pair &&
!!totalPoolTokens &&
!!userPoolBalance &&
// this condition is a short-circuit in the case where useTokenBalance updates sooner than useTotalSupply
JSBI.greaterThanOrEqual(totalPoolTokens.raw, userPoolBalance.raw)
? [
pair.getLiquidityValue(
pair.token0,
totalPoolTokens,
userPoolBalance,
false,
),
pair.getLiquidityValue(
pair.token1,
totalPoolTokens,
userPoolBalance,
false,
),
]
: [undefined, undefined];
return (
<Box className={classes.minimalCardWrapper} border={border}>
{userPoolBalance &&
JSBI.greaterThan(userPoolBalance.raw, JSBI.BigInt(0)) ? (
<Box>
<Typography>Your position</Typography>
<Box
mt={0.75}
display='flex'
justifyContent='space-between'
onClick={() => setShowMore(!showMore)}
>
<Box display='flex' alignItems='center'>
<DoubleCurrencyLogo
currency0={currency0}
currency1={currency1}
margin={true}
size={20}
/>
<Typography style={{ marginLeft: 6 }}>
{currency0.symbol}/{currency1.symbol}
</Typography>
</Box>
<Typography>{formatTokenAmount(userPoolBalance)}</Typography>
</Box>
<Box
mt={0.75}
display='flex'
alignItems='center'
justifyContent='space-between'
>
<Typography>Your pool share:</Typography>
<Typography>
{poolTokenPercentage ? poolTokenPercentage.toFixed(6) + '%' : '-'}
</Typography>
</Box>
<Box
mt={0.75}
display='flex'
alignItems='center'
justifyContent='space-between'
>
<Typography>{currency0.symbol}:</Typography>
<Typography>{formatTokenAmount(token0Deposited)}</Typography>
</Box>
<Box
mt={0.75}
display='flex'
alignItems='center'
justifyContent='space-between'
>
<Typography>{currency1.symbol}:</Typography>
<Typography>{formatTokenAmount(token1Deposited)}</Typography>
</Box>
</Box>
) : (
<Typography>
<span role='img' aria-label='wizard-icon'>
⭐️
</span>{' '}
By adding liquidity you'll earn 0.25% of all trades on this pair
proportional to your share of the pool. Fees are added to the pool,
accrue in real time and can be claimed by withdrawing your liquidity.
</Typography>
)}
</Box>
);
}
Example #8
Source File: PositionCard.tsx From interface-v2 with GNU General Public License v3.0 | 4 votes |
FullPositionCard: React.FC<PositionCardProps> = ({ pair }) => {
const { account } = useActiveWeb3React();
const currency0 = unwrappedToken(pair.token0);
const currency1 = unwrappedToken(pair.token1);
const [showMore, setShowMore] = useState(false);
const userPoolBalance = useTokenBalance(
account ?? undefined,
pair.liquidityToken,
);
const totalPoolTokens = useTotalSupply(pair.liquidityToken);
const poolTokenPercentage =
!!userPoolBalance &&
!!totalPoolTokens &&
JSBI.greaterThanOrEqual(totalPoolTokens.raw, userPoolBalance.raw)
? new Percent(userPoolBalance.raw, totalPoolTokens.raw)
: undefined;
const [token0Deposited, token1Deposited] =
!!pair &&
!!totalPoolTokens &&
!!userPoolBalance &&
// this condition is a short-circuit in the case where useTokenBalance updates sooner than useTotalSupply
JSBI.greaterThanOrEqual(totalPoolTokens.raw, userPoolBalance.raw)
? [
pair.getLiquidityValue(
pair.token0,
totalPoolTokens,
userPoolBalance,
false,
),
pair.getLiquidityValue(
pair.token1,
totalPoolTokens,
userPoolBalance,
false,
),
]
: [undefined, undefined];
return (
<Box>
<Box>
<Box>
<DoubleCurrencyLogo
currency0={currency0}
currency1={currency1}
margin={true}
size={20}
/>
<Typography>
{!currency0 || !currency1 ? (
<Typography>Loading</Typography>
) : (
`${currency0.symbol}/${currency1.symbol}`
)}
</Typography>
</Box>
<Button onClick={() => setShowMore(!showMore)}>
{showMore ? (
<>
{' '}
Manage
<ChevronUp size='20' style={{ marginLeft: '10px' }} />
</>
) : (
<>
Manage
<ChevronDown size='20' style={{ marginLeft: '10px' }} />
</>
)}
</Button>
</Box>
{showMore && (
<Box>
<Box>
<Typography>Your pool tokens:</Typography>
<Typography>{formatTokenAmount(userPoolBalance)}</Typography>
</Box>
<Box>
<Typography>Pooled {currency0.symbol}:</Typography>
<Box>
<Typography>{formatTokenAmount(token0Deposited)}</Typography>
<CurrencyLogo
size='20px'
style={{ marginLeft: '8px' }}
currency={currency0}
/>
</Box>
</Box>
<Box>
<Typography>Pooled {currency1.symbol}:</Typography>
<Box>
<Typography>{formatTokenAmount(token1Deposited)}</Typography>
<CurrencyLogo
size='20px'
style={{ marginLeft: '8px' }}
currency={currency1}
/>
</Box>
</Box>
<Box>
<Typography>Your pool share:</Typography>
<Typography>
{poolTokenPercentage ? poolTokenPercentage.toFixed(2) + '%' : '-'}
</Typography>
</Box>
<Button>
<a
style={{ width: '100%', textAlign: 'center' }}
href={`https://info.quickswap.exchange/account/${account}`}
target='_blank'
rel='noopener noreferrer'
>
View accrued fees and analytics
<span style={{ fontSize: '11px' }}>↗</span>
</a>
</Button>
<Box display='flex'>
<Box width='48%'>
<Link
to={`/add/${currencyId(currency0)}/${currencyId(currency1)}`}
>
Add
</Link>
</Box>
<Box width='48%'>
<Link
to={`/remove/${currencyId(currency0)}/${currencyId(currency1)}`}
>
Remove
</Link>
</Box>
</Box>
</Box>
)}
</Box>
);
}
Example #9
Source File: RemoveLiquidityModal.tsx From interface-v2 with GNU General Public License v3.0 | 4 votes |
RemoveLiquidityModal: React.FC<RemoveLiquidityModalProps> = ({
currency0,
currency1,
open,
onClose,
}) => {
const classes = useStyles();
const { palette } = useTheme();
const [showConfirm, setShowConfirm] = useState(false);
const [txPending, setTxPending] = useState(false);
const [approving, setApproving] = useState(false);
const [attemptingTxn, setAttemptingTxn] = useState(false);
const [removeErrorMessage, setRemoveErrorMessage] = useState('');
const [errorMsg, setErrorMsg] = useState('');
const [txHash, setTxHash] = useState('');
const addTransaction = useTransactionAdder();
const finalizedTransaction = useTransactionFinalizer();
const { chainId, account, library } = useActiveWeb3React();
const [tokenA, tokenB] = useMemo(
() => [
wrappedCurrency(currency0, chainId),
wrappedCurrency(currency1, chainId),
],
[currency0, currency1, chainId],
);
const { independentField, typedValue } = useBurnState();
const { pair, parsedAmounts, error } = useDerivedBurnInfo(
currency0,
currency1,
);
const deadline = useTransactionDeadline();
const { onUserInput: _onUserInput } = useBurnActionHandlers();
const [allowedSlippage] = useUserSlippageTolerance();
const onUserInput = useCallback(
(field: Field, typedValue: string) => {
return _onUserInput(field, typedValue);
},
[_onUserInput],
);
const onLiquidityInput = useCallback(
(typedValue: string): void => onUserInput(Field.LIQUIDITY, typedValue),
[onUserInput],
);
const liquidityPercentChangeCallback = useCallback(
(value: number) => {
onUserInput(Field.LIQUIDITY_PERCENT, value.toString());
},
[onUserInput],
);
const [
innerLiquidityPercentage,
setInnerLiquidityPercentage,
] = useDebouncedChangeHandler(
Number.parseInt(parsedAmounts[Field.LIQUIDITY_PERCENT].toFixed(0)),
liquidityPercentChangeCallback,
);
const userPoolBalance = useTokenBalance(
account ?? undefined,
pair?.liquidityToken,
);
const totalPoolTokens = useTotalSupply(pair?.liquidityToken);
const poolTokenPercentage =
!!userPoolBalance &&
!!totalPoolTokens &&
JSBI.greaterThanOrEqual(totalPoolTokens.raw, userPoolBalance.raw)
? new Percent(userPoolBalance.raw, totalPoolTokens.raw)
: undefined;
const formattedAmounts = {
[Field.LIQUIDITY_PERCENT]: parsedAmounts[Field.LIQUIDITY_PERCENT].equalTo(
'0',
)
? '0'
: parsedAmounts[Field.LIQUIDITY_PERCENT].lessThan(new Percent('1', '100'))
? '<1'
: parsedAmounts[Field.LIQUIDITY_PERCENT].toFixed(0),
[Field.LIQUIDITY]:
independentField === Field.LIQUIDITY
? typedValue
: parsedAmounts[Field.LIQUIDITY]?.toExact() ?? '',
[Field.CURRENCY_A]:
independentField === Field.CURRENCY_A
? typedValue
: parsedAmounts[Field.CURRENCY_A]?.toExact() ?? '',
[Field.CURRENCY_B]:
independentField === Field.CURRENCY_B
? typedValue
: parsedAmounts[Field.CURRENCY_B]?.toExact() ?? '',
};
const [token0Deposited, token1Deposited] =
!!pair &&
!!totalPoolTokens &&
!!userPoolBalance &&
JSBI.greaterThanOrEqual(totalPoolTokens.raw, userPoolBalance.raw)
? [
pair.getLiquidityValue(
pair.token0,
totalPoolTokens,
userPoolBalance,
false,
),
pair.getLiquidityValue(
pair.token1,
totalPoolTokens,
userPoolBalance,
false,
),
]
: [undefined, undefined];
const pairContract: Contract | null = usePairContract(
pair?.liquidityToken?.address,
);
const [approval, approveCallback] = useApproveCallback(
parsedAmounts[Field.LIQUIDITY],
chainId ? GlobalConst.addresses.ROUTER_ADDRESS[chainId] : undefined,
);
const onAttemptToApprove = async () => {
if (!pairContract || !pair || !library || !deadline) {
setErrorMsg('missing dependencies');
return;
}
const liquidityAmount = parsedAmounts[Field.LIQUIDITY];
if (!liquidityAmount) {
setErrorMsg('missing liquidity amount');
return;
}
setApproving(true);
try {
await approveCallback();
setApproving(false);
} catch (e) {
setApproving(false);
}
};
const handleDismissConfirmation = useCallback(() => {
setShowConfirm(false);
setTxHash('');
}, []);
const router = useRouterContract();
const onRemove = async () => {
if (!chainId || !library || !account || !deadline || !router)
throw new Error('missing dependencies');
const {
[Field.CURRENCY_A]: currencyAmountA,
[Field.CURRENCY_B]: currencyAmountB,
} = parsedAmounts;
if (!currencyAmountA || !currencyAmountB) {
throw new Error('missing currency amounts');
}
const amountsMin = {
[Field.CURRENCY_A]: calculateSlippageAmount(
currencyAmountA,
allowedSlippage,
)[0],
[Field.CURRENCY_B]: calculateSlippageAmount(
currencyAmountB,
allowedSlippage,
)[0],
};
const liquidityAmount = parsedAmounts[Field.LIQUIDITY];
if (!liquidityAmount) throw new Error('missing liquidity amount');
const currencyBIsETH = currency1 === ETHER;
const oneCurrencyIsETH = currency0 === ETHER || currencyBIsETH;
if (!tokenA || !tokenB) throw new Error('could not wrap');
let methodNames: string[],
args: Array<string | string[] | number | boolean>;
// we have approval, use normal remove liquidity
if (approval === ApprovalState.APPROVED) {
// removeLiquidityETH
if (oneCurrencyIsETH) {
methodNames = [
'removeLiquidityETH',
'removeLiquidityETHSupportingFeeOnTransferTokens',
];
args = [
currencyBIsETH ? tokenA.address : tokenB.address,
liquidityAmount.raw.toString(),
amountsMin[
currencyBIsETH ? Field.CURRENCY_A : Field.CURRENCY_B
].toString(),
amountsMin[
currencyBIsETH ? Field.CURRENCY_B : Field.CURRENCY_A
].toString(),
account,
deadline.toHexString(),
];
}
// removeLiquidity
else {
methodNames = ['removeLiquidity'];
args = [
tokenA.address,
tokenB.address,
liquidityAmount.raw.toString(),
amountsMin[Field.CURRENCY_A].toString(),
amountsMin[Field.CURRENCY_B].toString(),
account,
deadline.toHexString(),
];
}
} else {
throw new Error(
'Attempting to confirm without approval. Please contact support.',
);
}
const safeGasEstimates: (BigNumber | undefined)[] = await Promise.all(
methodNames.map((methodName) =>
router.estimateGas[methodName](...args)
.then(calculateGasMargin)
.catch((error) => {
console.error(`estimateGas failed`, methodName, args, error);
return undefined;
}),
),
);
const indexOfSuccessfulEstimation = safeGasEstimates.findIndex(
(safeGasEstimate) => BigNumber.isBigNumber(safeGasEstimate),
);
// all estimations failed...
if (indexOfSuccessfulEstimation === -1) {
console.error('This transaction would fail. Please contact support.');
} else {
const methodName = methodNames[indexOfSuccessfulEstimation];
const safeGasEstimate = safeGasEstimates[indexOfSuccessfulEstimation];
setAttemptingTxn(true);
await router[methodName](...args, {
gasLimit: safeGasEstimate,
})
.then(async (response: TransactionResponse) => {
setAttemptingTxn(false);
setTxPending(true);
const summary =
'Remove ' +
parsedAmounts[Field.CURRENCY_A]?.toSignificant(3) +
' ' +
currency0.symbol +
' and ' +
parsedAmounts[Field.CURRENCY_B]?.toSignificant(3) +
' ' +
currency1.symbol;
addTransaction(response, {
summary,
});
setTxHash(response.hash);
try {
const receipt = await response.wait();
finalizedTransaction(receipt, {
summary,
});
setTxPending(false);
} catch (error) {
setTxPending(false);
setRemoveErrorMessage('There is an error in transaction.');
}
ReactGA.event({
category: 'Liquidity',
action: 'Remove',
label: [currency0.symbol, currency1.symbol].join('/'),
});
})
.catch((error: Error) => {
setAttemptingTxn(false);
// we only care if the error is something _other_ than the user rejected the tx
console.error(error);
});
}
};
const modalHeader = () => {
return (
<Box>
<Box mt={10} mb={3} display='flex' justifyContent='center'>
<DoubleCurrencyLogo
currency0={currency0}
currency1={currency1}
size={48}
/>
</Box>
<Box mb={6} color={palette.text.primary} textAlign='center'>
<Typography variant='h6'>
Removing {formattedAmounts[Field.LIQUIDITY]} {currency0.symbol} /{' '}
{currency1.symbol} LP Tokens
<br />
You will receive {parsedAmounts[Field.CURRENCY_A]?.toSignificant(
2,
)}{' '}
{currency0.symbol} and{' '}
{parsedAmounts[Field.CURRENCY_B]?.toSignificant(2)}{' '}
{currency1.symbol}
</Typography>
</Box>
<Box mb={3} color={palette.text.secondary} textAlign='center'>
<Typography variant='body2'>
{`Output is estimated. If the price changes by more than ${allowedSlippage /
100}% your transaction will revert.`}
</Typography>
</Box>
<Box mt={2}>
<Button
style={{ width: '100%' }}
className={classes.removeButton}
onClick={onRemove}
>
Confirm
</Button>
</Box>
</Box>
);
};
return (
<CustomModal open={open} onClose={onClose}>
<Box paddingX={3} paddingY={4}>
{showConfirm && (
<TransactionConfirmationModal
isOpen={showConfirm}
onDismiss={handleDismissConfirmation}
attemptingTxn={attemptingTxn}
txPending={txPending}
hash={txHash}
content={() =>
removeErrorMessage ? (
<TransactionErrorContent
onDismiss={handleDismissConfirmation}
message={removeErrorMessage}
/>
) : (
<ConfirmationModalContent
title='Removing Liquidity'
onDismiss={handleDismissConfirmation}
content={modalHeader}
/>
)
}
pendingText=''
modalContent={
txPending
? 'Submitted transaction to remove liquidity'
: 'Successfully removed liquidity'
}
/>
)}
<Box display='flex' alignItems='center' justifyContent='space-between'>
<ArrowLeft
color={palette.text.secondary}
style={{ cursor: 'pointer' }}
onClick={onClose}
/>
<Typography
variant='subtitle2'
style={{ color: palette.text.primary }}
>
Remove Liquidity
</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'>
{currency0.symbol} / {currency1.symbol} LP
</Typography>
<Typography variant='body2'>
Balance: {formatTokenAmount(userPoolBalance)}
</Typography>
</Box>
<Box mt={2}>
<NumericalInput
placeholder='0'
value={formattedAmounts[Field.LIQUIDITY]}
fontSize={28}
onUserInput={(value) => {
onLiquidityInput(value);
}}
/>
</Box>
<Box display='flex' alignItems='center'>
<Box flex={1} mr={2} mt={0.5}>
<ColoredSlider
min={1}
max={100}
step={1}
value={innerLiquidityPercentage}
onChange={(evt: any, value) =>
setInnerLiquidityPercentage(value as number)
}
/>
</Box>
<Typography variant='body2'>
{formattedAmounts[Field.LIQUIDITY_PERCENT]}%
</Typography>
</Box>
</Box>
<Box display='flex' my={3} justifyContent='center'>
<ArrowDown color={palette.text.secondary} />
</Box>
<Box
padding='16px'
bgcolor={palette.secondary.light}
borderRadius='10px'
>
<Box
display='flex'
justifyContent='space-between'
alignItems='center'
>
<Typography variant='body1'>Pooled {currency0.symbol}</Typography>
<Box display='flex' alignItems='center'>
<Typography variant='body1' style={{ marginRight: 6 }}>
{formatTokenAmount(token0Deposited)}
</Typography>
<CurrencyLogo currency={currency0} />
</Box>
</Box>
<Box
mt={1}
display='flex'
justifyContent='space-between'
alignItems='center'
>
<Typography
variant='body1'
style={{ color: 'rgba(68, 138, 255, 0.5)' }}
>
- Withdraw {currency0.symbol}
</Typography>
<Typography
variant='body1'
style={{ color: 'rgba(68, 138, 255, 0.5)' }}
>
{formattedAmounts[Field.CURRENCY_A]}
</Typography>
</Box>
<Box
mt={1}
display='flex'
justifyContent='space-between'
alignItems='center'
>
<Typography variant='body1'>Pooled {currency1.symbol}</Typography>
<Box display='flex' alignItems='center'>
<Typography variant='body1' style={{ marginRight: 6 }}>
{formatTokenAmount(token1Deposited)}
</Typography>
<CurrencyLogo currency={currency1} />
</Box>
</Box>
<Box
mt={1}
display='flex'
justifyContent='space-between'
alignItems='center'
>
<Typography
variant='body1'
style={{ color: 'rgba(68, 138, 255, 0.5)' }}
>
- Withdraw {currency1.symbol}
</Typography>
<Typography
variant='body1'
style={{ color: 'rgba(68, 138, 255, 0.5)' }}
>
{formattedAmounts[Field.CURRENCY_B]}
</Typography>
</Box>
<Box
mt={1}
display='flex'
justifyContent='space-between'
alignItems='center'
>
<Typography variant='body1'>Your Pool Share</Typography>
<Typography variant='body1'>
{poolTokenPercentage
? poolTokenPercentage.toSignificant() + '%'
: '-'}
</Typography>
</Box>
</Box>
{pair && (
<Box
display='flex'
mt={2}
px={2}
alignItems='center'
justifyContent='space-between'
>
<Typography variant='body2'>
1 {currency0.symbol} ={' '}
{tokenA ? pair.priceOf(tokenA).toSignificant(6) : '-'}{' '}
{currency1.symbol}
</Typography>
<Typography variant='body2'>
1 {currency1.symbol} ={' '}
{tokenB ? pair.priceOf(tokenB).toSignificant(6) : '-'}{' '}
{currency0.symbol}
</Typography>
</Box>
)}
<Box
mt={2}
display='flex'
alignItems='center'
justifyContent='space-between'
>
<Button
className={classes.removeButton}
onClick={onAttemptToApprove}
disabled={approving || approval !== ApprovalState.NOT_APPROVED}
>
{approving
? 'Approving...'
: approval === ApprovalState.APPROVED
? 'Approved'
: 'Approve'}
</Button>
<Button
className={classes.removeButton}
onClick={() => {
setShowConfirm(true);
}}
disabled={Boolean(error) || approval !== ApprovalState.APPROVED}
>
{error || 'Remove'}
</Button>
</Box>
<Box mt={2}>
<Typography variant='body1' style={{ color: palette.error.main }}>
{errorMsg}
</Typography>
</Box>
</Box>
</CustomModal>
);
}
Example #10
Source File: index.tsx From interface-v2 with GNU General Public License v3.0 | 4 votes |
Search: React.FC = () => {
const classes = useStyles();
const history = useHistory();
const [searchVal, setSearchVal] = useState('');
const [menuOpen, setMenuOpen] = useState(false);
const menuRef = useRef<any>(null);
const wrapperRef = useRef<any>(null);
const [searchedTokens, setSearchedTokens] = useState<any[]>([]);
const [searchedPairs, setSearchedPairs] = useState<any[]>([]);
const [tokensShown, setTokensShown] = useState(3);
const [pairsShown, setPairsShown] = useState(3);
const [allTokens, setAllTokens] = useState<any[]>([]);
const [allPairs, setAllPairs] = useState<any[]>([]);
const escapeRegExp = (str: string) => {
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
};
const filteredTokens = useMemo(() => {
const tokens = allTokens.concat(
searchedTokens.filter((searchedToken) => {
let included = false;
allTokens.map((token) => {
if (token.id === searchedToken.id) {
included = true;
}
return true;
});
return !included;
}),
);
const filtered = tokens
? tokens.filter((token) => {
if (GlobalConst.blacklists.TOKEN_BLACKLIST.includes(token.id)) {
return false;
}
const regexMatches = Object.keys(token).map((tokenEntryKey) => {
const isAddress = searchVal.slice(0, 2) === '0x';
if (tokenEntryKey === 'id' && isAddress) {
return token[tokenEntryKey].match(
new RegExp(escapeRegExp(searchVal), 'i'),
);
}
if (tokenEntryKey === 'symbol' && !isAddress) {
return token[tokenEntryKey].match(
new RegExp(escapeRegExp(searchVal), 'i'),
);
}
if (tokenEntryKey === 'name' && !isAddress) {
return token[tokenEntryKey].match(
new RegExp(escapeRegExp(searchVal), 'i'),
);
}
return false;
});
return regexMatches.some((m) => m);
})
: [];
return filtered;
}, [allTokens, searchedTokens, searchVal]);
const filteredPairs = useMemo(() => {
const pairs = allPairs.concat(
searchedPairs.filter((searchedPair) => {
let included = false;
allPairs.map((pair) => {
if (pair.id === searchedPair.id) {
included = true;
}
return true;
});
return !included;
}),
);
const filtered = pairs
? pairs.filter((pair) => {
if (GlobalConst.blacklists.PAIR_BLACKLIST.includes(pair.id)) {
return false;
}
if (searchVal && searchVal.includes(' ')) {
const pairA = searchVal.split(' ')[0]?.toUpperCase();
const pairB = searchVal.split(' ')[1]?.toUpperCase();
return (
(pair.token0.symbol.includes(pairA) ||
pair.token0.symbol.includes(pairB)) &&
(pair.token1.symbol.includes(pairA) ||
pair.token1.symbol.includes(pairB))
);
}
if (searchVal && searchVal.includes('-')) {
const pairA = searchVal.split('-')[0]?.toUpperCase();
const pairB = searchVal.split('-')[1]?.toUpperCase();
return (
(pair.token0.symbol.includes(pairA) ||
pair.token0.symbol.includes(pairB)) &&
(pair.token1.symbol.includes(pairA) ||
pair.token1.symbol.includes(pairB))
);
}
const regexMatches = Object.keys(pair).map((field) => {
const isAddress = searchVal.slice(0, 2) === '0x';
if (field === 'id' && isAddress) {
return pair[field].match(
new RegExp(escapeRegExp(searchVal), 'i'),
);
}
if (field === 'token0') {
return (
pair[field].symbol.match(
new RegExp(escapeRegExp(searchVal), 'i'),
) ||
pair[field].name.match(new RegExp(escapeRegExp(searchVal), 'i'))
);
}
if (field === 'token1') {
return (
pair[field].symbol.match(
new RegExp(escapeRegExp(searchVal), 'i'),
) ||
pair[field].name.match(new RegExp(escapeRegExp(searchVal), 'i'))
);
}
return false;
});
return regexMatches.some((m) => m);
})
: [];
return filtered;
}, [allPairs, searchedPairs, searchVal]);
useEffect(() => {
async function fetchAllData() {
const tokens = await getAllTokensOnUniswap();
const pairs = await getAllPairsOnUniswap();
if (tokens) {
setAllTokens(tokens);
}
if (pairs) {
setAllPairs(pairs);
}
}
fetchAllData();
}, []);
useEffect(() => {
async function fetchData() {
try {
if (searchVal.length > 0) {
const tokens = await client.query({
query: TOKEN_SEARCH,
variables: {
value: searchVal ? searchVal.toUpperCase() : '',
id: searchVal,
},
});
const pairs = await client.query({
query: PAIR_SEARCH,
variables: {
tokens: tokens.data.asSymbol?.map((t: any) => t.id),
id: searchVal,
},
});
setSearchedPairs(
pairs.data.as0.concat(pairs.data.as1).concat(pairs.data.asAddress),
);
const foundTokens = tokens.data.asSymbol
.concat(tokens.data.asAddress)
.concat(tokens.data.asName);
setSearchedTokens(foundTokens);
}
} catch (e) {
console.log(e);
}
}
fetchData();
}, [searchVal]);
const handleClick = (e: any) => {
if (
!(menuRef.current && menuRef.current.contains(e.target)) &&
!(wrapperRef.current && wrapperRef.current.contains(e.target))
) {
setPairsShown(3);
setTokensShown(3);
setMenuOpen(false);
}
};
useEffect(() => {
document.addEventListener('click', handleClick);
return () => {
document.removeEventListener('click', handleClick);
};
});
return (
<Box position='relative'>
<Box className={classes.searchInput}>
<input
placeholder='Search for tokens, pairs, etc…'
value={searchVal}
ref={menuRef}
onFocus={() => setMenuOpen(true)}
onChange={(evt) => setSearchVal(evt.target.value)}
/>
<Box display='flex'>
<SearchIcon />
</Box>
</Box>
{menuOpen && (
<div ref={wrapperRef} className={classes.searchContent}>
<Typography variant='body1'>Pairs</Typography>
{filteredPairs.slice(0, pairsShown).map((val, ind) => {
const currency0 = new Token(
ChainId.MATIC,
getAddress(val.token0.id),
val.token0.decimals,
);
const currency1 = new Token(
ChainId.MATIC,
getAddress(val.token1.id),
val.token1.decimals,
);
return (
<Box
mt={1}
key={ind}
display='flex'
alignItems='center'
style={{ cursor: 'pointer' }}
onClick={() => history.push(`/analytics/pair/${val.id}`)}
>
<DoubleCurrencyLogo
currency0={currency0}
currency1={currency1}
size={28}
/>
<Typography variant='body2' style={{ marginLeft: 8 }}>
{val.token0.symbol} - {val.token1.symbol} Pair
</Typography>
</Box>
);
})}
<Typography
variant='body2'
style={{ cursor: 'pointer', margin: '8px 0' }}
onClick={() => setPairsShown(pairsShown + 5)}
>
Show More
</Typography>
<Typography variant='body1'>Tokens</Typography>
{filteredTokens.slice(0, tokensShown).map((val, ind) => {
const currency = new Token(
ChainId.MATIC,
getAddress(val.id),
val.decimals,
);
return (
<Box
mt={1}
key={ind}
display='flex'
alignItems='center'
style={{ cursor: 'pointer' }}
onClick={() => history.push(`/analytics/token/${val.id}`)}
>
<CurrencyLogo currency={currency} size='28px' />
<Typography variant='body2' style={{ marginLeft: 8 }}>
{val.name} {val.symbol}
</Typography>
</Box>
);
})}
<Typography
variant='body2'
style={{ cursor: 'pointer', marginTop: 8 }}
onClick={() => setTokensShown(tokensShown + 5)}
>
Show More
</Typography>
</div>
)}
</Box>
);
}
Example #11
Source File: AnalyticsPairDetails.tsx From interface-v2 with GNU General Public License v3.0 | 4 votes |
AnalyticsPairDetails: React.FC = () => {
const classes = useStyles();
const { palette, breakpoints } = useTheme();
const isMobile = useMediaQuery(breakpoints.down('xs'));
const history = useHistory();
const match = useRouteMatch<{ id: string }>();
const pairAddress = match.params.id;
const [pairData, setPairData] = useState<any>(null);
const [pairTransactions, setPairTransactions] = useState<any>(null);
const pairTransactionsList = useMemo(() => {
if (pairTransactions) {
const mints = pairTransactions.mints.map((item: any) => {
return { ...item, type: TxnType.ADD };
});
const swaps = pairTransactions.swaps.map((item: any) => {
const amount0 = item.amount0Out > 0 ? item.amount0Out : item.amount1Out;
const amount1 = item.amount0In > 0 ? item.amount0In : item.amount1In;
const token0 =
item.amount0Out > 0 ? item.pair.token0 : item.pair.token1;
const token1 =
item.amount0Out > 0 ? item.pair.token1 : item.pair.token0;
return {
...item,
amount0,
amount1,
pair: { token0, token1 },
type: TxnType.SWAP,
};
});
const burns = pairTransactions.burns.map((item: any) => {
return { ...item, type: TxnType.REMOVE };
});
return mints.concat(swaps).concat(burns);
} else {
return null;
}
}, [pairTransactions]);
const { chainId } = useActiveWeb3React();
const currency0 = pairData
? new Token(
ChainId.MATIC,
getAddress(pairData.token0.id),
pairData.token0.decimals,
)
: undefined;
const currency1 = pairData
? new Token(
ChainId.MATIC,
getAddress(pairData.token1.id),
pairData.token1.decimals,
)
: undefined;
const token0Rate =
pairData && pairData.reserve0 && pairData.reserve1
? Number(pairData.reserve1) / Number(pairData.reserve0) >= 0.0001
? (Number(pairData.reserve1) / Number(pairData.reserve0)).toFixed(
Number(pairData.reserve1) / Number(pairData.reserve0) > 1 ? 2 : 4,
)
: '< 0.0001'
: '-';
const token1Rate =
pairData && pairData.reserve0 && pairData.reserve1
? Number(pairData.reserve0) / Number(pairData.reserve1) >= 0.0001
? (Number(pairData.reserve0) / Number(pairData.reserve1)).toFixed(
Number(pairData.reserve0) / Number(pairData.reserve1) > 1 ? 2 : 4,
)
: '< 0.0001'
: '-';
const usingUtVolume =
pairData &&
pairData.oneDayVolumeUSD === 0 &&
!!pairData.oneDayVolumeUntracked;
const fees =
pairData && (pairData.oneDayVolumeUSD || pairData.oneDayVolumeUSD === 0)
? usingUtVolume
? (
Number(pairData.oneDayVolumeUntracked) *
GlobalConst.utils.FEEPERCENT
).toLocaleString()
: (
Number(pairData.oneDayVolumeUSD) * GlobalConst.utils.FEEPERCENT
).toLocaleString()
: '-';
useEffect(() => {
async function checkEthPrice() {
const [newPrice] = await getEthPrice();
const pairInfo = await getBulkPairData([pairAddress], newPrice);
if (pairInfo && pairInfo.length > 0) {
setPairData(pairInfo[0]);
}
}
async function fetchTransctions() {
const transactions = await getPairTransactions(pairAddress);
if (transactions) {
setPairTransactions(transactions);
}
}
checkEthPrice();
fetchTransctions();
}, [pairAddress]);
return (
<>
<AnalyticsHeader type='pair' data={pairData} />
{pairData ? (
<>
<Box
width={1}
display='flex'
flexWrap='wrap'
justifyContent='space-between'
>
<Box>
<Box display='flex' alignItems='center'>
<DoubleCurrencyLogo
currency0={currency0}
currency1={currency1}
size={32}
/>
<Box ml={1}>
<Typography className={classes.heading2}>
<Link to={`/analytics/token/${pairData.token0.id}`}>
{pairData.token0.symbol}
</Link>{' '}
/{' '}
<Link to={`/analytics/token/${pairData.token1.id}`}>
{pairData.token1.symbol}
</Link>
</Typography>
</Box>
</Box>
<Box mt={2} display='flex'>
<Box
paddingY={0.75}
paddingX={1.5}
borderRadius={20}
display='flex'
alignItems='center'
bgcolor={palette.grey.A700}
>
<CurrencyLogo currency={currency0} size='16px' />
<Typography
variant='body2'
color='textPrimary'
style={{ marginLeft: 6 }}
>
1 {pairData.token0.symbol} = {token0Rate}{' '}
{pairData.token1.symbol}
</Typography>
</Box>
<Box
padding={0.75}
paddingX={1.5}
ml={2}
borderRadius={20}
display='flex'
alignItems='center'
bgcolor={palette.grey.A700}
>
<CurrencyLogo currency={currency1} size='16px' />
<Typography
variant='body2'
color='textPrimary'
style={{ marginLeft: 6 }}
>
1 {pairData.token1.symbol} = {token1Rate}{' '}
{pairData.token0.symbol}
</Typography>
</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=${pairData.token0.id}¤cy1=${pairData.token1.id}`,
);
}}
>
<Typography variant='body2'>Add Liquidity</Typography>
</Box>
<Box
className={cx(classes.button, classes.filledButton)}
onClick={() => {
history.push(
`/swap?currency0=${pairData.token0.id}¤cy1=${pairData.token1.id}`,
);
}}
>
<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}>
<AnalyticsPairChart pairData={pairData} />
</Grid>
<Grid item xs={12} sm={12} md={6}>
<Box
my={2}
height={1}
display='flex'
justifyContent='center'
alignItems='center'
>
<Box
width={isMobile ? 1 : 0.8}
display='flex'
justifyContent='space-between'
>
<Box width={212}>
<Box>
<Typography
variant='caption'
style={{ color: palette.text.disabled }}
>
TOTAL TOKENS LOCKED
</Typography>
<Box
mt={1.5}
bgcolor={palette.grey.A400}
borderRadius={8}
padding={1.5}
>
<Box
display='flex'
alignItems='center'
justifyContent='space-between'
>
<Box display='flex' alignItems='center'>
<CurrencyLogo currency={currency0} size='16px' />
<Typography
variant='caption'
color='textPrimary'
style={{ marginLeft: 6 }}
>
{pairData.token0.symbol} :
</Typography>
</Box>
<Typography variant='caption' color='textPrimary'>
{Number(pairData.reserve0).toLocaleString()}
</Typography>
</Box>
<Box
mt={1}
display='flex'
alignItems='center'
justifyContent='space-between'
>
<Box display='flex' alignItems='center'>
<CurrencyLogo currency={currency1} size='16px' />
<Typography
variant='caption'
color='textPrimary'
style={{ marginLeft: 6 }}
>
{pairData.token1.symbol} :
</Typography>
</Box>
<Typography variant='caption' color='textPrimary'>
{Number(pairData.reserve1).toLocaleString()}
</Typography>
</Box>
</Box>
</Box>
<Box mt={4}>
<Typography
variant='caption'
style={{ color: palette.text.disabled }}
>
7d Trading Vol
</Typography>
<Typography variant={isMobile ? 'body1' : 'h5'}>
${pairData.oneWeekVolumeUSD.toLocaleString()}
</Typography>
</Box>
<Box mt={4}>
<Typography
variant='caption'
style={{ color: palette.text.disabled }}
>
24h FEES
</Typography>
<Typography variant={isMobile ? 'body1' : 'h5'}>
${fees}
</Typography>
</Box>
</Box>
<Box width={140}>
<Typography
variant='caption'
style={{ color: palette.text.disabled }}
>
TOTAL LIQUIDITY
</Typography>
<Typography variant={isMobile ? 'body1' : 'h5'}>
$
{Number(
pairData.reserveUSD
? pairData.reserveUSD
: pairData.trackedReserveUSD,
).toLocaleString()}
</Typography>
<Box mt={4}>
<Typography
variant='caption'
style={{ color: palette.text.disabled }}
>
24h Trading Vol
</Typography>
<Typography variant={isMobile ? 'body1' : 'h5'}>
${pairData.oneDayVolumeUSD.toLocaleString()}
</Typography>
</Box>
<Box mt={4}>
<Typography
variant='caption'
style={{ color: palette.text.disabled }}
>
Contract Address
</Typography>
<Typography
variant='h5'
style={{ color: palette.primary.main }}
>
{chainId ? (
<a
href={getEtherscanLink(
chainId,
pairData.id,
'address',
)}
target='_blank'
rel='noopener noreferrer'
style={{
color: palette.primary.main,
textDecoration: 'none',
}}
>
{shortenAddress(pairData.id)}
</a>
) : (
shortenAddress(pairData.id)
)}
</Typography>
</Box>
</Box>
</Box>
</Box>
</Grid>
</Grid>
</Box>
<Box width={1} mt={5}>
<Typography variant='body1'>Transactions</Typography>
</Box>
<Box width={1} className={classes.panel} mt={4}>
{pairTransactionsList ? (
<TransactionsTable data={pairTransactionsList} />
) : (
<Skeleton variant='rect' width='100%' height={150} />
)}
</Box>
</>
) : (
<Skeleton width='100%' height={100} />
)}
</>
);
}
Example #12
Source File: LiquidityPoolRow.tsx From interface-v2 with GNU General Public License v3.0 | 4 votes |
LiquidityPoolRow: React.FC<{
pair: any;
key: number;
}> = ({ pair, key }) => {
const classes = useStyles();
const { palette, breakpoints } = useTheme();
const daysCurrentYear = getDaysCurrentYear();
const isMobile = useMediaQuery(breakpoints.down('xs'));
const dayVolumeUSD =
Number(
pair.oneDayVolumeUSD ? pair.oneDayVolumeUSD : pair.oneDayVolumeUntracked,
) *
GlobalConst.utils.FEEPERCENT *
daysCurrentYear *
100;
const trackReserveUSD = Number(
pair.oneDayVolumeUSD ? pair.trackedReserveUSD : pair.reserveUSD,
);
const apy =
isNaN(dayVolumeUSD) || trackReserveUSD === 0
? 0
: dayVolumeUSD / trackReserveUSD;
const liquidity = pair.trackedReserveUSD
? pair.trackedReserveUSD
: pair.reserveUSD;
const volume = pair.oneDayVolumeUSD
? pair.oneDayVolumeUSD
: pair.oneDayVolumeUntracked;
const token0 = useCurrency(pair.token0.id);
const token1 = useCurrency(pair.token1.id);
return (
<Box
key={key}
display='flex'
flexWrap='wrap'
className={classes.liquidityContent}
padding={2}
>
<Box display='flex' alignItems='center' width={isMobile ? 1 : 0.5}>
<DoubleCurrencyLogo
currency0={token0 ?? undefined}
currency1={token1 ?? undefined}
size={28}
/>
<Typography variant='body2' style={{ marginLeft: 12 }}>
{pair.token0.symbol.toUpperCase()} /{' '}
{pair.token1.symbol.toUpperCase()}
</Typography>
</Box>
<Box
width={isMobile ? 1 : 0.2}
mt={isMobile ? 2.5 : 0}
display='flex'
justifyContent='space-between'
>
{isMobile && (
<Typography variant='body2' style={{ color: palette.text.secondary }}>
TVL
</Typography>
)}
<Typography variant='body2'>${formatCompact(liquidity)}</Typography>
</Box>
<Box
width={isMobile ? 1 : 0.15}
mt={isMobile ? 1 : 0}
display='flex'
justifyContent='space-between'
>
{isMobile && (
<Typography variant='body2' style={{ color: palette.text.secondary }}>
24H Volume
</Typography>
)}
<Typography variant='body2'>${formatCompact(volume)}</Typography>
</Box>
<Box
width={isMobile ? 1 : 0.15}
mt={isMobile ? 1 : 0}
display='flex'
justifyContent={isMobile ? 'space-between' : 'flex-end'}
>
{isMobile && (
<Typography variant='body2' style={{ color: palette.text.secondary }}>
APY
</Typography>
)}
<Typography
variant='body2'
align='right'
style={{
color: apy < 0 ? palette.error.main : palette.success.main,
}}
>
{apy.toFixed(2)}%
</Typography>
</Box>
</Box>
);
}