Пример #1
0
        public async Task PayInvoice(PaymentRequest invoice, long?amountMSat = null, CancellationToken ct = default)
        {
            var amount = invoice.AmountValue?.Value.MilliSatoshi ?? amountMSat;

            if (amount is null)
            {
                throw new NRustLightningException($"You must specify payment amount if it is not included in invoice");
            }

            var n = _networkProvider.TryGetByInvoice(invoice);

            if (n is null)
            {
                throw new NRustLightningException($"Unknown invoice prefix {invoice.PrefixValue}");
            }
            var peerMan    = _peerManagerProvider.GetPeerManager(n);
            var failureTcs = new TaskCompletionSource <Event>(TaskCreationOptions.RunContinuationsAsynchronously);
            var successTcs = new TaskCompletionSource <Event>(TaskCreationOptions.RunContinuationsAsynchronously);

            _eventAggregator.Subscribe <Event>(e =>
            {
                if (e is Event.PaymentFailed paymentF && paymentF.Item.PaymentHash.Equals(invoice.PaymentHash))
                {
                    _logger.LogError($"Payment for invoice ({invoice}) failed");
                    failureTcs.SetResult(paymentF);
                }

                if (e is Event.PaymentSent paymentS && paymentS.Item.Hash.Equals(invoice.PaymentHash))
                {
                    _logger.LogInformation($"Payment for invoice ({invoice}) succeed");
                    successTcs.SetResult(paymentS);
                }
            });
            peerMan.SendPayment(invoice.NodeIdValue.Item, invoice.PaymentHash, new List <RouteHint>(), LNMoney.MilliSatoshis(amount.Value), invoice.MinFinalCLTVExpiryDelta, _pool, invoice.PaymentSecret.Value);
            peerMan.ProcessEvents();

            // case 1: canceled by user.
            var cancelTcs = new TaskCompletionSource <object>(TaskCreationOptions.RunContinuationsAsynchronously);

            await using var _ = (ct.Register(state => { ((TaskCompletionSource <object>)state).TrySetResult(null); },
                                             cancelTcs));
            var cancelTask = cancelTcs.Task;

            // case 2: timeout.
            using var cts = new CancellationTokenSource();
            var timeoutTask = Task.Delay(TimeSpan.FromSeconds(_config.Value.PaymentTimeoutSec), cts.Token);

            // case 3: finishes
            var task = Task.WhenAny(failureTcs.Task, successTcs.Task);

            var resultTask = await Task.WhenAny(cancelTask, timeoutTask, task);

            if (resultTask == cancelTask)
            {
                throw new NRustLightningException($"Payment canceled.");
            }
            if (resultTask == timeoutTask)
            {
                throw new NRustLightningException($"Payment for {invoice} did not finish in {_config.Value.PaymentTimeoutSec} seconds");
            }
            cts.Cancel(); // cancel the timer task so it does not fire.

            var resultEvent = await await task;

            if (resultEvent is Event.PaymentFailed paymentFailed)
            {
                if (paymentFailed.Item.RejectedByDest)
                {
                    throw new NRustLightningException($"Failed to pay! rejected by destination");
                }
                throw new NRustLightningException($"Failed to pay!");
            }

            if (resultEvent is Event.PaymentSent paymentSent)
            {
                await _repository.SetPreimage(paymentSent.Item, ct);
            }
        }
Пример #2
0
        public async Task CanCallSendPayment()
        {
            var hostBuilder = new HostBuilder().ConfigureTestHost();

            using var host = await hostBuilder.StartAsync();

            var c = host.GetTestNRustLightningClient();
            var e = await Assert.ThrowsAsync <HttpRequestException>(async() => await c.PayToInvoiceAsync("lnbcrt1p03zqaapp54vmm7lg9fjjnm6v998v8cafzqcnzecjnqlq8dk55rhgzlrgstzasdqqcqzpgsp58vt9tjxuvx8jmy4q0wtdakdu24k6zlx8np67w8pxmvcmwcacsa3q9qy9qsqx8h8dmt0fsqel426tu0ayrscaty0pt4t3tg2rz0jpl7p3xyx6hynwhhc86h7apmmf9043n250275cuuad6npdasqclk0ga9htyq0v0qqjs26z3"));

            Assert.Equal("You must specify payment amount if it is not included in invoice", e.Message);
            e = await Assert.ThrowsAsync <HttpRequestException>(async() => await c.PayToInvoiceAsync("lnbcrt1p03zqaapp54vmm7lg9fjjnm6v998v8cafzqcnzecjnqlq8dk55rhgzlrgstzasdqqcqzpgsp58vt9tjxuvx8jmy4q0wtdakdu24k6zlx8np67w8pxmvcmwcacsa3q9qy9qsqx8h8dmt0fsqel426tu0ayrscaty0pt4t3tg2rz0jpl7p3xyx6hynwhhc86h7apmmf9043n250275cuuad6npdasqclk0ga9htyq0v0qqjs26z3", LNMoney.MilliSatoshis(100L)));

            Assert.Contains("Cannot route when there are no outbound routes away from us", e.Message);
        }
Пример #3
0
 public override LNMoney?Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
 {
     return(LNMoney.MilliSatoshis(reader.GetInt64()));
 }
Пример #4
0
        public void CanCallSendPayment()
        {
            using var peerMan = getTestPeerManager();
            var paymentHash = Primitives.PaymentHash.NewPaymentHash(uint256.Parse("4141414141414141414141414141414141414141414141414141414141414142"));
            var lastHops    = new List <RouteHint>();
            var e           = Assert.Throws <FFIException>(() => peerMan.SendPayment(_keys[0].PubKey, paymentHash, lastHops, LNMoney.MilliSatoshis(100L), TEST_FINAL_CTLV, _pool));

            Assert.Contains("Cannot route when there are no outbound routes away from us", e.Message);

            var secret = uint256.Parse("4141414141414141414141414141414141414141414141414141414141414143");

            e = Assert.Throws <FFIException>(() => peerMan.SendPayment(_keys[0].PubKey, paymentHash, lastHops, LNMoney.MilliSatoshis(100L), TEST_FINAL_CTLV, _pool, secret));
            Assert.Contains("Cannot route when there are no outbound routes away from us", e.Message);
        }