Beispiel #1
0
        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)}"));
            }
        }
Beispiel #2
0
        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,
                });
            }
        }
Beispiel #3
0
        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());
        }
Beispiel #4
0
        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());
        }
Beispiel #5
0
        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);
        }
Beispiel #7
0
        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());
        }
Beispiel #9
0
        //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);
            }
        }
Beispiel #11
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));
        }