Skip to content

Commit

Permalink
fix: fee estimation error, ref #4821
Browse files Browse the repository at this point in the history
  • Loading branch information
fbwoolf committed Jan 21, 2024
1 parent 7d75f4a commit 9b75521
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 44 deletions.
7 changes: 3 additions & 4 deletions src/app/components/fees-row/fees-row.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useCallback, useEffect, useMemo, useState } from 'react';
import { SharedComponentsSelectors } from '@tests/selectors/shared-component.selectors';
import BigNumber from 'bignumber.js';
import { useField } from 'formik';
import { styled } from 'leather-styles/jsx';
import { Box } from 'leather-styles/jsx';

import { STX_DECIMALS } from '@shared/constants';
import { FeeTypes, Fees } from '@shared/models/fees/fees.model';
Expand Down Expand Up @@ -115,18 +115,17 @@ export function FeesRow({
setFieldWarning={(value: string) => setFieldWarning(value)}
/>
) : (
<styled.button
<Box
onClick={() => handleSelectFeeEstimateOrCustomField(FeeTypes.Custom)}
textAlign="right"
width="100%"
type="button"
>
<TransactionFee
fee={feeField.value}
feeCurrencySymbol={feeCurrencySymbol}
usdAmount={feeInUsd}
/>
</styled.button>
</Box>
)
}
fieldWarning={fieldWarning}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import { useStacksCommonSendForm } from '../stacks/use-stacks-common-send-form';
export function useStxSendForm() {
const unsignedTx = useStxTokenTransferUnsignedTxState();
const { data: stxFees } = useCalculateStacksTxFees(unsignedTx);

const generateTx = useGenerateStxTokenTransferUnsignedTx();
const { onFormStateChange } = useUpdatePersistedSendFormValues();

Expand Down
4 changes: 2 additions & 2 deletions src/app/pages/swap/alex-swap-container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { isDefined, isUndefined } from '@shared/utils';
import { LoadingKeys, useLoading } from '@app/common/hooks/use-loading';
import { useWalletType } from '@app/common/use-wallet-type';
import { NonceSetter } from '@app/components/nonce-setter';
import { defaultFeesMinValues } from '@app/query/stacks/fees/fees.hooks';
import { defaultFeesMinValuesAsMoney } from '@app/query/stacks/fees/fees.utils';
import { useCurrentStacksAccount } from '@app/store/accounts/blockchain/stacks/stacks-account.hooks';
import { useGenerateStacksContractCallUnsignedTx } from '@app/store/transactions/contract-call.hooks';
import { useSignStacksTransaction } from '@app/store/transactions/transaction.hooks';
Expand Down Expand Up @@ -86,7 +86,7 @@ function AlexSwapContainer() {
]);

