Exemple #1
0
        public async Task <CommandHandlingResult> Handle(CreateTradeCommand command, IEventPublisher eventPublisher)
        {
            var queueMessage = command.QueueMessage;

            var clientId = queueMessage.Order.ClientId;

            if (!queueMessage.Order.Status.Equals("matched", StringComparison.OrdinalIgnoreCase))
            {
                _log.Info($"{nameof(TradeSaga)}:{nameof(TradeCommandHandler)}", "Message processing being aborted, due to order status is not matched",
                          queueMessage.ToJson());

                return(CommandHandlingResult.Ok());
            }

            var context = await _transactionService.GetTransactionContext <SwapOffchainContextData>(queueMessage.Order.Id) ?? new SwapOffchainContextData();

            await _contextFactory.FillTradeContext(context, queueMessage.Order, queueMessage.Trades, clientId);

            ChaosKitty.Meow();

            await _transactionService.SetTransactionContext(queueMessage.Order.Id, context);

            ChaosKitty.Meow();

            eventPublisher.PublishEvent(new TradeCreatedEvent
            {
                OrderId         = queueMessage.Order.Id,
                IsTrustedClient = context.IsTrustedClient,
                MarketOrder     = context.Order,
                ClientTrades    = context.ClientTrades,
                QueueMessage    = queueMessage
            });

            return(CommandHandlingResult.Ok());
        }
Exemple #2
0
        public async Task <CommandHandlingResult> Handle(UpdateLimitOrdersCountCommand command, IEventPublisher eventPublisher)
        {
            var sw = new Stopwatch();

            sw.Start();

            try
            {
                var activeLimitOrdersCount = await _limitOrdersRepository.GetActiveOrdersCountAsync(command.ClientId);

                await _clientCacheRepository.UpdateLimitOrdersCount(command.ClientId, activeLimitOrdersCount);

                ChaosKitty.Meow();

                _log.Info(nameof(UpdateLimitOrdersCountCommand), $"Client {command.ClientId}. Limit orders cache updated: {activeLimitOrdersCount} active orders");

                return(CommandHandlingResult.Ok());
            }
            finally
            {
                sw.Stop();
                _log.Info("Command execution time",
                          context: new { TxHandler = new { Handler = nameof(HistoryCommandHandler), Command = nameof(UpdateLimitOrdersCountCommand),
                                                           Time    = sw.ElapsedMilliseconds } });
            }
        }
        private async Task Handle(TransactionProcessedEvent evt, ICommandSender sender)
        {
            ChaosKitty.Meow();

            var clientAcc = await _clientAccountClient.GetByIdAsync(evt.ClientId);

            var sendEmailCommand = new SendNoRefundDepositDoneMailCommand
            {
                Email   = clientAcc.Email,
                Amount  = evt.Amount,
                AssetId = evt.Asset.Id
            };

            sender.SendCommand(sendEmailCommand, "email");

            ChaosKitty.Meow();

            var pushSettings = await _clientAccountClient.GetPushNotificationAsync(evt.ClientId);

            if (pushSettings.Enabled)
            {
                var sendNotificationCommand = new SendNotificationCommand
                {
                    NotificationId = clientAcc.NotificationsId,
                    Type           = NotificationType.TransactionConfirmed,
                    Message        = string.Format(TextResources.CashInSuccessText, new decimal(evt.Amount).TruncateDecimalPlaces(evt.Asset.Accuracy), evt.Asset.Id)
                };
                sender.SendCommand(sendNotificationCommand, "notifications");
            }
        }
        public async Task <CommandHandlingResult> Handle(ProcessCashInCommand command, IEventPublisher eventPublisher)
        {
            var id          = command.CommandId;
            var asset       = command.Asset;
            var amount      = command.Amount;
            var transaction = command.Transaction;

            ChaosKitty.Meow();

            var responseModel = await _matchingEngineClient.CashInOutAsync(id, transaction.ClientId, asset.Id, amount.TruncateDecimalPlaces(asset.Accuracy));

            if (responseModel.Status != MeStatusCodes.Ok && responseModel.Status != MeStatusCodes.AlreadyProcessed && responseModel.Status != MeStatusCodes.Duplicate)
            {
                _log.WriteInfo(nameof(ProcessCashInCommand), command, responseModel.ToJson());
                throw new ProcessingException(responseModel.ToJson());
            }

            ChaosKitty.Meow();

            eventPublisher.PublishEvent(new TransactionProcessedEvent {
                ClientId = command.Transaction.ClientId, Asset = command.Asset, Amount = command.Amount
            });

            return(CommandHandlingResult.Ok());
        }
