Пример #1
0
        public async Task <PersonalInformationViewModel> GetPersonalInformation(string returnUrl)
        {
            var userFullData = await _personalDataService.GetAsync(CurrentClientId);

            var model = Mapper.Map <PersonalInformationViewModel>(userFullData) ?? new PersonalInformationViewModel();

            model.ReturnUrl   = returnUrl;
            model.NextStepUrl = null; /*GetStepUrl("CountryOfResidence", returnUrl);*/
            model.PrevStepUrl = null;

            return(model);
        }
Пример #2
0
        public FxPaygatePaymentUrlInputValidationModel(
            IHttpContextAccessor httpContextAccessor,
            IAssetsHelper assetHelper,
            IAssetDisclaimersClient assetDisclaimersClient,
            IPaymentSystemClient paymentSystemClient,
            IPersonalDataService personalDataService,
            IClientAccountClient clientAccountService,
            IAssetsService assetsService,
            IKycStatusService kycStatusService,
            ITierClient tierClient,
            IRateCalculatorClient rateCalculatorClient)
        {
            _assetsHelper           = assetHelper;
            _assetDisclaimersClient = assetDisclaimersClient;
            _clientAccountService   = clientAccountService;
            _assetsService          = assetsService;
            _kycStatusService       = kycStatusService;
            _tierClient             = tierClient;
            _rateCalculatorClient   = rateCalculatorClient;

            _clientId = httpContextAccessor.HttpContext.User?.Identity?.Name;
            var paymentLimitsTask = paymentSystemClient.GetPaymentLimitsAsync();
            var pdTask            = personalDataService.GetAsync(_clientId);

            Task.WhenAll(paymentLimitsTask, pdTask).GetAwaiter().GetResult();

            _paymentLimitsResponse = paymentLimitsTask.Result;
            _personalData          = pdTask.Result;
            RegisterRules();
        }
        private async Task <ClientModel> GetClientModel()
        {
            var personalDataTask = _personalDataService.GetAsync(_requestContext.ClientId);
            var cashoutBlockTask = _clientAccountClient.ClientSettings.GetCashOutBlockSettingsAsync(_requestContext.ClientId);
            var backupDoneTask   = _clientAccountClient.ClientSettings.GetBackupSettingsAsync(_requestContext.ClientId);
            var kycStatusTask    = _kycStatusService.GetKycStatusAsync(_requestContext.ClientId);

            await Task.WhenAll(personalDataTask, cashoutBlockTask, backupDoneTask, kycStatusTask);

            var personalData = personalDataTask.Result;

            return(new ClientModel
            {
                Id = new Guid(_requestContext.ClientId),
                TradesBlocked = cashoutBlockTask.Result.TradesBlocked,
                BackupDone = backupDoneTask.Result.BackupDone,
                KycStatus = kycStatusTask.Result.ToString(),
                PersonalData = new PersonalDataModel
                {
                    Country = personalData.Country,
                    CountryFromID = personalData.CountryFromID,
                    CountryFromPOA = personalData.CountryFromPOA
                }
            });
        }
