Beispiel #1
0
        public override async Task PayAsync(
            Swap swap,
            CancellationToken cancellationToken = default)
        {
            if (swap.IsAcceptor && !swap.HasPartyPayment)
            {
                Log.Debug("Acceptor is not ready to broadcast {@currency} payment tx for swap {@swap}",
                          Currency,
                          swap.Id);

                return;
            }

            if (!CheckPayRelevance(swap))
            {
                return;
            }

            var lockTimeInSeconds = swap.IsInitiator
                ? DefaultInitiatorLockTimeInSeconds
                : DefaultAcceptorLockTimeInSeconds;

            await CreatePaymentAsync(swap, lockTimeInSeconds)
            .ConfigureAwait(false);

            Log.Debug("Broadcast {@currency} payment tx for swap {@swap}",
                      Currency,
                      swap.Id);

            var currency = Currencies.GetByName(swap.SoldCurrency);

            // broadcast payment transaction
            var broadcastResult = await currency.BlockchainApi
                                  .TryBroadcastAsync(swap.PaymentTx, cancellationToken : cancellationToken)
                                  .ConfigureAwait(false);

            if (broadcastResult.HasError)
            {
                Log.Error("Error while broadcast {@currency} transaction. Code: {@code}. Description: {@description}",
                          currency.Name,
                          broadcastResult.Error.Code,
                          broadcastResult.Error.Description);

                return;
            }

            var txId = broadcastResult.Value;

            swap.PaymentTxId = txId ?? throw new Exception("Transaction Id is null");
            swap.StateFlags |= SwapStateFlags.IsPaymentBroadcast;
            RaiseSwapUpdated(swap, SwapStateFlags.IsPaymentBroadcast);

            Log.Debug("{@currency} payment txId {@id} for swap {@swap}",
                      currency.Name,
                      txId,
                      swap.Id);

            // account new unconfirmed transaction
            await _account
            .UpsertTransactionAsync(
                tx : swap.PaymentTx,
                updateBalance : true,
                notifyIfUnconfirmed : false,
                cancellationToken : cancellationToken)
            .ConfigureAwait(false);

            // send payment txId to party
            SwapClient.SwapPaymentAsync(swap);

            await StartWaitForRedeemAsync(swap, cancellationToken)
            .ConfigureAwait(false);
        }
        public override async Task BroadcastPaymentAsync(ClientSwap swap)
        {
            if (swap.IsAcceptor &&
                (!swap.StateFlags.HasFlag(SwapStateFlags.HasPartyPayment) ||
                 !swap.StateFlags.HasFlag(SwapStateFlags.IsPartyPaymentConfirmed)))
            {
                Log.Debug("CounterParty is not ready to broadcast payment tx for swap {@swap}", swap.Id);

                return;
            }

            var lockTimeInSeconds = swap.IsInitiator
                ? DefaultInitiatorLockTimeInSeconds
                : DefaultAcceptorLockTimeInSeconds;

            await CreatePaymentAsync(swap, lockTimeInSeconds)
            .ConfigureAwait(false);

            Log.Debug("Broadcast payment tx for swap {@swap}", swap.Id);

            var currency = swap.SoldCurrency;

            // broadcast payment transaction
            var txId = await currency.BlockchainApi
                       .BroadcastAsync(swap.PaymentTx)
                       .ConfigureAwait(false);

            swap.PaymentTxId = txId ?? throw new Exception("Transaction Id is null");
            swap.SetPaymentBroadcast();
            RaiseSwapUpdated(swap, SwapStateFlags.IsPaymentBroadcast);

            Log.Debug("Payment txId {@id}", txId);

            // account new unconfirmed transaction
            await Account
            .UpsertTransactionAsync(
                tx : swap.PaymentTx,
                updateBalance : true,
                notifyIfUnconfirmed : false)
            .ConfigureAwait(false);

            // send payment txId to party
            SwapClient.SwapPaymentAsync(swap);

            if (swap.IsAcceptor)
            {
                var swapOutputs = ((IBitcoinBasedTransaction)swap.PaymentTx)
                                  .SwapOutputs()
                                  .ToList();

                if (swapOutputs.Count != 1)
                {
                    throw new InternalException(
                              code: Errors.SwapError,
                              description: "Payment tx must have only one swap output");
                }

                // track counter party payment spent event
                TaskPerformer.EnqueueTask(new BitcoinBasedOutputSpentTask
                {
                    Currency        = currency,
                    Swap            = swap,
                    OutputHash      = txId,
                    OutputIndex     = swapOutputs.First().Index,
                    Interval        = DefaultOutputSpentCheckInterval,
                    CompleteHandler = PaymentSpentEventHandler
                });
            }

            // track payment transaction confirmation
            TaskPerformer.EnqueueTask(new TransactionConfirmationCheckTask
            {
                Currency        = currency,
                Swap            = swap,
                TxId            = txId,
                Interval        = DefaultConfirmationCheckInterval,
                CompleteHandler = PaymentConfirmedEventHandler
            });
        }