Пример #1
0
        public async Task <TransactionResult> GetTransactionAsync(uint256 txId, bool includeOffchain = false, CancellationToken cancellation = default(CancellationToken))
        {
            if (txId == null)
            {
                throw new ArgumentNullException(nameof(txId));
            }
            var tx = await _Client.GetTransactionAsync(txId, cancellation);

            if (tx is null && includeOffchain)
            {
                var offchainTx = await GetOffchainTransactionAsync(txId);

                if (offchainTx != null)
                {
                    tx = new TransactionResult()
                    {
                        Confirmations   = -1,
                        TransactionHash = offchainTx.GetHash(),
                        Transaction     = offchainTx
                    }
                }
                ;
            }
            return(tx);
        }
Пример #2
0
        private async void WaitConfirmations(uint256 tx)
        {
            while (!cancel.IsCancellationRequested)
            {
                try
                {
                    var op = await client.GetTransactionAsync(oracleAddress, tx, cancel);

                    if (op.BalanceChange < Money.Zero)
                    {
                        await withdrawStream.Writer.WriteAsync(ProcessWithdraw(op));

                        return;
                    }
                    else if (op.Confirmations >= 3)
                    {
                        await depositStream.Writer.WriteAsync(ProcessDeposit(op));

                        return;
                    }
                }
                catch (Exception e)
                {
                    Log.Error("Failde to load transaction confirmation: " + e.ToString());
                }
                await Task.Delay(3000);
            }
        }
Пример #3
0
        public async Task <TransactionResult> GetTransactionAsync(uint256 txId, CancellationToken cancellation = default(CancellationToken))
        {
            if (txId == null)
            {
                throw new ArgumentNullException(nameof(txId));
            }
            var tx = await _Client.GetTransactionAsync(txId, cancellation);

            return(tx);
        }
Пример #4
0
        public static async Task <Dictionary <uint256, TransactionResult> > GetTransactions(this ExplorerClient client, uint256[] hashes, CancellationToken cts = default(CancellationToken))
        {
            hashes = hashes.Distinct().ToArray();
            var transactions = hashes
                               .Select(async o => await client.GetTransactionAsync(o, cts))
                               .ToArray();
            await Task.WhenAll(transactions).ConfigureAwait(false);

            return(transactions.Select(t => t.Result).Where(t => t != null).ToDictionary(o => o.Transaction.GetHash()));
        }
Пример #5
0
        private async Task <IEnumerable <(PaymentEntity Payment, TransactionResult Transaction)> > GetPaymentsWithTransaction(InvoiceEntity invoice)
        {
            var getPayments = invoice.Payments
                              .Select(async o => (Payment: o, Transaction: await _ExplorerClient.GetTransactionAsync(o.Outpoint.Hash, _Cts.Token)))
                              .ToArray();
            await Task.WhenAll(getPayments).ConfigureAwait(false);

            var transactions = getPayments.Select(c => (Payment: c.Result.Payment, Transaction: c.Result.Transaction));

            return(transactions);
        }