Пример #4
0
        public async Task <ClaimsIdentity> CreateUserIdentityAsync(string clientId, string email, string userName)
        {
            var personalData = await _personalDataService.GetAsync(clientId);

            var claims = new List <Claim>
            {
                new Claim(ClaimTypes.Name, email),
                new Claim(ClaimTypes.NameIdentifier, clientId),
                new Claim(OpenIdConnectConstants.Claims.Email, email)
            };

            if (!string.IsNullOrEmpty(personalData.FirstName))
            {
                claims.Add(new Claim(OpenIdConnectConstants.Claims.GivenName, personalData.FirstName));
            }

            if (!string.IsNullOrEmpty(personalData.LastName))
            {
                claims.Add(new Claim(OpenIdConnectConstants.Claims.FamilyName, personalData.LastName));
            }

            if (!string.IsNullOrEmpty(personalData.Country))
            {
                claims.Add(new Claim(OpenIdConnectConstantsExt.Claims.Country, personalData.Country));
            }

            var documents = (await GetDocumentListAsync(clientId)).ToList();

            if (documents.Any())
            {
                claims.Add(new Claim(OpenIdConnectConstantsExt.Claims.Documents, string.Join(",", documents)));
            }

            return(new ClaimsIdentity(new GenericIdentity(userName, "Token"), claims));
        }
        public void GenerateFromSwiftDetails(ICashOutRequest request, string initialRequestId, DateTime dateOfTransaction)
        {
            Task.Run(async() => {
                if (request == null || string.IsNullOrWhiteSpace(initialRequestId))
                {
                    return;
                }

                var swiftFields = request.PaymentFields.DeserializeJson <Swift>();
                var pd          = await _personalDataService.GetAsync(request.ClientId);

                var htmlContent = "<!DOCTYPE html><html><head><title>Cash out request</title></head><body><div style=\"font-family: Geneva, Arial, Helvetica, sans-serif; width: 650px; margin:20px auto;\"><div style=\"width:650px;\"><img src=\"https://lkefiles.blob.core.windows.net/images/emails/logo_emails.png\" height=\"40\" alt=\"Lykke logo\" /></div><table style=\"margin:auto;width:650px;border: none;background-color: #fff;\"><tr><td style=\"text-align:center;padding:0 40px 0 40px;\"><img src=\"https://lkefiles.blob.core.windows.net:443/images/emails/withdraw-icon.png\" width=\"200\" alt=\"Letter image\" /></td></tr><tr><td style=\"text-align:center;\"><span style=\"font-size: 1.4em; font-weight: bold;\">Cash Out Request <br/>(@[Amount] @[Asset] for @[UserEmail]) <br/>Processed</span></td></tr><tr><td style=\"padding:20px 40px 60px 40px;\"><table style=\"border-collapse:collapse\"><tr style=\"border-top: 1px solid #8C94A0; border-bottom: 1px solid #8C94A0;\"><td style=\"padding:15px 0 15px 0;\" width=\"260\"><span style=\"font-size: 1.1em;color: #8C94A0;\">SWIFT / ABA Routing</span></td><td style=\"padding:15px 0 15px 0;\" width=\"260\"><span style=\"font-size: 1.1em;color: #3F4D60;\">@[Bic]</span></td></tr><tr style=\"border-top: 1px solid #8C94A0; border-bottom: 1px solid #8C94A0;\"><td style=\"padding:15px 0 15px 0;\" width=\"260\"><span style=\"font-size: 1.1em;color: #8C94A0;\">Name of the bank</span></td><td style=\"padding:15px 0 15px 0;\" width=\"260\"><span style=\"font-size: 1.1em;color: #3F4D60;\">@[BankName]</span></td></tr><tr style=\"border-top: 1px solid #8C94A0; border-bottom: 1px solid #8C94A0;\"><td style=\"padding:15px 0 15px 0;\" width=\"260\"><span style=\"font-size: 1.1em;color: #8C94A0;\">Beneficiary's Account number (IBAN)</span></td><td style=\"padding:15px 0 15px 0;\" width=\"260\"><span style=\"font-size: 1.1em;color: #3F4D60;\">@[AccNumber]</span></td></tr><tr style=\"border-top: 1px solid #8C94A0; border-bottom: 1px solid #8C94A0;\"><td style=\"padding:15px 0 15px 0;\" width=\"260\"><span style=\"font-size: 1.1em;color: #8C94A0;\">Name of the account holder</span></td><td style=\"word-break:break-all; padding:15px 0 15px 0;\" width=\"260\"><span style=\"font-size: 1.1em;color: #3F4D60;\">@[AccName]</span></td></tr><tr style=\"border-top: 1px solid #8C94A0; border-bottom: 1px solid #8C94A0;\"><td style=\"padding:15px 0 15px 0;\" width=\"260\"><span style=\"font-size: 1.1em;color: #8C94A0;\">Country of the account holder</span></td><td style=\"padding:15px 0 15px 0;\" width=\"260\"><span style=\"font-size: 1.1em;color: #3F4D60;\">@[AccHolderCountry]</span></td></tr><tr style=\"border-top: 1px solid #8C94A0; border-bottom: 1px solid #8C94A0;\"><td style=\"padding:15px 0 15px 0;\" width=\"260\"><span style=\"font-size: 1.1em;color: #8C94A0;\">Zip Code of the account holder</span></td><td style=\"padding:15px 0 15px 0;\" width=\"260\"><span style=\"font-size: 1.1em;color: #3F4D60;\">@[AccHolderZipCode]</span></td></tr><tr style=\"border-top: 1px solid #8C94A0; border-bottom: 1px solid #8C94A0;\"><td style=\"padding:15px 0 15px 0;\" width=\"260\"><span style=\"font-size: 1.1em;color: #8C94A0;\">City of the account holder</span></td><td style=\"padding:15px 0 15px 0;\" width=\"260\"><span style=\"font-size: 1.1em;color: #3F4D60;\">@[AccHolderCity]</span></td></tr><tr style=\"border-top: 1px solid #8C94A0; border-bottom: 1px solid #8C94A0;\"><td style=\"padding:15px 0 15px 0;\" width=\"260\"><span style=\"font-size: 1.1em;color: #8C94A0;\">Address of the account holder</span></td><td style=\"padding:15px 0 15px 0;\" width=\"260\"><span style=\"font-size: 1.1em;color: #3F4D60;\">@[AccHolderAddress]</span></td></tr><tr style=\"border-top: 1px solid #8C94A0; border-bottom: 1px solid #8C94A0;\"><td style=\"padding:15px 0 15px 0;\" width=\"260\"><span style=\"font-size: 1.1em;color: #8C94A0;\">Date of the transaction</span><br/><span style=\"font-size: 1.1em;color: #8C94A0;\">(Year/Month/Date)</span></td><td style=\"padding:15px 0 15px 0;\" width=\"260\"><span style=\"font-size: 1.1em;color: #3F4D60;\">@[DateOfTransaction]</span></td></tr></table></td></tr></table></div></body></html>";

                htmlContent = htmlContent.Replace("@[Amount]", request.Amount.ToString());
                htmlContent = htmlContent.Replace("@[Asset]", request.AssetId);
                htmlContent = htmlContent.Replace("@[UserEmail]", pd.Email);

                htmlContent = htmlContent.Replace("@[Bic]", swiftFields.Bic);
                htmlContent = htmlContent.Replace("@[BankName]", swiftFields.BankName);
                htmlContent = htmlContent.Replace("@[AccNumber]", swiftFields.AccNumber);
                htmlContent = htmlContent.Replace("@[AccName]", swiftFields.AccName);
                htmlContent = htmlContent.Replace("@[AccHolderCountry]", swiftFields.AccHolderCountry);
                htmlContent = htmlContent.Replace("@[AccHolderZipCode]", swiftFields.AccHolderZipCode);
                htmlContent = htmlContent.Replace("@[AccHolderCity]", swiftFields.AccHolderCity);
                htmlContent = htmlContent.Replace("@[AccHolderAddress]", swiftFields.AccHolderAddress);
                htmlContent = htmlContent.Replace("@[DateOfTransaction]", dateOfTransaction.ToString("yyyy/MM/dd"));

                await HtmlToPdfAsync(htmlContent, SwiftDetailsBlobName(request.ClientId, initialRequestId), $"{dateOfTransaction:yyyyMMdd}_withdrawal {pd.FullName}.pdf");
                await SaveSwiftPdfReportToGoogleDriveAsync(request.ClientId, initialRequestId, request.AssetId);
            });
        }
