feat: implement-page-viewed-event-for-all-main-pages-of-app (#4089)
* init commit: initial constants for pages, implement vote page viewed * implement swap * implement pool * remove charts * simplify shouldLogImpression
This commit is contained in:
parent
64cb9f3ff2
commit
4e0c9b36a0
@ -17,7 +17,10 @@ export enum EventName {
|
|||||||
* Known pages in the app. Highest order context.
|
* Known pages in the app. Highest order context.
|
||||||
*/
|
*/
|
||||||
export const enum PageName {
|
export const enum PageName {
|
||||||
|
EXPLORE_PAGE = 'explore-page',
|
||||||
|
POOL_PAGE = 'pool-page',
|
||||||
SWAP_PAGE = 'swap-page',
|
SWAP_PAGE = 'swap-page',
|
||||||
|
VOTE_PAGE = 'vote-page',
|
||||||
// alphabetize additional page names.
|
// alphabetize additional page names.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,8 @@ import { getAddress, isAddress } from '@ethersproject/address'
|
|||||||
import { Trans } from '@lingui/macro'
|
import { Trans } from '@lingui/macro'
|
||||||
import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core'
|
import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core'
|
||||||
import { useWeb3React } from '@web3-react/core'
|
import { useWeb3React } from '@web3-react/core'
|
||||||
|
import { PageName } from 'components/AmplitudeAnalytics/constants'
|
||||||
|
import { Trace } from 'components/AmplitudeAnalytics/Trace'
|
||||||
import { ButtonError } from 'components/Button'
|
import { ButtonError } from 'components/Button'
|
||||||
import { BlueCard } from 'components/Card'
|
import { BlueCard } from 'components/Card'
|
||||||
import { AutoColumn } from 'components/Column'
|
import { AutoColumn } from 'components/Column'
|
||||||
@ -225,63 +227,66 @@ ${bodyValue}
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AppBody {...{ maxWidth: '800px' }}>
|
<Trace page={PageName.VOTE_PAGE} shouldLogImpression>
|
||||||
<CreateProposalTabs />
|
<AppBody {...{ maxWidth: '800px' }}>
|
||||||
<CreateProposalWrapper>
|
<CreateProposalTabs />
|
||||||
<BlueCard>
|
<CreateProposalWrapper>
|
||||||
<AutoColumn gap="10px">
|
<BlueCard>
|
||||||
<ThemedText.Link fontWeight={400} color={'primaryText1'}>
|
<AutoColumn gap="10px">
|
||||||
<Trans>
|
<ThemedText.Link fontWeight={400} color={'primaryText1'}>
|
||||||
<strong>Tip:</strong> Select an action and describe your proposal for the community. The proposal cannot
|
<Trans>
|
||||||
be modified after submission, so please verify all information before submitting. The voting period will
|
<strong>Tip:</strong> Select an action and describe your proposal for the community. The proposal
|
||||||
begin immediately and last for 7 days. To propose a custom action,{' '}
|
cannot be modified after submission, so please verify all information before submitting. The voting
|
||||||
<ExternalLink href="https://uniswap.org/docs/v2/governance/governance-reference/#propose">
|
period will begin immediately and last for 7 days. To propose a custom action,{' '}
|
||||||
read the docs
|
<ExternalLink href="https://uniswap.org/docs/v2/governance/governance-reference/#propose">
|
||||||
</ExternalLink>
|
read the docs
|
||||||
.
|
</ExternalLink>
|
||||||
</Trans>
|
.
|
||||||
</ThemedText.Link>
|
</Trans>
|
||||||
</AutoColumn>
|
</ThemedText.Link>
|
||||||
</BlueCard>
|
</AutoColumn>
|
||||||
|
</BlueCard>
|
||||||
|
|
||||||
<ProposalActionSelector onClick={handleActionSelectorClick} proposalAction={proposalAction} />
|
<ProposalActionSelector onClick={handleActionSelectorClick} proposalAction={proposalAction} />
|
||||||
<ProposalActionDetail
|
<ProposalActionDetail
|
||||||
proposalAction={proposalAction}
|
proposalAction={proposalAction}
|
||||||
currency={currencyValue}
|
currency={currencyValue}
|
||||||
amount={amountValue}
|
amount={amountValue}
|
||||||
toAddress={toAddressValue}
|
toAddress={toAddressValue}
|
||||||
onCurrencySelect={handleCurrencySelect}
|
onCurrencySelect={handleCurrencySelect}
|
||||||
onAmountInput={handleAmountInput}
|
onAmountInput={handleAmountInput}
|
||||||
onToAddressInput={handleToAddressInput}
|
onToAddressInput={handleToAddressInput}
|
||||||
|
/>
|
||||||
|
<ProposalEditor
|
||||||
|
title={titleValue}
|
||||||
|
body={bodyValue}
|
||||||
|
onTitleInput={handleTitleInput}
|
||||||
|
onBodyInput={handleBodyInput}
|
||||||
|
/>
|
||||||
|
<CreateProposalButton
|
||||||
|
proposalThreshold={proposalThreshold}
|
||||||
|
hasActiveOrPendingProposal={
|
||||||
|
latestProposalData?.status === ProposalState.ACTIVE ||
|
||||||
|
latestProposalData?.status === ProposalState.PENDING
|
||||||
|
}
|
||||||
|
hasEnoughVote={hasEnoughVote}
|
||||||
|
isFormInvalid={isFormInvalid}
|
||||||
|
handleCreateProposal={handleCreateProposal}
|
||||||
|
/>
|
||||||
|
{!hasEnoughVote ? (
|
||||||
|
<AutonomousProposalCTA>
|
||||||
|
Don’t have 2.5M votes? Anyone can create an autonomous proposal using{' '}
|
||||||
|
<ExternalLink href="https://fish.vote">fish.vote</ExternalLink>
|
||||||
|
</AutonomousProposalCTA>
|
||||||
|
) : null}
|
||||||
|
</CreateProposalWrapper>
|
||||||
|
<ProposalActionSelectorModal
|
||||||
|
isOpen={modalOpen}
|
||||||
|
onDismiss={handleDismissActionSelector}
|
||||||
|
onProposalActionSelect={(proposalAction: ProposalAction) => handleActionChange(proposalAction)}
|
||||||
/>
|
/>
|
||||||
<ProposalEditor
|
<ProposalSubmissionModal isOpen={attempting} hash={hash} onDismiss={handleDismissSubmissionModal} />
|
||||||
title={titleValue}
|
</AppBody>
|
||||||
body={bodyValue}
|
</Trace>
|
||||||
onTitleInput={handleTitleInput}
|
|
||||||
onBodyInput={handleBodyInput}
|
|
||||||
/>
|
|
||||||
<CreateProposalButton
|
|
||||||
proposalThreshold={proposalThreshold}
|
|
||||||
hasActiveOrPendingProposal={
|
|
||||||
latestProposalData?.status === ProposalState.ACTIVE || latestProposalData?.status === ProposalState.PENDING
|
|
||||||
}
|
|
||||||
hasEnoughVote={hasEnoughVote}
|
|
||||||
isFormInvalid={isFormInvalid}
|
|
||||||
handleCreateProposal={handleCreateProposal}
|
|
||||||
/>
|
|
||||||
{!hasEnoughVote ? (
|
|
||||||
<AutonomousProposalCTA>
|
|
||||||
Don’t have 2.5M votes? Anyone can create an autonomous proposal using{' '}
|
|
||||||
<ExternalLink href="https://fish.vote">fish.vote</ExternalLink>
|
|
||||||
</AutonomousProposalCTA>
|
|
||||||
) : null}
|
|
||||||
</CreateProposalWrapper>
|
|
||||||
<ProposalActionSelectorModal
|
|
||||||
isOpen={modalOpen}
|
|
||||||
onDismiss={handleDismissActionSelector}
|
|
||||||
onProposalActionSelect={(proposalAction: ProposalAction) => handleActionChange(proposalAction)}
|
|
||||||
/>
|
|
||||||
<ProposalSubmissionModal isOpen={attempting} hash={hash} onDismiss={handleDismissSubmissionModal} />
|
|
||||||
</AppBody>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,8 @@ import { Trans } from '@lingui/macro'
|
|||||||
import { Currency, CurrencyAmount, Fraction, Percent, Price, Token } from '@uniswap/sdk-core'
|
import { Currency, CurrencyAmount, Fraction, Percent, Price, Token } from '@uniswap/sdk-core'
|
||||||
import { NonfungiblePositionManager, Pool, Position } from '@uniswap/v3-sdk'
|
import { NonfungiblePositionManager, Pool, Position } from '@uniswap/v3-sdk'
|
||||||
import { useWeb3React } from '@web3-react/core'
|
import { useWeb3React } from '@web3-react/core'
|
||||||
|
import { PageName } from 'components/AmplitudeAnalytics/constants'
|
||||||
|
import { Trace } from 'components/AmplitudeAnalytics/Trace'
|
||||||
import { sendEvent } from 'components/analytics'
|
import { sendEvent } from 'components/analytics'
|
||||||
import Badge from 'components/Badge'
|
import Badge from 'components/Badge'
|
||||||
import { ButtonConfirmed, ButtonGray, ButtonPrimary } from 'components/Button'
|
import { ButtonConfirmed, ButtonGray, ButtonPrimary } from 'components/Button'
|
||||||
@ -567,344 +569,347 @@ export function PositionPage({
|
|||||||
<div />
|
<div />
|
||||||
</LoadingRows>
|
</LoadingRows>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<Trace page={PageName.POOL_PAGE} shouldLogImpression>
|
||||||
<PageWrapper>
|
<>
|
||||||
<TransactionConfirmationModal
|
<PageWrapper>
|
||||||
isOpen={showConfirm}
|
<TransactionConfirmationModal
|
||||||
onDismiss={() => setShowConfirm(false)}
|
isOpen={showConfirm}
|
||||||
attemptingTxn={collecting}
|
onDismiss={() => setShowConfirm(false)}
|
||||||
hash={collectMigrationHash ?? ''}
|
attemptingTxn={collecting}
|
||||||
content={() => (
|
hash={collectMigrationHash ?? ''}
|
||||||
<ConfirmationModalContent
|
content={() => (
|
||||||
title={<Trans>Claim fees</Trans>}
|
<ConfirmationModalContent
|
||||||
onDismiss={() => setShowConfirm(false)}
|
title={<Trans>Claim fees</Trans>}
|
||||||
topContent={modalHeader}
|
onDismiss={() => setShowConfirm(false)}
|
||||||
/>
|
topContent={modalHeader}
|
||||||
)}
|
|
||||||
pendingText={<Trans>Collecting fees</Trans>}
|
|
||||||
/>
|
|
||||||
<AutoColumn gap="md">
|
|
||||||
<AutoColumn gap="sm">
|
|
||||||
<Link style={{ textDecoration: 'none', width: 'fit-content', marginBottom: '0.5rem' }} to="/pool">
|
|
||||||
<HoverText>
|
|
||||||
<Trans>← Back to Pools Overview</Trans>
|
|
||||||
</HoverText>
|
|
||||||
</Link>
|
|
||||||
<ResponsiveRow>
|
|
||||||
<RowFixed>
|
|
||||||
<DoubleCurrencyLogo currency0={currencyBase} currency1={currencyQuote} size={24} margin={true} />
|
|
||||||
<ThemedText.Label fontSize={'24px'} mr="10px">
|
|
||||||
{currencyQuote?.symbol} / {currencyBase?.symbol}
|
|
||||||
</ThemedText.Label>
|
|
||||||
<Badge style={{ marginRight: '8px' }}>
|
|
||||||
<BadgeText>
|
|
||||||
<Trans>{new Percent(feeAmount, 1_000_000).toSignificant()}%</Trans>
|
|
||||||
</BadgeText>
|
|
||||||
</Badge>
|
|
||||||
<RangeBadge removed={removed} inRange={inRange} />
|
|
||||||
</RowFixed>
|
|
||||||
{ownsNFT && (
|
|
||||||
<RowFixed>
|
|
||||||
{currency0 && currency1 && feeAmount && tokenId ? (
|
|
||||||
<ButtonGray
|
|
||||||
as={Link}
|
|
||||||
to={`/increase/${currencyId(currency0)}/${currencyId(currency1)}/${feeAmount}/${tokenId}`}
|
|
||||||
width="fit-content"
|
|
||||||
padding="6px 8px"
|
|
||||||
$borderRadius="12px"
|
|
||||||
style={{ marginRight: '8px' }}
|
|
||||||
>
|
|
||||||
<Trans>Increase Liquidity</Trans>
|
|
||||||
</ButtonGray>
|
|
||||||
) : null}
|
|
||||||
{tokenId && !removed ? (
|
|
||||||
<ResponsiveButtonPrimary
|
|
||||||
as={Link}
|
|
||||||
to={`/remove/${tokenId}`}
|
|
||||||
width="fit-content"
|
|
||||||
padding="6px 8px"
|
|
||||||
$borderRadius="12px"
|
|
||||||
>
|
|
||||||
<Trans>Remove Liquidity</Trans>
|
|
||||||
</ResponsiveButtonPrimary>
|
|
||||||
) : null}
|
|
||||||
</RowFixed>
|
|
||||||
)}
|
|
||||||
</ResponsiveRow>
|
|
||||||
<RowBetween></RowBetween>
|
|
||||||
</AutoColumn>
|
|
||||||
<ResponsiveRow align="flex-start">
|
|
||||||
{'result' in metadata ? (
|
|
||||||
<DarkCard
|
|
||||||
width="100%"
|
|
||||||
height="100%"
|
|
||||||
style={{
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
flexDirection: 'column',
|
|
||||||
justifyContent: 'space-around',
|
|
||||||
marginRight: '12px',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div style={{ marginRight: 12 }}>
|
|
||||||
<NFT image={metadata.result.image} height={400} />
|
|
||||||
</div>
|
|
||||||
{typeof chainId === 'number' && owner && !ownsNFT ? (
|
|
||||||
<ExternalLink href={getExplorerLink(chainId, owner, ExplorerDataType.ADDRESS)}>
|
|
||||||
<Trans>Owner</Trans>
|
|
||||||
</ExternalLink>
|
|
||||||
) : null}
|
|
||||||
</DarkCard>
|
|
||||||
) : (
|
|
||||||
<DarkCard
|
|
||||||
width="100%"
|
|
||||||
height="100%"
|
|
||||||
style={{
|
|
||||||
marginRight: '12px',
|
|
||||||
minWidth: '340px',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Loader />
|
|
||||||
</DarkCard>
|
|
||||||
)}
|
|
||||||
<AutoColumn gap="sm" style={{ width: '100%', height: '100%' }}>
|
|
||||||
<DarkCard>
|
|
||||||
<AutoColumn gap="md" style={{ width: '100%' }}>
|
|
||||||
<AutoColumn gap="md">
|
|
||||||
<Label>
|
|
||||||
<Trans>Liquidity</Trans>
|
|
||||||
</Label>
|
|
||||||
{fiatValueOfLiquidity?.greaterThan(new Fraction(1, 100)) ? (
|
|
||||||
<ThemedText.LargeHeader fontSize="36px" fontWeight={500}>
|
|
||||||
<Trans>${fiatValueOfLiquidity.toFixed(2, { groupSeparator: ',' })}</Trans>
|
|
||||||
</ThemedText.LargeHeader>
|
|
||||||
) : (
|
|
||||||
<ThemedText.LargeHeader color={theme.text1} fontSize="36px" fontWeight={500}>
|
|
||||||
<Trans>$-</Trans>
|
|
||||||
</ThemedText.LargeHeader>
|
|
||||||
)}
|
|
||||||
</AutoColumn>
|
|
||||||
<LightCard padding="12px 16px">
|
|
||||||
<AutoColumn gap="md">
|
|
||||||
<RowBetween>
|
|
||||||
<LinkedCurrency chainId={chainId} currency={currencyQuote} />
|
|
||||||
<RowFixed>
|
|
||||||
<ThemedText.Main>
|
|
||||||
{inverted ? position?.amount0.toSignificant(4) : position?.amount1.toSignificant(4)}
|
|
||||||
</ThemedText.Main>
|
|
||||||
{typeof ratio === 'number' && !removed ? (
|
|
||||||
<Badge style={{ marginLeft: '10px' }}>
|
|
||||||
<ThemedText.Main fontSize={11}>
|
|
||||||
<Trans>{inverted ? ratio : 100 - ratio}%</Trans>
|
|
||||||
</ThemedText.Main>
|
|
||||||
</Badge>
|
|
||||||
) : null}
|
|
||||||
</RowFixed>
|
|
||||||
</RowBetween>
|
|
||||||
<RowBetween>
|
|
||||||
<LinkedCurrency chainId={chainId} currency={currencyBase} />
|
|
||||||
<RowFixed>
|
|
||||||
<ThemedText.Main>
|
|
||||||
{inverted ? position?.amount1.toSignificant(4) : position?.amount0.toSignificant(4)}
|
|
||||||
</ThemedText.Main>
|
|
||||||
{typeof ratio === 'number' && !removed ? (
|
|
||||||
<Badge style={{ marginLeft: '10px' }}>
|
|
||||||
<ThemedText.Main color={theme.text2} fontSize={11}>
|
|
||||||
<Trans>{inverted ? 100 - ratio : ratio}%</Trans>
|
|
||||||
</ThemedText.Main>
|
|
||||||
</Badge>
|
|
||||||
) : null}
|
|
||||||
</RowFixed>
|
|
||||||
</RowBetween>
|
|
||||||
</AutoColumn>
|
|
||||||
</LightCard>
|
|
||||||
</AutoColumn>
|
|
||||||
</DarkCard>
|
|
||||||
<DarkCard>
|
|
||||||
<AutoColumn gap="md" style={{ width: '100%' }}>
|
|
||||||
<AutoColumn gap="md">
|
|
||||||
<RowBetween style={{ alignItems: 'flex-start' }}>
|
|
||||||
<AutoColumn gap="md">
|
|
||||||
<Label>
|
|
||||||
<Trans>Unclaimed fees</Trans>
|
|
||||||
</Label>
|
|
||||||
{fiatValueOfFees?.greaterThan(new Fraction(1, 100)) ? (
|
|
||||||
<ThemedText.LargeHeader color={theme.green1} fontSize="36px" fontWeight={500}>
|
|
||||||
<Trans>${fiatValueOfFees.toFixed(2, { groupSeparator: ',' })}</Trans>
|
|
||||||
</ThemedText.LargeHeader>
|
|
||||||
) : (
|
|
||||||
<ThemedText.LargeHeader color={theme.text1} fontSize="36px" fontWeight={500}>
|
|
||||||
<Trans>$-</Trans>
|
|
||||||
</ThemedText.LargeHeader>
|
|
||||||
)}
|
|
||||||
</AutoColumn>
|
|
||||||
{ownsNFT && (feeValue0?.greaterThan(0) || feeValue1?.greaterThan(0) || !!collectMigrationHash) ? (
|
|
||||||
<ButtonConfirmed
|
|
||||||
disabled={collecting || !!collectMigrationHash}
|
|
||||||
confirmed={!!collectMigrationHash && !isCollectPending}
|
|
||||||
width="fit-content"
|
|
||||||
style={{ borderRadius: '12px' }}
|
|
||||||
padding="4px 8px"
|
|
||||||
onClick={() => setShowConfirm(true)}
|
|
||||||
>
|
|
||||||
{!!collectMigrationHash && !isCollectPending ? (
|
|
||||||
<ThemedText.Main color={theme.text1}>
|
|
||||||
<Trans> Collected</Trans>
|
|
||||||
</ThemedText.Main>
|
|
||||||
) : isCollectPending || collecting ? (
|
|
||||||
<ThemedText.Main color={theme.text1}>
|
|
||||||
{' '}
|
|
||||||
<Dots>
|
|
||||||
<Trans>Collecting</Trans>
|
|
||||||
</Dots>
|
|
||||||
</ThemedText.Main>
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
<ThemedText.Main color={theme.white}>
|
|
||||||
<Trans>Collect fees</Trans>
|
|
||||||
</ThemedText.Main>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</ButtonConfirmed>
|
|
||||||
) : null}
|
|
||||||
</RowBetween>
|
|
||||||
</AutoColumn>
|
|
||||||
<LightCard padding="12px 16px">
|
|
||||||
<AutoColumn gap="md">
|
|
||||||
<RowBetween>
|
|
||||||
<RowFixed>
|
|
||||||
<CurrencyLogo
|
|
||||||
currency={feeValueUpper?.currency}
|
|
||||||
size={'20px'}
|
|
||||||
style={{ marginRight: '0.5rem' }}
|
|
||||||
/>
|
|
||||||
<ThemedText.Main>{feeValueUpper?.currency?.symbol}</ThemedText.Main>
|
|
||||||
</RowFixed>
|
|
||||||
<RowFixed>
|
|
||||||
<ThemedText.Main>
|
|
||||||
{feeValueUpper ? formatCurrencyAmount(feeValueUpper, 4) : '-'}
|
|
||||||
</ThemedText.Main>
|
|
||||||
</RowFixed>
|
|
||||||
</RowBetween>
|
|
||||||
<RowBetween>
|
|
||||||
<RowFixed>
|
|
||||||
<CurrencyLogo
|
|
||||||
currency={feeValueLower?.currency}
|
|
||||||
size={'20px'}
|
|
||||||
style={{ marginRight: '0.5rem' }}
|
|
||||||
/>
|
|
||||||
<ThemedText.Main>{feeValueLower?.currency?.symbol}</ThemedText.Main>
|
|
||||||
</RowFixed>
|
|
||||||
<RowFixed>
|
|
||||||
<ThemedText.Main>
|
|
||||||
{feeValueLower ? formatCurrencyAmount(feeValueLower, 4) : '-'}
|
|
||||||
</ThemedText.Main>
|
|
||||||
</RowFixed>
|
|
||||||
</RowBetween>
|
|
||||||
</AutoColumn>
|
|
||||||
</LightCard>
|
|
||||||
{showCollectAsWeth && (
|
|
||||||
<AutoColumn gap="md">
|
|
||||||
<RowBetween>
|
|
||||||
<ThemedText.Main>
|
|
||||||
<Trans>Collect as {nativeWrappedSymbol}</Trans>
|
|
||||||
</ThemedText.Main>
|
|
||||||
<Toggle
|
|
||||||
id="receive-as-weth"
|
|
||||||
isActive={receiveWETH}
|
|
||||||
toggle={() => setReceiveWETH((receiveWETH) => !receiveWETH)}
|
|
||||||
/>
|
|
||||||
</RowBetween>
|
|
||||||
</AutoColumn>
|
|
||||||
)}
|
|
||||||
</AutoColumn>
|
|
||||||
</DarkCard>
|
|
||||||
</AutoColumn>
|
|
||||||
</ResponsiveRow>
|
|
||||||
<DarkCard>
|
|
||||||
<AutoColumn gap="md">
|
|
||||||
<RowBetween>
|
|
||||||
<RowFixed>
|
|
||||||
<Label display="flex" style={{ marginRight: '12px' }}>
|
|
||||||
<Trans>Price range</Trans>
|
|
||||||
</Label>
|
|
||||||
<HideExtraSmall>
|
|
||||||
<>
|
|
||||||
<RangeBadge removed={removed} inRange={inRange} />
|
|
||||||
<span style={{ width: '8px' }} />
|
|
||||||
</>
|
|
||||||
</HideExtraSmall>
|
|
||||||
</RowFixed>
|
|
||||||
<RowFixed>
|
|
||||||
{currencyBase && currencyQuote && (
|
|
||||||
<RateToggle
|
|
||||||
currencyA={currencyBase}
|
|
||||||
currencyB={currencyQuote}
|
|
||||||
handleRateToggle={() => setManuallyInverted(!manuallyInverted)}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</RowFixed>
|
|
||||||
</RowBetween>
|
|
||||||
|
|
||||||
<RowBetween>
|
|
||||||
<LightCard padding="12px" width="100%">
|
|
||||||
<AutoColumn gap="8px" justify="center">
|
|
||||||
<ExtentsText>
|
|
||||||
<Trans>Min price</Trans>
|
|
||||||
</ExtentsText>
|
|
||||||
<ThemedText.MediumHeader textAlign="center">
|
|
||||||
{formatTickPrice(priceLower, tickAtLimit, Bound.LOWER)}
|
|
||||||
</ThemedText.MediumHeader>
|
|
||||||
<ExtentsText>
|
|
||||||
{' '}
|
|
||||||
<Trans>
|
|
||||||
{currencyQuote?.symbol} per {currencyBase?.symbol}
|
|
||||||
</Trans>
|
|
||||||
</ExtentsText>
|
|
||||||
|
|
||||||
{inRange && (
|
|
||||||
<ThemedText.Small color={theme.text3}>
|
|
||||||
<Trans>Your position will be 100% {currencyBase?.symbol} at this price.</Trans>
|
|
||||||
</ThemedText.Small>
|
|
||||||
)}
|
|
||||||
</AutoColumn>
|
|
||||||
</LightCard>
|
|
||||||
|
|
||||||
<DoubleArrow>⟷</DoubleArrow>
|
|
||||||
<LightCard padding="12px" width="100%">
|
|
||||||
<AutoColumn gap="8px" justify="center">
|
|
||||||
<ExtentsText>
|
|
||||||
<Trans>Max price</Trans>
|
|
||||||
</ExtentsText>
|
|
||||||
<ThemedText.MediumHeader textAlign="center">
|
|
||||||
{formatTickPrice(priceUpper, tickAtLimit, Bound.UPPER)}
|
|
||||||
</ThemedText.MediumHeader>
|
|
||||||
<ExtentsText>
|
|
||||||
{' '}
|
|
||||||
<Trans>
|
|
||||||
{currencyQuote?.symbol} per {currencyBase?.symbol}
|
|
||||||
</Trans>
|
|
||||||
</ExtentsText>
|
|
||||||
|
|
||||||
{inRange && (
|
|
||||||
<ThemedText.Small color={theme.text3}>
|
|
||||||
<Trans>Your position will be 100% {currencyQuote?.symbol} at this price.</Trans>
|
|
||||||
</ThemedText.Small>
|
|
||||||
)}
|
|
||||||
</AutoColumn>
|
|
||||||
</LightCard>
|
|
||||||
</RowBetween>
|
|
||||||
<CurrentPriceCard
|
|
||||||
inverted={inverted}
|
|
||||||
pool={pool}
|
|
||||||
currencyQuote={currencyQuote}
|
|
||||||
currencyBase={currencyBase}
|
|
||||||
/>
|
/>
|
||||||
|
)}
|
||||||
|
pendingText={<Trans>Collecting fees</Trans>}
|
||||||
|
/>
|
||||||
|
<AutoColumn gap="md">
|
||||||
|
<AutoColumn gap="sm">
|
||||||
|
<Link style={{ textDecoration: 'none', width: 'fit-content', marginBottom: '0.5rem' }} to="/pool">
|
||||||
|
<HoverText>
|
||||||
|
<Trans>← Back to Pools Overview</Trans>
|
||||||
|
</HoverText>
|
||||||
|
</Link>
|
||||||
|
<ResponsiveRow>
|
||||||
|
<RowFixed>
|
||||||
|
<DoubleCurrencyLogo currency0={currencyBase} currency1={currencyQuote} size={24} margin={true} />
|
||||||
|
<ThemedText.Label fontSize={'24px'} mr="10px">
|
||||||
|
{currencyQuote?.symbol} / {currencyBase?.symbol}
|
||||||
|
</ThemedText.Label>
|
||||||
|
<Badge style={{ marginRight: '8px' }}>
|
||||||
|
<BadgeText>
|
||||||
|
<Trans>{new Percent(feeAmount, 1_000_000).toSignificant()}%</Trans>
|
||||||
|
</BadgeText>
|
||||||
|
</Badge>
|
||||||
|
<RangeBadge removed={removed} inRange={inRange} />
|
||||||
|
</RowFixed>
|
||||||
|
{ownsNFT && (
|
||||||
|
<RowFixed>
|
||||||
|
{currency0 && currency1 && feeAmount && tokenId ? (
|
||||||
|
<ButtonGray
|
||||||
|
as={Link}
|
||||||
|
to={`/increase/${currencyId(currency0)}/${currencyId(currency1)}/${feeAmount}/${tokenId}`}
|
||||||
|
width="fit-content"
|
||||||
|
padding="6px 8px"
|
||||||
|
$borderRadius="12px"
|
||||||
|
style={{ marginRight: '8px' }}
|
||||||
|
>
|
||||||
|
<Trans>Increase Liquidity</Trans>
|
||||||
|
</ButtonGray>
|
||||||
|
) : null}
|
||||||
|
{tokenId && !removed ? (
|
||||||
|
<ResponsiveButtonPrimary
|
||||||
|
as={Link}
|
||||||
|
to={`/remove/${tokenId}`}
|
||||||
|
width="fit-content"
|
||||||
|
padding="6px 8px"
|
||||||
|
$borderRadius="12px"
|
||||||
|
>
|
||||||
|
<Trans>Remove Liquidity</Trans>
|
||||||
|
</ResponsiveButtonPrimary>
|
||||||
|
) : null}
|
||||||
|
</RowFixed>
|
||||||
|
)}
|
||||||
|
</ResponsiveRow>
|
||||||
|
<RowBetween></RowBetween>
|
||||||
</AutoColumn>
|
</AutoColumn>
|
||||||
</DarkCard>
|
<ResponsiveRow align="flex-start">
|
||||||
</AutoColumn>
|
{'result' in metadata ? (
|
||||||
</PageWrapper>
|
<DarkCard
|
||||||
<SwitchLocaleLink />
|
width="100%"
|
||||||
</>
|
height="100%"
|
||||||
|
style={{
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
flexDirection: 'column',
|
||||||
|
justifyContent: 'space-around',
|
||||||
|
marginRight: '12px',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div style={{ marginRight: 12 }}>
|
||||||
|
<NFT image={metadata.result.image} height={400} />
|
||||||
|
</div>
|
||||||
|
{typeof chainId === 'number' && owner && !ownsNFT ? (
|
||||||
|
<ExternalLink href={getExplorerLink(chainId, owner, ExplorerDataType.ADDRESS)}>
|
||||||
|
<Trans>Owner</Trans>
|
||||||
|
</ExternalLink>
|
||||||
|
) : null}
|
||||||
|
</DarkCard>
|
||||||
|
) : (
|
||||||
|
<DarkCard
|
||||||
|
width="100%"
|
||||||
|
height="100%"
|
||||||
|
style={{
|
||||||
|
marginRight: '12px',
|
||||||
|
minWidth: '340px',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Loader />
|
||||||
|
</DarkCard>
|
||||||
|
)}
|
||||||
|
<AutoColumn gap="sm" style={{ width: '100%', height: '100%' }}>
|
||||||
|
<DarkCard>
|
||||||
|
<AutoColumn gap="md" style={{ width: '100%' }}>
|
||||||
|
<AutoColumn gap="md">
|
||||||
|
<Label>
|
||||||
|
<Trans>Liquidity</Trans>
|
||||||
|
</Label>
|
||||||
|
{fiatValueOfLiquidity?.greaterThan(new Fraction(1, 100)) ? (
|
||||||
|
<ThemedText.LargeHeader fontSize="36px" fontWeight={500}>
|
||||||
|
<Trans>${fiatValueOfLiquidity.toFixed(2, { groupSeparator: ',' })}</Trans>
|
||||||
|
</ThemedText.LargeHeader>
|
||||||
|
) : (
|
||||||
|
<ThemedText.LargeHeader color={theme.text1} fontSize="36px" fontWeight={500}>
|
||||||
|
<Trans>$-</Trans>
|
||||||
|
</ThemedText.LargeHeader>
|
||||||
|
)}
|
||||||
|
</AutoColumn>
|
||||||
|
<LightCard padding="12px 16px">
|
||||||
|
<AutoColumn gap="md">
|
||||||
|
<RowBetween>
|
||||||
|
<LinkedCurrency chainId={chainId} currency={currencyQuote} />
|
||||||
|
<RowFixed>
|
||||||
|
<ThemedText.Main>
|
||||||
|
{inverted ? position?.amount0.toSignificant(4) : position?.amount1.toSignificant(4)}
|
||||||
|
</ThemedText.Main>
|
||||||
|
{typeof ratio === 'number' && !removed ? (
|
||||||
|
<Badge style={{ marginLeft: '10px' }}>
|
||||||
|
<ThemedText.Main fontSize={11}>
|
||||||
|
<Trans>{inverted ? ratio : 100 - ratio}%</Trans>
|
||||||
|
</ThemedText.Main>
|
||||||
|
</Badge>
|
||||||
|
) : null}
|
||||||
|
</RowFixed>
|
||||||
|
</RowBetween>
|
||||||
|
<RowBetween>
|
||||||
|
<LinkedCurrency chainId={chainId} currency={currencyBase} />
|
||||||
|
<RowFixed>
|
||||||
|
<ThemedText.Main>
|
||||||
|
{inverted ? position?.amount1.toSignificant(4) : position?.amount0.toSignificant(4)}
|
||||||
|
</ThemedText.Main>
|
||||||
|
{typeof ratio === 'number' && !removed ? (
|
||||||
|
<Badge style={{ marginLeft: '10px' }}>
|
||||||
|
<ThemedText.Main color={theme.text2} fontSize={11}>
|
||||||
|
<Trans>{inverted ? 100 - ratio : ratio}%</Trans>
|
||||||
|
</ThemedText.Main>
|
||||||
|
</Badge>
|
||||||
|
) : null}
|
||||||
|
</RowFixed>
|
||||||
|
</RowBetween>
|
||||||
|
</AutoColumn>
|
||||||
|
</LightCard>
|
||||||
|
</AutoColumn>
|
||||||
|
</DarkCard>
|
||||||
|
<DarkCard>
|
||||||
|
<AutoColumn gap="md" style={{ width: '100%' }}>
|
||||||
|
<AutoColumn gap="md">
|
||||||
|
<RowBetween style={{ alignItems: 'flex-start' }}>
|
||||||
|
<AutoColumn gap="md">
|
||||||
|
<Label>
|
||||||
|
<Trans>Unclaimed fees</Trans>
|
||||||
|
</Label>
|
||||||
|
{fiatValueOfFees?.greaterThan(new Fraction(1, 100)) ? (
|
||||||
|
<ThemedText.LargeHeader color={theme.green1} fontSize="36px" fontWeight={500}>
|
||||||
|
<Trans>${fiatValueOfFees.toFixed(2, { groupSeparator: ',' })}</Trans>
|
||||||
|
</ThemedText.LargeHeader>
|
||||||
|
) : (
|
||||||
|
<ThemedText.LargeHeader color={theme.text1} fontSize="36px" fontWeight={500}>
|
||||||
|
<Trans>$-</Trans>
|
||||||
|
</ThemedText.LargeHeader>
|
||||||
|
)}
|
||||||
|
</AutoColumn>
|
||||||
|
{ownsNFT &&
|
||||||
|
(feeValue0?.greaterThan(0) || feeValue1?.greaterThan(0) || !!collectMigrationHash) ? (
|
||||||
|
<ButtonConfirmed
|
||||||
|
disabled={collecting || !!collectMigrationHash}
|
||||||
|
confirmed={!!collectMigrationHash && !isCollectPending}
|
||||||
|
width="fit-content"
|
||||||
|
style={{ borderRadius: '12px' }}
|
||||||
|
padding="4px 8px"
|
||||||
|
onClick={() => setShowConfirm(true)}
|
||||||
|
>
|
||||||
|
{!!collectMigrationHash && !isCollectPending ? (
|
||||||
|
<ThemedText.Main color={theme.text1}>
|
||||||
|
<Trans> Collected</Trans>
|
||||||
|
</ThemedText.Main>
|
||||||
|
) : isCollectPending || collecting ? (
|
||||||
|
<ThemedText.Main color={theme.text1}>
|
||||||
|
{' '}
|
||||||
|
<Dots>
|
||||||
|
<Trans>Collecting</Trans>
|
||||||
|
</Dots>
|
||||||
|
</ThemedText.Main>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<ThemedText.Main color={theme.white}>
|
||||||
|
<Trans>Collect fees</Trans>
|
||||||
|
</ThemedText.Main>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</ButtonConfirmed>
|
||||||
|
) : null}
|
||||||
|
</RowBetween>
|
||||||
|
</AutoColumn>
|
||||||
|
<LightCard padding="12px 16px">
|
||||||
|
<AutoColumn gap="md">
|
||||||
|
<RowBetween>
|
||||||
|
<RowFixed>
|
||||||
|
<CurrencyLogo
|
||||||
|
currency={feeValueUpper?.currency}
|
||||||
|
size={'20px'}
|
||||||
|
style={{ marginRight: '0.5rem' }}
|
||||||
|
/>
|
||||||
|
<ThemedText.Main>{feeValueUpper?.currency?.symbol}</ThemedText.Main>
|
||||||
|
</RowFixed>
|
||||||
|
<RowFixed>
|
||||||
|
<ThemedText.Main>
|
||||||
|
{feeValueUpper ? formatCurrencyAmount(feeValueUpper, 4) : '-'}
|
||||||
|
</ThemedText.Main>
|
||||||
|
</RowFixed>
|
||||||
|
</RowBetween>
|
||||||
|
<RowBetween>
|
||||||
|
<RowFixed>
|
||||||
|
<CurrencyLogo
|
||||||
|
currency={feeValueLower?.currency}
|
||||||
|
size={'20px'}
|
||||||
|
style={{ marginRight: '0.5rem' }}
|
||||||
|
/>
|
||||||
|
<ThemedText.Main>{feeValueLower?.currency?.symbol}</ThemedText.Main>
|
||||||
|
</RowFixed>
|
||||||
|
<RowFixed>
|
||||||
|
<ThemedText.Main>
|
||||||
|
{feeValueLower ? formatCurrencyAmount(feeValueLower, 4) : '-'}
|
||||||
|
</ThemedText.Main>
|
||||||
|
</RowFixed>
|
||||||
|
</RowBetween>
|
||||||
|
</AutoColumn>
|
||||||
|
</LightCard>
|
||||||
|
{showCollectAsWeth && (
|
||||||
|
<AutoColumn gap="md">
|
||||||
|
<RowBetween>
|
||||||
|
<ThemedText.Main>
|
||||||
|
<Trans>Collect as {nativeWrappedSymbol}</Trans>
|
||||||
|
</ThemedText.Main>
|
||||||
|
<Toggle
|
||||||
|
id="receive-as-weth"
|
||||||
|
isActive={receiveWETH}
|
||||||
|
toggle={() => setReceiveWETH((receiveWETH) => !receiveWETH)}
|
||||||
|
/>
|
||||||
|
</RowBetween>
|
||||||
|
</AutoColumn>
|
||||||
|
)}
|
||||||
|
</AutoColumn>
|
||||||
|
</DarkCard>
|
||||||
|
</AutoColumn>
|
||||||
|
</ResponsiveRow>
|
||||||
|
<DarkCard>
|
||||||
|
<AutoColumn gap="md">
|
||||||
|
<RowBetween>
|
||||||
|
<RowFixed>
|
||||||
|
<Label display="flex" style={{ marginRight: '12px' }}>
|
||||||
|
<Trans>Price range</Trans>
|
||||||
|
</Label>
|
||||||
|
<HideExtraSmall>
|
||||||
|
<>
|
||||||
|
<RangeBadge removed={removed} inRange={inRange} />
|
||||||
|
<span style={{ width: '8px' }} />
|
||||||
|
</>
|
||||||
|
</HideExtraSmall>
|
||||||
|
</RowFixed>
|
||||||
|
<RowFixed>
|
||||||
|
{currencyBase && currencyQuote && (
|
||||||
|
<RateToggle
|
||||||
|
currencyA={currencyBase}
|
||||||
|
currencyB={currencyQuote}
|
||||||
|
handleRateToggle={() => setManuallyInverted(!manuallyInverted)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</RowFixed>
|
||||||
|
</RowBetween>
|
||||||
|
|
||||||
|
<RowBetween>
|
||||||
|
<LightCard padding="12px" width="100%">
|
||||||
|
<AutoColumn gap="8px" justify="center">
|
||||||
|
<ExtentsText>
|
||||||
|
<Trans>Min price</Trans>
|
||||||
|
</ExtentsText>
|
||||||
|
<ThemedText.MediumHeader textAlign="center">
|
||||||
|
{formatTickPrice(priceLower, tickAtLimit, Bound.LOWER)}
|
||||||
|
</ThemedText.MediumHeader>
|
||||||
|
<ExtentsText>
|
||||||
|
{' '}
|
||||||
|
<Trans>
|
||||||
|
{currencyQuote?.symbol} per {currencyBase?.symbol}
|
||||||
|
</Trans>
|
||||||
|
</ExtentsText>
|
||||||
|
|
||||||
|
{inRange && (
|
||||||
|
<ThemedText.Small color={theme.text3}>
|
||||||
|
<Trans>Your position will be 100% {currencyBase?.symbol} at this price.</Trans>
|
||||||
|
</ThemedText.Small>
|
||||||
|
)}
|
||||||
|
</AutoColumn>
|
||||||
|
</LightCard>
|
||||||
|
|
||||||
|
<DoubleArrow>⟷</DoubleArrow>
|
||||||
|
<LightCard padding="12px" width="100%">
|
||||||
|
<AutoColumn gap="8px" justify="center">
|
||||||
|
<ExtentsText>
|
||||||
|
<Trans>Max price</Trans>
|
||||||
|
</ExtentsText>
|
||||||
|
<ThemedText.MediumHeader textAlign="center">
|
||||||
|
{formatTickPrice(priceUpper, tickAtLimit, Bound.UPPER)}
|
||||||
|
</ThemedText.MediumHeader>
|
||||||
|
<ExtentsText>
|
||||||
|
{' '}
|
||||||
|
<Trans>
|
||||||
|
{currencyQuote?.symbol} per {currencyBase?.symbol}
|
||||||
|
</Trans>
|
||||||
|
</ExtentsText>
|
||||||
|
|
||||||
|
{inRange && (
|
||||||
|
<ThemedText.Small color={theme.text3}>
|
||||||
|
<Trans>Your position will be 100% {currencyQuote?.symbol} at this price.</Trans>
|
||||||
|
</ThemedText.Small>
|
||||||
|
)}
|
||||||
|
</AutoColumn>
|
||||||
|
</LightCard>
|
||||||
|
</RowBetween>
|
||||||
|
<CurrentPriceCard
|
||||||
|
inverted={inverted}
|
||||||
|
pool={pool}
|
||||||
|
currencyQuote={currencyQuote}
|
||||||
|
currencyBase={currencyBase}
|
||||||
|
/>
|
||||||
|
</AutoColumn>
|
||||||
|
</DarkCard>
|
||||||
|
</AutoColumn>
|
||||||
|
</PageWrapper>
|
||||||
|
<SwitchLocaleLink />
|
||||||
|
</>
|
||||||
|
</Trace>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import { Trans } from '@lingui/macro'
|
import { Trans } from '@lingui/macro'
|
||||||
import { useWeb3React } from '@web3-react/core'
|
import { useWeb3React } from '@web3-react/core'
|
||||||
|
import { PageName } from 'components/AmplitudeAnalytics/constants'
|
||||||
|
import { Trace } from 'components/AmplitudeAnalytics/Trace'
|
||||||
import { ButtonGray, ButtonPrimary, ButtonText } from 'components/Button'
|
import { ButtonGray, ButtonPrimary, ButtonText } from 'components/Button'
|
||||||
import { AutoColumn } from 'components/Column'
|
import { AutoColumn } from 'components/Column'
|
||||||
import { FlyoutAlignment, NewMenu } from 'components/Menu'
|
import { FlyoutAlignment, NewMenu } from 'components/Menu'
|
||||||
@ -252,76 +254,78 @@ export default function Pool() {
|
|||||||
]
|
]
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<Trace page={PageName.POOL_PAGE} shouldLogImpression>
|
||||||
<PageWrapper>
|
<>
|
||||||
<SwapPoolTabs active="pool" />
|
<PageWrapper>
|
||||||
<AutoColumn gap="lg" justify="center">
|
<SwapPoolTabs active="pool" />
|
||||||
<AutoColumn gap="lg" style={{ width: '100%' }}>
|
<AutoColumn gap="lg" justify="center">
|
||||||
<TitleRow style={{ marginTop: '1rem' }} padding={'0'}>
|
<AutoColumn gap="lg" style={{ width: '100%' }}>
|
||||||
<ThemedText.Body fontSize={'20px'}>
|
<TitleRow style={{ marginTop: '1rem' }} padding={'0'}>
|
||||||
<Trans>Pools Overview</Trans>
|
<ThemedText.Body fontSize={'20px'}>
|
||||||
</ThemedText.Body>
|
<Trans>Pools Overview</Trans>
|
||||||
<ButtonRow>
|
</ThemedText.Body>
|
||||||
{showV2Features && (
|
<ButtonRow>
|
||||||
<Menu
|
{showV2Features && (
|
||||||
menuItems={menuItems}
|
<Menu
|
||||||
flyoutAlignment={FlyoutAlignment.LEFT}
|
menuItems={menuItems}
|
||||||
ToggleUI={(props: any) => (
|
flyoutAlignment={FlyoutAlignment.LEFT}
|
||||||
<MoreOptionsButton {...props}>
|
ToggleUI={(props: any) => (
|
||||||
<MoreOptionsText>
|
<MoreOptionsButton {...props}>
|
||||||
<Trans>More</Trans>
|
<MoreOptionsText>
|
||||||
<ChevronDown size={15} />
|
<Trans>More</Trans>
|
||||||
</MoreOptionsText>
|
<ChevronDown size={15} />
|
||||||
</MoreOptionsButton>
|
</MoreOptionsText>
|
||||||
)}
|
</MoreOptionsButton>
|
||||||
/>
|
)}
|
||||||
)}
|
/>
|
||||||
<ResponsiveButtonPrimary id="join-pool-button" as={Link} to="/add/ETH">
|
)}
|
||||||
+ <Trans>New Position</Trans>
|
<ResponsiveButtonPrimary id="join-pool-button" as={Link} to="/add/ETH">
|
||||||
</ResponsiveButtonPrimary>
|
+ <Trans>New Position</Trans>
|
||||||
</ButtonRow>
|
</ResponsiveButtonPrimary>
|
||||||
</TitleRow>
|
</ButtonRow>
|
||||||
|
</TitleRow>
|
||||||
|
|
||||||
<MainContentWrapper>
|
<MainContentWrapper>
|
||||||
{positionsLoading ? (
|
{positionsLoading ? (
|
||||||
<PositionsLoadingPlaceholder />
|
<PositionsLoadingPlaceholder />
|
||||||
) : filteredPositions && closedPositions && filteredPositions.length > 0 ? (
|
) : filteredPositions && closedPositions && filteredPositions.length > 0 ? (
|
||||||
<PositionList
|
<PositionList
|
||||||
positions={filteredPositions}
|
positions={filteredPositions}
|
||||||
setUserHideClosedPositions={setUserHideClosedPositions}
|
setUserHideClosedPositions={setUserHideClosedPositions}
|
||||||
userHideClosedPositions={userHideClosedPositions}
|
userHideClosedPositions={userHideClosedPositions}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<ErrorContainer>
|
<ErrorContainer>
|
||||||
<ThemedText.Body color={theme.text3} textAlign="center">
|
<ThemedText.Body color={theme.text3} textAlign="center">
|
||||||
<InboxIcon strokeWidth={1} />
|
<InboxIcon strokeWidth={1} />
|
||||||
<div>
|
<div>
|
||||||
<Trans>Your active V3 liquidity positions will appear here.</Trans>
|
<Trans>Your active V3 liquidity positions will appear here.</Trans>
|
||||||
</div>
|
</div>
|
||||||
</ThemedText.Body>
|
</ThemedText.Body>
|
||||||
{!showConnectAWallet && closedPositions.length > 0 && (
|
{!showConnectAWallet && closedPositions.length > 0 && (
|
||||||
<ButtonText
|
<ButtonText
|
||||||
style={{ marginTop: '.5rem' }}
|
style={{ marginTop: '.5rem' }}
|
||||||
onClick={() => setUserHideClosedPositions(!userHideClosedPositions)}
|
onClick={() => setUserHideClosedPositions(!userHideClosedPositions)}
|
||||||
>
|
>
|
||||||
<Trans>Show closed positions</Trans>
|
<Trans>Show closed positions</Trans>
|
||||||
</ButtonText>
|
</ButtonText>
|
||||||
)}
|
)}
|
||||||
{showConnectAWallet && (
|
{showConnectAWallet && (
|
||||||
<ButtonPrimary style={{ marginTop: '2em', padding: '8px 16px' }} onClick={toggleWalletModal}>
|
<ButtonPrimary style={{ marginTop: '2em', padding: '8px 16px' }} onClick={toggleWalletModal}>
|
||||||
<Trans>Connect a wallet</Trans>
|
<Trans>Connect a wallet</Trans>
|
||||||
</ButtonPrimary>
|
</ButtonPrimary>
|
||||||
)}
|
)}
|
||||||
</ErrorContainer>
|
</ErrorContainer>
|
||||||
)}
|
)}
|
||||||
</MainContentWrapper>
|
</MainContentWrapper>
|
||||||
<HideSmall>
|
<HideSmall>
|
||||||
<CTACards />
|
<CTACards />
|
||||||
</HideSmall>
|
</HideSmall>
|
||||||
|
</AutoColumn>
|
||||||
</AutoColumn>
|
</AutoColumn>
|
||||||
</AutoColumn>
|
</PageWrapper>
|
||||||
</PageWrapper>
|
<SwitchLocaleLink />
|
||||||
<SwitchLocaleLink />
|
</>
|
||||||
</>
|
</Trace>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import { Trans } from '@lingui/macro'
|
import { Trans } from '@lingui/macro'
|
||||||
import { Pair } from '@uniswap/v2-sdk'
|
import { Pair } from '@uniswap/v2-sdk'
|
||||||
import { useWeb3React } from '@web3-react/core'
|
import { useWeb3React } from '@web3-react/core'
|
||||||
|
import { PageName } from 'components/AmplitudeAnalytics/constants'
|
||||||
|
import { Trace } from 'components/AmplitudeAnalytics/Trace'
|
||||||
import { UNSUPPORTED_V2POOL_CHAIN_IDS } from 'constants/chains'
|
import { UNSUPPORTED_V2POOL_CHAIN_IDS } from 'constants/chains'
|
||||||
import JSBI from 'jsbi'
|
import JSBI from 'jsbi'
|
||||||
import { useContext, useMemo } from 'react'
|
import { useContext, useMemo } from 'react'
|
||||||
@ -135,147 +137,149 @@ export default function Pool() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<Trace page={PageName.POOL_PAGE} shouldLogImpression>
|
||||||
<PageWrapper>
|
<>
|
||||||
<SwapPoolTabs active={'pool'} />
|
<PageWrapper>
|
||||||
<VoteCard>
|
<SwapPoolTabs active={'pool'} />
|
||||||
<CardBGImage />
|
<VoteCard>
|
||||||
<CardNoise />
|
<CardBGImage />
|
||||||
<CardSection>
|
<CardNoise />
|
||||||
<AutoColumn gap="md">
|
<CardSection>
|
||||||
<RowBetween>
|
<AutoColumn gap="md">
|
||||||
<ThemedText.White fontWeight={600}>
|
<RowBetween>
|
||||||
<Trans>Liquidity provider rewards</Trans>
|
<ThemedText.White fontWeight={600}>
|
||||||
</ThemedText.White>
|
<Trans>Liquidity provider rewards</Trans>
|
||||||
</RowBetween>
|
</ThemedText.White>
|
||||||
<RowBetween>
|
</RowBetween>
|
||||||
<ThemedText.White fontSize={14}>
|
<RowBetween>
|
||||||
<Trans>
|
<ThemedText.White fontSize={14}>
|
||||||
Liquidity providers earn a 0.3% fee on all trades proportional to their share of the pool. Fees are
|
<Trans>
|
||||||
added to the pool, accrue in real time and can be claimed by withdrawing your liquidity.
|
Liquidity providers earn a 0.3% fee on all trades proportional to their share of the pool. Fees
|
||||||
</Trans>
|
are added to the pool, accrue in real time and can be claimed by withdrawing your liquidity.
|
||||||
</ThemedText.White>
|
</Trans>
|
||||||
</RowBetween>
|
</ThemedText.White>
|
||||||
<ExternalLink
|
</RowBetween>
|
||||||
style={{ color: 'white', textDecoration: 'underline' }}
|
<ExternalLink
|
||||||
target="_blank"
|
style={{ color: 'white', textDecoration: 'underline' }}
|
||||||
href="https://uniswap.org/docs/v2/core-concepts/pools/"
|
target="_blank"
|
||||||
>
|
href="https://uniswap.org/docs/v2/core-concepts/pools/"
|
||||||
<ThemedText.White fontSize={14}>
|
>
|
||||||
<Trans>Read more about providing liquidity</Trans>
|
<ThemedText.White fontSize={14}>
|
||||||
</ThemedText.White>
|
<Trans>Read more about providing liquidity</Trans>
|
||||||
</ExternalLink>
|
</ThemedText.White>
|
||||||
</AutoColumn>
|
</ExternalLink>
|
||||||
</CardSection>
|
</AutoColumn>
|
||||||
<CardBGImage />
|
</CardSection>
|
||||||
<CardNoise />
|
<CardBGImage />
|
||||||
</VoteCard>
|
<CardNoise />
|
||||||
|
</VoteCard>
|
||||||
|
|
||||||
{unsupportedV2Network ? (
|
{unsupportedV2Network ? (
|
||||||
<AutoColumn gap="lg" justify="center">
|
<AutoColumn gap="lg" justify="center">
|
||||||
<AutoColumn gap="md" style={{ width: '100%' }}>
|
<AutoColumn gap="md" style={{ width: '100%' }}>
|
||||||
<Layer2Prompt>
|
<Layer2Prompt>
|
||||||
<ThemedText.Body color={theme.text3} textAlign="center">
|
<ThemedText.Body color={theme.text3} textAlign="center">
|
||||||
<Trans>V2 Pool is not available on Layer 2. Switch to Layer 1 Ethereum.</Trans>
|
<Trans>V2 Pool is not available on Layer 2. Switch to Layer 1 Ethereum.</Trans>
|
||||||
</ThemedText.Body>
|
</ThemedText.Body>
|
||||||
</Layer2Prompt>
|
</Layer2Prompt>
|
||||||
|
</AutoColumn>
|
||||||
</AutoColumn>
|
</AutoColumn>
|
||||||
</AutoColumn>
|
) : (
|
||||||
) : (
|
<AutoColumn gap="lg" justify="center">
|
||||||
<AutoColumn gap="lg" justify="center">
|
<AutoColumn gap="md" style={{ width: '100%' }}>
|
||||||
<AutoColumn gap="md" style={{ width: '100%' }}>
|
<TitleRow style={{ marginTop: '1rem' }} padding={'0'}>
|
||||||
<TitleRow style={{ marginTop: '1rem' }} padding={'0'}>
|
<HideSmall>
|
||||||
<HideSmall>
|
<ThemedText.MediumHeader style={{ marginTop: '0.5rem', justifySelf: 'flex-start' }}>
|
||||||
<ThemedText.MediumHeader style={{ marginTop: '0.5rem', justifySelf: 'flex-start' }}>
|
<Trans>Your V2 liquidity</Trans>
|
||||||
<Trans>Your V2 liquidity</Trans>
|
</ThemedText.MediumHeader>
|
||||||
</ThemedText.MediumHeader>
|
</HideSmall>
|
||||||
</HideSmall>
|
<ButtonRow>
|
||||||
<ButtonRow>
|
<ResponsiveButtonSecondary as={Link} padding="6px 8px" to="/add/v2/ETH">
|
||||||
<ResponsiveButtonSecondary as={Link} padding="6px 8px" to="/add/v2/ETH">
|
<Trans>Create a pair</Trans>
|
||||||
<Trans>Create a pair</Trans>
|
</ResponsiveButtonSecondary>
|
||||||
</ResponsiveButtonSecondary>
|
<ResponsiveButtonPrimary id="find-pool-button" as={Link} to="/pool/v2/find" padding="6px 8px">
|
||||||
<ResponsiveButtonPrimary id="find-pool-button" as={Link} to="/pool/v2/find" padding="6px 8px">
|
<Text fontWeight={500} fontSize={16}>
|
||||||
<Text fontWeight={500} fontSize={16}>
|
<Trans>Import Pool</Trans>
|
||||||
<Trans>Import Pool</Trans>
|
</Text>
|
||||||
</Text>
|
</ResponsiveButtonPrimary>
|
||||||
</ResponsiveButtonPrimary>
|
<ResponsiveButtonPrimary id="join-pool-button" as={Link} to="/add/v2/ETH" padding="6px 8px">
|
||||||
<ResponsiveButtonPrimary id="join-pool-button" as={Link} to="/add/v2/ETH" padding="6px 8px">
|
<Text fontWeight={500} fontSize={16}>
|
||||||
<Text fontWeight={500} fontSize={16}>
|
<Trans>Add V2 Liquidity</Trans>
|
||||||
<Trans>Add V2 Liquidity</Trans>
|
</Text>
|
||||||
</Text>
|
</ResponsiveButtonPrimary>
|
||||||
</ResponsiveButtonPrimary>
|
</ButtonRow>
|
||||||
</ButtonRow>
|
</TitleRow>
|
||||||
</TitleRow>
|
|
||||||
|
|
||||||
{!account ? (
|
{!account ? (
|
||||||
<Card padding="40px">
|
<Card padding="40px">
|
||||||
<ThemedText.Body color={theme.text3} textAlign="center">
|
<ThemedText.Body color={theme.text3} textAlign="center">
|
||||||
<Trans>Connect to a wallet to view your liquidity.</Trans>
|
<Trans>Connect to a wallet to view your liquidity.</Trans>
|
||||||
</ThemedText.Body>
|
</ThemedText.Body>
|
||||||
</Card>
|
</Card>
|
||||||
) : v2IsLoading ? (
|
) : v2IsLoading ? (
|
||||||
<EmptyProposals>
|
<EmptyProposals>
|
||||||
<ThemedText.Body color={theme.text3} textAlign="center">
|
<ThemedText.Body color={theme.text3} textAlign="center">
|
||||||
<Dots>
|
<Dots>
|
||||||
<Trans>Loading</Trans>
|
<Trans>Loading</Trans>
|
||||||
</Dots>
|
</Dots>
|
||||||
</ThemedText.Body>
|
</ThemedText.Body>
|
||||||
</EmptyProposals>
|
</EmptyProposals>
|
||||||
) : allV2PairsWithLiquidity?.length > 0 || stakingPairs?.length > 0 ? (
|
) : allV2PairsWithLiquidity?.length > 0 || stakingPairs?.length > 0 ? (
|
||||||
<>
|
<>
|
||||||
<ButtonSecondary>
|
<ButtonSecondary>
|
||||||
<RowBetween>
|
<RowBetween>
|
||||||
<Trans>
|
<Trans>
|
||||||
<ExternalLink href={'https://v2.info.uniswap.org/account/' + account}>
|
<ExternalLink href={'https://v2.info.uniswap.org/account/' + account}>
|
||||||
Account analytics and accrued fees
|
Account analytics and accrued fees
|
||||||
</ExternalLink>
|
</ExternalLink>
|
||||||
<span> ↗ </span>
|
<span> ↗ </span>
|
||||||
</Trans>
|
</Trans>
|
||||||
</RowBetween>
|
</RowBetween>
|
||||||
</ButtonSecondary>
|
</ButtonSecondary>
|
||||||
{v2PairsWithoutStakedAmount.map((v2Pair) => (
|
{v2PairsWithoutStakedAmount.map((v2Pair) => (
|
||||||
<FullPositionCard key={v2Pair.liquidityToken.address} pair={v2Pair} />
|
<FullPositionCard key={v2Pair.liquidityToken.address} pair={v2Pair} />
|
||||||
))}
|
))}
|
||||||
{stakingPairs.map(
|
{stakingPairs.map(
|
||||||
(stakingPair, i) =>
|
(stakingPair, i) =>
|
||||||
stakingPair[1] && ( // skip pairs that arent loaded
|
stakingPair[1] && ( // skip pairs that arent loaded
|
||||||
<FullPositionCard
|
<FullPositionCard
|
||||||
key={stakingInfosWithBalance[i].stakingRewardAddress}
|
key={stakingInfosWithBalance[i].stakingRewardAddress}
|
||||||
pair={stakingPair[1]}
|
pair={stakingPair[1]}
|
||||||
stakedBalance={stakingInfosWithBalance[i].stakedAmount}
|
stakedBalance={stakingInfosWithBalance[i].stakedAmount}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
)}
|
)}
|
||||||
<RowFixed justify="center" style={{ width: '100%' }}>
|
<RowFixed justify="center" style={{ width: '100%' }}>
|
||||||
<ButtonOutlined
|
<ButtonOutlined
|
||||||
as={Link}
|
as={Link}
|
||||||
to="/migrate/v2"
|
to="/migrate/v2"
|
||||||
id="import-pool-link"
|
id="import-pool-link"
|
||||||
style={{
|
style={{
|
||||||
padding: '8px 16px',
|
padding: '8px 16px',
|
||||||
margin: '0 4px',
|
margin: '0 4px',
|
||||||
borderRadius: '12px',
|
borderRadius: '12px',
|
||||||
width: 'fit-content',
|
width: 'fit-content',
|
||||||
fontSize: '14px',
|
fontSize: '14px',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ChevronsRight size={16} style={{ marginRight: '8px' }} />
|
<ChevronsRight size={16} style={{ marginRight: '8px' }} />
|
||||||
<Trans>Migrate Liquidity to V3</Trans>
|
<Trans>Migrate Liquidity to V3</Trans>
|
||||||
</ButtonOutlined>
|
</ButtonOutlined>
|
||||||
</RowFixed>
|
</RowFixed>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<EmptyProposals>
|
<EmptyProposals>
|
||||||
<ThemedText.Body color={theme.text3} textAlign="center">
|
<ThemedText.Body color={theme.text3} textAlign="center">
|
||||||
<Trans>No liquidity found.</Trans>
|
<Trans>No liquidity found.</Trans>
|
||||||
</ThemedText.Body>
|
</ThemedText.Body>
|
||||||
</EmptyProposals>
|
</EmptyProposals>
|
||||||
)}
|
)}
|
||||||
|
</AutoColumn>
|
||||||
</AutoColumn>
|
</AutoColumn>
|
||||||
</AutoColumn>
|
)}
|
||||||
)}
|
</PageWrapper>
|
||||||
</PageWrapper>
|
<SwitchLocaleLink />
|
||||||
<SwitchLocaleLink />
|
</>
|
||||||
</>
|
</Trace>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import { Trans } from '@lingui/macro'
|
import { Trans } from '@lingui/macro'
|
||||||
import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core'
|
import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core'
|
||||||
import { useWeb3React } from '@web3-react/core'
|
import { useWeb3React } from '@web3-react/core'
|
||||||
|
import { PageName } from 'components/AmplitudeAnalytics/constants'
|
||||||
|
import { Trace } from 'components/AmplitudeAnalytics/Trace'
|
||||||
import JSBI from 'jsbi'
|
import JSBI from 'jsbi'
|
||||||
import { useCallback, useEffect, useState } from 'react'
|
import { useCallback, useEffect, useState } from 'react'
|
||||||
import { Plus } from 'react-feather'
|
import { Plus } from 'react-feather'
|
||||||
@ -95,139 +97,141 @@ export default function PoolFinder() {
|
|||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<Trace page={PageName.POOL_PAGE} shouldLogImpression>
|
||||||
<AppBody>
|
<>
|
||||||
<FindPoolTabs origin={query.get('origin') ?? '/pool/v2'} />
|
<AppBody>
|
||||||
<AutoColumn style={{ padding: '1rem' }} gap="md">
|
<FindPoolTabs origin={query.get('origin') ?? '/pool/v2'} />
|
||||||
<BlueCard>
|
<AutoColumn style={{ padding: '1rem' }} gap="md">
|
||||||
<AutoColumn gap="10px">
|
<BlueCard>
|
||||||
<ThemedText.Link fontWeight={400} color={'primaryText1'}>
|
<AutoColumn gap="10px">
|
||||||
<Trans>
|
<ThemedText.Link fontWeight={400} color={'primaryText1'}>
|
||||||
<b>Tip:</b> Use this tool to find v2 pools that don't automatically appear in the interface.
|
<Trans>
|
||||||
</Trans>
|
<b>Tip:</b> Use this tool to find v2 pools that don't automatically appear in the interface.
|
||||||
</ThemedText.Link>
|
</Trans>
|
||||||
</AutoColumn>
|
</ThemedText.Link>
|
||||||
</BlueCard>
|
</AutoColumn>
|
||||||
<ButtonDropdownLight
|
</BlueCard>
|
||||||
onClick={() => {
|
<ButtonDropdownLight
|
||||||
setShowSearch(true)
|
onClick={() => {
|
||||||
setActiveField(Fields.TOKEN0)
|
setShowSearch(true)
|
||||||
}}
|
setActiveField(Fields.TOKEN0)
|
||||||
>
|
}}
|
||||||
{currency0 ? (
|
|
||||||
<Row>
|
|
||||||
<CurrencyLogo currency={currency0} />
|
|
||||||
<Text fontWeight={500} fontSize={20} marginLeft={'12px'}>
|
|
||||||
{currency0.symbol}
|
|
||||||
</Text>
|
|
||||||
</Row>
|
|
||||||
) : (
|
|
||||||
<Text fontWeight={500} fontSize={20} marginLeft={'12px'}>
|
|
||||||
<Trans>Select a token</Trans>
|
|
||||||
</Text>
|
|
||||||
)}
|
|
||||||
</ButtonDropdownLight>
|
|
||||||
|
|
||||||
<ColumnCenter>
|
|
||||||
<Plus size="16" color="#888D9B" />
|
|
||||||
</ColumnCenter>
|
|
||||||
|
|
||||||
<ButtonDropdownLight
|
|
||||||
onClick={() => {
|
|
||||||
setShowSearch(true)
|
|
||||||
setActiveField(Fields.TOKEN1)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{currency1 ? (
|
|
||||||
<Row>
|
|
||||||
<CurrencyLogo currency={currency1} />
|
|
||||||
<Text fontWeight={500} fontSize={20} marginLeft={'12px'}>
|
|
||||||
{currency1.symbol}
|
|
||||||
</Text>
|
|
||||||
</Row>
|
|
||||||
) : (
|
|
||||||
<Text fontWeight={500} fontSize={20} marginLeft={'12px'}>
|
|
||||||
<Trans>Select a token</Trans>
|
|
||||||
</Text>
|
|
||||||
)}
|
|
||||||
</ButtonDropdownLight>
|
|
||||||
|
|
||||||
{hasPosition && (
|
|
||||||
<ColumnCenter
|
|
||||||
style={{ justifyItems: 'center', backgroundColor: '', padding: '12px 0px', borderRadius: '12px' }}
|
|
||||||
>
|
>
|
||||||
<Text textAlign="center" fontWeight={500}>
|
{currency0 ? (
|
||||||
<Trans>Pool Found!</Trans>
|
<Row>
|
||||||
</Text>
|
<CurrencyLogo currency={currency0} />
|
||||||
<StyledInternalLink to={`/pool/v2`}>
|
<Text fontWeight={500} fontSize={20} marginLeft={'12px'}>
|
||||||
<Text textAlign="center">
|
{currency0.symbol}
|
||||||
<Trans>Manage this pool.</Trans>
|
</Text>
|
||||||
</Text>
|
</Row>
|
||||||
</StyledInternalLink>
|
|
||||||
</ColumnCenter>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{currency0 && currency1 ? (
|
|
||||||
pairState === PairState.EXISTS ? (
|
|
||||||
hasPosition && pair ? (
|
|
||||||
<MinimalPositionCard pair={pair} border="1px solid #CED0D9" />
|
|
||||||
) : (
|
) : (
|
||||||
|
<Text fontWeight={500} fontSize={20} marginLeft={'12px'}>
|
||||||
|
<Trans>Select a token</Trans>
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
</ButtonDropdownLight>
|
||||||
|
|
||||||
|
<ColumnCenter>
|
||||||
|
<Plus size="16" color="#888D9B" />
|
||||||
|
</ColumnCenter>
|
||||||
|
|
||||||
|
<ButtonDropdownLight
|
||||||
|
onClick={() => {
|
||||||
|
setShowSearch(true)
|
||||||
|
setActiveField(Fields.TOKEN1)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{currency1 ? (
|
||||||
|
<Row>
|
||||||
|
<CurrencyLogo currency={currency1} />
|
||||||
|
<Text fontWeight={500} fontSize={20} marginLeft={'12px'}>
|
||||||
|
{currency1.symbol}
|
||||||
|
</Text>
|
||||||
|
</Row>
|
||||||
|
) : (
|
||||||
|
<Text fontWeight={500} fontSize={20} marginLeft={'12px'}>
|
||||||
|
<Trans>Select a token</Trans>
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
</ButtonDropdownLight>
|
||||||
|
|
||||||
|
{hasPosition && (
|
||||||
|
<ColumnCenter
|
||||||
|
style={{ justifyItems: 'center', backgroundColor: '', padding: '12px 0px', borderRadius: '12px' }}
|
||||||
|
>
|
||||||
|
<Text textAlign="center" fontWeight={500}>
|
||||||
|
<Trans>Pool Found!</Trans>
|
||||||
|
</Text>
|
||||||
|
<StyledInternalLink to={`/pool/v2`}>
|
||||||
|
<Text textAlign="center">
|
||||||
|
<Trans>Manage this pool.</Trans>
|
||||||
|
</Text>
|
||||||
|
</StyledInternalLink>
|
||||||
|
</ColumnCenter>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{currency0 && currency1 ? (
|
||||||
|
pairState === PairState.EXISTS ? (
|
||||||
|
hasPosition && pair ? (
|
||||||
|
<MinimalPositionCard pair={pair} border="1px solid #CED0D9" />
|
||||||
|
) : (
|
||||||
|
<LightCard padding="45px 10px">
|
||||||
|
<AutoColumn gap="sm" justify="center">
|
||||||
|
<Text textAlign="center">
|
||||||
|
<Trans>You don’t have liquidity in this pool yet.</Trans>
|
||||||
|
</Text>
|
||||||
|
<StyledInternalLink to={`/add/${currencyId(currency0)}/${currencyId(currency1)}`}>
|
||||||
|
<Text textAlign="center">
|
||||||
|
<Trans>Add liquidity.</Trans>
|
||||||
|
</Text>
|
||||||
|
</StyledInternalLink>
|
||||||
|
</AutoColumn>
|
||||||
|
</LightCard>
|
||||||
|
)
|
||||||
|
) : validPairNoLiquidity ? (
|
||||||
<LightCard padding="45px 10px">
|
<LightCard padding="45px 10px">
|
||||||
<AutoColumn gap="sm" justify="center">
|
<AutoColumn gap="sm" justify="center">
|
||||||
<Text textAlign="center">
|
<Text textAlign="center">
|
||||||
<Trans>You don’t have liquidity in this pool yet.</Trans>
|
<Trans>No pool found.</Trans>
|
||||||
</Text>
|
</Text>
|
||||||
<StyledInternalLink to={`/add/${currencyId(currency0)}/${currencyId(currency1)}`}>
|
<StyledInternalLink to={`/add/${currencyId(currency0)}/${currencyId(currency1)}`}>
|
||||||
<Text textAlign="center">
|
<Trans>Create pool.</Trans>
|
||||||
<Trans>Add liquidity.</Trans>
|
|
||||||
</Text>
|
|
||||||
</StyledInternalLink>
|
</StyledInternalLink>
|
||||||
</AutoColumn>
|
</AutoColumn>
|
||||||
</LightCard>
|
</LightCard>
|
||||||
)
|
) : pairState === PairState.INVALID ? (
|
||||||
) : validPairNoLiquidity ? (
|
<LightCard padding="45px 10px">
|
||||||
<LightCard padding="45px 10px">
|
<AutoColumn gap="sm" justify="center">
|
||||||
<AutoColumn gap="sm" justify="center">
|
<Text textAlign="center" fontWeight={500}>
|
||||||
<Text textAlign="center">
|
<Trans>Invalid pair.</Trans>
|
||||||
<Trans>No pool found.</Trans>
|
</Text>
|
||||||
</Text>
|
</AutoColumn>
|
||||||
<StyledInternalLink to={`/add/${currencyId(currency0)}/${currencyId(currency1)}`}>
|
</LightCard>
|
||||||
<Trans>Create pool.</Trans>
|
) : pairState === PairState.LOADING ? (
|
||||||
</StyledInternalLink>
|
<LightCard padding="45px 10px">
|
||||||
</AutoColumn>
|
<AutoColumn gap="sm" justify="center">
|
||||||
</LightCard>
|
<Text textAlign="center">
|
||||||
) : pairState === PairState.INVALID ? (
|
<Trans>Loading</Trans>
|
||||||
<LightCard padding="45px 10px">
|
<Dots />
|
||||||
<AutoColumn gap="sm" justify="center">
|
</Text>
|
||||||
<Text textAlign="center" fontWeight={500}>
|
</AutoColumn>
|
||||||
<Trans>Invalid pair.</Trans>
|
</LightCard>
|
||||||
</Text>
|
) : null
|
||||||
</AutoColumn>
|
) : (
|
||||||
</LightCard>
|
prerequisiteMessage
|
||||||
) : pairState === PairState.LOADING ? (
|
)}
|
||||||
<LightCard padding="45px 10px">
|
</AutoColumn>
|
||||||
<AutoColumn gap="sm" justify="center">
|
|
||||||
<Text textAlign="center">
|
|
||||||
<Trans>Loading</Trans>
|
|
||||||
<Dots />
|
|
||||||
</Text>
|
|
||||||
</AutoColumn>
|
|
||||||
</LightCard>
|
|
||||||
) : null
|
|
||||||
) : (
|
|
||||||
prerequisiteMessage
|
|
||||||
)}
|
|
||||||
</AutoColumn>
|
|
||||||
|
|
||||||
<CurrencySearchModal
|
<CurrencySearchModal
|
||||||
isOpen={showSearch}
|
isOpen={showSearch}
|
||||||
onCurrencySelect={handleCurrencySelect}
|
onCurrencySelect={handleCurrencySelect}
|
||||||
onDismiss={handleSearchDismiss}
|
onDismiss={handleSearchDismiss}
|
||||||
showCommonBases
|
showCommonBases
|
||||||
selectedCurrency={(activeField === Fields.TOKEN0 ? currency1 : currency0) ?? undefined}
|
selectedCurrency={(activeField === Fields.TOKEN0 ? currency1 : currency0) ?? undefined}
|
||||||
/>
|
/>
|
||||||
</AppBody>
|
</AppBody>
|
||||||
<SwitchLocaleLink />
|
<SwitchLocaleLink />
|
||||||
</>
|
</>
|
||||||
|
</Trace>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -398,7 +398,7 @@ export default function Swap({ history }: RouteComponentProps) {
|
|||||||
const priceImpactTooHigh = priceImpactSeverity > 3 && !isExpertMode
|
const priceImpactTooHigh = priceImpactSeverity > 3 && !isExpertMode
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Trace page={PageName.SWAP_PAGE} shouldLogImpression={false}>
|
<Trace page={PageName.SWAP_PAGE} shouldLogImpression>
|
||||||
<>
|
<>
|
||||||
<TokenWarningModal
|
<TokenWarningModal
|
||||||
isOpen={importTokensNotInDefault.length > 0 && !dismissTokenWarning}
|
isOpen={importTokensNotInDefault.length > 0 && !dismissTokenWarning}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import { Trans } from '@lingui/macro'
|
import { Trans } from '@lingui/macro'
|
||||||
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
|
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
|
||||||
import { useWeb3React } from '@web3-react/core'
|
import { useWeb3React } from '@web3-react/core'
|
||||||
|
import { PageName } from 'components/AmplitudeAnalytics/constants'
|
||||||
|
import { Trace } from 'components/AmplitudeAnalytics/Trace'
|
||||||
import { ButtonPrimary } from 'components/Button'
|
import { ButtonPrimary } from 'components/Button'
|
||||||
import { AutoColumn } from 'components/Column'
|
import { AutoColumn } from 'components/Column'
|
||||||
import { CardBGImage, CardNoise, CardSection, DataCard } from 'components/earn/styled'
|
import { CardBGImage, CardNoise, CardSection, DataCard } from 'components/earn/styled'
|
||||||
@ -132,150 +134,155 @@ export default function Landing() {
|
|||||||
)
|
)
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<PageWrapper gap="lg" justify="center">
|
<Trace page={PageName.VOTE_PAGE} shouldLogImpression>
|
||||||
<DelegateModal
|
<PageWrapper gap="lg" justify="center">
|
||||||
isOpen={showDelegateModal}
|
<DelegateModal
|
||||||
onDismiss={toggleDelegateModal}
|
isOpen={showDelegateModal}
|
||||||
title={showUnlockVoting ? <Trans>Unlock Votes</Trans> : <Trans>Update Delegation</Trans>}
|
onDismiss={toggleDelegateModal}
|
||||||
/>
|
title={showUnlockVoting ? <Trans>Unlock Votes</Trans> : <Trans>Update Delegation</Trans>}
|
||||||
<TopSection gap="md">
|
/>
|
||||||
<VoteCard>
|
<TopSection gap="md">
|
||||||
<CardBGImage />
|
<VoteCard>
|
||||||
<CardNoise />
|
<CardBGImage />
|
||||||
<CardSection>
|
<CardNoise />
|
||||||
|
<CardSection>
|
||||||
|
<AutoColumn gap="md">
|
||||||
|
<RowBetween>
|
||||||
|
<ThemedText.White fontWeight={600}>
|
||||||
|
<Trans>Uniswap Governance</Trans>
|
||||||
|
</ThemedText.White>
|
||||||
|
</RowBetween>
|
||||||
|
<RowBetween>
|
||||||
|
<ThemedText.White fontSize={14}>
|
||||||
|
<Trans>
|
||||||
|
UNI tokens represent voting shares in Uniswap governance. You can vote on each proposal yourself
|
||||||
|
or delegate your votes to a third party.
|
||||||
|
</Trans>
|
||||||
|
</ThemedText.White>
|
||||||
|
</RowBetween>
|
||||||
|
<ExternalLink
|
||||||
|
style={{ color: 'white', textDecoration: 'underline' }}
|
||||||
|
href="https://uniswap.org/blog/uni"
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
<ThemedText.White fontSize={14}>
|
||||||
|
<Trans>Read more about Uniswap governance</Trans>
|
||||||
|
</ThemedText.White>
|
||||||
|
</ExternalLink>
|
||||||
|
</AutoColumn>
|
||||||
|
</CardSection>
|
||||||
|
<CardBGImage />
|
||||||
|
<CardNoise />
|
||||||
|
</VoteCard>
|
||||||
|
</TopSection>
|
||||||
|
<TopSection gap="2px">
|
||||||
|
<WrapSmall>
|
||||||
|
<ThemedText.MediumHeader style={{ margin: '0.5rem 0.5rem 0.5rem 0', flexShrink: 0 }}>
|
||||||
|
<Trans>Proposals</Trans>
|
||||||
|
</ThemedText.MediumHeader>
|
||||||
|
<AutoRow gap="6px" justify="flex-end">
|
||||||
|
{loadingProposals || loadingAvailableVotes ? <Loader /> : null}
|
||||||
|
{showUnlockVoting ? (
|
||||||
|
<ButtonPrimary
|
||||||
|
style={{ width: 'fit-content' }}
|
||||||
|
padding="8px"
|
||||||
|
$borderRadius="8px"
|
||||||
|
onClick={toggleDelegateModal}
|
||||||
|
>
|
||||||
|
<Trans>Unlock Voting</Trans>
|
||||||
|
</ButtonPrimary>
|
||||||
|
) : availableVotes && JSBI.notEqual(JSBI.BigInt(0), availableVotes?.quotient) ? (
|
||||||
|
<ThemedText.Body fontWeight={500} mr="6px">
|
||||||
|
<Trans>
|
||||||
|
<FormattedCurrencyAmount currencyAmount={availableVotes} /> Votes
|
||||||
|
</Trans>
|
||||||
|
</ThemedText.Body>
|
||||||
|
) : uniBalance &&
|
||||||
|
userDelegatee &&
|
||||||
|
userDelegatee !== ZERO_ADDRESS &&
|
||||||
|
JSBI.notEqual(JSBI.BigInt(0), uniBalance?.quotient) ? (
|
||||||
|
<ThemedText.Body fontWeight={500} mr="6px">
|
||||||
|
<Trans>
|
||||||
|
<FormattedCurrencyAmount currencyAmount={uniBalance} /> Votes
|
||||||
|
</Trans>
|
||||||
|
</ThemedText.Body>
|
||||||
|
) : (
|
||||||
|
''
|
||||||
|
)}
|
||||||
|
<ButtonPrimary
|
||||||
|
as={Link}
|
||||||
|
to="/create-proposal"
|
||||||
|
style={{ width: 'fit-content', borderRadius: '8px' }}
|
||||||
|
padding="8px"
|
||||||
|
>
|
||||||
|
<Trans>Create Proposal</Trans>
|
||||||
|
</ButtonPrimary>
|
||||||
|
</AutoRow>
|
||||||
|
</WrapSmall>
|
||||||
|
{!showUnlockVoting && (
|
||||||
|
<RowBetween>
|
||||||
|
<div />
|
||||||
|
{userDelegatee && userDelegatee !== ZERO_ADDRESS ? (
|
||||||
|
<RowFixed>
|
||||||
|
<ThemedText.Body fontWeight={500} mr="4px">
|
||||||
|
<Trans>Delegated to:</Trans>
|
||||||
|
</ThemedText.Body>
|
||||||
|
<AddressButton>
|
||||||
|
<StyledExternalLink
|
||||||
|
href={getExplorerLink(1, userDelegatee, ExplorerDataType.ADDRESS)}
|
||||||
|
style={{ margin: '0 4px' }}
|
||||||
|
>
|
||||||
|
{userDelegatee === account ? <Trans>Self</Trans> : shortenAddress(userDelegatee)}
|
||||||
|
</StyledExternalLink>
|
||||||
|
<TextButton onClick={toggleDelegateModal} style={{ marginLeft: '4px' }}>
|
||||||
|
<Trans>(edit)</Trans>
|
||||||
|
</TextButton>
|
||||||
|
</AddressButton>
|
||||||
|
</RowFixed>
|
||||||
|
) : (
|
||||||
|
''
|
||||||
|
)}
|
||||||
|
</RowBetween>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{allProposals?.length === 0 && <ProposalEmptyState />}
|
||||||
|
|
||||||
|
{allProposals?.length > 0 && (
|
||||||
<AutoColumn gap="md">
|
<AutoColumn gap="md">
|
||||||
<RowBetween>
|
<RowBetween>
|
||||||
<ThemedText.White fontWeight={600}>
|
<ThemedText.Main>
|
||||||
<Trans>Uniswap Governance</Trans>
|
<Trans>Show Cancelled</Trans>
|
||||||
</ThemedText.White>
|
</ThemedText.Main>
|
||||||
|
<Toggle
|
||||||
|
isActive={!hideCancelled}
|
||||||
|
toggle={() => setHideCancelled((hideCancelled) => !hideCancelled)}
|
||||||
|
/>
|
||||||
</RowBetween>
|
</RowBetween>
|
||||||
<RowBetween>
|
|
||||||
<ThemedText.White fontSize={14}>
|
|
||||||
<Trans>
|
|
||||||
UNI tokens represent voting shares in Uniswap governance. You can vote on each proposal yourself
|
|
||||||
or delegate your votes to a third party.
|
|
||||||
</Trans>
|
|
||||||
</ThemedText.White>
|
|
||||||
</RowBetween>
|
|
||||||
<ExternalLink
|
|
||||||
style={{ color: 'white', textDecoration: 'underline' }}
|
|
||||||
href="https://uniswap.org/blog/uni"
|
|
||||||
target="_blank"
|
|
||||||
>
|
|
||||||
<ThemedText.White fontSize={14}>
|
|
||||||
<Trans>Read more about Uniswap governance</Trans>
|
|
||||||
</ThemedText.White>
|
|
||||||
</ExternalLink>
|
|
||||||
</AutoColumn>
|
</AutoColumn>
|
||||||
</CardSection>
|
)}
|
||||||
<CardBGImage />
|
|
||||||
<CardNoise />
|
|
||||||
</VoteCard>
|
|
||||||
</TopSection>
|
|
||||||
<TopSection gap="2px">
|
|
||||||
<WrapSmall>
|
|
||||||
<ThemedText.MediumHeader style={{ margin: '0.5rem 0.5rem 0.5rem 0', flexShrink: 0 }}>
|
|
||||||
<Trans>Proposals</Trans>
|
|
||||||
</ThemedText.MediumHeader>
|
|
||||||
<AutoRow gap="6px" justify="flex-end">
|
|
||||||
{loadingProposals || loadingAvailableVotes ? <Loader /> : null}
|
|
||||||
{showUnlockVoting ? (
|
|
||||||
<ButtonPrimary
|
|
||||||
style={{ width: 'fit-content' }}
|
|
||||||
padding="8px"
|
|
||||||
$borderRadius="8px"
|
|
||||||
onClick={toggleDelegateModal}
|
|
||||||
>
|
|
||||||
<Trans>Unlock Voting</Trans>
|
|
||||||
</ButtonPrimary>
|
|
||||||
) : availableVotes && JSBI.notEqual(JSBI.BigInt(0), availableVotes?.quotient) ? (
|
|
||||||
<ThemedText.Body fontWeight={500} mr="6px">
|
|
||||||
<Trans>
|
|
||||||
<FormattedCurrencyAmount currencyAmount={availableVotes} /> Votes
|
|
||||||
</Trans>
|
|
||||||
</ThemedText.Body>
|
|
||||||
) : uniBalance &&
|
|
||||||
userDelegatee &&
|
|
||||||
userDelegatee !== ZERO_ADDRESS &&
|
|
||||||
JSBI.notEqual(JSBI.BigInt(0), uniBalance?.quotient) ? (
|
|
||||||
<ThemedText.Body fontWeight={500} mr="6px">
|
|
||||||
<Trans>
|
|
||||||
<FormattedCurrencyAmount currencyAmount={uniBalance} /> Votes
|
|
||||||
</Trans>
|
|
||||||
</ThemedText.Body>
|
|
||||||
) : (
|
|
||||||
''
|
|
||||||
)}
|
|
||||||
<ButtonPrimary
|
|
||||||
as={Link}
|
|
||||||
to="/create-proposal"
|
|
||||||
style={{ width: 'fit-content', borderRadius: '8px' }}
|
|
||||||
padding="8px"
|
|
||||||
>
|
|
||||||
<Trans>Create Proposal</Trans>
|
|
||||||
</ButtonPrimary>
|
|
||||||
</AutoRow>
|
|
||||||
</WrapSmall>
|
|
||||||
{!showUnlockVoting && (
|
|
||||||
<RowBetween>
|
|
||||||
<div />
|
|
||||||
{userDelegatee && userDelegatee !== ZERO_ADDRESS ? (
|
|
||||||
<RowFixed>
|
|
||||||
<ThemedText.Body fontWeight={500} mr="4px">
|
|
||||||
<Trans>Delegated to:</Trans>
|
|
||||||
</ThemedText.Body>
|
|
||||||
<AddressButton>
|
|
||||||
<StyledExternalLink
|
|
||||||
href={getExplorerLink(1, userDelegatee, ExplorerDataType.ADDRESS)}
|
|
||||||
style={{ margin: '0 4px' }}
|
|
||||||
>
|
|
||||||
{userDelegatee === account ? <Trans>Self</Trans> : shortenAddress(userDelegatee)}
|
|
||||||
</StyledExternalLink>
|
|
||||||
<TextButton onClick={toggleDelegateModal} style={{ marginLeft: '4px' }}>
|
|
||||||
<Trans>(edit)</Trans>
|
|
||||||
</TextButton>
|
|
||||||
</AddressButton>
|
|
||||||
</RowFixed>
|
|
||||||
) : (
|
|
||||||
''
|
|
||||||
)}
|
|
||||||
</RowBetween>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{allProposals?.length === 0 && <ProposalEmptyState />}
|
{allProposals
|
||||||
|
?.slice(0)
|
||||||
|
?.reverse()
|
||||||
|
?.filter((p: ProposalData) => (hideCancelled ? p.status !== ProposalState.CANCELED : true))
|
||||||
|
?.map((p: ProposalData) => {
|
||||||
|
return (
|
||||||
|
<Proposal as={Link} to={`/vote/${p.governorIndex}/${p.id}`} key={`${p.governorIndex}${p.id}`}>
|
||||||
|
<ProposalNumber>
|
||||||
|
{p.governorIndex}.{p.id}
|
||||||
|
</ProposalNumber>
|
||||||
|
<ProposalTitle>{p.title}</ProposalTitle>
|
||||||
|
<ProposalStatus status={p.status} />
|
||||||
|
</Proposal>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</TopSection>
|
||||||
|
|
||||||
{allProposals?.length > 0 && (
|
<ThemedText.SubHeader color="text3">
|
||||||
<AutoColumn gap="md">
|
<Trans>A minimum threshold of 0.25% of the total UNI supply is required to submit proposals</Trans>
|
||||||
<RowBetween>
|
</ThemedText.SubHeader>
|
||||||
<ThemedText.Main>
|
</PageWrapper>
|
||||||
<Trans>Show Cancelled</Trans>
|
</Trace>
|
||||||
</ThemedText.Main>
|
|
||||||
<Toggle isActive={!hideCancelled} toggle={() => setHideCancelled((hideCancelled) => !hideCancelled)} />
|
|
||||||
</RowBetween>
|
|
||||||
</AutoColumn>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{allProposals
|
|
||||||
?.slice(0)
|
|
||||||
?.reverse()
|
|
||||||
?.filter((p: ProposalData) => (hideCancelled ? p.status !== ProposalState.CANCELED : true))
|
|
||||||
?.map((p: ProposalData) => {
|
|
||||||
return (
|
|
||||||
<Proposal as={Link} to={`/vote/${p.governorIndex}/${p.id}`} key={`${p.governorIndex}${p.id}`}>
|
|
||||||
<ProposalNumber>
|
|
||||||
{p.governorIndex}.{p.id}
|
|
||||||
</ProposalNumber>
|
|
||||||
<ProposalTitle>{p.title}</ProposalTitle>
|
|
||||||
<ProposalStatus status={p.status} />
|
|
||||||
</Proposal>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</TopSection>
|
|
||||||
|
|
||||||
<ThemedText.SubHeader color="text3">
|
|
||||||
<Trans>A minimum threshold of 0.25% of the total UNI supply is required to submit proposals</Trans>
|
|
||||||
</ThemedText.SubHeader>
|
|
||||||
</PageWrapper>
|
|
||||||
<SwitchLocaleLink />
|
<SwitchLocaleLink />
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
@ -2,6 +2,8 @@ import { BigNumber } from '@ethersproject/bignumber'
|
|||||||
import { Trans } from '@lingui/macro'
|
import { Trans } from '@lingui/macro'
|
||||||
import { CurrencyAmount, Fraction, Token } from '@uniswap/sdk-core'
|
import { CurrencyAmount, Fraction, Token } from '@uniswap/sdk-core'
|
||||||
import { useWeb3React } from '@web3-react/core'
|
import { useWeb3React } from '@web3-react/core'
|
||||||
|
import { PageName } from 'components/AmplitudeAnalytics/constants'
|
||||||
|
import { Trace } from 'components/AmplitudeAnalytics/Trace'
|
||||||
import ExecuteModal from 'components/vote/ExecuteModal'
|
import ExecuteModal from 'components/vote/ExecuteModal'
|
||||||
import QueueModal from 'components/vote/QueueModal'
|
import QueueModal from 'components/vote/QueueModal'
|
||||||
import { useActiveLocale } from 'hooks/useActiveLocale'
|
import { useActiveLocale } from 'hooks/useActiveLocale'
|
||||||
@ -258,226 +260,232 @@ export default function VotePage({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<Trace page={PageName.VOTE_PAGE} shouldLogImpression>
|
||||||
<PageWrapper gap="lg" justify="center">
|
<>
|
||||||
<VoteModal
|
<PageWrapper gap="lg" justify="center">
|
||||||
isOpen={showVoteModal}
|
<VoteModal
|
||||||
onDismiss={toggleVoteModal}
|
isOpen={showVoteModal}
|
||||||
proposalId={proposalData?.id}
|
onDismiss={toggleVoteModal}
|
||||||
voteOption={voteOption}
|
proposalId={proposalData?.id}
|
||||||
/>
|
voteOption={voteOption}
|
||||||
<DelegateModal isOpen={showDelegateModal} onDismiss={toggleDelegateModal} title={<Trans>Unlock Votes</Trans>} />
|
/>
|
||||||
<QueueModal isOpen={showQueueModal} onDismiss={toggleQueueModal} proposalId={proposalData?.id} />
|
<DelegateModal
|
||||||
<ExecuteModal isOpen={showExecuteModal} onDismiss={toggleExecuteModal} proposalId={proposalData?.id} />
|
isOpen={showDelegateModal}
|
||||||
<ProposalInfo gap="lg" justify="start">
|
onDismiss={toggleDelegateModal}
|
||||||
<RowBetween style={{ width: '100%' }}>
|
title={<Trans>Unlock Votes</Trans>}
|
||||||
<ArrowWrapper to="/vote">
|
/>
|
||||||
<Trans>
|
<QueueModal isOpen={showQueueModal} onDismiss={toggleQueueModal} proposalId={proposalData?.id} />
|
||||||
<ArrowLeft size={20} /> All Proposals
|
<ExecuteModal isOpen={showExecuteModal} onDismiss={toggleExecuteModal} proposalId={proposalData?.id} />
|
||||||
</Trans>
|
<ProposalInfo gap="lg" justify="start">
|
||||||
</ArrowWrapper>
|
<RowBetween style={{ width: '100%' }}>
|
||||||
{proposalData && <ProposalStatus status={proposalData.status} />}
|
<ArrowWrapper to="/vote">
|
||||||
</RowBetween>
|
<Trans>
|
||||||
<AutoColumn gap="10px" style={{ width: '100%' }}>
|
<ArrowLeft size={20} /> All Proposals
|
||||||
<ThemedText.LargeHeader style={{ marginBottom: '.5rem' }}>{proposalData?.title}</ThemedText.LargeHeader>
|
</Trans>
|
||||||
<RowBetween>
|
</ArrowWrapper>
|
||||||
<ThemedText.Main>
|
{proposalData && <ProposalStatus status={proposalData.status} />}
|
||||||
{startDate && startDate > now ? (
|
|
||||||
<Trans>Voting starts approximately {startDate.toLocaleString(locale, dateFormat)}</Trans>
|
|
||||||
) : null}
|
|
||||||
</ThemedText.Main>
|
|
||||||
</RowBetween>
|
</RowBetween>
|
||||||
<RowBetween>
|
<AutoColumn gap="10px" style={{ width: '100%' }}>
|
||||||
<ThemedText.Main>
|
<ThemedText.LargeHeader style={{ marginBottom: '.5rem' }}>{proposalData?.title}</ThemedText.LargeHeader>
|
||||||
{endDate &&
|
<RowBetween>
|
||||||
(endDate < now ? (
|
<ThemedText.Main>
|
||||||
<Trans>Voting ended {endDate.toLocaleString(locale, dateFormat)}</Trans>
|
{startDate && startDate > now ? (
|
||||||
) : (
|
<Trans>Voting starts approximately {startDate.toLocaleString(locale, dateFormat)}</Trans>
|
||||||
<Trans>Voting ends approximately {endDate.toLocaleString(locale, dateFormat)}</Trans>
|
) : null}
|
||||||
))}
|
</ThemedText.Main>
|
||||||
</ThemedText.Main>
|
</RowBetween>
|
||||||
</RowBetween>
|
<RowBetween>
|
||||||
{proposalData && proposalData.status === ProposalState.ACTIVE && !showVotingButtons && (
|
<ThemedText.Main>
|
||||||
<GreyCard>
|
{endDate &&
|
||||||
<ThemedText.Black>
|
(endDate < now ? (
|
||||||
<Trans>
|
<Trans>Voting ended {endDate.toLocaleString(locale, dateFormat)}</Trans>
|
||||||
Only UNI votes that were self delegated or delegated to another address before block{' '}
|
) : (
|
||||||
{proposalData.startBlock} are eligible for voting.
|
<Trans>Voting ends approximately {endDate.toLocaleString(locale, dateFormat)}</Trans>
|
||||||
</Trans>{' '}
|
))}
|
||||||
{showLinkForUnlock && (
|
</ThemedText.Main>
|
||||||
<span>
|
</RowBetween>
|
||||||
<Trans>
|
{proposalData && proposalData.status === ProposalState.ACTIVE && !showVotingButtons && (
|
||||||
<StyledInternalLink to="/vote">Unlock voting</StyledInternalLink> to prepare for the next
|
<GreyCard>
|
||||||
proposal.
|
|
||||||
</Trans>
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</ThemedText.Black>
|
|
||||||
</GreyCard>
|
|
||||||
)}
|
|
||||||
</AutoColumn>
|
|
||||||
{showVotingButtons && (
|
|
||||||
<RowFixed style={{ width: '100%', gap: '12px' }}>
|
|
||||||
<ButtonPrimary
|
|
||||||
padding="8px"
|
|
||||||
$borderRadius="8px"
|
|
||||||
onClick={() => {
|
|
||||||
setVoteOption(VoteOption.For)
|
|
||||||
toggleVoteModal()
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Trans>Vote For</Trans>
|
|
||||||
</ButtonPrimary>
|
|
||||||
<ButtonPrimary
|
|
||||||
padding="8px"
|
|
||||||
$borderRadius="8px"
|
|
||||||
onClick={() => {
|
|
||||||
setVoteOption(VoteOption.Against)
|
|
||||||
toggleVoteModal()
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Trans>Vote Against</Trans>
|
|
||||||
</ButtonPrimary>
|
|
||||||
</RowFixed>
|
|
||||||
)}
|
|
||||||
{showQueueButton && (
|
|
||||||
<RowFixed style={{ width: '100%', gap: '12px' }}>
|
|
||||||
<ButtonPrimary
|
|
||||||
padding="8px"
|
|
||||||
$borderRadius="8px"
|
|
||||||
onClick={() => {
|
|
||||||
toggleQueueModal()
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Trans>Queue</Trans>
|
|
||||||
</ButtonPrimary>
|
|
||||||
</RowFixed>
|
|
||||||
)}
|
|
||||||
{showExecuteButton && (
|
|
||||||
<>
|
|
||||||
{eta && (
|
|
||||||
<RowBetween>
|
|
||||||
<ThemedText.Black>
|
<ThemedText.Black>
|
||||||
<Trans>This proposal may be executed after {eta.toLocaleString(locale, dateFormat)}.</Trans>
|
<Trans>
|
||||||
|
Only UNI votes that were self delegated or delegated to another address before block{' '}
|
||||||
|
{proposalData.startBlock} are eligible for voting.
|
||||||
|
</Trans>{' '}
|
||||||
|
{showLinkForUnlock && (
|
||||||
|
<span>
|
||||||
|
<Trans>
|
||||||
|
<StyledInternalLink to="/vote">Unlock voting</StyledInternalLink> to prepare for the next
|
||||||
|
proposal.
|
||||||
|
</Trans>
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
</ThemedText.Black>
|
</ThemedText.Black>
|
||||||
</RowBetween>
|
</GreyCard>
|
||||||
)}
|
)}
|
||||||
|
</AutoColumn>
|
||||||
|
{showVotingButtons && (
|
||||||
<RowFixed style={{ width: '100%', gap: '12px' }}>
|
<RowFixed style={{ width: '100%', gap: '12px' }}>
|
||||||
<ButtonPrimary
|
<ButtonPrimary
|
||||||
padding="8px"
|
padding="8px"
|
||||||
$borderRadius="8px"
|
$borderRadius="8px"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
toggleExecuteModal()
|
setVoteOption(VoteOption.For)
|
||||||
|
toggleVoteModal()
|
||||||
}}
|
}}
|
||||||
// can't execute until the eta has arrived
|
|
||||||
disabled={!currentTimestamp || !proposalData?.eta || currentTimestamp.lt(proposalData.eta)}
|
|
||||||
>
|
>
|
||||||
<Trans>Execute</Trans>
|
<Trans>Vote For</Trans>
|
||||||
|
</ButtonPrimary>
|
||||||
|
<ButtonPrimary
|
||||||
|
padding="8px"
|
||||||
|
$borderRadius="8px"
|
||||||
|
onClick={() => {
|
||||||
|
setVoteOption(VoteOption.Against)
|
||||||
|
toggleVoteModal()
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Trans>Vote Against</Trans>
|
||||||
</ButtonPrimary>
|
</ButtonPrimary>
|
||||||
</RowFixed>
|
</RowFixed>
|
||||||
</>
|
)}
|
||||||
)}
|
{showQueueButton && (
|
||||||
<CardWrapper>
|
<RowFixed style={{ width: '100%', gap: '12px' }}>
|
||||||
<StyledDataCard>
|
<ButtonPrimary
|
||||||
<CardSection>
|
padding="8px"
|
||||||
<AutoColumn gap="md">
|
$borderRadius="8px"
|
||||||
<WrapSmall>
|
onClick={() => {
|
||||||
<ThemedText.Black fontWeight={600}>
|
toggleQueueModal()
|
||||||
<Trans>For</Trans>
|
}}
|
||||||
|
>
|
||||||
|
<Trans>Queue</Trans>
|
||||||
|
</ButtonPrimary>
|
||||||
|
</RowFixed>
|
||||||
|
)}
|
||||||
|
{showExecuteButton && (
|
||||||
|
<>
|
||||||
|
{eta && (
|
||||||
|
<RowBetween>
|
||||||
|
<ThemedText.Black>
|
||||||
|
<Trans>This proposal may be executed after {eta.toLocaleString(locale, dateFormat)}.</Trans>
|
||||||
</ThemedText.Black>
|
</ThemedText.Black>
|
||||||
{proposalData && (
|
</RowBetween>
|
||||||
|
)}
|
||||||
|
<RowFixed style={{ width: '100%', gap: '12px' }}>
|
||||||
|
<ButtonPrimary
|
||||||
|
padding="8px"
|
||||||
|
$borderRadius="8px"
|
||||||
|
onClick={() => {
|
||||||
|
toggleExecuteModal()
|
||||||
|
}}
|
||||||
|
// can't execute until the eta has arrived
|
||||||
|
disabled={!currentTimestamp || !proposalData?.eta || currentTimestamp.lt(proposalData.eta)}
|
||||||
|
>
|
||||||
|
<Trans>Execute</Trans>
|
||||||
|
</ButtonPrimary>
|
||||||
|
</RowFixed>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
<CardWrapper>
|
||||||
|
<StyledDataCard>
|
||||||
|
<CardSection>
|
||||||
|
<AutoColumn gap="md">
|
||||||
|
<WrapSmall>
|
||||||
<ThemedText.Black fontWeight={600}>
|
<ThemedText.Black fontWeight={600}>
|
||||||
{proposalData.forCount.toFixed(0, { groupSeparator: ',' })}
|
<Trans>For</Trans>
|
||||||
{quorumAmount && (
|
|
||||||
<span style={{ fontWeight: 400 }}>{` / ${quorumAmount.toExact({
|
|
||||||
groupSeparator: ',',
|
|
||||||
})}`}</span>
|
|
||||||
)}
|
|
||||||
</ThemedText.Black>
|
</ThemedText.Black>
|
||||||
)}
|
{proposalData && (
|
||||||
</WrapSmall>
|
<ThemedText.Black fontWeight={600}>
|
||||||
</AutoColumn>
|
{proposalData.forCount.toFixed(0, { groupSeparator: ',' })}
|
||||||
<ProgressWrapper>
|
{quorumAmount && (
|
||||||
<Progress
|
<span style={{ fontWeight: 400 }}>{` / ${quorumAmount.toExact({
|
||||||
status={'for'}
|
groupSeparator: ',',
|
||||||
percentageString={
|
})}`}</span>
|
||||||
proposalData?.forCount.greaterThan(0) ? `${forPercentage?.toFixed(0) ?? 0}%` : '0%'
|
)}
|
||||||
}
|
</ThemedText.Black>
|
||||||
/>
|
)}
|
||||||
</ProgressWrapper>
|
</WrapSmall>
|
||||||
</CardSection>
|
</AutoColumn>
|
||||||
</StyledDataCard>
|
<ProgressWrapper>
|
||||||
<StyledDataCard>
|
<Progress
|
||||||
<CardSection>
|
status={'for'}
|
||||||
<AutoColumn gap="md">
|
percentageString={
|
||||||
<WrapSmall>
|
proposalData?.forCount.greaterThan(0) ? `${forPercentage?.toFixed(0) ?? 0}%` : '0%'
|
||||||
<ThemedText.Black fontWeight={600}>
|
}
|
||||||
<Trans>Against</Trans>
|
/>
|
||||||
</ThemedText.Black>
|
</ProgressWrapper>
|
||||||
{proposalData && (
|
</CardSection>
|
||||||
|
</StyledDataCard>
|
||||||
|
<StyledDataCard>
|
||||||
|
<CardSection>
|
||||||
|
<AutoColumn gap="md">
|
||||||
|
<WrapSmall>
|
||||||
<ThemedText.Black fontWeight={600}>
|
<ThemedText.Black fontWeight={600}>
|
||||||
{proposalData.againstCount.toFixed(0, { groupSeparator: ',' })}
|
<Trans>Against</Trans>
|
||||||
</ThemedText.Black>
|
</ThemedText.Black>
|
||||||
)}
|
{proposalData && (
|
||||||
</WrapSmall>
|
<ThemedText.Black fontWeight={600}>
|
||||||
</AutoColumn>
|
{proposalData.againstCount.toFixed(0, { groupSeparator: ',' })}
|
||||||
<ProgressWrapper>
|
</ThemedText.Black>
|
||||||
<Progress
|
)}
|
||||||
status={'against'}
|
</WrapSmall>
|
||||||
percentageString={
|
</AutoColumn>
|
||||||
proposalData?.againstCount?.greaterThan(0) ? `${againstPercentage?.toFixed(0) ?? 0}%` : '0%'
|
<ProgressWrapper>
|
||||||
}
|
<Progress
|
||||||
/>
|
status={'against'}
|
||||||
</ProgressWrapper>
|
percentageString={
|
||||||
</CardSection>
|
proposalData?.againstCount?.greaterThan(0) ? `${againstPercentage?.toFixed(0) ?? 0}%` : '0%'
|
||||||
</StyledDataCard>
|
}
|
||||||
</CardWrapper>
|
/>
|
||||||
<AutoColumn gap="md">
|
</ProgressWrapper>
|
||||||
<ThemedText.MediumHeader fontWeight={600}>
|
</CardSection>
|
||||||
<Trans>Details</Trans>
|
</StyledDataCard>
|
||||||
</ThemedText.MediumHeader>
|
</CardWrapper>
|
||||||
{proposalData?.details?.map((d, i) => {
|
<AutoColumn gap="md">
|
||||||
return (
|
<ThemedText.MediumHeader fontWeight={600}>
|
||||||
<DetailText key={i}>
|
<Trans>Details</Trans>
|
||||||
{i + 1}: {linkIfAddress(d.target)}.{d.functionSig}(
|
</ThemedText.MediumHeader>
|
||||||
{d.callData.split(',').map((content, i) => {
|
{proposalData?.details?.map((d, i) => {
|
||||||
return (
|
return (
|
||||||
<span key={i}>
|
<DetailText key={i}>
|
||||||
{linkIfAddress(content)}
|
{i + 1}: {linkIfAddress(d.target)}.{d.functionSig}(
|
||||||
{d.callData.split(',').length - 1 === i ? '' : ','}
|
{d.callData.split(',').map((content, i) => {
|
||||||
</span>
|
return (
|
||||||
|
<span key={i}>
|
||||||
|
{linkIfAddress(content)}
|
||||||
|
{d.callData.split(',').length - 1 === i ? '' : ','}
|
||||||
|
</span>
|
||||||
|
)
|
||||||
|
})}
|
||||||
)
|
)
|
||||||
})}
|
</DetailText>
|
||||||
)
|
)
|
||||||
</DetailText>
|
})}
|
||||||
)
|
</AutoColumn>
|
||||||
})}
|
<AutoColumn gap="md">
|
||||||
</AutoColumn>
|
<ThemedText.MediumHeader fontWeight={600}>
|
||||||
<AutoColumn gap="md">
|
<Trans>Description</Trans>
|
||||||
<ThemedText.MediumHeader fontWeight={600}>
|
</ThemedText.MediumHeader>
|
||||||
<Trans>Description</Trans>
|
<MarkDownWrapper>
|
||||||
</ThemedText.MediumHeader>
|
<ReactMarkdown source={proposalData?.description} />
|
||||||
<MarkDownWrapper>
|
</MarkDownWrapper>
|
||||||
<ReactMarkdown source={proposalData?.description} />
|
</AutoColumn>
|
||||||
</MarkDownWrapper>
|
<AutoColumn gap="md">
|
||||||
</AutoColumn>
|
<ThemedText.MediumHeader fontWeight={600}>
|
||||||
<AutoColumn gap="md">
|
<Trans>Proposer</Trans>
|
||||||
<ThemedText.MediumHeader fontWeight={600}>
|
</ThemedText.MediumHeader>
|
||||||
<Trans>Proposer</Trans>
|
<ProposerAddressLink
|
||||||
</ThemedText.MediumHeader>
|
href={
|
||||||
<ProposerAddressLink
|
proposalData?.proposer && chainId
|
||||||
href={
|
? getExplorerLink(chainId, proposalData?.proposer, ExplorerDataType.ADDRESS)
|
||||||
proposalData?.proposer && chainId
|
: ''
|
||||||
? getExplorerLink(chainId, proposalData?.proposer, ExplorerDataType.ADDRESS)
|
}
|
||||||
: ''
|
>
|
||||||
}
|
<ReactMarkdown source={proposalData?.proposer} />
|
||||||
>
|
</ProposerAddressLink>
|
||||||
<ReactMarkdown source={proposalData?.proposer} />
|
</AutoColumn>
|
||||||
</ProposerAddressLink>
|
</ProposalInfo>
|
||||||
</AutoColumn>
|
</PageWrapper>
|
||||||
</ProposalInfo>
|
<SwitchLocaleLink />
|
||||||
</PageWrapper>
|
</>
|
||||||
<SwitchLocaleLink />
|
</Trace>
|
||||||
</>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user