Skip to content

Commit

Permalink
feat(earn): earn transaction details content (#5425)
Browse files Browse the repository at this point in the history
### Description

Adds transaction details content for `EarnDeposit`, `EarnClaimReward`
and `EarnWithdraw`.

#### Screenshots

| iOS Deposit | iOS Claim | iOS Withdraw |
| ----- | ----- | ----- |
|
![](https://github.com/valora-inc/wallet/assets/26950305/27692908-edb1-4bcf-a876-ffff1d0c50bf
"iOS Deposit") |
![](https://github.com/valora-inc/wallet/assets/26950305/136518ee-bf17-40ad-8fc7-1abf3fae9506
"iOS Claim") |
![](https://github.com/valora-inc/wallet/assets/26950305/517de616-6017-46e4-9ab8-31556241c87e
"iOS Withdraw") |

### Test plan

- [x] Tested locally on iOS
- [x] Tested locally on Android
- [x] Unit tests updated

### Related issues

- Fixes ACT-1198

### 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)
  • Loading branch information
MuckT committed May 20, 2024
1 parent da2b95c commit c55cd0a
Show file tree
Hide file tree
Showing 6 changed files with 421 additions and 97 deletions.
12 changes: 12 additions & 0 deletions locales/base/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -2406,6 +2406,18 @@
"earnDepositSubtitle": "to {{providerName}} Pool",
"earnWithdrawTitle": "Withdrew",
"earnWithdrawSubtitle": "from {{providerName}} Pool"
},
"transactionDetails": {
"descriptionLabel": "Details",
"earnClaimTitle": "Collected",
"earnClaimSubtitle": "Collected {{tokenSymbol}} from {{providerName}} Pool",
"earnClaimDetails": "Amount Collected",
"earnDepositTitle": "Deposited",
"earnDepositSubtitle": "Deposited {{tokenSymbol}} to {{providerName}} Pool",
"earnDepositDetails": "Amount Deposited",
"earnWithdrawTitle": "Withdrew",
"earnWithdrawSubtitle": "Withdrew {{tokenSymbol}} from {{providerName}} Pool",
"earnWithdrawDetails": "Amount Withdrawn"
}
}
}
106 changes: 11 additions & 95 deletions src/transactions/feed/EarnFeedItem.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,16 @@ import ValoraAnalytics from 'src/analytics/ValoraAnalytics'
import { navigate } from 'src/navigator/NavigationService'
import { Screens } from 'src/navigator/Screens'
import EarnFeedItem from 'src/transactions/feed/EarnFeedItem'
import { NetworkId, TransactionStatus } from 'src/transactions/types'
import { NetworkId } from 'src/transactions/types'
import networkConfig from 'src/web3/networkConfig'
import { createMockStore } from 'test/utils'
import { mockAaveArbUsdcAddress, mockArbArbTokenId } from 'test/values'
import {
mockAaveArbUsdcAddress,
mockArbArbTokenId,
mockEarnClaimRewardTransaction,
mockEarnDepositTransaction,
mockEarnWithdrawTransaction,
} from 'test/values'

