diff --git a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/TxDetailModal/ChangeFee/ChangeFee.tsx b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/TxDetailModal/ChangeFee/ChangeFee.tsx
index 3ad6494275a..8ae7ec74120 100644
--- a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/TxDetailModal/ChangeFee/ChangeFee.tsx
+++ b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/TxDetailModal/ChangeFee/ChangeFee.tsx
@@ -7,7 +7,7 @@ import { spacings } from '@trezor/theme';
import { Translation, FiatValue, FormattedCryptoAmount } from 'src/components/suite';
import { useSelector } from 'src/hooks/suite';
-import { useRbf, RbfContext, UseRbfProps } from 'src/hooks/wallet/useRbfForm';
+import { useRbfContext, UseRbfProps } from 'src/hooks/wallet/useRbfForm';
import { RbfFees } from './RbfFees';
import { AffectedTransactions } from './AffectedTransactions';
@@ -21,53 +21,53 @@ interface ChangeFeeProps extends UseRbfProps {
}
const ChangeFeeLoaded = (props: ChangeFeeProps) => {
- const contextValues = useRbf(props);
const { tx, showChained, children } = props;
- const { networkType } = contextValues.account;
+ const {
+ account: { networkType },
+ } = useRbfContext();
+
const feeRate =
networkType === 'bitcoin' ? `${tx.rbfParams?.feeRate} ${getFeeUnits(networkType)}` : null;
const fee = formatNetworkAmount(tx.fee, tx.symbol);
return (
-
-
-
-
- ({feeRate})
- >
- }
- typographyStyle="body"
- >
-
-
+
+
+ ({feeRate})
+ >
+ }
+ typographyStyle="body"
+ >
+
+
+
+
-
-
-
-
-
+
+
+
-
+
-
+
-
-
+
+
- {children}
-
-
+ {children}
+
);
};
diff --git a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/TxDetailModal/ChangeFee/ReplaceTxButton.tsx b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/TxDetailModal/ChangeFee/ReplaceTxButton.tsx
index af74735de9a..5a3d67b7062 100644
--- a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/TxDetailModal/ChangeFee/ReplaceTxButton.tsx
+++ b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/TxDetailModal/ChangeFee/ReplaceTxButton.tsx
@@ -1,21 +1,13 @@
import { NewModal } from '@trezor/components';
-import { SelectedAccountLoaded, RbfTransactionParams } from '@suite-common/wallet-types';
import { Translation } from 'src/components/suite';
import { useDevice } from 'src/hooks/suite';
-import { useRbf } from 'src/hooks/wallet/useRbfForm';
+import { useRbfContext } from 'src/hooks/wallet/useRbfForm';
-type ReplaceTxButtonProps = {
- rbfParams: RbfTransactionParams;
- selectedAccount: SelectedAccountLoaded;
-};
-
-export const ReplaceTxButton = ({ rbfParams, selectedAccount }: ReplaceTxButtonProps) => {
+export const ReplaceTxButton = () => {
const { device, isLocked } = useDevice();
- const { isLoading, signTransaction, getValues, composedLevels } = useRbf({
- selectedAccount,
- rbfParams,
- });
+
+ const { isLoading, signTransaction, getValues, composedLevels } = useRbfContext();
const values = getValues();
const composedTx = composedLevels ? composedLevels[values.selectedFee || 'normal'] : undefined;
diff --git a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/TxDetailModal/TxDetailModal.tsx b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/TxDetailModal/TxDetailModal.tsx
index 62ad5ade280..f22ca36df8d 100644
--- a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/TxDetailModal/TxDetailModal.tsx
+++ b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/TxDetailModal/TxDetailModal.tsx
@@ -1,25 +1,108 @@
import { useState, useMemo } from 'react';
-import { NewModal, Column, Banner } from '@trezor/components';
-import { HELP_CENTER_ZERO_VALUE_ATTACKS } from '@trezor/urls';
+import { NewModal } from '@trezor/components';
import { isPending, findChainedTransactions, getAccountKey } from '@suite-common/wallet-utils';
import { getNetwork } from '@suite-common/wallet-config';
import {
selectAccountByKey,
- selectTransactionConfirmations,
selectAllPendingTransactions,
selectIsPhishingTransaction,
} from '@suite-common/wallet-core';
-import { spacings } from '@trezor/theme';
+import {
+ ChainedTransactions,
+ SelectedAccountLoaded,
+ WalletAccountTransactionWithRequiredRbfParams,
+} from '@suite-common/wallet-types';
import { useSelector } from 'src/hooks/suite';
-import { Translation, TrezorLink } from 'src/components/suite';
+import { Translation } from 'src/components/suite';
import { Account, WalletAccountTransaction } from 'src/types/wallet';
+import { RbfContext, useRbf } from 'src/hooks/wallet/useRbfForm';
-import { BasicTxDetails } from './BasicTxDetails';
import { AdvancedTxDetails, TabID } from './AdvancedTxDetails/AdvancedTxDetails';
import { ChangeFee } from './ChangeFee/ChangeFee';
import { ReplaceTxButton } from './ChangeFee/ReplaceTxButton';
+import { TxDetailModalBase } from './TxDetailModalBase';
+
+const hasRbfParams = (
+ tx: WalletAccountTransaction,
+): tx is WalletAccountTransactionWithRequiredRbfParams => tx.rbfParams !== undefined;
+
+type DetailModalProps = {
+ tx: WalletAccountTransaction;
+ onCancel: () => void;
+ tab: TabID | undefined;
+ onChangeFeeClick: () => void;
+ chainedTxs?: ChainedTransactions;
+};
+
+const DetailModal = ({ tx, onCancel, tab, onChangeFeeClick, chainedTxs }: DetailModalProps) => {
+ const accountKey = getAccountKey(tx.descriptor, tx.symbol, tx.deviceState);
+ const account = useSelector(state => selectAccountByKey(state, accountKey)) as Account;
+ const network = getNetwork(account.symbol);
+ const isPhishingTransaction = useSelector(state =>
+ selectIsPhishingTransaction(state, tx.txid, accountKey),
+ );
+ const blockchain = useSelector(state => state.wallet.blockchain[tx.symbol]);
+
+ return (
+ }
+ bottomContent={
+
+
+
+ }
+ onBackClick={undefined}
+ >
+
+
+ );
+};
+
+type BumpFeeModalProps = {
+ tx: WalletAccountTransactionWithRequiredRbfParams;
+ onCancel: () => void;
+ onBackClick: () => void;
+ onShowChained: () => void;
+ chainedTxs?: ChainedTransactions;
+ selectedAccount: SelectedAccountLoaded;
+};
+
+const BumpFeeModal = ({
+ tx,
+ onCancel,
+ onBackClick,
+ onShowChained,
+ chainedTxs,
+ selectedAccount,
+}: BumpFeeModalProps) => {
+ const contextValues = useRbf({ rbfParams: tx.rbfParams, chainedTxs, selectedAccount });
+
+ return (
+
+ }
+ bottomContent={}
+ onBackClick={onBackClick}
+ >
+
+
+
+ );
+};
type TxDetailModalProps = {
tx: WalletAccountTransaction;
@@ -28,14 +111,18 @@ type TxDetailModalProps = {
};
export const TxDetailModal = ({ tx, rbfForm, onCancel }: TxDetailModalProps) => {
- const blockchain = useSelector(state => state.wallet.blockchain[tx.symbol]);
- const transactions = useSelector(selectAllPendingTransactions);
-
const [section, setSection] = useState<'CHANGE_FEE' | 'DETAILS'>(
rbfForm ? 'CHANGE_FEE' : 'DETAILS',
);
const [tab, setTab] = useState(undefined);
+ const accountKey = getAccountKey(tx.descriptor, tx.symbol, tx.deviceState);
+ const account = useSelector(state => selectAccountByKey(state, accountKey)) as Account;
+ const network = getNetwork(account.symbol);
+ const networkFeatures = network.accountTypes[account.accountType]?.features ?? network.features;
+ const selectedAccount = useSelector(state => state.wallet.selectedAccount);
+
+ const transactions = useSelector(selectAllPendingTransactions);
// const confirmations = getConfirmations(tx, blockchain.blockHeight);
// TODO: replace this part will be refactored after blockbook implementation:
// https://github.com/trezor/blockbook/issues/555
@@ -44,114 +131,48 @@ export const TxDetailModal = ({ tx, rbfForm, onCancel }: TxDetailModalProps) =>
return findChainedTransactions(tx.descriptor, tx.txid, transactions);
}, [tx, transactions]);
- const accountKey = getAccountKey(tx.descriptor, tx.symbol, tx.deviceState);
- const confirmations = useSelector(state =>
- selectTransactionConfirmations(state, tx.txid, accountKey),
- );
- const account = useSelector(state => selectAccountByKey(state, accountKey)) as Account;
- const selectedAccount = useSelector(state => state.wallet.selectedAccount);
- const network = getNetwork(account.symbol);
- const networkFeatures = network.accountTypes[account.accountType]?.features ?? network.features;
-
- const isPhishingTransaction = useSelector(state =>
- selectIsPhishingTransaction(state, tx.txid, accountKey),
- );
const onBackClick = () => {
setSection('DETAILS');
setTab(undefined);
};
- const getBottomContent = () => {
- if (
- networkFeatures?.includes('rbf') &&
- tx.rbfParams &&
- !tx.deadline &&
- selectedAccount.status === 'loaded'
- ) {
- if (section === 'CHANGE_FEE') {
- return (
-
- );
- } else {
- return (
- {
- setSection('CHANGE_FEE');
- setTab(undefined);
- }}
- >
-
-
- );
- }
- }
+ const onShowChained = () => {
+ setSection('DETAILS');
+ setTab('chained');
};
+ const onChangeFeeClick = () => {
+ setSection('CHANGE_FEE');
+ setTab(undefined);
+ };
+
+ if (
+ hasRbfParams(tx) &&
+ section === 'CHANGE_FEE' &&
+ networkFeatures?.includes('rbf') &&
+ !tx.deadline &&
+ selectedAccount.status === 'loaded'
+ ) {
+ return (
+
+ );
+ }
+
return (
-
- ) : (
-
- )
- }
- size="large"
- bottomContent={getBottomContent()}
- onBackClick={section === 'CHANGE_FEE' ? onBackClick : undefined}
- >
-
-
-
- {isPhishingTransaction && (
-
- (
-
- {chunks}
-
- ),
- }}
- />
-
- )}
-
- {section === 'CHANGE_FEE' ? (
- {
- setSection('DETAILS');
- setTab('chained');
- }}
- />
- ) : (
-
- )}
-
-
+ tab={tab}
+ onChangeFeeClick={onChangeFeeClick}
+ chainedTxs={chainedTxs}
+ />
);
};
diff --git a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/TxDetailModal/TxDetailModalBase.tsx b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/TxDetailModal/TxDetailModalBase.tsx
new file mode 100644
index 00000000000..1466d3a1c68
--- /dev/null
+++ b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/TxDetailModal/TxDetailModalBase.tsx
@@ -0,0 +1,90 @@
+import { ReactNode } from 'react';
+
+import { NewModal, Column, Banner } from '@trezor/components';
+import { HELP_CENTER_ZERO_VALUE_ATTACKS } from '@trezor/urls';
+import { getAccountKey } from '@suite-common/wallet-utils';
+import { getNetwork } from '@suite-common/wallet-config';
+import {
+ selectAccountByKey,
+ selectTransactionConfirmations,
+ selectIsPhishingTransaction,
+} from '@suite-common/wallet-core';
+import { spacings } from '@trezor/theme';
+
+import { useSelector } from 'src/hooks/suite';
+import { Translation, TrezorLink } from 'src/components/suite';
+import { Account, WalletAccountTransaction } from 'src/types/wallet';
+
+import { BasicTxDetails } from './BasicTxDetails';
+
+type TxDetailModalProps = {
+ tx: WalletAccountTransaction;
+ onCancel: () => void;
+ onBackClick: (() => void) | undefined;
+ heading: ReactNode;
+ bottomContent: ReactNode | undefined;
+ children: ReactNode;
+};
+
+export const TxDetailModalBase = ({
+ tx,
+ onCancel,
+ onBackClick,
+ heading,
+ bottomContent,
+ children,
+}: TxDetailModalProps) => {
+ const blockchain = useSelector(state => state.wallet.blockchain[tx.symbol]);
+
+ const accountKey = getAccountKey(tx.descriptor, tx.symbol, tx.deviceState);
+ const confirmations = useSelector(state =>
+ selectTransactionConfirmations(state, tx.txid, accountKey),
+ );
+ const account = useSelector(state => selectAccountByKey(state, accountKey)) as Account;
+ const network = getNetwork(account.symbol);
+
+ const isPhishingTransaction = useSelector(state =>
+ selectIsPhishingTransaction(state, tx.txid, accountKey),
+ );
+
+ return (
+
+
+
+
+ {isPhishingTransaction && (
+
+ (
+
+ {chunks}
+
+ ),
+ }}
+ />
+
+ )}
+
+ {children}
+
+
+ );
+};
diff --git a/packages/suite/src/hooks/wallet/__fixtures__/useRbfForm.ts b/packages/suite/src/hooks/wallet/__fixtures__/useRbfForm.ts
index 1d718b927ea..c39c9006352 100644
--- a/packages/suite/src/hooks/wallet/__fixtures__/useRbfForm.ts
+++ b/packages/suite/src/hooks/wallet/__fixtures__/useRbfForm.ts
@@ -1,3 +1,10 @@
+import {
+ ChainedTransactions,
+ WalletAccountTransaction,
+ WalletAccountTransactionWithRequiredRbfParams,
+} from '@suite-common/wallet-types';
+import { AccountUtxo } from '@trezor/connect';
+
export { getRootReducer } from './useSendForm';
const ABCD = 'abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd';
@@ -71,7 +78,41 @@ const BTC_CJ_ACCOUNT = {
// // script_type: 'PAYTOADDRESS',
// },
-const PREPARE_TX = (params = {}) => ({
+const txDummyData = {
+ deviceState: 'A@B:1',
+ descriptor: '',
+ type: 'sent',
+ txid: '',
+ amount: '',
+ fee: '',
+ targets: [],
+ tokens: [],
+ internalTransfers: [],
+ details: {
+ vin: [],
+ vout: [],
+ size: 0,
+ totalInput: '',
+ totalOutput: '',
+ },
+} satisfies Partial;
+
+// This type-magic here is for 2 reasons:
+//
+// 1. WalletAccountTransaction has rbfParams as optional, but we want to
+// enforce it in this fixture as we test only this case here
+//
+// 2. We need to add `required` into AccountUtxo because this is then passed
+// down into utxo-lib where it is present on ComposeInput. This is not
+// ideal and pretty magic, maybe subject of future refactor.
+//
+type HackedTxType = WalletAccountTransactionWithRequiredRbfParams & {
+ rbfParams: WalletAccountTransactionWithRequiredRbfParams['rbfParams'] & {
+ utxo: Array;
+ };
+};
+
+const PREPARE_TX = (params: Partial = {}): HackedTxType => ({
symbol: 'btc',
rbfParams: {
txid: 'ABCD',
@@ -110,9 +151,21 @@ const PREPARE_TX = (params = {}) => ({
baseFee: 175,
...params,
},
+ ...txDummyData,
});
-export const composeAndSign = [
+type ComposeAndSignFixture = {
+ description: string;
+ store: any;
+ tx: WalletAccountTransactionWithRequiredRbfParams;
+ composedLevels: any;
+ composeTransactionCalls: number;
+ chainedTxs?: ChainedTransactions;
+ signedTx?: any;
+ decreasedOutputs?: boolean | string;
+};
+
+export const composeAndSign: ComposeAndSignFixture[] = [
{
description:
'change-output reduced by fee. outputs order not affected. change was at the end of original tx.',
@@ -152,7 +205,7 @@ export const composeAndSign = [
],
},
},
- composeTransactionCalls: 2,
+ composeTransactionCalls: 1,
signedTx: {
outputs: [
{
@@ -178,10 +231,10 @@ export const composeAndSign = [
},
},
chainedTxs: {
- own: [{ txid: 'aaaa', fee: '500' }],
+ own: [{ symbol: 'btc', ...txDummyData, txid: 'aaaa', fee: '500' }],
others: [
- { txid: 'bbbb', fee: '500' },
- { txid: 'cccc', fee: '5000' },
+ { symbol: 'btc', ...txDummyData, txid: 'bbbb', fee: '500' },
+ { symbol: 'btc', ...txDummyData, txid: 'cccc', fee: '5000' },
],
},
tx: PREPARE_TX({
@@ -207,7 +260,7 @@ export const composeAndSign = [
feePerByte: '34.34', // 3.79 (old) + 4 (new) + 26.55 for chainedTxs
},
},
- composeTransactionCalls: 2,
+ composeTransactionCalls: 1,
signedTx: {
outputs: [
{
@@ -218,7 +271,7 @@ export const composeAndSign = [
},
{
address_n: [2147483692, 2147483648, 2147483648, 1, 0],
- amount: '9239',
+ amount: '3239',
orig_index: 1,
orig_hash: 'ABCD',
},
@@ -249,7 +302,7 @@ export const composeAndSign = [
],
},
},
- composeTransactionCalls: 2,
+ composeTransactionCalls: 1,
signedTx: {
outputs: [
{
@@ -304,7 +357,7 @@ export const composeAndSign = [
],
},
},
- composeTransactionCalls: 2,
+ composeTransactionCalls: 1,
signedTx: {
outputs: [
// change-output is gone
@@ -358,7 +411,7 @@ export const composeAndSign = [
],
},
},
- composeTransactionCalls: 4, // 1. normal fee, 2. custom fee
+ composeTransactionCalls: 2, // 1. normal fee, 2. custom fee
signedTx: {
outputs: [
// change-output is gone
@@ -432,7 +485,7 @@ export const composeAndSign = [
],
},
},
- composeTransactionCalls: 2,
+ composeTransactionCalls: 1,
signedTx: {
outputs: [
{
@@ -503,7 +556,7 @@ export const composeAndSign = [
],
},
},
- composeTransactionCalls: 4, // 1. normal fee, 2. custom fee
+ composeTransactionCalls: 2, // 1. normal fee, 2. custom fee
signedTx: {
inputs: [{ prev_hash: DCBA }, { prev_hash: ABCD }],
outputs: [
@@ -578,7 +631,7 @@ export const composeAndSign = [
],
},
},
- composeTransactionCalls: 4, // 1. normal fee, 2. custom fee
+ composeTransactionCalls: 2, // 1. normal fee, 2. custom fee
signedTx: {
inputs: [{ prev_hash: DCBA }, { prev_hash: ABCD }],
outputs: [
@@ -648,7 +701,7 @@ export const composeAndSign = [
],
},
},
- composeTransactionCalls: 6, // 1. normal fee, 2. custom fee, 3. send-max
+ composeTransactionCalls: 3, // 1. normal fee, 2. custom fee, 3. send-max
decreasedOutputs: true,
signedTx: {
inputs: [{ prev_hash: DCBA }],
@@ -695,7 +748,7 @@ export const composeAndSign = [
feeRate: '1.37',
changeAddress: undefined,
}),
- composeTransactionCalls: 2, // 1. immediate send-max
+ composeTransactionCalls: 1, // 1. immediate send-max
decreasedOutputs: true,
composedLevels: {
normal: {
@@ -754,7 +807,7 @@ export const composeAndSign = [
],
},
},
- composeTransactionCalls: 6, // 1. normal fee, 2. custom fee, 3 send-max
+ composeTransactionCalls: 3, // 1. normal fee, 2. custom fee, 3 send-max
decreasedOutputs: true,
signedTx: {
inputs: [{ prev_hash: DCBA }],
@@ -816,7 +869,7 @@ export const composeAndSign = [
],
},
},
- composeTransactionCalls: 2,
+ composeTransactionCalls: 1,
signedTx: {
// outputs are restored
outputs: [
@@ -878,7 +931,7 @@ export const composeAndSign = [
error: 'NOT-ENOUGH-FUNDS',
},
},
- composeTransactionCalls: 8, // 1. normal fee, 2. custom fee, 3. send-max normal fee, 4. send-max custom fee
+ composeTransactionCalls: 4, // 1. normal fee, 2. custom fee, 3. send-max normal fee, 4. send-max custom fee
// tx is not signed
},
{
@@ -943,7 +996,7 @@ export const composeAndSign = [
feePerByte: '15.33', // 11.33 (old) + 4 (new)
},
},
- composeTransactionCalls: 2, // 1. immediate send-max
+ composeTransactionCalls: 1, // 1. immediate send-max
decreasedOutputs: 'TR_NOT_ENOUGH_ANONYMIZED_FUNDS_RBF_WARNING',
signedTx: {
inputs: [{ prev_hash: DCBA }],
@@ -1029,7 +1082,7 @@ export const composeAndSign = [
feePerByte: '15.33', // 11.33 (old) + 4 (new)
},
},
- composeTransactionCalls: 2, // 1. immediate send-max
+ composeTransactionCalls: 1, // 1. immediate send-max
decreasedOutputs: 'TR_UTXO_REGISTERED_IN_COINJOIN_RBF_WARNING',
signedTx: {
inputs: [{ prev_hash: DCBA }],
diff --git a/packages/suite/src/hooks/wallet/__tests__/useRbfForm.test.tsx b/packages/suite/src/hooks/wallet/__tests__/useRbfForm.test.tsx
index 657595f8bb9..a09c036d578 100644
--- a/packages/suite/src/hooks/wallet/__tests__/useRbfForm.test.tsx
+++ b/packages/suite/src/hooks/wallet/__tests__/useRbfForm.test.tsx
@@ -2,7 +2,6 @@ import { screen } from '@testing-library/react';
import TrezorConnect from '@trezor/connect';
import { configureMockStore, initPreloadedState } from '@suite-common/test-utils';
-import { SelectedAccountLoaded, RbfTransactionParams } from '@suite-common/wallet-types';
import {
renderWithProviders,
@@ -14,7 +13,7 @@ import { ChangeFee } from 'src/components/suite/modals/ReduxModal/UserContextMod
import { ReplaceTxButton } from 'src/components/suite/modals/ReduxModal/UserContextModal/TxDetailModal/ChangeFee/ReplaceTxButton';
import * as fixtures from '../__fixtures__/useRbfForm';
-import { useRbfContext } from '../useRbfForm';
+import { RbfContext, useRbf, useRbfContext } from '../useRbfForm';
// do not mock
jest.unmock('@trezor/connect');
@@ -39,22 +38,30 @@ jest.mock('@trezor/blockchain-link', () => ({
default: class BlockchainLink {
name = 'jest-mocked-module';
listeners: Record void> = {};
+
constructor(args: any) {
this.name = args.name;
}
+
on(...args: any[]) {
const [type, fn] = args;
this.listeners[type] = fn;
}
+
listenerCount() {
return 0;
}
+
connect() {
return true;
}
+
disconnect() {}
+
removeAllListeners() {}
+
dispose() {}
+
getInfo() {
return {
url: this,
@@ -66,6 +73,7 @@ jest.mock('@trezor/blockchain-link', () => ({
blockHash: 'abcd',
};
}
+
estimateFee(params: { blocks: number[] }) {
return params.blocks.map(() => ({ feePerUnit: '-1' }));
}
@@ -73,6 +81,7 @@ jest.mock('@trezor/blockchain-link', () => ({
}));
type RootReducerState = ReturnType>;
+
interface Args {
send?: Partial;
fees?: any;
@@ -97,6 +106,7 @@ const initStore = ({ send, fees, selectedAccount, coinjoin }: Args = {}) => {
interface TestCallback {
getContextValues?: () => any;
}
+
// component rendered inside of SendIndex
// callback prop is an object passed from single test case
// getContextValues returns actual state of SendFormContext
@@ -130,17 +140,25 @@ describe('useRbfForm hook', () => {
it(`composeAndSign: ${f.description}`, async () => {
const store = initStore(f.store);
const callback: TestCallback = {};
- const { unmount } = renderWithProviders(
- store,
- // @ts-expect-error f.tx is not exact
- {}}>
-
-
- ,
- );
+
+ const TestComponent = () => {
+ const contextValues = useRbf({
+ rbfParams: f.tx.rbfParams,
+ chainedTxs: f.chainedTxs,
+ selectedAccount: f.store.selectedAccount,
+ });
+
+ return (
+
+ {}}>
+
+
+
+
+ );
+ };
+
+ const { unmount } = renderWithProviders(store, );
const composeTransactionSpy = jest.spyOn(TrezorConnect, 'composeTransaction');
@@ -165,13 +183,11 @@ describe('useRbfForm hook', () => {
expect(composedLevels).toMatchObject(f.composedLevels);
// validate number of calls to '@trezor/connect'
- if (typeof f.composeTransactionCalls === 'number') {
- expect(composeTransactionSpy).toHaveBeenCalledTimes(f.composeTransactionCalls);
- }
+ expect(composeTransactionSpy).toHaveBeenCalledTimes(f.composeTransactionCalls);
- if (f.decreasedOutputs) {
+ if (f.decreasedOutputs !== undefined) {
if (typeof f.decreasedOutputs === 'string') {
- expect(() => screen.getByText(f.decreasedOutputs)).not.toThrow();
+ expect(() => screen.getByText(f.decreasedOutputs as string)).not.toThrow();
} else {
expect(() => findByTestId('@send/decreased-outputs')).not.toThrow();
}
diff --git a/suite-common/wallet-types/src/transaction.ts b/suite-common/wallet-types/src/transaction.ts
index 84e12810b44..b12313b90d0 100644
--- a/suite-common/wallet-types/src/transaction.ts
+++ b/suite-common/wallet-types/src/transaction.ts
@@ -15,6 +15,7 @@ import {
} from '@trezor/connect';
import { Network, NetworkSymbol } from '@suite-common/wallet-config';
import { TranslationKey } from '@suite-common/intl-types';
+import { RequiredKey } from '@trezor/type-utils';
import { Account } from './account';
@@ -185,6 +186,11 @@ export interface WalletAccountTransaction extends AccountTransaction {
deadline?: number;
}
+export type WalletAccountTransactionWithRequiredRbfParams = RequiredKey<
+ WalletAccountTransaction,
+ 'rbfParams'
+>;
+
export interface ChainedTransactions {
own: WalletAccountTransaction[];
others: WalletAccountTransaction[];