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); }
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); }
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); } } }
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); }