diff --git a/src/elements/forms/AmountField.jsx b/src/elements/forms/AmountField.jsx new file mode 100644 index 0000000..01a7899 --- /dev/null +++ b/src/elements/forms/AmountField.jsx @@ -0,0 +1,39 @@ +import React from 'react' +import { Field, ErrorMessage, } from 'formik' +import { AssetEditor } from 'golos-lib-js/lib/utils' + +class AmountField extends React.Component { + static defaultProps = { + name: 'amount', + } + + _renderInput = ({ field, form }) => { + // TODO: is it right to pass all props to input + const { placeholder, name, ...rest } = this.props + const { value, } = field + const { values, setFieldTouched, setFieldValue } = form + return this.onChange(e, values, setFieldTouched, setFieldValue)} + /> + } + + onChange = (e, values, setFieldTouched, setFieldValue) => { + const { name } = this.props + const newAmount = values[name].withChange(e.target.value) + if (newAmount.hasChange && newAmount.asset.amount >= 0) { + setFieldValue(name, newAmount) + setFieldTouched(name, true, false) + } + } + + render() { + const { placeholder, name, ...rest } = this.props + return ( + {this._renderInput} + ) + } +} + +export default AmountField diff --git a/src/locales/en.json b/src/locales/en.json index b51b471..75736b5 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -100,7 +100,9 @@ "deposit_unavailable": " - deposit temporarily unavailable.", "cmc_error": " - cannot get min amount from CoinMarketCap.", "transfer_not_supported": " - not yet supported.", - "req_amount": "Amount should be strictly equal to ", + "min_amount": "Minimal amount is ", + "enter_amount": "Exact amount, which will be transferred by gate: ", + "slot_is_used": "Try another amount.", "fee": "Fee", "memo_fixed": "Memo", "to": "Send tokens to address/account", @@ -384,7 +386,7 @@ "close": "Close", "collapse": "Collapse", "comments": "Comments", - "continue": "continue", + "continue": "Continue", "convert": "Convert", "date": "Date", "delete": "Delete", diff --git a/src/locales/ru-RU.json b/src/locales/ru-RU.json index ef51470..e146df5 100644 --- a/src/locales/ru-RU.json +++ b/src/locales/ru-RU.json @@ -100,7 +100,9 @@ "deposit_unavailable": " - депозит временно недоступен.", "cmc_error": " - не удается получить минимальную сумму с CoinMarketCap.", "transfer_not_supported": " - пока не поддерживается.", - "req_amount": "Сумма токенов должна равняться ", + "min_amount": "Минимальная сумма - ", + "enter_amount": "Точная сумма, которую отправит шлюз: ", + "slot_is_used": "Введите другую сумму.", "fee": "Комиссия", "memo_fixed": "Заметка/memo", "to": "Отправьте токены на адрес/аккаунт", @@ -385,7 +387,7 @@ "close": "Закрыть", "collapse": "Свернуть", "comments": "Комментарии", - "continue": "продолжить", + "continue": "Продолжить", "convert": "Конвертировать", "created": "Сначала новые", "old": "Сначала старые", diff --git a/src/modules/register/TransferWaiter.jsx b/src/modules/register/TransferWaiter.jsx index 31f64a2..6440087 100644 --- a/src/modules/register/TransferWaiter.jsx +++ b/src/modules/register/TransferWaiter.jsx @@ -14,16 +14,16 @@ class TransferWaiter extends React.Component { super(props) } - poll = async (minAmount) => { + poll = async (amount) => { const retry = async () => { await delay(1000) if (!this.stopped) - this.poll(minAmount) + this.poll(amount) else this.stoppedPolling = true } try { - let res = await callApi('/api/reg/wait_for_transfer/' + minAmount.toString()) + let res = await callApi('/api/reg/wait_for_transfer/' + amount.toString()) res = await res.json() if (res.status === 'ok') { const { onTransfer } = this.props @@ -57,9 +57,9 @@ class TransferWaiter extends React.Component { }) }, 1000) - const { minAmount, } = this.props + const { amount, } = this.props - this.poll(minAmount) + this.poll(amount) } componentDidMount() { @@ -80,10 +80,10 @@ class TransferWaiter extends React.Component { } async componentDidUpdate(prevProps) { - const { minAmount } = this.props - if (minAmount && (!prevProps.minAmount || - minAmount.symbol !== prevProps.minAmount.symbol || - minAmount.amount !== prevProps.minAmount.amount)) { + const { amount } = this.props + if (amount && (!prevProps.amount || + amount.symbol !== prevProps.amount.symbol || + amount.amount !== prevProps.amount.amount)) { await this.stop() this.start() } diff --git a/src/modules/register/UIARegister.jsx b/src/modules/register/UIARegister.jsx index 4e30e06..f0b0151 100644 --- a/src/modules/register/UIARegister.jsx +++ b/src/modules/register/UIARegister.jsx @@ -3,11 +3,13 @@ import CopyToClipboard from 'react-copy-to-clipboard' import tt from 'counterpart' import cn from 'classnames' import golos, { api, } from 'golos-lib-js' -import { Asset } from 'golos-lib-js/lib/utils'; +import { Asset, AssetEditor } from 'golos-lib-js/lib/utils'; import { key_utils, PrivateKey } from 'golos-lib-js/lib/auth/ecc' import Link from 'next/link' +import { Formik, ErrorMessage, } from 'formik' import LoadingIndicator from '@/elements/LoadingIndicator' +import AmountField from '@/elements/forms/AmountField' import AccountName from '@/elements/register/AccountName' import VerifyWayTabs from '@/elements/register/VerifyWayTabs' import TransferWaiter from '@/modules/register/TransferWaiter' @@ -153,6 +155,9 @@ class UIARegister extends React.Component { this.setState({ rules: { ...deposit, creator: asset.creator, telegram }, minAmount, + initialForm: { + amount: AssetEditor(minAmount), + }, registrar, sym, copied_addr: false, @@ -282,7 +287,7 @@ class UIARegister extends React.Component { } _renderParams = () => { - const { rules, sym, registrar, minAmount } = this.state + const { rules, sym, registrar, minAmount, waiting } = this.state const username = registrar.name const { memo_fixed } = rules let details = rules.details @@ -290,17 +295,17 @@ class UIARegister extends React.Component { details = details.split('').join(username) } return
-
- {details &&
+ {waiting &&
} + {waiting && details &&
{details}

} - {minAmount &&
- {tt('uia_register_jsx.req_amount')} {minAmount.floatString}
} + {!waiting && minAmount &&
+ {tt('uia_register_jsx.min_amount')} {minAmount.floatString}.
}
; } _renderApi = () => { - const { sym, apiLoaded } = this.state + const { sym, apiLoaded, waiting } = this.state if (!apiLoaded) { return (

@@ -334,14 +339,14 @@ class UIARegister extends React.Component { } const { address } = apiLoaded return (
- {this._renderTo(address, null)} + {waiting && this._renderTo(address, null)} {this._renderParams(false)} - {this._renderWaiter()} + {waiting ? this._renderWaiter() : this._renderForm()}
) } _renderWaiter = () => { - const { minAmount, registrar, onTransfer } = this.state + const { waitAmount, registrar, onTransfer } = this.state if (!onTransfer) { onTransfer = async (deposited) => { this.setState({ @@ -372,9 +377,85 @@ class UIARegister extends React.Component { }) } } - return + return
+
+ {tt('uia_register_jsx.enter_amount')}{waitAmount.floatString}. +
+ +
+ } + + amountValidate = (values) => { + const errors = {} + const { minAmount } = this.state + if (values.amount.asset.lt(minAmount)) { + errors.amount = tt('uia_register_jsx.min_amount') + minAmount.floatString + } + this.setState({ + amountSubmitError: '' + }) + return errors + } + + _onAmountSubmit = async (values) => { + const waitAmount = values.amount.asset + try { + let fp = await callApi('/api/reg/get_free_poller/' + waitAmount.toString()) + fp = await fp.json() + if (fp.status !== 'ok') { + throw new Error(fp.error || 'Unknown error') + } + if (fp.amount !== waitAmount.toString()) { + throw new Error('Slot is used') + } + } catch (err) { + this.setState({ + amountSubmitError: err.message === 'Slot is used' ? tt('uia_register_jsx.slot_is_used') : err.message + }) + return + } + this.setState({ + waiting: true, + waitAmount + }) + } + + _renderForm = () => { + const { initialForm, amountSubmitError } = this.state + return + {({ + handleSubmit, isSubmitting, isValid, dirty, errors, touched, values, handleChange, setFieldValue, + }) => ( +
+
+ {tt('uia_register_jsx.enter_amount')} +
+
+ +
+ + {amountSubmitError &&
{amountSubmitError}
} + + {isSubmitting && } + + + )} +
} render() { @@ -385,7 +466,7 @@ class UIARegister extends React.Component { if (loading) { content = } else { - const { assets, sym } = this.state + const { assets, sym, waiting } = this.state const path = this.getPath()[0] @@ -431,8 +512,8 @@ class UIARegister extends React.Component { memo_fixed = memo_fixed.split('').join(username) } form =
- {this._renderTo(to, to_fixed)} - {memo_fixed ?
+ {waiting && this._renderTo(to, to_fixed)} + {(waiting && memo_fixed) ?
{tt('uia_register_jsx.memo_fixed')}:
{memo_fixed} @@ -445,7 +526,7 @@ class UIARegister extends React.Component {
: null} {this._renderParams()} - {this._renderWaiter()} + {waiting ? this._renderWaiter() : this._renderForm()}
} } diff --git a/src/modules/register/UIARegister.scss b/src/modules/register/UIARegister.scss index cd625ba..c9fdbe7 100644 --- a/src/modules/register/UIARegister.scss +++ b/src/modules/register/UIARegister.scss @@ -24,4 +24,8 @@ background-color: rgba(208,208,208,0.45); border: 1px solid rgba(128,128,128,0.45); } + + .error { + margin-bottom: 0.75rem; + } }