Пример #6
0
        public async Task <IActionResult> EmailRequestAsync(EmailRequestCommand cmd)
        {
            var swiftCredentials = await _swiftCredentialsService.GetAsync(cmd.RegulationId, cmd.AssetId);

            var pd = await _personalDataService.GetAsync(cmd.ClientId);

            var asset = await _assetsService.TryGetAssetAsync(cmd.AssetId);

            _cqrsEngine.PublishEvent(new SwiftCredentialsRequestedEvent
            {
                Email                = pd.Email,
                ClientName           = pd.FullName,
                Amount               = cmd.Amount,
                Year                 = DateTime.UtcNow.Year.ToString(),
                AccountName          = swiftCredentials.AccountName,
                AccountNumber        = swiftCredentials.AccountNumber,
                AssetId              = swiftCredentials.AssetId,
                AssetSymbol          = asset.Symbol ?? asset.DisplayId,
                BankAddress          = swiftCredentials.BankAddress,
                Bic                  = swiftCredentials.BIC,
                CompanyAddress       = swiftCredentials.CompanyAddress,
                CorrespondentAccount = swiftCredentials.CorrespondentAccount,
                PurposeOfPayment     = await _purposeOfPaymentBuilder.Build(
                    swiftCredentials.PurposeOfPayment,
                    cmd.ClientId,
                    cmd.AssetId),
                RegulatorId = swiftCredentials.RegulatorId
            }, SwiftCredentialsBoundedContext.Name);

            return(Ok());
        }
        public async Task SendReminderEmail(IClientReminder reminder)
        {
            await _clientReminderRepository.DeleteAsync(reminder);

            var clientAcc = await _clientAccountService.GetClientByIdAsync(reminder.ClientId);

            if (clientAcc == null)
            {
                await _log.WriteInfoAsync(nameof(ClientReminderService), nameof(SendReminderEmail), $"client {reminder.ClientId} reminder cannot be processed - no client account found");
            }
            else
            {
                var pd = await _personalDataService.GetAsync(reminder.ClientId);

                if (pd == null)
                {
                    await _log.WriteInfoAsync(nameof(ClientReminderService), nameof(SendReminderEmail), $"client {reminder.ClientId} reminder cannot be processed - no personal data found");
                }
                else
                {
                    var reminderData = new KycRegReminderData
                    {
                        Year     = DateTime.UtcNow.Year.ToString(),
                        FullName = String.IsNullOrWhiteSpace(pd.FullName) ? pd.FirstName + " " + pd.LastName : pd.FullName,
                        Date     = DateTime.UtcNow.ToString("MMM dd, hh:mm tt", CultureInfo.InvariantCulture),
                        Subject  = "Lykke Wallet"
                    };
                    await _emailSender.SendEmailAsync(clientAcc.PartnerId, clientAcc.Email, reminderData); // send email reminder

                    await _log.WriteInfoAsync(nameof(ClientReminderService), nameof(SendReminderEmail), $"client {reminder.ClientId} reminder processed - email sent");
                }
            }
        }
Пример #8
0
        public async Task <IActionResult> GetAvailableMethods()
        {
            var model = new WithdrawalMethodsResponse();

            try
            {
                var assetsTask =
                    _assetsHelper.GetAssetsAvailableToClientAsync(_requestContext.ClientId, _requestContext.PartnerId);
                var pdTask = _personalDataService.GetAsync(_requestContext.ClientId);

                await Task.WhenAll(assetsTask, pdTask);

                var assets = assetsTask.Result.ToList();
                var pd     = pdTask.Result;

                var cryptos = new WithdrawalMethod
                {
                    Name   = "Cryptos",
                    Assets = assets
                             .Where(x => x.BlockchainWithdrawal)
                             .Select(x => x.Id)
                             .ToList()
                };

                var swift = new WithdrawalMethod
                {
                    Name   = "Swift",
                    Assets = assets
                             .Where(x => x.SwiftWithdrawal && (!_blockedWithdawalSettings.AssetByCountry.ContainsKey(x.Id) ||
                                                               !_blockedWithdawalSettings.AssetByCountry[x.Id]
                                                               .Contains(pd.CountryFromPOA,
                                                                         StringComparer.InvariantCultureIgnoreCase)))
                             .Select(x => x.Id)
                             .ToList()
                };

                model.WithdrawalMethods = new List <WithdrawalMethod> {
                    cryptos, swift
                };
            }
            catch (Exception ex)
            {
                _log.Error(ex, "Error getting available methods", context: $"clientId: {_requestContext.ClientId}, partnerId: {_requestContext.PartnerId}");
                model.WithdrawalMethods = new List <WithdrawalMethod>
                {
                    new WithdrawalMethod
                    {
                        Name   = "Cryptos",
                        Assets = Array.Empty <string>()
                    },
                    new WithdrawalMethod
                    {
                        Name   = "Swift",
                        Assets = Array.Empty <string>()
                    }
                };
            }

            return(Ok(model));
        }
Пример #9
0
        public bool IsUnitedKingdom()
        {
            var clientId = _requestContext.ClientId;

            var personalData = _personalDataService.GetAsync(clientId).Result;

            return(personalData.CountryFromPOA == UnitedKingdomIso3Code);
        }
Пример #10
0
        public async Task <TierInfoResponse> GetClientTierInfoAsync(string clientId)
        {
            var clientTask = _clientAccountClient.ClientAccountInformation.GetByIdAsync(clientId);
            var pdTask     = _personalDataService.GetAsync(clientId);

            await Task.WhenAll(clientTask, pdTask);

            ClientInfo    client = clientTask.Result;
            IPersonalData pd     = pdTask.Result;

            if (pd == null)
            {
                throw new ValidationApiException(HttpStatusCode.NotFound, "Client not found");
            }

            var tierInfo = await _tiersService.GetClientTierInfoAsync(client.Id, client.Tier, pd.CountryFromPOA);

            return(_mapper.Map <TierInfoResponse>(tierInfo));
        }
Пример #11
0
        public async Task <IActionResult> UserInfo()
        {
            try
            {
                var personalDataTask = _personalDataService.GetAsync(_requestContext.ClientId);
                var isKycNeededTask  = _kycStatusService.IsKycNeededAsync(_requestContext.ClientId);

                await Task.WhenAll(personalDataTask, isKycNeededTask);

                IPersonalData personalData = personalDataTask.Result;
                bool          isKycNeeded  = isKycNeededTask.Result;

                return(Ok(new UserInfoResponseModel
                {
                    Email = personalData?.Email,
                    FirstName = personalData?.FirstName,
                    LastName = personalData?.LastName,
                    KycStatus = (isKycNeeded
                        ? KycStatus.NeedToFillData
                        : KycStatus.Ok).ToApiModel()
                }));
            }
            catch (Exception e)
            {
                _log.Error(e, $"clientId = {_requestContext.ClientId}");

                return(StatusCode((int)HttpStatusCode.InternalServerError));
            }
        }
        private async Task FinalizeCommonTransfer(IBitcoinTransaction transaction, TransferContextData contextData)
        {
            foreach (var transfer in contextData.Transfers)
            {
                await _transferEventsRepository.SetIsSettledIfExistsAsync(transfer.ClientId, transfer.OperationId, true);

                var clientData = await _personalDataService.GetAsync(transfer.ClientId);

                if (transfer.Actions?.CashInConvertedOkEmail != null)
                {
                    await
                    _srvEmailsFacade.SendTransferCompletedEmail(clientData.Email, clientData.FullName,
                                                                transfer.Actions.CashInConvertedOkEmail.AssetFromId, transfer.Actions.CashInConvertedOkEmail.AmountFrom,
                                                                transfer.Actions.CashInConvertedOkEmail.AmountLkk, transfer.Actions.CashInConvertedOkEmail.Price, transaction.BlockchainHash);
                }

                if (transfer.Actions?.SendTransferEmail != null)
                {
                    await
                    _srvEmailsFacade.SendDirectTransferCompletedEmail(clientData.Email, clientData.FullName,
                                                                      transfer.Actions.SendTransferEmail.AssetId, transfer.Actions.SendTransferEmail.Amount,
                                                                      transaction.BlockchainHash);
                }

                if (transfer.Actions?.PushNotification != null)
                {
                    var clientAcc = await _clientAccountsRepository.GetByIdAsync(transfer.ClientId);

                    var asset = await _assetsService.TryGetAssetAsync(transfer.Actions.PushNotification.AssetId);

                    await _appNotifications.SendAssetsCreditedNotification(new[] { clientAcc.NotificationsId },
                                                                           transfer.Actions.PushNotification.Amount, transfer.Actions.PushNotification.AssetId,
                                                                           string.Format(TextResources.CreditedPushText, transfer.Actions.PushNotification.Amount.GetFixedAsString(asset.Accuracy),
                                                                                         transfer.Actions.PushNotification.AssetId));
                }
            }

            await _paymentTransactionsRepository.SetStatus(transaction.TransactionId, PaymentStatus.NotifyProcessed);
        }