Exemple #5
0
        public async Task <CommandHandlingResult> Handle(Commands.SegwitTransferCommand command)
        {
            var sw = new Stopwatch();

            sw.Start();

            try
            {
                var response = await _bitcoinApiClient.SegwitTransfer(Guid.Parse(command.Id), command.Address);

                if (response.HasError && response.Error.ErrorCode != ErrorCode.DuplicateTransactionId)
                {
                    _log.Error($"{nameof(BitcoinCommandHandler)}:{nameof(Commands.SegwitTransferCommand)}", new Exception(response.ToJson()), context: command.ToJson());
                    return(CommandHandlingResult.Fail(_retryTimeout));
                }

                ChaosKitty.Meow();

                return(CommandHandlingResult.Ok());
            }
            finally
            {
                sw.Stop();
                _log.Info("Command execution time",
                          context: new { TxHandler = new { Handler = nameof(BitcoinCommandHandler), Command = nameof(Commands.SegwitTransferCommand),
                                                           Time    = sw.ElapsedMilliseconds } });
            }
        }
        public async Task <CommandHandlingResult> Handle(CreateOffchainCashoutRequestCommand command, IEventPublisher eventPublisher)
        {
            var sw = new Stopwatch();

            sw.Start();

            try
            {
                await _offchainRequestService.CreateOffchainRequestAndNotify(
                    transactionId : command.Id,
                    clientId : command.ClientId,
                    assetId : command.AssetId,
                    amount : command.Amount,
                    orderId : null,
                    type : OffchainTransferType.TrustedCashout);

                ChaosKitty.Meow();

                return(CommandHandlingResult.Ok());
            }
            finally
            {
                sw.Stop();
                _log.Info("Command execution time",
                          context: new { TxHandler = new { Handler = nameof(OffchainCommandHandler), Command = nameof(CreateOffchainCashoutRequestCommand),
                                                           Time    = sw.ElapsedMilliseconds } });
            }
        }
        public async Task <CommandHandlingResult> Handle(SaveEthInHistoryCommand command, IEventPublisher eventPublisher)
        {
            var sw = new Stopwatch();

            sw.Start();

            try
            {
                var cashinId      = command.CashinOperationId.ToString("N");
                var clientId      = command.ClientId;
                var hash          = command.TransactionHash;
                var amount        = command.Amount;
                var clientAddress = command.ClientAddress;

                await _cashOperationsRepositoryClient.RegisterAsync(new CashInOutOperation
                {
                    Id             = cashinId,
                    ClientId       = clientId.ToString(),
                    AssetId        = command.AssetId,
                    Amount         = (double)amount,
                    BlockChainHash = hash,
                    DateTime       = DateTime.UtcNow,
                    AddressTo      = clientAddress,
                    State          = TransactionStates.SettledOnchain
                });

                ChaosKitty.Meow();

                var clientAcc = await _clientAccountClient.GetByIdAsync(clientId.ToString());

                var clientEmail = await _personalDataService.GetEmailAsync(clientId.ToString());

                await _srvEmailsFacade.SendNoRefundDepositDoneMail(clientAcc.PartnerId, clientEmail, amount,
                                                                   command.AssetId);

                await _paymentTransactionsRepository.SetStatus(hash, PaymentStatus.NotifyProcessed);

                ChaosKitty.Meow();

                eventPublisher.PublishEvent(new EthCashinSavedInHistoryEvent()
                {
                    TransactionHash = hash
                });

                return(CommandHandlingResult.Ok());
            }
            catch (Exception e)
            {
                _log.Error(nameof(SaveEthInHistoryCommand), e, context: command);
                throw;
            }
            finally
            {
                sw.Stop();
                _log.Info("Command execution time",
                          context: new { TxHandler = new { Handler = nameof(EthereumCoreCommandHandler), Command = nameof(SaveEthInHistoryCommand),
                                                           Time    = sw.ElapsedMilliseconds } });
            }
        }
        public async Task <CommandHandlingResult> Handle(SendNotificationCommand command)
        {
            ChaosKitty.Meow();

            await _appNotifications.SendTextNotificationAsync(new [] { command.NotificationId }, command.Type, command.Message);

            return(CommandHandlingResult.Ok());
        }
Exemple #9
0
        public async Task <CommandHandlingResult> Handle(CreateTransactionCommand command)
        {
            await _transactionsRepository.TryCreateAsync(command.OrderId, BitCoinCommands.SwapOffchain, "", null, "");

            ChaosKitty.Meow();

            return(CommandHandlingResult.Ok());
        }
        public async Task <CommandHandlingResult> Handle(SavePostponedCashInCommand command)
        {
            await _postponedCashInRepository.SaveAsync(command.TransactionHash);

            ChaosKitty.Meow();

            return(CommandHandlingResult.Ok());
        }
Exemple #11
0
        public async Task Handle(TradeCreatedEvent evt)
        {
            if (evt.ClientTrades != null)
            {
                await _clientTradesRepository.SaveAsync(evt.ClientTrades);
            }

            ChaosKitty.Meow();
        }
Exemple #12
0
        public async Task Handle(TransferProcessedEvent evt)
        {
            ChaosKitty.Meow();

            await _paymentTransactionEventsLog.WriteAsync(PaymentTransactionLogEvent.Create(
                                                              transactionId: evt.TransferId,
                                                              techData: "",
                                                              message: "Confirmed",
                                                              who: "Tx Detector"));
        }
Exemple #13
0
        public async Task <OperationEstimationResult> EstimateCashoutGas(Guid id, string coinAdapterAddress, string fromAddress, string toAddress, BigInteger amount, string sign)
        {
            var blackListedAddress = await _blackListAddressesRepository.GetAsync(toAddress);

            var whiteListedAddress = await _whiteListAddressesRepository.GetAsync(toAddress);

            if (blackListedAddress != null && whiteListedAddress == null)
            {
                return(new OperationEstimationResult()
                {
                    GasAmount = Constants.GasForCoinTransaction,
                    IsAllowed = false
                });
            }

            //It is ok.
            if (ChaosKitty.MeowButLogically())
            {
                return(new OperationEstimationResult()
                {
                    GasAmount = 50000,
                    IsAllowed = true
                });
            }

            var coinAFromDb = await GetCoinWithCheck(coinAdapterAddress);

            if (string.IsNullOrEmpty(sign))
            {
                sign = await GetSign(id, coinAdapterAddress, fromAddress, toAddress, amount);
            }

            ThrowOnWrongSignature(id, coinAdapterAddress, fromAddress, toAddress, amount, sign);

            var contract    = _web3.Eth.GetContract(_settings.MainExchangeContract.Abi, _settings.MainExchangeContract.Address);
            var cashout     = contract.GetFunction("cashout");
            var convertedId = EthUtils.GuidToBigInteger(id);
            //ACTION
            var estimatedGasForOperation = await cashout.EstimateGasAsync(_settings.EthereumMainAccount,
                                                                          new HexBigInteger(Constants.GasForCoinTransaction), new HexBigInteger(0),
                                                                          convertedId,
                                                                          _addressUtil.ConvertToChecksumAddress(coinAFromDb.AdapterAddress),
                                                                          fromAddress,
                                                                          toAddress,
                                                                          amount,
                                                                          sign.HexToByteArray(),
                                                                          new byte[0]);

            return(new OperationEstimationResult()
            {
                GasAmount = estimatedGasForOperation.Value,
                IsAllowed = estimatedGasForOperation.Value < Constants.GasForCoinTransaction
            });
        }
