Skip to content

Commit

Permalink
feat: add swap fee to FeeDetailsBottomSheet (#6025)
Browse files Browse the repository at this point in the history
### Description

Adds the swap fee if available to the FeedDetailsBottomSheet used in
`EarnEnterAmount.tsx`.


| iOS w Swap | Android w Swap | iOS w/o Swap | Android w/o Swap |
| ----- | ----- | ----- | ----- |
|
![](https://github.com/user-attachments/assets/7537c3d6-d556-47be-b223-c7db0a0857dd)
|
![](https://github.com/user-attachments/assets/f1907e8b-13e9-4a52-a589-7d023c582aea)
|
![](https://github.com/user-attachments/assets/513762e4-80aa-454e-a033-b78f3d98a490)
|
![](https://github.com/user-attachments/assets/5a3f9b91-eda3-4db4-b9a8-53099909861b)
|

### Test plan

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

### Related issues

- Part of ACT-1357

### Backwards compatibility

Yes

### Network scalability

Yes

---------

Co-authored-by: Satish Ravi <satish.ravi@valoraapp.com>
  • Loading branch information
MuckT and satish-ravi authored Sep 19, 2024
1 parent 2aeec76 commit f27172b
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 18 deletions.
4 changes: 3 additions & 1 deletion locales/base/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -2571,7 +2571,9 @@
"moreInformation": "More information",
"estNetworkFee": "Est. Network Fee",
"maxNetworkFee": "Max Network Fee",
"networkFeeDescription": "The network fee is required by the network to process the deposit transaction."
"networkFeeDescription": "The network fee is required by the network to process the deposit transaction.",
"networkSwapFeeDescription": "The network fee is required by the network to process the deposit transactions. The {{appName}} fee of {{appFeePercentage}}% is charged for your use of our product.",
"appSwapFee": "{{appName}} Fee"
}
},
"activePools": {
Expand Down
7 changes: 3 additions & 4 deletions src/components/RowDivider.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import * as React from 'react'
import { StyleSheet, View, ViewStyle } from 'react-native'
import { StyleSheet, View } from 'react-native'
import { Colors } from 'src/styles/colors'
import { Spacing } from 'src/styles/styles'

export interface Props {
color?: Colors
style?: ViewStyle
}

export default function RowDivider({ color = Colors.gray2, style }: Props) {
return <View style={[styles.container, { backgroundColor: color }, style]} />
export default function RowDivider({ color = Colors.gray2 }: Props) {
return <View style={[styles.container, { backgroundColor: color }]} />
}

const styles = StyleSheet.create({
Expand Down
31 changes: 31 additions & 0 deletions src/earn/EarnEnterAmount.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -523,5 +523,36 @@ describe('EarnEnterAmount', () => {
expect(getByText('earnFlow.enterAmount.feeBottomSheet.feeDetails')).toBeVisible()
expect(getByTestId('EstNetworkFee/Value')).toBeTruthy()
expect(getByTestId('MaxNetworkFee/Value')).toBeTruthy()
expect(getByText('earnFlow.enterAmount.feeBottomSheet.networkFeeDescription')).toBeVisible()
})

it('should show swap fees on the FeeDetailsBottomSheet when swap transaction is present', async () => {
jest.mocked(usePrepareDepositTransactions).mockReturnValue({
prepareTransactionsResult: {
prepareTransactionsResult: mockPreparedTransaction,
swapTransaction: mockSwapTransaction,
},
refreshPreparedTransactions: jest.fn(),
clearPreparedTransactions: jest.fn(),
prepareTransactionError: undefined,
isPreparingTransactions: false,
})

const { getByTestId, getByText } = render(
<Provider store={store}>
<MockedNavigator component={EarnEnterAmount} params={params} />
</Provider>
)

fireEvent.press(getByTestId('LabelWithInfo/FeeLabel'))
expect(getByText('earnFlow.enterAmount.feeBottomSheet.feeDetails')).toBeVisible()
expect(getByTestId('EstNetworkFee/Value')).toBeTruthy()
expect(getByTestId('MaxNetworkFee/Value')).toBeTruthy()
expect(getByTestId('SwapFee/Value')).toBeTruthy()
expect(
getByText(
'earnFlow.enterAmount.feeBottomSheet.networkSwapFeeDescription, {"appFeePercentage":"0.6"}'
)
).toBeVisible()
})
})
89 changes: 76 additions & 13 deletions src/earn/EarnEnterAmount.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -439,14 +439,20 @@ function EarnEnterAmount({ route }: Props) {
/>
<KeyboardSpacer />
</KeyboardAwareScrollView>
<FeeDetailsBottomSheet
forwardedRef={feeDetailsBottomSheetRef}
title={t('earnFlow.enterAmount.feeBottomSheet.feeDetails')}
testID="FeeDetailsBottomSheet"
feeCurrency={feeCurrency}
estimatedFeeAmount={estimatedFeeAmount}
maxFeeAmount={maxFeeAmount}
/>
{tokenAmount && (
<FeeDetailsBottomSheet
forwardedRef={feeDetailsBottomSheetRef}
title={t('earnFlow.enterAmount.feeBottomSheet.feeDetails')}
testID="FeeDetailsBottomSheet"
feeCurrency={feeCurrency}
estimatedFeeAmount={estimatedFeeAmount}
maxFeeAmount={maxFeeAmount}
swapTransaction={swapTransaction}
pool={pool}
token={token}
tokenAmount={tokenAmount}
/>
)}
{tokenAmount && prepareTransactionsResult?.type === 'possible' && (
<EarnDepositBottomSheet
forwardedRef={reviewBottomSheetRef}
Expand Down Expand Up @@ -579,15 +585,42 @@ function FeeDetailsBottomSheet({
feeCurrency,
estimatedFeeAmount,
maxFeeAmount,
swapTransaction,
pool,
token,
tokenAmount,
}: {
forwardedRef: React.RefObject<BottomSheetModalRefType>
title: string
testID: string
feeCurrency?: TokenBalance
estimatedFeeAmount?: BigNumber
maxFeeAmount?: BigNumber
swapTransaction?: SwapTransaction | undefined
pool: EarnPosition
token: TokenBalance
tokenAmount: BigNumber
}) {
const { t } = useTranslation()
const depositToken = useTokenInfo(pool.dataProps.depositTokenId)

if (!depositToken) {
// should never happen
throw new Error(`Token info not found for token ID ${pool.dataProps.depositTokenId}`)
}

const swapFeeAmount = useMemo(() => {
if (swapTransaction && swapTransaction.appFeePercentageIncludedInPrice) {
return tokenAmount.multipliedBy(
new BigNumber(swapTransaction.appFeePercentageIncludedInPrice).shiftedBy(-2) // To convert from percentage to decimal
)
}
}, [swapTransaction, token])

const descriptionContainerStyle = [
styles.bottomSheetDescriptionContainer,
swapFeeAmount && { marginTop: Spacing.Large32 },
]

return (
<BottomSheet forwardedRef={forwardedRef} title={title} testId={testID}>
Expand Down Expand Up @@ -633,14 +666,40 @@ function FeeDetailsBottomSheet({
)}
</View>
</View>
<RowDivider style={{ marginBottom: Spacing.Large32 }} />
<View style={styles.gap8}>
<RowDivider />
{swapFeeAmount && (
<View style={styles.bottomSheetLineItem} testID="SwapFee">
<Text style={styles.bottomSheetLineLabel}>
{t('earnFlow.enterAmount.feeBottomSheet.appSwapFee')}
</Text>
<Text style={styles.bottomSheetLineLabelText} testID="SwapFee/Value">
{'≈ '}
<TokenDisplay tokenId={token.tokenId} amount={swapFeeAmount.toString()} />
{' ('}
<TokenDisplay
tokenId={token.tokenId}
showLocalAmount={false}
amount={swapFeeAmount.toString()}
/>
{')'}
</Text>
</View>
)}
<View style={descriptionContainerStyle}>
<Text style={styles.bottomSheetDescriptionTitle}>
{t('earnFlow.enterAmount.feeBottomSheet.moreInformation')}
</Text>
<Text style={styles.bottomSheetDescriptionText}>
{t('earnFlow.enterAmount.feeBottomSheet.networkFeeDescription')}
</Text>
{swapFeeAmount ? (
<Text style={styles.bottomSheetDescriptionText}>
{t('earnFlow.enterAmount.feeBottomSheet.networkSwapFeeDescription', {
appFeePercentage: swapTransaction?.appFeePercentageIncludedInPrice,
})}
</Text>
) : (
<Text style={styles.bottomSheetDescriptionText}>
{t('earnFlow.enterAmount.feeBottomSheet.networkFeeDescription')}
</Text>
)}
</View>
</View>
<Button
Expand Down Expand Up @@ -772,6 +831,10 @@ const styles = StyleSheet.create({
gap8: {
gap: Spacing.Smallest8,
},
bottomSheetDescriptionContainer: {
gap: Spacing.Smallest8,
marginTop: Spacing.Regular16,
},
bottomSheetTextContent: {
marginBottom: Spacing.XLarge48,
marginTop: Spacing.Smallest8,
Expand Down

0 comments on commit f27172b

Please sign in to comment.