public static async Task <TransferResult> ExchangeThrowFail(this ITransferService src, string assetId,
                                                                    string sourceAddress, string destAddress, decimal?amount = null)
        {
            TransferResult transferResult = await src.ExecuteAsync(assetId, sourceAddress, destAddress, amount);

            foreach (var transactionResult in transferResult.Transactions)
            {
                if (transactionResult.ErrorType == TransactionErrorType.NotEnoughFunds)
                {
                    throw new InsufficientFundsException(sourceAddress, assetId);
                }
            }

            if (!transferResult.HasSuccess())
            {
                throw new ExchangeOperationFailedException(transferResult.GetErrors());
            }

            if (transferResult.HasError())
            {
                throw new ExchangeOperationPartiallyFailedException(transferResult.GetErrors());
            }

            return(transferResult);
        }
 public static Task <TransferResult> ExecuteAsync(this ITransferService src, string assetId,
                                                  string sourceAddress, string destAddress, decimal?amount = null)
 {
     return(src.ExecuteAsync(new TransferCommand
     {
         AssetId = assetId,
         Amounts = new List <TransferAmount>
         {
             new TransferAmount
             {
                 Amount = amount,
                 Source = sourceAddress,
                 Destination = destAddress
             }
         }
     }));
 }
        public static async Task <TransferResult> SettleThrowFail(this ITransferService src, string assetId,
                                                                  string sourceAddress, string destAddress, decimal?amount = null)
        {
            TransferResult transferResult = await src.ExecuteAsync(assetId, sourceAddress, destAddress, amount);

            if (!transferResult.HasSuccess())
            {
                throw new SettlementOperationFailedException(transferResult.GetErrors());
            }

            if (transferResult.HasError())
            {
                throw new SettlementOperationPartiallyFailedException(transferResult.GetErrors());
            }

            return(transferResult);
        }
Example #4
0
        public async Task <RefundResult> ExecuteAsync(string merchantId, string paymentRequestId,
                                                      string destinationWalletAddress)
        {
            IPaymentRequest paymentRequest =
                await _paymentRequestService.GetAsync(merchantId, paymentRequestId);

            if (paymentRequest == null)
            {
                throw new RefundValidationException(RefundErrorType.PaymentRequestNotFound);
            }

            if (!paymentRequest.StatusValidForRefund())
            {
                throw new RefundValidationException(RefundErrorType.NotAllowedInStatus);
            }

            IEnumerable <IPaymentRequestTransaction> paymentTxs =
                (await _transactionsService.GetByWalletAsync(paymentRequest.WalletAddress)).Where(x => x.IsPayment()).ToList();

            if (!paymentTxs.Any())
            {
                throw new RefundValidationException(RefundErrorType.NoPaymentTransactions);
            }

            if (paymentTxs.MoreThanOne())
            {
                throw new RefundValidationException(RefundErrorType.MultitransactionNotSupported);
            }

            IPaymentRequestTransaction tx = paymentTxs.Single();

            bool isValidAddress = string.IsNullOrWhiteSpace(destinationWalletAddress) ||
                                  await _blockchainAddressValidator.Execute(destinationWalletAddress, tx.Blockchain);

            if (!isValidAddress)
            {
                throw new RefundValidationException(RefundErrorType.InvalidDestinationAddress);
            }

            if (!tx.SourceWalletAddresses.Any())
            {
                throw new RefundValidationException(RefundErrorType.InvalidDestinationAddress);
            }

            if (string.IsNullOrWhiteSpace(destinationWalletAddress))
            {
                if (tx.SourceWalletAddresses.MoreThanOne())
                {
                    throw new RefundValidationException(RefundErrorType.InvalidDestinationAddress);
                }
            }

            //validation finished, refund request accepted
            await _paymentRequestService.UpdateStatusAsync(paymentRequest.WalletAddress,
                                                           PaymentRequestStatusInfo.RefundInProgress());

            TransferResult transferResult;

            DateTime refundDueDate;

            try
            {
                TransferCommand refundTransferCommand = Mapper.Map <TransferCommand>(tx,
                                                                                     opts => opts.Items["destinationAddress"] = destinationWalletAddress);

                transferResult = await _transferService.ExecuteAsync(refundTransferCommand);

                refundDueDate = transferResult.Timestamp.Add(_refundExpirationPeriod);

                foreach (var transferResultTransaction in transferResult.Transactions)
                {
                    if (!string.IsNullOrEmpty(transferResultTransaction.Error))
                    {
                        await _log.WriteWarningAsync(nameof(RefundService), nameof(ExecuteAsync),
                                                     transferResultTransaction.ToJson(), "Transaction failed");

                        continue;
                    }

                    IPaymentRequestTransaction refundTransaction = await _transactionsService.CreateTransactionAsync(
                        new CreateTransactionCommand
                    {
                        Amount        = transferResultTransaction.Amount,
                        AssetId       = transferResultTransaction.AssetId,
                        Confirmations = 0,
                        Hash          = transferResultTransaction.Hash,
                        WalletAddress = paymentRequest.WalletAddress,
                        Type          = TransactionType.Refund,
                        Blockchain    = transferResult.Blockchain,
                        FirstSeen     = null,
                        DueDate       = refundDueDate,
                        TransferId    = transferResult.Id,
                        IdentityType  = transferResultTransaction.IdentityType,
                        Identity      = transferResultTransaction.Identity
                    });

                    await _transactionPublisher.PublishAsync(refundTransaction);
                }

                if (transferResult.Transactions.All(x => x.HasError))
                {
                    throw new RefundOperationFailedException {
                              TransferErrors = transferResult.Transactions.Select(x => x.Error)
                    }
                }
                ;

                IEnumerable <TransferTransactionResult> errorTransactions =
                    transferResult.Transactions.Where(x => x.HasError).ToList();

                if (errorTransactions.Any())
                {
                    throw new RefundOperationPartiallyFailedException(errorTransactions.Select(x => x.Error));
                }
            }
            catch (Exception)
            {
                await _paymentRequestService.UpdateStatusAsync(paymentRequest.WalletAddress,
                                                               PaymentRequestStatusInfo.Error(PaymentRequestProcessingError.UnknownRefund));

                throw;
            }

            return(await PrepareRefundResult(paymentRequest, transferResult, refundDueDate));
        }