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");
            }
        }
Exemple #2
0
        private void RequestPrice(ICommandSender sender, IOperationExecutionInfo <SpecialLiquidationOperationData>
                                  executionInfo)
        {
            //hack, requested by the bank
            var positionsVolume = executionInfo.Data.Volume != 0 ? executionInfo.Data.Volume : 1;

            var command = new GetPriceForSpecialLiquidationCommand
            {
                OperationId   = executionInfo.Id,
                CreationTime  = _dateService.Now(),
                Instrument    = executionInfo.Data.Instrument,
                Volume        = positionsVolume,
                RequestNumber = executionInfo.Data.RequestNumber,
                RequestedFromCorporateActions = executionInfo.Data.RequestedFromCorporateActions
            };

            if (_marginTradingSettings.ExchangeConnector == ExchangeConnectorType.RealExchangeConnector)
            {
                //send it to the Gavel
                sender.SendCommand(command, _cqrsContextNamesSettings.Gavel);
            }
            else
            {
                _specialLiquidationService.SavePriceRequestForSpecialLiquidation(command);
            }

            //special command is sent instantly for timeout control.. it is retried until timeout occurs
            sender.SendCommand(new GetPriceForSpecialLiquidationTimeoutInternalCommand
            {
                OperationId    = executionInfo.Id,
                CreationTime   = _dateService.Now(),
                TimeoutSeconds = _marginTradingSettings.SpecialLiquidation.PriceRequestTimeoutSec,
                RequestNumber  = executionInfo.Data.RequestNumber
            }, _cqrsContextNamesSettings.TradingEngine);
        }
Exemple #3
0
        private void LiquidatePositionsIfAnyAvailable(string operationId,
                                                      LiquidationOperationData data, ICommandSender sender)
        {
            var liquidationData = GetLiquidationData(data);

            if (!liquidationData.HasValue || !liquidationData.Value.Positions.Any())
            {
                sender.SendCommand(new FailLiquidationInternalCommand
                {
                    OperationId     = operationId,
                    CreationTime    = _dateService.Now(),
                    Reason          = "Nothing to liquidate",
                    LiquidationType = data.LiquidationType,
                }, _cqrsContextNamesSettings.TradingEngine);
            }
            else
            {
                sender.SendCommand(new LiquidatePositionsInternalCommand
                {
                    OperationId  = operationId,
                    CreationTime = _dateService.Now(),
                    PositionIds  = liquidationData.Value.Positions,
                    AssetPairId  = liquidationData.Value.AssetPairId,
                }, _cqrsContextNamesSettings.TradingEngine);
            }
        }
        public async Task <ActionResult <bool> > CreateOrderFromBasketDataAsync([FromBody] UserCheckoutAcceptedModel request)
        {
            var createOrderCommand = new CreateOrderCommand(request.Basket.Items, request.UserId, request.UserName, request.City, request.Street,
                                                            request.State, request.Country, request.ZipCode,
                                                            request.CardNumber, request.CardHolderName, request.CardExpiration,
                                                            request.CardSecurityNumber, request.CardTypeId);

            return(await _commandSender.SendCommand(createOrderCommand));
        }
Exemple #5
0
        private async Task Handle(EnrolledBalanceSetEvent evt, ICommandSender sender)
        {
            var aggregate = await _cashinRepository.GetAsync(evt.OperationId);

            var transitionResult = aggregate.OnEnrolledBalanceSet();

            if (transitionResult.ShouldSaveAggregate())
            {
                await _cashinRepository.SaveAsync(aggregate);
            }

            if (transitionResult.ShouldSendCommands())
            {
                if (!aggregate.IsDustCashin.HasValue)
                {
                    throw new InvalidOperationException("IsDustCashin should be not null here");
                }

                if (!aggregate.IsDustCashin.Value)
                {
                    if (!aggregate.BalanceAmount.HasValue)
                    {
                        throw new InvalidOperationException("Balance amount should be not null here");
                    }

                    sender.SendCommand
                    (
                        new StartOperationExecutionCommand
                    {
                        Amount      = aggregate.BalanceAmount.Value,
                        AssetId     = aggregate.AssetId,
                        FromAddress = aggregate.DepositWalletAddress,
                        IncludeFee  = true,
                        OperationId = aggregate.OperationId,
                        ToAddress   = aggregate.HotWalletAddress
                    },
                        BlockchainOperationsExecutorBoundedContext.Name
                    );
                }
                else
                {
                    sender.SendCommand
                    (
                        new ReleaseDepositWalletLockCommand
                    {
                        OperationId          = aggregate.OperationId,
                        BlockchainType       = aggregate.BlockchainType,
                        BlockchainAssetId    = aggregate.BlockchainAssetId,
                        DepositWalletAddress = aggregate.DepositWalletAddress
                    },
                        Self
                    );
                }

                _chaosKitty.Meow(aggregate.OperationId);
            }
        }
