CoinSelection.inOrderUntilEnough constructor

CoinSelection.inOrderUntilEnough({
  1. int version = Transaction.currentVersion,
  2. required Iterable<InputCandidate> candidates,
  3. required Iterable<Output> recipients,
  4. required Program changeProgram,
  5. required BigInt feePerKb,
  6. required BigInt minFee,
  7. required BigInt minChange,
  8. int locktime = 0,
  9. bool randomise = false,
  10. int maxCandidates = 6800,
})

A simple selection algorithm that selects inputs from the candidates in the order that they are given until the required amount has been reached. If there are not enough coins, all shall be selected and enoughFunds shall be false. If randomise is set to true, the order of inputs shall be randomised after being selected. This is useful for candidates that are not already randomised as it may avoid giving clues to the algorithm being used. The algorithm will only take upto 6800 candidates by default to avoid taking too long and due to size limitations. This can be changed with maxCandidates.

Implementation

factory CoinSelection.inOrderUntilEnough({
  int version = Transaction.currentVersion,
  required Iterable<InputCandidate> candidates,
  required Iterable<Output> recipients,
  required Program changeProgram,
  required BigInt feePerKb,
  required BigInt minFee,
  required BigInt minChange,
  int locktime = 0,
  bool randomise = false,
  int maxCandidates = 6800,
}) {

  CoinSelection trySelection(Iterable<InputCandidate> selected)
    => CoinSelection(
      version: version,
      selected: selected,
      recipients: recipients,
      changeProgram: changeProgram,
      feePerKb: feePerKb,
      minFee: minFee,
      minChange: minChange,
      locktime: locktime,
    );

  // Restrict number of candidates due to size limitation and for efficiency
  final list = candidates.take(maxCandidates).toList();

  CoinSelection selection = trySelection([]);
  for (int i = 0; i < list.length; i++) {
    selection = trySelection(list.take(i+1));
    if (selection.enoughFunds) break;
  }

  return randomise
    ? trySelection(selection.selected.toList()..shuffle())
    : selection;

}