onSetSwapSubmissionData({
fee: isSponsoredByAlex ? '0' : defaultFeesMinValues[1].amount.toString(),
fee: isSponsoredByAlex ? '0' : defaultFeesMinValuesAsMoney[1].amount.toString(),
feeCurrency: values.feeCurrency,
feeType: values.feeType,
liquidityFee: new BigNumber(Number(lpFee)).dividedBy(oneHundredMillion).toNumber(),
Expand Down
39 changes: 7 additions & 32 deletions src/app/query/stacks/fees/fees.hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { useMemo } from 'react';

import { StacksTransaction } from '@stacks/transactions';

import { logger } from '@shared/logger';
import { FeeCalculationTypes, Fees } from '@shared/models/fees/fees.model';
import { StacksFeeEstimate, StacksTxFeeEstimation } from '@shared/models/fees/stacks-fees.model';
import { Money, createMoney } from '@shared/models/money.model';
Expand All @@ -16,53 +15,30 @@ import {
import { useGetStacksTransactionFeeEstimationQuery } from '@app/query/stacks/fees/fees.query';

import {
defaultFeesMaxValuesAsMoney,
defaultFeesMinValuesAsMoney,
defaultStacksFees,
feeEstimationQueryFailedSilently,
getDefaultSimulatedFeeEstimations,
getEstimatedUnsignedStacksTxByteLength,
getFeeEstimationsWithCappedValues,
getSerializedUnsignedStacksTxPayload,
} from './fees.utils';

const defaultFeesMaxValues = [
createMoney(500000, 'STX'),
createMoney(750000, 'STX'),
createMoney(2000000, 'STX'),
];
export const defaultFeesMinValues = [
createMoney(2500, 'STX'),
createMoney(3000, 'STX'),
createMoney(3500, 'STX'),
];

const defaultStacksFeeEstimates: StacksFeeEstimate[] = [
{ fee: defaultFeesMinValues[0], feeRate: 0 },
{ fee: defaultFeesMinValues[1], feeRate: 0 },
{ fee: defaultFeesMinValues[2], feeRate: 0 },
];

const defaultStacksFees: Fees = {
blockchain: 'stacks',
estimates: defaultStacksFeeEstimates,
calculation: FeeCalculationTypes.Default,
};

function feeEstimationQueryFailedSilently(feeEstimation: StacksTxFeeEstimation) {
return !!(feeEstimation && (!!feeEstimation.error || !feeEstimation.estimations.length));
}

function useFeeEstimationsMaxValues() {
const configFeeEstimationsMaxEnabled = useConfigFeeEstimationsMaxEnabled();
const configFeeEstimationsMaxValues = useConfigFeeEstimationsMaxValues();

if (configFeeEstimationsMaxEnabled === false) return;
return configFeeEstimationsMaxValues || defaultFeesMaxValues;
return configFeeEstimationsMaxValues || defaultFeesMaxValuesAsMoney;
}

function useFeeEstimationsMinValues() {
const configFeeEstimationsMinEnabled = useConfigFeeEstimationsMinEnabled();
const configFeeEstimationsMinValues = useConfigFeeEstimationsMinValues();

if (configFeeEstimationsMinEnabled === false) return;
return configFeeEstimationsMinValues || defaultFeesMinValues;
return configFeeEstimationsMinValues || defaultFeesMinValuesAsMoney;
}

interface ParseStacksTxFeeEstimationResponseArgs {
Expand All @@ -77,7 +53,7 @@ function parseStacksTxFeeEstimationResponse({
minValues,
txByteLength,
}: ParseStacksTxFeeEstimationResponseArgs): Fees {
if (!!feeEstimation.error) defaultStacksFees;
if (!!feeEstimation.error) return defaultStacksFees;
if (txByteLength && feeEstimationQueryFailedSilently(feeEstimation)) {
return {
blockchain: 'stacks',
Expand Down Expand Up @@ -126,7 +102,6 @@ export function useCalculateStacksTxFees(unsignedTx?: StacksTransaction) {
}, [unsignedTx]);

return useGetStacksTransactionFeeEstimationQuery(txByteLength, txPayload, {
onError: err => logger.error('Error getting stacks tx fee estimation', { err }),
select: resp =>
parseStacksTxFeeEstimationResponse({
feeEstimation: resp,
Expand Down
21 changes: 19 additions & 2 deletions src/app/query/stacks/fees/fees.query.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { useQuery } from '@tanstack/react-query';
import axios from 'axios';

import { logger } from '@shared/logger';
import { StacksTxFeeEstimation } from '@shared/models/fees/stacks-fees.model';

import { AppUseQueryConfig } from '@app/query/query-config';
import { useCurrentNetworkState } from '@app/store/networks/networks.hooks';

import { RateLimiter, useHiroApiRateLimiter } from '../rate-limiter';
import { defaultApiFeeEstimations } from './fees.utils';

function fetchTransactionFeeEstimation(currentNetwork: any, limiter: RateLimiter) {
return async (estimatedLen: number | null, transactionPayload: string) => {
Expand Down Expand Up @@ -39,8 +41,23 @@ export function useGetStacksTransactionFeeEstimationQuery<
return useQuery({
enabled: transactionPayload !== '',
queryKey: ['stacks-tx-fee-estimation', transactionPayload],
queryFn: () =>
fetchTransactionFeeEstimation(currentNetwork, limiter)(estimatedLen, transactionPayload),
queryFn: async () => {
try {
return await fetchTransactionFeeEstimation(currentNetwork, limiter)(
estimatedLen,
transactionPayload
);
} catch (err) {
logger.error('Error getting stacks tx fee estimation', { err });
return {
cost_scalar_change_by_byte: 0,
estimated_cost: {},
estimated_cost_scalar: 0,
estimations: defaultApiFeeEstimations,
error: err ?? 'Error',
} as StacksTxFeeEstimation;
}
},
...options,
});
}
43 changes: 42 additions & 1 deletion src/app/query/stacks/fees/fees.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,50 @@ import { StacksTransaction, serializePayload } from '@stacks/transactions';
import { BigNumber } from 'bignumber.js';

import { DEFAULT_FEE_RATE } from '@shared/constants';
import { StacksFeeEstimate } from '@shared/models/fees/stacks-fees.model';
import { FeeCalculationTypes, Fees } from '@shared/models/fees/fees.model';
import {
ApiFeeEstimation,
StacksFeeEstimate,
StacksTxFeeEstimation,
} from '@shared/models/fees/stacks-fees.model';
import { Money, createMoney } from '@shared/models/money.model';

const defaultFeesMaxValues = [500000, 750000, 2000000];
const defaultFeesMinValues = [2500, 3000, 3500];

export const defaultFeesMaxValuesAsMoney = [
createMoney(defaultFeesMaxValues[0], 'STX'),
createMoney(defaultFeesMaxValues[1], 'STX'),
createMoney(defaultFeesMaxValues[2], 'STX'),
];
export const defaultFeesMinValuesAsMoney = [
createMoney(defaultFeesMinValues[0], 'STX'),
createMoney(defaultFeesMinValues[1], 'STX'),
createMoney(defaultFeesMinValues[2], 'STX'),
];

export const defaultApiFeeEstimations: ApiFeeEstimation[] = [
{ fee: defaultFeesMinValues[0], fee_rate: 0 },
{ fee: defaultFeesMinValues[1], fee_rate: 0 },
{ fee: defaultFeesMinValues[2], fee_rate: 0 },
];

const defaultStacksFeeEstimates: StacksFeeEstimate[] = [
{ fee: defaultFeesMinValuesAsMoney[0], feeRate: 0 },
{ fee: defaultFeesMinValuesAsMoney[1], feeRate: 0 },
{ fee: defaultFeesMinValuesAsMoney[2], feeRate: 0 },
];

export const defaultStacksFees: Fees = {
blockchain: 'stacks',
estimates: defaultStacksFeeEstimates,
calculation: FeeCalculationTypes.Default,
};

export function feeEstimationQueryFailedSilently(feeEstimation: StacksTxFeeEstimation) {
return !!(feeEstimation && (!!feeEstimation.error || !feeEstimation.estimations.length));
}

export function getEstimatedUnsignedStacksTxByteLength(transaction: StacksTransaction) {
return transaction.serialize().byteLength;
}
Expand Down
4 changes: 2 additions & 2 deletions src/shared/models/fees/stacks-fees.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export interface StacksFeeEstimate {
feeRate: number;
}

interface Estimation {
export interface ApiFeeEstimation {
fee: number;
fee_rate: number;
}
Expand All @@ -14,6 +14,6 @@ export interface StacksTxFeeEstimation {
cost_scalar_change_by_byte: number;
estimated_cost: object;
estimated_cost_scalar: number;
estimations: Estimation[];
estimations: ApiFeeEstimation[];
error?: string;
}

0 comments on commit 9b75521

Please sign in to comment.