Exemple #6
0
        private void ContinueOrFinishLiquidation(string operationId, LiquidationOperationData data, ICommandSender sender)
        {
            void FinishWithReason(string reason) => sender.SendCommand(new FinishLiquidationInternalCommand
            {
                OperationId           = operationId,
                CreationTime          = _dateService.Now(),
                Reason                = reason,
                LiquidationType       = data.LiquidationType,
                ProcessedPositionIds  = data.ProcessedPositionIds,
                LiquidatedPositionIds = data.LiquidatedPositionIds,
            }, _cqrsContextNamesSettings.TradingEngine);

            var account = _accountsCacheService.TryGet(data.AccountId);

            if (account == null)
            {
                sender.SendCommand(new FailLiquidationInternalCommand
                {
                    OperationId     = operationId,
                    CreationTime    = _dateService.Now(),
                    Reason          = "Account does not exist",
                    LiquidationType = data.LiquidationType,
                }, _cqrsContextNamesSettings.TradingEngine);
                return;
            }

            var accountLevel = account.GetAccountLevel();

            if (data.LiquidationType == LiquidationType.Forced)
            {
                if (!_ordersCache.Positions.GetPositionsByAccountIds(data.AccountId)
                    .Any(x => (string.IsNullOrWhiteSpace(data.AssetPairId) || x.AssetPairId == data.AssetPairId) &&
                         x.OpenDate < data.StartedAt &&
                         (data.Direction == null || x.Direction == data.Direction)))
                {
                    FinishWithReason("All positions are closed");
                }
                else
                {
                    LiquidatePositionsIfAnyAvailable(operationId, data, sender);
                }

                return;
            }

            if (accountLevel < AccountLevel.StopOut)
            {
                FinishWithReason($"Account margin level is {accountLevel}");
            }
            else
            {
                LiquidatePositionsIfAnyAvailable(operationId, data, sender);
            }
        }
Exemple #7
0
        private async Task Handle(PriceForSpecialLiquidationCalculatedEvent e, ICommandSender sender)
        {
            var executionInfo = await _operationExecutionInfoRepository.GetAsync <SpecialLiquidationOperationData>(
                operationName : OperationName,
                id : e.OperationId);

            if (executionInfo?.Data == null)
            {
                return;
            }

            if (executionInfo.Data.SwitchState(SpecialLiquidationOperationState.PriceRequested,
                                               SpecialLiquidationOperationState.PriceReceived))
            {
                //validate that volume didn't changed to peek either to execute order or request the price again
                var currentVolume = GetNetPositionCloseVolume(executionInfo.Data.PositionIds, executionInfo.Data.AccountId);
                if (currentVolume != 0 && currentVolume != e.Volume)
                {
                    sender.SendCommand(new GetPriceForSpecialLiquidationCommand
                    {
                        OperationId   = e.OperationId,
                        CreationTime  = _dateService.Now(),
                        Instrument    = executionInfo.Data.Instrument,
                        Volume        = currentVolume,
                        RequestNumber = e.RequestNumber++,
                        AccountId     = executionInfo.Data.AccountId,
                    }, _cqrsContextNamesSettings.Gavel);

                    executionInfo.Data.Volume = currentVolume;

                    await _operationExecutionInfoRepository.Save(executionInfo);

                    return;//wait for the new price
                }

                executionInfo.Data.Price = e.Price;

                //execute order in Gavel by API
                sender.SendCommand(new ExecuteSpecialLiquidationOrderCommand
                {
                    OperationId  = e.OperationId,
                    CreationTime = _dateService.Now(),
                    Instrument   = executionInfo.Data.Instrument,
                    Volume       = executionInfo.Data.Volume,
                    Price        = e.Price,
                }, _cqrsContextNamesSettings.TradingEngine);

                _chaosKitty.Meow(e.OperationId);

                await _operationExecutionInfoRepository.Save(executionInfo);
            }
        }
