public async Task <IActionResult> Cashout([FromBody] CreateCashoutRequest cmd, [FromQuery] Guid?id) { if (string.IsNullOrWhiteSpace(cmd.DestinationAddress) || string.IsNullOrWhiteSpace(cmd.AssetId) || cmd.Volume == 0m) { throw LykkeApiErrorException.BadRequest(LykkeApiErrorCodes.Service.InvalidInput); } var asset = await _assetsServiceWithCache.TryGetAssetAsync(cmd.AssetId); if (asset == null) { return(NotFound($"Asset '{cmd.AssetId}' not found.")); } var balance = await _balancesClient.GetClientBalanceByAssetId(new ClientBalanceByAssetIdModel(cmd.AssetId, _requestContext.ClientId)); var cashoutSettings = await _clientAccountClient.ClientSettings.GetCashOutBlockSettingsAsync(_requestContext.ClientId); var kycStatus = await _kycStatusService.GetKycStatusAsync(_requestContext.ClientId); if (_baseSettings.EnableTwoFactor) { try { if ((await _confirmationCodesClient.Google2FaIsClientBlacklistedAsync(_requestContext.ClientId)).IsClientBlacklisted) { throw LykkeApiErrorException.Forbidden(LykkeApiErrorCodes.Service.SecondFactorCheckForbiden); } } catch (ApiException e) { if (e.StatusCode == HttpStatusCode.BadRequest) { throw LykkeApiErrorException.Forbidden(LykkeApiErrorCodes.Service.TwoFactorRequired); } } } var operationId = id ?? Guid.NewGuid(); var cashoutCommand = new CreateCashoutCommand { OperationId = operationId, DestinationAddress = cmd.DestinationAddress, DestinationAddressExtension = cmd.DestinationAddressExtension, Volume = cmd.Volume, Asset = new AssetCashoutModel { Id = asset.Id, DisplayId = asset.DisplayId, MultiplierPower = asset.MultiplierPower, AssetAddress = asset.AssetAddress, Accuracy = asset.Accuracy, BlockchainIntegrationLayerId = asset.BlockchainIntegrationLayerId, Blockchain = asset.Blockchain.ToString(), Type = asset.Type?.ToString(), IsTradable = asset.IsTradable, IsTrusted = asset.IsTrusted, KycNeeded = asset.KycNeeded, BlockchainWithdrawal = asset.BlockchainWithdrawal, CashoutMinimalAmount = (decimal)asset.CashoutMinimalAmount, LowVolumeAmount = (decimal?)asset.LowVolumeAmount ?? 0, LykkeEntityId = asset.LykkeEntityId }, Client = new ClientCashoutModel { Id = new Guid(_requestContext.ClientId), Balance = balance?.Balance ?? 0, CashOutBlocked = cashoutSettings.CashOutBlocked, KycStatus = kycStatus.ToString(), ConfirmationType = "google" }, GlobalSettings = new GlobalSettingsCashoutModel { MaxConfirmationAttempts = _baseSettings.MaxTwoFactorConfirmationAttempts, TwoFactorEnabled = _baseSettings.EnableTwoFactor, CashOutBlocked = false, // TODO FeeSettings = new FeeSettingsCashoutModel { TargetClients = new Dictionary <string, string> { { "Cashout", _feeSettings.TargetClientId.Cashout } } } } }; _cqrsEngine.SendCommand(cashoutCommand, "apiv2", OperationsBoundedContext.Name); return(Created(Url.Action("Get", new { operationId }), operationId)); }
public async Task <Guid> CreateWithdrawalAsync( string requestId, string clientId, string walletId, string assetId, decimal volume, string destinationAddress, string destinationAddressExtension) { var uniqueRequestId = $"{walletId}_{requestId}"; var validationResult = await _validationService.ValidateWithdrawalRequestAsync(assetId, volume); if (validationResult != null) { throw HftApiException.Create(validationResult.Code, validationResult.Message).AddField(validationResult.FieldName); } var operationId = Guid.NewGuid(); var payload = await _idempotencyService.CreateEntityOrGetPayload(uniqueRequestId, operationId.ToString()); if (payload != null) { operationId = Guid.Parse(payload); } var asset = await _assetsService.GetAssetByIdAsync(assetId); if (asset.BlockchainIntegrationType != BlockchainIntegrationType.Sirius) { throw HftApiException.Create(HftApiErrorCode.ActionForbidden, "Asset unavailable"); } var balances = await _balanceService.GetBalancesAsync(walletId); var cashoutSettings = await _clientAccountClient.ClientSettings.GetCashOutBlockSettingsAsync(clientId); var kycStatus = await _kycStatusService.GetKycStatusAsync(clientId); var cashoutCommand = new CreateCashoutCommand { OperationId = operationId, WalletId = walletId, DestinationAddress = destinationAddress, DestinationAddressExtension = destinationAddressExtension, Volume = volume, Asset = new AssetCashoutModel { Id = asset.AssetId, DisplayId = asset.Symbol, MultiplierPower = asset.MultiplierPower, AssetAddress = asset.AssetAddress, Accuracy = asset.Accuracy, BlockchainIntegrationLayerId = asset.BlockchainIntegrationLayerId, Blockchain = asset.Blockchain.ToString(), Type = asset.Type?.ToString(), IsTradable = asset.IsTradable, IsTrusted = asset.IsTrusted, KycNeeded = asset.KycNeeded, BlockchainWithdrawal = asset.BlockchainWithdrawal, CashoutMinimalAmount = (decimal)asset.CashoutMinimalAmount, LowVolumeAmount = (decimal?)asset.LowVolumeAmount ?? 0, LykkeEntityId = asset.LykkeEntityId, SiriusAssetId = asset.SiriusAssetId, BlockchainIntegrationType = Lykke.Service.Assets.Client.Models.BlockchainIntegrationType.Sirius }, Client = new ClientCashoutModel { Id = new Guid(clientId), Balance = balances.SingleOrDefault(x => x.AssetId == assetId)?.Available ?? 0, CashOutBlocked = cashoutSettings.CashOutBlocked, KycStatus = kycStatus.ToString() }, GlobalSettings = new GlobalSettingsCashoutModel { MaxConfirmationAttempts = -1, TwoFactorEnabled = false, CashOutBlocked = false, // TODO FeeSettings = new FeeSettingsCashoutModel { TargetClients = new Dictionary <string, string> { { "Cashout", _feeSettings.WithdrawalFeeDestinationClientId } } } } }; _cqrsEngine.SendCommand(cashoutCommand, "hft-api", OperationsBoundedContext.Name); return(operationId); }