Exemple #14
0
        private async Task RegisterOperation(CashInOutOperation operation)
        {
            var operationId = await _cashOperationsRepositoryClient.RegisterAsync(operation);

            if (operationId != operation.Id)
            {
                _log.Warning($"Unexpected response from Operations Service: {operationId}",
                             context: operation.ToJson());
            }

            ChaosKitty.Meow();
        }
        public async Task <CommandHandlingResult> Handle(UpdateLimitOrdersCountCommand command, IEventPublisher eventPublisher)
        {
            var activeLimitOrdersCount = await _limitOrdersRepository.GetActiveOrdersCountAsync(command.ClientId);

            await _clientCacheRepository.UpdateLimitOrdersCount(command.ClientId, activeLimitOrdersCount);

            ChaosKitty.Meow();

            _log.Info(nameof(UpdateLimitOrdersCountCommand), $"Client {command.ClientId}. Limit orders cache updated: {activeLimitOrdersCount} active orders");

            return(CommandHandlingResult.Ok());
        }
Exemple #16
0
        private async Task RegisterOperation(TransferEvent operation)
        {
            var response = await _transferEventsRepositoryClient.RegisterAsync(operation);

            if (response.Id != operation.Id)
            {
                _log.Warning($"Unexpected response from Operations Service: {response.ToJson()}",
                             context: operation.ToJson());
            }

            ChaosKitty.Meow();
        }
        private async Task SaveState(BaseCommand command, BaseContextData context)
        {
            var transactionId = command.TransactionId.ToString();
            var requestData   = command.ToJson();

            await _transactionsRepository.UpdateAsync(transactionId, requestData, null, "");

            ChaosKitty.Meow();

            await _transactionService.SetTransactionContext(transactionId, context);

            ChaosKitty.Meow();
        }
        public async Task <CommandHandlingResult> Handle(SendNoRefundDepositDoneMailCommand command)
        {
            ChaosKitty.Meow();

            var content = new NoRefundDepositDoneData
            {
                Amount     = command.Amount,
                AssetBcnId = command.AssetId
            };
            await _emailSender.SendEmailAsync(command.Email, content);

            return(CommandHandlingResult.Ok());
        }
Exemple #19
0
        public async Task <CommandHandlingResult> Handle(ProcessTransferCommand command, IEventPublisher eventPublisher)
        {
            ChaosKitty.Meow();

            if (await _paymentTransactionsRepository.SetStatus(command.TransferId, PaymentStatus.NotifyProcessed) != null)
            {
                eventPublisher.PublishEvent(new TransferProcessedEvent {
                    TransferId = command.TransferId
                });
            }

            return(CommandHandlingResult.Ok());
        }
