diff --git a/app/components/SetAmountButton.test.tsx b/app/components/SetAmountButton.test.tsx
new file mode 100644
index 0000000000..4edd1f5068
--- /dev/null
+++ b/app/components/SetAmountButton.test.tsx
@@ -0,0 +1,20 @@
+import { render } from "@testing-library/react-native";
+import BigNumber from "bignumber.js";
+import * as React from "react";
+import { SetAmountButton } from "./SetAmountButton";
+
+const buttonType: Array<'half' | 'max'> = ['half', 'max']
+const buttonAmount = new BigNumber(10);
+
+describe('set amount button', () => {
+ buttonType.forEach(type => {
+ it(`should match styling of set amount button type ${type}`, () => {
+ const onPress = jest.fn()
+ const component = (
+
+ )
+ const rendered = render(component)
+ expect(rendered.toJSON()).toMatchSnapshot()
+ })
+ })
+})
diff --git a/app/components/SetAmountButton.tsx b/app/components/SetAmountButton.tsx
new file mode 100644
index 0000000000..7b725e36d1
--- /dev/null
+++ b/app/components/SetAmountButton.tsx
@@ -0,0 +1,35 @@
+import React from 'react'
+import { TouchableOpacity } from 'react-native'
+import { tailwind } from '../tailwind'
+import { Text } from './Text'
+import { translate } from '../translations'
+import BigNumber from 'bignumber.js'
+
+export enum AmountButtonTypes {
+ half = '50%',
+ max = 'MAX'
+}
+interface SetAmountButtonProps {
+ type: AmountButtonTypes
+ onPress: (amount: string) => void
+ amount: BigNumber
+}
+
+export function SetAmountButton (props: SetAmountButtonProps): JSX.Element {
+ const decimalPlace = 8
+
+ return (
+ {
+ props.onPress(props.type === AmountButtonTypes.half ? props.amount.div(2).toFixed(decimalPlace) : props.amount.toFixed(decimalPlace))
+ }}
+ >
+ {translate('components/max', props.type)}
+
+ )
+}
diff --git a/app/components/__snapshots__/SetAmountButton.test.tsx.snap b/app/components/__snapshots__/SetAmountButton.test.tsx.snap
new file mode 100644
index 0000000000..2fdc2026cc
--- /dev/null
+++ b/app/components/__snapshots__/SetAmountButton.test.tsx.snap
@@ -0,0 +1,117 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`set amount button should match styling of set amount button type half 1`] = `
+
+
+ half
+
+
+`;
+
+exports[`set amount button should match styling of set amount button type max 1`] = `
+
+
+ max
+
+
+`;
diff --git a/app/screens/AppNavigator/screens/Balances/ConvertScreen.tsx b/app/screens/AppNavigator/screens/Balances/ConvertScreen.tsx
index f5ab0703d7..73bc0310cf 100644
--- a/app/screens/AppNavigator/screens/Balances/ConvertScreen.tsx
+++ b/app/screens/AppNavigator/screens/Balances/ConvertScreen.tsx
@@ -15,6 +15,7 @@ import { Logging } from '../../../../api'
import { Text, TextInput, View } from '../../../../components'
import { Button } from '../../../../components/Button'
import { getTokenIcon } from '../../../../components/icons/tokens/_index'
+import { AmountButtonTypes, SetAmountButton } from '../../../../components/SetAmountButton'
import { SectionTitle } from '../../../../components/SectionTitle'
import { useTokensAPI } from '../../../../hooks/wallet/TokensAPI'
import { RootState } from '../../../../store'
@@ -131,27 +132,8 @@ function ConversionIOCard (props: { style?: StyleProp, mode: 'input'
const iconType = props.unit === 'UTXO' ? '_UTXO' : 'DFI'
const titlePrefix = props.mode === 'input' ? 'CONVERT' : 'TO'
const title = `${translate('screens/Convert', titlePrefix)} ${props.unit}`
-
const DFIIcon = getTokenIcon(iconType)
- const MaxButton = (): JSX.Element | null => {
- if (props.mode === 'output') {
- return null
- }
- return (
- {
- if (props.onChange !== undefined) {
- props.onChange(props.balance.toString())
- }
- }}
- >
- {translate('components/max', 'MAX')}
-
- )
- }
return (
@@ -170,15 +152,16 @@ function ConversionIOCard (props: { style?: StyleProp, mode: 'input'
/>
-
-
+
+
{translate('screens/Convert', 'Balance')}:
{value}}
/>
- {MaxButton()}
+ {props.mode === 'input' && props.onChange && }
+ {props.mode === 'input' && props.onChange && }
)
diff --git a/app/screens/AppNavigator/screens/Balances/screens/SendScreen.tsx b/app/screens/AppNavigator/screens/Balances/screens/SendScreen.tsx
index 1d6b0eb616..e0ea93638a 100644
--- a/app/screens/AppNavigator/screens/Balances/screens/SendScreen.tsx
+++ b/app/screens/AppNavigator/screens/Balances/screens/SendScreen.tsx
@@ -17,6 +17,7 @@ import { Text, TextInput } from '../../../../../components'
import { Button } from '../../../../../components/Button'
import { getTokenIcon } from '../../../../../components/icons/tokens/_index'
import { SectionTitle } from '../../../../../components/SectionTitle'
+import { AmountButtonTypes, SetAmountButton } from '../../../../../components/SetAmountButton'
import { useNetworkContext } from '../../../../../contexts/NetworkContext'
import { useWhaleApiClient } from '../../../../../contexts/WhaleContext'
import { RootState } from '../../../../../store'
@@ -112,7 +113,9 @@ export function SendScreen ({ route, navigation }: Props): JSX.Element {
/>
{
+ token={token}
+ control={control}
+ onAmountButtonPress={async (amount) => {
setValue('amount', amount)
await trigger('amount')
}}
@@ -189,11 +192,11 @@ function AddressRow ({
interface AmountForm {
control: Control
token: WalletToken
- onMaxPress: (amount: string) => void
+ onAmountButtonPress: (amount: string) => void
fee: BigNumber
}
-function AmountRow ({ token, control, onMaxPress, fee }: AmountForm): JSX.Element {
+function AmountRow ({ token, control, onAmountButtonPress, fee }: AmountForm): JSX.Element {
const Icon = getTokenIcon(token.avatarSymbol)
let maxAmount = token.symbol === 'DFI' ? new BigNumber(token.amount).minus(fee).toFixed(8) : token.amount
maxAmount = BigNumber.max(maxAmount, 0).toFixed(8)
@@ -234,20 +237,16 @@ function AmountRow ({ token, control, onMaxPress, fee }: AmountForm): JSX.Elemen
name='amount'
defaultValue=''
/>
-
-
+
+
{translate('screens/SendScreen', 'Balance: ')}
{value}}
/>
- onMaxPress(maxAmount)}>
- {translate('screens/SendScreen', 'MAX')}
-
-
+
+
>
)
diff --git a/app/screens/AppNavigator/screens/Dex/DexAddLiquidity.tsx b/app/screens/AppNavigator/screens/Dex/DexAddLiquidity.tsx
index a8819d30f7..1b09c4b272 100644
--- a/app/screens/AppNavigator/screens/Dex/DexAddLiquidity.tsx
+++ b/app/screens/AppNavigator/screens/Dex/DexAddLiquidity.tsx
@@ -4,11 +4,12 @@ import { StackScreenProps } from '@react-navigation/stack'
import BigNumber from 'bignumber.js'
import * as React from 'react'
import { useCallback, useEffect, useState } from 'react'
-import { ScrollView, TouchableOpacity } from 'react-native'
+import { ScrollView } from 'react-native'
import NumberFormat from 'react-number-format'
import { Text, TextInput, View } from '../../../../components'
import { Button } from '../../../../components/Button'
import { getTokenIcon } from '../../../../components/icons/tokens/_index'
+import { AmountButtonTypes, SetAmountButton } from '../../../../components/SetAmountButton'
import { SectionTitle } from '../../../../components/SectionTitle'
import { useTokensAPI } from '../../../../hooks/wallet/TokensAPI'
import { tailwind } from '../../../../tailwind'
@@ -45,11 +46,11 @@ export function AddLiquidityScreen (props: Props): JSX.Element {
if (pair === undefined) return
if (ref === 'primary') {
setTokenAAmount(amountString)
- setTokenBAmount(refAmount.times(pair.aToBRate).toString())
+ setTokenBAmount(refAmount.times(pair.aToBRate).toFixed(8))
setSharePercentage(refAmount.div(pair.tokenA.reserve))
} else {
setTokenBAmount(amountString)
- setTokenAAmount(refAmount.times(pair.bToARate).toString())
+ setTokenAAmount(refAmount.times(pair.bToARate).toFixed(8))
setSharePercentage(refAmount.div(pair.tokenB.reserve))
}
}, [pair])
@@ -150,8 +151,8 @@ function TokenInput (props: { symbol: string, balance: BigNumber, current: strin
{props.symbol}
-
-
+
+
{translate('screens/AddLiquidity', 'Balance')}:
- props.onChange(props.balance.toString())}
- >
- {translate('screens/AddLiquidity', 'MAX')}
-
-
+
+
diff --git a/app/screens/AppNavigator/screens/Dex/PoolSwap/PoolSwapScreen.tsx b/app/screens/AppNavigator/screens/Dex/PoolSwap/PoolSwapScreen.tsx
index 99b9841671..9a0f3e9bed 100644
--- a/app/screens/AppNavigator/screens/Dex/PoolSwap/PoolSwapScreen.tsx
+++ b/app/screens/AppNavigator/screens/Dex/PoolSwap/PoolSwapScreen.tsx
@@ -14,6 +14,7 @@ import { Logging } from '../../../../../api'
import { Text, TextInput } from '../../../../../components'
import { Button } from '../../../../../components/Button'
import { getTokenIcon } from '../../../../../components/icons/tokens/_index'
+import { AmountButtonTypes, SetAmountButton } from '../../../../../components/SetAmountButton'
import { SectionTitle } from '../../../../../components/SectionTitle'
import { useWallet } from '../../../../../contexts/WalletContext'
import { useTokensAPI } from '../../../../../hooks/wallet/TokensAPI'
@@ -198,8 +199,8 @@ function TokenRow (form: TokenForm): JSX.Element {
name={controlName}
defaultValue=''
/>
-
-
+
+
{translate('screens/PoolSwapScreen', 'Balance: ')}
{
(enableMaxButton != null && onChangeFromAmount !== undefined) && (
- onChangeFromAmount(token.amount)}>
- {translate('screens/PoolSwapScreen', 'MAX')}
-
-
+ <>
+
+
+ >
)
}
diff --git a/cypress/integration/functional/balances/convert/convert.spec.ts b/cypress/integration/functional/balances/convert/convert.spec.ts
index cad66e1d01..f3bb9251c8 100644
--- a/cypress/integration/functional/balances/convert/convert.spec.ts
+++ b/cypress/integration/functional/balances/convert/convert.spec.ts
@@ -24,9 +24,24 @@ context('wallet/balances/convert - bi-direction success case', () => {
// cy.getByTestID('button_continue_convert').should('not.be.enabled')
})
+ it('utxosToToken: should build summary correctly with max amount button', function () {
+ cy.getByTestID('MAX_amount_button').click()
+ cy.getByTestID('text_preview_input_value').contains('0 DFI')
+ cy.getByTestID('text_preview_output_value').contains('10 DFI')
+ cy.getByTestID('button_continue_convert').should('not.be.disabled')
+ })
+
+ it('utxosToToken: should build summary correctly with half amount button', function () {
+ cy.getByTestID('50%_amount_button').click()
+ cy.getByTestID('text_preview_input_value').contains('5 DFI')
+ cy.getByTestID('text_preview_output_value').contains('5 DFI')
+ cy.getByTestID('button_continue_convert').should('not.be.disabled')
+ })
+
it('utxosToToken: should build summary correctly', function () {
// https://github.com/cypress-io/cypress/issues/1171#issuecomment-364059485
cy.getByTestID('text_input_convert_from_input')
+ .clear()
.invoke('attr', 'type', 'text') // cypress issue with numeric/decimal input, must cast
.type('1.23')
@@ -71,8 +86,23 @@ context('wallet/balances/convert - bi-direction success case', () => {
cy.getByTestID('text_preview_output_value').contains('8.769').contains('DFI')
})
+ it('tokenToUtxos: should build summary correctly with max amount button', function () {
+ cy.getByTestID('MAX_amount_button').click()
+ cy.getByTestID('text_preview_input_value').should('contain', '0 DFI')
+ cy.getByTestID('text_preview_output_value').should('contain', '9.999').contains('DFI')
+ cy.getByTestID('button_continue_convert').should('not.be.disabled')
+ })
+
+ it('tokenToUtxos: should build summary correctly with half amount button', function () {
+ cy.getByTestID('50%_amount_button').click()
+ cy.getByTestID('text_preview_input_value').should('contain', '0.615 DFI')
+ cy.getByTestID('text_preview_output_value').should('contain', '9.384').contains('DFI')
+ cy.getByTestID('button_continue_convert').should('not.be.disabled')
+ })
+
it('tokenToUtxos: should build summary correctly', function () {
cy.getByTestID('text_input_convert_from_input')
+ .clear()
.invoke('attr', 'type', 'text') // cypress issue with numeric/decimal input, must cast
.type('0.4')
diff --git a/cypress/integration/functional/balances/convert/convert_account_to_utxos.spec.ts b/cypress/integration/functional/balances/convert/convert_account_to_utxos.spec.ts
index 5a6580f327..be5c485176 100644
--- a/cypress/integration/functional/balances/convert/convert_account_to_utxos.spec.ts
+++ b/cypress/integration/functional/balances/convert/convert_account_to_utxos.spec.ts
@@ -36,8 +36,16 @@ context('wallet/balances/convert - accountToUtxos', () => {
cy.getByTestID('button_continue_convert').should('not.be.enabled')
})
+ it('should insert 50% of balance as amount on 50% pressed', function () {
+ cy.getByTestID('50%_amount_button').click()
+
+ cy.getByTestID('text_preview_input_value').contains('5 DFI')
+ cy.getByTestID('text_preview_output_value').contains('15 DFI')
+ cy.getByTestID('button_continue_convert').should('not.be.disabled')
+ })
+
it('should insert balance as amount on MAX pressed', function () {
- cy.getByTestID('button_max_convert_from').click()
+ cy.getByTestID('MAX_amount_button').click()
cy.getByTestID('text_preview_input_value').contains('0 DFI')
cy.getByTestID('text_preview_output_value').contains('20 DFI')
diff --git a/cypress/integration/functional/balances/convert/convert_utxos_to_account.spec.ts b/cypress/integration/functional/balances/convert/convert_utxos_to_account.spec.ts
index f0f878c7ab..335fa5096f 100644
--- a/cypress/integration/functional/balances/convert/convert_utxos_to_account.spec.ts
+++ b/cypress/integration/functional/balances/convert/convert_utxos_to_account.spec.ts
@@ -34,8 +34,16 @@ context('wallet/balances/convert - utxosToAccount', () => {
cy.getByTestID('button_continue_convert').should('not.be.enabled')
})
+ it('should insert balance as amount on 50% pressed', function () {
+ cy.getByTestID('50%_amount_button').click()
+
+ cy.getByTestID('text_preview_input_value').contains('5 DFI')
+ cy.getByTestID('text_preview_output_value').contains('5 DFI')
+ cy.getByTestID('button_continue_convert').should('not.be.disabled')
+ })
+
it('should insert balance as amount on MAX pressed', function () {
- cy.getByTestID('button_max_convert_from').click()
+ cy.getByTestID('MAX_amount_button').click()
cy.getByTestID('text_preview_input_value').contains('0 DFI')
cy.getByTestID('text_preview_output_value').contains('10 DFI')
diff --git a/cypress/integration/functional/balances/send.spec.ts b/cypress/integration/functional/balances/send.spec.ts
index 5499b73050..0392a28772 100644
--- a/cypress/integration/functional/balances/send.spec.ts
+++ b/cypress/integration/functional/balances/send.spec.ts
@@ -50,13 +50,28 @@ context('wallet/send', () => {
const maxValue = $txt[0].textContent.replace(' DFI', '')
expect(new BigNumber(transactionFee).plus(maxValue).toFixed(0)).eq('10')
cy.getByTestID('amount_input').clear()
- cy.getByTestID('max_button').click()
+ cy.getByTestID('MAX_amount_button').click()
cy.getByTestID('amount_input').should('have.value', maxValue)
cy.getByTestID('send_submit_button').should('not.have.attr', 'disabled')
})
})
})
+ it('should be able to compute half of max values', function () {
+ cy.getByTestID('transaction_fee').then(($txt: any) => {
+ const transactionFee = $txt[0].textContent.replace(' DFI', '')
+ cy.getByTestID('max_value').then(($txt: any) => {
+ const maxValue = $txt[0].textContent.replace(' DFI', '')
+ const halfValue = new BigNumber(maxValue).div(2)
+ expect(new BigNumber(halfValue).multipliedBy(2).plus(transactionFee).toFixed(0)).eq('10')
+ cy.getByTestID('amount_input').clear()
+ cy.getByTestID('50%_amount_button').click()
+ cy.getByTestID('amount_input').should('have.value', halfValue.toFixed(8))
+ cy.getByTestID('send_submit_button').should('not.have.attr', 'disabled')
+ })
+ })
+ })
+
addresses.forEach((address) => {
it(`should be able to send to address ${address}`, function () {
cy.getByTestID('address_input').clear().type(address)
@@ -98,7 +113,7 @@ context('wallet/send', () => {
cy.getByTestID('balances_row_1_amount').contains(10).click()
cy.getByTestID('send_button').click()
cy.getByTestID('address_input').type(address)
- cy.getByTestID('max_button').click()
+ cy.getByTestID('MAX_amount_button').click()
cy.getByTestID('send_submit_button').click()
cy.wait(5000).getByTestID('oceanInterface_close').click().wait(5000)
cy.getByTestID('playground_wallet_fetch_balances').click()
diff --git a/cypress/integration/functional/dex/add_liquidity.spec.ts b/cypress/integration/functional/dex/add_liquidity.spec.ts
index 9c1fdcd123..74589407b8 100644
--- a/cypress/integration/functional/dex/add_liquidity.spec.ts
+++ b/cypress/integration/functional/dex/add_liquidity.spec.ts
@@ -1,12 +1,44 @@
context('app/dex/addLiquidity', () => {
- beforeEach(function () {
+ before(function () {
cy.createEmptyWallet(true)
+ cy.getByTestID('bottom_tab_dex').click()
+ cy.sendDFItoWallet()
+ .sendDFITokentoWallet()
+ .sendTokenToWallet(['BTC']).wait(10000)
+ cy.getByTestID('playground_wallet_fetch_balances').click()
+
cy.getByTestID('bottom_tab_dex').click()
cy.getByTestID('pool_pair_add_DFI-BTC').click()
+ cy.wait(100)
+ cy.getByTestID('token_balance_primary').contains('10')
+ cy.getByTestID('token_balance_secondary').contains('10')
+ })
+
+ it('should update both token and build summary when click on max amount button', function () {
+ cy.getByTestID('MAX_amount_button').first().click()
+ cy.getByTestID('token_input_primary').should('have.value', '10.00000000')
+ cy.getByTestID('token_input_secondary').should('have.value', '10.00000000')
+ cy.getByTestID('a_per_b_price').contains('1')
+ cy.getByTestID('a_per_b_unit').contains('DFI per BTC')
+ cy.getByTestID('b_per_a_price').contains('1')
+ cy.getByTestID('b_per_a_unit').contains('BTC per DFI')
+ cy.getByTestID('share_of_pool').contains('1')
+ })
+
+ it('should update both token and build summary when click on half amount button', function () {
+ cy.getByTestID('token_input_primary').clear()
+ cy.getByTestID('50%_amount_button').first().click()
+ cy.getByTestID('token_input_primary').should('have.value', '5.00000000')
+ cy.getByTestID('token_input_secondary').should('have.value', '5.00000000')
+ cy.getByTestID('a_per_b_price').contains('1')
+ cy.getByTestID('a_per_b_unit').contains('DFI per BTC')
+ cy.getByTestID('b_per_a_price').contains('1')
+ cy.getByTestID('b_per_a_unit').contains('BTC per DFI')
+ cy.getByTestID('share_of_pool').contains('0.5')
})
it('should update both token and build summary base on primary token input', function () {
- cy.getByTestID('token_input_primary').invoke('val').should(text => expect(text).to.contain('0'))
+ cy.getByTestID('token_input_primary').clear().invoke('val').should(text => expect(text).to.contain(''))
cy.getByTestID('token_input_secondary').invoke('val').should(text => expect(text).to.contain('0'))
cy.getByTestID('token_input_primary').invoke('attr', 'type', 'text').type('1.23').trigger('change')
@@ -22,7 +54,7 @@ context('app/dex/addLiquidity', () => {
})
it('should update both token and build summary base on secondary token input', function () {
- cy.getByTestID('token_input_secondary').invoke('attr', 'type', 'text').type('7.8').trigger('change')
+ cy.getByTestID('token_input_secondary').clear().invoke('attr', 'type', 'text').type('7.8').trigger('change')
cy.getByTestID('token_input_primary').invoke('val').should(text => expect(text).to.contain('7.8'))
cy.getByTestID('token_input_secondary').invoke('val').should(text => expect(text).to.contain('7.8'))
diff --git a/cypress/integration/functional/dex/poolswap.spec.ts b/cypress/integration/functional/dex/poolswap.spec.ts
index 14b9f70975..dcb81ded2d 100644
--- a/cypress/integration/functional/dex/poolswap.spec.ts
+++ b/cypress/integration/functional/dex/poolswap.spec.ts
@@ -54,7 +54,7 @@ context('poolswap with values', () => {
})
it('should be able to click max', function () {
- cy.getByTestID('max_button_token_a').click().wait(3000)
+ cy.getByTestID('MAX_amount_button').click().wait(3000)
cy.getByTestID('text_input_tokenA').should('have.value', '10.00000000')
cy.getByTestID('text_price_row_minimum_0').then(($txt: any) => {
const tokenValue = $txt[0].textContent.replace(' LTC', '').replace(',', '')
@@ -62,6 +62,15 @@ context('poolswap with values', () => {
})
})
+ it('should be able to click half', function () {
+ cy.getByTestID('50%_amount_button').click().wait(3000)
+ cy.getByTestID('text_input_tokenA').should('have.value', '5.00000000')
+ cy.getByTestID('text_price_row_minimum_0').then(($txt: any) => {
+ const tokenValue = $txt[0].textContent.replace(' LTC', '').replace(',', '')
+ cy.getByTestID('text_input_tokenB').should('have.value', new BigNumber(tokenValue).div(2).toFixed(8))
+ })
+ })
+
it('should be able to swap', function () {
cy.getByTestID('text_price_row_minimum_0').then(() => {
// const tokenValue = $txt[0].textContent.replace(' LTC', '').replace(',', '')
diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts
index 57afeacbbf..cac72a7196 100644
--- a/cypress/support/commands.ts
+++ b/cypress/support/commands.ts
@@ -64,7 +64,7 @@ declare global {
}
Cypress.Commands.add('getByTestID', (selector, ...args) => {
- return cy.get(`[data-testid=${selector}]`, ...args)
+ return cy.get(`[data-testid=${Cypress.$.escapeSelector(selector)}]`, ...args)
})
Cypress.Commands.add('createEmptyWallet', (isRandom: boolean = false) => {