utils#getExplorerLink TypeScript Examples
The following examples show how to use
utils#getExplorerLink.
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: Transaction.tsx From vvs-ui with GNU General Public License v3.0 | 6 votes |
export default function Transaction({ tx }: { tx: TransactionDetails }) {
const { chainId } = useActiveWeb3React()
const summary = tx?.summary
const pending = !tx?.receipt
const success = !pending && tx && (tx.receipt?.status === 1 || typeof tx.receipt?.status === 'undefined')
if (!chainId) return null
return (
<TransactionState pending={pending} success={success}>
<LinkExternal href={getExplorerLink(tx.hash, 'transaction', chainId)}>{summary ?? tx.hash}</LinkExternal>
<IconWrapper pending={pending} success={success}>
{pending ? <CircleLoader /> : success ? <CheckmarkIcon color="success" /> : <CloseIcon color="failure" />}
</IconWrapper>
</TransactionState>
)
}
Example #2
Source File: VoteRow.tsx From vvs-ui with GNU General Public License v3.0 | 6 votes |
VoteRow: React.FC<VoteRowProps> = ({ vote, isVoter }) => {
const { t } = useTranslation()
const hasVotingPower = !!vote.metadata?.votingPower
const votingPower = hasVotingPower
? parseFloat(vote.metadata.votingPower).toLocaleString(undefined, {
minimumFractionDigits: 0,
maximumFractionDigits: 3,
})
: '--'
return (
<Row>
<AddressColumn>
<Flex alignItems="center">
<LinkExternal href={getExplorerLink(vote.voter, 'address')}>{truncateHash(vote.voter)}</LinkExternal>
{isVoter && (
<Tag variant="success" outline ml="8px">
<CheckmarkCircleIcon mr="4px" /> {t('Voted')}
</Tag>
)}
</Flex>
</AddressColumn>
<ChoiceColumn>
<TextEllipsis title={vote.proposal.choices[vote.choice - 1]}>
{vote.proposal.choices[vote.choice - 1]}
</TextEllipsis>
</ChoiceColumn>
<VotingPowerColumn>
<Flex alignItems="center" justifyContent="end">
<Text title={vote.metadata.votingPower}>{votingPower}</Text>
{hasVotingPower && <LinkExternal href={`${IPFS_GATEWAY}/${vote.id}`} />}
</Flex>
</VotingPowerColumn>
</Row>
)
}
Example #3
Source File: Timer.tsx From vvs-ui with GNU General Public License v3.0 | 6 votes |
TooltipContent = ({ blockNumber, t }: { blockNumber: number; t: ContextApi['t'] }): JSX.Element => (
<>
<Text color="body" mb="10px" fontWeight="600">
{t('Block %num%', { num: blockNumber })}
</Text>
<Link external href={getExplorerLink(blockNumber, 'block')}>
{t('View on Cronos Explorer')}
</Link>
</>
)
Example #4
Source File: ResultAvatar.tsx From vvs-ui with GNU General Public License v3.0 | 6 votes |
ResultAvatar: React.FC<ResultAvatarProps> = ({ user, ...props }) => {
const { t } = useTranslation()
const profileAvatar = useGetProfileAvatar(user.id)
const [onPresentWalletStatsModal] = useModal(<WalletStatsModal account={user.id} />)
return (
<SubMenu
component={
<Flex alignItems="center" {...props}>
<UsernameWrapper>
<Text color="primary" fontWeight="bold">
{profileAvatar.username || truncateHash(user.id)}
</Text>{' '}
</UsernameWrapper>
<AvatarWrapper
width={['32px', null, null, null, null, '40px']}
height={['32px', null, null, null, null, '40px']}
>
<ProfileAvatar src={`/images/nfts/${profileAvatar.nft?.images?.md}`} height={40} width={40} />
</AvatarWrapper>
</Flex>
}
options={{ placement: 'bottom-start' }}
>
<SubMenuItem onClick={onPresentWalletStatsModal}>{t('View Stats')}</SubMenuItem>
<SubMenuItem as={Link} href={getExplorerLink(user.id, 'address')} bold={false} color="text" external>
{t('View on Cronos Explorer')}
</SubMenuItem>
</SubMenu>
)
}
Example #5
Source File: TransactionsTable.tsx From vvs-ui with GNU General Public License v3.0 | 6 votes |
DataRow: React.FC<{ transaction: Transaction }> = ({ transaction }) => {
const { t } = useTranslation()
const abs0 = Math.abs(transaction.amountToken0)
const abs1 = Math.abs(transaction.amountToken1)
const outputTokenSymbol = transaction.amountToken0 < 0 ? transaction.token0Symbol : transaction.token1Symbol
const inputTokenSymbol = transaction.amountToken1 < 0 ? transaction.token0Symbol : transaction.token1Symbol
return (
<ResponsiveGrid>
<LinkExternal href={getExplorerLink(transaction.hash, 'transaction')}>
<Text>
{transaction.type === TransactionType.MINT
? t('Add %token0% and %token1%', { token0: transaction.token0Symbol, token1: transaction.token1Symbol })
: transaction.type === TransactionType.SWAP
? t('Swap %token0% for %token1%', { token0: inputTokenSymbol, token1: outputTokenSymbol })
: t('Remove %token0% and %token1%', { token0: transaction.token0Symbol, token1: transaction.token1Symbol })}
</Text>
</LinkExternal>
<Text>${formatAmount(transaction.amountUSD)}</Text>
<Text>
<Text>{`${formatAmount(abs0)} ${transaction.token0Symbol}`}</Text>
</Text>
<Text>
<Text>{`${formatAmount(abs1)} ${transaction.token1Symbol}`}</Text>
</Text>
<LinkExternal href={getExplorerLink(transaction.sender, 'address')}>
<Text>{truncateHash(transaction.sender)}</Text>
</LinkExternal>
<Text>{formatDistanceToNowStrict(parseInt(transaction.timestamp, 10) * 1000)}</Text>
</ResponsiveGrid>
)
}
Example #6
Source File: Timer.tsx From vvs-ui with GNU General Public License v3.0 | 6 votes |
Timer: React.FC<Props> = ({ publicIfoData }) => {
const { t } = useTranslation()
const { status, secondsUntilStart, secondsUntilEnd, startBlockNum } = publicIfoData
const countdownToUse = status === 'coming_soon' ? secondsUntilStart : secondsUntilEnd
const timeUntil = getTimePeriods(countdownToUse)
const suffix = status === 'coming_soon' ? t('Start').toLowerCase() : t('Finish').toLowerCase()
return (
<Flex justifyContent="center" mb="32px">
{status === 'idle' ? (
<Skeleton animation="pulse" variant="rect" width="100%" height="48px" />
) : (
<>
<PocketWatchIcon width="48px" mr="16px" />
<Flex alignItems="center">
<Text bold mr="16px">
{suffix}:
</Text>
<Text>
{t('%day%d %hour%h %minute%m', {
day: timeUntil.days,
hour: timeUntil.hours,
minute: timeUntil.minutes,
})}
</Text>
<Link
href={getExplorerLink(startBlockNum, 'countdown')}
target="blank"
rel="noopener noreferrer"
ml="8px"
textTransform="lowercase"
>
{`(${t('Blocks')})`}
</Link>
</Flex>
</>
)}
</Flex>
)
}
Example #7
Source File: DescriptionWithTx.tsx From vvs-ui with GNU General Public License v3.0 | 6 votes |
DescriptionWithTx: React.FC<DescriptionWithTxProps> = ({ txHash, children }) => {
const { chainId } = useActiveWeb3React()
const { t } = useTranslation()
return (
<>
{typeof children === 'string' ? <Text as="p">{children}</Text> : children}
{txHash && (
<Link external href={getExplorerLink(txHash, 'transaction', chainId)}>
{t('View on Cronos Explorer')}: {truncateHash(txHash, 8, 0)}
</Link>
)}
</>
)
}
Example #8
Source File: TransactionRow.tsx From vvs-ui with GNU General Public License v3.0 | 6 votes |
TransactionRow: React.FC<TransactionRowProps> = ({ txn }) => {
const { chainId } = useActiveWeb3React()
if (!txn) {
return null
}
return (
<TxnLink href={getExplorerLink(txn.hash, 'transaction', chainId)} external>
<TxnIcon>{renderIcon(txn)}</TxnIcon>
<Summary>{txn.summary ?? txn.hash}</Summary>
<TxnIcon>
<OpenNewIcon width="24px" color="primary" />
</TxnIcon>
</TxnLink>
)
}
Example #9
Source File: UnsupportedCurrencyFooter.tsx From vvs-ui with GNU General Public License v3.0 | 5 votes |
UnsupportedModal: React.FC<Props> = ({ currencies, onDismiss }) => {
const { chainId } = useActiveWeb3React()
const tokens =
chainId && currencies
? currencies.map((currency) => {
return wrappedCurrency(currency, chainId)
})
: []
const unsupportedTokens: { [address: string]: Token } = useUnsupportedTokens()
return (
<Modal title="Unsupported Assets" maxWidth="420px" onDismiss={onDismiss}>
<AutoColumn gap="lg">
{tokens.map((token) => {
return (
token &&
unsupportedTokens &&
Object.keys(unsupportedTokens).includes(token.address) && (
<AutoColumn key={token.address?.concat('not-supported')} gap="10px">
<AutoRow gap="5px" align="center">
<CurrencyLogo currency={token} size="24px" />
<Text>{token.symbol}</Text>
</AutoRow>
{chainId && (
<Link external small color="primaryDark" href={getExplorerLink(token.address, 'address', chainId)}>
{token.address}
</Link>
)}
</AutoColumn>
)
)
})}
<AutoColumn gap="lg">
<Text>
Some assets are not available through this interface because they may not work well with our smart contract
or we are unable to allow trading for legal reasons.
</Text>
</AutoColumn>
</AutoColumn>
</Modal>
)
}
Example #10
Source File: index.test.ts From vvs-ui with GNU General Public License v3.0 | 5 votes |
describe('utils', () => {
describe('#getBscScanLink', () => {
it('correct for tx', () => {
expect(getExplorerLink('abc', 'transaction', ChainId.MAINNET)).toEqual('https://bscscan.com/tx/abc')
})
it('correct for token', () => {
expect(getExplorerLink('abc', 'token', ChainId.MAINNET)).toEqual('https://bscscan.com/token/abc')
})
it('correct for address', () => {
expect(getExplorerLink('abc', 'address', ChainId.MAINNET)).toEqual('https://bscscan.com/address/abc')
})
it('enum', () => {
expect(getExplorerLink('abc', 'address', ChainId.TESTNET)).toEqual('https://testnet.bscscan.com/address/abc')
})
})
describe('#calculateSlippageAmount', () => {
it('bounds are correct', () => {
const tokenAmount = new TokenAmount(new Token(ChainId.MAINNET, AddressZero, 0), '100')
expect(() => calculateSlippageAmount(tokenAmount, -1)).toThrow()
expect(calculateSlippageAmount(tokenAmount, 0).map((bound) => bound.toString())).toEqual(['100', '100'])
expect(calculateSlippageAmount(tokenAmount, 100).map((bound) => bound.toString())).toEqual(['99', '101'])
expect(calculateSlippageAmount(tokenAmount, 200).map((bound) => bound.toString())).toEqual(['98', '102'])
expect(calculateSlippageAmount(tokenAmount, 10000).map((bound) => bound.toString())).toEqual(['0', '200'])
expect(() => calculateSlippageAmount(tokenAmount, 10001)).toThrow()
})
})
describe('#isAddress', () => {
it('returns false if not', () => {
expect(isAddress('')).toBe(false)
expect(isAddress('0x0000')).toBe(false)
expect(isAddress(1)).toBe(false)
expect(isAddress({})).toBe(false)
expect(isAddress(undefined)).toBe(false)
})
it('returns the checksummed address', () => {
expect(isAddress('0xf164fc0ec4e93095b804a4795bbe1e041497b92a')).toBe('0xf164fC0Ec4E93095b804a4795bBe1e041497b92a')
expect(isAddress('0xf164fC0Ec4E93095b804a4795bBe1e041497b92a')).toBe('0xf164fC0Ec4E93095b804a4795bBe1e041497b92a')
})
it('succeeds even without prefix', () => {
expect(isAddress('f164fc0ec4e93095b804a4795bbe1e041497b92a')).toBe('0xf164fC0Ec4E93095b804a4795bBe1e041497b92a')
})
it('fails if too long', () => {
expect(isAddress('f164fc0ec4e93095b804a4795bbe1e041497b92a0')).toBe(false)
})
})
describe('#calculateGasMargin', () => {
it('adds 10%', () => {
expect(calculateGasMargin(BigNumber.from(1000)).toString()).toEqual('1100')
expect(calculateGasMargin(BigNumber.from(50)).toString()).toEqual('55')
})
})
describe('#basisPointsToPercent', () => {
it('converts basis points numbers to percents', () => {
expect(basisPointsToPercent(100).equalTo(new Percent(JSBI.BigInt(1), JSBI.BigInt(100)))).toBeTruthy()
expect(basisPointsToPercent(500).equalTo(new Percent(JSBI.BigInt(5), JSBI.BigInt(100)))).toBeTruthy()
expect(basisPointsToPercent(50).equalTo(new Percent(JSBI.BigInt(5), JSBI.BigInt(1000)))).toBeTruthy()
})
})
})
Example #11
Source File: Details.tsx From vvs-ui with GNU General Public License v3.0 | 5 votes |
Details: React.FC<DetailsProps> = ({ proposal }) => {
const { t } = useTranslation()
const startDate = new Date(proposal.start * 1000)
const endDate = new Date(proposal.end * 1000)
return (
<Card mb="16px">
<CardHeader>
<Heading as="h3" scale="md">
{t('Details')}
</Heading>
</CardHeader>
<CardBody>
<Flex alignItems="center" mb="8px">
<Text color="textSubtle">{t('Identifier')}</Text>
<LinkExternal href={`${IPFS_GATEWAY}/${proposal.id}`} ml="8px">
{proposal.id.slice(0, 8)}
</LinkExternal>
</Flex>
<Flex alignItems="center" mb="8px">
<Text color="textSubtle">{t('Creator')}</Text>
<LinkExternal href={getExplorerLink(proposal.author, 'address')} ml="8px">
{truncateHash(proposal.author)}
</LinkExternal>
</Flex>
<Flex alignItems="center" mb="16px">
<Text color="textSubtle">{t('Snapshot')}</Text>
<LinkExternal href={getExplorerLink(proposal.snapshot, 'block')} ml="8px">
{proposal.snapshot}
</LinkExternal>
</Flex>
<DetailBox p="16px">
<ProposalStateTag proposalState={proposal.state} mb="8px" />
<Flex alignItems="center">
<Text color="textSubtle" fontSize="14px">
{t('Start Date')}
</Text>
<Text ml="8px">{format(startDate, 'yyyy-MM-dd HH:mm')}</Text>
</Flex>
<Flex alignItems="center">
<Text color="textSubtle" fontSize="14px">
{t('End Date')}
</Text>
<Text ml="8px">{format(endDate, 'yyyy-MM-dd HH:mm')}</Text>
</Flex>
</DetailBox>
</CardBody>
</Card>
)
}
Example #12
Source File: PublicProfile.tsx From vvs-ui with GNU General Public License v3.0 | 5 votes |
PublicProfile = () => {
const { account } = useWeb3React()
const { profile } = useProfile()
const [usernameVisibilityToggled, setUsernameVisibility] = useUserUsernameVisibility()
const { t } = useTranslation()
if (!account) {
return <WalletNotConnected />
}
const toggleUsernameVisibility = () => {
setUsernameVisibility(!usernameVisibilityToggled)
}
const { username, team, isActive, points } = profile
const Icon = usernameVisibilityToggled ? VisibilityOff : VisibilityOn
return (
<>
<Menu activeIndex={1} />
<div>
<Card>
<CardHeader>
<Flex alignItems={['start', null, 'center']} flexDirection={['column', null, 'row']}>
<EditProfileAvatar profile={profile} />
<Content>
<Flex alignItems="center">
<Username>@{usernameVisibilityToggled ? username : username.replace(/./g, '*')}</Username>
<Icon ml="4px" onClick={toggleUsernameVisibility} cursor="pointer" />
</Flex>
<Flex alignItems="center">
<AddressLink href={getExplorerLink(account, 'address')} color="text" external>
{account}
<OpenNewIcon ml="4px" />
</AddressLink>
</Flex>
<ResponsiveText bold>{team.name}</ResponsiveText>
</Content>
</Flex>
<Status>
{isActive ? (
<Tag startIcon={<CheckmarkCircleIcon width="18px" />} outline>
{t('Active')}
</Tag>
) : (
<Tag variant="failure" startIcon={<BlockIcon width="18px" />} outline>
{t('Paused')}
</Tag>
)}
</Status>
</CardHeader>
<CardBody>
<StatBox icon={PrizeIcon} title={points} subtitle={t('Points')} mb="24px" />
<Section>
<Heading as="h4" scale="md" mb="16px">
{t('Achievements')}
</Heading>
<AchievementsList />
</Section>
<Collectibles />
</CardBody>
</Card>
</div>
</>
)
}
Example #13
Source File: BetDetails.tsx From vvs-ui with GNU General Public License v3.0 | 5 votes |
BetDetails: React.FC<BetDetailsProps> = ({ bet, result }) => {
const { t } = useTranslation()
const { totalAmount, bullAmount, bearAmount } = bet.round
const bullMultiplier = getMultiplier(totalAmount, bullAmount)
const bearMultiplier = getMultiplier(totalAmount, bearAmount)
return (
<StyledBetDetails>
{result === Result.CANCELED && (
<Text as="p" color="failure" mb="24px">
{t(
'This round was automatically canceled due to an error. If you entered a position, please reclaim your funds below.',
)}
</Text>
)}
{result !== Result.LIVE && <BetResult bet={bet} result={result} />}
<Heading mb="8px">{t('Round History')}</Heading>
<RoundResultHistory round={bet.round} mb="24px">
<PayoutRow positionLabel={t('Up')} multiplier={bullMultiplier} amount={bullAmount} />
<PayoutRow positionLabel={t('Down')} multiplier={bearMultiplier} amount={bearAmount} />
</RoundResultHistory>
{bet.round.lockBlock && (
<Flex alignItems="center" justifyContent="space-between" mb="8px">
<Text>{t('Opening Block')}</Text>
<Link href={getExplorerLink(bet.round.lockBlock, 'block')} external>
{bet.round.lockBlock}
</Link>
</Flex>
)}
{bet.round.closeBlock && (
<Flex alignItems="center" justifyContent="space-between">
<Text>{t('Closing Block')}</Text>
<Link href={getExplorerLink(bet.round.closeBlock, 'block')} external>
{bet.round.closeBlock}
</Link>
</Flex>
)}
</StyledBetDetails>
)
}
Example #14
Source File: WalletInfo.tsx From vvs-ui with GNU General Public License v3.0 | 5 votes |
WalletInfo: React.FC<WalletInfoProps> = ({ hasLowCROBalance, onDismiss }) => {
const { t } = useTranslation()
const { account } = useWeb3React()
const { balance, fetchStatus } = useGetCroBalance()
const { balance: vvsBalance, fetchStatus: vvsFetchStatus } = useTokenBalance(tokens.vvs.address)
const { logout } = useAuth()
const handleLogout = () => {
onDismiss()
logout()
}
return (
<>
<Text color="textSubtle" fontSize="12px" textTransform="uppercase" fontWeight="bold" mb="8px">
{t('Your Address')}
</Text>
<CopyAddress account={account} mb="24px" />
{hasLowCROBalance && (
<Message variant="warning" mb="24px" icon={false}>
<Box>
<Text fontWeight="bold">{t('CRO Balance Low')}</Text>
<Text as="p">{t('You need CRO for transaction fees.')}</Text>
</Box>
</Message>
)}
<Flex alignItems="center" justifyContent="space-between" style={balanceRowStyles}>
<Text color="textSubtle">{t('CRO Balance')}</Text>
{fetchStatus !== FetchStatus.SUCCESS ? (
<Skeleton height="22px" width="60px" />
) : (
<Text>{formatBigNumber(balance, 6)}</Text>
)}
</Flex>
<Flex alignItems="center" justifyContent="space-between" mb="24px" style={balanceRowStyles}>
<Text color="textSubtle">{t('VVS Balance')}</Text>
{vvsFetchStatus !== FetchStatus.SUCCESS ? (
<Skeleton height="22px" width="60px" />
) : (
<Text>{getFullDisplayBalance(vvsBalance, 18, 3)}</Text>
)}
</Flex>
<Flex alignItems="center" justifyContent="start" mb="24px">
<LinkExternal color="blue" href={getExplorerLink(account, 'address')}>
<Text fontSize="13px">{t('View on Cronos Explorer')}</Text>
</LinkExternal>
</Flex>
<Button variant="primary" height="60px" width="100%" onClick={handleLogout}>
{t('Disconnect Wallet')}
</Button>
</>
)
}
Example #15
Source File: RankingCard.tsx From vvs-ui with GNU General Public License v3.0 | 5 votes |
RankingCard: React.FC<RankingCardProps> = ({ rank, user }) => {
const { t } = useTranslation()
const rankColor = getRankingColor(rank)
const profileAvatar = useGetProfileAvatar(user.id)
const [onPresentWalletStatsModal] = useModal(<WalletStatsModal account={user.id} />)
return (
<Card ribbon={<CardRibbon variantColor={rankColor} text={`#${rank}`} ribbonPosition="left" />}>
<CardBody p="24px">
<Flex alignItems="center" justifyContent="center" flexDirection="column" mb="24px">
<SubMenu
component={
<>
<Flex mb="4px">
<RotatedLaurelLeftIcon color={rankColor} width="32px" />
<Box width={['40px', null, null, '64px']} height={['40px', null, null, '64px']}>
<ProfileAvatar src={`/images/nfts/${profileAvatar.nft?.images?.md}`} height={64} width={64} />
</Box>
<RotatedLaurelRightIcon color={rankColor} width="32px" />
</Flex>
<Text color="primary" fontWeight="bold" textAlign="center">
{profileAvatar.username || truncateHash(user.id)}
</Text>
</>
}
options={{ placement: 'bottom' }}
>
<SubMenuItem onClick={onPresentWalletStatsModal}>{t('View Stats')}</SubMenuItem>
<SubMenuItem as={Link} href={getExplorerLink(user.id, 'address')} bold={false} color="text" external>
{t('View on Cronos Explorer')}
</SubMenuItem>
</SubMenu>
</Flex>
<Row mb="4px">
<Text fontSize="12px" color="textSubtle">
{t('Win Rate')}
</Text>
<Text fontWeight="bold">
{`${user.winRate.toLocaleString(undefined, { minimumFractionDigits: 0, maximumFractionDigits: 2 })}%`}
</Text>
</Row>
<NetWinningsRow amount={user.netCRO} />
<Row>
<Text fontSize="12px" color="textSubtle">
{t('Rounds Won')}
</Text>
<Text fontWeight="bold">{`${user.totalBetsClaimed.toLocaleString()}/${user.totalBets.toLocaleString()}`}</Text>
</Row>
</CardBody>
</Card>
)
}
Example #16
Source File: EndsInCell.tsx From vvs-ui with GNU General Public License v3.0 | 5 votes |
EndsInCell: React.FC<FinishCellProps> = ({ pool }) => {
const { sousId, totalStaked, startBlock, endBlock, isFinished } = pool
const { currentBlock } = useBlock()
const { t } = useTranslation()
const { shouldShowBlockCountdown, blocksUntilStart, blocksRemaining, hasPoolStarted, blocksToDisplay } =
getPoolBlockInfo(pool, currentBlock)
const isVvsPool = sousId === 0
const renderBlocks = shouldShowBlockCountdown ? (
<Flex alignItems="center">
<Flex flex="1.3">
<Balance fontSize="16px" value={blocksToDisplay} decimals={0} />
<Text ml="4px" textTransform="lowercase">
{t('Blocks')}
</Text>
</Flex>
<Flex flex="1">
<Link
external
href={getExplorerLink(hasPoolStarted ? endBlock : startBlock, 'countdown')}
onClick={(e) => e.stopPropagation()}
>
<TimerIcon ml="4px" />
</Link>
</Flex>
</Flex>
) : (
<Text>-</Text>
)
// A bit hacky way to determine if public data is loading relying on totalStaked
// Opted to go for this since we don't really need a separate publicDataLoaded flag
// anywhere else
const isLoadingPublicData = !totalStaked.gt(0) || !currentBlock || (!blocksRemaining && !blocksUntilStart)
const showLoading = isLoadingPublicData && !isVvsPool && !isFinished
return (
<StyledCell role="cell">
<CellContent>
<Text fontSize="12px" color="textSubtle" textAlign="left">
{hasPoolStarted || !shouldShowBlockCountdown ? t('Ends in') : t('Starts in')}
</Text>
{showLoading ? <Skeleton width="80px" height="16px" /> : renderBlocks}
</CellContent>
</StyledCell>
)
}
Example #17
Source File: Achievement.tsx From vvs-ui with GNU General Public License v3.0 | 5 votes |
Achievement: React.FC<Props> = ({ ifo, publicIfoData }) => {
const { t } = useTranslation()
const tokenName = ifo.token.symbol?.toLowerCase()
const campaignTitle = ifo.name
const minLpForAchievement = MIN_DOLLAR_FOR_ACHIEVEMENT.div(publicIfoData.currencyPriceInUSD).toNumber()
return (
<Container>
<AchievementFlex isFinished={publicIfoData.status === 'finished'} alignItems="center" flexGrow={1}>
<Image src={`/images/achievements/ifo-${tokenName}.svg`} width={56} height={56} mr="8px" />
<Flex flexDirection="column">
<Text color="secondary" fontSize="12px">
{`${t('Achievement')}:`}
</Text>
<Flex>
<Text bold mr="8px">
{t('IFO Shopper: %title%', { title: campaignTitle })}
</Text>
<Flex alignItems="center" mr="8px">
<PrizeIcon color="textSubtle" width="16px" mr="4px" />
<Text color="textSubtle">{publicIfoData.numberPoints}</Text>
</Flex>
</Flex>
{publicIfoData.currencyPriceInUSD.gt(0) ? (
<Text color="textSubtle" fontSize="12px">
{t('Commit ~%amount% LP in total to earn!', { amount: minLpForAchievement.toFixed(3) })}
</Text>
) : (
<Skeleton minHeight={18} width={80} />
)}
</Flex>
</AchievementFlex>
<Flex alignItems="flex-end" flexDirection="column">
<StyledLinkExternal href={ifo.articleUrl} mb="8px">
{t('Learn more about %title%', { title: campaignTitle })}
</StyledLinkExternal>
<StyledLinkExternal href={getExplorerLink(ifo.address, 'address')}>{t('View Contract')}</StyledLinkExternal>
</Flex>
</Container>
)
}
Example #18
Source File: ActionPanel.tsx From vvs-ui with GNU General Public License v3.0 | 5 votes |
ActionPanel: React.FunctionComponent<ActionPanelProps> = ({
details,
apr,
allocation,
multiplier,
liquidity,
userDataReady,
expanded,
}) => {
const farm = details
const { t } = useTranslation()
const isActive = farm.multiplier !== '0X'
const { quoteToken, token, dual } = farm
// const lpLabel = farm.lpSymbol && farm.lpSymbol.toUpperCase().replace('VVS', '') // FIXME replace ??
const lpLabel = farm.lpSymbol && farm.lpSymbol.toUpperCase()
const liquidityUrlPathParts = getLiquidityUrlPathParts({
quoteTokenAddress: quoteToken.address,
tokenAddress: token.address,
})
const lpAddress = getAddress(farm.lpAddresses)
const bsc = getExplorerLink(lpAddress, 'address')
const info = `/info/farm/${lpAddress}`
return (
<Container expanded={expanded} background="#F4F5F1">
<InfoContainer>
{isActive && (
<StakeContainer>
<StyledLinkExternal color="blue" href={`/add/${liquidityUrlPathParts}`}>
{t('Get %symbol%', { symbol: lpLabel })}
</StyledLinkExternal>
</StakeContainer>
)}
<StyledLinkExternal color="blue" href={bsc}>
{t('View Contract')}
</StyledLinkExternal>
{!isBlindMode() && <StyledLinkExternal color="blue" href={info}>
{t('See Pair Info')}
</StyledLinkExternal>}
{/* <TagsContainer>
{farm.isCommunity ? <CommunityTag /> : <CoreTag />}
{dual ? <DualTag /> : null}
</TagsContainer> */}
</InfoContainer>
<ValueContainer>
{isBlindMode() ? (
<ValueWrapper>
<Text color="textSubtle">{t('VVS Allocation')}</Text>
<VvsAllocation {...allocation} />
</ValueWrapper>
) : (<ValueWrapper>
<Text color="textSubtle">{t('APR')}</Text>
<Apr {...apr} />
</ValueWrapper>)}
<ValueWrapper>
<Text color="textSubtle">{t('Multiplier')}</Text>
<Multiplier {...multiplier} />
</ValueWrapper>
<ValueWrapper>
<Text color="textSubtle">{t('Liquidity')}</Text>
<Liquidity {...liquidity} />
</ValueWrapper>
</ValueContainer>
<ActionContainer>
<HarvestAction {...farm} userDataReady={userDataReady} />
<StakedAction {...farm} userDataReady={userDataReady} lpLabel={lpLabel} displayApr={apr?.value} />
</ActionContainer>
</Container>
)
}
Example #19
Source File: AuctionLeaderboardTable.tsx From vvs-ui with GNU General Public License v3.0 | 5 votes |
LeaderboardRow: React.FC<LeaderboardRowProps> = ({ bidder, vvsPriceUsdc, isMobile }) => {
const { t } = useTranslation()
const { isTopPosition, position, samePositionAsAbove, farmName, tokenName, amount, projectSite, lpAddress, account } =
bidder
return (
<>
<GridCell isTopPosition={isTopPosition} pl={['12px', '24px']}>
<Flex>
<Text bold={isTopPosition} color={samePositionAsAbove ? 'textDisabled' : 'text'} textTransform="uppercase">
#{position}
</Text>
</Flex>
</GridCell>
<GridCell isTopPosition={isTopPosition}>
<Flex flexDirection="column" pl={['8px']}>
<Flex>
<Text bold={isTopPosition} mr="4px">
{farmName}
</Text>
{!isMobile && <Text>(1x)</Text>}
</Flex>
<Text fontSize="12px" color="textSubtle">
{tokenName}
</Text>
</Flex>
</GridCell>
<GridCell isTopPosition={isTopPosition}>
<Flex flexDirection="column" width="100%" justifyContent="flex-end" pr={[null, null, '24px']}>
<Text bold textTransform="uppercase" width="100%" textAlign="right">
{getBalanceNumber(amount).toLocaleString()}
</Text>
{vvsPriceUsdc.gt(0) ? (
<Text fontSize="12px" color="textSubtle" textAlign="right">
~${getBalanceNumber(amount.times(vvsPriceUsdc)).toLocaleString('en', { maximumFractionDigits: 0 })}
</Text>
) : (
<Flex justifyContent="flex-end">
<Skeleton width="48px" />
</Flex>
)}
</Flex>
</GridCell>
<GridCell isTopPosition={isTopPosition}>
<SubMenu component={<EllipsisIcon height="16px" width="16px" />}>
{projectSite && (
<SubMenuItem as={LinkExternal} href={projectSite} bold={false} color="text">
{t('Project Site')}
</SubMenuItem>
)}
{lpAddress && (
<SubMenuItem as={LinkExternal} href={`/info/farm/${lpAddress}`} bold={false} color="text">
{t('LP Info')}
</SubMenuItem>
)}
{account && (
<SubMenuItem as={LinkExternal} href={getExplorerLink(account, 'address')} bold={false} color="text">
{t('Bidder Address')}
</SubMenuItem>
)}
</SubMenu>
</GridCell>
</>
)
}
Example #20
Source File: updater.tsx From vvs-ui with GNU General Public License v3.0 | 5 votes |
export default function Updater(): null {
const { library, chainId } = useActiveWeb3React()
const { currentBlock } = useBlock()
const dispatch = useDispatch<AppDispatch>()
const state = useSelector<AppState, AppState['transactions']>((s) => s.transactions)
const transactions = useMemo(() => (chainId ? state[chainId] ?? {} : {}), [chainId, state])
const { toastError, toastSuccess } = useToast()
useEffect(() => {
if (!chainId || !library || !currentBlock) return
Object.keys(transactions)
.filter((hash) => shouldCheck(currentBlock, transactions[hash]))
.forEach((hash) => {
library
.getTransactionReceipt(hash)
.then((receipt) => {
if (receipt) {
dispatch(
finalizeTransaction({
chainId,
hash,
receipt: {
blockHash: receipt.blockHash,
blockNumber: receipt.blockNumber,
contractAddress: receipt.contractAddress,
from: receipt.from,
status: receipt.status,
to: receipt.to,
transactionHash: receipt.transactionHash,
transactionIndex: receipt.transactionIndex,
},
}),
)
const toast = receipt.status === 1 ? toastSuccess : toastError
toast(
'Transaction receipt',
<Flex flexDirection="column">
<Text color="darkGrey" fontWeight="400" fontSize="13px">
{transactions[hash]?.summary ?? `Hash: ${hash.slice(0, 8)}...${hash.slice(58, 65)}`}
</Text>
{chainId && (
<Link external href={getExplorerLink(hash, 'transaction', chainId)}>
<Text fontSize="13px" fontWeight="400" color="darkBlue">
View on Cronos Explorer
</Text>
</Link>
)}
</Flex>,
)
} else {
dispatch(checkedTransaction({ chainId, hash, blockNumber: currentBlock }))
}
})
.catch((error) => {
console.error(`failed to check transaction hash: ${hash}`, error)
})
})
}, [chainId, library, transactions, currentBlock, dispatch, toastSuccess, toastError])
return null
}
Example #21
Source File: ImportToken.tsx From vvs-ui with GNU General Public License v3.0 | 4 votes |
function ImportToken({ tokens, handleCurrencySelect }: ImportProps) {
const { chainId } = useActiveWeb3React()
const { t } = useTranslation()
const [confirmed, setConfirmed] = useState(false)
const addToken = useAddUserToken()
// use for showing import source on inactive tokens
const inactiveTokenList = useCombinedInactiveList()
return (
<AutoColumn gap="lg">
<Message variant="warning">
<Text>
{t(
'Warning: Anyone can create a CRC20 token on Cronos with any name. Such is the beauty of decentralization. However, beware that anyone can create fake versions of existing tokens or claim to represent projects they do not. So always check the official links and perform your research.',
)}
<br />
<br />
{t('If you purchase any arbitrary token, you may be unable to sell it back. Purchase knowing the risks.')}
</Text>
</Message>
{tokens.map((token) => {
const list = chainId && inactiveTokenList?.[chainId]?.[token.address]?.list
const address = token.address ? `${truncateHash(token.address)}` : null
return (
<Grid key={token.address} gridTemplateRows="1fr 1fr 1fr" gridGap="4px">
{list !== undefined ? (
<Tag
variant="success"
outline
scale="sm"
startIcon={list.logoURI && <ListLogo logoURI={list.logoURI} size="12px" />}
>
{t('via')} {list.name}
</Tag>
) : (
<Tag variant="failure" outline scale="sm" startIcon={<ErrorIcon color="failure" />}>
{t('Unknown Source')}
</Tag>
)}
<Flex alignItems="center">
<Text mr="8px">{token.name}</Text>
<Text>({token.symbol})</Text>
</Flex>
{chainId && (
<Flex justifyContent="space-between" width="100%">
<Text mr="4px">{address}</Text>
<Link href={getExplorerLink(token.address, 'address', chainId)} external>
({t('View on Cronos Explorer')})
</Link>
</Flex>
)}
</Grid>
)
})}
<Flex justifyContent="space-between" alignItems="center">
<Flex alignItems="center" onClick={() => setConfirmed(!confirmed)}>
<Checkbox
scale="sm"
name="confirmed"
type="checkbox"
checked={confirmed}
onChange={() => setConfirmed(!confirmed)}
/>
<Text ml="8px" style={{ userSelect: 'none' }}>
{t('I understand')}
</Text>
</Flex>
<Button
variant="danger"
disabled={!confirmed}
onClick={() => {
tokens.map((token) => addToken(token))
if (handleCurrencySelect) {
handleCurrencySelect(tokens[0])
}
}}
className=".token-dismiss-button"
>
{t('Import')}
</Button>
</Flex>
</AutoColumn>
)
}
Example #22
Source File: ExpandedFooter.tsx From vvs-ui with GNU General Public License v3.0 | 4 votes |
ExpandedFooter: React.FC<ExpandedFooterProps> = ({ pool, account }) => {
const { t } = useTranslation()
const { chainId } = useActiveWeb3React()
const { currentBlock } = useBlock()
const {
totalVvsInVault,
fees: { performanceFee },
} = useVvsVault()
const {
stakingToken,
earningToken,
totalStaked,
startBlock,
endBlock,
stakingLimit,
contractAddress,
sousId,
isAutoVault,
} = pool
const tokenAddress = earningToken.address || ''
const poolContractAddress = getAddress(contractAddress)
const vvsVaultContractAddress = getVvsVaultAddress()
const isMetaMaskInScope = !!window.ethereum?.isMetaMask
const isManualVvsPool = sousId === 0
const { shouldShowBlockCountdown, blocksUntilStart, blocksRemaining, hasPoolStarted, blocksToDisplay } =
getPoolBlockInfo(pool, currentBlock)
const { targetRef, tooltip, tooltipVisible } = useTooltip(
t('Subtracted automatically from each yield harvest and burned.'),
{ placement: 'bottom-start' },
)
const getTotalStakedBalance = () => {
if (isAutoVault) {
return getBalanceNumber(totalVvsInVault, stakingToken.decimals)
}
if (isManualVvsPool) {
const manualVvsTotalMinusAutoVault = new BigNumber(totalStaked).minus(totalVvsInVault)
return getBalanceNumber(manualVvsTotalMinusAutoVault, stakingToken.decimals)
}
return getBalanceNumber(totalStaked, stakingToken.decimals)
}
const {
targetRef: totalStakedTargetRef,
tooltip: totalStakedTooltip,
tooltipVisible: totalStakedTooltipVisible,
} = useTooltip(t('Total amount of %symbol% staked in this pool', { symbol: stakingToken.symbol }), {
placement: 'bottom',
})
return (
<ExpandedWrapper flexDirection="column">
<Flex mb="2px" justifyContent="space-between" alignItems="center">
<Text small>{t('Total staked')}:</Text>
<Flex alignItems="flex-start">
{totalStaked && totalStaked.gte(0) ? (
<>
<Balance small value={getTotalStakedBalance()} decimals={0} unit={` ${stakingToken.symbol}`} />
<span ref={totalStakedTargetRef}>
<HelpIcon color="textSubtle" width="20px" ml="6px" mt="4px" />
</span>
</>
) : (
<Skeleton width="90px" height="21px" />
)}
{totalStakedTooltipVisible && totalStakedTooltip}
</Flex>
</Flex>
{stakingLimit && stakingLimit.gt(0) && (
<Flex mb="2px" justifyContent="space-between">
<Text small>{t('Max. stake per user')}:</Text>
<Text small>{`${getFullDisplayBalance(stakingLimit, stakingToken.decimals, 0)} ${stakingToken.symbol}`}</Text>
</Flex>
)}
{shouldShowBlockCountdown && (
<Flex mb="2px" justifyContent="space-between" alignItems="center">
<Text small>{hasPoolStarted ? t('Ends in') : t('Starts in')}:</Text>
{blocksRemaining || blocksUntilStart ? (
<Flex alignItems="center">
<Link external href={getExplorerLink(hasPoolStarted ? endBlock : startBlock, 'countdown')}>
<Balance small value={blocksToDisplay} decimals={0} color="primary" />
<Text small ml="4px" color="primary" textTransform="lowercase">
{t('Blocks')}
</Text>
<TimerIcon ml="4px" color="primary" />
</Link>
</Flex>
) : (
<Skeleton width="54px" height="21px" />
)}
</Flex>
)}
{isAutoVault && (
<Flex mb="2px" justifyContent="space-between" alignItems="center">
{tooltipVisible && tooltip}
<TooltipText ref={targetRef} small>
{t('Performance Fee')}
</TooltipText>
<Flex alignItems="center">
{performanceFee ? (
<Text ml="4px" small>
{performanceFee / 100}%
</Text>
) : (
<Skeleton width="90px" height="21px" />
)}
</Flex>
</Flex>
)}
{!isBlindMode() && <Flex mb="2px" justifyContent="flex-end">
<LinkExternal href={`/info/token/${earningToken.address}`} bold={false} small>
{t('See Token Info')}
</LinkExternal>
</Flex>}
<Flex mb="2px" justifyContent="flex-end">
<LinkExternal href={earningToken.projectLink} bold={false} small>
{t('View Project Site')}
</LinkExternal>
</Flex>
{poolContractAddress && (
<Flex mb="2px" justifyContent="flex-end">
<LinkExternal
href={`${BASE_EXPLORER_URLS[chainId]}/address/${isAutoVault ? vvsVaultContractAddress : poolContractAddress}`}
bold={false}
small
>
{t('View Contract')}
</LinkExternal>
</Flex>
)}
{account && isMetaMaskInScope && tokenAddress && (
<Flex justifyContent="flex-end">
<Button
variant="text"
p="0"
height="auto"
onClick={() => registerToken(tokenAddress, earningToken.symbol, earningToken.decimals)}
>
<Text color="primary" fontSize="14px">
{t('Add to Metamask')}
</Text>
<MetamaskIcon ml="4px" />
</Button>
</Flex>
)}
</ExpandedWrapper>
)
}
Example #23
Source File: ActionPanel.tsx From vvs-ui with GNU General Public License v3.0 | 4 votes |
ActionPanel: React.FC<ActionPanelProps> = ({ account, pool, userDataLoaded, expanded, breakpoints }) => {
const {
sousId,
stakingToken,
earningToken,
totalStaked,
startBlock,
endBlock,
stakingLimit,
contractAddress,
userData,
isAutoVault,
} = pool
const { t } = useTranslation()
const { chainId } = useActiveWeb3React()
const poolContractAddress = getAddress(contractAddress)
const vvsVaultContractAddress = getVvsVaultAddress()
const { currentBlock } = useBlock()
const { isXs, isSm, isMd } = breakpoints
const showSubtitle = (isXs || isSm) && sousId === 0
const { shouldShowBlockCountdown, blocksUntilStart, blocksRemaining, hasPoolStarted, blocksToDisplay } =
getPoolBlockInfo(pool, currentBlock)
const isMetaMaskInScope = !!window.ethereum?.isMetaMask
const tokenAddress = earningToken.address || ''
const {
totalVvsInVault,
userData: { userShares },
fees: { performanceFee },
pricePerFullShare,
} = useVvsVault()
const stakingTokenBalance = userData?.stakingTokenBalance ? new BigNumber(userData.stakingTokenBalance) : BIG_ZERO
const stakedBalance = userData?.stakedBalance ? new BigNumber(userData.stakedBalance) : BIG_ZERO
const { vvsAsBigNumber } = convertSharesToVvs(userShares, pricePerFullShare)
const poolStakingTokenBalance = isAutoVault
? vvsAsBigNumber.plus(stakingTokenBalance)
: stakedBalance.plus(stakingTokenBalance)
const performanceFeeAsDecimal = performanceFee && performanceFee / 100
const isManualVvsPool = sousId === 0
const getTotalStakedBalance = () => {
if (isAutoVault) {
return getBalanceNumber(totalVvsInVault, stakingToken.decimals)
}
if (isManualVvsPool) {
const manualVvsTotalMinusAutoVault = new BigNumber(totalStaked).minus(totalVvsInVault)
return getBalanceNumber(manualVvsTotalMinusAutoVault, stakingToken.decimals)
}
return getBalanceNumber(totalStaked, stakingToken.decimals)
}
const {
targetRef: totalStakedTargetRef,
tooltip: totalStakedTooltip,
tooltipVisible: totalStakedTooltipVisible,
} = useTooltip(t('Total amount of %symbol% staked in this pool', { symbol: stakingToken.symbol }), {
placement: 'bottom',
})
const manualTooltipText = t('You must harvest and compound your earnings from this pool manually.')
const autoTooltipText = t(
'Any funds you stake in this pool will be automagically harvested and restaked (compounded) for you.',
)
const {
targetRef: tagTargetRef,
tooltip: tagTooltip,
tooltipVisible: tagTooltipVisible,
} = useTooltip(isAutoVault ? autoTooltipText : manualTooltipText, {
placement: 'bottom-start',
})
const maxStakeRow = stakingLimit.gt(0) ? (
<Flex mb="8px" justifyContent="space-between">
<Text>{t('Max. stake per user')}:</Text>
<Text>{`${getFullDisplayBalance(stakingLimit, stakingToken.decimals, 0)} ${stakingToken.symbol}`}</Text>
</Flex>
) : null
const blocksRow =
blocksRemaining || blocksUntilStart ? (
<Flex mb="8px" justifyContent="space-between">
<Text>{hasPoolStarted ? t('Ends in') : t('Starts in')}:</Text>
<Flex>
<Link external href={getExplorerLink(hasPoolStarted ? endBlock : startBlock, 'countdown')}>
<Balance fontSize="16px" value={blocksToDisplay} decimals={0} color="primary" />
<Text ml="4px" color="primary" textTransform="lowercase">
{t('Blocks')}
</Text>
<TimerIcon ml="4px" color="primary" />
</Link>
</Flex>
</Flex>
) : (
<Skeleton width="56px" height="16px" />
)
const aprRow = (
<Flex justifyContent="space-between" alignItems="center" mb="8px">
<Text>{isAutoVault ? t('APY') : t('APR')}:</Text>
<Apr
pool={pool}
showIcon
stakedBalance={poolStakingTokenBalance}
performanceFee={isAutoVault ? performanceFeeAsDecimal : 0}
/>
</Flex>
)
const totalStakedRow = (
<Flex justifyContent="space-between" alignItems="center" mb="8px">
<Text maxWidth={['50px', '100%']}>{t('Total staked')}:</Text>
<Flex alignItems="center">
{totalStaked && totalStaked.gte(0) ? (
<>
<Balance fontSize="16px" value={getTotalStakedBalance()} decimals={0} unit={` ${stakingToken.symbol}`} />
<span ref={totalStakedTargetRef}>
<HelpIcon color="textSubtle" width="20px" ml="4px" />
</span>
</>
) : (
<Skeleton width="56px" height="16px" />
)}
{totalStakedTooltipVisible && totalStakedTooltip}
</Flex>
</Flex>
)
return (
<StyledActionPanel expanded={expanded}>
<InfoSection>
{maxStakeRow}
{(isXs || isSm) && aprRow}
{(isXs || isSm || isMd) && totalStakedRow}
{shouldShowBlockCountdown && blocksRow}
{!isBlindMode() && <Flex mb="8px" justifyContent={['flex-end', 'flex-end', 'flex-start']}>
<LinkExternal href={`/info/token/${earningToken.address}`} bold={false}>
{t('See Token Info')}
</LinkExternal>
</Flex>}
<Flex mb="8px" justifyContent={['flex-end', 'flex-end', 'flex-start']}>
<LinkExternal href={earningToken.projectLink} bold={false}>
{t('View Project Site')}
</LinkExternal>
</Flex>
{poolContractAddress && (
<Flex mb="8px" justifyContent={['flex-end', 'flex-end', 'flex-start']}>
<LinkExternal
href={`${BASE_EXPLORER_URLS[chainId]}/address/${isAutoVault ? vvsVaultContractAddress : poolContractAddress}`}
bold={false}
>
{t('View Contract')}
</LinkExternal>
</Flex>
)}
{account && isMetaMaskInScope && tokenAddress && (
<Flex mb="8px" justifyContent={['flex-end', 'flex-end', 'flex-start']}>
<Button
variant="text"
p="0"
height="auto"
onClick={() => registerToken(tokenAddress, earningToken.symbol, earningToken.decimals)}
>
<Text color="primary">{t('Add to Metamask')}</Text>
<MetamaskIcon ml="4px" />
</Button>
</Flex>
)}
{isAutoVault ? <CompoundingPoolTag /> : <ManualPoolTag />}
{tagTooltipVisible && tagTooltip}
<span ref={tagTargetRef}>
<HelpIcon ml="4px" width="20px" height="20px" color="textSubtle" />
</span>
</InfoSection>
<ActionContainer>
{showSubtitle && (
<Text mt="4px" mb="16px" color="textSubtle">
{isAutoVault ? t('Automatic restaking') : `${t('Earn')} VVS ${t('Stake').toLocaleLowerCase()} VVS`}
</Text>
)}
{pool.isAutoVault ? (
<AutoHarvest {...pool} userDataLoaded={userDataLoaded} />
) : (
<Harvest {...pool} userDataLoaded={userDataLoaded} />
)}
<Stake pool={pool} userDataLoaded={userDataLoaded} />
</ActionContainer>
</StyledActionPanel>
)
}
Example #24
Source File: TokenPage.tsx From vvs-ui with GNU General Public License v3.0 | 4 votes |
TokenPage: React.FC<RouteComponentProps<{ address: string }>> = ({
match: {
params: { address: routeAddress },
},
}) => {
const { isXs, isSm } = useMatchBreakpoints()
const { t } = useTranslation()
// Needed to scroll up if user comes to this page by clicking on entry in the table
useEffect(() => {
window.scrollTo(0, 0)
}, [])
// In case somebody pastes checksummed address into url (since GraphQL expects lowercase address)
const address = routeAddress.toLowerCase()
const cmcLink = useCMCLink(address)
const tokenData = useTokenData(address)
const poolsForToken = usePoolsForToken(address)
const poolDatas = usePoolDatas(poolsForToken ?? [])
const transactions = useTokenTransactions(address)
const chartData = useTokenChartData(address)
// pricing data
const priceData = useTokenPriceData(address, ONE_HOUR_SECONDS, DEFAULT_TIME_WINDOW)
const adjustedPriceData = useMemo(() => {
// Include latest available price
if (priceData && tokenData && priceData.length > 0) {
return [
...priceData,
{
time: new Date().getTime() / 1000,
open: priceData[priceData.length - 1].close,
close: tokenData?.priceUSD,
high: tokenData?.priceUSD,
low: priceData[priceData.length - 1].close,
},
]
}
return undefined
}, [priceData, tokenData])
const [watchlistTokens, addWatchlistToken] = useWatchlistTokens()
return (
<Page symbol={tokenData?.symbol}>
{tokenData ? (
!tokenData.exists ? (
<Card>
<Box p="16px">
<Text>
{t('No pool has been created with this token yet. Create one')}
<Link style={{ display: 'inline', marginLeft: '6px' }} to={`/add/${address}`}>
{t('here.')}
</Link>
</Text>
</Box>
</Card>
) : (
<>
{/* Stuff on top */}
<Flex justifyContent="space-between" mb="24px" flexDirection={['column', 'column', 'row']}>
<Breadcrumbs mb="32px">
<Link to="/info">
<Text color="primary">{t('Info')}</Text>
</Link>
<Link to="/info/tokens">
<Text color="primary">{t('Tokens')}</Text>
</Link>
<Flex>
<Text mr="8px">{tokenData.symbol}</Text>
<Text>{`(${truncateHash(address)})`}</Text>
</Flex>
</Breadcrumbs>
<Flex justifyContent={[null, null, 'flex-end']} mt={['8px', '8px', 0]}>
<LinkExternal mr="8px" color="primary" href={getExplorerLink(address, 'address')}>
{t('View on Cronos Explorer')}
</LinkExternal>
{cmcLink && (
<StyledCMCLink href={cmcLink} rel="noopener noreferrer nofollow" target="_blank">
<Image src="/images/CMC-logo.svg" height={22} width={22} alt={t('View token on CoinMarketCap')} />
</StyledCMCLink>
)}
<SaveIcon fill={watchlistTokens.includes(address)} onClick={() => addWatchlistToken(address)} />
</Flex>
</Flex>
<Flex justifyContent="space-between" flexDirection={['column', 'column', 'column', 'row']}>
<Flex flexDirection="column" mb={['8px', null]}>
<Flex alignItems="center">
<CurrencyLogo size="32px" address={address} />
<Text
ml="12px"
bold
lineHeight="0.7"
fontSize={isXs || isSm ? '24px' : '40px'}
id="info-token-name-title"
>
{tokenData.name}
</Text>
<Text ml="12px" lineHeight="1" color="textSubtle" fontSize={isXs || isSm ? '14px' : '20px'}>
({tokenData.symbol})
</Text>
</Flex>
<Flex mt="8px" ml="46px" alignItems="center">
<Text mr="16px" bold fontSize="24px">
${formatAmount(tokenData.priceUSD, { notation: 'standard' })}
</Text>
<Percent value={tokenData.priceUSDChange} fontWeight={600} />
</Flex>
</Flex>
<Flex>
<Link to={`/add/${address}`}>
<Button mr="8px" variant="secondary">
{t('Add Liquidity')}
</Button>
</Link>
<Link to={`/swap?inputCurrency=${address}`}>
<Button>{t('Trade')}</Button>
</Link>
</Flex>
</Flex>
{/* data on the right side of chart */}
<ContentLayout>
<Card>
<Box p="24px">
<Text bold small color="secondary" fontSize="12px" textTransform="uppercase">
{t('Liquidity')}
</Text>
<Text bold fontSize="24px">
${formatAmount(tokenData.liquidityUSD)}
</Text>
<Percent value={tokenData.liquidityUSDChange} />
<Text mt="24px" bold color="secondary" fontSize="12px" textTransform="uppercase">
{t('Volume 24H')}
</Text>
<Text bold fontSize="24px" textTransform="uppercase">
${formatAmount(tokenData.volumeUSD)}
</Text>
<Percent value={tokenData.volumeUSDChange} />
<Text mt="24px" bold color="secondary" fontSize="12px" textTransform="uppercase">
{t('Volume 7D')}
</Text>
<Text bold fontSize="24px">
${formatAmount(tokenData.volumeUSDWeek)}
</Text>
<Text mt="24px" bold color="secondary" fontSize="12px" textTransform="uppercase">
{t('Transactions 24H')}
</Text>
<Text bold fontSize="24px">
{formatAmount(tokenData.txCount, { isInteger: true })}
</Text>
</Box>
</Card>
{/* charts card */}
<ChartCard
variant="token"
chartData={chartData}
tokenData={tokenData}
tokenPriceData={adjustedPriceData}
/>
</ContentLayout>
{/* pools and transaction tables */}
<Heading scale="lg" mb="16px" mt="40px">
Farms
</Heading>
<PoolTable poolDatas={poolDatas} />
<Heading scale="lg" mb="16px" mt="40px">
{t('Transactions')}
</Heading>
<TransactionTable transactions={transactions} />
</>
)
) : (
<Flex mt="80px" justifyContent="center">
<Spinner />
</Flex>
)}
</Page>
)
}
Example #25
Source File: PoolPage.tsx From vvs-ui with GNU General Public License v3.0 | 4 votes |
PoolPage: React.FC<RouteComponentProps<{ address: string }>> = ({
match: {
params: { address: routeAddress },
},
}) => {
const { isXs, isSm } = useMatchBreakpoints()
const { t } = useTranslation()
const [showWeeklyData, setShowWeeklyData] = useState(0)
const { tooltip, tooltipVisible, targetRef } = useTooltip(
t(`Based on last 7 days' performance. Does not account for impermanent loss`),
{},
)
// Needed to scroll up if user comes to this page by clicking on entry in the table
useEffect(() => {
window.scrollTo(0, 0)
}, [])
// In case somebody pastes checksummed address into url (since GraphQL expects lowercase address)
const address = routeAddress.toLowerCase()
const poolData = usePoolDatas([address])[0]
const chartData = usePoolChartData(address)
const transactions = usePoolTransactions(address)
const [watchlistPools, addPoolToWatchlist] = useWatchlistPools()
return (
<Page symbol={poolData ? `${poolData?.token0.symbol} / ${poolData?.token1.symbol}` : null}>
{poolData ? (
<>
<Flex justifyContent="space-between" mb="16px" flexDirection={['column', 'column', 'row']}>
<Breadcrumbs mb="32px">
<Link to="/info">
<Text color="primary">{t('Info')}</Text>
</Link>
<Link to="/info/farms">
<Text color="primary">{t('Farms')}</Text>
</Link>
<Flex>
<Text mr="8px">{`${poolData.token0.symbol} / ${poolData.token1.symbol}`}</Text>
</Flex>
</Breadcrumbs>
<Flex justifyContent={[null, null, 'flex-end']} mt={['8px', '8px', 0]}>
<LinkExternal mr="8px" href={getExplorerLink(address, 'address')}>
{t('View on Cronos Explorer')}
</LinkExternal>
<SaveIcon fill={watchlistPools.includes(address)} onClick={() => addPoolToWatchlist(address)} />
</Flex>
</Flex>
<Flex flexDirection="column">
<Flex alignItems="center" mb={['8px', null]}>
<DoubleCurrencyLogo address0={poolData.token0.address} address1={poolData.token1.address} size={32} />
<Text
ml="38px"
bold
fontSize={isXs || isSm ? '24px' : '40px'}
id="info-pool-pair-title"
>{`${poolData.token0.symbol} / ${poolData.token1.symbol}`}</Text>
</Flex>
<Flex justifyContent="space-between" flexDirection={['column', 'column', 'column', 'row']}>
<Flex flexDirection={['column', 'column', 'row']} mb={['8px', '8px', null]}>
<Link to={`/info/token/${poolData.token0.address}`}>
<TokenButton>
<CurrencyLogo address={poolData.token0.address} size="24px" />
<Text fontSize="16px" ml="4px" style={{ whiteSpace: 'nowrap' }} width="fit-content">
{`1 ${poolData.token0.symbol} = ${poolData.token0Price.toFixed(7)} ${poolData.token1.symbol}`}
</Text>
</TokenButton>
</Link>
<Link to={`/info/token/${poolData.token1.address}`}>
<TokenButton ml={[null, null, '10px']}>
<CurrencyLogo address={poolData.token1.address} size="24px" />
<Text fontSize="16px" ml="4px" style={{ whiteSpace: 'nowrap' }} width="fit-content">
{`1 ${poolData.token1.symbol} = ${poolData.token1Price.toFixed(7)} ${poolData.token0.symbol}`}
</Text>
</TokenButton>
</Link>
</Flex>
<Flex>
<Link to={`/add/${poolData.token0.address}/${poolData.token1.address}`}>
<Button mr="8px" variant="secondary">
{t('Add Liquidity')}
</Button>
</Link>
<Link to={`/swap?inputCurrency=${poolData.token0.address}&outputCurrency=${poolData.token1.address}`}>
<Button>{t('Trade')}</Button>
</Link>
</Flex>
</Flex>
</Flex>
<ContentLayout>
<Box>
<Card>
<Box p="24px">
<Flex justifyContent="space-between">
<Flex flex="1" flexDirection="column">
<Text color="secondary" bold fontSize="12px" textTransform="uppercase">
{t('Liquidity')}
</Text>
<Text fontSize="24px" bold>
${formatAmount(poolData.liquidityUSD)}
</Text>
<Percent value={poolData.liquidityUSDChange} />
</Flex>
<Flex flex="1" flexDirection="column">
<Text color="secondary" bold fontSize="12px" textTransform="uppercase">
{t('LP reward APR')}
</Text>
<Text fontSize="24px" bold>
{formatAmount(poolData.lpApr7d)}%
</Text>
<Flex alignItems="center">
<span ref={targetRef}>
<HelpIcon color="textSubtle" />
</span>
<Text ml="4px" fontSize="12px" color="textSubtle">
{t('7D performance')}
</Text>
{tooltipVisible && tooltip}
</Flex>
</Flex>
</Flex>
<Text color="secondary" bold mt="24px" fontSize="12px" textTransform="uppercase">
{t('Total Tokens Locked')}
</Text>
<LockedTokensContainer>
<Flex justifyContent="space-between">
<Flex>
<CurrencyLogo address={poolData.token0.address} size="24px" />
<Text small color="textSubtle" ml="8px">
{poolData.token0.symbol}
</Text>
</Flex>
<Text small>{formatAmount(poolData.liquidityToken0)}</Text>
</Flex>
<Flex justifyContent="space-between">
<Flex>
<CurrencyLogo address={poolData.token1.address} size="24px" />
<Text small color="textSubtle" ml="8px">
{poolData.token1.symbol}
</Text>
</Flex>
<Text small>{formatAmount(poolData.liquidityToken1)}</Text>
</Flex>
</LockedTokensContainer>
</Box>
</Card>
<Card mt="16px">
<Flex flexDirection="column" p="24px">
<ButtonMenu
activeIndex={showWeeklyData}
onItemClick={(index) => setShowWeeklyData(index)}
scale="sm"
variant="subtle"
>
<ButtonMenuItem width="100%">{t('24H')}</ButtonMenuItem>
<ButtonMenuItem width="100%">{t('7D')}</ButtonMenuItem>
</ButtonMenu>
<Flex mt="24px">
<Flex flex="1" flexDirection="column">
<Text color="secondary" fontSize="12px" bold textTransform="uppercase">
{showWeeklyData ? t('Volume 7D') : t('Volume 24H')}
</Text>
<Text fontSize="24px" bold>
${showWeeklyData ? formatAmount(poolData.volumeUSDWeek) : formatAmount(poolData.volumeUSD)}
</Text>
<Percent value={showWeeklyData ? poolData.volumeUSDChangeWeek : poolData.volumeUSDChange} />
</Flex>
<Flex flex="1" flexDirection="column">
<Text color="secondary" fontSize="12px" bold textTransform="uppercase">
{showWeeklyData ? t('LP reward fees 7D') : t('LP reward fees 24H')}
</Text>
<Text fontSize="24px" bold>
${showWeeklyData ? formatAmount(poolData.lpFees7d) : formatAmount(poolData.lpFees24h)}
</Text>
<Text color="textSubtle" fontSize="12px">
{t('out of $%totalFees% total fees', {
totalFees: showWeeklyData
? formatAmount(poolData.totalFees7d)
: formatAmount(poolData.totalFees24h),
})}
</Text>
</Flex>
</Flex>
</Flex>
</Card>
</Box>
<ChartCard variant="pool" chartData={chartData} />
</ContentLayout>
<Heading mb="16px" mt="40px" scale="lg">
{t('Transactions')}
</Heading>
<TransactionTable transactions={transactions} />
</>
) : (
<Flex mt="80px" justifyContent="center">
<Spinner />
</Flex>
)}
</Page>
)
}
Example #26
Source File: ManageTokens.tsx From vvs-ui with GNU General Public License v3.0 | 4 votes |
export default function ManageTokens({
setModalView,
setImportToken,
}: {
setModalView: (view: CurrencyModalView) => void
setImportToken: (token: Token) => void
}) {
const { chainId } = useActiveWeb3React()
const { t } = useTranslation()
const [searchQuery, setSearchQuery] = useState<string>('')
// manage focus on modal show
const inputRef = useRef<HTMLInputElement>()
const handleInput = useCallback((event) => {
const input = event.target.value
const checksummedInput = isAddress(input)
setSearchQuery(checksummedInput || input)
}, [])
// if they input an address, use it
const searchToken = useToken(searchQuery)
// all tokens for local list
const userAddedTokens: Token[] = useUserAddedTokens()
const removeToken = useRemoveUserAddedToken()
const handleRemoveAll = useCallback(() => {
if (chainId && userAddedTokens) {
userAddedTokens.map((token) => {
return removeToken(chainId, token.address)
})
}
}, [removeToken, userAddedTokens, chainId])
const tokenList = useMemo(() => {
return (
chainId &&
userAddedTokens.map((token) => (
<RowBetween key={token.address} width="100%">
<RowFixed>
<CurrencyLogo currency={token} size="20px" />
<Link external href={getExplorerLink(token.address, 'address', chainId)} color="textSubtle" ml="10px">
{token.symbol}
</Link>
</RowFixed>
<RowFixed>
<IconButton variant="text" onClick={() => removeToken(chainId, token.address)}>
<CloseIcon />
</IconButton>
<LinkExternal href={getExplorerLink(token.address, 'address', chainId)} />
</RowFixed>
</RowBetween>
))
)
}, [userAddedTokens, chainId, removeToken])
const isAddressValid = searchQuery === '' || isAddress(searchQuery)
return (
<Wrapper>
<Column style={{ width: '100%', flex: '1 1' }}>
<AutoColumn gap="14px">
<Row>
<Input
id="token-search-input"
scale="lg"
placeholder="0x0000"
value={searchQuery}
autoComplete="off"
ref={inputRef as RefObject<HTMLInputElement>}
onChange={handleInput}
isWarning={!isAddressValid}
/>
</Row>
{!isAddressValid && <Text color="failure">{t('Enter valid token address')}</Text>}
{searchToken && (
<ImportRow
token={searchToken}
showImportView={() => setModalView(CurrencyModalView.importToken)}
setImportToken={setImportToken}
style={{ height: 'fit-content' }}
/>
)}
</AutoColumn>
{tokenList}
<Footer>
<Text bold color="textSubtle">
{userAddedTokens?.length} {userAddedTokens.length === 1 ? t('Custom Token') : t('Custom Tokens')}
</Text>
{userAddedTokens.length > 0 && (
<Button variant="tertiary" onClick={handleRemoveAll}>
{t('Clear all')}
</Button>
)}
</Footer>
</Column>
</Wrapper>
)
}
Example #27
Source File: WalletStatsModal.tsx From vvs-ui with GNU General Public License v3.0 | 4 votes |
WalletStatsModal: React.FC<WalletStatsModalProps> = ({ account, onDismiss, onBeforeDismiss }) => {
const { t } = useTranslation()
const { theme } = useTheme()
const result = useGetOrFetchLeaderboardAddressResult(account)
const profileAvatar = useGetProfileAvatar(account)
const leaderboardLoadingState = useGetLeaderboardLoadingState()
const isLoading = leaderboardLoadingState === LeaderboardLoadingState.LOADING
const { isDesktop } = useMatchBreakpoints()
const handleDismiss = () => {
if (onBeforeDismiss) {
onBeforeDismiss()
}
onDismiss()
}
return (
<ModalContainer minWidth="320px">
<ModalHeader background={theme.colors.gradients.bubblegum}>
<Flex alignItems="center" style={{ flex: 1 }}>
<Box width={['64px', null, null, null, null, null, '96px']} mr="16px">
<ProfileAvatar src={`/images/nfts/${profileAvatar.nft?.images?.md}`} height={96} width={96} />
</Box>
<Box>
{profileAvatar.username && (
<Heading scale="lg" mb="8px">
{profileAvatar.username}
</Heading>
)}
<ExternalLink href={getExplorerLink(account, 'address')}>{truncateHash(account)}</ExternalLink>
</Box>
</Flex>
<IconButton variant="text" onClick={handleDismiss} aria-label="Close the dialog">
<CloseIcon color="text" width="24px" />
</IconButton>
</ModalHeader>
{result === null ? (
<Text p="32px" textAlign="center" fontWeight="bold">
{t('No results found.')}
</Text>
) : (
<Box maxHeight={['500px', null, null, null, null, null, 'none']} overflowY="auto">
<Grid
gridTemplateColumns={['1fr', null, null, null, null, null, 'repeat(4, 1fr)']}
gridGap="16px"
p="24px"
borderBottom="1px solid"
borderColor="cardBorder"
>
<Box>
<Text as="h6" fontSize="12px" textTransform="uppercase" color="textSubtle" fontWeight="bold" mb="8px">
{t('Net Winnings')}
</Text>
{isLoading ? (
<Skeleton />
) : (
<NetWinnings
amount={result?.netCRO}
textPrefix={result?.netCRO > 0 ? '+' : ''}
textColor={result?.netCRO > 0 ? 'success' : 'failure'}
alignItems="flex-end"
/>
)}
</Box>
<Box>
<Text as="h6" fontSize="12px" textTransform="uppercase" color="textSubtle" fontWeight="bold" mb="8px">
{t('Win Rate')}
</Text>
{isLoading ? (
<Skeleton />
) : (
<Text fontWeight="bold">{`${result?.winRate?.toLocaleString(undefined, {
minimumFractionDigits: 0,
maximumFractionDigits: 2,
})}%`}</Text>
)}
</Box>
<Box>
<Text as="h6" fontSize="12px" textTransform="uppercase" color="textSubtle" fontWeight="bold" mb="8px">
{t('Rounds Won')}
</Text>
{isLoading ? <Skeleton /> : <Text fontWeight="bold">{result?.totalBetsClaimed?.toLocaleString()}</Text>}
</Box>
<Box>
<Text as="h6" fontSize="12px" textTransform="uppercase" color="textSubtle" fontWeight="bold" mb="8px">
{t('Rounds Played')}
</Text>
{isLoading ? <Skeleton /> : <Text fontWeight="bold">{result?.totalBets?.toLocaleString()}</Text>}
</Box>
</Grid>
{isDesktop ? <DesktopBetsTable account={account} /> : <MobileBetsTable account={account} />}
</Box>
)}
</ModalContainer>
)
}
Example #28
Source File: BetResult.tsx From vvs-ui with GNU General Public License v3.0 | 4 votes |
BetResult: React.FC<BetResultProps> = ({ bet, result }) => {
const { t } = useTranslation()
const dispatch = useAppDispatch()
const { account } = useWeb3React()
const { isRefundable } = useIsRefundable(bet.round.epoch)
const canClaim = useGetIsClaimable(bet.round.epoch)
const croUsdcPrice = useCroUsdcPrice()
const { targetRef, tooltip, tooltipVisible } = useTooltip(
<Text as="p">{t('Includes your original position and your winnings, minus the %fee% fee.', { fee: '3%' })}</Text>,
{ placement: 'auto' },
)
const isWinner = result === Result.WIN
// Winners get the payout, otherwise the claim what they put it if it was canceled
const payout = isWinner ? getNetPayout(bet, REWARD_RATE) : bet.amount
const totalPayout = multiplyPriceByAmount(croUsdcPrice, payout)
const returned = payout + bet.amount
const getHeaderColor = () => {
switch (result) {
case Result.WIN:
return 'warning'
case Result.LOSE:
return 'textSubtle'
case Result.CANCELED:
return 'textDisabled'
default:
return 'text'
}
}
const getHeaderText = () => {
switch (result) {
case Result.WIN:
return t('Win')
case Result.LOSE:
return t('Lose')
case Result.CANCELED:
return t('Canceled')
default:
return ''
}
}
const getHeaderIcon = () => {
switch (result) {
case Result.WIN:
return <PrizeIcon color={getHeaderColor()} />
case Result.LOSE:
case Result.CANCELED:
return <BlockIcon color={getHeaderColor()} />
default:
return null
}
}
const getResultColor = () => {
switch (result) {
case Result.WIN:
return 'success'
case Result.LOSE:
return 'failure'
case Result.CANCELED:
default:
return 'text'
}
}
const handleSuccess = async () => {
// We have to mark the bet as claimed immediately because it does not update fast enough
dispatch(markAsCollected({ [bet.round.epoch]: true }))
dispatch(fetchLedgerData({ account, epochs: [bet.round.epoch] }))
}
return (
<>
<Flex alignItems="center" justifyContent="space-between" mb="8px">
<Heading>{t('Your History')}</Heading>
<Flex alignItems="center">
<Heading as="h3" color={getHeaderColor()} textTransform="uppercase" bold mr="4px">
{getHeaderText()}
</Heading>
{getHeaderIcon()}
</Flex>
</Flex>
<StyledBetResult>
{result === Result.WIN && !canClaim && (
<CollectWinningsButton hasClaimed={!canClaim} width="100%" mb="16px" onSuccess={handleSuccess}>
{bet.claimed ? t('Already Collected') : t('Collect Winnings')}
</CollectWinningsButton>
)}
{bet.claimed && bet.claimedHash && (
<Flex justifyContent="center">
<LinkExternal href={getExplorerLink(bet.claimedHash, 'transaction')} mb="16px">
{t('View on Cronos Explorer')}
</LinkExternal>
</Flex>
)}
{result === Result.CANCELED && isRefundable && (
<ReclaimPositionButton epoch={bet.round.epoch} width="100%" mb="16px" />
)}
<Flex alignItems="center" justifyContent="space-between" mb="16px">
<Text>{t('Your direction')}:</Text>
<PositionTag betPosition={bet.position}>
{bet.position === BetPosition.BULL ? t('Up') : t('Down')}
</PositionTag>
</Flex>
<Flex alignItems="center" justifyContent="space-between" mb="16px">
<Text>{t('Your position')}</Text>
<Text>{`${formatCro(bet.amount)} CRO`}</Text>
</Flex>
<Flex alignItems="start" justifyContent="space-between">
<Text bold>{isWinner ? t('Your winnings') : t('Your Result')}:</Text>
<Box style={{ textAlign: 'right' }}>
<Text bold color={getResultColor()}>{`${isWinner ? '+' : '-'}${formatCro(payout)} CRO`}</Text>
<Text fontSize="12px" color="textSubtle">
{`~$${totalPayout.toFixed(2)}`}
</Text>
</Box>
</Flex>
{isWinner && (
<>
<Divider />
<Flex alignItems="start" justifyContent="space-between">
<Text fontSize="14px" color="textSubtle">
{t('Amount to collect')}:
</Text>
<Flex justifyContent="end">
<Text fontSize="14px" color="textSubtle">{`${formatCro(returned)} CRO`}</Text>
<span ref={targetRef}>
<InfoIcon color="textSubtle" ml="4px" />
</span>
</Flex>
{tooltipVisible && tooltip}
</Flex>
</>
)}
</StyledBetResult>
</>
)
}
Example #29
Source File: PnlTab.tsx From vvs-ui with GNU General Public License v3.0 | 4 votes |
PnlTab: React.FC<PnlTabProps> = ({ hasBetHistory, bets }) => {
const { t } = useTranslation()
const { account } = useWeb3React()
const currentEpoch = useGetCurrentEpoch()
const croUsdcPrice = useCroUsdcPrice()
const summary = getPnlSummary(bets, currentEpoch)
const netResultAmount = summary.won.payout - summary.lost.amount
const netResultIsPositive = netResultAmount > 0
const avgPositionEntered = summary.entered.amount / summary.entered.rounds
const avgBnbWonPerRound = netResultAmount / summary.entered.rounds
const avgBnbWonIsPositive = avgBnbWonPerRound > 0
// Guard in case user has only lost rounds
const hasBestRound = summary.won.bestRound.payout !== 0
const netResultInUsd = multiplyPriceByAmount(croUsdcPrice, netResultAmount)
const avgBnbWonInUsd = multiplyPriceByAmount(croUsdcPrice, avgBnbWonPerRound)
const betRoundInUsd = multiplyPriceByAmount(croUsdcPrice, summary.won.bestRound.multiplier)
const avgPositionEnteredInUsd = multiplyPriceByAmount(croUsdcPrice, avgPositionEntered)
return hasBetHistory ? (
<Box p="16px">
<Text bold fontSize="24px" color="secondary" pb="24px">
{t('Your history')}
</Text>
<Flex>
<PnlChart lost={summary.lost.rounds} won={summary.won.rounds} />
<Flex flexDirection="column" justifyContent="center" pl="24px">
<Text bold color="textSubtle">
{t('Net results')}
</Text>
<Text bold fontSize="24px" lineHeight="1" color={netResultIsPositive ? 'success' : 'failure'}>
{`${netResultIsPositive ? '+' : ''}${formatCro(netResultAmount)} CRO`}
</Text>
<Text small color="textSubtle">
{`~$${netResultInUsd.toFixed(2)}`}
</Text>
</Flex>
</Flex>
<Box pl="8px">
<Text mt="24px" bold color="textSubtle">
{t('Average return / round')}
</Text>
<Text bold color={avgBnbWonIsPositive ? 'success' : 'failure'}>
{`${avgBnbWonIsPositive ? '+' : ''}${formatCro(avgBnbWonPerRound)} CRO`}
</Text>
<Text small color="textSubtle">
{`~$${avgBnbWonInUsd.toFixed(2)}`}
</Text>
{hasBestRound && (
<>
<Text mt="16px" bold color="textSubtle">
{t('Best round: #%roundId%', { roundId: summary.won.bestRound.id })}
</Text>
<Flex alignItems="flex-end">
<Text bold color="success">{`+${formatCro(summary.won.bestRound.payout)} CRO`}</Text>
<Text ml="4px" small color="textSubtle">
({summary.won.bestRound.multiplier.toFixed(2)}x)
</Text>
</Flex>
<Text small color="textSubtle">
{`~$${betRoundInUsd.toFixed(2)}`}
</Text>
</>
)}
<Text mt="16px" bold color="textSubtle">
{t('Average position entered / round')}
</Text>
<Text bold>{`${formatCro(avgPositionEntered)} CRO`}</Text>
<Text small color="textSubtle">
{`~$${avgPositionEnteredInUsd.toFixed(2)}`}
</Text>
<Divider />
<SummaryRow type="won" summary={summary} croUsdcPrice={croUsdcPrice} />
<SummaryRow type="lost" summary={summary} croUsdcPrice={croUsdcPrice} />
<SummaryRow type="entered" summary={summary} croUsdcPrice={croUsdcPrice} />
<Flex justifyContent="center" mt="24px">
<Link href={`${getExplorerLink(account, 'address')}#internaltx`} mb="16px" external>
<Button mt="8px" width="100%">
{t('View Reclaimed & Won')}
<OpenNewIcon color="white" ml="4px" />
</Button>
</Link>
</Flex>
</Box>
</Box>
) : (
<Box p="24px">
<Heading size="lg" textAlign="center" mb="8px">
{t('No prediction history available')}
</Heading>
<Text as="p" textAlign="center">
{t(
'If you are sure you should see history here, make sure you’re connected to the correct wallet and try again.',
)}
</Text>
</Box>
)
}