From 06c96c3b815043ee944d6307b68cd5a5e183fa90 Mon Sep 17 00:00:00 2001 From: Jean Regisser Date: Thu, 31 Oct 2024 11:47:07 +0100 Subject: [PATCH] feat(feedV2): generic claim reward type (#6198) ### Description Introduce new generic type for the TX feed for claim reward. `CLAIM_REWARD` replaces `EARN_CLAIM_REWARD` Why? 1. This allows directly supporting more claim reward TXs, not only for Earn but also GoodDollar, etc. 2. We can do this now without too much effort and keep a "simple" backend implementation for the new `getWalletTransactions` Similar to what was done in https://github.com/valora-inc/wallet/pull/6189 This is just for the new feed API with Zerion. ### Test plan - Tests pass ### Related issues - Related to RET-1204 - Also see this Slack [thread](https://valora-app.slack.com/archives/C029Z1QMD7B/p1729847488933829) for context ### Backwards compatibility Yes ### Network scalability If a new NetworkId and/or Network are added in the future, the changes in this PR will: - [x] Continue to work without code changes, OR trigger a compilation error (guaranteeing we find it when a new network is added) --- locales/base/translation.json | 9 +- .../feed/ClaimRewardFeedItem.test.tsx | 162 ++++++++++++++++++ src/transactions/feed/ClaimRewardFeedItem.tsx | 143 ++++++++++++++++ .../feed/TransactionDetailsScreen.test.tsx | 78 +++++++++ .../feed/TransactionDetailsScreen.tsx | 6 + src/transactions/feed/TransactionFeed.tsx | 1 + .../feed/TransactionFeedItemImage.tsx | 2 + src/transactions/feed/TransactionFeedV2.tsx | 3 + .../feed/detailContent/ClaimRewardContent.tsx | 87 ++++++++++ src/transactions/types.ts | 20 ++- test/RootStateSchema.json | 155 +++++++++++++++++ test/values.ts | 28 +++ 12 files changed, 692 insertions(+), 2 deletions(-) create mode 100644 src/transactions/feed/ClaimRewardFeedItem.test.tsx create mode 100644 src/transactions/feed/ClaimRewardFeedItem.tsx create mode 100644 src/transactions/feed/detailContent/ClaimRewardContent.tsx diff --git a/locales/base/translation.json b/locales/base/translation.json index 4e41b77b301..bd669500c30 100644 --- a/locales/base/translation.json +++ b/locales/base/translation.json @@ -2288,7 +2288,10 @@ "depositSubtitle_noTxAppName": "to unknown pool", "withdrawTitle": "Withdrew", "withdrawSubtitle": "from {{txAppName}} Pool", - "withdrawSubtitle_noTxAppName": "from unknown app" + "withdrawSubtitle_noTxAppName": "from unknown app", + "claimRewardTitle": "Collected", + "claimRewardSubtitle": "from {{txAppName}} Pool", + "claimRewardSubtitle_noTxAppName": "from unknown app" }, "transactionDetails": { "descriptionLabel": "Details", @@ -2300,6 +2303,10 @@ "withdrawSubtitle": "Withdrew {{tokenSymbol}} from {{txAppName}} Pool", "withdrawSubtitle_noTxAppName": "Withdrew {{tokenSymbol}} from unknown app", "withdrawDetails": "Amount Withdrawn", + "claimRewardTitle": "Collected", + "claimRewardSubtitle": "Collected {{tokenSymbol}} from {{txAppName}} Pool", + "claimRewardSubtitle_noTxAppName": "Collected {{tokenSymbol}} from unknown app", + "claimRewardDetails": "Amount Collected", "swap": "Swap", "network": "Network", "fees": "Fees" diff --git a/src/transactions/feed/ClaimRewardFeedItem.test.tsx b/src/transactions/feed/ClaimRewardFeedItem.test.tsx new file mode 100644 index 00000000000..c863a0da4e7 --- /dev/null +++ b/src/transactions/feed/ClaimRewardFeedItem.test.tsx @@ -0,0 +1,162 @@ +import { fireEvent, render, within } from '@testing-library/react-native' +import React from 'react' +import { Provider } from 'react-redux' +import AppAnalytics from 'src/analytics/AppAnalytics' +import { HomeEvents } from 'src/analytics/Events' +import { navigate } from 'src/navigator/NavigationService' +import { Screens } from 'src/navigator/Screens' +import { getFeatureGate } from 'src/statsig' +import { StatsigFeatureGates } from 'src/statsig/types' +import ClaimRewardFeedItem from 'src/transactions/feed/ClaimRewardFeedItem' +import { NetworkId } from 'src/transactions/types' +import { createMockStore } from 'test/utils' +import { + mockAaveArbUsdcAddress, + mockAaveArbUsdcTokenId, + mockArbArbTokenId, + mockArbUsdcTokenId, + mockClaimRewardTransaction, +} from 'test/values' + +jest.mock('src/statsig') +jest + .mocked(getFeatureGate) + .mockImplementation((featureGateName) => featureGateName === StatsigFeatureGates.SHOW_POSITIONS) + +const store = createMockStore({ + tokens: { + tokenBalances: { + [mockArbUsdcTokenId]: { + tokenId: mockArbUsdcTokenId, + symbol: 'USDC', + priceUsd: '1', + priceFetchedAt: Date.now(), + networkId: NetworkId['arbitrum-sepolia'], + }, + [mockArbArbTokenId]: { + tokenId: mockArbArbTokenId, + symbol: 'ARB', + priceUsd: '0.9898', + priceFetchedAt: Date.now(), + networkId: NetworkId['arbitrum-sepolia'], + }, + [mockAaveArbUsdcTokenId]: { + networkId: NetworkId['arbitrum-sepolia'], + address: mockAaveArbUsdcAddress, + tokenId: mockAaveArbUsdcTokenId, + symbol: 'aArbSepUSDC', + priceUsd: '1', + priceFetchedAt: Date.now(), + }, + }, + }, + positions: { + positions: [ + { + type: 'app-token', + networkId: NetworkId['arbitrum-sepolia'], + address: '0x460b97bd498e1157530aeb3086301d5225b91216', + tokenId: 'arbitrum-sepolia:0x460b97bd498e1157530aeb3086301d5225b91216', + positionId: 'arbitrum-sepolia:0x460b97bd498e1157530aeb3086301d5225b91216', + appId: 'aave', + appName: 'Aave', + symbol: 'aArbSepUSDC', + decimals: 6, + displayProps: { + title: 'USDC', + description: 'Supplied (APY: 1.92%)', + imageUrl: 'https://raw.githubusercontent.com/valora-inc/dapp-list/main/assets/aave.png', + }, + dataProps: { + yieldRates: [ + { + percentage: 1.9194202601763743, + label: 'Earnings APY', + tokenId: 'arbitrum-sepolia:0x75faf114eafb1bdbe2f0316df893fd58ce46aa4d', + }, + ], + earningItems: [], + depositTokenId: 'arbitrum-sepolia:0x75faf114eafb1bdbe2f0316df893fd58ce46aa4d', + withdrawTokenId: 'arbitrum-sepolia:0x460b97bd498e1157530aeb3086301d5225b91216', + }, + tokens: [ + { + tokenId: 'arbitrum-sepolia:0x75faf114eafb1bdbe2f0316df893fd58ce46aa4d', + networkId: NetworkId['arbitrum-sepolia'], + address: '0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d', + symbol: 'USDC', + decimals: 6, + priceUsd: '0', + type: 'base-token', + balance: '0', + }, + ], + pricePerShare: ['1'], + priceUsd: '0.999', + balance: '10', + supply: '190288.768509', + availableShortcutIds: ['deposit', 'withdraw'], + }, + ], + earnPositionIds: ['arbitrum-sepolia:0x460b97bd498e1157530aeb3086301d5225b91216'], + }, +}) + +describe('ClaimRewardFeedItem', () => { + beforeEach(() => { + jest.clearAllMocks() + }) + + it('should render correctly', () => { + const { getByText, getByTestId } = render( + + + + ) + + expect(getByText('transactionFeed.claimRewardTitle')).toBeTruthy() + expect(getByText('transactionFeed.claimRewardSubtitle, {"txAppName":"Aave"}')).toBeTruthy() + expect( + within(getByTestId('ClaimRewardFeedItem/amount-crypto')).getByText('+1.50 ARB') + ).toBeTruthy() + expect(within(getByTestId('ClaimRewardFeedItem/amount-local')).getByText('₱1.97')).toBeTruthy() + }) + + it('should display when app name is not available', () => { + const { getByText } = render( + + + + ) + + expect(getByText('transactionFeed.claimRewardSubtitle, {"context":"noTxAppName"}')).toBeTruthy() + }) + + it('should navigate correctly on tap', () => { + const { getByTestId } = render( + + + + ) + + fireEvent.press( + getByTestId(`ClaimRewardFeedItem/${mockClaimRewardTransaction.transactionHash}`) + ) + expect(navigate).toHaveBeenCalledWith(Screens.TransactionDetailsScreen, { + transaction: mockClaimRewardTransaction, + }) + }) + + it('should fire analytic event on tap', () => { + const { getByTestId } = render( + + + + ) + + fireEvent.press( + getByTestId(`ClaimRewardFeedItem/${mockClaimRewardTransaction.transactionHash}`) + ) + expect(AppAnalytics.track).toHaveBeenCalledWith(HomeEvents.transaction_feed_item_select) + }) +}) diff --git a/src/transactions/feed/ClaimRewardFeedItem.tsx b/src/transactions/feed/ClaimRewardFeedItem.tsx new file mode 100644 index 00000000000..71608b9956c --- /dev/null +++ b/src/transactions/feed/ClaimRewardFeedItem.tsx @@ -0,0 +1,143 @@ +import BigNumber from 'bignumber.js' +import React from 'react' +import { useTranslation } from 'react-i18next' +import { StyleSheet, Text, View } from 'react-native' +import AppAnalytics from 'src/analytics/AppAnalytics' +import { HomeEvents } from 'src/analytics/Events' +import TokenDisplay from 'src/components/TokenDisplay' +import Touchable from 'src/components/Touchable' +import { navigate } from 'src/navigator/NavigationService' +import { Screens } from 'src/navigator/Screens' +import Colors from 'src/styles/colors' +import { typeScale } from 'src/styles/fonts' +import { Spacing } from 'src/styles/styles' +import variables from 'src/styles/variables' +import TransactionFeedItemImage from 'src/transactions/feed/TransactionFeedItemImage' +import { ClaimReward } from 'src/transactions/types' + +interface DescriptionProps { + transaction: ClaimReward +} + +function Description({ transaction }: DescriptionProps) { + const { t } = useTranslation() + const txAppName = transaction.appName + const title = t('transactionFeed.claimRewardTitle') + const subtitle = t('transactionFeed.claimRewardSubtitle', { + context: !txAppName ? 'noTxAppName' : undefined, + txAppName, + }) + + return ( + + + {title} + + + {subtitle} + + + ) +} + +interface AmountDisplayProps { + transaction: ClaimReward + isLocal: boolean +} + +function AmountDisplay({ transaction, isLocal }: AmountDisplayProps) { + const amountValue = new BigNumber(transaction.amount.value) + const tokenId = transaction.amount.tokenId + + const textStyle = isLocal ? styles.amountSubtitle : [styles.amountTitle, { color: Colors.accent }] + + return ( + + ) +} + +interface AmountProps { + transaction: ClaimReward +} + +function Amount({ transaction }: AmountProps) { + return ( + + + + + ) +} + +interface Props { + transaction: ClaimReward +} + +export default function ClaimRewardFeedItem({ transaction }: Props) { + return ( + { + // TODO: we'll add the type in a subsequent PR + AppAnalytics.track(HomeEvents.transaction_feed_item_select) + navigate(Screens.TransactionDetailsScreen, { transaction }) + }} + > + + + + + + + ) +} + +const styles = StyleSheet.create({ + container: { + flexDirection: 'row', + paddingVertical: Spacing.Small12, + paddingHorizontal: variables.contentPadding, + alignItems: 'center', + }, + contentContainer: { + flex: 1, + paddingHorizontal: variables.contentPadding, + }, + title: { + ...typeScale.labelMedium, + color: Colors.black, + }, + subtitle: { + ...typeScale.bodySmall, + color: Colors.gray4, + }, + amountContainer: { + maxWidth: '50%', + }, + amountTitle: { + ...typeScale.labelMedium, + color: Colors.black, + flexWrap: 'wrap', + textAlign: 'right', + }, + amountSubtitle: { + ...typeScale.bodySmall, + color: Colors.gray4, + flexWrap: 'wrap', + textAlign: 'right', + }, +}) diff --git a/src/transactions/feed/TransactionDetailsScreen.test.tsx b/src/transactions/feed/TransactionDetailsScreen.test.tsx index 16e4ac6bc5b..e2956b66db2 100644 --- a/src/transactions/feed/TransactionDetailsScreen.test.tsx +++ b/src/transactions/feed/TransactionDetailsScreen.test.tsx @@ -11,6 +11,7 @@ import { getDynamicConfigParams } from 'src/statsig' import { StatsigDynamicConfigs } from 'src/statsig/types' import TransactionDetailsScreen from 'src/transactions/feed/TransactionDetailsScreen' import { + ClaimReward, DepositOrWithdraw, EarnClaimReward, EarnDeposit, @@ -44,6 +45,7 @@ import { mockCeloTokenId, mockCeurAddress, mockCeurTokenId, + mockClaimRewardTransaction, mockCusdAddress, mockCusdTokenId, mockDisplayNumber2, @@ -243,6 +245,17 @@ describe('TransactionDetailsScreen', () => { } } + function claimRewardTransaction({ + status = TransactionStatus.Complete, + ...rest + }: Partial): ClaimReward { + return { + ...mockClaimRewardTransaction, + status, + ...rest, + } + } + function earnClaimTransaction({ status = TransactionStatus.Complete, }: Partial): EarnClaimReward { @@ -692,6 +705,71 @@ describe('TransactionDetailsScreen', () => { }) }) + describe('Claim Reward', () => { + beforeEach(() => { + jest.clearAllMocks() + }) + + it('renders check status action for pending ClaimReward transaction', () => { + const { getByText } = renderScreen({ + transaction: claimRewardTransaction({ + status: TransactionStatus.Pending, + }), + }) + + expect(getByText('transactionDetailsActions.checkPendingTransactionStatus')).toBeTruthy() + }) + + it('renders details action for complete ClaimReward transaction', () => { + const { getByText } = renderScreen({ + transaction: claimRewardTransaction({ + status: TransactionStatus.Complete, + }), + storeOverrides: { + tokens: { + tokenBalances: mockTokenBalances, + }, + }, + }) + + expect(getByText('transactionDetailsActions.showCompletedTransactionDetails')).toBeTruthy() + }) + + it('should display app name', () => { + const { getByText } = renderScreen({ + transaction: claimRewardTransaction({ appName: 'Aave' }), + storeOverrides: { + tokens: { + tokenBalances: mockTokenBalances, + }, + }, + }) + + expect( + getByText( + 'transactionDetails.claimRewardSubtitle, {"txAppName":"Aave","tokenSymbol":"ARB"}' + ) + ).toBeTruthy() + }) + + it('should display when app name is not available', () => { + const { getByText } = renderScreen({ + transaction: claimRewardTransaction({ appName: undefined }), + storeOverrides: { + tokens: { + tokenBalances: mockTokenBalances, + }, + }, + }) + + expect( + getByText( + 'transactionDetails.claimRewardSubtitle, {"context":"noTxAppName","tokenSymbol":"ARB"}' + ) + ).toBeTruthy() + }) + }) + it(`renders the correct details for ${TokenTransactionTypeV2.Approval} transaction`, () => { const { getByText, getByTestId } = renderScreen({ transaction: approvalTransaction({ diff --git a/src/transactions/feed/TransactionDetailsScreen.tsx b/src/transactions/feed/TransactionDetailsScreen.tsx index 1ef8d3e437d..851a11073d7 100644 --- a/src/transactions/feed/TransactionDetailsScreen.tsx +++ b/src/transactions/feed/TransactionDetailsScreen.tsx @@ -9,6 +9,7 @@ import { coinbasePaySendersSelector, rewardsSendersSelector } from 'src/recipien import { useSelector } from 'src/redux/hooks' import { useTokenInfo } from 'src/tokens/hooks' import TransactionDetails from 'src/transactions/feed/TransactionDetails' +import { ClaimRewardContent } from 'src/transactions/feed/detailContent/ClaimRewardContent' import { EarnClaimContent, EarnDepositContent, @@ -64,6 +65,8 @@ function useHeaderTitle(transaction: TokenTransaction) { return t('swapScreen.title') case TokenTransactionTypeV2.Approval: return t('transactionFeed.approvalTransactionTitle') + case TokenTransactionTypeV2.ClaimReward: + return t('transactionFeed.claimRewardTitle') case TokenTransactionTypeV2.EarnWithdraw: return t('earnFlow.transactionFeed.earnWithdrawTitle') case TokenTransactionTypeV2.EarnClaimReward: @@ -115,6 +118,9 @@ function TransactionDetailsScreen({ route }: Props) { case TokenTransactionTypeV2.Withdraw: content = break + case TokenTransactionTypeV2.ClaimReward: + content = + break case TokenTransactionTypeV2.EarnClaimReward: content = break diff --git a/src/transactions/feed/TransactionFeed.tsx b/src/transactions/feed/TransactionFeed.tsx index f396edd59f3..162d8a1aaf0 100644 --- a/src/transactions/feed/TransactionFeed.tsx +++ b/src/transactions/feed/TransactionFeed.tsx @@ -116,6 +116,7 @@ function TransactionFeed() { return case TokenTransactionTypeV2.Deposit: case TokenTransactionTypeV2.Withdraw: + case TokenTransactionTypeV2.ClaimReward: // These are handled by the FeedV2 only return null case TokenTransactionTypeV2.EarnDeposit: diff --git a/src/transactions/feed/TransactionFeedItemImage.tsx b/src/transactions/feed/TransactionFeedItemImage.tsx index 014e4e7b052..8b39899cb06 100644 --- a/src/transactions/feed/TransactionFeedItemImage.tsx +++ b/src/transactions/feed/TransactionFeedItemImage.tsx @@ -24,6 +24,7 @@ type Props = { networkId: NetworkId; status: TransactionStatus; hideNetworkIcon? | TokenTransactionTypeV2.Approval | TokenTransactionTypeV2.Deposit | TokenTransactionTypeV2.Withdraw + | TokenTransactionTypeV2.ClaimReward | TokenTransactionTypeV2.EarnDeposit | TokenTransactionTypeV2.EarnSwapDeposit | TokenTransactionTypeV2.EarnWithdraw @@ -85,6 +86,7 @@ function TransactionFeedItemBaseImage(props: Props) { if ( transactionType === TokenTransactionTypeV2.Deposit || transactionType === TokenTransactionTypeV2.Withdraw || + transactionType === TokenTransactionTypeV2.ClaimReward || transactionType === TokenTransactionTypeV2.EarnWithdraw || transactionType === TokenTransactionTypeV2.EarnDeposit || transactionType === TokenTransactionTypeV2.EarnClaimReward || diff --git a/src/transactions/feed/TransactionFeedV2.tsx b/src/transactions/feed/TransactionFeedV2.tsx index bd5a8e812dd..cff9720be50 100644 --- a/src/transactions/feed/TransactionFeedV2.tsx +++ b/src/transactions/feed/TransactionFeedV2.tsx @@ -20,6 +20,7 @@ import { Spacing } from 'src/styles/styles' import { tokensByIdSelector } from 'src/tokens/selectors' import { getSupportedNetworkIdsForSwap } from 'src/tokens/utils' import { useTransactionFeedV2Query } from 'src/transactions/api' +import ClaimRewardFeedItem from 'src/transactions/feed/ClaimRewardFeedItem' import DepositOrWithdrawFeedItem from 'src/transactions/feed/DepositOrWithdrawFeedItem' import EarnFeedItem from 'src/transactions/feed/EarnFeedItem' import NftFeedItem from 'src/transactions/feed/NftFeedItem' @@ -307,6 +308,8 @@ function renderItem({ item: tx }: { item: TokenTransaction }) { case TokenTransactionTypeV2.Deposit: case TokenTransactionTypeV2.Withdraw: return + case TokenTransactionTypeV2.ClaimReward: + return case TokenTransactionTypeV2.EarnDeposit: case TokenTransactionTypeV2.EarnSwapDeposit: case TokenTransactionTypeV2.EarnWithdraw: diff --git a/src/transactions/feed/detailContent/ClaimRewardContent.tsx b/src/transactions/feed/detailContent/ClaimRewardContent.tsx new file mode 100644 index 00000000000..4c9a0ec7010 --- /dev/null +++ b/src/transactions/feed/detailContent/ClaimRewardContent.tsx @@ -0,0 +1,87 @@ +import React from 'react' +import { useTranslation } from 'react-i18next' +import { StyleSheet, Text, View } from 'react-native' +import RowDivider from 'src/components/RowDivider' +import TokenDisplay from 'src/components/TokenDisplay' +import Colors from 'src/styles/colors' +import { typeScale } from 'src/styles/fonts' +import { useTokenInfo } from 'src/tokens/hooks' +import FeeRowItem from 'src/transactions/feed/detailContent/FeeRowItem' +import { ClaimReward, FeeType } from 'src/transactions/types' + +interface ClaimRewardProps { + transaction: ClaimReward +} + +export function ClaimRewardContent({ transaction }: ClaimRewardProps) { + const { t } = useTranslation() + const txAppName = transaction.appName + const tokenInfo = useTokenInfo(transaction.amount.tokenId) + const tokenSymbol = tokenInfo?.symbol ?? '' + + return ( + <> + {t('transactionDetails.descriptionLabel')} + + {t('transactionDetails.claimRewardSubtitle', { + context: !txAppName ? 'noTxAppName' : undefined, + txAppName, + tokenSymbol, + })} + + + + + + {t('transactionDetails.claimRewardDetails')} + + + + + + + + + ) +} + +const styles = StyleSheet.create({ + detailsTitle: { + ...typeScale.labelSmall, + color: Colors.black, + }, + detailsSubtitle: { + ...typeScale.bodyMedium, + color: Colors.black, + }, + row: { + flex: 1, + flexDirection: 'row', + justifyContent: 'space-between', + flexWrap: 'wrap', + }, + amountTitle: { + ...typeScale.labelSemiBoldMedium, + color: Colors.black, + }, + amountSubtitle: { + ...typeScale.bodySmall, + color: Colors.gray4, + marginLeft: 'auto', + }, +}) diff --git a/src/transactions/types.ts b/src/transactions/types.ts index ad7f88046d3..820e91c0fe1 100644 --- a/src/transactions/types.ts +++ b/src/transactions/types.ts @@ -41,6 +41,7 @@ export type ConfirmedStandbyTransaction = ( | Omit | Omit | Omit + | Omit | Omit | Omit | Omit @@ -57,6 +58,7 @@ export type StandbyTransaction = | PendingStandbyTransaction | PendingStandbyTransaction | PendingStandbyTransaction + | PendingStandbyTransaction | PendingStandbyTransaction | PendingStandbyTransaction | PendingStandbyTransaction @@ -111,6 +113,7 @@ export type TokenTransaction = | NftTransfer | TokenApproval | DepositOrWithdraw + | ClaimReward | EarnDeposit | EarnSwapDeposit | EarnWithdraw @@ -141,12 +144,14 @@ export enum TokenTransactionTypeV2 { Approval = 'APPROVAL', Deposit = 'DEPOSIT', Withdraw = 'WITHDRAW', + ClaimReward = 'CLAIM_REWARD', /** @deprecated Use Deposit instead */ EarnDeposit = 'EARN_DEPOSIT', /** @deprecated Use Deposit instead */ EarnSwapDeposit = 'EARN_SWAP_DEPOSIT', /** @deprecated Use Withdraw instead */ EarnWithdraw = 'EARN_WITHDRAW', + /** @deprecated Use ClaimReward instead */ EarnClaimReward = 'EARN_CLAIM_REWARD', } @@ -162,6 +167,7 @@ export const FEED_V2_INCLUDE_TYPES = [ TokenTransactionTypeV2.Approval, TokenTransactionTypeV2.Deposit, TokenTransactionTypeV2.Withdraw, + TokenTransactionTypeV2.ClaimReward, ] // Can we optional the fields `transactionHash` and `block`? @@ -308,7 +314,7 @@ export interface EarnWithdraw { status: TransactionStatus } -/** @deprecated Use TokenTransfer instead */ +/** @deprecated Use ClaimReward instead */ export interface EarnClaimReward { networkId: NetworkId amount: TokenAmount @@ -321,6 +327,18 @@ export interface EarnClaimReward { status: TransactionStatus } +export interface ClaimReward { + networkId: NetworkId + amount: TokenAmount + type: TokenTransactionTypeV2.ClaimReward + transactionHash: string + timestamp: number + block: string + fees: Fee[] + appName: string | undefined + status: TransactionStatus +} + export interface TrackedTx { tx: TransactionRequest | undefined txHash: Hash | undefined diff --git a/test/RootStateSchema.json b/test/RootStateSchema.json index 0c24a0e1da6..14008f609e6 100644 --- a/test/RootStateSchema.json +++ b/test/RootStateSchema.json @@ -813,6 +813,54 @@ } ] }, + "ClaimReward": { + "additionalProperties": false, + "properties": { + "amount": { + "$ref": "#/definitions/TokenAmount" + }, + "appName": { + "type": "string" + }, + "block": { + "type": "string" + }, + "fees": { + "items": { + "$ref": "#/definitions/Fee" + }, + "type": "array" + }, + "networkId": { + "$ref": "#/definitions/NetworkId" + }, + "status": { + "$ref": "#/definitions/TransactionStatus" + }, + "timestamp": { + "type": "number" + }, + "transactionHash": { + "type": "string" + }, + "type": { + "const": "CLAIM_REWARD", + "type": "string" + } + }, + "required": [ + "amount", + "appName", + "block", + "fees", + "networkId", + "status", + "timestamp", + "transactionHash", + "type" + ], + "type": "object" + }, "CleverTapInboxMessage": { "additionalProperties": false, "properties": { @@ -2603,6 +2651,49 @@ ], "type": "object" }, + "PendingStandbyTransaction": { + "additionalProperties": false, + "properties": { + "amount": { + "$ref": "#/definitions/TokenAmount" + }, + "appName": { + "type": "string" + }, + "context": { + "$ref": "#/definitions/TransactionContext" + }, + "feeCurrencyId": { + "type": "string" + }, + "networkId": { + "$ref": "#/definitions/NetworkId" + }, + "status": { + "const": "Pending", + "type": "string" + }, + "timestamp": { + "type": "number" + }, + "transactionHash": { + "type": "string" + }, + "type": { + "const": "CLAIM_REWARD", + "type": "string" + } + }, + "required": [ + "amount", + "context", + "networkId", + "status", + "timestamp", + "type" + ], + "type": "object" + }, "PendingStandbyTransaction": { "additionalProperties": false, "properties": { @@ -3931,6 +4022,9 @@ { "$ref": "#/definitions/PendingStandbyTransaction" }, + { + "$ref": "#/definitions/PendingStandbyTransaction" + }, { "additionalProperties": false, "properties": { @@ -4265,6 +4359,64 @@ ], "type": "object" }, + { + "additionalProperties": false, + "properties": { + "amount": { + "$ref": "#/definitions/TokenAmount" + }, + "appName": { + "type": "string" + }, + "block": { + "type": "string" + }, + "context": { + "$ref": "#/definitions/TransactionContext" + }, + "feeCurrencyId": { + "type": "string" + }, + "fees": { + "items": { + "$ref": "#/definitions/Fee" + }, + "type": "array" + }, + "networkId": { + "$ref": "#/definitions/NetworkId" + }, + "status": { + "enum": [ + "Complete", + "Failed" + ], + "type": "string" + }, + "timestamp": { + "type": "number" + }, + "transactionHash": { + "type": "string" + }, + "type": { + "const": "CLAIM_REWARD", + "type": "string" + } + }, + "required": [ + "amount", + "block", + "context", + "fees", + "networkId", + "status", + "timestamp", + "transactionHash", + "type" + ], + "type": "object" + }, { "additionalProperties": false, "properties": { @@ -6281,6 +6433,9 @@ }, { "$ref": "#/definitions/DepositOrWithdraw" + }, + { + "$ref": "#/definitions/ClaimReward" } ] }, diff --git a/test/values.ts b/test/values.ts index b0af3d84aa1..8e14ad89d5d 100644 --- a/test/values.ts +++ b/test/values.ts @@ -48,6 +48,7 @@ import { import { TransactionDataInput } from 'src/send/types' import { NativeTokenBalance, StoredTokenBalance, TokenBalance } from 'src/tokens/slice' import { + ClaimReward, EarnClaimReward, EarnDeposit, EarnSwapDeposit, @@ -2035,6 +2036,33 @@ export const mockApprovalTransaction: TokenApproval = { status: TransactionStatus.Complete, } +export const mockClaimRewardTransaction: ClaimReward = { + type: TokenTransactionTypeV2.ClaimReward, + amount: { + localAmount: undefined, + tokenAddress: mockArbArbAddress, + tokenId: mockArbArbTokenId, + value: '1.5', + }, + block: '211278852', + fees: [ + { + amount: { + localAmount: undefined, + tokenAddress: mockArbArbAddress, + tokenId: mockArbArbTokenId, + value: '0.00000146037', + }, + type: 'SECURITY_FEE', + }, + ], + networkId: NetworkId['arbitrum-sepolia'], + appName: 'Aave', + timestamp: Date.now(), + transactionHash: '0xHASH2', + status: TransactionStatus.Complete, +} + export const mockEarnClaimRewardTransaction: EarnClaimReward = { type: TokenTransactionTypeV2.EarnClaimReward, amount: {