public async Task AddFee(Transaction tr, TransactionBuildContext context) { var fee = await _feeProvider.CalcFeeForTransaction(tr); var providedAmount = Money.Zero; var queue = _pregeneratedOutputsQueueFactory.CreateFeeQueue(); do { var feeInput = await queue.DequeueCoin(); context.AddCoins(true, feeInput); tr.Inputs.Add(new TxIn { PrevOut = feeInput.Outpoint }); providedAmount += feeInput.Amount; fee = await _feeProvider.CalcFeeForTransaction(tr); if (fee <= providedAmount) { if (fee < providedAmount) { tr.Outputs.Add(new TxOut(providedAmount - fee, feeInput.ScriptPubKey)); } return; } } while (true); }
public async Task <Money> AddFee(TransactionBuilder builder, TransactionBuildContext context, decimal?feeMultiplier = null) { builder.SetChange(BitcoinAddress.Create(_baseSettings.ChangeAddress, _connectionParams.Network), ChangeType.Uncolored); var totalFeeSent = Money.Zero; var sentAmount = Money.Zero; var dustAmount = Money.Zero; try { var precalculatedFee = await _feeProvider.CalcFeeForTransaction(builder, feeMultiplier); builder.SendFees(precalculatedFee); totalFeeSent = precalculatedFee; } catch (NotEnoughFundsException ex) { if (ex.Missing is Money) { dustAmount = ((Money)ex.Missing).Satoshi; } else { throw; } } var queue = _pregeneratedOutputsQueueFactory.CreateFeeQueue(); do { var feeInput = await queue.DequeueCoin(); builder.AddCoins(feeInput); context.AddCoins(true, feeInput); sentAmount += feeInput.Amount; if (sentAmount < dustAmount + totalFeeSent) { continue; } var newEstimate = await _feeProvider.CalcFeeForTransaction(builder, feeMultiplier); builder.SendFees(newEstimate - totalFeeSent); totalFeeSent = newEstimate; } while (totalFeeSent + dustAmount > sentAmount); builder.Send(BitcoinAddress.Create(_baseSettings.ChangeAddress, _connectionParams.Network), sentAmount - dustAmount - totalFeeSent); return(totalFeeSent + dustAmount); }
public void SendAssetWithChange(TransactionBuilder builder, TransactionBuildContext context, List <ColoredCoin> coins, IDestination destination, AssetMoney amount, IDestination changeDestination) { if (amount.Quantity <= 0) { throw new BackendException("Amount can't be less or equal to zero", ErrorCode.BadInputParameter); } Action throwError = () => { throw new BackendException($"The sum of total applicable outputs is less than the required: {amount.Quantity} {amount.Id}.", ErrorCode.NotEnoughAssetAvailable); }; var selectedCoins = OpenAssetsHelper.CoinSelect(coins, amount); if (selectedCoins == null) { throwError(); } var orderedCounts = selectedCoins.Cast <ColoredCoin>().OrderBy(o => o.Amount).ToList(); var sendAmount = new AssetMoney(amount.Id); var cnt = 0; while (sendAmount < amount && cnt < orderedCounts.Count) { sendAmount += orderedCounts[cnt].Amount; cnt++; } if (sendAmount < amount) { throwError(); } builder.AddCoins(orderedCounts.Take(cnt)); context.AddCoins(orderedCounts.Take(cnt)); builder.SendAsset(destination, amount); if ((sendAmount - amount).Quantity > 0) { builder.SendAsset(changeDestination, sendAmount - amount); } }
public async Task <decimal> SendWithChange(TransactionBuilder builder, TransactionBuildContext context, List <ICoin> coins, IDestination destination, Money amount, IDestination changeDestination, bool addDust = true) { if (amount.Satoshi <= 0) { throw new BackendException("Amount can't be less or equal to zero", ErrorCode.BadInputParameter); } Action throwError = () => { throw new BackendException($"The sum of total applicable outputs is less than the required: {amount.Satoshi} satoshis.", ErrorCode.NotEnoughBitcoinAvailable); }; var selectedCoins = OpenAssetsHelper.CoinSelect(coins, amount); if (selectedCoins == null) { throwError(); } var orderedCoins = selectedCoins.OrderBy(o => o.Amount).ToList(); var sendAmount = Money.Zero; var cnt = 0; while (sendAmount < amount && cnt < orderedCoins.Count) { sendAmount += orderedCoins[cnt].TxOut.Value; cnt++; } if (sendAmount < amount) { throwError(); } context.AddCoins(orderedCoins.Take(cnt)); builder.AddCoins(orderedCoins.Take(cnt)); var sent = await Send(builder, context, destination, amount, addDust); if (sendAmount - amount > 0) { await Send(builder, context, changeDestination, sendAmount - amount, addDust); } return(sent); }
public async Task AddFeeWithoutChange(Transaction tr, TransactionBuildContext context, int maxCoins = int.MaxValue) { Money fee = Money.Zero; var providedAmount = Money.Zero; var queue = _pregeneratedOutputsQueueFactory.CreateFeeQueue(); int count = 0; do { var feeInput = await queue.DequeueCoin(); context.AddCoins(true, feeInput); count++; tr.Inputs.Add(new TxIn { PrevOut = feeInput.Outpoint }); providedAmount += feeInput.Amount; fee = await _feeProvider.CalcFeeForTransaction(tr); } while (fee > providedAmount && count < maxCoins); }