diff --git a/packages/suite/src/components/wallet/TransactionItem/TransactionItem.tsx b/packages/suite/src/components/wallet/TransactionItem/TransactionItem.tsx
index 629e7e1e0942..19649a8bcf54 100644
--- a/packages/suite/src/components/wallet/TransactionItem/TransactionItem.tsx
+++ b/packages/suite/src/components/wallet/TransactionItem/TransactionItem.tsx
@@ -2,7 +2,7 @@ import { memo, useMemo, useState } from 'react';
import styled, { css } from 'styled-components';
import { AnimatePresence } from 'framer-motion';
import { selectIsPhishingTransaction } from '@suite-common/wallet-core';
-import { variables, Button, Card } from '@trezor/components';
+import { variables, Button, Card, Link } from '@trezor/components';
import { Translation } from 'src/components/suite';
import { useDispatch, useSelector } from 'src/hooks/suite';
import { openModal } from 'src/actions/suite/modalActions';
@@ -35,6 +35,8 @@ import { BlurWrapper } from './TransactionItemBlurWrapper';
import { selectSelectedAccount } from 'src/reducers/wallet/selectedAccountReducer';
import { getInstantStakeType } from 'src/utils/suite/stake';
import { isStakeTypeTx } from '@suite-common/suite-utils';
+import { Tooltip } from '@trezor/components';
+import { HELP_CENTER_REPLACE_BY_FEE } from '@trezor/urls';
// eslint-disable-next-line local-rules/no-override-ds-component
const Wrapper = styled(Card)<{
@@ -88,6 +90,7 @@ interface TransactionItemProps {
network: Network;
accountType: AccountType;
className?: string;
+ disableBumpFee?: boolean;
index: number;
}
@@ -101,6 +104,7 @@ export const TransactionItem = memo(
network,
accountType,
className,
+ disableBumpFee,
index,
}: TransactionItemProps) => {
const [limit, setLimit] = useState(0);
@@ -183,6 +187,42 @@ export const TransactionItem = memo(
transaction.deadline ? '/prepending' : ''
}`;
+ const BumpFeeButton = ({ isDisabled }: { isDisabled: boolean }) => (
+
+ );
+
+ const DisabledBumpFeeButtonWithTooltip = () => (
+
+ (
+
+ {chunks}
+
+ ),
+ }}
+ />
+
+ }
+ >
+
+
+ );
+
// we are using slightly different layout for 1 targets txs to better match the design
// the only difference is that crypto amount is in the same row as tx heading/description
// fiat amount is in the second row along with address
@@ -418,12 +458,11 @@ export const TransactionItem = memo(
networkFeatures?.includes('rbf') &&
!transaction?.deadline && (
-
+ {disableBumpFee ? (
+
+ ) : (
+
+ )}
)}
diff --git a/packages/suite/src/support/messages.ts b/packages/suite/src/support/messages.ts
index f6494b9a3ee3..66300a036002 100644
--- a/packages/suite/src/support/messages.ts
+++ b/packages/suite/src/support/messages.ts
@@ -9157,4 +9157,9 @@ export default defineMessages({
defaultMessage:
'Setting a low fee might cause your transaction to fail or experience significant delays.',
},
+ TR_BUMP_FEE_DISABLED_TOOLTIP: {
+ id: 'TR_BUMP_FEE_DISABLED_TOOLTIP',
+ defaultMessage:
+ 'To speed up your transactions, increase the fee on the first pending transaction in the queue (the one processed first). Transactions must be confirmed in order. Learn more',
+ },
});
diff --git a/packages/suite/src/views/wallet/transactions/TransactionList/TransactionGroupedList.tsx b/packages/suite/src/views/wallet/transactions/TransactionList/TransactionGroupedList.tsx
index 1eb4d21ed68d..92add38607cb 100644
--- a/packages/suite/src/views/wallet/transactions/TransactionList/TransactionGroupedList.tsx
+++ b/packages/suite/src/views/wallet/transactions/TransactionList/TransactionGroupedList.tsx
@@ -1,4 +1,8 @@
-import { GroupedTransactionsByDate, groupJointTransactions } from '@suite-common/wallet-utils';
+import {
+ getTransactionWithLowestNonce,
+ GroupedTransactionsByDate,
+ groupJointTransactions,
+} from '@suite-common/wallet-utils';
import { getNetwork } from '@suite-common/wallet-config';
import { CoinjoinBatchItem } from 'src/components/wallet/TransactionItem/CoinjoinBatchItem';
import { useSelector } from 'src/hooks/suite';
@@ -25,6 +29,9 @@ export const TransactionGroupedList = ({
const accountMetadata = useSelector(state => selectLabelingDataForAccount(state, account.key));
const network = getNetwork(symbol);
+ const transactionWithLowestNonce: WalletAccountTransaction | null =
+ getTransactionWithLowestNonce(transactionGroups);
+
return Object.entries(transactionGroups).map(([dateKey, value], groupIndex) => (
),
)}
diff --git a/packages/urls/src/urls.ts b/packages/urls/src/urls.ts
index ef9101090092..19161878d7f9 100644
--- a/packages/urls/src/urls.ts
+++ b/packages/urls/src/urls.ts
@@ -103,6 +103,8 @@ export const HELP_CENTER_EVM_ADDRESS_CHECKSUM: Url =
'https://trezor.io/learn/a/evm-address-checksum-in-trezor-suite';
export const HELP_CENTER_FIRMWARE_REVISION_CHECK: Url =
'https://trezor.io/learn/a/trezor-firmware-revision-check';
+export const HELP_CENTER_REPLACE_BY_FEE: Url =
+ 'https://trezor.io/learn/a/replace-by-fee-rbf-ethereum';
export const INVITY_URL: Url = 'https://invity.io/';
export const INVITY_SCHEDULE_OF_FEES: Url = 'https://blog.invity.io/schedule-of-fees';
diff --git a/suite-common/wallet-utils/src/transactionUtils.ts b/suite-common/wallet-utils/src/transactionUtils.ts
index 182db04bbe34..12b0be8287e9 100644
--- a/suite-common/wallet-utils/src/transactionUtils.ts
+++ b/suite-common/wallet-utils/src/transactionUtils.ts
@@ -1034,3 +1034,21 @@ export const groupTokensTransactionsByContractAddress = (
return groupedTokensTxs;
};
+
+export const getTransactionWithLowestNonce = (
+ transactionGroups: GroupedTransactionsByDate,
+): WalletAccountTransaction | null =>
+ Object.values(transactionGroups)
+ .flat()
+ .reduce((lowestNonceTransaction, transaction) => {
+ if (!transaction.ethereumSpecific) return null;
+ const currentNonce = Number(transaction.ethereumSpecific?.nonce);
+ if (
+ lowestNonceTransaction === null ||
+ currentNonce < Number(lowestNonceTransaction.ethereumSpecific?.nonce)
+ ) {
+ lowestNonceTransaction = transaction;
+ }
+
+ return lowestNonceTransaction;
+ }, null);