refactor: transaction info is translated in the appropriate places (#2380)
* refactor: transaction info is translated in the appropriate places fixes https://github.com/Uniswap/interface/issues/1756 * getting closer * more work * finished, finally * bit more refactoring * move summary into its own file * little more cleanup in the transaction summary file * fix bad copy * fix the migrate notification * missing translation * fix the language for vote and address other pr comments * fix typo * - remove old transactions with this update - change to present tense - show ens name where appropriate * add a test that shows we don't clear old ones
This commit is contained in:
parent
9fa3b70475
commit
fb07919888
@ -1,14 +1,13 @@
|
||||
import styled from 'styled-components/macro'
|
||||
import { CheckCircle, Triangle } from 'react-feather'
|
||||
import styled from 'styled-components/macro'
|
||||
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import { ExternalLink } from '../../theme'
|
||||
import { useAllTransactions } from '../../state/transactions/hooks'
|
||||
import { ExternalLink } from '../../theme'
|
||||
import { ExplorerDataType, getExplorerLink } from '../../utils/getExplorerLink'
|
||||
import { RowFixed } from '../Row'
|
||||
import Loader from '../Loader'
|
||||
|
||||
const TransactionWrapper = styled.div``
|
||||
import { RowFixed } from '../Row'
|
||||
import { TransactionSummary } from './TransactionSummary'
|
||||
|
||||
const TransactionStatusText = styled.div`
|
||||
margin-right: 0.5rem;
|
||||
@ -40,26 +39,28 @@ export default function Transaction({ hash }: { hash: string }) {
|
||||
const allTransactions = useAllTransactions()
|
||||
|
||||
const tx = allTransactions?.[hash]
|
||||
const summary = tx?.summary
|
||||
const info = tx?.info
|
||||
const pending = !tx?.receipt
|
||||
const success = !pending && tx && (tx.receipt?.status === 1 || typeof tx.receipt?.status === 'undefined')
|
||||
|
||||
if (!chainId) return null
|
||||
|
||||
return (
|
||||
<TransactionWrapper>
|
||||
<div>
|
||||
<TransactionState
|
||||
href={getExplorerLink(chainId, hash, ExplorerDataType.TRANSACTION)}
|
||||
pending={pending}
|
||||
success={success}
|
||||
>
|
||||
<RowFixed>
|
||||
<TransactionStatusText>{summary ?? hash} ↗</TransactionStatusText>
|
||||
<TransactionStatusText>
|
||||
<TransactionSummary info={info} /> ↗
|
||||
</TransactionStatusText>
|
||||
</RowFixed>
|
||||
<IconWrapper pending={pending} success={success}>
|
||||
{pending ? <Loader /> : success ? <CheckCircle size="16" /> : <Triangle size="16" />}
|
||||
</IconWrapper>
|
||||
</TransactionState>
|
||||
</TransactionWrapper>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
328
src/components/AccountDetails/TransactionSummary.tsx
Normal file
328
src/components/AccountDetails/TransactionSummary.tsx
Normal file
@ -0,0 +1,328 @@
|
||||
import { Trans } from '@lingui/macro'
|
||||
import { Fraction, TradeType } from '@uniswap/sdk-core'
|
||||
import JSBI from 'jsbi'
|
||||
import { useCurrency, useToken } from '../../hooks/Tokens'
|
||||
import useENSName from '../../hooks/useENSName'
|
||||
import { VoteOption } from '../../state/governance/types'
|
||||
import {
|
||||
AddLiquidityV2PoolTransactionInfo,
|
||||
AddLiquidityV3PoolTransactionInfo,
|
||||
ApproveTransactionInfo,
|
||||
ClaimTransactionInfo,
|
||||
CollectFeesTransactionInfo,
|
||||
CreateV3PoolTransactionInfo,
|
||||
DelegateTransactionInfo,
|
||||
DepositLiquidityStakingTransactionInfo,
|
||||
ExactInputSwapTransactionInfo,
|
||||
ExactOutputSwapTransactionInfo,
|
||||
MigrateV2LiquidityToV3TransactionInfo,
|
||||
RemoveLiquidityV3TransactionInfo,
|
||||
SubmitProposalTransactionInfo,
|
||||
TransactionInfo,
|
||||
TransactionType,
|
||||
VoteTransactionInfo,
|
||||
WithdrawLiquidityStakingTransactionInfo,
|
||||
WrapTransactionInfo,
|
||||
} from '../../state/transactions/actions'
|
||||
|
||||
function formatAmount(amountRaw: string, decimals: number, sigFigs: number): string {
|
||||
return new Fraction(amountRaw, JSBI.exponentiate(JSBI.BigInt(10), JSBI.BigInt(decimals))).toSignificant(sigFigs)
|
||||
}
|
||||
|
||||
function FormattedCurrencyAmount({
|
||||
rawAmount,
|
||||
symbol,
|
||||
decimals,
|
||||
sigFigs,
|
||||
}: {
|
||||
rawAmount: string
|
||||
symbol: string
|
||||
decimals: number
|
||||
sigFigs: number
|
||||
}) {
|
||||
return (
|
||||
<>
|
||||
{formatAmount(rawAmount, decimals, sigFigs)} {symbol}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
function FormattedCurrencyAmountManaged({
|
||||
rawAmount,
|
||||
currencyId,
|
||||
sigFigs = 6,
|
||||
}: {
|
||||
rawAmount: string
|
||||
currencyId: string
|
||||
sigFigs: number
|
||||
}) {
|
||||
const currency = useCurrency(currencyId)
|
||||
return currency ? (
|
||||
<FormattedCurrencyAmount
|
||||
rawAmount={rawAmount}
|
||||
decimals={currency.decimals}
|
||||
sigFigs={sigFigs}
|
||||
symbol={currency.symbol ?? '???'}
|
||||
/>
|
||||
) : null
|
||||
}
|
||||
|
||||
function ClaimSummary({ info: { recipient, uniAmountRaw } }: { info: ClaimTransactionInfo }) {
|
||||
const { ENSName } = useENSName()
|
||||
return typeof uniAmountRaw === 'string' ? (
|
||||
<Trans>
|
||||
Claim <FormattedCurrencyAmount rawAmount={uniAmountRaw} symbol={'UNI'} decimals={18} sigFigs={4} /> for{' '}
|
||||
{ENSName ?? recipient}
|
||||
</Trans>
|
||||
) : (
|
||||
<Trans>Claim UNI reward for {ENSName ?? recipient}</Trans>
|
||||
)
|
||||
}
|
||||
|
||||
function SubmitProposalTransactionSummary({}: { info: SubmitProposalTransactionInfo }) {
|
||||
return <Trans>Submit new proposal</Trans>
|
||||
}
|
||||
|
||||
function ApprovalSummary({ info }: { info: ApproveTransactionInfo }) {
|
||||
const token = useToken(info.tokenAddress)
|
||||
|
||||
return <Trans>Approve {token?.symbol}</Trans>
|
||||
}
|
||||
|
||||
function VoteSummary({ info }: { info: VoteTransactionInfo }) {
|
||||
const proposalKey = `${info.governorAddress}/${info.proposalId}`
|
||||
if (info.reason && info.reason.trim().length > 0) {
|
||||
switch (info.decision) {
|
||||
case VoteOption.For:
|
||||
return <Trans>Vote for proposal {proposalKey}</Trans>
|
||||
case VoteOption.Abstain:
|
||||
return <Trans>Vote to abstain on proposal {proposalKey}</Trans>
|
||||
case VoteOption.Against:
|
||||
return <Trans>Vote against proposal {proposalKey}</Trans>
|
||||
}
|
||||
} else {
|
||||
switch (info.decision) {
|
||||
case VoteOption.For:
|
||||
return (
|
||||
<Trans>
|
||||
Vote for proposal {proposalKey} with reason "{info.reason}"
|
||||
</Trans>
|
||||
)
|
||||
case VoteOption.Abstain:
|
||||
return (
|
||||
<Trans>
|
||||
Vote to abstain on proposal {proposalKey} with reason "{info.reason}"
|
||||
</Trans>
|
||||
)
|
||||
case VoteOption.Against:
|
||||
return (
|
||||
<Trans>
|
||||
Vote against proposal {proposalKey} with reason "{info.reason}"
|
||||
</Trans>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function DelegateSummary({ info: { delegatee } }: { info: DelegateTransactionInfo }) {
|
||||
const { ENSName } = useENSName(delegatee)
|
||||
return <Trans>Delegate voting power to {ENSName ?? delegatee}</Trans>
|
||||
}
|
||||
|
||||
function WrapSummary({ info: { currencyAmountRaw, unwrapped } }: { info: WrapTransactionInfo }) {
|
||||
if (unwrapped) {
|
||||
return (
|
||||
<Trans>
|
||||
Unwrap <FormattedCurrencyAmount rawAmount={currencyAmountRaw} symbol={'WETH'} decimals={18} sigFigs={6} /> to
|
||||
ETH
|
||||
</Trans>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<Trans>
|
||||
Wrap <FormattedCurrencyAmount rawAmount={currencyAmountRaw} symbol={'ETH'} decimals={18} sigFigs={6} /> to WETH
|
||||
</Trans>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
function DepositLiquidityStakingSummary({}: { info: DepositLiquidityStakingTransactionInfo }) {
|
||||
// not worth rendering the tokens since you can should no longer deposit liquidity in the staking contracts
|
||||
// todo: deprecate and delete the code paths that allow this, show user more information
|
||||
return <Trans>Deposit liquidity</Trans>
|
||||
}
|
||||
|
||||
function WithdrawLiquidityStakingSummary({}: { info: WithdrawLiquidityStakingTransactionInfo }) {
|
||||
return <Trans>Withdraw deposited liquidity</Trans>
|
||||
}
|
||||
|
||||
function MigrateLiquidityToV3Summary({
|
||||
info: { baseCurrencyId, quoteCurrencyId },
|
||||
}: {
|
||||
info: MigrateV2LiquidityToV3TransactionInfo
|
||||
}) {
|
||||
const baseCurrency = useCurrency(baseCurrencyId)
|
||||
const quoteCurrency = useCurrency(quoteCurrencyId)
|
||||
|
||||
return (
|
||||
<Trans>
|
||||
Migrate {baseCurrency?.symbol}/{quoteCurrency?.symbol} liquidity to V3
|
||||
</Trans>
|
||||
)
|
||||
}
|
||||
|
||||
function CreateV3PoolSummary({ info: { quoteCurrencyId, baseCurrencyId } }: { info: CreateV3PoolTransactionInfo }) {
|
||||
const baseCurrency = useCurrency(baseCurrencyId)
|
||||
const quoteCurrency = useCurrency(quoteCurrencyId)
|
||||
|
||||
return (
|
||||
<Trans>
|
||||
Create {baseCurrency?.symbol}/{quoteCurrency?.symbol} V3 pool
|
||||
</Trans>
|
||||
)
|
||||
}
|
||||
|
||||
function CollectFeesSummary({ info: { currencyId0, currencyId1 } }: { info: CollectFeesTransactionInfo }) {
|
||||
const currency0 = useCurrency(currencyId0)
|
||||
const currency1 = useCurrency(currencyId1)
|
||||
|
||||
return (
|
||||
<Trans>
|
||||
Collect {currency0?.symbol}/{currency1?.symbol} fees
|
||||
</Trans>
|
||||
)
|
||||
}
|
||||
|
||||
function RemoveLiquidityV3Summary({
|
||||
info: { baseCurrencyId, quoteCurrencyId, expectedAmountBaseRaw, expectedAmountQuoteRaw },
|
||||
}: {
|
||||
info: RemoveLiquidityV3TransactionInfo
|
||||
}) {
|
||||
return (
|
||||
<Trans>
|
||||
Remove{' '}
|
||||
<FormattedCurrencyAmountManaged rawAmount={expectedAmountBaseRaw} currencyId={baseCurrencyId} sigFigs={3} /> and{' '}
|
||||
<FormattedCurrencyAmountManaged rawAmount={expectedAmountQuoteRaw} currencyId={quoteCurrencyId} sigFigs={3} />
|
||||
</Trans>
|
||||
)
|
||||
}
|
||||
|
||||
function AddLiquidityV3PoolSummary({
|
||||
info: { createPool, quoteCurrencyId, baseCurrencyId },
|
||||
}: {
|
||||
info: AddLiquidityV3PoolTransactionInfo
|
||||
}) {
|
||||
const baseCurrency = useCurrency(baseCurrencyId)
|
||||
const quoteCurrency = useCurrency(quoteCurrencyId)
|
||||
|
||||
return createPool ? (
|
||||
<Trans>
|
||||
Create pool and add {baseCurrency?.symbol}/{quoteCurrency?.symbol} V3 liquidity
|
||||
</Trans>
|
||||
) : (
|
||||
<Trans>
|
||||
Add {baseCurrency?.symbol}/{quoteCurrency?.symbol} V3 liquidity
|
||||
</Trans>
|
||||
)
|
||||
}
|
||||
|
||||
function AddLiquidityV2PoolSummary({
|
||||
info: { quoteCurrencyId, expectedAmountBaseRaw, expectedAmountQuoteRaw, baseCurrencyId },
|
||||
}: {
|
||||
info: AddLiquidityV2PoolTransactionInfo
|
||||
}) {
|
||||
return (
|
||||
<Trans>
|
||||
Add <FormattedCurrencyAmountManaged rawAmount={expectedAmountBaseRaw} currencyId={baseCurrencyId} sigFigs={3} />{' '}
|
||||
and <FormattedCurrencyAmountManaged rawAmount={expectedAmountQuoteRaw} currencyId={quoteCurrencyId} sigFigs={3} />{' '}
|
||||
to Uniswap V2
|
||||
</Trans>
|
||||
)
|
||||
}
|
||||
|
||||
function SwapSummary({ info }: { info: ExactInputSwapTransactionInfo | ExactOutputSwapTransactionInfo }) {
|
||||
if (info.tradeType === TradeType.EXACT_INPUT) {
|
||||
return (
|
||||
<Trans>
|
||||
Swap exactly{' '}
|
||||
<FormattedCurrencyAmountManaged
|
||||
rawAmount={info.inputCurrencyAmountRaw}
|
||||
currencyId={info.inputCurrencyId}
|
||||
sigFigs={6}
|
||||
/>{' '}
|
||||
for{' '}
|
||||
<FormattedCurrencyAmountManaged
|
||||
rawAmount={info.expectedOutputCurrencyAmountRaw}
|
||||
currencyId={info.outputCurrencyId}
|
||||
sigFigs={6}
|
||||
/>
|
||||
</Trans>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<Trans>
|
||||
Swap{' '}
|
||||
<FormattedCurrencyAmountManaged
|
||||
rawAmount={info.expectedInputCurrencyAmountRaw}
|
||||
currencyId={info.inputCurrencyId}
|
||||
sigFigs={6}
|
||||
/>{' '}
|
||||
for exactly{' '}
|
||||
<FormattedCurrencyAmountManaged
|
||||
rawAmount={info.outputCurrencyAmountRaw}
|
||||
currencyId={info.outputCurrencyId}
|
||||
sigFigs={6}
|
||||
/>
|
||||
</Trans>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export function TransactionSummary({ info }: { info: TransactionInfo }) {
|
||||
switch (info.type) {
|
||||
case TransactionType.ADD_LIQUIDITY_V3_POOL:
|
||||
return <AddLiquidityV3PoolSummary info={info} />
|
||||
|
||||
case TransactionType.ADD_LIQUIDITY_V2_POOL:
|
||||
return <AddLiquidityV2PoolSummary info={info} />
|
||||
|
||||
case TransactionType.CLAIM:
|
||||
return <ClaimSummary info={info} />
|
||||
|
||||
case TransactionType.DEPOSIT_LIQUIDITY_STAKING:
|
||||
return <DepositLiquidityStakingSummary info={info} />
|
||||
|
||||
case TransactionType.WITHDRAW_LIQUIDITY_STAKING:
|
||||
return <WithdrawLiquidityStakingSummary info={info} />
|
||||
|
||||
case TransactionType.SWAP:
|
||||
return <SwapSummary info={info} />
|
||||
|
||||
case TransactionType.APPROVAL:
|
||||
return <ApprovalSummary info={info} />
|
||||
|
||||
case TransactionType.VOTE:
|
||||
return <VoteSummary info={info} />
|
||||
|
||||
case TransactionType.DELEGATE:
|
||||
return <DelegateSummary info={info} />
|
||||
|
||||
case TransactionType.WRAP:
|
||||
return <WrapSummary info={info} />
|
||||
|
||||
case TransactionType.CREATE_V3_POOL:
|
||||
return <CreateV3PoolSummary info={info} />
|
||||
|
||||
case TransactionType.MIGRATE_LIQUIDITY_V3:
|
||||
return <MigrateLiquidityToV3Summary info={info} />
|
||||
|
||||
case TransactionType.COLLECT_FEES:
|
||||
return <CollectFeesSummary info={info} />
|
||||
|
||||
case TransactionType.REMOVE_LIQUIDITY_V3:
|
||||
return <RemoveLiquidityV3Summary info={info} />
|
||||
|
||||
case TransactionType.SUBMIT_PROPOSAL:
|
||||
return <SubmitProposalTransactionSummary info={info} />
|
||||
}
|
||||
}
|
@ -73,9 +73,9 @@ export default function PopupItem({
|
||||
let popupContent
|
||||
if ('txn' in content) {
|
||||
const {
|
||||
txn: { hash, success, summary },
|
||||
txn: { hash },
|
||||
} = content
|
||||
popupContent = <TransactionPopup hash={hash} success={success} summary={summary} />
|
||||
popupContent = <TransactionPopup hash={hash} />
|
||||
}
|
||||
|
||||
const faderStyle = useSpring({
|
||||
|
@ -2,9 +2,11 @@ import { useContext } from 'react'
|
||||
import { AlertCircle, CheckCircle } from 'react-feather'
|
||||
import styled, { ThemeContext } from 'styled-components/macro'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import { useTransaction } from '../../state/transactions/hooks'
|
||||
import { TYPE } from '../../theme'
|
||||
import { ExternalLink } from '../../theme/components'
|
||||
import { ExplorerDataType, getExplorerLink } from '../../utils/getExplorerLink'
|
||||
import { TransactionSummary } from '../AccountDetails/TransactionSummary'
|
||||
import { AutoColumn } from '../Column'
|
||||
import { AutoRow } from '../Row'
|
||||
|
||||
@ -12,26 +14,24 @@ const RowNoFlex = styled(AutoRow)`
|
||||
flex-wrap: nowrap;
|
||||
`
|
||||
|
||||
export default function TransactionPopup({
|
||||
hash,
|
||||
success,
|
||||
summary,
|
||||
}: {
|
||||
hash: string
|
||||
success?: boolean
|
||||
summary?: string
|
||||
}) {
|
||||
export default function TransactionPopup({ hash }: { hash: string }) {
|
||||
const { chainId } = useActiveWeb3React()
|
||||
|
||||
const tx = useTransaction(hash)
|
||||
const theme = useContext(ThemeContext)
|
||||
|
||||
if (!tx) return null
|
||||
const success = Boolean(tx.receipt && tx.receipt.status === 1)
|
||||
|
||||
return (
|
||||
<RowNoFlex>
|
||||
<div style={{ paddingRight: 16 }}>
|
||||
{success ? <CheckCircle color={theme.green1} size={24} /> : <AlertCircle color={theme.red1} size={24} />}
|
||||
</div>
|
||||
<AutoColumn gap="8px">
|
||||
<TYPE.body fontWeight={500}>{summary ?? 'Hash: ' + hash.slice(0, 8) + '...' + hash.slice(58, 65)}</TYPE.body>
|
||||
<TYPE.body fontWeight={500}>
|
||||
<TransactionSummary info={tx.info} />
|
||||
</TYPE.body>
|
||||
{chainId && (
|
||||
<ExternalLink href={getExplorerLink(chainId, hash, ExplorerDataType.TRANSACTION)}>
|
||||
View on Explorer
|
||||
|
@ -2,6 +2,7 @@ import { Currency } from '@uniswap/sdk-core'
|
||||
import { ReactNode, useContext } from 'react'
|
||||
import styled, { ThemeContext } from 'styled-components/macro'
|
||||
import { getExplorerLink, ExplorerDataType } from '../../utils/getExplorerLink'
|
||||
import { TransactionSummary } from '../AccountDetails/TransactionSummary'
|
||||
import Modal from '../Modal'
|
||||
import { ExternalLink } from '../../theme'
|
||||
import { Text } from 'rebass'
|
||||
@ -273,7 +274,7 @@ function L2Content({
|
||||
)}
|
||||
</Text>
|
||||
<Text fontWeight={400} fontSize={16} textAlign="center">
|
||||
{transaction?.summary ?? pendingText ?? ''}
|
||||
{transaction ? <TransactionSummary info={transaction.info} /> : pendingText}
|
||||
</Text>
|
||||
{chainId && hash ? (
|
||||
<ExternalLink href={getExplorerLink(chainId, hash, ExplorerDataType.TRANSACTION)}>
|
||||
|
@ -188,7 +188,7 @@ export default function ClaimModal() {
|
||||
<AutoColumn gap="100px" justify={'center'}>
|
||||
<AutoColumn gap="12px" justify={'center'}>
|
||||
<TYPE.largeHeader fontWeight={600} color="black">
|
||||
{claimConfirmed ? 'Claimed!' : 'Claiming'}
|
||||
{claimConfirmed ? <Trans>Claimed!</Trans> : <Trans>Claiming</Trans>}
|
||||
</TYPE.largeHeader>
|
||||
{!claimConfirmed && (
|
||||
<Text fontSize={36} color={'#ff007a'} fontWeight={800}>
|
||||
|
@ -1,17 +1,18 @@
|
||||
import { useState } from 'react'
|
||||
import Modal from '../Modal'
|
||||
import { AutoColumn } from '../Column'
|
||||
import styled from 'styled-components/macro'
|
||||
import { RowBetween } from '../Row'
|
||||
import { TYPE, CloseIcon } from '../../theme'
|
||||
import { ButtonError } from '../Button'
|
||||
import { StakingInfo } from '../../state/stake/hooks'
|
||||
import { useStakingContract } from '../../hooks/useContract'
|
||||
import { SubmittedView, LoadingView } from '../ModalViews'
|
||||
import { TransactionResponse } from '@ethersproject/providers'
|
||||
import { useTransactionAdder } from '../../state/transactions/hooks'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import { t, Trans } from '@lingui/macro'
|
||||
import { useState } from 'react'
|
||||
import styled from 'styled-components/macro'
|
||||
import { useStakingContract } from '../../hooks/useContract'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import { StakingInfo } from '../../state/stake/hooks'
|
||||
import { TransactionType } from '../../state/transactions/actions'
|
||||
import { useTransactionAdder } from '../../state/transactions/hooks'
|
||||
import { CloseIcon, TYPE } from '../../theme'
|
||||
import { ButtonError } from '../Button'
|
||||
import { AutoColumn } from '../Column'
|
||||
import Modal from '../Modal'
|
||||
import { LoadingView, SubmittedView } from '../ModalViews'
|
||||
import { RowBetween } from '../Row'
|
||||
|
||||
const ContentWrapper = styled(AutoColumn)`
|
||||
width: 100%;
|
||||
@ -41,12 +42,15 @@ export default function ClaimRewardModal({ isOpen, onDismiss, stakingInfo }: Sta
|
||||
const stakingContract = useStakingContract(stakingInfo.stakingRewardAddress)
|
||||
|
||||
async function onClaimReward() {
|
||||
if (stakingContract && stakingInfo?.stakedAmount) {
|
||||
if (stakingContract && stakingInfo?.stakedAmount && account) {
|
||||
setAttempting(true)
|
||||
await stakingContract
|
||||
.getReward({ gasLimit: 350000 })
|
||||
.then((response: TransactionResponse) => {
|
||||
addTransaction(response, { summary: t`Claim accumulated UNI rewards` })
|
||||
addTransaction(response, {
|
||||
type: TransactionType.CLAIM,
|
||||
recipient: account,
|
||||
})
|
||||
setHash(response.hash)
|
||||
})
|
||||
.catch((error: any) => {
|
||||
|
@ -1,26 +1,27 @@
|
||||
import { useState, useCallback } from 'react'
|
||||
import { TransactionResponse } from '@ethersproject/providers'
|
||||
import { Trans } from '@lingui/macro'
|
||||
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
|
||||
import { Pair } from '@uniswap/v2-sdk'
|
||||
import { useCallback, useState } from 'react'
|
||||
import styled from 'styled-components/macro'
|
||||
import { ApprovalState, useApproveCallback } from '../../hooks/useApproveCallback'
|
||||
import { usePairContract, useStakingContract, useV2RouterContract } from '../../hooks/useContract'
|
||||
import { useV2LiquidityTokenPermit } from '../../hooks/useERC20Permit'
|
||||
import useTransactionDeadline from '../../hooks/useTransactionDeadline'
|
||||
import { formatCurrencyAmount } from '../../utils/formatCurrencyAmount'
|
||||
import Modal from '../Modal'
|
||||
import { AutoColumn } from '../Column'
|
||||
import styled from 'styled-components/macro'
|
||||
import { RowBetween } from '../Row'
|
||||
import { TYPE, CloseIcon } from '../../theme'
|
||||
import { ButtonConfirmed, ButtonError } from '../Button'
|
||||
import ProgressCircles from '../ProgressSteps'
|
||||
import CurrencyInputPanel from '../CurrencyInputPanel'
|
||||
import { Pair } from '@uniswap/v2-sdk'
|
||||
import { Token, CurrencyAmount } from '@uniswap/sdk-core'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import { maxAmountSpend } from '../../utils/maxAmountSpend'
|
||||
import { usePairContract, useStakingContract, useV2RouterContract } from '../../hooks/useContract'
|
||||
import { useApproveCallback, ApprovalState } from '../../hooks/useApproveCallback'
|
||||
import { StakingInfo, useDerivedStakeInfo } from '../../state/stake/hooks'
|
||||
import { TransactionResponse } from '@ethersproject/providers'
|
||||
import { TransactionType } from '../../state/transactions/actions'
|
||||
import { useTransactionAdder } from '../../state/transactions/hooks'
|
||||
import { CloseIcon, TYPE } from '../../theme'
|
||||
import { formatCurrencyAmount } from '../../utils/formatCurrencyAmount'
|
||||
import { maxAmountSpend } from '../../utils/maxAmountSpend'
|
||||
import { ButtonConfirmed, ButtonError } from '../Button'
|
||||
import { AutoColumn } from '../Column'
|
||||
import CurrencyInputPanel from '../CurrencyInputPanel'
|
||||
import Modal from '../Modal'
|
||||
import { LoadingView, SubmittedView } from '../ModalViews'
|
||||
import { t, Trans } from '@lingui/macro'
|
||||
import ProgressCircles from '../ProgressSteps'
|
||||
import { RowBetween } from '../Row'
|
||||
|
||||
const HypotheticalRewardRate = styled.div<{ dim: boolean }>`
|
||||
display: flex;
|
||||
@ -105,7 +106,9 @@ export default function StakingModal({ isOpen, onDismiss, stakingInfo, userLiqui
|
||||
)
|
||||
.then((response: TransactionResponse) => {
|
||||
addTransaction(response, {
|
||||
summary: t`Deposit liquidity`,
|
||||
type: TransactionType.DEPOSIT_LIQUIDITY_STAKING,
|
||||
token0Address: stakingInfo.tokens[0].address,
|
||||
token1Address: stakingInfo.tokens[1].address,
|
||||
})
|
||||
setHash(response.hash)
|
||||
})
|
||||
|
@ -1,18 +1,19 @@
|
||||
import { useState } from 'react'
|
||||
import Modal from '../Modal'
|
||||
import { AutoColumn } from '../Column'
|
||||
import styled from 'styled-components/macro'
|
||||
import { RowBetween } from '../Row'
|
||||
import { TYPE, CloseIcon } from '../../theme'
|
||||
import { ButtonError } from '../Button'
|
||||
import { StakingInfo } from '../../state/stake/hooks'
|
||||
import { useStakingContract } from '../../hooks/useContract'
|
||||
import { SubmittedView, LoadingView } from '../ModalViews'
|
||||
import { TransactionResponse } from '@ethersproject/providers'
|
||||
import { useTransactionAdder } from '../../state/transactions/hooks'
|
||||
import FormattedCurrencyAmount from '../FormattedCurrencyAmount'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import { t, Trans } from '@lingui/macro'
|
||||
import { useState } from 'react'
|
||||
import styled from 'styled-components/macro'
|
||||
import { useStakingContract } from '../../hooks/useContract'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import { StakingInfo } from '../../state/stake/hooks'
|
||||
import { TransactionType } from '../../state/transactions/actions'
|
||||
import { useTransactionAdder } from '../../state/transactions/hooks'
|
||||
import { CloseIcon, TYPE } from '../../theme'
|
||||
import { ButtonError } from '../Button'
|
||||
import { AutoColumn } from '../Column'
|
||||
import FormattedCurrencyAmount from '../FormattedCurrencyAmount'
|
||||
import Modal from '../Modal'
|
||||
import { LoadingView, SubmittedView } from '../ModalViews'
|
||||
import { RowBetween } from '../Row'
|
||||
|
||||
const ContentWrapper = styled(AutoColumn)`
|
||||
width: 100%;
|
||||
@ -48,7 +49,9 @@ export default function UnstakingModal({ isOpen, onDismiss, stakingInfo }: Staki
|
||||
.exit({ gasLimit: 300000 })
|
||||
.then((response: TransactionResponse) => {
|
||||
addTransaction(response, {
|
||||
summary: t`Withdraw deposited liquidity`,
|
||||
type: TransactionType.WITHDRAW_LIQUIDITY_STAKING,
|
||||
token0Address: stakingInfo.tokens[0].address,
|
||||
token1Address: stakingInfo.tokens[1].address,
|
||||
})
|
||||
setHash(response.hash)
|
||||
})
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { useState, useContext } from 'react'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import { VoteOption } from '../../state/governance/types'
|
||||
import { getExplorerLink, ExplorerDataType } from '../../utils/getExplorerLink'
|
||||
|
||||
import Modal from '../Modal'
|
||||
@ -10,7 +11,7 @@ import { TYPE, CustomLightSpinner } from '../../theme'
|
||||
import { X, ArrowUpCircle } from 'react-feather'
|
||||
import { ButtonPrimary } from '../Button'
|
||||
import Circle from '../../assets/images/blue-loader.svg'
|
||||
import { useVoteCallback, useUserVotes, VoteOption } from '../../state/governance/hooks'
|
||||
import { useVoteCallback, useUserVotes } from '../../state/governance/hooks'
|
||||
import { ExternalLink } from '../../theme/components'
|
||||
import { formatCurrencyAmount } from 'utils/formatCurrencyAmount'
|
||||
import { Trans } from '@lingui/macro'
|
||||
|
@ -5,6 +5,7 @@ import { Trade as V2Trade } from '@uniswap/v2-sdk'
|
||||
import { Trade as V3Trade } from '@uniswap/v3-sdk'
|
||||
import { useCallback, useMemo } from 'react'
|
||||
import { SWAP_ROUTER_ADDRESSES, V2_ROUTER_ADDRESS } from '../constants/addresses'
|
||||
import { TransactionType } from '../state/transactions/actions'
|
||||
import { useTransactionAdder, useHasPendingApproval } from '../state/transactions/hooks'
|
||||
import { calculateGasMargin } from '../utils/calculateGasMargin'
|
||||
import { useTokenContract } from './useContract'
|
||||
@ -88,10 +89,7 @@ export function useApproveCallback(
|
||||
gasLimit: calculateGasMargin(chainId, estimatedGas),
|
||||
})
|
||||
.then((response: TransactionResponse) => {
|
||||
addTransaction(response, {
|
||||
summary: 'Approve ' + amountToApprove.currency.symbol,
|
||||
approval: { tokenAddress: token.address, spender },
|
||||
})
|
||||
addTransaction(response, { type: TransactionType.APPROVAL, tokenAddress: token.address, spender })
|
||||
})
|
||||
.catch((error: Error) => {
|
||||
console.debug('Failed to approve token', error)
|
||||
|
@ -5,11 +5,11 @@ import { SwapRouter, Trade as V3Trade } from '@uniswap/v3-sdk'
|
||||
import { Currency, Percent, TradeType } from '@uniswap/sdk-core'
|
||||
import { useMemo } from 'react'
|
||||
import { SWAP_ROUTER_ADDRESSES } from '../constants/addresses'
|
||||
import { TransactionType } from '../state/transactions/actions'
|
||||
import { calculateGasMargin } from '../utils/calculateGasMargin'
|
||||
import approveAmountCalldata from '../utils/approveAmountCalldata'
|
||||
import { getTradeVersion } from '../utils/getTradeVersion'
|
||||
import { useTransactionAdder } from '../state/transactions/hooks'
|
||||
import { isAddress, shortenAddress } from '../utils'
|
||||
import { currencyId } from '../utils/currencyId'
|
||||
import isZero from '../utils/isZero'
|
||||
import { useActiveWeb3React } from './web3'
|
||||
import { useArgentWalletContract } from './useArgentWalletContract'
|
||||
@ -17,7 +17,6 @@ import { useV2RouterContract } from './useContract'
|
||||
import { SignatureData } from './useERC20Permit'
|
||||
import useTransactionDeadline from './useTransactionDeadline'
|
||||
import useENS from './useENS'
|
||||
import { Version } from './useToggledVersion'
|
||||
|
||||
enum SwapCallbackState {
|
||||
INVALID,
|
||||
@ -334,28 +333,28 @@ export function useSwapCallback(
|
||||
...(value && !isZero(value) ? { value } : {}),
|
||||
})
|
||||
.then((response) => {
|
||||
const inputSymbol = trade.inputAmount.currency.symbol
|
||||
const outputSymbol = trade.outputAmount.currency.symbol
|
||||
const inputAmount = trade.inputAmount.toSignificant(4)
|
||||
const outputAmount = trade.outputAmount.toSignificant(4)
|
||||
|
||||
const base = `Swap ${inputAmount} ${inputSymbol} for ${outputAmount} ${outputSymbol}`
|
||||
const withRecipient =
|
||||
recipient === account
|
||||
? base
|
||||
: `${base} to ${
|
||||
recipientAddressOrName && isAddress(recipientAddressOrName)
|
||||
? shortenAddress(recipientAddressOrName)
|
||||
: recipientAddressOrName
|
||||
}`
|
||||
|
||||
const tradeVersion = getTradeVersion(trade)
|
||||
|
||||
const withVersion = tradeVersion === Version.v3 ? withRecipient : `${withRecipient} on ${tradeVersion}`
|
||||
|
||||
addTransaction(response, {
|
||||
summary: withVersion,
|
||||
})
|
||||
addTransaction(
|
||||
response,
|
||||
trade.tradeType === TradeType.EXACT_INPUT
|
||||
? {
|
||||
type: TransactionType.SWAP,
|
||||
tradeType: TradeType.EXACT_INPUT,
|
||||
inputCurrencyId: currencyId(trade.inputAmount.currency),
|
||||
inputCurrencyAmountRaw: trade.inputAmount.quotient.toString(),
|
||||
expectedOutputCurrencyAmountRaw: trade.outputAmount.quotient.toString(),
|
||||
outputCurrencyId: currencyId(trade.outputAmount.currency),
|
||||
minimumOutputCurrencyAmountRaw: trade.minimumAmountOut(allowedSlippage).quotient.toString(),
|
||||
}
|
||||
: {
|
||||
type: TransactionType.SWAP,
|
||||
tradeType: TradeType.EXACT_OUTPUT,
|
||||
inputCurrencyId: currencyId(trade.inputAmount.currency),
|
||||
maximumInputCurrencyAmountRaw: trade.maximumAmountIn(allowedSlippage).quotient.toString(),
|
||||
outputCurrencyId: currencyId(trade.outputAmount.currency),
|
||||
outputCurrencyAmountRaw: trade.outputAmount.quotient.toString(),
|
||||
expectedInputCurrencyAmountRaw: trade.inputAmount.quotient.toString(),
|
||||
}
|
||||
)
|
||||
|
||||
return response.hash
|
||||
})
|
||||
@ -373,5 +372,5 @@ export function useSwapCallback(
|
||||
},
|
||||
error: null,
|
||||
}
|
||||
}, [trade, library, account, chainId, recipient, recipientAddressOrName, swapCalls, addTransaction])
|
||||
}, [trade, library, account, chainId, recipient, recipientAddressOrName, swapCalls, addTransaction, allowedSlippage])
|
||||
}
|
||||
|
@ -2,10 +2,11 @@ import { Currency } from '@uniswap/sdk-core'
|
||||
import { useMemo } from 'react'
|
||||
import { WETH9_EXTENDED } from '../constants/tokens'
|
||||
import { tryParseAmount } from '../state/swap/hooks'
|
||||
import { TransactionType } from '../state/transactions/actions'
|
||||
import { useTransactionAdder } from '../state/transactions/hooks'
|
||||
import { useCurrencyBalance } from '../state/wallet/hooks'
|
||||
import { useActiveWeb3React } from './web3'
|
||||
import { useWETHContract } from './useContract'
|
||||
import { useActiveWeb3React } from './web3'
|
||||
|
||||
export enum WrapType {
|
||||
NOT_APPLICABLE,
|
||||
@ -48,7 +49,11 @@ export default function useWrapCallback(
|
||||
? async () => {
|
||||
try {
|
||||
const txReceipt = await wethContract.deposit({ value: `0x${inputAmount.quotient.toString(16)}` })
|
||||
addTransaction(txReceipt, { summary: `Wrap ${inputAmount.toSignificant(6)} ETH to WETH` })
|
||||
addTransaction(txReceipt, {
|
||||
type: TransactionType.WRAP,
|
||||
unwrapped: false,
|
||||
currencyAmountRaw: inputAmount?.quotient.toString(),
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('Could not deposit', error)
|
||||
}
|
||||
@ -64,7 +69,11 @@ export default function useWrapCallback(
|
||||
? async () => {
|
||||
try {
|
||||
const txReceipt = await wethContract.withdraw(`0x${inputAmount.quotient.toString(16)}`)
|
||||
addTransaction(txReceipt, { summary: `Unwrap ${inputAmount.toSignificant(6)} WETH to ETH` })
|
||||
addTransaction(txReceipt, {
|
||||
type: TransactionType.WRAP,
|
||||
unwrapped: true,
|
||||
currencyAmountRaw: inputAmount?.quotient.toString(),
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('Could not withdraw', error)
|
||||
}
|
||||
|
@ -1,54 +1,3 @@
|
||||
import { useCallback, useContext, useEffect, useState } from 'react'
|
||||
import { TransactionResponse } from '@ethersproject/providers'
|
||||
import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core'
|
||||
import { AlertTriangle } from 'react-feather'
|
||||
import ReactGA from 'react-ga'
|
||||
import { ZERO_PERCENT } from '../../constants/misc'
|
||||
import { NONFUNGIBLE_POSITION_MANAGER_ADDRESSES } from '../../constants/addresses'
|
||||
import { WETH9_EXTENDED } from '../../constants/tokens'
|
||||
import { useArgentWalletContract } from '../../hooks/useArgentWalletContract'
|
||||
import { useV3NFTPositionManagerContract } from '../../hooks/useContract'
|
||||
import { RouteComponentProps } from 'react-router-dom'
|
||||
import { Text } from 'rebass'
|
||||
import { ThemeContext } from 'styled-components/macro'
|
||||
import { ButtonError, ButtonLight, ButtonPrimary, ButtonText, ButtonYellow } from '../../components/Button'
|
||||
import { YellowCard, OutlineCard, BlueCard } from '../../components/Card'
|
||||
import { AutoColumn } from '../../components/Column'
|
||||
import TransactionConfirmationModal, { ConfirmationModalContent } from '../../components/TransactionConfirmationModal'
|
||||
import CurrencyInputPanel from '../../components/CurrencyInputPanel'
|
||||
import Row, { RowBetween, RowFixed, AutoRow } from '../../components/Row'
|
||||
import { useIsSwapUnsupported } from '../../hooks/useIsSwapUnsupported'
|
||||
import { useUSDCValue } from '../../hooks/useUSDCPrice'
|
||||
import approveAmountCalldata from '../../utils/approveAmountCalldata'
|
||||
import { calculateGasMargin } from '../../utils/calculateGasMargin'
|
||||
import { Review } from './Review'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import { useCurrency } from '../../hooks/Tokens'
|
||||
import { ApprovalState, useApproveCallback } from '../../hooks/useApproveCallback'
|
||||
import useTransactionDeadline from '../../hooks/useTransactionDeadline'
|
||||
import { useWalletModalToggle } from '../../state/application/hooks'
|
||||
import { Field, Bound } from '../../state/mint/v3/actions'
|
||||
import { useTransactionAdder } from '../../state/transactions/hooks'
|
||||
import { useIsExpertMode, useUserSlippageToleranceWithDefault } from '../../state/user/hooks'
|
||||
import { TYPE, ExternalLink } from '../../theme'
|
||||
import { maxAmountSpend } from '../../utils/maxAmountSpend'
|
||||
import { Dots } from '../Pool/styleds'
|
||||
import { currencyId } from '../../utils/currencyId'
|
||||
import UnsupportedCurrencyFooter from 'components/swap/UnsupportedCurrencyFooter'
|
||||
import {
|
||||
DynamicSection,
|
||||
CurrencyDropdown,
|
||||
StyledInput,
|
||||
Wrapper,
|
||||
ScrollablePage,
|
||||
ResponsiveTwoColumns,
|
||||
PageWrapper,
|
||||
StackedContainer,
|
||||
StackedItem,
|
||||
RightContainer,
|
||||
MediumOnly,
|
||||
HideMedium,
|
||||
} from './styled'
|
||||
import { Trans, t } from '@lingui/macro'
|
||||
import {
|
||||
useV3MintState,
|
||||
@ -57,21 +6,72 @@ import {
|
||||
useV3DerivedMintInfo,
|
||||
} from 'state/mint/v3/hooks'
|
||||
import { FeeAmount, NonfungiblePositionManager } from '@uniswap/v3-sdk'
|
||||
import { useV3PositionFromTokenId } from 'hooks/useV3Positions'
|
||||
import { useDerivedPositionInfo } from 'hooks/useDerivedPositionInfo'
|
||||
import { PositionPreview } from 'components/PositionPreview'
|
||||
import FeeSelector from 'components/FeeSelector'
|
||||
import RangeSelector from 'components/RangeSelector'
|
||||
import PresetsButtons from 'components/RangeSelector/PresetsButtons'
|
||||
import RateToggle from 'components/RateToggle'
|
||||
import { BigNumber } from '@ethersproject/bignumber'
|
||||
import { AddRemoveTabs } from 'components/NavigationTabs'
|
||||
import HoverInlineText from 'components/HoverInlineText'
|
||||
import { SwitchLocaleLink } from 'components/SwitchLocaleLink'
|
||||
import LiquidityChartRangeInput from 'components/LiquidityChartRangeInput'
|
||||
import { SupportedChainId } from 'constants/chains'
|
||||
import DowntimeWarning from 'components/DowntimeWarning'
|
||||
import { CHAIN_INFO } from '../../constants/chains'
|
||||
import { TransactionResponse } from '@ethersproject/providers'
|
||||
import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core'
|
||||
import UnsupportedCurrencyFooter from 'components/swap/UnsupportedCurrencyFooter'
|
||||
import { useCallback, useContext, useEffect, useState } from 'react'
|
||||
import { AlertTriangle } from 'react-feather'
|
||||
import ReactGA from 'react-ga'
|
||||
import { RouteComponentProps } from 'react-router-dom'
|
||||
import { Text } from 'rebass'
|
||||
import { ThemeContext } from 'styled-components/macro'
|
||||
import { ButtonError, ButtonLight, ButtonPrimary, ButtonText, ButtonYellow } from '../../components/Button'
|
||||
import { BlueCard, OutlineCard, YellowCard } from '../../components/Card'
|
||||
import { AutoColumn } from '../../components/Column'
|
||||
import CurrencyInputPanel from '../../components/CurrencyInputPanel'
|
||||
import FeeSelector from '../../components/FeeSelector'
|
||||
import HoverInlineText from '../../components/HoverInlineText'
|
||||
import LiquidityChartRangeInput from '../../components/LiquidityChartRangeInput'
|
||||
import { AddRemoveTabs } from '../../components/NavigationTabs'
|
||||
import { PositionPreview } from '../../components/PositionPreview'
|
||||
import RangeSelector from '../../components/RangeSelector'
|
||||
import PresetsButtons from '../../components/RangeSelector/PresetsButtons'
|
||||
import RateToggle from '../../components/RateToggle'
|
||||
import Row, { AutoRow, RowBetween, RowFixed } from '../../components/Row'
|
||||
import { SwitchLocaleLink } from '../../components/SwitchLocaleLink'
|
||||
import TransactionConfirmationModal, { ConfirmationModalContent } from '../../components/TransactionConfirmationModal'
|
||||
import { NONFUNGIBLE_POSITION_MANAGER_ADDRESSES } from '../../constants/addresses'
|
||||
import { CHAIN_INFO, SupportedChainId } from '../../constants/chains'
|
||||
import { ZERO_PERCENT } from '../../constants/misc'
|
||||
import { WETH9_EXTENDED } from '../../constants/tokens'
|
||||
import { useCurrency } from '../../hooks/Tokens'
|
||||
import { ApprovalState, useApproveCallback } from '../../hooks/useApproveCallback'
|
||||
import { useArgentWalletContract } from '../../hooks/useArgentWalletContract'
|
||||
import { useV3NFTPositionManagerContract } from '../../hooks/useContract'
|
||||
import { useDerivedPositionInfo } from '../../hooks/useDerivedPositionInfo'
|
||||
import { useIsSwapUnsupported } from '../../hooks/useIsSwapUnsupported'
|
||||
import useTransactionDeadline from '../../hooks/useTransactionDeadline'
|
||||
import { useUSDCValue } from '../../hooks/useUSDCPrice'
|
||||
import { useV3PositionFromTokenId } from '../../hooks/useV3Positions'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import { useWalletModalToggle } from '../../state/application/hooks'
|
||||
import { Bound, Field } from '../../state/mint/v3/actions'
|
||||
import { TransactionType } from '../../state/transactions/actions'
|
||||
import { useTransactionAdder } from '../../state/transactions/hooks'
|
||||
import { useIsExpertMode, useUserSlippageToleranceWithDefault } from '../../state/user/hooks'
|
||||
import { ExternalLink, TYPE } from '../../theme'
|
||||
import approveAmountCalldata from '../../utils/approveAmountCalldata'
|
||||
import { calculateGasMargin } from '../../utils/calculateGasMargin'
|
||||
import { currencyId } from '../../utils/currencyId'
|
||||
import { maxAmountSpend } from '../../utils/maxAmountSpend'
|
||||
import { Dots } from '../Pool/styleds'
|
||||
import { Review } from './Review'
|
||||
import {
|
||||
CurrencyDropdown,
|
||||
DynamicSection,
|
||||
HideMedium,
|
||||
MediumOnly,
|
||||
PageWrapper,
|
||||
ResponsiveTwoColumns,
|
||||
RightContainer,
|
||||
ScrollablePage,
|
||||
StackedContainer,
|
||||
StackedItem,
|
||||
StyledInput,
|
||||
Wrapper,
|
||||
} from './styled'
|
||||
|
||||
const DEFAULT_ADD_IN_RANGE_SLIPPAGE_TOLERANCE = new Percent(50, 10_000)
|
||||
|
||||
@ -208,11 +208,7 @@ export default function AddLiquidity({
|
||||
async function onCreate() {
|
||||
if (!chainId || !library) return
|
||||
|
||||
if (!positionManager || !baseCurrency || !quoteCurrency) {
|
||||
return
|
||||
}
|
||||
|
||||
if (position && account && deadline) {
|
||||
if (chainId && library && position && account && deadline && baseCurrency && quoteCurrency && positionManager) {
|
||||
const { calldata, value } = NonfungiblePositionManager.createCallParameters(position.pool)
|
||||
|
||||
const txn: { to: string; data: string; value: string } = {
|
||||
@ -237,7 +233,9 @@ export default function AddLiquidity({
|
||||
.then((response: TransactionResponse) => {
|
||||
setAttemptingTxn(false)
|
||||
addTransaction(response, {
|
||||
summary: t`Create ${baseCurrency?.symbol}/${quoteCurrency?.symbol} V3 pool`,
|
||||
type: TransactionType.CREATE_V3_POOL,
|
||||
baseCurrencyId: currencyId(baseCurrency),
|
||||
quoteCurrencyId: currencyId(quoteCurrency),
|
||||
})
|
||||
// dont set txn hash as we dont want submitted txn screen for create
|
||||
ReactGA.event({
|
||||
@ -332,9 +330,13 @@ export default function AddLiquidity({
|
||||
.then((response: TransactionResponse) => {
|
||||
setAttemptingTxn(false)
|
||||
addTransaction(response, {
|
||||
summary: noLiquidity
|
||||
? t`Create pool and add ${baseCurrency?.symbol}/${quoteCurrency?.symbol} V3 liquidity`
|
||||
: t`Add ${baseCurrency?.symbol}/${quoteCurrency?.symbol} V3 liquidity`,
|
||||
type: TransactionType.ADD_LIQUIDITY_V3_POOL,
|
||||
baseCurrencyId: currencyId(baseCurrency),
|
||||
quoteCurrencyId: currencyId(quoteCurrency),
|
||||
createPool: Boolean(noLiquidity),
|
||||
expectedAmountBaseRaw: parsedAmounts[Field.CURRENCY_A]?.quotient?.toString() ?? '0',
|
||||
expectedAmountQuoteRaw: parsedAmounts[Field.CURRENCY_B]?.quotient?.toString() ?? '0',
|
||||
feeAmount: position.pool.fee,
|
||||
})
|
||||
setTxHash(response.hash)
|
||||
ReactGA.event({
|
||||
|
@ -1,6 +1,9 @@
|
||||
import { BigNumber } from '@ethersproject/bignumber'
|
||||
import { TransactionResponse } from '@ethersproject/providers'
|
||||
import { t, Trans } from '@lingui/macro'
|
||||
import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core'
|
||||
import UnsupportedCurrencyFooter from 'components/swap/UnsupportedCurrencyFooter'
|
||||
import { SwitchLocaleLink } from 'components/SwitchLocaleLink'
|
||||
import { useCallback, useContext, useState } from 'react'
|
||||
import { Plus } from 'react-feather'
|
||||
import ReactGA from 'react-ga'
|
||||
@ -10,40 +13,38 @@ import { ThemeContext } from 'styled-components/macro'
|
||||
import { ButtonError, ButtonLight, ButtonPrimary } from '../../components/Button'
|
||||
import { BlueCard, LightCard } from '../../components/Card'
|
||||
import { AutoColumn, ColumnCenter } from '../../components/Column'
|
||||
import TransactionConfirmationModal, { ConfirmationModalContent } from '../../components/TransactionConfirmationModal'
|
||||
import CurrencyInputPanel from '../../components/CurrencyInputPanel'
|
||||
import DoubleCurrencyLogo from '../../components/DoubleLogo'
|
||||
import { AddRemoveTabs } from '../../components/NavigationTabs'
|
||||
import { MinimalPositionCard } from '../../components/PositionCard'
|
||||
import Row, { RowBetween, RowFlat } from '../../components/Row'
|
||||
import TransactionConfirmationModal, { ConfirmationModalContent } from '../../components/TransactionConfirmationModal'
|
||||
|
||||
import { ZERO_PERCENT } from '../../constants/misc'
|
||||
import { WETH9_EXTENDED } from '../../constants/tokens'
|
||||
import { useV2RouterContract } from '../../hooks/useContract'
|
||||
import { PairState } from '../../hooks/useV2Pairs'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import { useCurrency } from '../../hooks/Tokens'
|
||||
import { ApprovalState, useApproveCallback } from '../../hooks/useApproveCallback'
|
||||
import { useV2RouterContract } from '../../hooks/useContract'
|
||||
import { useIsSwapUnsupported } from '../../hooks/useIsSwapUnsupported'
|
||||
import useTransactionDeadline from '../../hooks/useTransactionDeadline'
|
||||
import { PairState } from '../../hooks/useV2Pairs'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import { useWalletModalToggle } from '../../state/application/hooks'
|
||||
import { Field } from '../../state/mint/actions'
|
||||
import { useDerivedMintInfo, useMintActionHandlers, useMintState } from '../../state/mint/hooks'
|
||||
import { TransactionType } from '../../state/transactions/actions'
|
||||
|
||||
import { useTransactionAdder } from '../../state/transactions/hooks'
|
||||
import { useIsExpertMode, useUserSlippageToleranceWithDefault } from '../../state/user/hooks'
|
||||
import { TYPE } from '../../theme'
|
||||
import { calculateGasMargin } from '../../utils/calculateGasMargin'
|
||||
import { calculateSlippageAmount } from '../../utils/calculateSlippageAmount'
|
||||
import { currencyId } from '../../utils/currencyId'
|
||||
import { maxAmountSpend } from '../../utils/maxAmountSpend'
|
||||
import AppBody from '../AppBody'
|
||||
import { Dots, Wrapper } from '../Pool/styleds'
|
||||
import { ConfirmAddModalBottom } from './ConfirmAddModalBottom'
|
||||
import { currencyId } from '../../utils/currencyId'
|
||||
import { PoolPriceBar } from './PoolPriceBar'
|
||||
import UnsupportedCurrencyFooter from 'components/swap/UnsupportedCurrencyFooter'
|
||||
import { SwitchLocaleLink } from 'components/SwitchLocaleLink'
|
||||
import { t, Trans } from '@lingui/macro'
|
||||
|
||||
const DEFAULT_ADD_V2_SLIPPAGE_TOLERANCE = new Percent(50, 10_000)
|
||||
|
||||
@ -189,9 +190,11 @@ export default function AddLiquidity({
|
||||
setAttemptingTxn(false)
|
||||
|
||||
addTransaction(response, {
|
||||
summary: t`Add ${parsedAmounts[Field.CURRENCY_A]?.toSignificant(3)} ${
|
||||
currencies[Field.CURRENCY_A]?.symbol
|
||||
} and ${parsedAmounts[Field.CURRENCY_B]?.toSignificant(3)} ${currencies[Field.CURRENCY_B]?.symbol}`,
|
||||
type: TransactionType.ADD_LIQUIDITY_V2_POOL,
|
||||
baseCurrencyId: currencyId(currencyA),
|
||||
expectedAmountBaseRaw: parsedAmounts[Field.CURRENCY_A]?.quotient.toString() ?? '0',
|
||||
quoteCurrencyId: currencyId(currencyB),
|
||||
expectedAmountQuoteRaw: parsedAmounts[Field.CURRENCY_B]?.quotient.toString() ?? '0',
|
||||
})
|
||||
|
||||
setTxHash(response.hash)
|
||||
|
@ -1,55 +1,57 @@
|
||||
import { Contract } from '@ethersproject/contracts'
|
||||
import { TransactionResponse } from '@ethersproject/providers'
|
||||
import { Trans } from '@lingui/macro'
|
||||
import { CurrencyAmount, Fraction, Percent, Price, Token } from '@uniswap/sdk-core'
|
||||
import { FeeAmount, Pool, Position, priceToClosestTick, TickMath } from '@uniswap/v3-sdk'
|
||||
import Badge, { BadgeVariant } from 'components/Badge'
|
||||
import { ButtonConfirmed } from 'components/Button'
|
||||
import { BlueCard, DarkGreyCard, LightCard, YellowCard } from 'components/Card'
|
||||
import DoubleCurrencyLogo from 'components/DoubleLogo'
|
||||
import FeeSelector from 'components/FeeSelector'
|
||||
import RangeSelector from 'components/RangeSelector'
|
||||
import RateToggle from 'components/RateToggle'
|
||||
import SettingsTab from 'components/Settings'
|
||||
import { Dots } from 'components/swap/styleds'
|
||||
import { ApprovalState, useApproveCallback } from 'hooks/useApproveCallback'
|
||||
import useCurrentBlockTimestamp from 'hooks/useCurrentBlockTimestamp'
|
||||
import { PoolState, usePool } from 'hooks/usePools'
|
||||
import useTheme from 'hooks/useTheme'
|
||||
import useTransactionDeadline from 'hooks/useTransactionDeadline'
|
||||
import JSBI from 'jsbi'
|
||||
import { useCallback, useMemo, useState, useEffect, ReactNode } from 'react'
|
||||
import { Fraction, Percent, Price, Token, CurrencyAmount } from '@uniswap/sdk-core'
|
||||
import { ReactNode, useCallback, useEffect, useMemo, useState } from 'react'
|
||||
import { AlertCircle, AlertTriangle, ArrowDown } from 'react-feather'
|
||||
import ReactGA from 'react-ga'
|
||||
import { Redirect, RouteComponentProps } from 'react-router'
|
||||
import { Text } from 'rebass'
|
||||
|
||||
import { useAppDispatch } from 'state/hooks'
|
||||
import { Bound, resetMintState } from 'state/mint/v3/actions'
|
||||
import { useRangeHopCallbacks, useV3DerivedMintInfo, useV3MintActionHandlers } from 'state/mint/v3/hooks'
|
||||
import { useIsTransactionPending, useTransactionAdder } from 'state/transactions/hooks'
|
||||
import { useUserSlippageToleranceWithDefault } from 'state/user/hooks'
|
||||
import { formatCurrencyAmount } from 'utils/formatCurrencyAmount'
|
||||
import { unwrappedToken } from 'utils/unwrappedToken'
|
||||
import { AutoColumn } from '../../components/Column'
|
||||
import CurrencyLogo from '../../components/CurrencyLogo'
|
||||
import FormattedCurrencyAmount from '../../components/FormattedCurrencyAmount'
|
||||
import { AutoRow, RowBetween, RowFixed } from '../../components/Row'
|
||||
import { V2_FACTORY_ADDRESSES } from '../../constants/addresses'
|
||||
import { WETH9_EXTENDED } from '../../constants/tokens'
|
||||
import { useToken } from '../../hooks/Tokens'
|
||||
import { usePairContract, useV2MigratorContract } from '../../hooks/useContract'
|
||||
import { useV2LiquidityTokenPermit } from '../../hooks/useERC20Permit'
|
||||
import useIsArgentWallet from '../../hooks/useIsArgentWallet'
|
||||
import { useTotalSupply } from '../../hooks/useTotalSupply'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import { useToken } from '../../hooks/Tokens'
|
||||
import { usePairContract, useV2MigratorContract } from '../../hooks/useContract'
|
||||
import { NEVER_RELOAD, useSingleCallResult } from '../../state/multicall/hooks'
|
||||
import { TransactionType } from '../../state/transactions/actions'
|
||||
import { useTokenBalance } from '../../state/wallet/hooks'
|
||||
import { BackArrow, ExternalLink, TYPE } from '../../theme'
|
||||
import { isAddress } from '../../utils'
|
||||
import { calculateGasMargin } from '../../utils/calculateGasMargin'
|
||||
import { getExplorerLink, ExplorerDataType } from '../../utils/getExplorerLink'
|
||||
import { currencyId } from '../../utils/currencyId'
|
||||
import { ExplorerDataType, getExplorerLink } from '../../utils/getExplorerLink'
|
||||
import { BodyWrapper } from '../AppBody'
|
||||
import { PoolState, usePool } from 'hooks/usePools'
|
||||
import { FeeAmount, Pool, Position, priceToClosestTick, TickMath } from '@uniswap/v3-sdk'
|
||||
import { BlueCard, DarkGreyCard, LightCard, YellowCard } from 'components/Card'
|
||||
import { ApprovalState, useApproveCallback } from 'hooks/useApproveCallback'
|
||||
import { Dots } from 'components/swap/styleds'
|
||||
import { ButtonConfirmed } from 'components/Button'
|
||||
import useTransactionDeadline from 'hooks/useTransactionDeadline'
|
||||
import { useUserSlippageToleranceWithDefault } from 'state/user/hooks'
|
||||
import ReactGA from 'react-ga'
|
||||
import { TransactionResponse } from '@ethersproject/providers'
|
||||
import { useIsTransactionPending, useTransactionAdder } from 'state/transactions/hooks'
|
||||
import { useV3DerivedMintInfo, useRangeHopCallbacks, useV3MintActionHandlers } from 'state/mint/v3/hooks'
|
||||
import { Bound, resetMintState } from 'state/mint/v3/actions'
|
||||
import { Trans } from '@lingui/macro'
|
||||
import { AlertCircle, AlertTriangle, ArrowDown } from 'react-feather'
|
||||
import FeeSelector from 'components/FeeSelector'
|
||||
import RangeSelector from 'components/RangeSelector'
|
||||
import RateToggle from 'components/RateToggle'
|
||||
import { Contract } from '@ethersproject/contracts'
|
||||
import useCurrentBlockTimestamp from 'hooks/useCurrentBlockTimestamp'
|
||||
import { formatCurrencyAmount } from 'utils/formatCurrencyAmount'
|
||||
import useTheme from 'hooks/useTheme'
|
||||
import { unwrappedToken } from 'utils/unwrappedToken'
|
||||
import DoubleCurrencyLogo from 'components/DoubleLogo'
|
||||
import Badge, { BadgeVariant } from 'components/Badge'
|
||||
|
||||
import { useAppDispatch } from 'state/hooks'
|
||||
import SettingsTab from 'components/Settings'
|
||||
|
||||
const ZERO = JSBI.BigInt(0)
|
||||
|
||||
@ -341,7 +343,10 @@ function V2PairMigration({
|
||||
})
|
||||
|
||||
addTransaction(response, {
|
||||
summary: `Migrate ${currency0.symbol}/${currency1.symbol} liquidity to V3`,
|
||||
type: TransactionType.MIGRATE_LIQUIDITY_V3,
|
||||
baseCurrencyId: currencyId(currency0),
|
||||
quoteCurrencyId: currencyId(currency1),
|
||||
isFork: isNotUniswap,
|
||||
})
|
||||
setPendingMigrationHash(response.hash)
|
||||
})
|
||||
|
@ -1,49 +1,50 @@
|
||||
import { useCallback, useMemo, useRef, useState } from 'react'
|
||||
import { BigNumber } from '@ethersproject/bignumber'
|
||||
import { TransactionResponse } from '@ethersproject/providers'
|
||||
import { Trans } from '@lingui/macro'
|
||||
import { Currency, CurrencyAmount, Fraction, Percent, Price, Token } from '@uniswap/sdk-core'
|
||||
import { NonfungiblePositionManager, Pool, Position } from '@uniswap/v3-sdk'
|
||||
import Badge from 'components/Badge'
|
||||
import { ButtonConfirmed, ButtonGray, ButtonPrimary } from 'components/Button'
|
||||
import { DarkCard, LightCard } from 'components/Card'
|
||||
import { AutoColumn } from 'components/Column'
|
||||
import CurrencyLogo from 'components/CurrencyLogo'
|
||||
import DoubleCurrencyLogo from 'components/DoubleLogo'
|
||||
import Loader from 'components/Loader'
|
||||
import { RowBetween, RowFixed } from 'components/Row'
|
||||
import { Dots } from 'components/swap/styleds'
|
||||
import Toggle from 'components/Toggle'
|
||||
import TransactionConfirmationModal, { ConfirmationModalContent } from 'components/TransactionConfirmationModal'
|
||||
import { SupportedChainId } from 'constants/chains'
|
||||
import { useToken } from 'hooks/Tokens'
|
||||
import { useV3NFTPositionManagerContract } from 'hooks/useContract'
|
||||
import useIsTickAtLimit from 'hooks/useIsTickAtLimit'
|
||||
|
||||
import { PoolState, usePool } from 'hooks/usePools'
|
||||
import { useToken } from 'hooks/Tokens'
|
||||
import useUSDCPrice from 'hooks/useUSDCPrice'
|
||||
import { useV3PositionFees } from 'hooks/useV3PositionFees'
|
||||
import { useV3PositionFromTokenId } from 'hooks/useV3Positions'
|
||||
import { useActiveWeb3React } from 'hooks/web3'
|
||||
import { useCallback, useMemo, useRef, useState } from 'react'
|
||||
import ReactGA from 'react-ga'
|
||||
import { Link, RouteComponentProps } from 'react-router-dom'
|
||||
import { unwrappedToken } from 'utils/unwrappedToken'
|
||||
import { usePositionTokenURI } from '../../hooks/usePositionTokenURI'
|
||||
import { calculateGasMargin } from '../../utils/calculateGasMargin'
|
||||
import { getExplorerLink, ExplorerDataType } from '../../utils/getExplorerLink'
|
||||
import { Bound } from 'state/mint/v3/actions'
|
||||
import { useSingleCallResult } from 'state/multicall/hooks'
|
||||
import { useIsTransactionPending, useTransactionAdder } from 'state/transactions/hooks'
|
||||
import styled from 'styled-components/macro'
|
||||
import { AutoColumn } from 'components/Column'
|
||||
import { RowBetween, RowFixed } from 'components/Row'
|
||||
import DoubleCurrencyLogo from 'components/DoubleLogo'
|
||||
import { ExternalLink, HideExtraSmall, TYPE } from 'theme'
|
||||
import Badge from 'components/Badge'
|
||||
import { ButtonConfirmed, ButtonPrimary, ButtonGray } from 'components/Button'
|
||||
import { DarkCard, LightCard } from 'components/Card'
|
||||
import CurrencyLogo from 'components/CurrencyLogo'
|
||||
import { Trans } from '@lingui/macro'
|
||||
import { currencyId } from 'utils/currencyId'
|
||||
import { formatCurrencyAmount } from 'utils/formatCurrencyAmount'
|
||||
import { useV3PositionFees } from 'hooks/useV3PositionFees'
|
||||
import { BigNumber } from '@ethersproject/bignumber'
|
||||
import { Token, Currency, CurrencyAmount, Percent, Fraction, Price } from '@uniswap/sdk-core'
|
||||
import { useActiveWeb3React } from 'hooks/web3'
|
||||
import { useV3NFTPositionManagerContract } from 'hooks/useContract'
|
||||
import { useIsTransactionPending, useTransactionAdder } from 'state/transactions/hooks'
|
||||
import ReactGA from 'react-ga'
|
||||
import TransactionConfirmationModal, { ConfirmationModalContent } from 'components/TransactionConfirmationModal'
|
||||
import { TransactionResponse } from '@ethersproject/providers'
|
||||
import { Dots } from 'components/swap/styleds'
|
||||
import { getPriceOrderingFromPositionForUI } from '../../components/PositionListItem'
|
||||
import useTheme from '../../hooks/useTheme'
|
||||
import RateToggle from '../../components/RateToggle'
|
||||
import { useSingleCallResult } from 'state/multicall/hooks'
|
||||
import RangeBadge from '../../components/Badge/RangeBadge'
|
||||
import { SwitchLocaleLink } from '../../components/SwitchLocaleLink'
|
||||
import useUSDCPrice from 'hooks/useUSDCPrice'
|
||||
import Loader from 'components/Loader'
|
||||
import Toggle from 'components/Toggle'
|
||||
import { Bound } from 'state/mint/v3/actions'
|
||||
import useIsTickAtLimit from 'hooks/useIsTickAtLimit'
|
||||
import { formatTickPrice } from 'utils/formatTickPrice'
|
||||
import { SupportedChainId } from 'constants/chains'
|
||||
import { unwrappedToken } from 'utils/unwrappedToken'
|
||||
import RangeBadge from '../../components/Badge/RangeBadge'
|
||||
import { getPriceOrderingFromPositionForUI } from '../../components/PositionListItem'
|
||||
import RateToggle from '../../components/RateToggle'
|
||||
import { SwitchLocaleLink } from '../../components/SwitchLocaleLink'
|
||||
import { usePositionTokenURI } from '../../hooks/usePositionTokenURI'
|
||||
import useTheme from '../../hooks/useTheme'
|
||||
import { TransactionType } from '../../state/transactions/actions'
|
||||
import { calculateGasMargin } from '../../utils/calculateGasMargin'
|
||||
import { ExplorerDataType, getExplorerLink } from '../../utils/getExplorerLink'
|
||||
import { LoadingRows } from './styleds'
|
||||
|
||||
const PageWrapper = styled.div`
|
||||
@ -459,7 +460,9 @@ export function PositionPage({
|
||||
})
|
||||
|
||||
addTransaction(response, {
|
||||
summary: `Collect ${feeValue0.currency.symbol}/${feeValue1.currency.symbol} fees`,
|
||||
type: TransactionType.COLLECT_FEES,
|
||||
currencyId0: currencyId(feeValue0.currency),
|
||||
currencyId1: currencyId(feeValue1.currency),
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -1,41 +1,43 @@
|
||||
import { useCallback, useMemo, useState } from 'react'
|
||||
import { useV3PositionFromTokenId } from 'hooks/useV3Positions'
|
||||
import { Redirect, RouteComponentProps } from 'react-router-dom'
|
||||
import { WETH9_EXTENDED } from '../../constants/tokens'
|
||||
import { calculateGasMargin } from '../../utils/calculateGasMargin'
|
||||
import AppBody from '../AppBody'
|
||||
import { BigNumber } from '@ethersproject/bignumber'
|
||||
import useDebouncedChangeHandler from 'hooks/useDebouncedChangeHandler'
|
||||
import { useBurnV3ActionHandlers, useBurnV3State, useDerivedV3BurnInfo } from 'state/burn/v3/hooks'
|
||||
import Slider from 'components/Slider'
|
||||
import { AutoRow, RowBetween, RowFixed } from 'components/Row'
|
||||
import TransactionConfirmationModal, { ConfirmationModalContent } from '../../components/TransactionConfirmationModal'
|
||||
import { AutoColumn } from 'components/Column'
|
||||
import { TransactionResponse } from '@ethersproject/providers'
|
||||
import { Trans } from '@lingui/macro'
|
||||
import { Percent } from '@uniswap/sdk-core'
|
||||
import { NonfungiblePositionManager } from '@uniswap/v3-sdk'
|
||||
import RangeBadge from 'components/Badge/RangeBadge'
|
||||
import { ButtonConfirmed, ButtonPrimary } from 'components/Button'
|
||||
import { LightCard } from 'components/Card'
|
||||
import { Text } from 'rebass'
|
||||
import { AutoColumn } from 'components/Column'
|
||||
import CurrencyLogo from 'components/CurrencyLogo'
|
||||
import FormattedCurrencyAmount from 'components/FormattedCurrencyAmount'
|
||||
import { useV3NFTPositionManagerContract } from 'hooks/useContract'
|
||||
import { useUserSlippageToleranceWithDefault } from 'state/user/hooks'
|
||||
import useTransactionDeadline from 'hooks/useTransactionDeadline'
|
||||
import ReactGA from 'react-ga'
|
||||
import { useActiveWeb3React } from 'hooks/web3'
|
||||
import { TransactionResponse } from '@ethersproject/providers'
|
||||
import { useTransactionAdder } from 'state/transactions/hooks'
|
||||
import { Percent } from '@uniswap/sdk-core'
|
||||
import { TYPE } from 'theme'
|
||||
import { Wrapper, SmallMaxButton, ResponsiveHeaderText } from './styled'
|
||||
import Loader from 'components/Loader'
|
||||
import DoubleCurrencyLogo from 'components/DoubleLogo'
|
||||
import { Break } from 'components/earn/styled'
|
||||
import { NonfungiblePositionManager } from '@uniswap/v3-sdk'
|
||||
import useTheme from 'hooks/useTheme'
|
||||
import FormattedCurrencyAmount from 'components/FormattedCurrencyAmount'
|
||||
import Loader from 'components/Loader'
|
||||
import { AddRemoveTabs } from 'components/NavigationTabs'
|
||||
import RangeBadge from 'components/Badge/RangeBadge'
|
||||
import { AutoRow, RowBetween, RowFixed } from 'components/Row'
|
||||
import Slider from 'components/Slider'
|
||||
import Toggle from 'components/Toggle'
|
||||
import { t, Trans } from '@lingui/macro'
|
||||
import { SupportedChainId } from 'constants/chains'
|
||||
import { useV3NFTPositionManagerContract } from 'hooks/useContract'
|
||||
import useDebouncedChangeHandler from 'hooks/useDebouncedChangeHandler'
|
||||
import useTheme from 'hooks/useTheme'
|
||||
import useTransactionDeadline from 'hooks/useTransactionDeadline'
|
||||
import { useV3PositionFromTokenId } from 'hooks/useV3Positions'
|
||||
import { useActiveWeb3React } from 'hooks/web3'
|
||||
import { useCallback, useMemo, useState } from 'react'
|
||||
import ReactGA from 'react-ga'
|
||||
import { Redirect, RouteComponentProps } from 'react-router-dom'
|
||||
import { Text } from 'rebass'
|
||||
import { useBurnV3ActionHandlers, useBurnV3State, useDerivedV3BurnInfo } from 'state/burn/v3/hooks'
|
||||
import { useTransactionAdder } from 'state/transactions/hooks'
|
||||
import { useUserSlippageToleranceWithDefault } from 'state/user/hooks'
|
||||
import { TYPE } from 'theme'
|
||||
import TransactionConfirmationModal, { ConfirmationModalContent } from '../../components/TransactionConfirmationModal'
|
||||
import { WETH9_EXTENDED } from '../../constants/tokens'
|
||||
import { TransactionType } from '../../state/transactions/actions'
|
||||
import { calculateGasMargin } from '../../utils/calculateGasMargin'
|
||||
import { currencyId } from '../../utils/currencyId'
|
||||
import AppBody from '../AppBody'
|
||||
import { ResponsiveHeaderText, SmallMaxButton, Wrapper } from './styled'
|
||||
|
||||
const DEFAULT_REMOVE_V3_LIQUIDITY_SLIPPAGE_TOLERANCE = new Percent(5, 100)
|
||||
|
||||
@ -152,7 +154,11 @@ function Remove({ tokenId }: { tokenId: BigNumber }) {
|
||||
setTxnHash(response.hash)
|
||||
setAttemptingTxn(false)
|
||||
addTransaction(response, {
|
||||
summary: t`Remove ${liquidityValue0.currency.symbol}/${liquidityValue1.currency.symbol} V3 liquidity`,
|
||||
type: TransactionType.REMOVE_LIQUIDITY_V3,
|
||||
baseCurrencyId: currencyId(liquidityValue0.currency),
|
||||
quoteCurrencyId: currencyId(liquidityValue1.currency),
|
||||
expectedAmountBaseRaw: liquidityValue0.quotient.toString(),
|
||||
expectedAmountQuoteRaw: liquidityValue1.quotient.toString(),
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -187,9 +193,12 @@ function Remove({ tokenId }: { tokenId: BigNumber }) {
|
||||
setTxnHash('')
|
||||
}, [onPercentSelectForSlider, txnHash])
|
||||
|
||||
const pendingText = `Removing ${liquidityValue0?.toSignificant(6)} ${
|
||||
liquidityValue0?.currency?.symbol
|
||||
} and ${liquidityValue1?.toSignificant(6)} ${liquidityValue1?.currency?.symbol}`
|
||||
const pendingText = (
|
||||
<Trans>
|
||||
Removing {liquidityValue0?.toSignificant(6)} {liquidityValue0?.currency?.symbol} and{' '}
|
||||
{liquidityValue1?.toSignificant(6)} {liquidityValue1?.currency?.symbol}
|
||||
</Trans>
|
||||
)
|
||||
|
||||
function modalHeader() {
|
||||
return (
|
||||
|
@ -1,5 +1,7 @@
|
||||
import { BigNumber } from '@ethersproject/bignumber'
|
||||
import { Contract } from '@ethersproject/contracts'
|
||||
import { TransactionResponse } from '@ethersproject/providers'
|
||||
import { t, Trans } from '@lingui/macro'
|
||||
import { Currency, Percent } from '@uniswap/sdk-core'
|
||||
import { useCallback, useContext, useMemo, useState } from 'react'
|
||||
import { ArrowDown, Plus } from 'react-feather'
|
||||
@ -7,42 +9,40 @@ import ReactGA from 'react-ga'
|
||||
import { RouteComponentProps } from 'react-router'
|
||||
import { Text } from 'rebass'
|
||||
import { ThemeContext } from 'styled-components/macro'
|
||||
import { ButtonPrimary, ButtonLight, ButtonError, ButtonConfirmed } from '../../components/Button'
|
||||
import { ButtonConfirmed, ButtonError, ButtonLight, ButtonPrimary } from '../../components/Button'
|
||||
import { BlueCard, LightCard } from '../../components/Card'
|
||||
import { AutoColumn, ColumnCenter } from '../../components/Column'
|
||||
import TransactionConfirmationModal, { ConfirmationModalContent } from '../../components/TransactionConfirmationModal'
|
||||
import CurrencyInputPanel from '../../components/CurrencyInputPanel'
|
||||
import CurrencyLogo from '../../components/CurrencyLogo'
|
||||
import DoubleCurrencyLogo from '../../components/DoubleLogo'
|
||||
import { AddRemoveTabs } from '../../components/NavigationTabs'
|
||||
import { MinimalPositionCard } from '../../components/PositionCard'
|
||||
import Row, { RowBetween, RowFixed } from '../../components/Row'
|
||||
|
||||
import Slider from '../../components/Slider'
|
||||
import CurrencyLogo from '../../components/CurrencyLogo'
|
||||
import { Dots } from '../../components/swap/styleds'
|
||||
import TransactionConfirmationModal, { ConfirmationModalContent } from '../../components/TransactionConfirmationModal'
|
||||
import { WETH9_EXTENDED } from '../../constants/tokens'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import { useCurrency } from '../../hooks/Tokens'
|
||||
import { ApprovalState, useApproveCallback } from '../../hooks/useApproveCallback'
|
||||
import { usePairContract, useV2RouterContract } from '../../hooks/useContract'
|
||||
import useDebouncedChangeHandler from '../../hooks/useDebouncedChangeHandler'
|
||||
import { useV2LiquidityTokenPermit } from '../../hooks/useERC20Permit'
|
||||
import useTransactionDeadline from '../../hooks/useTransactionDeadline'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import { useWalletModalToggle } from '../../state/application/hooks'
|
||||
import { Field } from '../../state/burn/actions'
|
||||
import { useBurnActionHandlers, useBurnState, useDerivedBurnInfo } from '../../state/burn/hooks'
|
||||
import { TransactionType } from '../../state/transactions/actions'
|
||||
|
||||
import { useTransactionAdder } from '../../state/transactions/hooks'
|
||||
import { useUserSlippageToleranceWithDefault } from '../../state/user/hooks'
|
||||
import { StyledInternalLink, TYPE } from '../../theme'
|
||||
import { calculateGasMargin } from '../../utils/calculateGasMargin'
|
||||
import { calculateSlippageAmount } from '../../utils/calculateSlippageAmount'
|
||||
import { currencyId } from '../../utils/currencyId'
|
||||
import useDebouncedChangeHandler from '../../hooks/useDebouncedChangeHandler'
|
||||
import AppBody from '../AppBody'
|
||||
import { ClickableText, MaxButton, Wrapper } from '../Pool/styleds'
|
||||
import { useApproveCallback, ApprovalState } from '../../hooks/useApproveCallback'
|
||||
import { Dots } from '../../components/swap/styleds'
|
||||
import { useBurnActionHandlers } from '../../state/burn/hooks'
|
||||
import { useDerivedBurnInfo, useBurnState } from '../../state/burn/hooks'
|
||||
import { Field } from '../../state/burn/actions'
|
||||
import { useWalletModalToggle } from '../../state/application/hooks'
|
||||
import { useUserSlippageToleranceWithDefault } from '../../state/user/hooks'
|
||||
import { BigNumber } from '@ethersproject/bignumber'
|
||||
import { t, Trans } from '@lingui/macro'
|
||||
|
||||
const DEFAULT_REMOVE_LIQUIDITY_SLIPPAGE_TOLERANCE = new Percent(5, 100)
|
||||
|
||||
@ -267,9 +267,11 @@ export default function RemoveLiquidity({
|
||||
setAttemptingTxn(false)
|
||||
|
||||
addTransaction(response, {
|
||||
summary: t`Remove ${parsedAmounts[Field.CURRENCY_A]?.toSignificant(3)} ${
|
||||
currencyA?.symbol
|
||||
} and ${parsedAmounts[Field.CURRENCY_B]?.toSignificant(3)} ${currencyB?.symbol}`,
|
||||
type: TransactionType.REMOVE_LIQUIDITY_V3,
|
||||
baseCurrencyId: currencyId(currencyA),
|
||||
quoteCurrencyId: currencyId(currencyB),
|
||||
expectedAmountBaseRaw: parsedAmounts[Field.CURRENCY_A]?.quotient.toString() ?? '0',
|
||||
expectedAmountQuoteRaw: parsedAmounts[Field.CURRENCY_B]?.quotient.toString() ?? '0',
|
||||
})
|
||||
|
||||
setTxHash(response.hash)
|
||||
@ -277,7 +279,7 @@ export default function RemoveLiquidity({
|
||||
ReactGA.event({
|
||||
category: 'Liquidity',
|
||||
action: 'Remove',
|
||||
label: [currencyA?.symbol, currencyB?.symbol].join('/'),
|
||||
label: [currencyA.symbol, currencyB.symbol].join('/'),
|
||||
})
|
||||
})
|
||||
.catch((error: Error) => {
|
||||
|
@ -33,8 +33,8 @@ import {
|
||||
useProposalData,
|
||||
useUserDelegatee,
|
||||
useUserVotesAsOfBlock,
|
||||
VoteOption,
|
||||
} from '../../state/governance/hooks'
|
||||
import { VoteOption } from '../../state/governance/types'
|
||||
import { useTokenBalance } from '../../state/wallet/hooks'
|
||||
import { ExternalLink, StyledInternalLink, TYPE } from '../../theme'
|
||||
import { isAddress } from '../../utils'
|
||||
|
@ -3,8 +3,6 @@ import { createAction } from '@reduxjs/toolkit'
|
||||
export type PopupContent = {
|
||||
txn: {
|
||||
hash: string
|
||||
success: boolean
|
||||
summary?: string
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@ describe('application reducer', () => {
|
||||
beforeEach(() => {
|
||||
store = createStore(reducer, {
|
||||
chainId: null,
|
||||
chainConnectivityWarning: false,
|
||||
popupList: [],
|
||||
blockNumber: {
|
||||
[1]: 3,
|
||||
@ -18,23 +19,23 @@ describe('application reducer', () => {
|
||||
|
||||
describe('addPopup', () => {
|
||||
it('adds the popup to list with a generated id', () => {
|
||||
store.dispatch(addPopup({ content: { txn: { hash: 'abc', summary: 'test', success: true } } }))
|
||||
store.dispatch(addPopup({ content: { txn: { hash: 'abc' } } }))
|
||||
const list = store.getState().popupList
|
||||
expect(list).toHaveLength(1)
|
||||
expect(typeof list[0].key).toEqual('string')
|
||||
expect(list[0].show).toEqual(true)
|
||||
expect(list[0].content).toEqual({ txn: { hash: 'abc', summary: 'test', success: true } })
|
||||
expect(list[0].content).toEqual({ txn: { hash: 'abc' } })
|
||||
expect(list[0].removeAfterMs).toEqual(25000)
|
||||
})
|
||||
|
||||
it('replaces any existing popups with the same key', () => {
|
||||
store.dispatch(addPopup({ key: 'abc', content: { txn: { hash: 'abc', summary: 'test', success: true } } }))
|
||||
store.dispatch(addPopup({ key: 'abc', content: { txn: { hash: 'def', summary: 'test2', success: false } } }))
|
||||
store.dispatch(addPopup({ key: 'abc', content: { txn: { hash: 'abc' } } }))
|
||||
store.dispatch(addPopup({ key: 'abc', content: { txn: { hash: 'def' } } }))
|
||||
const list = store.getState().popupList
|
||||
expect(list).toHaveLength(1)
|
||||
expect(list[0].key).toEqual('abc')
|
||||
expect(list[0].show).toEqual(true)
|
||||
expect(list[0].content).toEqual({ txn: { hash: 'def', summary: 'test2', success: false } })
|
||||
expect(list[0].content).toEqual({ txn: { hash: 'def' } })
|
||||
expect(list[0].removeAfterMs).toEqual(25000)
|
||||
})
|
||||
})
|
||||
@ -82,7 +83,7 @@ describe('application reducer', () => {
|
||||
|
||||
describe('removePopup', () => {
|
||||
beforeEach(() => {
|
||||
store.dispatch(addPopup({ key: 'abc', content: { txn: { hash: 'abc', summary: 'test', success: true } } }))
|
||||
store.dispatch(addPopup({ key: 'abc', content: { txn: { hash: 'abc' } } }))
|
||||
})
|
||||
it('hides the popup', () => {
|
||||
expect(store.getState().popupList[0].show).toBe(true)
|
||||
|
@ -1,13 +1,14 @@
|
||||
import JSBI from 'jsbi'
|
||||
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
|
||||
import { TransactionResponse } from '@ethersproject/providers'
|
||||
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
|
||||
import JSBI from 'jsbi'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { UNI } from '../../constants/tokens'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import { useMerkleDistributorContract } from '../../hooks/useContract'
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import { isAddress } from '../../utils'
|
||||
import { calculateGasMargin } from '../../utils/calculateGasMargin'
|
||||
import { useSingleCallResult } from '../multicall/hooks'
|
||||
import { isAddress } from '../../utils'
|
||||
import { TransactionType } from '../transactions/actions'
|
||||
import { useTransactionAdder } from '../transactions/hooks'
|
||||
|
||||
interface UserClaimData {
|
||||
@ -165,8 +166,9 @@ export function useClaimCallback(account: string | null | undefined): {
|
||||
.claim(...args, { value: null, gasLimit: calculateGasMargin(chainId, estimatedGasLimit) })
|
||||
.then((response: TransactionResponse) => {
|
||||
addTransaction(response, {
|
||||
summary: `Claimed ${unclaimedAmount?.toSignificant(4)} UNI`,
|
||||
claim: { recipient: account },
|
||||
type: TransactionType.CLAIM,
|
||||
recipient: account,
|
||||
uniAmountRaw: unclaimedAmount?.quotient.toString(),
|
||||
})
|
||||
return response.hash
|
||||
})
|
||||
|
@ -28,7 +28,9 @@ import { BRAVO_START_BLOCK, UNISWAP_GRANTS_START_BLOCK } from '../../constants/p
|
||||
import { UNI } from '../../constants/tokens'
|
||||
import { useLogs } from '../logs/hooks'
|
||||
import { useSingleCallResult, useSingleContractMultipleData } from '../multicall/hooks'
|
||||
import { TransactionType } from '../transactions/actions'
|
||||
import { useTransactionAdder } from '../transactions/hooks'
|
||||
import { VoteOption } from './types'
|
||||
|
||||
interface ProposalDetail {
|
||||
target: string
|
||||
@ -300,7 +302,7 @@ export function useDelegateCallback(): (delegatee: string | undefined) => undefi
|
||||
|
||||
return useCallback(
|
||||
(delegatee: string | undefined) => {
|
||||
if (!library || !chainId || !account || !isAddress(delegatee ?? '')) return undefined
|
||||
if (!library || !chainId || !account || !delegatee || !isAddress(delegatee ?? '')) return undefined
|
||||
const args = [delegatee]
|
||||
if (!uniContract) throw new Error('No UNI Contract!')
|
||||
return uniContract.estimateGas.delegate(...args, {}).then((estimatedGasLimit) => {
|
||||
@ -308,7 +310,8 @@ export function useDelegateCallback(): (delegatee: string | undefined) => undefi
|
||||
.delegate(...args, { value: null, gasLimit: calculateGasMargin(chainId, estimatedGasLimit) })
|
||||
.then((response: TransactionResponse) => {
|
||||
addTransaction(response, {
|
||||
summary: t`Delegated votes`,
|
||||
type: TransactionType.DELEGATE,
|
||||
delegatee,
|
||||
})
|
||||
return response.hash
|
||||
})
|
||||
@ -318,12 +321,6 @@ export function useDelegateCallback(): (delegatee: string | undefined) => undefi
|
||||
)
|
||||
}
|
||||
|
||||
export enum VoteOption {
|
||||
Against,
|
||||
For,
|
||||
Abstain,
|
||||
}
|
||||
|
||||
export function useVoteCallback(): {
|
||||
voteCallback: (proposalId: string | undefined, voteOption: VoteOption) => undefined | Promise<string>
|
||||
} {
|
||||
@ -342,9 +339,11 @@ export function useVoteCallback(): {
|
||||
.castVote(...args, { value: null, gasLimit: calculateGasMargin(chainId, estimatedGasLimit) })
|
||||
.then((response: TransactionResponse) => {
|
||||
addTransaction(response, {
|
||||
summary: `Voted ${
|
||||
voteOption === VoteOption.Against ? 'against' : voteOption === VoteOption.For ? 'for' : 'to abstain on'
|
||||
} proposal ${proposalId}`,
|
||||
type: TransactionType.VOTE,
|
||||
decision: voteOption,
|
||||
governorAddress: latestGovernanceContract.address,
|
||||
proposalId: parseInt(proposalId),
|
||||
reason: '',
|
||||
})
|
||||
return response.hash
|
||||
})
|
||||
@ -380,7 +379,7 @@ export function useCreateProposalCallback(): (
|
||||
.propose(...args, { gasLimit: calculateGasMargin(chainId, estimatedGasLimit) })
|
||||
.then((response: TransactionResponse) => {
|
||||
addTransaction(response, {
|
||||
summary: t`Submitted new proposal`,
|
||||
type: TransactionType.SUBMIT_PROPOSAL,
|
||||
})
|
||||
return response.hash
|
||||
})
|
||||
|
5
src/state/governance/types.ts
Normal file
5
src/state/governance/types.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export enum VoteOption {
|
||||
Against,
|
||||
For,
|
||||
Abstain,
|
||||
}
|
@ -1,4 +1,6 @@
|
||||
import { createAction } from '@reduxjs/toolkit'
|
||||
import { TradeType } from '@uniswap/sdk-core'
|
||||
import { VoteOption } from '../governance/types'
|
||||
|
||||
export interface SerializableTransactionReceipt {
|
||||
to: string
|
||||
@ -11,14 +13,168 @@ export interface SerializableTransactionReceipt {
|
||||
status?: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Be careful adding to this enum, always assign a unique value (typescript will not prevent duplicate values).
|
||||
* These values is persisted in state and if you change the value it will cause errors
|
||||
*/
|
||||
export enum TransactionType {
|
||||
APPROVAL = 0,
|
||||
SWAP = 1,
|
||||
DEPOSIT_LIQUIDITY_STAKING = 2,
|
||||
WITHDRAW_LIQUIDITY_STAKING = 3,
|
||||
CLAIM = 4,
|
||||
VOTE = 5,
|
||||
DELEGATE = 6,
|
||||
WRAP = 7,
|
||||
CREATE_V3_POOL = 8,
|
||||
ADD_LIQUIDITY_V3_POOL = 9,
|
||||
ADD_LIQUIDITY_V2_POOL = 10,
|
||||
MIGRATE_LIQUIDITY_V3 = 11,
|
||||
COLLECT_FEES = 12,
|
||||
REMOVE_LIQUIDITY_V3 = 13,
|
||||
SUBMIT_PROPOSAL = 14,
|
||||
}
|
||||
|
||||
export interface BaseTransactionInfo {
|
||||
type: TransactionType
|
||||
}
|
||||
|
||||
export interface VoteTransactionInfo extends BaseTransactionInfo {
|
||||
type: TransactionType.VOTE
|
||||
governorAddress: string
|
||||
proposalId: number
|
||||
decision: VoteOption
|
||||
reason: string
|
||||
}
|
||||
|
||||
export interface DelegateTransactionInfo extends BaseTransactionInfo {
|
||||
type: TransactionType.DELEGATE
|
||||
delegatee: string
|
||||
}
|
||||
|
||||
export interface ApproveTransactionInfo extends BaseTransactionInfo {
|
||||
type: TransactionType.APPROVAL
|
||||
tokenAddress: string
|
||||
spender: string
|
||||
}
|
||||
|
||||
interface BaseSwapTransactionInfo extends BaseTransactionInfo {
|
||||
type: TransactionType.SWAP
|
||||
tradeType: TradeType
|
||||
inputCurrencyId: string
|
||||
outputCurrencyId: string
|
||||
}
|
||||
|
||||
export interface ExactInputSwapTransactionInfo extends BaseSwapTransactionInfo {
|
||||
tradeType: TradeType.EXACT_INPUT
|
||||
inputCurrencyAmountRaw: string
|
||||
expectedOutputCurrencyAmountRaw: string
|
||||
minimumOutputCurrencyAmountRaw: string
|
||||
}
|
||||
export interface ExactOutputSwapTransactionInfo extends BaseSwapTransactionInfo {
|
||||
tradeType: TradeType.EXACT_OUTPUT
|
||||
outputCurrencyAmountRaw: string
|
||||
expectedInputCurrencyAmountRaw: string
|
||||
maximumInputCurrencyAmountRaw: string
|
||||
}
|
||||
|
||||
export interface DepositLiquidityStakingTransactionInfo {
|
||||
type: TransactionType.DEPOSIT_LIQUIDITY_STAKING
|
||||
token0Address: string
|
||||
token1Address: string
|
||||
}
|
||||
|
||||
export interface WithdrawLiquidityStakingTransactionInfo {
|
||||
type: TransactionType.WITHDRAW_LIQUIDITY_STAKING
|
||||
token0Address: string
|
||||
token1Address: string
|
||||
}
|
||||
|
||||
export interface WrapTransactionInfo {
|
||||
type: TransactionType.WRAP
|
||||
unwrapped: boolean
|
||||
currencyAmountRaw: string
|
||||
}
|
||||
|
||||
export interface ClaimTransactionInfo {
|
||||
type: TransactionType.CLAIM
|
||||
recipient: string
|
||||
uniAmountRaw?: string
|
||||
}
|
||||
|
||||
export interface CreateV3PoolTransactionInfo {
|
||||
type: TransactionType.CREATE_V3_POOL
|
||||
baseCurrencyId: string
|
||||
quoteCurrencyId: string
|
||||
}
|
||||
|
||||
export interface AddLiquidityV3PoolTransactionInfo {
|
||||
type: TransactionType.ADD_LIQUIDITY_V3_POOL
|
||||
createPool: boolean
|
||||
baseCurrencyId: string
|
||||
quoteCurrencyId: string
|
||||
feeAmount: number
|
||||
expectedAmountBaseRaw: string
|
||||
expectedAmountQuoteRaw: string
|
||||
}
|
||||
|
||||
export interface AddLiquidityV2PoolTransactionInfo {
|
||||
type: TransactionType.ADD_LIQUIDITY_V2_POOL
|
||||
baseCurrencyId: string
|
||||
quoteCurrencyId: string
|
||||
expectedAmountBaseRaw: string
|
||||
expectedAmountQuoteRaw: string
|
||||
}
|
||||
|
||||
export interface MigrateV2LiquidityToV3TransactionInfo {
|
||||
type: TransactionType.MIGRATE_LIQUIDITY_V3
|
||||
baseCurrencyId: string
|
||||
quoteCurrencyId: string
|
||||
isFork: boolean
|
||||
}
|
||||
|
||||
export interface CollectFeesTransactionInfo {
|
||||
type: TransactionType.COLLECT_FEES
|
||||
currencyId0: string
|
||||
currencyId1: string
|
||||
}
|
||||
|
||||
export interface RemoveLiquidityV3TransactionInfo {
|
||||
type: TransactionType.REMOVE_LIQUIDITY_V3
|
||||
baseCurrencyId: string
|
||||
quoteCurrencyId: string
|
||||
expectedAmountBaseRaw: string
|
||||
expectedAmountQuoteRaw: string
|
||||
}
|
||||
|
||||
export interface SubmitProposalTransactionInfo {
|
||||
type: TransactionType.SUBMIT_PROPOSAL
|
||||
}
|
||||
|
||||
export type TransactionInfo =
|
||||
| ApproveTransactionInfo
|
||||
| ExactOutputSwapTransactionInfo
|
||||
| ExactInputSwapTransactionInfo
|
||||
| ClaimTransactionInfo
|
||||
| VoteTransactionInfo
|
||||
| DelegateTransactionInfo
|
||||
| DepositLiquidityStakingTransactionInfo
|
||||
| WithdrawLiquidityStakingTransactionInfo
|
||||
| WrapTransactionInfo
|
||||
| CreateV3PoolTransactionInfo
|
||||
| AddLiquidityV3PoolTransactionInfo
|
||||
| AddLiquidityV2PoolTransactionInfo
|
||||
| MigrateV2LiquidityToV3TransactionInfo
|
||||
| CollectFeesTransactionInfo
|
||||
| RemoveLiquidityV3TransactionInfo
|
||||
| SubmitProposalTransactionInfo
|
||||
|
||||
export const addTransaction =
|
||||
createAction<{
|
||||
chainId: number
|
||||
hash: string
|
||||
from: string
|
||||
approval?: { tokenAddress: string; spender: string }
|
||||
claim?: { recipient: string }
|
||||
summary?: string
|
||||
info: TransactionInfo
|
||||
}>('transactions/addTransaction')
|
||||
export const clearAllTransactions = createAction<{ chainId: number }>('transactions/clearAllTransactions')
|
||||
export const finalizeTransaction = createAction<{
|
||||
|
@ -3,26 +3,16 @@ import { useCallback, useMemo } from 'react'
|
||||
import { useAppDispatch, useAppSelector } from 'state/hooks'
|
||||
|
||||
import { useActiveWeb3React } from '../../hooks/web3'
|
||||
import { addTransaction } from './actions'
|
||||
import { addTransaction, TransactionInfo, TransactionType } from './actions'
|
||||
import { TransactionDetails } from './reducer'
|
||||
|
||||
// helper that can take a ethers library transaction response and add it to the list of transactions
|
||||
export function useTransactionAdder(): (
|
||||
response: TransactionResponse,
|
||||
customData?: { summary?: string; approval?: { tokenAddress: string; spender: string }; claim?: { recipient: string } }
|
||||
) => void {
|
||||
export function useTransactionAdder(): (response: TransactionResponse, info: TransactionInfo) => void {
|
||||
const { chainId, account } = useActiveWeb3React()
|
||||
const dispatch = useAppDispatch()
|
||||
|
||||
return useCallback(
|
||||
(
|
||||
response: TransactionResponse,
|
||||
{
|
||||
summary,
|
||||
approval,
|
||||
claim,
|
||||
}: { summary?: string; claim?: { recipient: string }; approval?: { tokenAddress: string; spender: string } } = {}
|
||||
) => {
|
||||
(response: TransactionResponse, info: TransactionInfo) => {
|
||||
if (!account) return
|
||||
if (!chainId) return
|
||||
|
||||
@ -30,7 +20,7 @@ export function useTransactionAdder(): (
|
||||
if (!hash) {
|
||||
throw Error('No transaction hash found.')
|
||||
}
|
||||
dispatch(addTransaction({ hash, from: account, chainId, approval, summary, claim }))
|
||||
dispatch(addTransaction({ hash, from: account, info, chainId }))
|
||||
},
|
||||
[dispatch, chainId, account]
|
||||
)
|
||||
@ -92,9 +82,8 @@ export function useHasPendingApproval(tokenAddress: string | undefined, spender:
|
||||
if (tx.receipt) {
|
||||
return false
|
||||
} else {
|
||||
const approval = tx.approval
|
||||
if (!approval) return false
|
||||
return approval.spender === spender && approval.tokenAddress === tokenAddress && isTransactionRecent(tx)
|
||||
if (tx.info.type !== TransactionType.APPROVAL) return false
|
||||
return tx.info.spender === spender && tx.info.tokenAddress === tokenAddress && isTransactionRecent(tx)
|
||||
}
|
||||
}),
|
||||
[allTransactions, spender, tokenAddress]
|
||||
@ -113,7 +102,7 @@ export function useUserHasSubmittedClaim(account?: string): {
|
||||
const claimTxn = useMemo(() => {
|
||||
const txnIndex = Object.keys(allTransactions).find((hash) => {
|
||||
const tx = allTransactions[hash]
|
||||
return tx.claim && tx.claim.recipient === account
|
||||
return tx.info.type === TransactionType.CLAIM && tx.info.recipient === account
|
||||
})
|
||||
return txnIndex && allTransactions[txnIndex] ? allTransactions[txnIndex] : undefined
|
||||
}, [account, allTransactions])
|
||||
|
@ -1,5 +1,12 @@
|
||||
import { createStore, Store } from 'redux'
|
||||
import { addTransaction, checkedTransaction, clearAllTransactions, finalizeTransaction } from './actions'
|
||||
import { updateVersion } from '../global/actions'
|
||||
import {
|
||||
addTransaction,
|
||||
checkedTransaction,
|
||||
clearAllTransactions,
|
||||
finalizeTransaction,
|
||||
TransactionType,
|
||||
} from './actions'
|
||||
import reducer, { initialState, TransactionState } from './reducer'
|
||||
|
||||
describe('transaction reducer', () => {
|
||||
@ -9,16 +16,45 @@ describe('transaction reducer', () => {
|
||||
store = createStore(reducer, initialState)
|
||||
})
|
||||
|
||||
describe('updateVersion', () => {
|
||||
it('clears old format transactions that do not have info', () => {
|
||||
store = createStore(reducer, {
|
||||
[1]: {
|
||||
abc: {
|
||||
hash: 'abc',
|
||||
} as any,
|
||||
},
|
||||
})
|
||||
store.dispatch(updateVersion())
|
||||
expect(store.getState()[1]['abc']).toBeUndefined()
|
||||
})
|
||||
it('keeps old format transactions that do have info', () => {
|
||||
store = createStore(reducer, {
|
||||
[1]: {
|
||||
abc: {
|
||||
hash: 'abc',
|
||||
info: {},
|
||||
} as any,
|
||||
},
|
||||
})
|
||||
store.dispatch(updateVersion())
|
||||
expect(store.getState()[1]['abc']).toBeTruthy()
|
||||
})
|
||||
})
|
||||
|
||||
describe('addTransaction', () => {
|
||||
it('adds the transaction', () => {
|
||||
const beforeTime = new Date().getTime()
|
||||
store.dispatch(
|
||||
addTransaction({
|
||||
chainId: 1,
|
||||
summary: 'hello world',
|
||||
hash: '0x0',
|
||||
approval: { tokenAddress: 'abc', spender: 'def' },
|
||||
from: 'abc',
|
||||
info: {
|
||||
type: TransactionType.APPROVAL,
|
||||
tokenAddress: 'abc',
|
||||
spender: 'def',
|
||||
},
|
||||
})
|
||||
)
|
||||
const txs = store.getState()
|
||||
@ -27,10 +63,13 @@ describe('transaction reducer', () => {
|
||||
const tx = txs[1]?.['0x0']
|
||||
expect(tx).toBeTruthy()
|
||||
expect(tx?.hash).toEqual('0x0')
|
||||
expect(tx?.summary).toEqual('hello world')
|
||||
expect(tx?.approval).toEqual({ tokenAddress: 'abc', spender: 'def' })
|
||||
expect(tx?.from).toEqual('abc')
|
||||
expect(tx?.addedTime).toBeGreaterThanOrEqual(beforeTime)
|
||||
expect(tx?.info).toEqual({
|
||||
type: TransactionType.APPROVAL,
|
||||
tokenAddress: 'abc',
|
||||
spender: 'def',
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -59,8 +98,7 @@ describe('transaction reducer', () => {
|
||||
addTransaction({
|
||||
hash: '0x0',
|
||||
chainId: 4,
|
||||
approval: { spender: '0x0', tokenAddress: '0x0' },
|
||||
summary: 'hello world',
|
||||
info: { type: TransactionType.APPROVAL, spender: '0x0', tokenAddress: '0x0' },
|
||||
from: '0x0',
|
||||
})
|
||||
)
|
||||
@ -82,7 +120,6 @@ describe('transaction reducer', () => {
|
||||
})
|
||||
)
|
||||
const tx = store.getState()[4]?.['0x0']
|
||||
expect(tx?.summary).toEqual('hello world')
|
||||
expect(tx?.confirmedTime).toBeGreaterThanOrEqual(beforeTime)
|
||||
expect(tx?.receipt).toEqual({
|
||||
status: 1,
|
||||
@ -113,8 +150,7 @@ describe('transaction reducer', () => {
|
||||
addTransaction({
|
||||
hash: '0x0',
|
||||
chainId: 4,
|
||||
approval: { spender: '0x0', tokenAddress: '0x0' },
|
||||
summary: 'hello world',
|
||||
info: { type: TransactionType.APPROVAL, spender: '0x0', tokenAddress: '0x0' },
|
||||
from: '0x0',
|
||||
})
|
||||
)
|
||||
@ -133,8 +169,7 @@ describe('transaction reducer', () => {
|
||||
addTransaction({
|
||||
hash: '0x0',
|
||||
chainId: 4,
|
||||
approval: { spender: '0x0', tokenAddress: '0x0' },
|
||||
summary: 'hello world',
|
||||
info: { type: TransactionType.APPROVAL, spender: '0x0', tokenAddress: '0x0' },
|
||||
from: '0x0',
|
||||
})
|
||||
)
|
||||
@ -162,18 +197,16 @@ describe('transaction reducer', () => {
|
||||
store.dispatch(
|
||||
addTransaction({
|
||||
chainId: 1,
|
||||
summary: 'hello world',
|
||||
hash: '0x0',
|
||||
approval: { tokenAddress: 'abc', spender: 'def' },
|
||||
info: { type: TransactionType.APPROVAL, spender: 'abc', tokenAddress: 'def' },
|
||||
from: 'abc',
|
||||
})
|
||||
)
|
||||
store.dispatch(
|
||||
addTransaction({
|
||||
chainId: 4,
|
||||
summary: 'hello world',
|
||||
hash: '0x1',
|
||||
approval: { tokenAddress: 'abc', spender: 'def' },
|
||||
info: { type: TransactionType.APPROVAL, spender: 'abc', tokenAddress: 'def' },
|
||||
from: 'abc',
|
||||
})
|
||||
)
|
||||
|
@ -1,24 +1,24 @@
|
||||
import { createReducer } from '@reduxjs/toolkit'
|
||||
import { updateVersion } from '../global/actions'
|
||||
import {
|
||||
addTransaction,
|
||||
checkedTransaction,
|
||||
clearAllTransactions,
|
||||
finalizeTransaction,
|
||||
SerializableTransactionReceipt,
|
||||
TransactionInfo,
|
||||
} from './actions'
|
||||
|
||||
const now = () => new Date().getTime()
|
||||
|
||||
export interface TransactionDetails {
|
||||
hash: string
|
||||
approval?: { tokenAddress: string; spender: string }
|
||||
summary?: string
|
||||
claim?: { recipient: string }
|
||||
receipt?: SerializableTransactionReceipt
|
||||
lastCheckedBlockNumber?: number
|
||||
addedTime: number
|
||||
confirmedTime?: number
|
||||
from: string
|
||||
info: TransactionInfo
|
||||
}
|
||||
|
||||
export interface TransactionState {
|
||||
@ -31,12 +31,24 @@ export const initialState: TransactionState = {}
|
||||
|
||||
export default createReducer(initialState, (builder) =>
|
||||
builder
|
||||
.addCase(addTransaction, (transactions, { payload: { chainId, from, hash, approval, summary, claim } }) => {
|
||||
.addCase(updateVersion, (transactions) => {
|
||||
// in case there are any transactions in the store with the old format, remove them
|
||||
Object.keys(transactions).forEach((chainId) => {
|
||||
const chainTransactions = transactions[chainId as unknown as number]
|
||||
Object.keys(chainTransactions).forEach((hash) => {
|
||||
if (!('info' in chainTransactions[hash])) {
|
||||
// clear old transactions that don't have the right format
|
||||
delete chainTransactions[hash]
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
.addCase(addTransaction, (transactions, { payload: { chainId, from, hash, info } }) => {
|
||||
if (transactions[chainId]?.[hash]) {
|
||||
throw Error('Attempted to add existing transaction.')
|
||||
}
|
||||
const txs = transactions[chainId] ?? {}
|
||||
txs[hash] = { hash, approval, summary, claim, from, addedTime: now() }
|
||||
txs[hash] = { hash, info, from, addedTime: now() }
|
||||
transactions[chainId] = txs
|
||||
})
|
||||
.addCase(clearAllTransactions, (transactions, { payload: { chainId } }) => {
|
||||
|
@ -106,8 +106,6 @@ export default function Updater(): null {
|
||||
{
|
||||
txn: {
|
||||
hash,
|
||||
success: receipt.status === 1,
|
||||
summary: transactions[hash]?.summary,
|
||||
},
|
||||
},
|
||||
hash,
|
||||
|
Loading…
Reference in New Issue
Block a user