Exemple #8
0
        private async Task Handle(SpecialLiquidationStartedInternalEvent e, ICommandSender sender)
        {
            var executionInfo = await _operationExecutionInfoRepository.GetAsync <SpecialLiquidationOperationData>(
                operationName : OperationName,
                id : e.OperationId);

            if (executionInfo?.Data == null)
            {
                return;
            }

            if (executionInfo.Data.SwitchState(SpecialLiquidationOperationState.Started,
                                               SpecialLiquidationOperationState.PriceRequested))
            {
                var positionsVolume = GetNetPositionCloseVolume(executionInfo.Data.PositionIds, executionInfo.Data.AccountId);

                //special command is sent instantly for timeout control.. it is retried until timeout occurs
                sender.SendCommand(new GetPriceForSpecialLiquidationTimeoutInternalCommand
                {
                    OperationId    = e.OperationId,
                    CreationTime   = _dateService.Now(),
                    TimeoutSeconds = _marginTradingSettings.SpecialLiquidation.PriceRequestTimeoutSec,
                }, _cqrsContextNamesSettings.TradingEngine);

                executionInfo.Data.Instrument = e.Instrument;
                executionInfo.Data.Volume     = positionsVolume;

                if (_marginTradingSettings.ExchangeConnector == ExchangeConnectorType.RealExchangeConnector)
                {
                    //send it to the Gavel
                    sender.SendCommand(new GetPriceForSpecialLiquidationCommand
                    {
                        OperationId   = e.OperationId,
                        CreationTime  = _dateService.Now(),
                        Instrument    = e.Instrument,
                        Volume        = positionsVolume != 0 ? positionsVolume : 1,//hack, requested by the bank
                        RequestNumber = 1,
                    }, _cqrsContextNamesSettings.Gavel);
                }
                else
                {
                    _specialLiquidationService.FakeGetPriceForSpecialLiquidation(e.OperationId, e.Instrument,
                                                                                 positionsVolume);
                }

                _chaosKitty.Meow(e.OperationId);

                await _operationExecutionInfoRepository.Save(executionInfo);
            }
        }
        private void ProcessQueueItem(FeedQueueItem queueItem, IVkDataProvider vkDataProvider, FeedProcessingConfig processingConfig)
        {
            try
            {
                if (!this.feedProviders.ContainsKey(queueItem.QueueItemType))
                {
                    throw new ArgumentException(string.Format("Unsupported feed type provided: \"{0}\"", queueItem.QueueItemType));
                }

                var feedProvider = this.feedProviders[queueItem.QueueItemType];
                var vkGroup      = this.groupRepository.GetGroupById(queueItem.VkGroupId);

                if (vkGroup == null)
                {
                    this.log.InfoFormat("Group with Id = \"{0}\" not found. Processing stopped.", queueItem.VkGroupId);
                    return;
                }

                this.log.InfoFormat("Fetching of feed '{0}' for VkGroupId {1} is started", queueItem.QueueItemType, queueItem.VkGroupId);

                using (ICommandSender commandSender = Factory.GetInstance <ICommandSender>().Open(processingConfig.OutputQueueId))
                {
                    foreach (var dataFeed in feedProvider.GetFeeds(vkDataProvider, vkGroup))
                    {
                        dataFeed.TtlInMinutes = processingConfig.TtlInMinutes;
                        commandSender.SendCommand(dataFeed);
                    }

                    var terminator = new DataFeed
                    {
                        IsSequenceTerminator = true,
                        ReceivedAt           = this.dateTimeHelper.GetDateTimeNow(),
                        SendingDate          = this.dateTimeHelper.GetDateTimeNow(),
                        VkGroupId            = vkGroup.Id,
                        Type            = feedProvider.ProvidedDataType,
                        FetchingServer  = this.webUtilities.GetServerName(),
                        FetchingProcess = this.webUtilities.GetApplicationPoolName()
                    };

                    commandSender.SendCommand(terminator);
                }

                this.log.InfoFormat("Fetching of feed '{0}' for VkGroupId {1} is finished", queueItem.QueueItemType, queueItem.VkGroupId);
            }
            catch (Exception exc)
            {
                this.log.Error(string.Format("Fetching of feed '{0}' for VkGroupId {1} is FAILED. Reason: {2}", queueItem.QueueItemType, queueItem.VkGroupId, exc));
            }
        }
        private async Task Handle(SourceAddressLockReleasedEvent evt, ICommandSender sender)
        {
            var aggregate = await _repository.GetAsync(evt.TransactionId);

            if (_stateSwitcher.Switch(aggregate, evt))
            {
                switch (aggregate.State)
                {
                case TransactionExecutionState.WaitingForEnding:
                    sender.SendCommand
                    (
                        new WaitForTransactionEndingCommand
                    {
                        OperationId       = aggregate.OperationId,
                        TransactionId     = aggregate.TransactionId,
                        TransactionNumber = aggregate.TransactionNumber,
                        BlockchainType    = aggregate.BlockchainType,
                        BlockchainAssetId = aggregate.BlockchainAssetId,
                        Outputs           = aggregate.Outputs
                                            .Select(o => o.ToContract())
                                            .ToArray()
                    },
                        Self
                    );
                    break;

                case TransactionExecutionState.SourceAddressReleased:
                    sender.SendCommand
                    (
                        new ClearBroadcastedTransactionCommand
                    {
                        OperationId    = aggregate.OperationId,
                        TransactionId  = aggregate.TransactionId,
                        BlockchainType = aggregate.BlockchainType
                    },
                        Self
                    );
                    break;

                default:
                    throw new InvalidOperationException($"Unexpected aggregate state [{aggregate.State}]");
                }

                _chaosKitty.Meow(evt.TransactionId);

                await _repository.SaveAsync(aggregate);
            }
        }