Exemple #20
0
        private async Task ProcessOutcomeOperation(ProcessEthCoinEventCommand queueMessage)
        {
            var transferTx = await _ethereumTransactionRequestRepository.GetAsync(Guid.Parse(queueMessage.OperationId));

            CashOutContextData context = await _transactionService.GetTransactionContext <CashOutContextData>(queueMessage.OperationId);

            if (transferTx != null)
            {
                switch (transferTx.OperationType)
                {
                case OperationType.CashOut:
                    await SetCashoutHashes(transferTx, queueMessage.TransactionHash);

                    break;

                case OperationType.Trade:
                    await SetTradeHashes(transferTx, queueMessage.TransactionHash);

                    break;

                case OperationType.TransferToTrusted:
                case OperationType.TransferFromTrusted:
                    await SetTransferHashes(transferTx, queueMessage.TransactionHash);

                    break;
                }

                ChaosKitty.Meow();

                return;
            }

            if (context == null)
            {
                return;
            }

            string clientId        = context.ClientId;
            string hash            = queueMessage.TransactionHash;
            string cashOperationId = context.CashOperationId;

            var clientAcc = await _clientAccountClient.GetByIdAsync(clientId);

            var clientEmail = await _personalDataService.GetEmailAsync(clientId);

            await _cashOperationsRepositoryClient.UpdateBlockchainHashAsync(clientId, cashOperationId, hash);

            await _srvEmailsFacade.SendNoRefundOCashOutMail(clientAcc.PartnerId, clientEmail, context.Amount, context.AssetId, hash);

            ChaosKitty.Meow();
        }
        public async Task <CommandHandlingResult> Handle(CreateOffchainCashoutRequestCommand command, IEventPublisher eventPublisher)
        {
            await _offchainRequestService.CreateOffchainRequestAndNotify(
                transactionId : command.Id,
                clientId : command.ClientId,
                assetId : command.AssetId,
                amount : command.Amount,
                orderId : null,
                type : OffchainTransferType.TrustedCashout);

            ChaosKitty.Meow();

            return(CommandHandlingResult.Ok());
        }
        public async Task <CommandHandlingResult> Handle(Commands.SegwitTransferCommand command)
        {
            var response = await _bitcoinApiClient.SegwitTransfer(Guid.Parse(command.Id), command.Address);

            if (response.HasError && response.Error.ErrorCode != ErrorCode.DuplicateTransactionId)
            {
                _log.Error($"{nameof(BitcoinCommandHandler)}:{nameof(Commands.SegwitTransferCommand)}", new Exception(response.ToJson()), context: command.ToJson());
                return(CommandHandlingResult.Fail(_retryTimeout));
            }

            ChaosKitty.Meow();

            return(CommandHandlingResult.Ok());
        }
        public async Task Handle(LimitOrderExecutedEvent evt, ICommandSender commandSender)
        {
            if (evt.IsTrustedClient)
            {
                return;
            }

            ChaosKitty.Meow();

            var cmd = new UpdateLimitOrdersCountCommand
            {
                ClientId        = evt.LimitOrder.Order.ClientId,
                IsTrustedClient = evt.IsTrustedClient
            };

            commandSender.SendCommand(cmd, "operations-history");
        }
        public async Task <CommandHandlingResult> Handle(RegisterCashInOutCommand command, IEventPublisher eventPublisher)
        {
            var id          = command.CommandId;
            var asset       = command.Asset;
            var amount      = command.Amount;
            var transaction = command.Transaction;

            ChaosKitty.Meow();

            try
            {
                await _cashOperationsRepositoryClient.RegisterAsync(new CashInOutOperation
                {
                    Id             = id,
                    ClientId       = transaction.ClientId,
                    Multisig       = transaction.Multisig,
                    AssetId        = asset.Id,
                    Amount         = amount,
                    BlockChainHash = transaction.Hash,
                    DateTime       = DateTime.UtcNow,
                    AddressTo      = transaction.Multisig,
                    State          = TransactionStates.SettledOnchain
                });
            }
            catch (HttpOperationException)
            {
                var persistedOperation = await _cashOperationsRepositoryClient.GetAsync(transaction.ClientId, id);

                if (persistedOperation == null)
                {
                    throw;
                }
                // else assuming that operation was correctly persisted before
            }

            eventPublisher.PublishEvent(new CashInOutOperationRegisteredEvent
            {
                CommandId   = command.CommandId,
                Asset       = command.Asset,
                Amount      = command.Amount,
                Transaction = command.Transaction
            });

            return(CommandHandlingResult.Ok());
        }
        public async Task <CommandHandlingResult> Handle(RegisterBitcoinCashInCommand command, IEventPublisher eventPublisher)
        {
            var id          = command.CommandId;
            var transaction = command.Transaction;

            ChaosKitty.Meow();

            await _bitcoinCashinRepository.InsertOrReplaceAsync(id, transaction.ClientId, transaction.Multisig, transaction.Hash, transaction.IsSegwit);

            eventPublisher.PublishEvent(new BitcoinCashInRegisteredEvent
            {
                CommandId   = command.CommandId,
                Asset       = command.Asset,
                Amount      = command.Amount,
                Transaction = command.Transaction
            });

            return(CommandHandlingResult.Ok());
        }
        public async Task ProcessMessage(CashInOutQueueMessage message)
        {
            _log.Info(message: "Processing message", message.ToJson());

            ChaosKitty.Meow();

            var transaction = await _transactionsRepository.FindByTransactionIdAsync(message.Id);

            if (transaction == null)
            {
                if (_cashOperationsRepositoryClient.GetAsync(message.ClientId, message.Id) == null)
                {
                    _log.Warning($"{nameof(CashInOutQueue)}:{nameof(CashInOutQueueMessage)}", "unknown transaction", context: message.ToJson());
                    return;
                }

                await ProcessExternalCashin(message);
            }
            else
            {
                switch (transaction.CommandType)
                {
                case BitCoinCommands.CashIn:
                case BitCoinCommands.Issue:
                    await ProcessIssue(message);

                    break;

                case BitCoinCommands.CashOut:
                    await ProcessCashOut(message);

                    break;

                case BitCoinCommands.ManualUpdate:
                    ProcessManualUpdate(message);
                    break;

                default:
                    _log.Warning($"{nameof(CashInOutQueue)}:{nameof(CashInOutQueueMessage)}", $"Unknown command type (value = [{transaction.CommandType}])", context: message.ToJson());
                    break;
                }
            }
        }
