From d72de35e0a6969e89062ef41f830f6df9f7c3ea6 Mon Sep 17 00:00:00 2001 From: Louis Singer <41042567+louisinger@users.noreply.github.com> Date: Fri, 23 Sep 2022 12:19:07 +0200 Subject: [PATCH] address-amount form: handle asset precision (#409) * address-amount form handle precision * fix Input value * send-select-asset list: do not display if balance=0 * prettier & lint * fix Input * sanitaze input value --- .../containers/send-select-asset.container.ts | 4 +- .../components/address-amount-form.tsx | 145 ++++++++---------- src/presentation/components/input.tsx | 60 ++++---- 3 files changed, 99 insertions(+), 110 deletions(-) diff --git a/src/application/redux/containers/send-select-asset.container.ts b/src/application/redux/containers/send-select-asset.container.ts index 569fbd6b..6ce20a17 100644 --- a/src/application/redux/containers/send-select-asset.container.ts +++ b/src/application/redux/containers/send-select-asset.container.ts @@ -10,7 +10,9 @@ const mapStateToProps = (state: RootReducerState): SendSelectAssetProps => { const balances = selectBalances(...selectAllAccountsIDsSpendableViaUI(state))(state); const getAsset = assetGetterFromIAssets(state.assets); return { - balanceAssets: Object.keys(balances).map(getAsset), + balanceAssets: Object.keys(balances) + .filter((asset) => balances[asset] > 0) + .map(getAsset), balances, }; }; diff --git a/src/presentation/components/address-amount-form.tsx b/src/presentation/components/address-amount-form.tsx index f2950072..7b43c6a3 100644 --- a/src/presentation/components/address-amount-form.tsx +++ b/src/presentation/components/address-amount-form.tsx @@ -2,7 +2,6 @@ import type { FormikProps } from 'formik'; import { withFormik } from 'formik'; import type { RouteComponentProps } from 'react-router'; import type { ProxyStoreDispatch } from '../../application/redux/proxyStore'; -import cx from 'classnames'; import Button from './button'; import { setAddressesAndAmount, @@ -18,10 +17,12 @@ import type { Account } from '../../domain/account'; import type { NetworkString } from 'ldk'; import { isValidAddressForNetwork } from '../../application/utils/address'; import { fromSatoshi, getMinAmountFromPrecision, toSatoshi } from '../utils'; +import Input from './input'; +import React from 'react'; interface AddressAmountFormValues { address: string; - amount: number; + amount: string; assetTicker: string; assetPrecision: number; balance: number; @@ -37,83 +38,56 @@ interface AddressAmountFormProps { account: Account; } +/** + * Sanitize input amount + * @param eventDetailValue string + * @returns sanitizedValue string + */ +function sanitizeInputAmount(eventDetailValue: string, precision: number): string { + // Sanitize value + let sanitizedValue = eventDetailValue + // Replace comma by dot + .replace(',', '.') + // Remove non-numeric chars or period + .replace(/[^0-9.]/g, ''); + // Prefix single dot + if (sanitizedValue === '.') sanitizedValue = '0.'; + // Remove last dot. Remove all if consecutive + if ((sanitizedValue.match(/\./g) || []).length > 1) { + sanitizedValue = sanitizedValue.replace(/\.$/, ''); + } + // No more than max decimal digits for respective unit + if (eventDetailValue.split(/[,.]/, 2)[1]?.length > precision) { + sanitizedValue = Number(eventDetailValue).toFixed(precision); + } + + return sanitizedValue; +} + +function isValidAmountString(precision: number, amount?: string) { + const splitted = amount?.replace(',', '.').split('.'); + if (splitted && splitted.length < 2) return true; + return splitted !== undefined && splitted[1].length <= precision; +} + const AddressAmountForm = (props: FormikProps) => { - const { - errors, - handleChange, - handleBlur, - handleSubmit, - isSubmitting, - touched, - values, - setFieldValue, - setFieldTouched, - } = props; + const { errors, handleSubmit, isSubmitting, touched, values, setFieldValue, setFieldTouched } = + props; const setMaxAmount = () => { const maxAmount = values.balance; - setFieldValue('amount', maxAmount); + setFieldValue('amount', maxAmount, true); setFieldTouched('amount', true, false); }; return ( -
-
- - {errors.address && touched.address && ( -

{errors.address}

- )} -
+ +

Address

+ -
- -

+

+

Amount

+
-

- {errors.amount && touched.amount && ( -

{errors.amount}

- )} +
+ ) => { + const amount = e.target.value as string; + setFieldValue('amount', sanitizeInputAmount(amount, values.assetPrecision), true); + }} + value={values.amount} + name="amount" + placeholder="0" + type="text" + inputSuffix={values.assetTicker} + validateOnChange={true} + />