Exemple #11
0
        public async Task Handle(NotEnoughLiquidityInternalEvent e, ICommandSender sender)
        {
            var executionInfo = await _operationExecutionInfoRepository.GetAsync <LiquidationOperationData>(
                operationName : OperationName,
                id : e.OperationId);

            if (executionInfo?.Data == null)
            {
                return;
            }

            if (executionInfo.Data.SwitchState(LiquidationOperationState.Started,
                                               LiquidationOperationState.SpecialLiquidationStarted))
            {
                sender.SendCommand(new StartSpecialLiquidationInternalCommand
                {
                    OperationId          = Guid.NewGuid().ToString(),
                    CreationTime         = _dateService.Now(),
                    AccountId            = executionInfo.Data.AccountId,
                    PositionIds          = e.PositionIds,
                    CausationOperationId = e.OperationId,
                    AdditionalInfo       = executionInfo.Data.AdditionalInfo,
                    OriginatorType       = executionInfo.Data.OriginatorType
                }, _cqrsContextNamesSettings.TradingEngine);

                _chaosKitty.Meow(
                    $"{nameof(PositionsLiquidationFinishedInternalEvent)}:" +
                    $"Save_OperationExecutionInfo:" +
                    $"{e.OperationId}");

                await _operationExecutionInfoRepository.Save(executionInfo);
            }
        }
        private async Task Handle(SourceAddressLockedEvent evt, ICommandSender sender)
        {
            var aggregate = await _repository.GetAsync(evt.TransactionId);

            if (_stateSwitcher.Switch(aggregate, evt))
            {
                sender.SendCommand
                (
                    new BuildTransactionCommand
                {
                    OperationId       = aggregate.OperationId,
                    TransactionId     = aggregate.TransactionId,
                    TransactionNumber = aggregate.TransactionNumber,
                    BlockchainType    = aggregate.BlockchainType,
                    BlockchainAssetId = aggregate.BlockchainAssetId,
                    FromAddress       = aggregate.FromAddress,
                    Outputs           = aggregate.Outputs
                                        .Select(e => e.ToContract())
                                        .ToArray(),
                    IncludeFee = aggregate.IncludeFee
                },
                    Self
                );

                _chaosKitty.Meow(evt.TransactionId);

                await _repository.SaveAsync(aggregate);
            }
        }
        private async Task Handle(TransactionExecutionStartedEvent evt, ICommandSender sender)
        {
            var aggregate = await _repository.GetOrAddAsync(
                evt.TransactionId,
                () => TransactionExecutionAggregate.Start(
                    evt.OperationId,
                    evt.TransactionId,
                    evt.TransactionNumber,
                    evt.FromAddress,
                    evt.Outputs
                    .Select(e => e.ToDomain())
                    .ToArray(),
                    evt.BlockchainType,
                    evt.BlockchainAssetId,
                    evt.AssetId,
                    evt.IncludeFee));

            _chaosKitty.Meow(evt.TransactionId);

            if (aggregate.State == TransactionExecutionState.Started)
            {
                sender.SendCommand
                (
                    new LockSourceAddressCommand
                {
                    OperationId    = aggregate.OperationId,
                    TransactionId  = aggregate.TransactionId,
                    BlockchainType = aggregate.BlockchainType,
                    FromAddress    = aggregate.FromAddress
                },
                    Self
                );
            }
        }
Exemple #14
0
 public Task SendMissedMessagesAsync(ICommandSender sender,
                                     SayPlace place,
                                     string target,
                                     int accountID,
                                     int maxCount = MessageResendCount)
 {
     return(Task.Run(async() =>
     {
         await sendHistorySemaphore.WaitAsync();
         try
         {
             using (var db = new ZkDataContext())
             {
                 var acc = db.Accounts.Find(accountID);
                 foreach (var entry in
                          db.LobbyChatHistories.Where(x => (x.Target == target) && (x.SayPlace == place) && (x.Time >= acc.LastLogout))
                          .OrderByDescending(x => x.Time)
                          .Take(maxCount)
                          .OrderBy(x => x.Time))
                 {
                     await sender.SendCommand(entry.ToSay());
                 }
             }
         }
         catch (Exception ex)
         {
             Trace.TraceError("Error sending chat history: {0}", ex);
         }
         finally
         {
             sendHistorySemaphore.Release();
         }
     }));
 }
