public async Task <IActionResult> GetCandles([FromQuery] CandleSticksRequestModel request) { try { var assetPair = (await _assetPairs.Values()).FirstOrDefault(x => x.Id == request.AssetPairId); if (assetPair == null) { return(NotFound("Asset pair not found")); } var candleHistoryService = _candlesServiceProvider.Get(request.Type); var candles = await candleHistoryService.GetCandlesHistoryAsync( request.AssetPairId, request.PriceType, request.TimeInterval, request.FromMoment, request.ToMoment); var baseAsset = await _assetsService.AssetGetAsync(assetPair.BaseAssetId); var quotingAsset = await _assetsService.AssetGetAsync(assetPair.QuotingAssetId); return(Ok( candles.ToResponseModel( baseAsset.DisplayAccuracy ?? baseAsset.Accuracy, quotingAsset.DisplayAccuracy ?? quotingAsset.Accuracy))); } catch (ErrorResponseException ex) { var errors = ex.Error.ErrorMessages.Values.SelectMany(s => s.Select(ss => ss)); return(NotFound($"{string.Join(',', errors)}")); } }
private async Task ProcessTrade(TradeQueueItem message) { if (!message.Order.Status.Equals("matched", StringComparison.OrdinalIgnoreCase)) { return; } var pair = await _assetsService.AssetPairGetAsync(message.Order.AssetPairId); if (pair == null) { throw new ArgumentNullException(nameof(pair)); } bool isLimitAssetBase = message.Trades.First().LimitAsset == pair.BaseAssetId; var limitAsset = await _assetsService.AssetGetAsync(message.Trades.First().LimitAsset); if (limitAsset == null) { throw new ArgumentNullException(nameof(limitAsset)); } var marketAsset = await _assetsService.AssetGetAsync(message.Trades.First().MarketAsset); if (marketAsset == null) { throw new ArgumentNullException(nameof(marketAsset)); } foreach (var trade in message.Trades) { await _tradesCommonRepository.InsertCommonTrade(new TradeCommon { Amount = isLimitAssetBase ? trade.LimitVolume : trade.MarketVolume, AssetPair = message.Order.AssetPairId, BaseAsset = isLimitAssetBase ? limitAsset.DisplayId : marketAsset.DisplayId, BaseAssetId = isLimitAssetBase ? trade.LimitAsset : trade.MarketAsset, QuotAssetId = isLimitAssetBase ? trade.MarketAsset : trade.LimitAsset, Dt = trade.Timestamp, Id = Guid.NewGuid().ToString(), LimitOrderId = trade.LimitOrderId, MarketOrderId = message.Order.Id, Price = trade.Price.GetValueOrDefault(), QuotAsset = isLimitAssetBase ? marketAsset.DisplayId : limitAsset.DisplayId, }); } }
public async Task <CommandHandlingResult> Handle(RetrieveAssetInfoCommand command, IEventPublisher publisher) { var asset = await _assetsService.AssetGetAsync(command.AssetId); publisher.PublishEvent(new AssetInfoRetrievedEvent { 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, Moment = DateTime.UtcNow, OperationId = command.OperationId }); _chaosKitty.Meow(command.OperationId); return(CommandHandlingResult.Ok()); }
public async Task <CommandHandlingResult> Handle(RetrieveAssetInfoCommand command, IEventPublisher publisher) { var neoAsset = await _assetsService.AssetGetAsync(command.NeoAssetId); var gasAsset = await _assetsService.AssetGetAsync(command.GasAssetId); publisher.PublishEvent(new AssetInfoRetrievedEvent { TransactionId = command.TransactionId, NeoAssetId = command.NeoAssetId, NeoBlockchainType = neoAsset.BlockchainIntegrationLayerId, NeoBlockchainAssetId = neoAsset.BlockchainIntegrationLayerAssetId, GasAssetId = command.GasAssetId, GasBlockchainType = gasAsset.BlockchainIntegrationLayerId, GasBlockchainAssetId = gasAsset.BlockchainIntegrationLayerAssetId }); _chaosKitty.Meow(command.TransactionId); return(CommandHandlingResult.Ok()); }
public async Task <CommandHandlingResult> Handle(StartCashoutCommand command, IEventPublisher eventPublisher) { var asset = await _assetsService.AssetGetAsync(command.AssetId); var amount = EthServiceHelpers.ConvertToContract(command.Amount, asset.MultiplierPower, asset.Accuracy); try { if (asset.Type == AssetType.Erc20Token) { var token = await _assetsService.Erc20TokenGetBySpecificationAsync(new Erc20TokenSpecification(new List <string>() { asset.Id })); var tokenAddress = token?.Items?.FirstOrDefault()?.Address; if (string.IsNullOrEmpty(tokenAddress)) { _logger.WriteWarning(nameof(CashoutCommandHandler), nameof(Handle), $"Can't perform cashout on empty token, {command.Id}"); return(CommandHandlingResult.Ok()); } await _hotWalletService.EnqueueCashoutAsync(new Service.EthereumCore.Core.Repositories.HotWalletOperation() { Amount = amount, OperationId = command.Id.ToString(), FromAddress = command.FromAddress, ToAddress = command.ToAddress, TokenAddress = tokenAddress }); } else { await _pendingOperationService.CashOut(command.Id, asset.AssetAddress, _addressUtil.ConvertToChecksumAddress(command.FromAddress), _addressUtil.ConvertToChecksumAddress(command.ToAddress), amount, string.Empty); } } catch (ClientSideException ex) when(ex.ExceptionType == ExceptionType.EntityAlreadyExists || ex.ExceptionType == ExceptionType.OperationWithIdAlreadyExists) { _logger.WriteWarning(nameof(CashoutCommandHandler), nameof(Handle), $"Operation already exists, {command.Id}", ex); } eventPublisher.PublishEvent(new CashoutCompletedEvent { OperationId = command.Id }); return(CommandHandlingResult.Ok()); }
public async Task <string> GetShortNameAsync(string assetId) { var alias = CleanupNameForTable(assetId); if (alias.Length <= 31) { return(alias); } if (!_assetsDict.ContainsKey(assetId)) { var asset = await _assetsService.AssetGetAsync(assetId); if (asset == null) { throw new UnknownAssetException($"Unknown asset {assetId}"); } var assetName = string.IsNullOrWhiteSpace(asset.DisplayId) ? asset.Name : asset.DisplayId; _assetsDict.TryAdd(assetId, CleanupNameForTable(assetName)); } _assetsDict.TryGetValue(assetId, out string result); return(result); }
public async Task <IActionResult> Get(string id) { if (string.IsNullOrEmpty(id)) { return(BadRequest()); } var asset = await _assetsService.AssetGetAsync(id); if (asset == null) { return(NotFound()); } return(Ok(GetClientBaseAssetRespModel.Create(asset.ConvertToApiModel()))); }
public async Task <CommandHandlingResult> Handle(StartTransferCommand command, IEventPublisher eventPublisher) { var asset = await _assetsService.AssetGetAsync(command.AssetId); var amount = EthServiceHelpers.ConvertToContract(command.Amount, asset.MultiplierPower, asset.Accuracy); try { await _pendingOperationService.Transfer(command.Id, asset.AssetAddress, _addressUtil.ConvertToChecksumAddress(command.FromAddress), _addressUtil.ConvertToChecksumAddress(command.ToAddress), amount, command.Sign); } catch (ClientSideException ex) when(ex.ExceptionType == ExceptionType.EntityAlreadyExists || ex.ExceptionType == ExceptionType.OperationWithIdAlreadyExists) { _logger.WriteWarning(nameof(TransferCommandHandler), nameof(Handle), $"Operation already exists, {command.Id}", ex); } eventPublisher.PublishEvent(new TransferCompletedEvent { OperationId = command.Id }); return(CommandHandlingResult.Ok()); }
//TODO: Split wth the help of the process management private async Task ProcessFailedCashout(ProcessEthCoinEventCommand queueMessage) { CashOutContextData context = await _transactionService.GetTransactionContext <CashOutContextData>(queueMessage.OperationId); if (context != null) { string transactionHandlerUserId = "auto redeem"; string clientId = context.ClientId; string hash = queueMessage.TransactionHash; string cashOperationId = context.CashOperationId; string assetId = context.AssetId; var amount = context.Amount; try { ChaosKitty.Meow(); var asset = await _assetsService.AssetGetAsync(assetId); await _cashOperationsRepositoryClient.UpdateBlockchainHashAsync(clientId, cashOperationId, hash); var pt = await _paymentTransactionsRepository.TryCreateAsync(PaymentTransaction.Create(hash, CashInPaymentSystem.Ethereum, clientId, (double)amount, asset.DisplayId ?? asset.Id, status: PaymentStatus.Processing)); if (pt == null) { _log.Warning($"{nameof(EthereumCoreCommandHandler)}:{nameof(ProcessFailedCashout)}", "Transaction already handled", context: hash); return; //if was handled previously } ChaosKitty.Meow(); var sign = "+"; var commentText = $"Balance Update: {sign}{amount} {asset.Name}. Cashout failed: {hash} {queueMessage.OperationId}"; var newComment = new ClientComment { ClientId = clientId, Comment = commentText, CreatedAt = DateTime.UtcNow, FullName = "Lykke.Job.TransactionHandler", UserId = transactionHandlerUserId }; var exResult = await _exchangeOperationsServiceClient.ExchangeOperations.ManualCashInAsync( new ManualCashInRequestModel { ClientId = clientId, AssetId = assetId, Amount = (double)amount, UserId = "auto redeem", Comment = commentText, }); if (!exResult.IsOk()) { _log.Warning($"{nameof(EthereumCoreCommandHandler)}:{nameof(ProcessFailedCashout)}", "ME operation failed", context: new { ExchangeServiceResponse = exResult, QueueMessage = queueMessage }.ToJson()); } await _clientCommentsRepository.AddClientCommentAsync(newComment); await _paymentTransactionsRepository.SetStatus(hash, PaymentStatus.NotifyProcessed); ChaosKitty.Meow(); } catch (Exception e) { _log.Error($"{nameof(EthereumCoreCommandHandler)}:{nameof(ProcessFailedCashout)}", e, context: queueMessage.ToJson()); throw; } } else { _log.Warning("Can't get a context", context: queueMessage.ToJson()); } }
public async Task Handle(TransferEvent transferEvent) { if (transferEvent == null) { return; } Erc20Token token = await _assetsService.Erc20TokenGetByAddressAsync(transferEvent.TokenAddress); if (token == null) { throw new UnknownErc20TokenException(transferEvent.TokenAddress); } Asset asset = await _assetsService.AssetGetAsync(token.AssetId); if (asset == null) { throw new UnknownErc20AssetException(token.AssetId); } switch (transferEvent.SenderType) { case SenderType.Customer: var inboundTransactionRequest = Mapper.Map <RegisterInboundTxModel>( transferEvent, opt => { opt.Items["AssetId"] = asset.DisplayId; opt.Items["AssetMultiplier"] = asset.MultiplierPower; opt.Items["AssetAccuracy"] = asset.Accuracy; }); await _log.LogPayInternalExceptionIfAny(() => _payInternalClient.RegisterEthereumInboundTransactionAsync(inboundTransactionRequest)); break; case SenderType.EthereumCore: switch (transferEvent.EventType) { case EventType.Started: var outboundTransactionRequest = Mapper.Map <RegisterOutboundTxModel>( transferEvent, opt => { opt.Items["AssetId"] = asset.DisplayId; opt.Items["AssetMultiplier"] = asset.MultiplierPower; opt.Items["AssetAccuracy"] = asset.Accuracy; }); await _log.LogPayInternalExceptionIfAny(() => _payInternalClient .RegisterEthereumOutboundTransactionAsync(outboundTransactionRequest)); break; case EventType.Failed: await _log.LogPayInternalExceptionIfAny(() => _payInternalClient.FailEthereumOutboundTransactionAsync( Mapper.Map <FailOutboundTxModel>(transferEvent))); break; case EventType.Completed: await _log.LogPayInternalExceptionIfAny(() => _payInternalClient.CompleteEthereumOutboundTransactionAsync( Mapper.Map <CompleteOutboundTxModel>(transferEvent, opt => { opt.Items["AssetMultiplier"] = asset.MultiplierPower; opt.Items["AssetAccuracy"] = asset.Accuracy; }))); break; case EventType.NotEnoughFunds: await _log.LogPayInternalExceptionIfAny(() => _payInternalClient.FailEthereumOutboundTransactionAsync( Mapper.Map <NotEnoughFundsOutboundTxModel>(transferEvent))); break; default: throw new UnexpectedEthereumEventTypeException(transferEvent.EventType); } break; default: throw new UnexpectedEthereumTransferTypeException(transferEvent.SenderType); } }
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)); }