Пример #13
0
        public async Task <IActionResult> SetupGoogle2FaVerify([FromBody] GoogleSetupVerifyRequest model)
        {
            try
            {
                if (await _confirmationCodesClient.Google2FaClientHasSetupAsync(_requestContext.ClientId))
                {
                    throw LykkeApiErrorException.BadRequest(LykkeApiErrorCodes.Service.SecondFactorAlreadySetup);
                }

                var pd = await _personalDataService.GetAsync(_requestContext.ClientId);

                var resp = await _confirmationCodesClient.Google2FaVerifySetupAsync(
                    new VerifySetupGoogle2FaRequest
                {
                    ClientId = _requestContext.ClientId,
                    Phone    = pd.ContactPhone,
                    SmsCode  = model.Code,
                    GaCode   = model.GaCode
                });

                return(Ok(new GoogleSetupVerifyResponse {
                    IsValid = resp.IsValid
                }));
            }
            catch (ApiException e)
            {
                switch (e.StatusCode)
                {
                case HttpStatusCode.BadRequest:
                    throw LykkeApiErrorException.BadRequest(LykkeApiErrorCodes.Service.InconsistentState);

                case HttpStatusCode.Forbidden:
                    throw LykkeApiErrorException.BadRequest(LykkeApiErrorCodes.Service.MaxAttemptsReached);
                }

                throw;
            }
        }
        private async Task Execute(ITimerTrigger timer, TimerTriggeredHandlerArgs args, CancellationToken cancellationToken)
        {
            var limitsReached = await _limitsService.GetAllLimitReachedAsync();

            if (limitsReached.Count == 0)
            {
                return;
            }

            var clientIds = limitsReached.Select(x => x.ClientId).Distinct().ToArray();

            var clients = (await _clientAccountClient.ClientAccountInformation.GetClientsByIdsAsync(
                               new ClientIdsRequest {
                Ids = clientIds
            })).ToList();

            var personalDatas = (await _personalDataService.GetAsync(clientIds)).ToList();

            foreach (var limit in limitsReached)
            {
                var client = clients.FirstOrDefault(x => x.Id == limit.ClientId);
                var pd     = personalDatas.FirstOrDefault(x => x.Id == limit.ClientId);

                if (client == null || pd == null)
                {
                    _log.Warning("Client or personal data not found", context: limit.ClientId);
                    continue;
                }

                var currentLimitSettingsTask = _limitsService.GetClientLimitSettingsAsync(limit.ClientId, client.Tier, pd.CountryFromPOA);
                var checkAmountTask          = _limitsService.GetClientDepositAmountAsync(limit.ClientId);

                await Task.WhenAll(currentLimitSettingsTask, checkAmountTask);

                if (currentLimitSettingsTask.Result?.MaxLimit == null)
                {
                    continue;
                }

                var checkAmount = checkAmountTask.Result;

                if (checkAmount < currentLimitSettingsTask.Result.MaxLimit.Value)
                {
                    await _limitsService.RemoveLimitReachedAsync(limit.ClientId);

                    _log.Info("Limit reached removed", context: limit.ClientId);
                }
            }
        }
Пример #15
0
        public async Task <ISpiderCheckResult> CheckAsync(string clientId)
        {
            var personalData = await _personalDataService.GetAsync(clientId);

            if (personalData == null)
            {
                throw new InvalidOperationException($"No personal data for ClientId:{clientId} but spider check requested");
            }

            var request = new checkPerson(FormRequest(personalData));
            var result  = await PerformCheck(request);

            var mappedResult = MapResult(personalData, result);

            return(await _repository.AddAsync(mappedResult));
        }
Пример #16
0
        private async Task <ClientModel> GetClientModel()
        {
            var personalData = await _personalDataService.GetAsync(_requestContext.ClientId);

            return(new ClientModel
            {
                Id = new Guid(_requestContext.ClientId),
                TradesBlocked = (await _clientAccountClient.GetCashOutBlockAsync(personalData.Id)).TradesBlocked,
                BackupDone = (await _clientAccountClient.GetBackupAsync(personalData.Id)).BackupDone,
                KycStatus = (await _kycStatusService.GetKycStatusAsync(personalData.Id)).ToString(),
                PersonalData = new PersonalDataModel
                {
                    Country = personalData.Country,
                    CountryFromID = personalData.CountryFromID,
                    CountryFromPOA = personalData.CountryFromPOA
                }
            });
        }
        private async Task SendWhitelistEmail(string clientId, string asset, string address, string tag)
        {
            var clientAccountTask = _clientAccountService.ClientAccountInformation.GetByIdAsync(clientId);
            var pdTask            = _personalDataService.GetAsync(clientId);

            await Task.WhenAll(clientAccountTask, pdTask);

            var clientAccount = clientAccountTask.Result;
            var pd            = pdTask.Result;

            var template = await _templateFormatter.FormatAsync("AddressWhitelistedTemplate", clientAccount.PartnerId,
                                                                "EN", new { FullName = pd.FullName, Asset = asset, Address = address, Tag = tag ?? "---", Year = DateTime.UtcNow.Year });

            var msgData = new PlainTextData
            {
                Sender  = pd.Email,
                Subject = template.Subject,
                Text    = template.HtmlBody
            };

            await _emailSender.SendEmailAsync(clientAccount.PartnerId, pd.Email, msgData);
        }