Exemple #15
0
 public void DeleteProject(int projectId, int groupId)
 {
     using (ICommandSender commandSender = Factory.GetInstance <ICommandSender>().Open(CONST_DeleteProjectQueueName))
     {
         try
         {
             string ticketId = Guid.NewGuid().ToString();
             DeleteProjectCommand command = new DeleteProjectCommand
             {
                 ProjectId = projectId,
                 GroupId   = groupId,
                 TicketId  = ticketId
             };
             commandSender.SendCommand(command);
         }
         catch (Exception e)
         {
             e.ToString();
         }
         using (this.unitOfWorkProvider.CreateUnitOfWork())
         {
             var accountId = this.currentUserProvider.GetCurrentUser().GetAccount().Id;
             var project1  =
                 this.projectRepository.GetByAccountId(accountId).FirstOrDefault(x => x.Id == projectId);
             if (project1 != null)
             {
                 this.projectRepository.Delete(project1);
             }
         }
     }
 }
Exemple #16
0
        private async Task Handle(SpecialLiquidationCancelledEvent e, ICommandSender sender)
        {
            var executionInfo = await _operationExecutionInfoRepository.GetAsync <SpecialLiquidationOperationData>(
                operationName : OperationName,
                id : e.OperationId);

            if (executionInfo?.Data == null)
            {
                return;
            }

            if (executionInfo.Data.SwitchState(executionInfo.Data.State,//from any state
                                               SpecialLiquidationOperationState.Cancelled))
            {
                if (e.ClosePositions)
                {
                    sender.SendCommand(new ClosePositionsRegularFlowCommand
                    {
                        OperationId = e.OperationId
                    }, _cqrsContextNamesSettings.TradingEngine);
                }

                _chaosKitty.Meow(e.OperationId);

                await _operationExecutionInfoRepository.Save(executionInfo);
            }
        }
        private async Task Handle(AccountsBlockedForDeletionEvent e, ICommandSender sender)
        {
            var executionInfo = await _executionInfoRepository.GetAsync <DeleteAccountsData>(
                OperationName,
                e.OperationId
                );

            if (executionInfo == null)
            {
                return;
            }

            if (executionInfo.Data.SwitchState(DeleteAccountsState.Started, DeleteAccountsState.MtCoreAccountsBlocked))
            {
                executionInfo.Data.AddFailedIfNotExist(e.FailedAccountIds);

                sender.SendCommand(new MarkAccountsAsDeletedInternalCommand
                {
                    OperationId = e.OperationId,
                    Timestamp   = _systemClock.UtcNow.UtcDateTime,
                },
                                   _contextNames.AccountsManagement);

                _chaosKitty.Meow(
                    $"{nameof(AccountsBlockedForDeletionEvent)}: " +
                    "Save_OperationExecutionInfo: " +
                    $"{e.OperationId}");

                await _executionInfoRepository.SaveAsync(executionInfo);
            }
        }
Exemple #18
0
        private async Task Handle(SpecialLiquidationFinishedEvent e, ICommandSender sender)
        {
            var executionInfo = await _operationExecutionInfoRepository.GetAsync <SpecialLiquidationOperationData>(
                operationName : OperationName,
                id : e.OperationId);

            if (executionInfo?.Data == null)
            {
                return;
            }

            if (executionInfo.Data.SwitchState(SpecialLiquidationOperationState.InternalOrdersExecuted,
                                               SpecialLiquidationOperationState.Finished))
            {
                if (!string.IsNullOrEmpty(executionInfo.Data.CausationOperationId))
                {
                    sender.SendCommand(new ResumeLiquidationInternalCommand
                    {
                        OperationId  = executionInfo.Data.CausationOperationId,
                        CreationTime = _dateService.Now(),
                        Comment      = $"Resume after special liquidation {executionInfo.Id} finished",
                        IsCausedBySpecialLiquidation            = true,
                        CausationOperationId                    = executionInfo.Id,
                        PositionsLiquidatedBySpecialLiquidation = executionInfo.Data.PositionIds
                    }, _cqrsContextNamesSettings.TradingEngine);
                }

                _chaosKitty.Meow(e.OperationId);

                await _operationExecutionInfoRepository.Save(executionInfo);
            }
        }
