refactor to use transaction parameters record object when creating a wallet transaction
What changed, and why it matters
This commit is a straightforward internal code cleanup. It bundles many individual transaction settings into a single 'TransactionParameters' object and passes that object around instead of a long list of separate values. There is no change to what the software actually does, and nothing in the commit suggests a security fix.
No security action required. Treat as normal refactoring.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch refactors callers of wallet.createWalletTransaction() and the WalletTransactionService constructor to use a new TransactionParameters record. All previously passed arguments (utxoSelectors, txoFilters, payments, opReturns, excludedChangeNodes, fee rates, block height, grouping flags, RBF flag) are now packaged into the record. The diff shows only structural changes; no logic, validation, or behavior changes are introduced.
Changed components
src/main/java/com/sparrowwallet/sparrow/paynym/PayNymController.javasrc/main/java/com/sparrowwallet/sparrow/wallet/SendController.javaInspect captured patch +16 / −42
diff --git a/src/main/java/com/sparrowwallet/sparrow/paynym/PayNymController.java b/src/main/java/com/sparrowwallet/sparrow/paynym/PayNymController.java
index 76f58b1..c21bf46 100644
--- a/src/main/java/com/sparrowwallet/sparrow/paynym/PayNymController.java
+++ b/src/main/java/com/sparrowwallet/sparrow/paynym/PayNymController.java
@@ -624,8 +624,9 @@ public class PayNymController {
List<UtxoSelector> utxoSelectors = List.of(utxos == null ? new KnapsackUtxoSelector(noInputsFee) : new PresetUtxoSelector(utxos, true, false));
List<TxoFilter> txoFilters = List.of(new SpentTxoFilter(), new FrozenTxoFilter(), new CoinbaseTxoFilter(wallet));
- return wallet.createWalletTransaction(utxoSelectors, txoFilters, payments, opReturns, Collections.emptySet(), feeRate, minimumFeeRate, minRelayFeeRate, null,
- AppServices.getCurrentBlockHeight(), groupByAddress, includeMempoolOutputs, true);
+ TransactionParameters params = new TransactionParameters(utxoSelectors, txoFilters, payments, opReturns, Collections.emptySet(),
+ feeRate, minimumFeeRate, minRelayFeeRate, null, AppServices.getCurrentBlockHeight(), groupByAddress, includeMempoolOutputs, true);
+ return wallet.createWalletTransaction(params);
}
private Map<BlockTransaction, WalletNode> getNotificationTransaction(PaymentCode externalPaymentCode) {
diff --git a/src/main/java/com/sparrowwallet/sparrow/wallet/SendController.java b/src/main/java/com/sparrowwallet/sparrow/wallet/SendController.java
index 435b501..6390794 100644
--- a/src/main/java/com/sparrowwallet/sparrow/wallet/SendController.java
+++ b/src/main/java/com/sparrowwallet/sparrow/wallet/SendController.java
@@ -619,10 +619,11 @@ public class SendController extends WalletFormController implements Initializabl
boolean allowRbf = (replacedTransaction == null || replacedTransaction.getTransaction().isReplaceByFee())
&& payments.stream().noneMatch(payment -> payment instanceof SilentPayment);
- walletTransactionService = new WalletTransactionService(wallet, getUtxoSelectors(payments), getTxoFilters(),
+ TransactionParameters params = new TransactionParameters(getUtxoSelectors(payments), getTxoFilters(),
payments, opReturnsList, excludedChangeNodes,
feeRate, getMinimumFeeRate(), minRelayFeeRate, userFee,
- currentBlockHeight, groupByAddress, includeMempoolOutputs, replacedTransaction, allowRbf);
+ currentBlockHeight, groupByAddress, includeMempoolOutputs, allowRbf);
+ walletTransactionService = new WalletTransactionService(wallet, params, replacedTransaction);
walletTransactionService.setOnSucceeded(event -> {
if(!walletTransactionService.isIgnoreResult()) {
walletTransactionProperty.setValue(walletTransactionService.getValue());
@@ -685,42 +686,14 @@ public class SendController extends WalletFormController implements Initializabl
private static class WalletTransactionService extends Service<WalletTransaction> {
private final Wallet wallet;
- private final List<UtxoSelector> utxoSelectors;
- private final List<TxoFilter> txoFilters;
- private final List<Payment> payments;
- private final List<byte[]> opReturns;
- private final Set<WalletNode> excludedChangeNodes;
- private final double feeRate;
- private final double longTermFeeRate;
- private final double minRelayFeeRate;
- private final Long fee;
- private final Integer currentBlockHeight;
- private final boolean groupByAddress;
- private final boolean includeMempoolOutputs;
+ private final TransactionParameters params;
private final BlockTransaction replacedTransaction;
- private final boolean allowRbf;
private boolean ignoreResult;
- public WalletTransactionService(Wallet wallet, List<UtxoSelector> utxoSelectors, List<TxoFilter> txoFilters,
- List<Payment> payments, List<byte[]> opReturns, Set<WalletNode> excludedChangeNodes,
- double feeRate, double longTermFeeRate, double minRelayFeeRate, Long fee,
- Integer currentBlockHeight, boolean groupByAddress, boolean includeMempoolOutputs,
- BlockTransaction replacedTransaction, boolean allowRbf) {
+ public WalletTransactionService(Wallet wallet, TransactionParameters params, BlockTransaction replacedTransaction) {
this.wallet = wallet;
- this.utxoSelectors = utxoSelectors;
- this.txoFilters = txoFilters;
- this.payments = payments;
- this.opReturns = opReturns;
- this.excludedChangeNodes = excludedChangeNodes;
- this.feeRate = feeRate;
- this.longTermFeeRate = longTermFeeRate;
- this.minRelayFeeRate = minRelayFeeRate;
- this.fee = fee;
- this.currentBlockHeight = currentBlockHeight;
- this.groupByAddress = groupByAddress;
- this.includeMempoolOutputs = includeMempoolOutputs;
+ this.params = params;
this.replacedTransaction = replacedTransaction;
- this.allowRbf = allowRbf;
}
@Override
@@ -731,11 +704,11 @@ public class SendController extends WalletFormController implements Initializabl
return getWalletTransaction();
} catch(InsufficientFundsException e) {
if(e.getTargetValue() != null && replacedTransaction != null && wallet.isSafeToAddInputsOrOutputs(replacedTransaction)
- && utxoSelectors.size() == 1 && utxoSelectors.getFirst() instanceof PresetUtxoSelector presetUtxoSelector) {
+ && params.utxoSelectors().size() == 1 && params.utxoSelectors().getFirst() instanceof PresetUtxoSelector presetUtxoSelector) {
//Creating RBF transaction - include additional UTXOs if available to pay desired fee
- List<TxoFilter> filters = new ArrayList<>(txoFilters);
+ List<TxoFilter> filters = new ArrayList<>(params.txoFilters());
filters.add(presetUtxoSelector.asExcludeTxoFilter());
- List<OutputGroup> outputGroups = wallet.getGroupedUtxos(filters, feeRate, AppServices.getMinimumRelayFeeRate(), Config.get().isGroupByAddress())
+ List<OutputGroup> outputGroups = wallet.getGroupedUtxos(filters, params.feeRate(), AppServices.getMinimumRelayFeeRate(), Config.get().isGroupByAddress())
.stream().filter(outputGroup -> outputGroup.getEffectiveValue() >= 0).collect(Collectors.toList());
Collections.shuffle(outputGroups);
@@ -756,8 +729,7 @@ public class SendController extends WalletFormController implements Initializabl
private WalletTransaction getWalletTransaction() throws InsufficientFundsException {
try {
updateMessage("Selecting UTXOs...");
- return wallet.createWalletTransaction(utxoSelectors, txoFilters, payments, opReturns, excludedChangeNodes,
- feeRate, longTermFeeRate, minRelayFeeRate, fee, currentBlockHeight, groupByAddress, includeMempoolOutputs, allowRbf);
+ return wallet.createWalletTransaction(params);
} finally {
updateMessage("");
}
@@ -1265,8 +1237,9 @@ public class SendController extends WalletFormController implements Initializabl
boolean groupByAddress = Config.get().isGroupByAddress();
boolean includeMempoolOutputs = Config.get().isIncludeMempoolOutputs();
- WalletTransaction finalWalletTx = decryptedWallet.createWalletTransaction(utxoSelectors, getTxoFilters(), walletTransaction.getPayments(), List.of(blindedPaymentCode),
+ TransactionParameters params = new TransactionParameters(utxoSelectors, getTxoFilters(), walletTransaction.getPayments(), List.of(blindedPaymentCode),
excludedChangeNodes, feeRate, getMinimumFeeRate(), minRelayFeeRate, userFee, currentBlockHeight, groupByAddress, includeMempoolOutputs, true);
+ WalletTransaction finalWalletTx = decryptedWallet.createWalletTransaction(params);
PSBT psbt = finalWalletTx.createPSBT();
decryptedWallet.sign(psbt);
decryptedWallet.finalise(psbt);
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.