Пример #18
0
        public async Task <IActionResult> GetLastByDate(string clientId)
        {
            var lastPaymentTransaction = await _paymentTransactionsService.GetLastByDateAsync(clientId);

            var personalData = await _personalDataService.GetAsync(clientId);

            if (personalData == null)
            {
                return(BadRequest("A user with such an clientId does not exist."));
            }

            var isCreditVoucherOrFxpaygate = lastPaymentTransaction != null &&
                                             (lastPaymentTransaction.PaymentSystem == CashInPaymentSystem.CreditVoucher ||
                                              lastPaymentTransaction.PaymentSystem == CashInPaymentSystem.Fxpaygate);

            var result = isCreditVoucherOrFxpaygate
                ? PaymentTransactionResponse.Create(lastPaymentTransaction, personalData)
                : PaymentTransactionResponse.Create(personalData);

            result.Country = _countryComponent.GetCountryIso3Code(result.Country);

            return(Ok(result));
        }
Пример #19
0
        public async Task <IActionResult> UserInfo()
        {
            IPersonalData personalData;

            try
            {
                personalData = await _personalDataService.GetAsync(_requestContext.ClientId);
            }
            catch (Exception e)
            {
                await _log.WriteErrorAsync(nameof(ClientController), nameof(UserInfo),
                                           $"clientId = {_requestContext.ClientId}", e);

                return(StatusCode((int)HttpStatusCode.InternalServerError));
            }

            return(Ok(new UserInfoResponseModel
            {
                Email = personalData?.Email,
                FirstName = personalData?.FirstName,
                LastName = personalData?.LastName
            }));
        }
