public async Task <ResponseModel <IMarginTradingWatchList> > AddWatchList([FromBody] WatchList model) { var clientId = User.GetClaim(ClaimTypes.NameIdentifier); if (clientId == null) { return(ResponseModel <IMarginTradingWatchList> .CreateFail(ResponseModel.ErrorCodeType.NoAccess, "Wrong token")); } var result = new ResponseModel <IMarginTradingWatchList>(); if (model.AssetIds == null || model.AssetIds.Count == 0) { return(ResponseModel <IMarginTradingWatchList> .CreateInvalidFieldError("AssetIds", "AssetIds should not be empty")); } var addResult = await _watchListService.AddAsync(model.Id, clientId, model.Name, model.AssetIds); switch (addResult.Status) { case WatchListStatus.AssetNotFound: return(ResponseModel <IMarginTradingWatchList> .CreateFail(ResponseModel.ErrorCodeType.AssetNotFound, $"Asset '{addResult.Message}' is not found or not allowed")); case WatchListStatus.ReadOnly: return(ResponseModel <IMarginTradingWatchList> .CreateFail(ResponseModel.ErrorCodeType.InconsistentData, "This watch list is readonly")); } result.Result = addResult.Result; return(result); }
public async Task <ResponseModel> Post(PinSecurityChangeModel data) { if (string.IsNullOrEmpty(data.Pin)) { return(ResponseModel.CreateInvalidFieldError("pin", Phrases.FieldShouldNotBeEmpty)); } if (!data.Pin.IsOnlyDigits()) { return(ResponseModel.CreateInvalidFieldError("pin", Phrases.PinShouldContainsDigitsOnly)); } if (data.Pin.Length < 4) { return(ResponseModel.CreateInvalidFieldError("pin", Phrases.MinLengthIs4Digits)); } var clientId = this.GetClientId(); if (string.IsNullOrEmpty(clientId)) { return(ResponseModel <PinSecurityCheckResultModel> .CreateFail(ResponseModel.ErrorCodeType.NotAuthenticated, Phrases.NotAuthenticated)); } await _puPinSecurityRepository.SaveAsync(clientId, data.Pin); return(ResponseModel.CreateOk()); }
public async Task <ResponseModel <AuthenticateResponseModel> > Post(AuthenticateModel model) { if (string.IsNullOrEmpty(model.Email)) { return(ResponseModel <AuthenticateResponseModel> .CreateInvalidFieldError("email", Phrases.FieldShouldNotBeEmpty)); } if (!model.Email.IsValidEmail()) { return(ResponseModel <AuthenticateResponseModel> .CreateInvalidFieldError("email", Phrases.InvalidEmailFormat)); } if (string.IsNullOrEmpty(model.Password)) { return(ResponseModel <AuthenticateResponseModel> .CreateInvalidFieldError("passowrd", Phrases.FieldShouldNotBeEmpty)); } var client = await _clientAccountsRepository.AuthenticateAsync(model.Email, model.Password); if (client == null) { return(ResponseModel <AuthenticateResponseModel> .CreateInvalidFieldError("passowrd", Phrases.InvalidUsernameOrPassword)); } this.AuthenticateUserViaOwin(client); return(ResponseModel <AuthenticateResponseModel> .CreateOk(new AuthenticateResponseModel { KycStatus = (await _kycRepository.GetKycStatusAsync(client.Id)).ToString(), PinIsEntered = await _pinSecurityRepository.IsPinEntered(client.Id) })); }
public async Task <ResponseModel> Post(KycDocumentsModel model) { if (string.IsNullOrEmpty(model.Type)) { return(ResponseModel.CreateInvalidFieldError("type", Phrases.FieldShouldNotBeEmpty)); } if (!KycDocumentTypes.HasDocumentType(model.Type)) { return(ResponseModel.CreateInvalidFieldError("type", Phrases.InvalidDocumentType)); } if (string.IsNullOrEmpty(model.Ext)) { return(ResponseModel.CreateInvalidFieldError("ext", Phrases.FieldShouldNotBeEmpty)); } if (string.IsNullOrEmpty(model.Data)) { return(ResponseModel.CreateInvalidFieldError("data", Phrases.FieldShouldNotBeEmpty)); } byte[] data; try { data = Convert.FromBase64String(model.Data); } catch (Exception) { return(ResponseModel.CreateInvalidFieldError("data", "Base64 format expected")); } var clientId = this.GetClientId(); if (string.IsNullOrEmpty(clientId)) { return(ResponseModel.CreateFail(ResponseModel.ErrorCodeType.NotAuthenticated, Phrases.NotAuthenticated)); } var status = await _kycRepository.GetKycStatusAsync(clientId); if (status != KycStatus.NeedToFillData) { return(ResponseModel.CreateFail(ResponseModel.ErrorCodeType.InconsistentData, Phrases.OperationCanNotBePerformed)); } var fileName = "myFile" + model.Ext.AddFirstSymbolIfNotExists('.'); var mimeType = MimeMapping.GetMimeMapping(fileName); await _srvKycDocumentsManager.UploadDocument(clientId, model.Type, fileName, mimeType, data); return(ResponseModel.CreateOk()); }
/// <summary> /// Validate requested price. /// </summary> public bool ValidatePrice(decimal price, out ResponseModel model, string name = "Price") { if (price <= 0) { model = ResponseModel.CreateInvalidFieldError(name, "Price must be greater than asset accuracy."); return(false); } model = null; return(true); }
/// <summary> /// Validate requested asset. /// </summary> public bool ValidateAsset(AssetPair assetPair, string assetId, Asset baseAsset, Asset quotingAsset, out ResponseModel model) { if (assetId != baseAsset.Id && assetId != baseAsset.DisplayId && assetId != quotingAsset.Id && assetId != quotingAsset.DisplayId) { model = ResponseModel.CreateInvalidFieldError("Asset", $"Asset <{assetId}> is not valid for asset pair <{assetPair.Id}>."); return(false); } model = null; return(true); }
public async Task <ResponseModel> Post(AccountRegistrationModel model) { if (string.IsNullOrEmpty(model.Email)) { return(ResponseModel.CreateInvalidFieldError("email", Phrases.FieldShouldNotBeEmpty)); } if (!model.Email.IsValidEmail()) { return(ResponseModel.CreateInvalidFieldError("email", Phrases.InvalidEmailFormat)); } if (string.IsNullOrEmpty(model.FirstName)) { return(ResponseModel.CreateInvalidFieldError("firstname", Phrases.FieldShouldNotBeEmpty)); } if (string.IsNullOrEmpty(model.LastName)) { return(ResponseModel.CreateInvalidFieldError("lastname", Phrases.FieldShouldNotBeEmpty)); } if (string.IsNullOrEmpty(model.ContactPhone)) { return(ResponseModel.CreateInvalidFieldError("contactphone", Phrases.FieldShouldNotBeEmpty)); } if (await _clientAccountsRepository.IsTraderWithEmailExistsAsync(model.Email)) { return(ResponseModel.CreateInvalidFieldError("email", Phrases.ClientWithEmailIsRegistered)); } if (string.IsNullOrEmpty(model.Password)) { return(ResponseModel.CreateInvalidFieldError("passowrd", Phrases.FieldShouldNotBeEmpty)); } try { var user = await _srvClientManager.RegisterClientAsync(model.Email, model.FirstName, model.LastName, model.ContactPhone, model.Password); this.AuthenticateUserViaOwin(user); return(ResponseModel.CreateOk()); } catch (Exception ex) { return(ResponseModel.CreateInvalidFieldError("email", ex.StackTrace)); } }
public async Task <ResponseModel <AccountExistResultModel> > Get(string email) { if (string.IsNullOrEmpty(email)) { return(ResponseModel <AccountExistResultModel> .CreateInvalidFieldError("email", Phrases.FieldShouldNotBeEmpty)); } if (!email.IsValidEmail()) { return(ResponseModel <AccountExistResultModel> .CreateInvalidFieldError("email", Phrases.InvalidEmailFormat)); } return(ResponseModel <AccountExistResultModel> .CreateOk( new AccountExistResultModel { IsEmailRegistered = await _clientAccountsRepository.IsTraderWithEmailExistsAsync(email) })); }
/// <summary> /// Validate requested asset pair. /// </summary> public bool ValidateAssetPair(string assetPairId, AssetPair assetPair, out ResponseModel model) { if (assetPair == null) { model = ResponseModel.CreateInvalidFieldError("AssetPairId", $"AssetPair {assetPairId} is unknown"); return(false); } if (IsAssetPairDisabled(assetPair)) { model = ResponseModel.CreateInvalidFieldError("AssetPairId", $"AssetPair {assetPairId} is temporarily disabled"); return(false); } model = null; return(true); }
public static ResponseModel <int> ValidateAndGetValue(this int?paramValue, string parameter, int maxValue, int defaultValue) { var value = paramValue.GetValueOrDefault(defaultValue); if (value > maxValue) { return(ResponseModel <int> .CreateInvalidFieldError(parameter, $"{parameter} '{value}' is too big, maximum is '{maxValue}'.")); } if (value < 0) { return(ResponseModel <int> .CreateInvalidFieldError(parameter, $"{parameter} cannot be less than zero.")); } if (value == 0) { value = defaultValue; } return(ResponseModel <int> .CreateOk(value)); }
public async Task <IActionResult> GetOrders(OrderStatusQuery?status = null, int?take = 100, OrderType orderType = OrderType.Unknown) { var toTake = take.ValidateAndGetValue(nameof(take), MaxPageSize, 100); if (toTake.Error != null) { return(BadRequest(toTake.Error)); } if (!status.HasValue) { status = OrderStatusQuery.All; } var walletId = Guid.Parse(User.GetUserId()); var orderTypes = orderType == OrderType.Unknown ? new History.Contracts.Enums.OrderType[0] : new[] { (History.Contracts.Enums.OrderType)orderType }; IEnumerable <OrderModel> orders = new List <OrderModel>(); try { switch (status) { case OrderStatusQuery.All: orders = await _historyClient.OrdersApi.GetOrdersByWalletAsync( walletId, new History.Contracts.Enums.OrderStatus[0], orderTypes, 0, toTake.Result); break; case OrderStatusQuery.Open: orders = await _historyClient.OrdersApi.GetActiveOrdersByWalletAsync(walletId, 0, toTake.Result); break; case OrderStatusQuery.InOrderBook: orders = await _historyClient.OrdersApi.GetOrdersByWalletAsync( walletId, new[] { History.Contracts.Enums.OrderStatus.Placed }, orderTypes, 0, toTake.Result); break; case OrderStatusQuery.Processing: orders = await _historyClient.OrdersApi.GetOrdersByWalletAsync( walletId, new[] { History.Contracts.Enums.OrderStatus.PartiallyMatched }, orderTypes, 0, toTake.Result); break; case OrderStatusQuery.Matched: orders = await _historyClient.OrdersApi.GetOrdersByWalletAsync( walletId, new[] { History.Contracts.Enums.OrderStatus.Matched }, orderTypes, 0, toTake.Result); break; case OrderStatusQuery.Replaced: orders = await _historyClient.OrdersApi.GetOrdersByWalletAsync( walletId, new[] { History.Contracts.Enums.OrderStatus.Replaced }, orderTypes, 0, toTake.Result); break; case OrderStatusQuery.Cancelled: orders = await _historyClient.OrdersApi.GetOrdersByWalletAsync( walletId, new[] { History.Contracts.Enums.OrderStatus.Cancelled }, orderTypes, 0, toTake.Result); break; case OrderStatusQuery.Rejected: orders = await _historyClient.OrdersApi.GetOrdersByWalletAsync( walletId, new[] { History.Contracts.Enums.OrderStatus.Rejected }, orderTypes, 0, toTake.Result); break; default: return(BadRequest( ResponseModel.CreateInvalidFieldError("status", $"Invalid status: <{status}>"))); } } catch (Exception ex) { _log.Warning("Error getting orders", ex, context: new { walletId = walletId, status, orderType, take = toTake.Result }.ToJson()); } return(Ok(orders.Select(ToModel))); }
public async Task <IActionResult> PlaceStopLimitOrder([FromBody] PlaceStopLimitOrderModel order) { var assetPair = _assetPairsReadModel.TryGetIfEnabled(order.AssetPairId); if (assetPair == null) { return(NotFound($"Asset-pair {order.AssetPairId} could not be found or is disabled.")); } if (!_requestValidator.ValidateAssetPair(order.AssetPairId, assetPair, out var badRequestModel)) { return(BadRequest(badRequestModel)); } var asset = _assetsReadModel.TryGetIfEnabled(assetPair.BaseAssetId); if (asset == null) { throw new InvalidOperationException($"Base asset '{assetPair.BaseAssetId}' for asset pair '{assetPair.Id}' not found."); } var lowerPrice = order.LowerPrice; if (lowerPrice.HasValue && !_requestValidator.ValidatePrice(lowerPrice.Value, out badRequestModel, nameof(PlaceStopLimitOrderModel.LowerPrice))) { return(BadRequest(badRequestModel)); } var lowerLimitPrice = order.LowerLimitPrice; if (lowerLimitPrice.HasValue && !_requestValidator.ValidatePrice(lowerLimitPrice.Value, out badRequestModel, nameof(PlaceStopLimitOrderModel.LowerLimitPrice))) { return(BadRequest(badRequestModel)); } if ((lowerPrice.HasValue && !lowerLimitPrice.HasValue) || (!lowerPrice.HasValue && lowerLimitPrice.HasValue)) { return(BadRequest(ResponseModel.CreateInvalidFieldError(nameof(order.LowerPrice), "When lower price is send then also lower limit price is required and vice versa."))); } var upperPrice = order.UpperPrice; if (upperPrice.HasValue && !_requestValidator.ValidatePrice(upperPrice.Value, out badRequestModel, nameof(PlaceStopLimitOrderModel.UpperPrice))) { return(BadRequest(badRequestModel)); } var upperLimitPrice = order.UpperLimitPrice; if (upperLimitPrice.HasValue && !_requestValidator.ValidatePrice(upperLimitPrice.Value, out badRequestModel, nameof(PlaceStopLimitOrderModel.UpperLimitPrice))) { return(BadRequest(badRequestModel)); } if ((upperPrice.HasValue && !upperLimitPrice.HasValue) || (!upperPrice.HasValue && upperLimitPrice.HasValue)) { return(BadRequest(ResponseModel.CreateInvalidFieldError(nameof(order.UpperPrice), "When upper price is send then also upper limit price is required and vice versa."))); } if (new[] { lowerPrice, lowerLimitPrice, upperPrice, upperLimitPrice }.All(x => !x.HasValue)) { return(BadRequest(ResponseModel.CreateFail(ErrorCodeType.Rejected, "At least lower or upper prices are needed for a stop order."))); } var volume = order.Volume; var minVolume = assetPair.MinVolume; if (!_requestValidator.ValidateVolume(volume, minVolume, asset.DisplayId, out badRequestModel)) { return(BadRequest(badRequestModel)); } var walletId = User.GetUserId(); var response = await _matchingEngineAdapter.PlaceStopLimitOrderAsync( clientId : walletId, assetPair : assetPair, orderAction : order.OrderAction, volume : volume, lowerPrice : lowerPrice, lowerLimitPrice : lowerLimitPrice, upperPrice : upperPrice, upperLimitPrice : upperLimitPrice); if (response.Error != null) { return(BadRequest(response)); } return(Ok(response.Result)); }