Exemple #19
0
        private async Task Handle(AccountChangedEvent e, ICommandSender sender)
        {
            if (e.Source != OperationName)
            {
                return;
            }

            var executionInfo = await _executionInfoRepository.GetAsync <GiveTemporaryCapitalData>(OperationName, e.BalanceChange.Id);

            if (executionInfo == null)
            {
                return;
            }

            if (executionInfo.Data.SwitchState(TemporaryCapitalState.Started, TemporaryCapitalState.ChargedOnAccount))
            {
                sender.SendCommand(
                    new FinishGiveTemporaryCapitalInternalCommand(
                        e.BalanceChange.Id,
                        _systemClock.UtcNow.UtcDateTime,
                        true,
                        null),
                    _contextNames.AccountsManagement);

                _chaosKitty.Meow($"{nameof(AccountChangedEvent)}: " +
                                 "Save_OperationExecutionInfo:" + e.BalanceChange.Id);

                await _executionInfoRepository.SaveAsync(executionInfo);
            }
        }
Exemple #20
0
 public void PutVkGroupToQueue(GroupQueueItem groupQueueItem)
 {
     using (ICommandSender commandSender = Factory.GetInstance <ICommandSender>().Open("GroupJobQueue"))
     {
         commandSender.SendCommand(groupQueueItem);
     }
 }
Exemple #21
0
        private async Task Handle(SpecialLiquidationOrderExecutedEvent e, ICommandSender sender)
        {
            var executionInfo = await _operationExecutionInfoRepository.GetAsync <SpecialLiquidationOperationData>(
                operationName : OperationName,
                id : e.OperationId);

            if (executionInfo?.Data == null)
            {
                return;
            }

            if (executionInfo.Data.SwitchState(SpecialLiquidationOperationState.ExternalOrderExecuted,
                                               SpecialLiquidationOperationState.InternalOrderExecutionStarted))
            {
                sender.SendCommand(new ExecuteSpecialLiquidationOrdersInternalCommand
                {
                    OperationId           = e.OperationId,
                    CreationTime          = _dateService.Now(),
                    Instrument            = executionInfo.Data.Instrument,
                    Volume                = executionInfo.Data.Volume,
                    Price                 = e.ExecutionPrice,
                    MarketMakerId         = e.MarketMakerId,
                    ExternalOrderId       = e.OrderId,
                    ExternalExecutionTime = e.ExecutionTime,
                }, _cqrsContextNamesSettings.TradingEngine);

                _chaosKitty.Meow(e.OperationId);

                await _operationExecutionInfoRepository.Save(executionInfo);
            }
        }
        public async Task Handle(OperationRejectedEvent evt, ICommandSender sender)
        {
            var aggregate = await _riskControlRepository.TryGetAsync(evt.OperationId);

            if (aggregate == null)
            {
                return; // not a cashout operation
            }

            if (aggregate.OnOperationRejected(evt.Message))
            {
                // just send a regular CashoutFailed notification
                sender.SendCommand
                (
                    new NotifyCashoutFailedCommand
                {
                    OperationId  = aggregate.OperationId,
                    ClientId     = aggregate.ClientId,
                    AssetId      = aggregate.AssetId,
                    Amount       = aggregate.Amount,
                    StartMoment  = aggregate.StartMoment.Value,
                    FinishMoment = aggregate.OperationRejectionMoment.Value,
                    Error        = aggregate.Error,
                    ErrorCode    = CashoutErrorCode.Unknown
                },
                    CqrsModule.Self
                );

                _chaosKitty.Meow(evt.OperationId);

                await _riskControlRepository.SaveAsync(aggregate);

                _chaosKitty.Meow(evt.OperationId);
            }
        }
Exemple #23
0
        private async Task Handle(AccountChangedEvent evt, ICommandSender sender)
        {
            if (evt.EventType != AccountChangedEventTypeContract.BalanceUpdated)
            {
                return;
            }
            if (evt.BalanceChange == null)
            {
                return;
            }

            var account = await _accountsRepository.GetAsync(evt.Account.Id);

            var amount = await _negativeProtectionService.CheckAsync(evt.OperationId,
                                                                     evt.Account.Id,
                                                                     evt.BalanceChange.Balance,
                                                                     evt.BalanceChange.ChangeAmount);

            if (account == null || amount == null)
            {
                return;
            }

            sender.SendCommand(new NotifyNegativeProtectionInternalCommand(
                                   Guid.NewGuid().ToString("N"),
                                   evt.OperationId,
                                   evt.OperationId,
                                   _systemClock.UtcNow.UtcDateTime,
                                   account.ClientId,
                                   account.Id,
                                   amount.Value
                                   ),
                               _contextNames.AccountsManagement);
        }
        public async Task Handle(OperationAcceptedEvent evt, ICommandSender sender)
        {
            var aggregate = await _riskControlRepository.TryGetAsync(evt.OperationId);

            if (aggregate == null)
            {
                return; // not a cashout operation
            }

            if (aggregate.OnOperationAccepted())
            {
                sender.SendCommand
                (
                    new AcceptCashoutCommand
                {
                    OperationId       = evt.OperationId,
                    ClientId          = aggregate.ClientId,
                    AssetId           = aggregate.AssetId,
                    BlockchainType    = aggregate.BlockchainType,
                    BlockchainAssetId = aggregate.BlockchainAssetId,
                    HotWalletAddress  = aggregate.HotWalletAddress,
                    ToAddress         = aggregate.ToAddress,
                    Amount            = aggregate.Amount
                },
                    Self
                );

                _chaosKitty.Meow(evt.OperationId);

                await _riskControlRepository.SaveAsync(aggregate);

                _chaosKitty.Meow(evt.OperationId);
            }
        }
