import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import log from 'loglevel';
import classnames from 'classnames';
import BigNumber from 'bignumber.js';
import Modal from '../../modal';
import Identicon from '../../../ui/identicon';
import TextField from '../../../ui/text-field';
import {
calcTokenAmount,
toPrecisionWithoutTrailingZeros,
} from '../../../../../shared/lib/transactions-controller-utils';
import { ButtonIcon } from '../../../component-library';
import {
ICON_SIZES,
ICON_NAMES,
} from '../../../component-library/icon/deprecated';
const MAX_UNSIGNED_256_INT = new BigNumber(2).pow(256).minus(1).toString(10);
export default class EditApprovalPermission extends PureComponent {
static propTypes = {
decimals: PropTypes.number,
hideModal: PropTypes.func.isRequired,
selectedIdentity: PropTypes.object,
tokenAmount: PropTypes.string,
customTokenAmount: PropTypes.string,
tokenSymbol: PropTypes.string,
tokenBalance: PropTypes.string,
setCustomAmount: PropTypes.func,
origin: PropTypes.string.isRequired,
requiredMinimum: PropTypes.instanceOf(BigNumber),
};
static contextTypes = {
t: PropTypes.func,
};
state = {
// This is used as a TextField value, which should be a string.
customSpendLimit: this.props.customTokenAmount || '',
selectedOptionIsUnlimited: !this.props.customTokenAmount,
};
renderModalContent(error) {
const { t } = this.context;
const {
hideModal,
selectedIdentity,
tokenAmount,
tokenSymbol,
tokenBalance,
customTokenAmount,
origin,
} = this.props;
const { name, address } = selectedIdentity || {};
const { selectedOptionIsUnlimited } = this.state;
return (
{`${toPrecisionWithoutTrailingZeros(
tokenBalance,
9,
)} ${tokenSymbol}`}
{t('spendLimitPermission')}
{t('allowWithdrawAndSpend', [origin])}
this.setState({ selectedOptionIsUnlimited: true })}
>
{selectedOptionIsUnlimited && (
)}
{new BigNumber(tokenAmount).equals(
new BigNumber(MAX_UNSIGNED_256_INT),
)
? t('unlimited')
: t('proposedApprovalLimit')}
{t('spendLimitRequestedBy', [origin])}
{`${Number(tokenAmount)} ${tokenSymbol}`}
this.setState({ selectedOptionIsUnlimited: false })
}
>
{!selectedOptionIsUnlimited && (
)}
{t('customSpendLimit')}
{t('enterMaxSpendLimit')}
{
this.setState({ customSpendLimit: event.target.value });
if (selectedOptionIsUnlimited) {
this.setState({ selectedOptionIsUnlimited: false });
}
}}
fullWidth
margin="dense"
value={this.state.customSpendLimit}
error={error}
/>
);
}
validateSpendLimit() {
const { t } = this.context;
const { decimals, requiredMinimum } = this.props;
const { selectedOptionIsUnlimited, customSpendLimit } = this.state;
if (selectedOptionIsUnlimited || !customSpendLimit) {
return undefined;
}
let customSpendLimitNumber;
try {
customSpendLimitNumber = new BigNumber(customSpendLimit);
} catch (error) {
log.debug(`Error converting '${customSpendLimit}' to BigNumber:`, error);
return t('spendLimitInvalid');
}
if (customSpendLimitNumber.isNegative()) {
return t('spendLimitInvalid');
}
const maxTokenAmount = calcTokenAmount(MAX_UNSIGNED_256_INT, decimals);
if (customSpendLimitNumber.greaterThan(maxTokenAmount)) {
return t('spendLimitTooLarge');
}
if (
requiredMinimum !== undefined &&
customSpendLimitNumber.lessThan(requiredMinimum)
) {
return t('spendLimitInsufficient');
}
return undefined;
}
render() {
const { t } = this.context;
const { setCustomAmount, hideModal, customTokenAmount } = this.props;
const { selectedOptionIsUnlimited, customSpendLimit } = this.state;
const error = this.validateSpendLimit();
const disabled = Boolean(
(customSpendLimit === customTokenAmount && !selectedOptionIsUnlimited) ||
error,
);
return (
{
setCustomAmount(selectedOptionIsUnlimited ? '' : customSpendLimit);
hideModal();
}}
submitText={t('save')}
contentClass="edit-approval-permission-modal-content"
containerClass="edit-approval-permission-modal-container"
submitDisabled={disabled}
>
{this.renderModalContent(error)}
);
}
}