feat(accounts): get trasfer fee from estimateTransferFee API

This commit is contained in:
Bartłomiej Głownia 2024-02-05 11:40:46 +01:00
parent 575897d94f
commit 8cfcb8ef79
No known key found for this signature in database
GPG Key ID: A622E438A7075295
5 changed files with 99 additions and 86 deletions

View File

@ -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,
]); ]);

View File

@ -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);
}); });
}); });
}); });

View File

@ -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>

View File

@ -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",

View File

@ -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>)