Exemple #25
0
        private async Task Handle(AmountForWithdrawalFrozenEvent e, ICommandSender sender)
        {
            var executionInfo = await _executionInfoRepository.GetAsync <WithdrawalDepositData>(OperationName, e.OperationId);

            if (executionInfo == null)
            {
                return;
            }

            if (SwitchState(executionInfo.Data, WithdrawalState.FreezingAmount, WithdrawalState.UpdatingBalance))
            {
                sender.SendCommand(
                    new UpdateBalanceInternalCommand(
                        e.OperationId,
                        executionInfo.Data.AccountId,
                        -executionInfo.Data.Amount,
                        "Funds withdrawal " + executionInfo.Data.Comment,
                        executionInfo.Data.AuditLog,
                        OperationName,
                        AccountBalanceChangeReasonType.Withdraw,
                        e.OperationId,
                        string.Empty,
                        DateTime.UtcNow),
                    _contextNames.AccountsManagement);

                _chaosKitty.Meow(e.OperationId);

                await _executionInfoRepository.SaveAsync(executionInfo);
            }
        }
Exemple #26
0
        public async Task Handle(EodProcessFinishedEvent e, ICommandSender sender)
        {
            var productsResult = await _productsRepository.GetAllAsync(null, null, isStarted : false);

            if (productsResult.IsSuccess && productsResult.Value != null && productsResult.Value.Any())
            {
                var products    = productsResult.Value;
                var markets     = products.Select(x => x.Market).Distinct().ToArray();
                var marketInfos = await _marketDayOffService.GetMarketsInfo(markets, null);

                var productsToStart = productsResult.Value
                                      .Where(x => x.StartDate < marketInfos[x.Market].NextTradingDayStart.Date.AddDays(1))
                                      .ToList();

                _log.WriteInfo(nameof(StartProductsSaga), nameof(Handle),
                               $"Found {productsToStart.Count} products that need to be started. Ids are: {string.Concat(',', productsToStart.Select(x => x.ProductId))}"
                               );

                foreach (var product in productsToStart)
                {
                    sender.SendCommand(new StartProductCommand()
                    {
                        ProductId   = product.ProductId,
                        OperationId = e.OperationId,
                    }, _contextNames.AssetService);
                }
            }
        }
        public async Task Handle(RiskyOperationDetectedEvent evt, ICommandSender sender)
        {
            switch (evt.RiskLevel)
            {
            case OperationRiskLevel.ResolutionRequired:
                if (!string.IsNullOrEmpty(_chatId))
                {
                    await _telegramBot.SendTextMessageAsync(_chatId, $"Operation requires for manual confirmation (operationId = {evt.OperationId})");
                }

                sender.SendCommand
                (
                    new WaitForOperationResolutionCommand
                {
                    OperationId = evt.OperationId
                },
                    BlockchainRiskControlBoundedContext.Name
                );

                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(evt.RiskLevel), evt.RiskLevel, null);
            }
        }
Exemple #28
0
        private async Task Handle(WithdrawalStartedInternalEvent e, ICommandSender sender)
        {
            var executionInfo = await _executionInfoRepository.GetAsync <WithdrawalDepositData>(OperationName, e.OperationId);

            if (executionInfo == null)
            {
                return;
            }

            if (SwitchState(executionInfo.Data, WithdrawalState.Created, WithdrawalState.FreezingAmount))
            {
                sender.SendCommand(
                    new FreezeAmountForWithdrawalCommand(
                        executionInfo.Id,
                        _systemClock.UtcNow.UtcDateTime,
                        executionInfo.Data.AccountId,
                        executionInfo.Data.Amount,
                        executionInfo.Data.Comment),
                    _contextNames.TradingEngine);

                _chaosKitty.Meow(e.OperationId);

                await _executionInfoRepository.SaveAsync(executionInfo);
            }
        }
