diff --git a/packages/suite/src/support/messages.ts b/packages/suite/src/support/messages.ts index a815dbcd33f..a244992a3e3 100644 --- a/packages/suite/src/support/messages.ts +++ b/packages/suite/src/support/messages.ts @@ -5805,6 +5805,11 @@ export default defineMessages({ defaultMessage: 'Rejected by coordinator', description: 'Tooltip over an icon in Coin control section', }, + TR_UTXO_NOT_MATURED_COINBASE: { + id: 'TR_UTXO_NOT_MATURED_COINBASE', + defaultMessage: + 'Coinbase transaction has to have at least {confirmations} confirmations to be spendable', + }, TR_CHANGE_ADDRESS_TOOLTIP: { id: 'TR_CHANGE_ADDRESS_TOOLTIP', defaultMessage: 'This is a change address created from a previous send.', diff --git a/packages/suite/src/views/wallet/send/Options/BitcoinOptions/CoinControl/UtxoSelectionList/UtxoSelection/UtxoSelection.tsx b/packages/suite/src/views/wallet/send/Options/BitcoinOptions/CoinControl/UtxoSelectionList/UtxoSelection/UtxoSelection.tsx index 4f5dcca640b..63dff2c3091 100644 --- a/packages/suite/src/views/wallet/send/Options/BitcoinOptions/CoinControl/UtxoSelectionList/UtxoSelection/UtxoSelection.tsx +++ b/packages/suite/src/views/wallet/send/Options/BitcoinOptions/CoinControl/UtxoSelectionList/UtxoSelection/UtxoSelection.tsx @@ -1,10 +1,10 @@ -import { MouseEventHandler } from 'react'; +import { MouseEventHandler, ReactNode } from 'react'; import styled, { css, useTheme } from 'styled-components'; import { formatNetworkAmount, isSameUtxo } from '@suite-common/wallet-utils'; import { Checkbox, Row, Spinner, TextButton, Tooltip } from '@trezor/components'; -import type { AccountUtxo } from '@trezor/connect'; +import { AccountUtxo } from '@trezor/connect'; import { borders, spacings, spacingsPx, typography } from '@trezor/theme'; import { CheckContainer } from '@trezor/components/src/components/form/Checkbox/Checkbox'; @@ -120,6 +120,36 @@ const StyledFiatValue = styled(FiatValue)` ${typography.hint} `; +type ResolveUtxoSpendableProps = { + utxo: AccountUtxo; + coinjoinRegisteredUtxos: AccountUtxo[]; +}; + +// Same as MINIMAL_COINBASE_CONFIRMATIONS in '@trezor/utxo-lib'; It is redeclared here to avoid +// some magic import/export errors. This is very niche stuff and probably never changes. +// Also, this most probably bothers only developers on Regtest. +const MINIMAL_COINBASE_CONFIRMATIONS = 100; + +const resolveUtxoSpendable = ({ + utxo, + coinjoinRegisteredUtxos, +}: ResolveUtxoSpendableProps): ReactNode | null => { + if (utxo.coinbase === true && utxo.confirmations < MINIMAL_COINBASE_CONFIRMATIONS) { + return ( + + ); + } + + if (coinjoinRegisteredUtxos.includes(utxo)) { + return ; + } + + return null; +}; + type UtxoSelectionProps = { transaction?: WalletAccountTransaction; utxo: AccountUtxo; @@ -155,7 +185,10 @@ export const UtxoSelection = ({ transaction, utxo }: UtxoSelectionProps) => { const isChecked = isCoinControlEnabled ? selectedUtxos.some(selected => isSameUtxo(selected, utxo)) : composedInputs.some(u => u.prev_hash === utxo.txid && u.prev_index === utxo.vout); - const isDisabled = coinjoinRegisteredUtxos.includes(utxo); + + const unspendableTooltip = resolveUtxoSpendable({ utxo, coinjoinRegisteredUtxos }); + const isDisabled = unspendableTooltip !== null; + const utxoTagIconColor = isDisabled ? theme.legacy.TYPE_LIGHT_GREY : theme.legacy.TYPE_DARK_GREY; @@ -174,7 +207,7 @@ export const UtxoSelection = ({ transaction, utxo }: UtxoSelectionProps) => { $isDisabled={isDisabled} onClick={isDisabled ? undefined : handleCheckbox} > - }> + { const utxos = filterCoinbase(utxosO, coinbase);