Пример #6
0
        private async Task <(bool NeedSave, UTXOChanges Changes)> UpdateInvoice(UTXOChanges changes, InvoiceEntity invoice)
        {
            bool needSave = false;

            if (invoice.Status != "invalid" && invoice.ExpirationTime < DateTimeOffset.UtcNow && (invoice.Status == "new" || invoice.Status == "paidPartial"))
            {
                needSave       = true;
                invoice.Status = "invalid";
            }

            if (invoice.Status == "invalid" || invoice.Status == "new" || invoice.Status == "paidPartial")
            {
                var strategy = _DerivationFactory.Parse(invoice.DerivationStrategy);
                changes = await _ExplorerClient.SyncAsync(strategy, changes, !LongPollingMode, _Cts.Token).ConfigureAwait(false);

                var utxos      = changes.Confirmed.UTXOs.Concat(changes.Unconfirmed.UTXOs).ToArray();
                var invoiceIds = utxos.Select(u => _Wallet.GetInvoiceId(u.Output.ScriptPubKey)).ToArray();
                utxos =
                    utxos
                    .Where((u, i) => invoiceIds[i].GetAwaiter().GetResult() == invoice.Id)
                    .ToArray();

                List <Coin> receivedCoins = new List <Coin>();
                foreach (var received in utxos)
                {
                    if (received.Output.ScriptPubKey == invoice.DepositAddress.ScriptPubKey)
                    {
                        receivedCoins.Add(new Coin(received.Outpoint, received.Output));
                    }
                }

                var alreadyAccounted = new HashSet <OutPoint>(invoice.Payments.Select(p => p.Outpoint));
                foreach (var coin in receivedCoins.Where(c => !alreadyAccounted.Contains(c.Outpoint)))
                {
                    var payment = await _InvoiceRepository.AddPayment(invoice.Id, coin).ConfigureAwait(false);

                    invoice.Payments.Add(payment);
                    if (invoice.Status == "new")
                    {
                        invoice.Status = "paidPartial";
                        needSave       = true;
                    }
                }
            }

            if (invoice.Status == "paidPartial")
            {
                var totalPaid = invoice.Payments.Select(p => p.Output.Value).Sum();
                if (totalPaid == invoice.GetTotalCryptoDue())
                {
                    invoice.Status = "paid";
                    if (invoice.FullNotifications)
                    {
                        _NotificationManager.Notify(invoice);
                    }
                    invoice.ExceptionStatus = null;
                    needSave = true;
                }

                if (totalPaid > invoice.GetTotalCryptoDue())
                {
                    invoice.Status          = "paidOver";
                    invoice.ExceptionStatus = "paidOver";
                    needSave = true;
                }

                if (totalPaid < invoice.GetTotalCryptoDue() && invoice.ExceptionStatus == null)
                {
                    invoice.ExceptionStatus = "paidPartial";
                    needSave = true;
                }
            }

            if (invoice.Status == "paid" || invoice.Status == "paidOver")
            {
                var getTransactions = invoice.Payments.Select(o => o.Outpoint.Hash).Select(o => _ExplorerClient.GetTransactionAsync(o, _Cts.Token)).ToArray();
                await Task.WhenAll(getTransactions).ConfigureAwait(false);

                var transactions = getTransactions.Select(c => c.GetAwaiter().GetResult()).ToArray();

                bool confirmed = false;
                var  minConf   = transactions.Select(t => t.Confirmations).Min();
                if (invoice.SpeedPolicy == SpeedPolicy.HighSpeed)
                {
                    if (minConf > 0)
                    {
                        confirmed = true;
                    }
                    else
                    {
                        confirmed = !transactions.Any(t => t.Transaction.RBF);
                    }
                }
                else if (invoice.SpeedPolicy == SpeedPolicy.MediumSpeed)
                {
                    confirmed = minConf >= 1;
                }
                else if (invoice.SpeedPolicy == SpeedPolicy.LowSpeed)
                {
                    confirmed = minConf >= 6;
                }

                if (confirmed)
                {
                    invoice.Status = "confirmed";
                    _NotificationManager.Notify(invoice);
                    needSave = true;
                }
            }

            if (invoice.Status == "confirmed")
            {
                var getTransactions = invoice.Payments.Select(o => o.Outpoint.Hash).Select(o => _ExplorerClient.GetTransactionAsync(o, _Cts.Token)).ToArray();
                await Task.WhenAll(getTransactions).ConfigureAwait(false);

                var transactions = getTransactions.Select(c => c.GetAwaiter().GetResult()).ToArray();
                var minConf      = transactions.Select(t => t.Confirmations).Min();
                if (minConf >= 6)
                {
                    invoice.Status = "complete";
                    if (invoice.FullNotifications)
                    {
                        _NotificationManager.Notify(invoice);
                    }
                    needSave = true;
                }
            }

            return(needSave, changes);
        }