diff --git a/src/app/components/fees-row/fees-row.tsx b/src/app/components/fees-row/fees-row.tsx index 2e19021382f..c57bd1746c3 100644 --- a/src/app/components/fees-row/fees-row.tsx +++ b/src/app/components/fees-row/fees-row.tsx @@ -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'; @@ -115,18 +115,17 @@ export function FeesRow({ setFieldWarning={(value: string) => setFieldWarning(value)} /> ) : ( - handleSelectFeeEstimateOrCustomField(FeeTypes.Custom)} textAlign="right" width="100%" - type="button" > - + ) } fieldWarning={fieldWarning} diff --git a/src/app/pages/send/send-crypto-asset-form/form/stx/use-stx-send-form.tsx b/src/app/pages/send/send-crypto-asset-form/form/stx/use-stx-send-form.tsx index ae39961fc94..61aee92f800 100644 --- a/src/app/pages/send/send-crypto-asset-form/form/stx/use-stx-send-form.tsx +++ b/src/app/pages/send/send-crypto-asset-form/form/stx/use-stx-send-form.tsx @@ -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(); diff --git a/src/app/pages/swap/alex-swap-container.tsx b/src/app/pages/swap/alex-swap-container.tsx index 7b7f4b85465..ec4258915e8 100644 --- a/src/app/pages/swap/alex-swap-container.tsx +++ b/src/app/pages/swap/alex-swap-container.tsx @@ -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'; @@ -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(), diff --git a/src/app/query/stacks/fees/fees.hooks.ts b/src/app/query/stacks/fees/fees.hooks.ts index 766de8ab51c..7ef7ef5f680 100644 --- a/src/app/query/stacks/fees/fees.hooks.ts +++ b/src/app/query/stacks/fees/fees.hooks.ts @@ -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'; @@ -16,45 +15,22 @@ 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() { @@ -62,7 +38,7 @@ function useFeeEstimationsMinValues() { const configFeeEstimationsMinValues = useConfigFeeEstimationsMinValues(); if (configFeeEstimationsMinEnabled === false) return; - return configFeeEstimationsMinValues || defaultFeesMinValues; + return configFeeEstimationsMinValues || defaultFeesMinValuesAsMoney; } interface ParseStacksTxFeeEstimationResponseArgs { @@ -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', @@ -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, diff --git a/src/app/query/stacks/fees/fees.query.ts b/src/app/query/stacks/fees/fees.query.ts index 6cda35fc37d..114a9079bb6 100644 --- a/src/app/query/stacks/fees/fees.query.ts +++ b/src/app/query/stacks/fees/fees.query.ts @@ -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) => { @@ -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, }); } diff --git a/src/app/query/stacks/fees/fees.utils.ts b/src/app/query/stacks/fees/fees.utils.ts index bc0673e9ae6..69e950b82e2 100644 --- a/src/app/query/stacks/fees/fees.utils.ts +++ b/src/app/query/stacks/fees/fees.utils.ts @@ -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; } diff --git a/src/shared/models/fees/stacks-fees.model.ts b/src/shared/models/fees/stacks-fees.model.ts index 45f462151fc..ee15f390190 100644 --- a/src/shared/models/fees/stacks-fees.model.ts +++ b/src/shared/models/fees/stacks-fees.model.ts @@ -5,7 +5,7 @@ export interface StacksFeeEstimate { feeRate: number; } -interface Estimation { +export interface ApiFeeEstimation { fee: number; fee_rate: number; } @@ -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; }