diff --git a/locales/base/translation.json b/locales/base/translation.json index 5bacd247aa5..9d6a5534aac 100644 --- a/locales/base/translation.json +++ b/locales/base/translation.json @@ -1341,6 +1341,12 @@ "rewards": { "title": "Your rewards", "description": "Claim available rewards from open dapp positions" + }, + "claimRewardsScreen": { + "title": "Your rewards", + "description": "Now you can claim rewards from open dapp positions directly in {{appName}}!", + "claimButton": "Claim", + "rewardLabel": "Available reward" } }, "dappsScreenHelpDialog": { diff --git a/src/dapps/DappShortcutsRewards.test.tsx b/src/dapps/DappShortcutsRewards.test.tsx new file mode 100644 index 00000000000..750677ef796 --- /dev/null +++ b/src/dapps/DappShortcutsRewards.test.tsx @@ -0,0 +1,74 @@ +import { render, within } from '@testing-library/react-native' +import React from 'react' +import { Provider } from 'react-redux' +import DappShortcutsRewards from 'src/dapps/DappShortcutsRewards' +import { createMockStore } from 'test/utils' +import { mockCusdAddress, mockPositions, mockShortcuts } from 'test/values' + +jest.mock('src/statsig', () => ({ + getFeatureGate: jest.fn(() => true), +})) + +const mockCeloAddress = '0x471ece3750da237f93b8e339c536989b8978a438' +const mockUbeAddress = '0x00be915b9dcf56a3cbe739d9b9c202ca692409ec' + +describe('DappShortcutsRewards', () => { + beforeEach(() => { + jest.clearAllMocks() + }) + + it('should render claimable rewards correctly', () => { + const { getByText, getAllByTestId } = render( + + + + ) + + expect(getByText('dappShortcuts.claimRewardsScreen.title')).toBeTruthy() + expect(getByText('dappShortcuts.claimRewardsScreen.description')).toBeTruthy() + expect(getAllByTestId('DappShortcutsRewards/Card').length).toBe(1) + + const rewardCard = getAllByTestId('DappShortcutsRewards/Card')[0] + expect(within(rewardCard).getByTestId('DappShortcutsRewards/RewardAmount')).toHaveTextContent( + '0.098 UBE, 0.95 CELO' + ) + expect( + within(rewardCard).getByTestId('DappShortcutsRewards/RewardAmountFiat') + ).toHaveTextContent('₱0.88') // USD value $0.66, mocked exchange rate 1.33 + expect(within(rewardCard).getByTestId('DappShortcutsRewards/ClaimButton')).toBeTruthy() + }) +}) diff --git a/src/dapps/DappShortcutsRewards.tsx b/src/dapps/DappShortcutsRewards.tsx new file mode 100644 index 00000000000..41d19611864 --- /dev/null +++ b/src/dapps/DappShortcutsRewards.tsx @@ -0,0 +1,171 @@ +import { BigNumber } from 'bignumber.js' +import React from 'react' +import { useTranslation } from 'react-i18next' +import { Image, StyleSheet, Text, View } from 'react-native' +import Animated from 'react-native-reanimated' +import { useSafeAreaInsets } from 'react-native-safe-area-context' +import { useSelector } from 'react-redux' +import Button, { BtnSizes } from 'src/components/Button' +import TokenDisplay from 'src/components/TokenDisplay' +import { positionsWithClaimableRewardsSelector } from 'src/positions/selectors' +import { ClaimablePosition } from 'src/positions/types' +import Colors from 'src/styles/colors' +import fontStyles from 'src/styles/fonts' +import { Spacing } from 'src/styles/styles' +import { Currency } from 'src/utils/currencies' + +function DappShortcutsRewards() { + const { t } = useTranslation() + const insets = useSafeAreaInsets() + + const positionsWithClaimableRewards = useSelector(positionsWithClaimableRewardsSelector) + + const handleClaimReward = (position: ClaimablePosition) => () => { + // do something + } + + const renderItem = ({ item }: { item: ClaimablePosition }) => { + let claimableValueUsd = new BigNumber(0) + item.claimableShortcut.claimableTokens.forEach((token) => { + claimableValueUsd = claimableValueUsd.plus( + BigNumber(token.priceUsd).times(BigNumber(token.balance)) + ) + }) + + return ( + + + + + {t('dappShortcuts.claimRewardsScreen.rewardLabel')} + + + + {item.claimableShortcut.claimableTokens.map((token, index) => ( + + {index > 0 && ', '} + + + ))} + + {claimableValueUsd && ( + + )} + +