Exemple #1
0
        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);
        }
Exemple #2
0
        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);
        }
Exemple #3
0
        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);
            }
        }
Exemple #4
0
        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);
        }
Exemple #5
0
        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);
        }