private async Task ProcessIssue(CashInOutQueueMessage message)
        {
            var isClientTrusted = await _clientAccountClient.IsTrustedAsync(message.ClientId);

            var asset = await _assetsServiceWithCache.TryGetAssetAsync(message.AssetId);

            if (!isClientTrusted.Value && !asset.IsTrusted)
            {
                _log.Warning($"{nameof(CashInOutMessageProcessor)}:{nameof(ProcessIssue)}", "Client and asset are not trusted.", context: message.ToJson());
                return;
            }

            var walletCredentials = await _walletCredentialsRepository.GetAsync(message.ClientId);

            var amount        = message.Amount.ParseAnyDecimal();
            var transactionId = message.Id;
            var context       = await _transactionService.GetTransactionContext <IssueContextData>(transactionId);

            context.CashOperationId = transactionId;
            _cqrsEngine.SendCommand(new SaveIssueOperationStateCommand
            {
                Command = new IssueCommand
                {
                    TransactionId = Guid.Parse(transactionId),
                    Context       = context.ToJson(),
                    Amount        = Math.Abs(amount),
                    AssetId       = message.AssetId,
                    Multisig      = walletCredentials?.MultiSig
                },
                Context = context,
                Message = message
            }, BoundedContexts.TxHandler, BoundedContexts.Operations);
        }
        public async Task <CommandHandlingResult> Handle(ProcessLimitOrderCommand command, IEventPublisher eventPublisher)
        {
            var clientId = command.LimitOrder.Order.ClientId;

            if (!_trusted.ContainsKey(clientId))
            {
                _trusted[clientId] = (await _clientAccountClient.IsTrustedAsync(clientId)).Value;
            }

            var isTrustedClient = _trusted[clientId];

            var limitOrderExecutedEvent = new LimitOrderExecutedEvent
            {
                IsTrustedClient = isTrustedClient,
                LimitOrder      = command.LimitOrder
            };

            var tradesWerePerformed = command.LimitOrder.Trades != null && command.LimitOrder.Trades.Any();

            if (!isTrustedClient)
            {
                // need previous order state for not trusted clients
                var prevOrderState = await _limitOrdersRepository.GetOrderAsync(command.LimitOrder.Order.ClientId, command.LimitOrder.Order.Id);

                var isImmediateTrade = tradesWerePerformed && command.LimitOrder.Trades.First().Timestamp == command.LimitOrder.Order.Registered;
                limitOrderExecutedEvent.HasPrevOrderState   = prevOrderState != null && !isImmediateTrade;
                limitOrderExecutedEvent.PrevRemainingVolume = prevOrderState?.RemainingVolume;

                limitOrderExecutedEvent.Aggregated = AggregateSwaps(limitOrderExecutedEvent.LimitOrder.Trades);
            }

            await _limitOrdersRepository.CreateOrUpdateAsync(command.LimitOrder.Order);

            var status = (OrderStatus)Enum.Parse(typeof(OrderStatus), command.LimitOrder.Order.Status);

            // workaround: ME sends wrong status
            if (status == OrderStatus.Processing && !tradesWerePerformed)
            {
                status = OrderStatus.InOrderBook;
            }
            else if (status == OrderStatus.PartiallyMatched && !tradesWerePerformed)
            {
                status = OrderStatus.Placed;
            }

            if (status == OrderStatus.Processing ||
                status == OrderStatus.PartiallyMatched || // new version of Processing
                status == OrderStatus.Matched ||
                status == OrderStatus.Cancelled)
            {
                limitOrderExecutedEvent.Trades = await CreateTrades(command.LimitOrder);
            }

            eventPublisher.PublishEvent(limitOrderExecutedEvent);

            return(CommandHandlingResult.Ok());
        }
Beispiel #3
0
        public async Task <SwapOffchainContextData> FillTradeContext(SwapOffchainContextData context, TradeQueueItem.MarketOrder order, List <TradeQueueItem.TradeInfo> trades, string clientId)
        {
            context.Order        = order;
            context.Trades       = trades;
            context.ClientTrades = await _clientTradesFactory.Create(order, trades, clientId);

            context.IsTrustedClient = (await _clientAccountClient.IsTrustedAsync(clientId)).Value;
            context.Status          = OperationStatus.Matched;

            if (!context.IsTrustedClient)
            {
                var aggregatedTrades = await AggregateSwaps(trades);

                context.SellTransfer = aggregatedTrades.sellTransfer;
                context.BuyTransfer  = aggregatedTrades.buyTransfer;

                var operations = new[] { aggregatedTrades.sellTransfer, aggregatedTrades.buyTransfer };

                foreach (var operation in operations)
                {
                    var trade = context.ClientTrades.FirstOrDefault(x =>
                                                                    x.ClientId == clientId && x.AssetId == operation.Asset.Id &&
                                                                    Math.Abs(x.Amount - (double)operation.Amount) < LykkeConstants.Eps);

                    // find existed operation (which was inserted in LW after guarantee transfer)
                    var existed = context.Operations.FirstOrDefault(x => x.ClientId == clientId && x.AssetId == operation.Asset.Id);

                    if (existed != null)
                    {
                        existed.ClientTradeId = trade?.Id;
                        continue;
                    }

                    context.Operations.Add(new SwapOffchainContextData.Operation()
                    {
                        TransactionId = operation.TransferId,
                        Amount        = operation.Amount,
                        ClientId      = clientId,
                        AssetId       = operation.Asset.Id,
                        ClientTradeId = trade?.Id
                    });
                }
            }
            return(context);
        }
