diff --git a/libs/accounts/src/lib/TransferFee.graphql b/libs/accounts/src/lib/TransferFee.graphql new file mode 100644 index 000000000..49d5e9d84 --- /dev/null +++ b/libs/accounts/src/lib/TransferFee.graphql @@ -0,0 +1,18 @@ +query TransferFee( + $fromAccount: ID! + $fromAccountType: AccountType! + $toAccount: ID! + $amount: String! + $assetId: String! +) { + estimateTransferFee( + fromAccount: $fromAccount + fromAccountType: $fromAccountType + toAccount: $toAccount + amount: $amount + assetId: $assetId + ) { + fee + discount + } +} diff --git a/libs/accounts/src/lib/__generated__/TransferFee.ts b/libs/accounts/src/lib/__generated__/TransferFee.ts new file mode 100644 index 000000000..22ad02662 --- /dev/null +++ b/libs/accounts/src/lib/__generated__/TransferFee.ts @@ -0,0 +1,63 @@ +import * as Types from '@vegaprotocol/types'; + +import { gql } from '@apollo/client'; +import * as Apollo from '@apollo/client'; +const defaultOptions = {} as const; +export type TransferFeeQueryVariables = Types.Exact<{ + fromAccount: Types.Scalars['ID']; + fromAccountType: Types.AccountType; + toAccount: Types.Scalars['ID']; + amount: Types.Scalars['String']; + assetId: Types.Scalars['String']; +}>; + + +export type TransferFeeQuery = { __typename?: 'Query', estimateTransferFee?: { __typename?: 'EstimatedTransferFee', fee: string, discount: string } | null }; + + +export const TransferFeeDocument = gql` + query TransferFee($fromAccount: ID!, $fromAccountType: AccountType!, $toAccount: ID!, $amount: String!, $assetId: String!) { + estimateTransferFee( + fromAccount: $fromAccount + fromAccountType: $fromAccountType + toAccount: $toAccount + amount: $amount + assetId: $assetId + ) { + fee + discount + } +} + `; + +/** + * __useTransferFeeQuery__ + * + * To run a query within a React component, call `useTransferFeeQuery` and pass it any options that fit your needs. + * When your component renders, `useTransferFeeQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useTransferFeeQuery({ + * variables: { + * fromAccount: // value for 'fromAccount' + * fromAccountType: // value for 'fromAccountType' + * toAccount: // value for 'toAccount' + * amount: // value for 'amount' + * assetId: // value for 'assetId' + * }, + * }); + */ +export function useTransferFeeQuery(baseOptions: Apollo.QueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(TransferFeeDocument, options); + } +export function useTransferFeeLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(TransferFeeDocument, options); + } +export type TransferFeeQueryHookResult = ReturnType; +export type TransferFeeLazyQueryHookResult = ReturnType; +export type TransferFeeQueryResult = Apollo.QueryResult; \ No newline at end of file diff --git a/libs/accounts/src/lib/transfer-container.tsx b/libs/accounts/src/lib/transfer-container.tsx index a02f07f94..306aa2147 100644 --- a/libs/accounts/src/lib/transfer-container.tsx +++ b/libs/accounts/src/lib/transfer-container.tsx @@ -72,7 +72,6 @@ export const TransferContainer = ({ assetId }: { assetId?: string }) => { pubKeys={pubKeys ? pubKeys?.map((pk) => pk.publicKey) : null} isReadOnly={isReadOnly} assetId={assetId} - feeFactor={params.transfer_fee_factor} minQuantumMultiple={params.transfer_minTransferQuantumMultiple} submitTransfer={transfer} accounts={sortedAccounts} diff --git a/libs/accounts/src/lib/transfer-form.tsx b/libs/accounts/src/lib/transfer-form.tsx index dc1adf77a..1210304be 100644 --- a/libs/accounts/src/lib/transfer-form.tsx +++ b/libs/accounts/src/lib/transfer-form.tsx @@ -6,6 +6,7 @@ import { addDecimal, formatNumber, toBigNum, + removeDecimal, } from '@vegaprotocol/utils'; import { useT } from './use-t'; import { @@ -26,6 +27,7 @@ import { useCallback, useEffect, useMemo, useState } from 'react'; import { Controller, useForm } from 'react-hook-form'; import { AssetOption, Balance } from '@vegaprotocol/assets'; import { AccountType, AccountTypeMapping } from '@vegaprotocol/types'; +import { useTransferFeeQuery } from './__generated__/TransferFee'; interface FormFields { toVegaKey: string; @@ -52,7 +54,6 @@ export interface TransferFormProps { asset: Asset; }>; assetId?: string; - feeFactor: string | null; minQuantumMultiple: string | null; submitTransfer: (transfer: Transfer) => void; } @@ -62,7 +63,6 @@ export const TransferForm = ({ pubKeys, isReadOnly, assetId: initialAssetId, - feeFactor, submitTransfer, accounts, minQuantumMultiple, @@ -140,23 +140,29 @@ export const TransferForm = ({ // Max amount given selected asset and from account const max = accountBalance ? new BigNumber(accountBalance) : new BigNumber(0); + const transferFeeQuery = useTransferFeeQuery({ + variables: { + fromAccount: pubKey || '', + fromAccountType: accountType || AccountType.ACCOUNT_TYPE_GENERAL, + amount: (amount && asset && removeDecimal(amount, asset.decimals)) || '0', + assetId: asset?.id || '', + toAccount: selectedPubKey, + }, + skip: !pubKey || !amount || !asset || !selectedPubKey || fromVested, + }); + const transferFee = transferFeeQuery.loading + ? transferFeeQuery.data || transferFeeQuery.previousData + : transferFeeQuery.data; const transferAmount = useMemo(() => { if (!amount) return undefined; - if (includeFee && feeFactor) { - return new BigNumber(1).minus(feeFactor).times(amount).toString(); + if (includeFee && transferFee?.estimateTransferFee) { + return new BigNumber(amount) + .minus(transferFee.estimateTransferFee.fee) + .plus(transferFee.estimateTransferFee.discount) + .toString(); } return amount; - }, [amount, includeFee, feeFactor]); - - const fee = useMemo(() => { - if (!transferAmount) return undefined; - if (includeFee) { - return new BigNumber(amount).minus(transferAmount).toString(); - } - return ( - feeFactor && new BigNumber(feeFactor).times(transferAmount).toString() - ); - }, [amount, includeFee, transferAmount, feeFactor]); + }, [amount, includeFee, transferFee?.estimateTransferFee]); const onSubmit = useCallback( (fields: FormFields) => { @@ -449,29 +455,33 @@ export const TransferForm = ({ )} -
- -
- setIncludeFee((x) => !x)} - /> -
-
-
- {transferAmount && fee && ( + {fromVested ? null : ( +
+ +
+ setIncludeFee((x) => !x)} + /> +
+
+
+ )} + {(transferFee?.estimateTransferFee || fromVested) && transferAmount && ( )} @@ -485,20 +495,19 @@ export const TransferForm = ({ export const TransferFee = ({ amount, transferAmount, - feeFactor, fee, + discount, decimals, }: { amount: string; transferAmount: string; - feeFactor: string | null; fee?: string; + discount?: string; decimals?: number; }) => { const t = useT(); - if (!feeFactor || !amount || !transferAmount || !fee) return null; + if (!amount || !transferAmount || !fee) return null; if ( - isNaN(Number(feeFactor)) || isNaN(Number(amount)) || isNaN(Number(transferAmount)) || isNaN(Number(fee)) @@ -507,6 +516,7 @@ export const TransferFee = ({ } const totalValue = new BigNumber(transferAmount).plus(fee).toString(); + const feeFactor = new BigNumber(fee).dividedBy(amount).toFixed(2); return (
@@ -524,6 +534,15 @@ export const TransferFee = ({ {formatNumber(fee, decimals)}
+ {discount && discount !== '0' && ( +
+
{t('Discount')}
+
+ {formatNumber(discount, decimals)} +
+
+ )} +