const store = createMockStore({
tokens: {
Expand Down Expand Up @@ -43,113 +49,23 @@ const store = createMockStore({
describe.each([
{
type: 'EarnWithdraw',
transaction: {
__typename: 'EarnWithdraw',
inAmount: {
localAmount: null,
tokenAddress: '0xdef',
tokenId: networkConfig.arbUsdcTokenId,
value: '1',
},
outAmount: {
localAmount: null,
tokenAddress: mockAaveArbUsdcAddress,
tokenId: networkConfig.aaveArbUsdcTokenId,
value: '0.996614',
},
block: '211276583',
fees: [
{
amount: {
localAmount: null,
tokenAddress: null,
tokenId: mockArbArbTokenId,
value: '0.00000229122',
},
type: 'SECURITY_FEE',
},
],
networkId: NetworkId['arbitrum-sepolia'],
providerId: 'aave-v3',
timestamp: Date.now(),
transactionHash: '0xHASH0',
type: 'EARN_WITHDRAW',
status: TransactionStatus.Complete,
},
transaction: mockEarnWithdrawTransaction,
expectedTitle: 'earnFlow.transactionFeed.earnWithdrawTitle',
expectedSubTitle: 'earnFlow.transactionFeed.earnWithdrawSubtitle, {"providerName":"Aave"}',
expectedTotal: '+1.00 USDC',
expectedTotalLocal: '₱1.33',
},
{
type: 'EarnDeposit',
transaction: {
__typename: 'EarnDeposit',
inAmount: {
localAmount: null,
tokenAddress: mockAaveArbUsdcAddress,
tokenId: networkConfig.aaveArbUsdcTokenId,
value: '10',
},
outAmount: {
localAmount: null,
tokenAddress: '0xdef',
tokenId: networkConfig.arbUsdcTokenId,
value: '10',
},
block: '210927567',
fees: [
{
amount: {
localAmount: null,
tokenAddress: null,
tokenId: mockArbArbTokenId,
value: '0.00000284243',
},
type: 'SECURITY_FEE',
},
],
networkId: NetworkId['arbitrum-sepolia'],
providerId: 'aave-v3',
timestamp: Date.now(),
transactionHash: '0xHASH1',
type: 'EARN_DEPOSIT',
status: TransactionStatus.Complete,
},
transaction: mockEarnDepositTransaction,
expectedTitle: 'earnFlow.transactionFeed.earnDepositTitle',
expectedSubTitle: 'earnFlow.transactionFeed.earnDepositSubtitle, {"providerName":"Aave"}',
expectedTotal: '-10.00 USDC',
expectedTotalLocal: '₱13.30',
},
{
type: 'EarnClaimReward',
transaction: {
__typename: 'EarnClaimReward',
amount: {
localAmount: null,
tokenAddress: '0xhij',
tokenId: mockArbArbTokenId,
value: '1.5',
},
block: '211278852',
fees: [
{
amount: {
localAmount: null,
tokenAddress: null,
tokenId: mockArbArbTokenId,
value: '0.00000146037',
},
type: 'SECURITY_FEE',
},
],
networkId: NetworkId['arbitrum-sepolia'],
providerId: 'aave-v3',
timestamp: Date.now(),
transactionHash: '0xHASH2',
type: 'EARN_CLAIM_REWARD',
status: TransactionStatus.Complete,
} as any,
transaction: mockEarnClaimRewardTransaction,
expectedTitle: 'earnFlow.transactionFeed.earnClaimTitle',
expectedSubTitle: 'earnFlow.transactionFeed.earnClaimSubtitle, {"providerName":"Aave"}',
expectedTotal: '+1.50 ARB',
Expand Down
115 changes: 114 additions & 1 deletion src/transactions/feed/TransactionDetailsScreen.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,13 @@ import ValoraAnalytics from 'src/analytics/ValoraAnalytics'
import { navigate } from 'src/navigator/NavigationService'
import { Screens } from 'src/navigator/Screens'
import { RootState } from 'src/redux/reducers'
import { getDynamicConfigParams } from 'src/statsig'
import { StatsigDynamicConfigs } from 'src/statsig/types'
import TransactionDetailsScreen from 'src/transactions/feed/TransactionDetailsScreen'
import {
EarnClaimReward,
EarnDeposit,
EarnWithdraw,
Fee,
FeeType,
NetworkId,
Expand Down Expand Up @@ -39,6 +44,9 @@ import {
mockCusdTokenId,
mockDisplayNumber2,
mockE164Number2,
mockEarnClaimRewardTransaction,
mockEarnDepositTransaction,
mockEarnWithdrawTransaction,
} from 'test/values'

jest.mock('src/analytics/ValoraAnalytics')
Expand Down Expand Up @@ -176,6 +184,33 @@ describe('TransactionDetailsScreen', () => {
}
}

function earnClaimTransaction({
status = TransactionStatus.Complete,
}: Partial<EarnClaimReward>): EarnClaimReward {
return {
...mockEarnClaimRewardTransaction,
status,
}
}

function earnDepositTransaction({
status = TransactionStatus.Complete,
}: Partial<EarnDeposit>): EarnDeposit {
return {
...mockEarnDepositTransaction,
status,
}
}

function earnWithdrawTransaction({
status = TransactionStatus.Complete,
}: Partial<EarnWithdraw>): EarnWithdraw {
return {
...mockEarnWithdrawTransaction,
status,
}
}

it('renders correctly for sends', async () => {
const { getByTestId, getByText } = renderScreen({
transaction: tokenTransfer({
Expand Down Expand Up @@ -338,7 +373,85 @@ describe('TransactionDetailsScreen', () => {
expect(getByText('transactionDetailsActions.checkPendingTransactionStatus')).toBeTruthy()
})

it(`renders the correct details for ${TokenTransactionTypeV2.Approval} transacton`, () => {
describe('Earn', () => {
beforeEach(() => {
jest.clearAllMocks()
jest.mocked(getDynamicConfigParams).mockImplementation(({ configName, defaultValues }) => {
switch (configName) {
case StatsigDynamicConfigs.EARN_STABLECOIN_CONFIG:
return {
providerName: 'Aave',
providerLogoUrl: 'logoUrl',
providerTermsAndConditionsUrl: 'termsUrl',
}
default:
return defaultValues
}
})
})

it(`renders check status action for pending ${TokenTransactionTypeV2.EarnClaimReward} transaction`, () => {
const { getByText } = renderScreen({
transaction: earnClaimTransaction({
status: TransactionStatus.Pending,
}),
})

expect(getByText('transactionDetailsActions.checkPendingTransactionStatus')).toBeTruthy()
})

it(`renders check status action for pending ${TokenTransactionTypeV2.EarnDeposit} transaction`, () => {
const { getByText } = renderScreen({
transaction: earnDepositTransaction({
status: TransactionStatus.Pending,
}),
})

expect(getByText('transactionDetailsActions.checkPendingTransactionStatus')).toBeTruthy()
})

it(`renders check status action for pending ${TokenTransactionTypeV2.EarnWithdraw} transaction`, () => {
const { getByText } = renderScreen({
transaction: earnWithdrawTransaction({
status: TransactionStatus.Pending,
}),
})

expect(getByText('transactionDetailsActions.checkPendingTransactionStatus')).toBeTruthy()
})

it(`renders details action for complete ${TokenTransactionTypeV2.EarnClaimReward} transaction`, () => {
const { getByText } = renderScreen({
transaction: earnClaimTransaction({
status: TransactionStatus.Complete,
}),
})

expect(getByText('transactionDetailsActions.showCompletedTransactionDetails')).toBeTruthy()
})

it(`renders details action for complete ${TokenTransactionTypeV2.EarnDeposit} transaction`, () => {
const { getByText } = renderScreen({
transaction: earnDepositTransaction({
status: TransactionStatus.Complete,
}),
})

expect(getByText('transactionDetailsActions.showCompletedTransactionDetails')).toBeTruthy()
})

it(`renders details action for complete ${TokenTransactionTypeV2.EarnWithdraw} transaction`, () => {
const { getByText } = renderScreen({
transaction: earnWithdrawTransaction({
status: TransactionStatus.Complete,
}),
})

expect(getByText('transactionDetailsActions.showCompletedTransactionDetails')).toBeTruthy()
})
})

it(`renders the correct details for ${TokenTransactionTypeV2.Approval} transaction`, () => {
const { getByText, getByTestId } = renderScreen({
transaction: approvalTransaction({
status: TransactionStatus.Complete,
Expand Down
14 changes: 13 additions & 1 deletion src/transactions/feed/TransactionDetailsScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,17 @@ 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 {
EarnClaimContent,
EarnDepositContent,
EarnWithdrawContent,
} from 'src/transactions/feed/detailContent/EarnContent'
import TokenApprovalDetails from 'src/transactions/feed/detailContent/TokenApprovalDetails'
import TransferSentContent from 'src/transactions/feed/detailContent/TransferSentContent'
import {
EarnClaimReward,
EarnDeposit,
EarnWithdraw,
TokenApproval,
TokenExchange,
TokenTransaction,
Expand Down Expand Up @@ -112,9 +120,13 @@ function TransactionDetailsScreen({ route }: Props) {
retryHandler = () => navigate(Screens.SwapScreenWithBack)
break
case TokenTransactionTypeV2.EarnClaimReward:
content = <EarnClaimContent transaction={transaction as EarnClaimReward} />
break
case TokenTransactionTypeV2.EarnWithdraw:
content = <EarnWithdrawContent transaction={transaction as EarnWithdraw} />
break
case TokenTransactionTypeV2.EarnDeposit:
content = null //TODO (act-1198): details for Earn
content = <EarnDepositContent transaction={transaction as EarnDeposit} />
break
case TokenTransactionTypeV2.Approval:
content = <TokenApprovalDetails transaction={transaction as TokenApproval} />
Expand Down
Loading

0 comments on commit c55cd0a

Please sign in to comment.