Skip to content

Commit

Permalink
feat(earn): include swap info in deposit bottom sheet (#6027)
Browse files Browse the repository at this point in the history
### Description

Pass swap tx info to bottom sheet and display swap details. Will do
analytics update in a follow up

### Test plan

<img
src="https://github.com/user-attachments/assets/3cbf59e1-5528-4fcd-adc1-a6f9b6d1d39c"
width="250" />


### Related issues

- Part of ACT-1358

### 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
satish-ravi authored Sep 19, 2024
1 parent 86ab990 commit f284401
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 57 deletions.
140 changes: 92 additions & 48 deletions src/earn/EarnDepositBottomSheet.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,20 @@ import { EarnEvents } from 'src/analytics/Events'
import { openUrl } from 'src/app/actions'
import EarnDepositBottomSheet from 'src/earn/EarnDepositBottomSheet'
import { depositStart } from 'src/earn/slice'
import { isGasSubsidizedForNetwork } from 'src/earn/utils'
import * as earnUtils from 'src/earn/utils'
import { NetworkId } from 'src/transactions/types'
import { PreparedTransactionsPossible } from 'src/viem/prepareTransactions'
import { getSerializablePreparedTransactions } from 'src/viem/preparedTransactionSerialization'
import { createMockStore } from 'test/utils'
import {
mockAccount,
mockArbEthTokenId,
mockArbUsdcTokenId,
mockEarnPositions,
mockTokenBalances,
mockUSDCAddress,
} from 'test/values'

jest.mock('src/earn/utils')

const mockPreparedTransaction: PreparedTransactionsPossible = {
type: 'possible' as const,
transactions: [
Expand Down Expand Up @@ -52,6 +52,41 @@ const mockPreparedTransaction: PreparedTransactionsPossible = {
},
}

const mockDepositProps = {
forwardedRef: { current: null },
inputAmount: new BigNumber(100),
preparedTransaction: mockPreparedTransaction,
pool: mockEarnPositions[0],
mode: 'deposit' as const,
inputTokenId: mockArbUsdcTokenId,
}

const mockSwapDepositProps = {
...mockDepositProps,
mode: 'swap-deposit' as const,
inputTokenId: mockArbEthTokenId,
inputAmount: new BigNumber(0.041),
swapTransaction: {
swapType: 'same-chain' as const,
chainId: 42161,
price: '2439',
guaranteedPrice: '2377',
appFeePercentageIncludedInPrice: '0.6',
sellTokenAddress: '0xEeeeeeE',
buyTokenAddress: mockUSDCAddress,
sellAmount: '41000000000000000',
buyAmount: '99999000',
allowanceTarget: '0x0000000000000000000000000000000000000123',
from: mockAccount,
to: '0x0000000000000000000000000000000000000123',
value: '0',
data: '0x0',
gas: '1800000',
estimatedGasUse: undefined,
estimatedPriceImpact: '0.1',
},
}

describe('EarnDepositBottomSheet', () => {
const expectedAnalyticsProperties = {
depositTokenId: mockArbUsdcTokenId,
Expand All @@ -63,22 +98,58 @@ describe('EarnDepositBottomSheet', () => {

beforeEach(() => {
jest.clearAllMocks()
jest.mocked(isGasSubsidizedForNetwork).mockReturnValue(false)
jest.spyOn(earnUtils, 'isGasSubsidizedForNetwork').mockReturnValue(false)
})

it('renders all elements for deposit', () => {
const { getByTestId, queryByTestId, getByText } = render(
<Provider
store={createMockStore({
tokens: { tokenBalances: mockTokenBalances },
})}
>
<EarnDepositBottomSheet {...mockDepositProps} />
</Provider>
)
expect(getByText('earnFlow.depositBottomSheet.title')).toBeTruthy()
expect(
getByText('earnFlow.depositBottomSheet.descriptionV1_93, {"providerName":"Aave"}')
).toBeTruthy()

expect(queryByTestId('EarnDeposit/GasSubsidized')).toBeFalsy()

expect(getByText('earnFlow.depositBottomSheet.yieldRate')).toBeTruthy()
expect(getByText('earnFlow.depositBottomSheet.apy, {"apy":"1.92"}')).toBeTruthy()

expect(getByText('earnFlow.depositBottomSheet.amount')).toBeTruthy()
expect(getByTestId('EarnDeposit/Amount')).toHaveTextContent('100.00 USDC(₱133.00)')

expect(getByText('earnFlow.depositBottomSheet.fee')).toBeTruthy()
expect(getByTestId('EarnDeposit/Fee')).toHaveTextContent('₱0.012(0.000006 ETH)')

expect(getByText('earnFlow.depositBottomSheet.provider')).toBeTruthy()
expect(getByText('Aave')).toBeTruthy()
expect(getByTestId('EarnDeposit/ProviderInfo')).toBeTruthy()

expect(getByText('earnFlow.depositBottomSheet.network')).toBeTruthy()
expect(getByText('Arbitrum Sepolia')).toBeTruthy()

expect(
getByText('earnFlow.depositBottomSheet.footerV1_93, {"providerName":"Aave"}')
).toBeTruthy()

expect(getByTestId('EarnDeposit/PrimaryCta')).toBeTruthy()
expect(getByTestId('EarnDeposit/SecondaryCta')).toBeTruthy()
})

it('renders all elements', () => {
it('renders all elements for swap-deposit', () => {
const { getByTestId, queryByTestId, getByText } = render(
<Provider
store={createMockStore({
tokens: { tokenBalances: mockTokenBalances },
})}
>
<EarnDepositBottomSheet
forwardedRef={{ current: null }}
amount={new BigNumber(100)}
preparedTransaction={mockPreparedTransaction}
pool={mockEarnPositions[0]}
/>
<EarnDepositBottomSheet {...mockSwapDepositProps} />
</Provider>
)
expect(getByText('earnFlow.depositBottomSheet.title')).toBeTruthy()
Expand All @@ -94,6 +165,9 @@ describe('EarnDepositBottomSheet', () => {
expect(getByText('earnFlow.depositBottomSheet.amount')).toBeTruthy()
expect(getByTestId('EarnDeposit/Amount')).toHaveTextContent('100.00 USDC(₱133.00)')

expect(getByTestId('EarnDeposit/Swap/From')).toHaveTextContent('0.041 ETH')
expect(getByTestId('EarnDeposit/Swap/To')).toHaveTextContent('100.00 USDC')

expect(getByText('earnFlow.depositBottomSheet.fee')).toBeTruthy()
expect(getByTestId('EarnDeposit/Fee')).toHaveTextContent('₱0.012(0.000006 ETH)')

Expand All @@ -116,12 +190,7 @@ describe('EarnDepositBottomSheet', () => {
const store = createMockStore({ tokens: { tokenBalances: mockTokenBalances } })
const { getByTestId } = render(
<Provider store={store}>
<EarnDepositBottomSheet
forwardedRef={{ current: null }}
amount={new BigNumber(100)}
preparedTransaction={mockPreparedTransaction}
pool={mockEarnPositions[0]}
/>
<EarnDepositBottomSheet {...mockDepositProps} />
</Provider>
)

Expand All @@ -147,12 +216,7 @@ describe('EarnDepositBottomSheet', () => {
it('pressing cancel fires analytics event', () => {
const { getByTestId } = render(
<Provider store={createMockStore({ tokens: { tokenBalances: mockTokenBalances } })}>
<EarnDepositBottomSheet
forwardedRef={{ current: null }}
amount={new BigNumber(100)}
preparedTransaction={mockPreparedTransaction}
pool={mockEarnPositions[0]}
/>
<EarnDepositBottomSheet {...mockDepositProps} />
</Provider>
)

Expand All @@ -167,12 +231,7 @@ describe('EarnDepositBottomSheet', () => {
const store = createMockStore({ tokens: { tokenBalances: mockTokenBalances } })
const { getByTestId } = render(
<Provider store={store}>
<EarnDepositBottomSheet
forwardedRef={{ current: null }}
amount={new BigNumber(100)}
preparedTransaction={mockPreparedTransaction}
pool={mockEarnPositions[0]}
/>
<EarnDepositBottomSheet {...mockDepositProps} />
</Provider>
)

Expand All @@ -188,12 +247,7 @@ describe('EarnDepositBottomSheet', () => {
const store = createMockStore({ tokens: { tokenBalances: mockTokenBalances } })
const { getByTestId } = render(
<Provider store={store}>
<EarnDepositBottomSheet
forwardedRef={{ current: null }}
amount={new BigNumber(100)}
preparedTransaction={mockPreparedTransaction}
pool={mockEarnPositions[0]}
/>
<EarnDepositBottomSheet {...mockDepositProps} />
</Provider>
)

Expand All @@ -212,12 +266,7 @@ describe('EarnDepositBottomSheet', () => {
})
const { getByTestId } = render(
<Provider store={store}>
<EarnDepositBottomSheet
forwardedRef={{ current: null }}
amount={new BigNumber(100)}
preparedTransaction={mockPreparedTransaction}
pool={mockEarnPositions[0]}
/>
<EarnDepositBottomSheet {...mockDepositProps} />
</Provider>
)

Expand All @@ -227,15 +276,10 @@ describe('EarnDepositBottomSheet', () => {
})

it('shows gas subsidized copy if feature gate is set', () => {
jest.mocked(isGasSubsidizedForNetwork).mockReturnValue(true)
jest.spyOn(earnUtils, 'isGasSubsidizedForNetwork').mockReturnValue(true)
const { getByTestId } = render(
<Provider store={createMockStore({ tokens: { tokenBalances: mockTokenBalances } })}>
<EarnDepositBottomSheet
forwardedRef={{ current: null }}
amount={new BigNumber(100)}
preparedTransaction={mockPreparedTransaction}
pool={mockEarnPositions[0]}
/>
<EarnDepositBottomSheet {...mockDepositProps} />
</Provider>
)

Expand Down
52 changes: 44 additions & 8 deletions src/earn/EarnDepositBottomSheet.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import BigNumber from 'bignumber.js'
import React, { RefObject } from 'react'
import React, { RefObject, useMemo } from 'react'
import { Trans, useTranslation } from 'react-i18next'
import { StyleSheet, Text, View } from 'react-native'
import AppAnalytics from 'src/analytics/AppAnalytics'
Expand All @@ -12,13 +12,16 @@ import TokenDisplay from 'src/components/TokenDisplay'
import { getTotalYieldRate } from 'src/earn/poolInfo'
import { depositStatusSelector } from 'src/earn/selectors'
import { depositStart } from 'src/earn/slice'
import { isGasSubsidizedForNetwork } from 'src/earn/utils'
import { EarnDepositMode } from 'src/earn/types'
import { getSwapToAmountInDecimals, isGasSubsidizedForNetwork } from 'src/earn/utils'
import ArrowRightThick from 'src/icons/ArrowRightThick'
import { EarnPosition } from 'src/positions/types'
import { useDispatch, useSelector } from 'src/redux/hooks'
import { NETWORK_NAMES } from 'src/shared/conts'
import Colors from 'src/styles/colors'
import { typeScale } from 'src/styles/fonts'
import { Spacing } from 'src/styles/styles'
import { SwapTransaction } from 'src/swap/types'
import {
PreparedTransactionsPossible,
getFeeCurrencyAndAmounts,
Expand All @@ -28,23 +31,37 @@ import { getSerializablePreparedTransactions } from 'src/viem/preparedTransactio
export default function EarnDepositBottomSheet({
forwardedRef,
preparedTransaction,
amount,
inputAmount,
inputTokenId,
pool,
mode,
swapTransaction,
}: {
forwardedRef: RefObject<BottomSheetModalRefType>
preparedTransaction: PreparedTransactionsPossible
amount: BigNumber
inputTokenId: string
inputAmount: BigNumber
pool: EarnPosition
mode: EarnDepositMode
swapTransaction?: SwapTransaction
}) {
const { t } = useTranslation()
const dispatch = useDispatch()
const depositStatus = useSelector(depositStatusSelector)
const transactionSubmitted = depositStatus === 'loading'

const depositAmount = useMemo(
() =>
mode === 'swap-deposit' && swapTransaction
? getSwapToAmountInDecimals({ swapTransaction, fromAmount: inputAmount })
: inputAmount,
[inputAmount, swapTransaction]
)

const commonAnalyticsProperties = {
providerId: pool.appId,
depositTokenId: pool.dataProps.depositTokenId,
tokenAmount: amount.toString(),
tokenAmount: inputAmount.toString(),
networkId: pool.networkId,
poolId: pool.positionId,
}
Expand Down Expand Up @@ -75,7 +92,7 @@ export default function EarnDepositBottomSheet({
const onPressComplete = () => {
dispatch(
depositStart({
amount: amount.toString(),
amount: depositAmount.toString(),
pool,
preparedTransactions: getSerializablePreparedTransactions(preparedTransaction.transactions),
})
Expand Down Expand Up @@ -106,7 +123,7 @@ export default function EarnDepositBottomSheet({
<View style={styles.valueRow} testID="EarnDeposit/Amount">
<TokenDisplay
testID="EarnDeposit/AmountCrypto"
amount={amount}
amount={depositAmount}
tokenId={pool.dataProps.depositTokenId}
style={styles.value}
showLocalAmount={false}
Expand All @@ -115,13 +132,32 @@ export default function EarnDepositBottomSheet({
{'('}
<TokenDisplay
testID="EarnDeposit/AmountFiat"
amount={amount}
amount={depositAmount}
tokenId={pool.dataProps.depositTokenId}
showLocalAmount={true}
/>
{')'}
</Text>
</View>
{mode === 'swap-deposit' && (
<View style={styles.valueRow}>
<TokenDisplay
testID="EarnDeposit/Swap/From"
tokenId={inputTokenId}
amount={inputAmount.toString()}
showLocalAmount={false}
style={styles.valueSecondary}
/>
<ArrowRightThick size={20} color={Colors.gray3} />
<TokenDisplay
testID="EarnDeposit/Swap/To"
tokenId={pool.dataProps.depositTokenId}
amount={depositAmount}
showLocalAmount={false}
style={styles.valueSecondary}
/>
</View>
)}
</LabelledItem>
<LabelledItem label={t('earnFlow.depositBottomSheet.fee')}>
<View style={styles.valueRow} testID="EarnDeposit/Fee">
Expand Down
5 changes: 4 additions & 1 deletion src/earn/EarnEnterAmount.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -451,8 +451,11 @@ function EarnEnterAmount({ route }: Props) {
<EarnDepositBottomSheet
forwardedRef={reviewBottomSheetRef}
preparedTransaction={prepareTransactionsResult}
amount={tokenAmount}
inputAmount={tokenAmount}
pool={pool}
mode={mode}
swapTransaction={swapTransaction}
inputTokenId={token.tokenId}
/>
)}
<TokenBottomSheet
Expand Down

0 comments on commit f284401

Please sign in to comment.