Exemple #27
0
        public async Task <CommandHandlingResult> Handle(CreateTransactionCommand command)
        {
            var sw = new Stopwatch();

            sw.Start();

            try
            {
                await _transactionsRepository.TryCreateAsync(command.OrderId, BitCoinCommands.SwapOffchain, "", null, "");

                ChaosKitty.Meow();

                return(CommandHandlingResult.Ok());
            }
            finally
            {
                sw.Stop();
                _log.Info("Command execution time",
                          context: new { TxHandler = new { Handler = nameof(TradeCommandHandler), Command = nameof(CreateTransactionCommand),
                                                           Time    = sw.ElapsedMilliseconds } });
            }
        }
Exemple #28
0
        // entry point
        public async Task <CommandHandlingResult> Handle(ProcessTransactionCommand command, IEventPublisher eventPublisher)
        {
            var confirmations = (await _qBitNinjaApiCaller.GetTransaction(command.TransactionHash))?.Block?.Confirmations;

            var isConfirmed = confirmations >= _settings.TxDetectorConfirmationsLimit;

            if (!isConfirmed)
            {
                //put back if not confirmed yet
                return(new CommandHandlingResult {
                    Retry = true, RetryDelay = (long)RetryTimeoutForTransactionConfirmations.TotalMilliseconds
                });
            }

            ChaosKitty.Meow();

            var hash = command.TransactionHash;
            var balanceChangeTransactions = await _balanceChangeTransactionsRepository.GetAsync(hash);

            foreach (var tx in balanceChangeTransactions)
            {
                var alreadyProcessed = !await _confirmedTransactionsRepository.SaveConfirmedIfNotExist(hash, tx.ClientId);

                if (alreadyProcessed)
                {
                    _log.WriteInfo(nameof(ProcessTransactionCommand), command,
                                   $"Transaction with hash {hash} for client {tx.ClientId} is already processed; ignoring it.");
                    continue;
                }

                eventPublisher.PublishEvent(new ConfirmationSavedEvent {
                    TransactionHash = hash, ClientId = tx.ClientId, Multisig = tx.Multisig
                });
            }
            return(CommandHandlingResult.Ok());
        }