Пример #20
0
        public async Task NotifyAsync(IPaymentTransaction pt)
        {
            string emailAddress = string.Empty;

            try
            {
                var pdTask  = _personalDataService.GetAsync(pt.ClientId);
                var accTask = _clientAccountClient.ClientAccountInformation.GetByIdAsync(pt.ClientId);

                await Task.WhenAll(pdTask, accTask);

                var acc = accTask.Result;
                var pd  = pdTask.Result;

                emailAddress = pd.Email;

                await _emailSender.SendEmailAsync(acc.PartnerId, emailAddress, new DirectTransferCompletedData
                {
                    Amount     = pt.Amount,
                    AssetId    = pt.AssetId,
                    ClientName = pd.FullName
                });

                var body = $"Client: {pd.Email}, "
                           + $"Payment system amount: {pt.AssetId} {pt.Amount:0.00}, "
                           + $"Deposited amount: {pt.DepositedAssetId} {pt.DepositedAmount}, "
                           + $"PaymentSystem: {pt.PaymentSystem}";

                // email to Payments group
                await _emailSender.BroadcastEmailAsync(acc.PartnerId, BroadcastGroup.Payments, $"{pt.PaymentSystem}, payment notification Ok", body);
            }
            catch (Exception exc)
            {
                _log.Error("PaymentOkEmailSender.NotifyAsync", exc, emailAddress);
            }
        }
        public async Task Handle(SwiftCashoutCreatedEvent evt)
        {
            var client = await _personalDataService.GetAsync(evt.ClientId);

            await _cashoutRequestLogRepository.AddRecordAsync("Client", evt.RequestId, client.FullName, client.Email, CashoutRequestStatus.Pending, evt.VolumeSize);
        }
        public async Task <IActionResult> DisplayUserProfile(string id)
        {
            if (!id.IsGuid())
            {
                return(View("ProfileNotFound"));
            }

            var streamsIds = await _streamsIdRepository.GetStreamsIdsAsync();

            var userStreamsId = streamsIds.FirstOrDefault(x => x.StreamsId == id);

            if (userStreamsId == null)
            {
                return(View("ProfileNotFound"));
            }

            var clientId = userStreamsId.ClientId;

            var profile = await _personalDataService.GetAsync(clientId);

            if (profile == null)
            {
                return(View("ProfileNotFound"));
            }

            var avatars = await _personalDataService.GetClientAvatarsAsync(new List <string> {
                clientId
            });

            var user = UserModel.GetAuthenticatedUser(User.Identity);

            if (profile.Id == user.Id && profile.FirstName != user.FirstName)
            {
                var newIdentity = ClaimsHelper.UpdateFirstNameClaim(User.Identity, profile.FirstName);
                var principal   = new ClaimsPrincipal();
                principal.AddIdentity(newIdentity);
                await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal);
            }

            var commentsViewModel = new CommentsViewModel
            {
                CommentsList  = await GetUserComments(profile.Email),
                CommentAvatar = avatars[clientId]
            };

            var userProfileViewModel = new UserProfileViewModel
            {
                Profile              = profile,
                AvatarUrl            = avatars[clientId],
                WinningsSum          = await GetUserWinnigsSum(profile.Email),
                CreatedProjects      = await GetCreatedProjects(profile.Email),
                ParticipatedProjects = await GetParticipatedProjects(profile.Email),
                WonProjects          = await GetWonProjects(profile.Email),
                Comments             = commentsViewModel,
                AuthLink             = _settings.LykkeStreams.Authentication.Authority,
                IsLykkeMember        = await IsUserLykkeMember(profile.Email),
                ExpertedProjects     = await GetExpertedProjects(profile.Email)
            };

            return(View("~/Views/UserProfile/UserProfile.cshtml", userProfileViewModel));
        }
        public async Task Handle(ClientDepositedEvent evt, ICommandSender commandSender)
        {
            var clientAccountTask = _clientAccountClient.ClientAccountInformation.GetByIdAsync(evt.ClientId);
            var pdTask            = _personalDataService.GetAsync(evt.ClientId);

            await Task.WhenAll(clientAccountTask, pdTask);

            ClientInfo    clientAccount = clientAccountTask.Result;
            IPersonalData pd            = pdTask.Result;

            if (clientAccount == null)
            {
                return;
            }

            await _limitsService.SaveDepositOperationAsync(_mapper.Map <DepositOperation>(evt));

            LimitSettings currentLimitSettings = await _limitsService.GetClientLimitSettingsAsync(evt.ClientId, clientAccount.Tier, pd.CountryFromPOA);

            if (currentLimitSettings?.MaxLimit == null)
            {
                return;
            }

            var checkAmountTask  = _limitsService.GetClientDepositAmountAsync(evt.ClientId);
            var pushSettingsTask = _clientAccountClient.ClientSettings.GetPushNotificationAsync(evt.ClientId);

            await Task.WhenAll(checkAmountTask, pushSettingsTask);

            var checkAmount  = checkAmountTask.Result;
            var pushSettings = pushSettingsTask.Result;

            if (checkAmount > currentLimitSettings.MaxLimit.Value)
            {
                await _limitsService.SetLimitReachedAsync(evt.ClientId, checkAmount,
                                                          currentLimitSettings.MaxLimit.Value, evt.BaseAsset);

                if (pushSettings.Enabled && !string.IsNullOrEmpty(clientAccount.NotificationsId))
                {
                    await SendPushNotificationAsync(clientAccount.PartnerId, clientAccount.NotificationsId,
                                                    "PushLimitReachedTemplate", new { }, commandSender);
                }
            }

            if (checkAmount <= currentLimitSettings.MaxLimit.Value)
            {
                bool needNotification = _settingsService.IsLimitReachedForNotification(checkAmount, currentLimitSettings.MaxLimit.Value);

                if (!needNotification)
                {
                    return;
                }

                if (pushSettings.Enabled && !string.IsNullOrEmpty(clientAccount.NotificationsId))
                {
                    await SendPushNotificationAsync(clientAccount.PartnerId, clientAccount.NotificationsId,
                                                    "PushLimitPercentReachedTemplate", new {
                        CurrentAmount = checkAmount,
                        Limit         = currentLimitSettings.MaxLimit.Value,
                        Percent       = Math.Round(checkAmount / currentLimitSettings.MaxLimit.Value * 100),
                        FullName      = pd.FullName,
                        Asset         = evt.BaseAsset
                    }, commandSender);
                }
            }
        }
        private async Task SendNotificationAsync(TierUpgradeRequestChangedEvent evt, ICommandSender commandSender)
        {
            var clientAccTask    = _clientAccountClient.ClientAccountInformation.GetByIdAsync(evt.ClientId);
            var personalDataTask = _personalDataService.GetAsync(evt.ClientId);
            var pushSettingsTask = _clientAccountClient.ClientSettings.GetPushNotificationAsync(evt.ClientId);

            await Task.WhenAll(clientAccTask, personalDataTask, pushSettingsTask);

            var  clientAcc    = clientAccTask.Result;
            var  personalData = personalDataTask.Result;
            var  pushSettings = pushSettingsTask.Result;
            bool pushEnabled  = pushSettings.Enabled && !string.IsNullOrEmpty(clientAcc.NotificationsId);

            Task <EmailMessage> emailTemplateTask = Task.FromResult <EmailMessage>(null);
            Task <EmailMessage> pushTemplateTask  = Task.FromResult <EmailMessage>(null);
            string type = string.Empty;

            try
            {
                switch (evt.NewStatus)
                {
                case KycStatus.Ok:
                    var tierInfo = await _tiersService.GetClientTierInfoAsync(evt.ClientId, clientAcc.Tier, personalData.CountryFromPOA);

                    bool   noAmountTemplate = tierInfo.CurrentTier.MaxLimit == 0;
                    string upgradeTemplate  =
                        tierInfo.CurrentTier.Tier == AccountTier.Advanced
                                ? "TierUpgradedToProTemplate"
                                : "TierUpgradedTemplate";

                    emailTemplateTask = _templateFormatter.FormatAsync(noAmountTemplate ? "TierUpgradedNoAmountTemplate" : upgradeTemplate, clientAcc.PartnerId,
                                                                       "EN", new
                    {
                        Tier   = evt.Tier.ToString(),
                        Year   = DateTime.UtcNow.Year,
                        Amount = $"{tierInfo.CurrentTier.MaxLimit} {tierInfo.CurrentTier.Asset}",
                        //TODO: remove when TierUpgradedTemplate will be updated (@[UpgradeText] removed)
                        UpgradeText = string.Empty
                    });

                    if (pushEnabled)
                    {
                        pushTemplateTask = _templateFormatter.FormatAsync(noAmountTemplate ? "PushTierUpgradedNoAmountTemplate" : "PushTierUpgradedTemplate", clientAcc.PartnerId, "EN",
                                                                          new { Tier = evt.Tier.ToString(), Amount = $"{tierInfo.CurrentTier.MaxLimit} {tierInfo.CurrentTier.Asset}" });
                    }

                    type = NotificationType.TierUpgraded.ToString();
                    break;

                case KycStatus.NeedToFillData:
                    var documents = await _kycDocumentsService.GetCurrentDocumentsAsync(evt.ClientId);

                    var declinedDocuments = documents
                                            .Where(item => item.Status.Name == CheckDocumentPorcess.DeclinedState.Name)
                                            .ToArray();

                    if (declinedDocuments.Length > 0)
                    {
                        string documentsAsHtml = GetDocumentsInfo(declinedDocuments);
                        emailTemplateTask = _templateFormatter.FormatAsync("DeclinedDocumentsTemplate", clientAcc.PartnerId,
                                                                           "EN", new { FullName = personalData.FullName, DocumentsAsHtml = documentsAsHtml, Year = DateTime.UtcNow.Year });
                    }

                    if (pushEnabled)
                    {
                        pushTemplateTask = _templateFormatter.FormatAsync("PushKycNeedDocumentsTemplate", clientAcc.PartnerId, "EN", new { });
                    }

                    type = NotificationType.KycNeedToFillDocuments.ToString();
                    break;

                case KycStatus.Rejected:
                    emailTemplateTask = _templateFormatter.FormatAsync("TierUpgradeRejectedTemplate", clientAcc.PartnerId,
                                                                       "EN", new { FullName = personalData.FullName, Tier = evt.Tier.ToString(), Year = DateTime.UtcNow.Year });
                    break;
                }
            }
            finally
            {
                await Task.WhenAll(emailTemplateTask, pushTemplateTask);

                var sendEmailTask = Task.CompletedTask;

                if (emailTemplateTask.Result != null)
                {
                    var msgData = new PlainTextData
                    {
                        Sender  = personalData.Email,
                        Subject = emailTemplateTask.Result.Subject,
                        Text    = emailTemplateTask.Result.HtmlBody
                    };

                    sendEmailTask = _emailSender.SendEmailAsync(clientAcc.PartnerId, personalData.Email, msgData);
                }

                if (pushEnabled && pushTemplateTask.Result != null)
                {
                    commandSender.SendCommand(new TextNotificationCommand
                    {
                        NotificationIds = new[] { clientAcc.NotificationsId },
                        Type            = type,
                        Message         = pushTemplateTask.Result.Subject
                    }, PushNotificationsBoundedContext.Name);
                }

                await sendEmailTask;
            }
        }