Exemple #29
0
        private async Task Handle(AccountBalanceChangeFailedEvent e, ICommandSender sender)
        {
            if (e.Source != OperationName)
            {
                return;
            }

            var executionInfo = await _executionInfoRepository.GetAsync <WithdrawalDepositData>(OperationName, e.OperationId);

            if (executionInfo == null)
            {
                return;
            }

            if (SwitchState(executionInfo.Data, WithdrawalState.UpdatingBalance, WithdrawalState.UnfreezingAmount))
            {
                executionInfo.Data.FailReason = e.Reason;
                sender.SendCommand(
                    new UnfreezeMarginOnFailWithdrawalCommand(
                        e.OperationId),
                    _contextNames.TradingEngine);

                _chaosKitty.Meow(e.OperationId);

                await _executionInfoRepository.SaveAsync(executionInfo);
            }
        }
Exemple #30
0
        private async Task Handle(AccountChangedEvent e, ICommandSender sender)
        {
            if (e.Source != OperationName)
            {
                return;
            }

            var executionInfo = await _executionInfoRepository.GetAsync <WithdrawalDepositData>(OperationName, e.BalanceChange.Id);

            if (executionInfo == null)
            {
                return;
            }

            if (SwitchState(executionInfo.Data, WithdrawalState.UpdatingBalance, WithdrawalState.Succeeded))
            {
                sender.SendCommand(
                    new CompleteWithdrawalInternalCommand(
                        e.BalanceChange.Id),
                    _contextNames.AccountsManagement);

                _chaosKitty.Meow(e.BalanceChange.Id);

                await _executionInfoRepository.SaveAsync(executionInfo);
            }
        }
 public async Task SendMissedMessages(ICommandSender sender, SayPlace place, string target, int accountID, int maxCount = OfflineMessageResendCount)
 {
     using (var db = new ZkDataContext()) {
         var acc = await db.Accounts.FindAsync(accountID);
         await
             db.LobbyChatHistories.Where(x => x.Target == target && x.SayPlace == place && x.Time >= acc.LastLogout)
                 .OrderByDescending(x => x.Time)
                 .Take(maxCount)
                 .OrderBy(x => x.Time)
                 .ForEachAsync(async (chatHistory) => { await sender.SendCommand(chatHistory.ToSay()); });
     }
 }
 public async Task SendMissedMessages(ICommandSender sender, SayPlace place, string target, int accountID, int maxCount = OfflineMessageResendCount)
 {
     using (var db = new ZkDataContext()) {
         var acc = await db.Accounts.FindAsync(accountID);
         await
             db.LobbyChatHistories.Where(x => x.Target == target && x.SayPlace == place && x.Time >= acc.LastLogout)
                 .OrderByDescending(x => x.Time)
                 .Take(maxCount)
                 .OrderBy(x => x.Time)
                 .ForEachAsync(async (chatHistory) => { await sender.SendCommand(chatHistory.ToSay()); });
         
         if (place == SayPlace.User) { // don't keep PMs longer than needed
             db.LobbyChatHistories.DeleteAllOnSubmit(db.LobbyChatHistories.Where(x => x.Target == target && x.SayPlace == SayPlace.User).ToList());
             db.SaveChanges();
         }
     }
 }
        public Task SendMissedMessagesAsync(ICommandSender sender,
            SayPlace place,
            string target,
            int accountID,
            int maxCount = MessageResendCount)
        {
            return Task.Run(async () =>
            {
                await sendHistorySemaphore.WaitAsync();
                try
                {
                    using (var db = new ZkDataContext())
                    {
                        var acc = db.Accounts.Find(accountID);
                        foreach (var entry in
                            db.LobbyChatHistories.Where(x => (x.Target == target) && (x.SayPlace == place) && (x.Time >= acc.LastLogout))
                                .OrderByDescending(x => x.Time)
                                .Take(maxCount)
                                .OrderBy(x => x.Time)) await sender.SendCommand(entry.ToSay());

                        if (place == SayPlace.User)
                        {
                            // don't keep PMs longer than needed
                            db.LobbyChatHistories.DeleteAllOnSubmit(
                                db.LobbyChatHistories.Where(x => (x.Target == target) && (x.SayPlace == SayPlace.User)).ToList());
                            db.SaveChanges();
                        }
                    }
                }
                catch (Exception ex)
                {
                    Trace.TraceError("Error sending chat history: {0}", ex);
                }
                finally
                {
                    sendHistorySemaphore.Release();
                }
            });
        }
 public async Task OnLoginAccepted(ICommandSender client)
 {
     await client.SendCommand(new MatchMakerSetup() { PossibleQueues = possibleQueues });
 }