feat(accounts): get trasfer fee from estimateTransferFee API
This commit is contained in:
parent
575897d94f
commit
8cfcb8ef79
@ -25,7 +25,6 @@ export const TransferContainer = ({ assetId }: { assetId?: string }) => {
|
|||||||
const t = useT();
|
const t = useT();
|
||||||
const { pubKey, pubKeys, isReadOnly } = useVegaWallet();
|
const { pubKey, pubKeys, isReadOnly } = useVegaWallet();
|
||||||
const { params } = useNetworkParams([
|
const { params } = useNetworkParams([
|
||||||
NetworkParams.transfer_fee_factor,
|
|
||||||
NetworkParams.transfer_minTransferQuantumMultiple,
|
NetworkParams.transfer_minTransferQuantumMultiple,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
@ -15,6 +15,30 @@ import {
|
|||||||
} from './transfer-form';
|
} from './transfer-form';
|
||||||
import { AccountType, AccountTypeMapping } from '@vegaprotocol/types';
|
import { AccountType, AccountTypeMapping } from '@vegaprotocol/types';
|
||||||
import { removeDecimal } from '@vegaprotocol/utils';
|
import { removeDecimal } from '@vegaprotocol/utils';
|
||||||
|
import type { TransferFeeQuery } from './__generated__/TransferFee';
|
||||||
|
|
||||||
|
const feeFactor = 0.001;
|
||||||
|
const mockUseTransferFeeQuery = jest.fn(
|
||||||
|
({
|
||||||
|
variables: { amount },
|
||||||
|
}: {
|
||||||
|
variables: { amount: string };
|
||||||
|
}): { data: TransferFeeQuery } => {
|
||||||
|
return {
|
||||||
|
data: {
|
||||||
|
estimateTransferFee: {
|
||||||
|
discount: '0',
|
||||||
|
fee: (Number(amount) * feeFactor).toFixed(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
jest.mock('./__generated__/TransferFee', () => ({
|
||||||
|
useTransferFeeQuery: (props: { variables: { amount: string } }) =>
|
||||||
|
mockUseTransferFeeQuery(props),
|
||||||
|
}));
|
||||||
|
|
||||||
describe('TransferForm', () => {
|
describe('TransferForm', () => {
|
||||||
const renderComponent = (props: TransferFormProps) => {
|
const renderComponent = (props: TransferFormProps) => {
|
||||||
@ -56,7 +80,6 @@ describe('TransferForm', () => {
|
|||||||
const props = {
|
const props = {
|
||||||
pubKey,
|
pubKey,
|
||||||
pubKeys: [pubKey, '2'.repeat(64)],
|
pubKeys: [pubKey, '2'.repeat(64)],
|
||||||
feeFactor: '0.001',
|
|
||||||
submitTransfer: jest.fn(),
|
submitTransfer: jest.fn(),
|
||||||
accounts: [
|
accounts: [
|
||||||
{
|
{
|
||||||
@ -79,7 +102,6 @@ describe('TransferForm', () => {
|
|||||||
pubKey,
|
pubKey,
|
||||||
'a4b6e3de5d7ef4e31ae1b090be49d1a2ef7bcefff60cccf7658a0d4922651cce',
|
'a4b6e3de5d7ef4e31ae1b090be49d1a2ef7bcefff60cccf7658a0d4922651cce',
|
||||||
],
|
],
|
||||||
feeFactor: '0.001',
|
|
||||||
submitTransfer: jest.fn(),
|
submitTransfer: jest.fn(),
|
||||||
accounts: [],
|
accounts: [],
|
||||||
minQuantumMultiple: '1',
|
minQuantumMultiple: '1',
|
||||||
@ -96,10 +118,6 @@ describe('TransferForm', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
{
|
|
||||||
targetText: 'Transfer fee',
|
|
||||||
tooltipText: /transfer\.fee\.factor/,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
targetText: 'Amount to be transferred',
|
targetText: 'Amount to be transferred',
|
||||||
tooltipText: /without the fee/,
|
tooltipText: /without the fee/,
|
||||||
@ -109,9 +127,6 @@ describe('TransferForm', () => {
|
|||||||
tooltipText: /total amount taken from your account/,
|
tooltipText: /total amount taken from your account/,
|
||||||
},
|
},
|
||||||
])('Tooltip for "$targetText" shows', async (o) => {
|
])('Tooltip for "$targetText" shows', async (o) => {
|
||||||
// 1003-TRAN-015
|
|
||||||
// 1003-TRAN-016
|
|
||||||
// 1003-TRAN-017
|
|
||||||
// 1003-TRAN-018
|
// 1003-TRAN-018
|
||||||
// 1003-TRAN-019
|
// 1003-TRAN-019
|
||||||
renderComponent(props);
|
renderComponent(props);
|
||||||
@ -124,6 +139,10 @@ describe('TransferForm', () => {
|
|||||||
// Select asset
|
// Select asset
|
||||||
await selectAsset(asset);
|
await selectAsset(asset);
|
||||||
|
|
||||||
|
await userEvent.selectOptions(
|
||||||
|
screen.getByLabelText('From account'),
|
||||||
|
`${AccountType.ACCOUNT_TYPE_GENERAL}-${asset.id}`
|
||||||
|
);
|
||||||
// set valid amount
|
// set valid amount
|
||||||
const amountInput = screen.getByLabelText('Amount');
|
const amountInput = screen.getByLabelText('Amount');
|
||||||
await userEvent.type(amountInput, amount);
|
await userEvent.type(amountInput, amount);
|
||||||
@ -214,9 +233,7 @@ describe('TransferForm', () => {
|
|||||||
// set valid amount
|
// set valid amount
|
||||||
await userEvent.clear(amountInput);
|
await userEvent.clear(amountInput);
|
||||||
await userEvent.type(amountInput, amount);
|
await userEvent.type(amountInput, amount);
|
||||||
expect(screen.getByTestId('transfer-fee')).toHaveTextContent(
|
expect(screen.getByTestId('transfer-fee')).toHaveTextContent('1');
|
||||||
new BigNumber(props.feeFactor).times(amount).toFixed()
|
|
||||||
);
|
|
||||||
|
|
||||||
await submit();
|
await submit();
|
||||||
|
|
||||||
@ -385,47 +402,44 @@ describe('TransferForm', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('IncludeFeesCheckbox', () => {
|
|
||||||
it('validates fields when checkbox is not checked', async () => {
|
|
||||||
renderComponent(props);
|
|
||||||
|
|
||||||
// check current pubkey not shown
|
it('validates fields', async () => {
|
||||||
const keySelect: HTMLSelectElement = screen.getByLabelText('To Vega key');
|
renderComponent(props);
|
||||||
const pubKeyOptions = ['', pubKey, props.pubKeys[1]];
|
|
||||||
expect(keySelect.children).toHaveLength(pubKeyOptions.length);
|
|
||||||
expect(Array.from(keySelect.options).map((o) => o.value)).toEqual(
|
|
||||||
pubKeyOptions
|
|
||||||
);
|
|
||||||
|
|
||||||
await submit();
|
// check current pubkey not shown
|
||||||
expect(await screen.findAllByText('Required')).toHaveLength(2); // pubkey set as default value
|
const keySelect: HTMLSelectElement = screen.getByLabelText('To Vega key');
|
||||||
|
const pubKeyOptions = ['', pubKey, props.pubKeys[1]];
|
||||||
|
expect(keySelect.children).toHaveLength(pubKeyOptions.length);
|
||||||
|
expect(Array.from(keySelect.options).map((o) => o.value)).toEqual(
|
||||||
|
pubKeyOptions
|
||||||
|
);
|
||||||
|
|
||||||
// Select a pubkey
|
await submit();
|
||||||
await userEvent.selectOptions(
|
expect(await screen.findAllByText('Required')).toHaveLength(2); // pubkey set as default value
|
||||||
screen.getByLabelText('To Vega key'),
|
|
||||||
props.pubKeys[1]
|
|
||||||
);
|
|
||||||
|
|
||||||
// Select asset
|
// Select a pubkey
|
||||||
await selectAsset(asset);
|
await userEvent.selectOptions(
|
||||||
|
screen.getByLabelText('To Vega key'),
|
||||||
|
props.pubKeys[1]
|
||||||
|
);
|
||||||
|
|
||||||
await userEvent.selectOptions(
|
// Select asset
|
||||||
screen.getByLabelText('From account'),
|
await selectAsset(asset);
|
||||||
`${AccountType.ACCOUNT_TYPE_GENERAL}-${asset.id}`
|
|
||||||
);
|
|
||||||
|
|
||||||
const amountInput = screen.getByLabelText('Amount');
|
await userEvent.selectOptions(
|
||||||
|
screen.getByLabelText('From account'),
|
||||||
|
`${AccountType.ACCOUNT_TYPE_GENERAL}-${asset.id}`
|
||||||
|
);
|
||||||
|
|
||||||
await userEvent.type(amountInput, amount);
|
const amountInput = screen.getByLabelText('Amount');
|
||||||
const expectedFee = new BigNumber(amount)
|
|
||||||
.times(props.feeFactor)
|
await userEvent.type(amountInput, amount);
|
||||||
.toFixed();
|
const expectedFee = new BigNumber(amount).times(feeFactor).toFixed();
|
||||||
const total = new BigNumber(amount).plus(expectedFee).toFixed();
|
const total = new BigNumber(amount).plus(expectedFee).toFixed();
|
||||||
// 1003-TRAN-021
|
// 1003-TRAN-021
|
||||||
expect(screen.getByTestId('transfer-fee')).toHaveTextContent(expectedFee);
|
expect(screen.getByTestId('transfer-fee')).toHaveTextContent(expectedFee);
|
||||||
expect(screen.getByTestId('transfer-amount')).toHaveTextContent(amount);
|
expect(screen.getByTestId('transfer-amount')).toHaveTextContent(amount);
|
||||||
expect(screen.getByTestId('total-transfer-fee')).toHaveTextContent(total);
|
expect(screen.getByTestId('total-transfer-fee')).toHaveTextContent(total);
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('AddressField', () => {
|
describe('AddressField', () => {
|
||||||
@ -457,24 +471,29 @@ describe('TransferForm', () => {
|
|||||||
|
|
||||||
describe('TransferFee', () => {
|
describe('TransferFee', () => {
|
||||||
const props = {
|
const props = {
|
||||||
amount: '200',
|
amount: '20000',
|
||||||
feeFactor: '0.001',
|
discount: '0',
|
||||||
fee: '0.2',
|
fee: '20',
|
||||||
transferAmount: '200',
|
decimals: 2,
|
||||||
decimals: 8,
|
|
||||||
};
|
};
|
||||||
it('calculates and renders the transfer fee', () => {
|
it('calculates and renders amounts and fee', () => {
|
||||||
render(<TransferFee {...props} />);
|
render(<TransferFee {...props} />);
|
||||||
|
expect(screen.queryByTestId('discount')).not.toBeInTheDocument();
|
||||||
const expected = new BigNumber(props.amount)
|
expect(screen.getByTestId('transfer-fee')).toHaveTextContent('0.2');
|
||||||
.times(props.feeFactor)
|
expect(screen.getByTestId('transfer-amount')).toHaveTextContent('200.00');
|
||||||
.toFixed();
|
expect(screen.getByTestId('total-transfer-fee')).toHaveTextContent(
|
||||||
const total = new BigNumber(props.amount).plus(expected).toFixed();
|
'200.20'
|
||||||
expect(screen.getByTestId('transfer-fee')).toHaveTextContent(expected);
|
);
|
||||||
expect(screen.getByTestId('transfer-amount')).toHaveTextContent(
|
});
|
||||||
props.amount
|
|
||||||
|
it('calculates and renders amounts, fee and discount', () => {
|
||||||
|
render(<TransferFee {...props} discount="10" />);
|
||||||
|
expect(screen.getByTestId('discount')).toHaveTextContent('0.1');
|
||||||
|
expect(screen.getByTestId('transfer-fee')).toHaveTextContent('0.2');
|
||||||
|
expect(screen.getByTestId('transfer-amount')).toHaveTextContent('200.00');
|
||||||
|
expect(screen.getByTestId('total-transfer-fee')).toHaveTextContent(
|
||||||
|
'200.10'
|
||||||
);
|
);
|
||||||
expect(screen.getByTestId('total-transfer-fee')).toHaveTextContent(total);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -4,9 +4,9 @@ import {
|
|||||||
useRequired,
|
useRequired,
|
||||||
useVegaPublicKey,
|
useVegaPublicKey,
|
||||||
addDecimal,
|
addDecimal,
|
||||||
formatNumber,
|
|
||||||
toBigNum,
|
toBigNum,
|
||||||
removeDecimal,
|
removeDecimal,
|
||||||
|
addDecimalsFormatNumber,
|
||||||
} from '@vegaprotocol/utils';
|
} from '@vegaprotocol/utils';
|
||||||
import { useT } from './use-t';
|
import { useT } from './use-t';
|
||||||
import {
|
import {
|
||||||
@ -136,12 +136,14 @@ export const TransferForm = ({
|
|||||||
|
|
||||||
// Max amount given selected asset and from account
|
// Max amount given selected asset and from account
|
||||||
const max = accountBalance ? new BigNumber(accountBalance) : new BigNumber(0);
|
const max = accountBalance ? new BigNumber(accountBalance) : new BigNumber(0);
|
||||||
|
const normalizedAmount =
|
||||||
|
(amount && asset && removeDecimal(amount, asset.decimals)) || '0';
|
||||||
|
|
||||||
const transferFeeQuery = useTransferFeeQuery({
|
const transferFeeQuery = useTransferFeeQuery({
|
||||||
variables: {
|
variables: {
|
||||||
fromAccount: pubKey || '',
|
fromAccount: pubKey || '',
|
||||||
fromAccountType: accountType || AccountType.ACCOUNT_TYPE_GENERAL,
|
fromAccountType: accountType || AccountType.ACCOUNT_TYPE_GENERAL,
|
||||||
amount: (amount && asset && removeDecimal(amount, asset.decimals)) || '0',
|
amount: normalizedAmount,
|
||||||
assetId: asset?.id || '',
|
assetId: asset?.id || '',
|
||||||
toAccount: selectedPubKey,
|
toAccount: selectedPubKey,
|
||||||
},
|
},
|
||||||
@ -441,14 +443,15 @@ export const TransferForm = ({
|
|||||||
</TradingInputError>
|
</TradingInputError>
|
||||||
)}
|
)}
|
||||||
</TradingFormGroup>
|
</TradingFormGroup>
|
||||||
{(transferFee?.estimateTransferFee || fromVested) && amount && (
|
{JSON.stringify(transferFee)}
|
||||||
|
{(transferFee?.estimateTransferFee || fromVested) && amount && asset && (
|
||||||
<TransferFee
|
<TransferFee
|
||||||
amount={amount}
|
amount={normalizedAmount}
|
||||||
fee={fromVested ? '0' : transferFee?.estimateTransferFee?.fee}
|
fee={fromVested ? '0' : transferFee?.estimateTransferFee?.fee}
|
||||||
discount={
|
discount={
|
||||||
fromVested ? '0' : transferFee?.estimateTransferFee?.discount
|
fromVested ? '0' : transferFee?.estimateTransferFee?.discount
|
||||||
}
|
}
|
||||||
decimals={asset?.decimals}
|
decimals={asset.decimals}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<TradingButton type="submit" fill={true} disabled={isReadOnly}>
|
<TradingButton type="submit" fill={true} disabled={isReadOnly}>
|
||||||
@ -467,7 +470,7 @@ export const TransferFee = ({
|
|||||||
amount: string;
|
amount: string;
|
||||||
fee?: string;
|
fee?: string;
|
||||||
discount?: string;
|
discount?: string;
|
||||||
decimals?: number;
|
decimals: number;
|
||||||
}) => {
|
}) => {
|
||||||
const t = useT();
|
const t = useT();
|
||||||
if (!amount || !fee) return null;
|
if (!amount || !fee) return null;
|
||||||
@ -475,30 +478,25 @@ export const TransferFee = ({
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const totalValue = new BigNumber(amount).plus(fee).toString();
|
const totalValue = (
|
||||||
const feeFactor = new BigNumber(fee).dividedBy(amount).toFixed(2);
|
BigInt(amount) +
|
||||||
|
BigInt(fee) -
|
||||||
|
BigInt(discount || '0')
|
||||||
|
).toString();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mb-4 flex flex-col gap-2 text-xs">
|
<div className="mb-4 flex flex-col gap-2 text-xs">
|
||||||
<div className="flex flex-wrap items-center justify-between gap-1">
|
<div className="flex flex-wrap items-center justify-between gap-1">
|
||||||
<Tooltip
|
<div>{t('Transfer fee')}</div>
|
||||||
description={t(
|
|
||||||
`The transfer fee is set by the network parameter transfer.fee.factor, currently set to {{feeFactor}}`,
|
|
||||||
{ feeFactor }
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<div>{t('Transfer fee')}</div>
|
|
||||||
</Tooltip>
|
|
||||||
|
|
||||||
<div data-testid="transfer-fee" className="text-muted">
|
<div data-testid="transfer-fee" className="text-muted">
|
||||||
{formatNumber(fee, decimals)}
|
{addDecimalsFormatNumber(fee, decimals)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{discount && discount !== '0' && (
|
{discount && discount !== '0' && (
|
||||||
<div className="flex flex-wrap items-center justify-between gap-1">
|
<div className="flex flex-wrap items-center justify-between gap-1">
|
||||||
<div>{t('Discount')}</div>
|
<div>{t('Discount')}</div>
|
||||||
<div data-testid="discount" className="text-muted">
|
<div data-testid="discount" className="text-muted">
|
||||||
{formatNumber(discount, decimals)}
|
{addDecimalsFormatNumber(discount, decimals)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@ -513,7 +511,7 @@ export const TransferFee = ({
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
<div data-testid="transfer-amount" className="text-muted">
|
<div data-testid="transfer-amount" className="text-muted">
|
||||||
{formatNumber(amount, decimals)}
|
{addDecimalsFormatNumber(amount, decimals)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-wrap items-center justify-between gap-1">
|
<div className="flex flex-wrap items-center justify-between gap-1">
|
||||||
@ -526,7 +524,7 @@ export const TransferFee = ({
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
<div data-testid="total-transfer-fee" className="text-muted">
|
<div data-testid="total-transfer-fee" className="text-muted">
|
||||||
{formatNumber(totalValue, decimals)}
|
{addDecimalsFormatNumber(totalValue, decimals)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -35,7 +35,6 @@
|
|||||||
"The total amount of each asset on this key. Includes used and available collateral.": "The total amount of each asset on this key. Includes used and available collateral.",
|
"The total amount of each asset on this key. Includes used and available collateral.": "The total amount of each asset on this key. Includes used and available collateral.",
|
||||||
"The total amount taken from your account. The amount to be transferred plus the fee.": "The total amount taken from your account. The amount to be transferred plus the fee.",
|
"The total amount taken from your account. The amount to be transferred plus the fee.": "The total amount taken from your account. The amount to be transferred plus the fee.",
|
||||||
"The total amount to be transferred (without the fee)": "The total amount to be transferred (without the fee)",
|
"The total amount to be transferred (without the fee)": "The total amount to be transferred (without the fee)",
|
||||||
"The transfer fee is set by the network parameter transfer.fee.factor, currently set to {{feeFactor}}": "The transfer fee is set by the network parameter transfer.fee.factor, currently set to {{feeFactor}}",
|
|
||||||
"To account": "To account",
|
"To account": "To account",
|
||||||
"To Vega key": "To Vega key",
|
"To Vega key": "To Vega key",
|
||||||
"Total": "Total",
|
"Total": "Total",
|
||||||
|
@ -40,8 +40,6 @@
|
|||||||
|
|
||||||
## Transfer
|
## Transfer
|
||||||
|
|
||||||
- **Must** display tooltip for "Transfer fee when hovered over.(<a name="1003-TRAN-017" href="#1003-TRAN-017">1003-TRAN-017</a>)
|
|
||||||
|
|
||||||
- **Must** display tooltip for "Amount to be transferred" when hovered over.(<a name="1003-TRAN-018" href="#1003-TRAN-018">1003-TRAN-018</a>)
|
- **Must** display tooltip for "Amount to be transferred" when hovered over.(<a name="1003-TRAN-018" href="#1003-TRAN-018">1003-TRAN-018</a>)
|
||||||
|
|
||||||
- **Must** display tooltip for "Total amount (with fee)" when hovered over.(<a name="1003-TRAN-019" href="#1003-TRAN-019">1003-TRAN-019</a>)
|
- **Must** display tooltip for "Total amount (with fee)" when hovered over.(<a name="1003-TRAN-019" href="#1003-TRAN-019">1003-TRAN-019</a>)
|
||||||
|
Loading…
Reference in New Issue
Block a user