public async Task ProcessTransferEventAsync(ITransfer transfer)
        {
            var isValid = ValidateTransfer(transfer);

            if (!isValid)
            {
                return;
            }

            // fetching additional data
            var getSenderWalletAddressTask    = GetCachedCustomerWalletAddressAsync(transfer.SenderCustomerId);
            var getRecipientWalletAddressTask = GetCachedCustomerWalletAddressAsync(transfer.ReceiverCustomerId);
            await Task.WhenAll(getSenderWalletAddressTask, getRecipientWalletAddressTask);

            // extending transfer event with additional data
            transfer.SenderWalletAddress   = getSenderWalletAddressTask.Result;
            transfer.ReceiverWalletAddress = getRecipientWalletAddressTask.Result;

            await _transfersRepository.AddAsync(transfer);
        }
        public async Task <TransferResultModel> TransferBalanceAsync(
            string externalOperationId,
            string senderCustomerId,
            string receiverCustomerId,
            Money18 amount)
        {
            var isSenderIdValidGuid   = Guid.TryParse(senderCustomerId, out var senderId);
            var isReceiverIdValidGuid = Guid.TryParse(receiverCustomerId, out var receiverId);

            if (!isSenderIdValidGuid)
            {
                return new TransferResultModel {
                           ErrorCode = TransferErrorCodes.InvalidSenderId
                }
            }
            ;

            if (!isReceiverIdValidGuid)
            {
                return new TransferResultModel {
                           ErrorCode = TransferErrorCodes.InvalidRecipientId
                }
            }
            ;

            if (await ValidateIfCustomerExists(senderCustomerId))
            {
                _log.Warning($"Attempt for Transfer from Sender with ${senderCustomerId} failed as such Customer does not exist");

                return(new TransferResultModel {
                    ErrorCode = TransferErrorCodes.SourceCustomerNotFound
                });
            }

            if (await ValidateIfCustomerExists(receiverCustomerId))
            {
                _log.Warning($"Attempt for Transfer from Sender with ${senderCustomerId} failed as Receiver Customer with ${receiverCustomerId} does not exist");
                return(new TransferResultModel {
                    ErrorCode = TransferErrorCodes.TargetCustomerNotFound
                });
            }

            if (senderCustomerId == receiverCustomerId)
            {
                return new TransferResultModel {
                           ErrorCode = TransferErrorCodes.TransferSourceAndTargetMustBeDifferent
                }
            }
            ;

            if (amount <= 0)
            {
                return new TransferResultModel {
                           ErrorCode = TransferErrorCodes.InvalidAmount
                }
            }
            ;

            if (await ValidateIfCustomerWalletIsBlocked(senderCustomerId))
            {
                _log.Warning($"Attempt for Transfer from Sender with ${senderCustomerId} failed as such Customer Wallet is blocked");

                return(new TransferResultModel {
                    ErrorCode = TransferErrorCodes.SourceCustomerWalletBlocked
                });
            }

            if (await ValidateIfCustomerWalletIsBlocked(receiverCustomerId))
            {
                _log.Warning($"Attempt for Transfer from Sender with ${senderCustomerId} failed as Receiver Customer Wallet is blocked");
                return(new TransferResultModel {
                    ErrorCode = TransferErrorCodes.TargetCustomerWalletBlocked
                });
            }

            var transactionId = Guid.NewGuid().ToString();
            var contextId     = externalOperationId ?? transactionId;

            var pbfTransferResponse = await _blockchainFacadeClient.TransfersApi.TransferAsync(
                new TransferRequestModel
            {
                TransferId          = contextId,
                SenderCustomerId    = senderId,
                RecipientCustomerId = receiverId,
                Amount = amount
            });

            if (pbfTransferResponse.Error != TransferError.None)
            {
                return(new TransferResultModel {
                    ErrorCode = (TransferErrorCodes)pbfTransferResponse.Error
                });
            }

            var now = DateTime.UtcNow;
            // saving context
            await _transfersRepository.AddAsync(new TransferDto
            {
                Id                  = contextId,
                OperationId         = transactionId,
                ExternalOperationId = externalOperationId,
                SenderCustomerId    = senderCustomerId,
                RecipientCustomerId = receiverCustomerId,
                Amount              = amount,
                AssetSymbol         = _tokenSymbol,
                TimeStamp           = now
            });

            return(new TransferResultModel
            {
                ExternalOperationId = externalOperationId,
                TransactionId = transactionId,
                Timestamp = now
            });
        }