Exemple #29
0
        //TODO: Split wth the help of the process management
        private async Task ProcessFailedCashout(ProcessEthCoinEventCommand queueMessage)
        {
            CashOutContextData context = await _transactionService.GetTransactionContext <CashOutContextData>(queueMessage.OperationId);

            if (context != null)
            {
                string transactionHandlerUserId = "auto redeem";
                string clientId        = context.ClientId;
                string hash            = queueMessage.TransactionHash;
                string cashOperationId = context.CashOperationId;
                string assetId         = context.AssetId;
                var    amount          = context.Amount;

                try
                {
                    ChaosKitty.Meow();

                    var asset = await _assetsService.AssetGetAsync(assetId);

                    await _cashOperationsRepositoryClient.UpdateBlockchainHashAsync(clientId, cashOperationId, hash);

                    var pt = await _paymentTransactionsRepository.TryCreateAsync(PaymentTransaction.Create(hash,
                                                                                                           CashInPaymentSystem.Ethereum, clientId, (double)amount,
                                                                                                           asset.DisplayId ?? asset.Id, status: PaymentStatus.Processing));

                    if (pt == null)
                    {
                        _log.Warning($"{nameof(EthereumCoreCommandHandler)}:{nameof(ProcessFailedCashout)}", "Transaction already handled", context: hash);
                        return; //if was handled previously
                    }

                    ChaosKitty.Meow();

                    var sign        = "+";
                    var commentText =
                        $"Balance Update: {sign}{amount} {asset.Name}. Cashout failed: {hash} {queueMessage.OperationId}";

                    var newComment = new ClientComment
                    {
                        ClientId  = clientId,
                        Comment   = commentText,
                        CreatedAt = DateTime.UtcNow,
                        FullName  = "Lykke.Job.TransactionHandler",
                        UserId    = transactionHandlerUserId
                    };

                    var exResult = await _exchangeOperationsServiceClient.ExchangeOperations.ManualCashInAsync(
                        new ManualCashInRequestModel
                    {
                        ClientId = clientId,
                        AssetId  = assetId,
                        Amount   = (double)amount,
                        UserId   = "auto redeem",
                        Comment  = commentText,
                    });

                    if (!exResult.IsOk())
                    {
                        _log.Warning($"{nameof(EthereumCoreCommandHandler)}:{nameof(ProcessFailedCashout)}",
                                     "ME operation failed",
                                     context: new {
                            ExchangeServiceResponse = exResult,
                            QueueMessage            = queueMessage
                        }.ToJson());
                    }

                    await _clientCommentsRepository.AddClientCommentAsync(newComment);

                    await _paymentTransactionsRepository.SetStatus(hash, PaymentStatus.NotifyProcessed);

                    ChaosKitty.Meow();
                }
                catch (Exception e)
                {
                    _log.Error($"{nameof(EthereumCoreCommandHandler)}:{nameof(ProcessFailedCashout)}", e, context: queueMessage.ToJson());
                    throw;
                }
            }
            else
            {
                _log.Warning("Can't get a context", context: queueMessage.ToJson());
            }
        }
Exemple #30
0
        public async Task <CommandHandlingResult> Handle(EnrollEthCashinToMatchingEngineCommand command, IEventPublisher eventPublisher)
        {
            try
            {
                var cashinId = command.CashinOperationId.ToString("N");
                var clientId = command.ClientId;
                var hash     = command.TransactionHash;
                var amount   = command.Amount;
                var asset    = await _assetsServiceWithCache.TryGetAssetAsync(command.AssetId);

                var createPendingActions = command.CreatePendingActions;
                var paymentTransaction   = PaymentTransaction.Create(hash,
                                                                     CashInPaymentSystem.Ethereum, clientId.ToString(), (double)amount,
                                                                     asset.DisplayId ?? asset.Id, status: PaymentStatus.Processing);

                var exists = await _paymentTransactionsRepository.CheckExistsAsync(paymentTransaction);

                if (exists)
                {
                    _log.Warning(command.TransactionHash ?? "Empty", $"Transaction already handled {hash}",
                                 context: command);

                    return(CommandHandlingResult.Ok());
                }

                if (createPendingActions && asset.IsTrusted)
                {
                    await _ethererumPendingActionsRepository.CreateAsync(clientId.ToString(), Guid.NewGuid().ToString());
                }

                ChaosKitty.Meow();

                MeResponseModel result = null;

                await ExecuteWithTimeoutHelper.ExecuteWithTimeoutAsync(async() =>
                {
                    result = await _matchingEngineClient.CashInOutAsync(cashinId, clientId.ToString(), asset.Id, (double)amount);
                }, 5 * 60 * 1000);     // 5 min in ms

                if (result == null ||
                    (result.Status != MeStatusCodes.Ok &&
                     result.Status != MeStatusCodes.Duplicate))
                {
                    _log.Warning(command.TransactionHash ?? "Empty", "ME error", context: result);

                    return(CommandHandlingResult.Fail(TimeSpan.FromMinutes(1)));
                }

                eventPublisher.PublishEvent(new EthCashinEnrolledToMatchingEngineEvent()
                {
                    TransactionHash = hash,
                });

                ChaosKitty.Meow();

                await _paymentTransactionsRepository.TryCreateAsync(paymentTransaction);

                return(CommandHandlingResult.Ok());
            }
            catch (Exception e)
            {
                _log.Error(nameof(EnrollEthCashinToMatchingEngineCommand), e, context: command);
                throw;
            }
        }