Пример #25
0
        public async Task ChangePhoneAsync(string clientId, string phoneNumber, string changer)
        {
            var dataBefore = await _personalDataService.GetAsync(clientId);

            await _clientAccountsRepository.ChangePhoneAsync(clientId, phoneNumber);

            await _personalDataService.ChangeContactPhoneAsync(clientId, phoneNumber);

            var dataAfter = await _personalDataService.GetAsync(clientId);

            await
            _auditLogRepository.AddAuditRecordAsync(clientId, dataBefore, dataAfter, AuditRecordType.PersonalData,
                                                    changer);
        }
Пример #26
0
        public async Task <IActionResult> Post(PaymentUrlDataRequest model)
        {
            if (string.IsNullOrWhiteSpace(model.AssetId))
            {
                model.AssetId = LykkeConstants.UsdAssetId;
            }

            var phoneNumberE164 = model.Phone.PreparePhoneNum().ToE164Number();
            var countryAsIso3   = _countryComponent.GetCountryIso3Code(model.Country);
            var pd = await _personalDataService.GetAsync(model.ClientId);

            CashInPaymentSystem paymentSystem;

            switch (model.DepositOption)
            {
            case DepositOption.BankCard:
                paymentSystem = CashInPaymentSystem.Fxpaygate;
                break;

            case DepositOption.Other:
                paymentSystem = CashInPaymentSystem.CreditVoucher;
                break;

            default:
                paymentSystem = CashInPaymentSystem.Unknown;
                break;
            }

            var transactionId = await _paymentUrlDataService.GenerateNewTransactionIdAsync();

            const string formatOfDateOfBirth = "yyyy-MM-dd";

            var info = OtherPaymentInfo.Create(
                model.FirstName,
                model.LastName,
                model.City,
                model.Zip,
                model.Address,
                countryAsIso3,
                model.Email,
                phoneNumberE164,
                pd.DateOfBirth?.ToString(formatOfDateOfBirth),
                model.OkUrl,
                model.FailUrl,
                model.CancelUrl)
                       .ToJson();

            var bankCardsFee = await _feeCalculatorClient.GetBankCardFees();

            var asset = await _assetsService.AssetGetAsync(model.AssetId);

            var feeAmount          = Math.Round(model.Amount * bankCardsFee.Percentage, 15);
            var feeAmountTruncated = feeAmount.TruncateDecimalPlaces(asset.Accuracy, true);

            var urlData = await _paymentUrlDataService.GetUrlDataAsync(
                paymentSystem.ToString(),
                transactionId,
                model.ClientId,
                model.Amount + feeAmountTruncated,
                model.AssetId,
                model.WalletId,
                countryAsIso3,
                info);

            await _paymentTransactionEventLogService.InsertPaymentTransactionEventLogAsync(new PaymentTransactionEventLog
            {
                PaymentTransactionId = transactionId,
                Message  = "Payment Url has created",
                DateTime = DateTime.UtcNow,
                TechData = urlData.PaymentUrl,
                Who      = model.ClientId
            });

            if (!string.IsNullOrEmpty(urlData.ErrorMessage))
            {
                await _log.WriteWarningAsync(nameof(PaymentUrlDataController), nameof(Post), model.ToJson(),
                                             urlData.ErrorMessage, DateTime.UtcNow);

                return(BadRequest(new
                {
                    message = urlData.ErrorMessage
                }));
            }

            await _paymentTransactionsService.InsertPaymentTransactionAsync(
                new PaymentTransaction
            {
                Amount           = model.Amount,
                Status           = PaymentStatus.Created,
                PaymentSystem    = paymentSystem,
                FeeAmount        = feeAmountTruncated,
                Id               = transactionId,
                ClientId         = model.ClientId,
                AssetId          = model.AssetId,
                DepositedAssetId = model.AssetId,
                WalletId         = model.WalletId,
                Created          = DateTime.UtcNow,
                Info             = info
            });

            await _paymentTransactionEventLogService.InsertPaymentTransactionEventLogAsync(new PaymentTransactionEventLog
            {
                PaymentTransactionId = transactionId,
                Message  = "Registered",
                DateTime = DateTime.UtcNow,
                TechData = string.Empty,
                Who      = model.ClientId
            });

            // mode=iframe is for Mobile version
            if (!string.IsNullOrWhiteSpace(urlData.PaymentUrl))
            {
                urlData.PaymentUrl = urlData.PaymentUrl
                                     + (urlData.PaymentUrl.Contains("?") ? "&" : "?")
                                     + "mode=iframe";
            }

            var result = new PaymentUrlDataResponse
            {
                Url       = urlData.PaymentUrl,
                OkUrl     = urlData.OkUrl,
                FailUrl   = urlData.FailUrl,
                CancelUrl = urlData.CancelUrl,
            };

            return(Ok(result));
        }
        private async Task <IEnumerable <KycOfficersPerformanceRow> > GenerateKycOfficersPerformance(DateTime from)
        {
            var startDate = from;
            var endDate   = DateTime.Today.AddDays(-1);

            var datesArray = Enumerable.Range(0, 1 + endDate.Subtract(startDate).Days)
                             .Select(offset => startDate.AddDays(offset))
                             .ToArray();

            List <KycStatusLogRecord> auditLogEntities = null;

            var reportRows = new List <KycOfficersPerformanceRow>();

            foreach (var startOfDay in datesArray)
            {
                try
                {
                    var existedJsonRows = await _reportRepository.GetKycOfficersPerformanceJsonRows(startOfDay, startOfDay);

                    if (existedJsonRows.Any())
                    {
                        continue;
                    }

                    if (auditLogEntities == null)
                    {
                        auditLogEntities = await GetKycStatusLogRecords(startDate, endDate);
                    }

                    var itemsTodayGroups =
                        auditLogEntities.Where(i => i.Date >= startOfDay && i.Date < startOfDay.AddDays(1))
                        .GroupBy(i => i.KycOfficer)
                        .ToList();

                    if (!itemsTodayGroups.Any())
                    {
                        await _reportRepository.InsertRow(KycOfficersPerformanceRow.MakeNoDataRow(startOfDay));
                    }

                    foreach (var itemsToday in itemsTodayGroups)
                    {
                        var kycOfficer = itemsToday.Key;

                        List <KycOfficersPerformanceRow> onBoarded  = new List <KycOfficersPerformanceRow>();
                        List <KycOfficersPerformanceRow> declined   = new List <KycOfficersPerformanceRow>();
                        List <KycOfficersPerformanceRow> toResubmit = new List <KycOfficersPerformanceRow>();

                        foreach (var row in itemsToday.OrderBy(i => i.Date))
                        {
                            if ((row.StatusCurrent == KycStatus.ReviewDone || row.StatusCurrent == KycStatus.Ok) && IsPending(row))
                            {
                                onBoarded.Add(
                                    new KycOfficersPerformanceRow()
                                {
                                    ReportDay  = startOfDay,
                                    KycOfficer = kycOfficer,
                                    Operation  = KycOfficerReportOperationType.OnBoarded,
                                    ClientId   = row.ClientId
                                });
                            }
                            if ((row.StatusCurrent == KycStatus.RestrictedArea || row.StatusCurrent == KycStatus.Rejected) && IsPending(row))
                            {
                                declined.Add(
                                    new KycOfficersPerformanceRow()
                                {
                                    ReportDay  = startOfDay,
                                    KycOfficer = kycOfficer,
                                    Operation  = KycOfficerReportOperationType.Declined,
                                    ClientId   = row.ClientId
                                });
                            }
                            if (row.StatusCurrent == KycStatus.NeedToFillData && IsPending(row))
                            {
                                toResubmit.Add(
                                    new KycOfficersPerformanceRow()
                                {
                                    ReportDay  = startOfDay,
                                    KycOfficer = kycOfficer,
                                    Operation  = KycOfficerReportOperationType.ToResubmit,
                                    ClientId   = row.ClientId
                                });
                            }
                        }

                        reportRows.AddRange(onBoarded);
                        reportRows.AddRange(declined);
                        reportRows.AddRange(toResubmit);

                        if (onBoarded.Count == 0 && declined.Count == 0 && toResubmit.Count == 0)
                        {
                            await _reportRepository.InsertRow(KycOfficersPerformanceRow.MakeNoDataRow(startOfDay));
                        }
                    }
                }
                catch (Exception ex)
                {
                    await _log.WriteErrorAsync("SrvReports", "GenerateKycOfficersPerformance (process day)", startOfDay.ToString(), ex);
                }
            }

            var clientIds = reportRows.Select(row => row.ClientId).Where(id => !string.IsNullOrEmpty(id)).Distinct();

            if (reportRows.Count > 0)
            {
                var personalData = (await _personalDataService.GetAsync(clientIds)).ToDictionary(key => key.Id, val => val.Email);
                foreach (var reportRow in reportRows)
                {
                    try
                    {
                        reportRow.ClientEmail = string.Empty;

                        if (string.IsNullOrWhiteSpace(reportRow.ClientId))
                        {
                            continue;
                        }

                        if (personalData.ContainsKey(reportRow.ClientId))
                        {
                            reportRow.ClientEmail = personalData[reportRow.ClientId];
                        }

                        await _reportRepository.InsertRow(reportRow);
                    }
                    catch (Exception ex)
                    {
                        await _log.WriteErrorAsync("SrvReports", "GenerateKycOfficersPerformance (insert new rows)", null, ex);
                    }
                }
            }

            return(reportRows);
        }
        public async Task <ClientSwiftCredentials> GetSwiftCredentialsAsync(string clientId, string legalEntityId, string assetId)
        {
            var clientSwiftCredentials = await _clientSwiftCredentialsCache.GetAsync(clientId, legalEntityId, assetId);

            if (clientSwiftCredentials != null)
            {
                return(clientSwiftCredentials);
            }

            var asset = await _assetsServiceWithCache.TryGetAssetAsync(assetId);

            if (asset == null)
            {
                await _log.WriteWarningAsync(nameof(ClientService), nameof(GetSwiftCredentialsAsync),
                                             new { clientId, legalEntityId, assetId }.ToJson(), "Asset not found.");

                return(null);
            }

            var swiftCredentialsList = await _swiftCredentialsRepository.FindAsync(legalEntityId, assetId);

            if (swiftCredentialsList.Count > 1)
            {
                await _log.WriteWarningAsync(nameof(ClientService), nameof(GetSwiftCredentialsAsync),
                                             new { legalEntityId, assetId }.ToJson(), "Ambiguous swift credentials.");

                return(null);
            }

            var swiftCredentials = swiftCredentialsList.FirstOrDefault();

            if (swiftCredentials == null)
            {
                await _log.WriteWarningAsync(nameof(ClientService), nameof(GetSwiftCredentialsAsync),
                                             new { clientId, legalEntityId, assetId }.ToJson(), "Swift credentials not found.");

                return(null);
            }

            var personalData = await _personalDataService.GetAsync(clientId);

            if (personalData == null)
            {
                await _log.WriteWarningAsync(nameof(ClientService), nameof(GetSwiftCredentialsAsync),
                                             new { clientId, legalEntityId, assetId }.ToJson(), "Personal data not found.");

                return(null);
            }

            var assetTitle = string.IsNullOrEmpty(asset.DisplayId) ? asset.Id : asset.DisplayId;

            var purposeOfPayment = string.Format(swiftCredentials.PurposeOfPaymentFormat, assetTitle,
                                                 personalData.Email?.Replace("@", "."));

            clientSwiftCredentials = new ClientSwiftCredentials
            {
                Bic                  = swiftCredentials.Bic,
                AccountName          = swiftCredentials.AccountName,
                AccountNumber        = swiftCredentials.AccountNumber,
                PurposeOfPayment     = purposeOfPayment,
                BankAddress          = swiftCredentials.BankAddress,
                CompanyAddress       = swiftCredentials.CompanyAddress,
                CorrespondentAccount = swiftCredentials.CorrespondentAccount
            };

            await _clientSwiftCredentialsCache.SetAsync(clientId, legalEntityId, assetId, clientSwiftCredentials);

            return(clientSwiftCredentials);
        }