* change to setting envars rather than passing in via CLI * update nx to latest patch version * add env files for token-e2e, fix lint and ts errors * move generate functions to mocs for trading e2e to avoid violating boundary rules * add jsx compiler option for trading-e2e * downgrade nextjs * add testing-library to types declaration where required
193 lines
4.7 KiB
TypeScript
193 lines
4.7 KiB
TypeScript
import './token-input.scss';
|
|
|
|
import {
|
|
Button,
|
|
Callout,
|
|
Input,
|
|
Intent,
|
|
FormGroup,
|
|
} from '@vegaprotocol/ui-toolkit';
|
|
import React from 'react';
|
|
import { useTranslation } from 'react-i18next';
|
|
|
|
import type {
|
|
TransactionAction,
|
|
TransactionState,
|
|
} from '../../hooks/transaction-reducer';
|
|
import {
|
|
TransactionActionType,
|
|
TxState,
|
|
} from '../../hooks/transaction-reducer';
|
|
import { BigNumber } from '../../lib/bignumber';
|
|
import { TransactionCallout } from '../transaction-callout';
|
|
|
|
const inputName = 'amount';
|
|
|
|
export const AmountInput = ({
|
|
amount,
|
|
setAmount,
|
|
maximum,
|
|
// TODO: render currency in input when https://github.com/vegaprotocol/frontend-monorepo/issues/273
|
|
currency,
|
|
}: {
|
|
amount: string;
|
|
setAmount: React.Dispatch<React.SetStateAction<string>>;
|
|
maximum: BigNumber;
|
|
currency: string;
|
|
}) => {
|
|
const { t } = useTranslation();
|
|
return (
|
|
<div className="token-input__container">
|
|
<Input
|
|
data-testid="token-amount-input"
|
|
className="token-input__input"
|
|
name={inputName}
|
|
id={inputName}
|
|
onChange={(e) => setAmount(e.target.value)}
|
|
value={amount}
|
|
autoComplete="off"
|
|
type="number"
|
|
max={maximum.toString()}
|
|
min={0}
|
|
step="any"
|
|
/>
|
|
{maximum && (
|
|
<Button
|
|
variant="inline-link"
|
|
onClick={() => setAmount(maximum.toString())}
|
|
data-testid="token-amount-use-maximum"
|
|
className="text-ui token-input__use-maximum"
|
|
>
|
|
{t('Use maximum')}
|
|
</Button>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export const TokenInput = ({
|
|
amount,
|
|
setAmount,
|
|
perform,
|
|
submitText,
|
|
currency,
|
|
|
|
approveText,
|
|
allowance,
|
|
approve,
|
|
requireApproval = false,
|
|
maximum = new BigNumber('0'),
|
|
minimum = new BigNumber('0'),
|
|
approveTxState,
|
|
approveTxDispatch,
|
|
}: {
|
|
amount: string;
|
|
setAmount: React.Dispatch<React.SetStateAction<string>>;
|
|
perform: () => void;
|
|
submitText: string;
|
|
currency: string;
|
|
|
|
requireApproval?: boolean;
|
|
maximum?: BigNumber;
|
|
minimum?: BigNumber;
|
|
allowance?: BigNumber;
|
|
approve?: () => void;
|
|
approveText?: string;
|
|
approveTxState?: TransactionState;
|
|
approveTxDispatch?: React.Dispatch<TransactionAction>;
|
|
}) => {
|
|
if (
|
|
requireApproval &&
|
|
(allowance == null ||
|
|
approve == null ||
|
|
!approveTxState ||
|
|
!approveTxDispatch)
|
|
) {
|
|
throw new Error(
|
|
'If requires approval is true allowance, approve, approveTxState and approveDispatch props are required!'
|
|
);
|
|
}
|
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
const isApproved = !new BigNumber(allowance!).isEqualTo(0);
|
|
const showApproveButton =
|
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
!isApproved || new BigNumber(amount).isGreaterThan(allowance!);
|
|
|
|
const isDisabled = React.useMemo<boolean>(() => {
|
|
if (requireApproval) {
|
|
return (
|
|
!isApproved ||
|
|
!amount ||
|
|
new BigNumber(amount).isLessThanOrEqualTo('0') ||
|
|
new BigNumber(amount).isGreaterThan(maximum)
|
|
);
|
|
}
|
|
|
|
return (
|
|
!amount ||
|
|
new BigNumber(amount).isLessThanOrEqualTo('0') ||
|
|
new BigNumber(amount).isGreaterThan(maximum) ||
|
|
new BigNumber(amount).isLessThan(minimum)
|
|
);
|
|
}, [amount, isApproved, maximum, requireApproval, minimum]);
|
|
let approveContent = null;
|
|
|
|
if (showApproveButton) {
|
|
if (
|
|
approveTxDispatch &&
|
|
approveTxState &&
|
|
approveTxState.txState !== TxState.Default
|
|
) {
|
|
approveContent = (
|
|
<TransactionCallout
|
|
state={approveTxState}
|
|
pendingHeading={`Approve ${currency} for staking on Vega`}
|
|
reset={() =>
|
|
approveTxDispatch({ type: TransactionActionType.TX_RESET })
|
|
}
|
|
/>
|
|
);
|
|
} else {
|
|
approveContent = (
|
|
<Button
|
|
data-testid="token-input-approve-button"
|
|
className="token-input__submit w-full"
|
|
onClick={approve}
|
|
>
|
|
{approveText}
|
|
</Button>
|
|
);
|
|
}
|
|
} else if (requireApproval) {
|
|
approveContent = (
|
|
<Callout
|
|
iconName="tick"
|
|
intent={Intent.Success}
|
|
title={`${currency} are approved for staking`}
|
|
/>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<>
|
|
<FormGroup label="" labelFor={inputName}>
|
|
<AmountInput
|
|
amount={amount}
|
|
setAmount={setAmount}
|
|
maximum={maximum}
|
|
currency={currency}
|
|
/>
|
|
</FormGroup>
|
|
{approveContent ? <div className="mb-24">{approveContent}</div> : null}
|
|
<Button
|
|
data-testid="token-input-submit-button"
|
|
className="w-full"
|
|
disabled={isDisabled}
|
|
onClick={perform}
|
|
>
|
|
{submitText}
|
|
</Button>
|
|
</>
|
|
);
|
|
};
|