feat: add amount to local copy of Approval transactions (#6726)
* feat: add amount to local copy of Approval transactions * fix: use alternate * fix: type problem * feat: add test
This commit is contained in:
parent
094664dc7a
commit
8b16f454ca
@ -1,5 +1,6 @@
|
||||
import { Trans } from '@lingui/macro'
|
||||
import { Fraction, TradeType } from '@uniswap/sdk-core'
|
||||
import { BigNumber } from 'ethers/lib/ethers'
|
||||
import JSBI from 'jsbi'
|
||||
|
||||
import { nativeOnChain } from '../../constants/tokens'
|
||||
@ -87,7 +88,11 @@ function SubmitProposalTransactionSummary() {
|
||||
function ApprovalSummary({ info }: { info: ApproveTransactionInfo }) {
|
||||
const token = useToken(info.tokenAddress)
|
||||
|
||||
return <Trans>Approve {token?.symbol}</Trans>
|
||||
return BigNumber.from(info.amount)?.eq(0) ? (
|
||||
<Trans>Revoke {token?.symbol}</Trans>
|
||||
) : (
|
||||
<Trans>Approve {token?.symbol}</Trans>
|
||||
)
|
||||
}
|
||||
|
||||
function VoteSummary({ info }: { info: VoteTransactionInfo }) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { SupportedChainId, Token, TradeType as MockTradeType } from '@uniswap/sdk-core'
|
||||
import { PERMIT2_ADDRESS } from '@uniswap/universal-router-sdk'
|
||||
import { DAI as MockDAI, nativeOnChain, USDC_MAINNET as MockUSDC_MAINNET } from 'constants/tokens'
|
||||
import { DAI as MockDAI, nativeOnChain, USDC_MAINNET as MockUSDC_MAINNET, USDT as MockUSDT } from 'constants/tokens'
|
||||
import { TransactionStatus as MockTxStatus } from 'graphql/data/__generated__/types-and-hooks'
|
||||
import { ChainTokenMap } from 'hooks/Tokens'
|
||||
import {
|
||||
@ -50,6 +50,7 @@ const mockChainId = SupportedChainId.MAINNET
|
||||
const mockSpenderAddress = PERMIT2_ADDRESS[mockChainId]
|
||||
const mockCurrencyAmountRaw = '1000000000000000000'
|
||||
const mockCurrencyAmountRawUSDC = '1000000'
|
||||
const mockApprovalAmountRaw = '10000000'
|
||||
|
||||
function mockHash(id: string, status: MockTxStatus = MockTxStatus.Confirmed) {
|
||||
return id + status
|
||||
@ -93,6 +94,7 @@ const mockTokenAddressMap: ChainTokenMap = {
|
||||
[mockChainId]: {
|
||||
[MockDAI.address]: MockDAI,
|
||||
[MockUSDC_MAINNET.address]: MockUSDC_MAINNET,
|
||||
[MockUSDT.address]: MockUSDT,
|
||||
},
|
||||
}
|
||||
|
||||
@ -142,9 +144,19 @@ jest.mock('../../../../state/transactions/hooks', () => {
|
||||
type: MockTxType.APPROVAL,
|
||||
tokenAddress: MockDAI.address,
|
||||
spender: mockSpenderAddress,
|
||||
amount: mockApprovalAmountRaw,
|
||||
},
|
||||
'0xapproval'
|
||||
),
|
||||
...mockMultiStatus(
|
||||
{
|
||||
type: MockTxType.APPROVAL,
|
||||
tokenAddress: MockUSDT.address,
|
||||
spender: mockSpenderAddress,
|
||||
amount: '0',
|
||||
},
|
||||
'0xrevoke_approval'
|
||||
),
|
||||
...mockMultiStatus(
|
||||
{
|
||||
type: MockTxType.WRAP,
|
||||
@ -315,7 +327,7 @@ describe('parseLocalActivity', () => {
|
||||
const account2Activites = renderHook(() => useLocalActivities(mockAccount2)).result.current
|
||||
|
||||
expect(Object.values(account1Activites)).toHaveLength(1)
|
||||
expect(Object.values(account2Activites)).toHaveLength(30)
|
||||
expect(Object.values(account2Activites)).toHaveLength(33)
|
||||
})
|
||||
|
||||
it('Properly uses correct tense of activity title based on tx status', () => {
|
||||
@ -380,6 +392,23 @@ describe('parseLocalActivity', () => {
|
||||
})
|
||||
})
|
||||
|
||||
it('Adapts Revoke Approval to Activity type', () => {
|
||||
const hash = mockHash('0xrevoke_approval')
|
||||
const activity = renderHook(() => useLocalActivities(mockAccount2)).result.current[hash]
|
||||
expect(activity).toMatchObject({
|
||||
chainId: mockChainId,
|
||||
currencies: [MockUSDT],
|
||||
title: 'Revoked approval',
|
||||
descriptor: MockUSDT.symbol,
|
||||
hash,
|
||||
status: MockTxStatus.Confirmed,
|
||||
receipt: {
|
||||
id: hash,
|
||||
status: MockTxStatus.Confirmed,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
it('Adapts Wrap to Activity type', () => {
|
||||
const hash = mockHash('0xwrap')
|
||||
const activity = renderHook(() => useLocalActivities(mockAccount2)).result.current[hash]
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { BigNumber } from '@ethersproject/bignumber'
|
||||
import { t } from '@lingui/macro'
|
||||
import { formatCurrencyAmount } from '@uniswap/conedison/format'
|
||||
import { Currency, CurrencyAmount, TradeType } from '@uniswap/sdk-core'
|
||||
@ -76,12 +77,17 @@ function parseWrap(wrap: WrapTransactionInfo, chainId: SupportedChainId, status:
|
||||
function parseApproval(
|
||||
approval: ApproveTransactionInfo,
|
||||
chainId: SupportedChainId,
|
||||
tokens: ChainTokenMap
|
||||
tokens: ChainTokenMap,
|
||||
status: TransactionStatus
|
||||
): Partial<Activity> {
|
||||
// TODO: Add 'amount' approved to ApproveTransactionInfo so we can distinguish between revoke and approve
|
||||
const currency = getCurrency(approval.tokenAddress, chainId, tokens)
|
||||
const descriptor = currency?.symbol ?? currency?.name ?? t`Unknown`
|
||||
return {
|
||||
title: getActivityTitle(
|
||||
TransactionType.APPROVAL,
|
||||
status,
|
||||
BigNumber.from(approval.amount).eq(0) /* use alternate if it's a revoke */
|
||||
),
|
||||
descriptor,
|
||||
currencies: [currency],
|
||||
}
|
||||
@ -165,7 +171,7 @@ export function parseLocalActivity(
|
||||
if (info.type === TransactionType.SWAP) {
|
||||
additionalFields = parseSwap(info, chainId, tokens)
|
||||
} else if (info.type === TransactionType.APPROVAL) {
|
||||
additionalFields = parseApproval(info, chainId, tokens)
|
||||
additionalFields = parseApproval(info, chainId, tokens, status)
|
||||
} else if (info.type === TransactionType.WRAP) {
|
||||
additionalFields = parseWrap(info, chainId, status)
|
||||
} else if (
|
||||
|
@ -144,6 +144,11 @@ const AlternateTransactionTitleTable: { [key in TransactionType]?: { [state in T
|
||||
[TransactionStatus.Confirmed]: t`Unwrapped`,
|
||||
[TransactionStatus.Failed]: t`Unwrap failed`,
|
||||
},
|
||||
[TransactionType.APPROVAL]: {
|
||||
[TransactionStatus.Pending]: t`Revoking approval`,
|
||||
[TransactionStatus.Confirmed]: t`Revoked approval`,
|
||||
[TransactionStatus.Failed]: t`Revoke approval failed`,
|
||||
},
|
||||
}
|
||||
|
||||
export function getActivityTitle(type: TransactionType, status: TransactionStatus, alternate?: boolean) {
|
||||
|
@ -11,8 +11,13 @@ function useGetAndTrackApproval(getApproval: ReturnType<typeof useApproval>[1])
|
||||
return useCallback(() => {
|
||||
return getApproval().then((pending) => {
|
||||
if (pending) {
|
||||
const { response, tokenAddress, spenderAddress: spender } = pending
|
||||
addTransaction(response, { type: TransactionType.APPROVAL, tokenAddress, spender })
|
||||
const { response, tokenAddress, spenderAddress: spender, amount } = pending
|
||||
addTransaction(response, {
|
||||
type: TransactionType.APPROVAL,
|
||||
tokenAddress,
|
||||
spender,
|
||||
amount: amount.quotient.toString(),
|
||||
})
|
||||
}
|
||||
})
|
||||
}, [addTransaction, getApproval])
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { BigNumberish } from '@ethersproject/bignumber'
|
||||
import { ContractTransaction } from '@ethersproject/contracts'
|
||||
import { CurrencyAmount, MaxUint256, Token } from '@uniswap/sdk-core'
|
||||
import { useTokenContract } from 'hooks/useContract'
|
||||
@ -49,7 +48,7 @@ export function useUpdateTokenAllowance(
|
||||
if (!contract) throw new Error('missing contract')
|
||||
if (!spender) throw new Error('missing spender')
|
||||
|
||||
const allowance: BigNumberish = MaxUint256.toString()
|
||||
const allowance = MaxUint256.toString()
|
||||
const response = await contract.approve(spender, allowance)
|
||||
return {
|
||||
response,
|
||||
@ -57,6 +56,7 @@ export function useUpdateTokenAllowance(
|
||||
type: TransactionType.APPROVAL,
|
||||
tokenAddress: contract.address,
|
||||
spender,
|
||||
amount: allowance,
|
||||
},
|
||||
}
|
||||
} catch (e: unknown) {
|
||||
|
@ -49,7 +49,10 @@ export function useApproval(
|
||||
useIsPendingApproval: (token?: Token, spender?: string) => boolean
|
||||
): [
|
||||
ApprovalState,
|
||||
() => Promise<{ response: TransactionResponse; tokenAddress: string; spenderAddress: string } | undefined>
|
||||
() => Promise<
|
||||
| { response: TransactionResponse; tokenAddress: string; spenderAddress: string; amount: CurrencyAmount<Currency> }
|
||||
| undefined
|
||||
>
|
||||
] {
|
||||
const { chainId } = useWeb3React()
|
||||
const token = amountToApprove?.currency?.isToken ? amountToApprove.currency : undefined
|
||||
@ -102,6 +105,7 @@ export function useApproval(
|
||||
response,
|
||||
tokenAddress: token.address,
|
||||
spenderAddress: spender,
|
||||
amount: amountToApprove,
|
||||
}
|
||||
})
|
||||
.catch((error: Error) => {
|
||||
|
@ -58,6 +58,7 @@ describe('transaction reducer', () => {
|
||||
type: TransactionType.APPROVAL,
|
||||
tokenAddress: 'abc',
|
||||
spender: 'def',
|
||||
amount: '10000',
|
||||
},
|
||||
})
|
||||
)
|
||||
@ -73,6 +74,7 @@ describe('transaction reducer', () => {
|
||||
type: TransactionType.APPROVAL,
|
||||
tokenAddress: 'abc',
|
||||
spender: 'def',
|
||||
amount: '10000',
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -103,7 +105,7 @@ describe('transaction reducer', () => {
|
||||
hash: '0x0',
|
||||
chainId: SupportedChainId.MAINNET,
|
||||
nonce: 2,
|
||||
info: { type: TransactionType.APPROVAL, spender: '0x0', tokenAddress: '0x0' },
|
||||
info: { type: TransactionType.APPROVAL, spender: '0x0', tokenAddress: '0x0', amount: '10000' },
|
||||
from: '0x0',
|
||||
})
|
||||
)
|
||||
@ -156,7 +158,7 @@ describe('transaction reducer', () => {
|
||||
hash: '0x0',
|
||||
chainId: SupportedChainId.MAINNET,
|
||||
nonce: 3,
|
||||
info: { type: TransactionType.APPROVAL, spender: '0x0', tokenAddress: '0x0' },
|
||||
info: { type: TransactionType.APPROVAL, spender: '0x0', tokenAddress: '0x0', amount: '10000' },
|
||||
from: '0x0',
|
||||
})
|
||||
)
|
||||
@ -176,7 +178,7 @@ describe('transaction reducer', () => {
|
||||
hash: '0x0',
|
||||
chainId: SupportedChainId.MAINNET,
|
||||
nonce: 4,
|
||||
info: { type: TransactionType.APPROVAL, spender: '0x0', tokenAddress: '0x0' },
|
||||
info: { type: TransactionType.APPROVAL, spender: '0x0', tokenAddress: '0x0', amount: '10000' },
|
||||
from: '0x0',
|
||||
})
|
||||
)
|
||||
@ -206,7 +208,7 @@ describe('transaction reducer', () => {
|
||||
chainId: SupportedChainId.MAINNET,
|
||||
hash: '0x0',
|
||||
nonce: 5,
|
||||
info: { type: TransactionType.APPROVAL, spender: 'abc', tokenAddress: 'def' },
|
||||
info: { type: TransactionType.APPROVAL, spender: 'abc', tokenAddress: 'def', amount: '10000' },
|
||||
from: 'abc',
|
||||
})
|
||||
)
|
||||
@ -215,7 +217,7 @@ describe('transaction reducer', () => {
|
||||
chainId: SupportedChainId.OPTIMISM,
|
||||
nonce: 6,
|
||||
hash: '0x1',
|
||||
info: { type: TransactionType.APPROVAL, spender: 'abc', tokenAddress: 'def' },
|
||||
info: { type: TransactionType.APPROVAL, spender: 'abc', tokenAddress: 'def', amount: '10000' },
|
||||
from: 'abc',
|
||||
})
|
||||
)
|
||||
|
@ -79,6 +79,7 @@ export interface ApproveTransactionInfo extends BaseTransactionInfo {
|
||||
type: TransactionType.APPROVAL
|
||||
tokenAddress: string
|
||||
spender: string
|
||||
amount: string
|
||||
}
|
||||
|
||||
interface BaseSwapTransactionInfo extends BaseTransactionInfo {
|
||||
|
Loading…
Reference in New Issue
Block a user