Beispiel #4
0
        public async Task <CommandHandlingResult> Handle(ProcessLimitOrderCommand command, IEventPublisher eventPublisher)
        {
            var sw = new Stopwatch();

            sw.Start();
            var stepWatch = new Stopwatch();

            stepWatch.Start();

            try
            {
                var clientId = command.LimitOrder.Order.ClientId;

                if (!_trusted.ContainsKey(clientId))
                {
                    _trusted[clientId] = (await _clientAccountClient.IsTrustedAsync(clientId)).Value;
                }

                _log.Info("LimitOrderProcessing", new { TxHandler = new { Step = "01. Check client account is trusted", Time = stepWatch.ElapsedMilliseconds } });
                stepWatch.Restart();

                var isTrustedClient = _trusted[clientId];

                var limitOrderExecutedEvent = new LimitOrderExecutedEvent
                {
                    IsTrustedClient = isTrustedClient,
                    LimitOrder      = command.LimitOrder
                };

                var tradesWerePerformed = command.LimitOrder.Trades != null && command.LimitOrder.Trades.Any();
                if (!isTrustedClient)
                {
                    // need previous order state for not trusted clients
                    var prevOrderState = await _limitOrdersRepository.GetOrderAsync(command.LimitOrder.Order.ClientId, command.LimitOrder.Order.Id);

                    var isImmediateTrade = tradesWerePerformed && command.LimitOrder.Trades.First().Timestamp == command.LimitOrder.Order.Registered;
                    limitOrderExecutedEvent.HasPrevOrderState   = prevOrderState != null && !isImmediateTrade;
                    limitOrderExecutedEvent.PrevRemainingVolume = prevOrderState?.RemainingVolume;

                    limitOrderExecutedEvent.Aggregated = AggregateSwaps(limitOrderExecutedEvent.LimitOrder.Trades);

                    _log.Info("LimitOrderProcessing", new { TxHandler = new { Step = "02. Get Previous order state for not trusted client", Time = stepWatch.ElapsedMilliseconds } });
                    stepWatch.Restart();
                }

                if (!isTrustedClient)
                {
                    await _limitOrdersRepository.CreateOrUpdateAsync(command.LimitOrder.Order);

                    _log.Info("LimitOrderProcessing", new { TxHandler = new { Step = "03. Upsert limit order for not trusted client", Time = stepWatch.ElapsedMilliseconds } });
                    stepWatch.Restart();
                }

                var status = (OrderStatus)Enum.Parse(typeof(OrderStatus), command.LimitOrder.Order.Status);

                // workaround: ME sends wrong status
                if (status == OrderStatus.Processing && !tradesWerePerformed)
                {
                    status = OrderStatus.InOrderBook;
                }
                else if (status == OrderStatus.PartiallyMatched && !tradesWerePerformed)
                {
                    status = OrderStatus.Placed;
                }

                if (status == OrderStatus.Processing ||
                    status == OrderStatus.PartiallyMatched ||  // new version of Processing
                    status == OrderStatus.Matched ||
                    status == OrderStatus.Cancelled)
                {
                    limitOrderExecutedEvent.Trades = await CreateTrades(command.LimitOrder);
                }

                _log.Info("LimitOrderProcessing", new { TxHandler = new { Step = "04. Create trades", Time = stepWatch.ElapsedMilliseconds } });
                stepWatch.Restart();

                eventPublisher.PublishEvent(limitOrderExecutedEvent);

                return(CommandHandlingResult.Ok());
            }
            finally
            {
                sw.Stop();
                _log.Info("Command execution time",
                          context: new { TxHandler = new { Handler = nameof(LimitOrderCommandHandler), Command = nameof(ProcessLimitOrderCommand),
                                                           Time    = sw.ElapsedMilliseconds } });
            }
        }