Skip to content

[GEN-1815] Refactor coin selection - #563

Open
imclvr wants to merge 1 commit into
feat/improve-coin-selectionfrom
feat/improve-coin-selection-ff
Open

[GEN-1815] Refactor coin selection#563
imclvr wants to merge 1 commit into
feat/improve-coin-selectionfrom
feat/improve-coin-selection-ff

Conversation

@imclvr

@imclvr imclvr commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

This refactoring allows a common and meaningful place to put utxo selection from NG.


Stack created with GitHub Stacks CLIGive Feedback 💬

@imclvr
imclvr requested review from Jossec101, RodriFS and daliclovr and a lite review from Copilot August 12, 2026 12:25

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors coin/UTXO selection by extracting UTXO selection logic into a dedicated helper and moving UTXO→ICoin mapping onto Wallet, providing a more central and reusable place for coin selection behavior across NodeGuard’s on-chain workflows.

Changes:

  • Introduces UTXOSelectionAlgorithms to host domain-agnostic UTXO selection logic (e.g., “oldest first”).
  • Removes coin/UTXO selection helpers from LightningHelper and updates CoinSelectionService to use the new helper + Wallet mapping.
  • Adds Wallet.ToCoins(...) to convert selected UTXOs into the correct spendable coin type (plain vs script coins).

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

File Description
src/Services/CoinSelectionService.cs Switches input-coin selection to the new helper + wallet mapping method.
src/Helpers/UTXOSelectionAlgorithms.cs New centralized UTXO selection algorithms implementation.
src/Helpers/LightningHelper.cs Removes UTXO/coin selection helpers now moved elsewhere.
src/Data/Models/Wallet.cs Adds ToCoins to map selected UTXOs into spendable ICoin instances.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +41 to +55
public static List<UTXO> SelectUTXOsByOldest(
Wallet wallet, long satsAmount, List<UTXO> availableUTXOs, ILogger logger)
{
if (wallet == null) throw new ArgumentNullException(nameof(wallet));
if (logger == null) throw new ArgumentNullException(nameof(logger));
if (satsAmount <= 0) throw new ArgumentOutOfRangeException(nameof(satsAmount));

var selectedUTXOs = new List<UTXO>();

if (!availableUTXOs.Any())
{
logger.LogError("The PSBT cannot be generated, no UTXOs are available for walletId: {WalletId}",
wallet.Id);
return selectedUTXOs;
}
Comment on lines +71 to +88
var utxosSatsAmountAccumulator = 0M;

var iterations = 0;
while (satsAmount >= utxosSatsAmountAccumulator)
{
if (utxosStack.TryPop(out var utxo))
{
selectedUTXOs.Add(utxo);
utxosSatsAmountAccumulator += ((Money)utxo.Value).Satoshi;
}

iterations++;

if (iterations == 1_000)
{
break;
}
}
Comment thread src/Data/Models/Wallet.cs
Comment on lines +221 to +238
public List<ICoin> ToCoins(List<UTXO> selectedUTXOs)
{
var derivationStrategy = GetDerivationStrategy();

//UTXOS to Enumerable of ICOINS
return [
.. selectedUTXOs.Select<UTXO, ICoin>(x =>
{
var coin = x.AsCoin(derivationStrategy);
if (IsHotWallet)
{
return coin;
}

return coin.ToScriptCoin(x.ScriptPubKey);
})
];
}
Comment on lines +270 to +280
public Task<(List<ICoin> coins, List<UTXO> selectedUTXOs)> GetTxInputCoins(
List<UTXO> availableUTXOs,
IBitcoinRequest request,
DerivationStrategyBase derivationStrategy)
{
var satsAmount = request.SatsAmount;

var selectedUTXOs = await LightningHelper.SelectUTXOsByOldest(request.Wallet, satsAmount, availableUTXOs, _logger);
var coins = await LightningHelper.SelectCoins(request.Wallet, selectedUTXOs);
var selectedUTXOs = UTXOSelectionAlgorithms.SelectUTXOsByOldest(request.Wallet, satsAmount, availableUTXOs, _logger);
var coins = request.Wallet.ToCoins(selectedUTXOs);

return (coins, selectedUTXOs);
return Task.FromResult((coins, selectedUTXOs));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants