Example #1
0
        private async Task HandleAcceptAsync(Swap swap, Swap receivedSwap)
        {
            if (DateTime.UtcNow > swap.TimeStamp.ToUniversalTime() + DefaultCredentialsExchangeTimeout)
            {
                Log.Error("Handle accept after swap {@swap} timeout", swap.Id);

                swap.Cancel();
                RaiseSwapUpdated(swap, SwapStateFlags.IsCanceled);

                return;
            }

            // check party requisites
            if (receivedSwap.PartyAddress == null)
            {
                throw new InternalException(
                          code: Errors.InvalidWallets,
                          description: $"Incorrect party address for swap {swap.Id}");
            }

            //if (IsCriminal(clientSwap.PartyAddress))
            //    throw new InternalException(
            //        code: Errors.IsCriminalWallet,
            //        description: $"Party wallet is criminal for swap {swap.Id}");

            if (receivedSwap.RewardForRedeem < 0)
            {
                throw new InternalException(
                          code: Errors.InvalidRewardForRedeem,
                          description: $"Incorrect reward for redeem for swap {swap.Id}");
            }

            swap.PartyAddress         = receivedSwap.PartyAddress;
            swap.PartyRewardForRedeem = receivedSwap.PartyRewardForRedeem;
            RaiseSwapUpdated(swap, SwapStateFlags.Empty);

            // broadcast initiator payment
            await GetCurrencySwap(swap.SoldCurrency)
            .PayAsync(swap)
            .ConfigureAwait(false);

            await GetCurrencySwap(swap.PurchasedCurrency)
            .StartPartyPaymentControlAsync(swap)
            .ConfigureAwait(false);
        }
Example #2
0
        protected bool CheckPayRelevance(Swap swap)
        {
            if (swap.IsAcceptor)
            {
                var acceptorRefundTimeUtc = swap.TimeStamp
                                            .ToUniversalTime()
                                            .AddSeconds(DefaultAcceptorLockTimeInSeconds);

                var paymentDeadline = acceptorRefundTimeUtc - PaymentTimeReserve;

                if (DateTime.UtcNow > paymentDeadline)
                {
                    Log.Error("Payment deadline reached for swap {@swap}", swap.Id);

                    swap.Cancel();
                    RaiseSwapUpdated(swap, SwapStateFlags.IsCanceled);

                    return(false);
                }
            }

            return(true);
        }
Example #3
0
        private async Task RestoreSwapAsync(
            Swap swap,
            CancellationToken cancellationToken = default)
        {
            if (swap.StateFlags.HasFlag(SwapStateFlags.IsPaymentBroadcast))
            {
                bool confirmed = true;

                if (!swap.StateFlags.HasFlag(SwapStateFlags.IsPaymentConfirmed) &&
                    DateTime.UtcNow > swap.TimeStamp.ToUniversalTime() + DefaultMaxPaymentTimeout)
                {
                    var result = await swap.PaymentTx
                                 .IsTransactionConfirmed(
                        cancellationToken : cancellationToken)
                                 .ConfigureAwait(false);

                    if (result.HasError || !result.Value.IsConfirmed)
                    {
                        confirmed = false;

                        Log.Debug("Swap {@id} canceled in RestoreSwapAsync. Timeout reached.", swap.Id);

                        swap.Cancel();
                        RaiseSwapUpdated(swap, SwapStateFlags.IsCanceled);
                    }
                }

                if (confirmed)
                {
                    await GetCurrencySwap(swap.SoldCurrency)
                    .StartWaitForRedeemAsync(swap, cancellationToken)
                    .ConfigureAwait(false);

                    if (swap.IsInitiator)
                    {
                        // check acceptor payment confirmation
                        await GetCurrencySwap(swap.PurchasedCurrency)
                        .StartPartyPaymentControlAsync(swap, cancellationToken)
                        .ConfigureAwait(false);
                    }
                }
            }
            else
            {
                if (DateTime.UtcNow < swap.TimeStamp.ToUniversalTime() + DefaultMaxSwapTimeout)
                {
                    if (swap.IsInitiator)
                    {
                        // todo: reinitiate swap
                    }
                    else
                    {
                        // todo: reaccept swap
                    }
                }
                else
                {
                    swap.Cancel();
                    RaiseSwapUpdated(swap, SwapStateFlags.IsCanceled);
                }
            }
        }
Example #4
0
        private async Task HandleInitiateAsync(Swap swap, Swap receivedSwap)
        {
            if (DateTime.UtcNow > swap.TimeStamp.ToUniversalTime() + DefaultCredentialsExchangeTimeout)
            {
                Log.Error("Handle initiate after swap {@swap} timeout", swap.Id);

                swap.Cancel();
                RaiseSwapUpdated(swap, SwapStateFlags.IsCanceled);

                return;
            }

            if (swap.SecretHash != null)
            {
                if (!swap.SecretHash.SequenceEqual(receivedSwap.SecretHash))
                {
                    throw new InternalException(
                              code: Errors.InvalidSecretHash,
                              description: $"Secret hash does not match the one already received for swap {swap.Id}");
                }
                return;
            }

            if (receivedSwap.SecretHash == null || receivedSwap.SecretHash.Length != CurrencySwap.DefaultSecretHashSize)
            {
                throw new InternalException(
                          code: Errors.InvalidSecretHash,
                          description: $"Incorrect secret hash length for swap {swap.Id}");
            }

            Log.Debug("Secret hash {@hash} successfully received", receivedSwap.SecretHash.ToHexString());

            swap.SecretHash = receivedSwap.SecretHash;
            RaiseSwapUpdated(swap, SwapStateFlags.HasSecretHash);

            // check party requisites
            if (receivedSwap.PartyAddress == null)
            {
                throw new InternalException(
                          code: Errors.InvalidWallets,
                          description: $"Incorrect party address for swap {swap.Id}");
            }

            //if (IsCriminal(clientSwap.PartyAddress))
            //    throw new InternalException(
            //        code: Errors.IsCriminalWallet,
            //        description: $"Party wallet is criminal for swap {swap.Id}");

            if (receivedSwap.RewardForRedeem < 0)
            {
                throw new InternalException(
                          code: Errors.InvalidRewardForRedeem,
                          description: $"Incorrect reward for redeem for swap {swap.Id}");
            }

            swap.PartyAddress         = receivedSwap.PartyAddress;
            swap.PartyRewardForRedeem = receivedSwap.PartyRewardForRedeem;

            // create self requisites
            var walletToAddress = (await _account
                                   .GetRedeemAddressAsync(swap.PurchasedCurrency)
                                   .ConfigureAwait(false));

            swap.ToAddress = walletToAddress.Address;

            swap.RewardForRedeem = await GetRewardForRedeemAsync(walletToAddress)
                                   .ConfigureAwait(false);

            RaiseSwapUpdated(swap, SwapStateFlags.Empty);

            // send "accept" to other side
            _swapClient.SwapAcceptAsync(swap);

            await GetCurrencySwap(swap.PurchasedCurrency)
            .StartPartyPaymentControlAsync(swap)
            .ConfigureAwait(false);
        }