largestFirst function
Future<Result<CoinSelection, CoinSelectionError> >
largestFirst({
- required List<
WalletTransaction> unspentInputsAvailable, - required List<
MultiAssetRequest> outputsRequested, - required Set<
ShelleyAddress> ownedAddresses, - int coinSelectionLimit = defaultCoinSelectionLimit,
- bool logSelection = false,
Implementation
Future<Result<CoinSelection, CoinSelectionError>> largestFirst({
required List<WalletTransaction> unspentInputsAvailable,
required List<MultiAssetRequest> outputsRequested,
required Set<ShelleyAddress> ownedAddresses,
int coinSelectionLimit = defaultCoinSelectionLimit,
bool logSelection = false,
}) async {
final logger = Logger();
if (outputsRequested.isEmpty) {
return Err(CoinSelectionError(
reason: CoinSelectionErrorEnum.inputCountInsufficient,
message: "can't create an empty transaction"));
}
const String hardCodedUnit = lovelaceHex;
Coin amount = 0;
for (final reqest in outputsRequested) {
if (reqest.policyId == '') {
for (final asset in reqest.assets) {
if (asset.name == lovelaceHex) {
amount = asset.value;
} else {
return Err(CoinSelectionError(
reason: CoinSelectionErrorEnum.unsupported,
message: "only support ADA transactions at this time",
));
}
}
} else {
return Err(CoinSelectionError(
reason: CoinSelectionErrorEnum.unsupported,
message: "only support ADA transactions at this time",
));
}
}
if (amount <= 0) {
return Err(CoinSelectionError(
reason: CoinSelectionErrorEnum.inputValueInsufficient,
message: "transactions must be greater than zero",
));
}
final List<WalletTransaction> sortedInputs =
List.from(unspentInputsAvailable);
sortedInputs.sort((a, b) => b.amount.compareTo(a.amount));
List<ShelleyTransactionInput> results = [];
Coin selectedAmount = 0;
int coinsSelected = 0;
for (final tx in sortedInputs) {
if (tx.status != TransactionStatus.unspent) {
logger.i("SHOULDN'T SEE TransactionStatus.unspent HERE: ${tx.txId}");
}
// int index = 0;
for (int index = 0; index < tx.outputs.length; index++) {
final output = tx.outputs[index];
//Coin coinAmount = tx.currencyAmount(assetId: hardCodedUnit);
final contains = ownedAddresses.contains(output.address);
logger.i(
"contains:$contains, tx=${tx.txId.substring(0, 20)} index[$index]=${output.amounts.first.quantity}");
if (contains) {
for (final txAmount in output.amounts) {
if (txAmount.quantity > 0 && txAmount.unit == hardCodedUnit) {
selectedAmount += txAmount.quantity;
if (logSelection) {
logger.i(
"selectedAmount += quantity: $selectedAmount += ${txAmount.quantity} -> tx: ${tx.txId} index: $index");
}
if (++coinsSelected > coinSelectionLimit) {
return Err(CoinSelectionError(
reason: CoinSelectionErrorEnum.inputsExhausted,
message:
"coinsSelected ($coinsSelected) exceeds allowed coinSelectionLimit ($coinSelectionLimit)",
));
}
results.add(
ShelleyTransactionInput(index: index, transactionId: tx.txId));
}
}
}
//index++;
}
if (selectedAmount >= amount) {
break;
}
}
if (selectedAmount < amount) {
return Err(CoinSelectionError(
reason: CoinSelectionErrorEnum.inputValueInsufficient,
message: "insufficient funds",
));
}
return Ok(CoinSelection(inputs: results));
}