private Task ProcessMessageAsync(CashOutEvent message)
        {
            var fees   = message.CashOut.Fees;
            var fee    = fees?.FirstOrDefault()?.Transfer;
            var @event = new CashOutProcessedEvent
            {
                OperationId = Guid.Parse(message.Header.RequestId),
                RequestId   = Guid.Parse(message.Header.MessageId),
                WalletId    = Guid.Parse(message.CashOut.WalletId),
                Volume      = decimal.Parse(message.CashOut.Volume),
                AssetId     = message.CashOut.AssetId,
                Timestamp   = message.Header.Timestamp,
                FeeSize     = ParseNullabe(fee?.Volume)
            };

            _cqrsEngine.PublishEvent(@event, BoundedContext.Name);

            if (fees != null)
            {
                var feeEvent = new FeeChargedEvent
                {
                    OperationId   = message.Header.MessageId,
                    OperationType = FeeOperationType.CashInOut,
                    Fee           = fees.Where(x => x.Transfer != null).Select(x => x.Transfer).ToJson()
                };
                _cqrsEngine.PublishEvent(feeEvent, BoundedContext.Name);
            }

            return(Task.CompletedTask);
        }
        public async Task <CommandHandlingResult> Handle(CashOutProcessedEvent @event)
        {
            var entity = Mapper.Map <Cashout>(@event);

            if (!await _historyRecordsRepository.TryInsertAsync(entity))
            {
                _logger.Warning($"Skipped duplicated cashout record", context: new
                {
                    id = @event.OperationId
                });
            }

            return(CommandHandlingResult.Ok());
        }
        public async Task <CommandHandlingResult> Handle(CashOutProcessedEvent cashOutProcessedEvent, ICommandSender commandSender)
        {
            var bitcoinTransactionExists = await _bitCoinTransactionsRepository.ForwardWithdrawalExistsAsync(cashOutProcessedEvent.OperationId.ToString());

            if (!bitcoinTransactionExists)
            {
                _log.Info("Skip cashout - not forward withdrawal.", context: cashOutProcessedEvent.ToJson());
                return(CommandHandlingResult.Ok());
            }

            var record = await _repository.TryGetByCashoutIdAsync(cashOutProcessedEvent.WalletId.ToString(), cashOutProcessedEvent.OperationId.ToString());

            if (record != null)
            {
                if (!Guid.TryParse(record.CashInId, out var cashinId))
                {
                    _log.Warning($"Cannot parse data : {record.ToJson()}");
                    return(CommandHandlingResult.Ok());
                }

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

                var forwardAsset = await _assetsServiceWithCache.TryGetAssetAsync(asset.ForwardBaseAsset);

                var settlementDate = record.DateTime.AddDays(asset.ForwardFrozenDays);

                var command = new CreateForwardCashinCommand
                {
                    AssetId     = forwardAsset.Id,
                    OperationId = cashinId,
                    Timestamp   = settlementDate,
                    Volume      = Math.Abs(cashOutProcessedEvent.Volume).TruncateDecimalPlaces(forwardAsset.Accuracy),
                    WalletId    = cashOutProcessedEvent.WalletId
                };

                commandSender.SendCommand(command, HistoryBoundedContext.Name);

                _log.Info("CreateForwardCashinCommand has been sent.", command);
                return(CommandHandlingResult.Ok());
            }

            _log.Warning("No forward withdrawal record found.", context: new { Id = cashOutProcessedEvent.OperationId.ToString() });
            return(CommandHandlingResult.Fail(TimeSpan.FromSeconds(10)));
        }
        private CashOutProcessedEvent CreateCashoutRecord()
        {
            var cqrs = _container.Resolve <ICqrsEngine>();

            var id       = Guid.NewGuid();
            var clientId = Guid.NewGuid();
            var volume   = 54.31M;

            var @event = new CashOutProcessedEvent
            {
                OperationId = id,
                WalletId    = clientId,
                Volume      = volume,
                AssetId     = "EUR",
                Timestamp   = DateTime.UtcNow
            };

            cqrs.PublishEvent(@event, PostProcessingBoundedContext.Name);

            return(@event);
        }