public async Task <APIResponse> Profile() { var rcfg = RuntimeConfigHolder.Clone(); var user = await GetUserFromDb(); var userTier = CoreLogic.User.GetTier(user); // user challenges var challenges = new List <string>(); if (!user.UserOptions.InitialTfaQuest && !user.TwoFactorEnabled) { challenges.Add("2fa"); } return(APIResponse.Success( new ProfileView() { Id = user.UserName, Name = CoreLogic.User.HasFilledPersonalData(user.UserVerification) ? (user.UserVerification.FirstName + " " + user.UserVerification.LastName).Trim() : user.UserName, Email = user.Email ?? "", TfaEnabled = user.TwoFactorEnabled, VerifiedL0 = userTier >= UserTier.Tier1, VerifiedL1 = userTier >= UserTier.Tier2, Challenges = challenges.ToArray(), } )); }
public async Task <APIResponse> Estimate([FromBody] EstimateModel model) { if (BaseValidableModel.IsInvalid(model, out var errFields)) { return(APIResponse.BadRequest(errFields)); } var exchangeCurrency = FiatCurrency.Usd; TradableCurrency?cryptoToken = null; // try parse fiat currency if (Enum.TryParse(model.Currency, true, out FiatCurrency fc)) { exchangeCurrency = fc; } // or crypto currency else if (Enum.TryParse(model.Currency, true, out TradableCurrency cc)) { cryptoToken = cc; } else { return(APIResponse.BadRequest(nameof(model.Currency), "Invalid format")); } // try parse amount if (!BigInteger.TryParse(model.Amount, out var inputAmount) || inputAmount < 1 || (cryptoToken == null && !model.Reversed && inputAmount > long.MaxValue)) { return(APIResponse.BadRequest(nameof(model.Amount), "Invalid amount")); } // --- var userOrNull = await GetUserFromDb(); var rcfg = RuntimeConfigHolder.Clone(); // get user limits var limits = cryptoToken != null ? DepositLimits(rcfg, cryptoToken.Value) : await DepositLimits(rcfg, DbContext, userOrNull?.Id, exchangeCurrency) ; // estimate var estimation = await Estimation(rcfg, inputAmount, cryptoToken, exchangeCurrency, model.Reversed, 0, limits.Min, limits.Max); if (!estimation.TradingAllowed) { return(APIResponse.BadRequest(APIErrorCode.TradingNotAllowed)); } if (estimation.IsLimitExceeded) { return(APIResponse.BadRequest(APIErrorCode.TradingExchangeLimit, estimation.View.Limits)); } return(APIResponse.Success(estimation.View)); }
private VerificationView MakeVerificationView(DAL.Models.Identity.User user) { if (user == null) { throw new ArgumentException("User must be specified"); } var kycFinished = CoreLogic.User.HasKycVerification(user.UserVerification); var kycPending = !kycFinished && user.UserVerification?.LastKycTicket != null && user.UserVerification.LastKycTicket.TimeResponded == null && (DateTime.UtcNow - user.UserVerification.LastKycTicket.TimeCreated) < AllowedPeriodBetweenKycRequests ; var rcfg = RuntimeConfigHolder.Clone(); var agrSigned = CoreLogic.User.HasTosSigned(user.UserVerification); var ret = new VerificationView() { IsFormFilled = CoreLogic.User.HasFilledPersonalData(user?.UserVerification), IsKycPending = kycPending, IsKycFinished = kycFinished, IsAgreementSigned = agrSigned, FirstName = user.UserVerification?.FirstName ?? "", MiddleName = user.UserVerification?.MiddleName ?? "", LastName = user.UserVerification?.LastName ?? "", Dob = user.UserVerification?.DoB?.ToString("dd.MM.yyyy") ?? "", PhoneNumber = user.UserVerification?.PhoneNumber ?? "", Country = user.UserVerification?.CountryCode ?? "", State = user.UserVerification?.State ?? "", City = user.UserVerification?.City ?? "", PostalCode = user.UserVerification?.PostalCode ?? "", Street = user.UserVerification?.Street ?? "", Apartment = user.UserVerification?.Apartment ?? "", }; return(ret); }
public async Task <APIResponse> AssetEth([FromBody] AssetEthModel model) { // validate if (BaseValidableModel.IsInvalid(model, out var errFields)) { return(APIResponse.BadRequest(errFields)); } // try parse amount if (!BigInteger.TryParse(model.Amount, out var inputAmount) || inputAmount < 1) { return(APIResponse.BadRequest(nameof(model.Amount), "Invalid amount")); } // try parse fiat currency var exchangeCurrency = FiatCurrency.Usd; if (Enum.TryParse(model.Currency, true, out FiatCurrency fc)) { exchangeCurrency = fc; } // --- var rcfg = RuntimeConfigHolder.Clone(); var user = await GetUserFromDb(); var userTier = CoreLogic.User.GetTier(user); var agent = GetUserAgentInfo(); if (userTier < UserTier.Tier2) { return(APIResponse.BadRequest(APIErrorCode.AccountNotVerified)); } // --- if (!rcfg.Gold.AllowTradingEth) { return(APIResponse.BadRequest(APIErrorCode.TradingNotAllowed)); } var limits = WithdrawalLimits(rcfg, TradableCurrency.Eth); var estimation = await Estimation(rcfg, inputAmount, TradableCurrency.Eth, exchangeCurrency, model.EthAddress, model.Reversed, limits.Min, limits.Max); if (!estimation.TradingAllowed || estimation.ResultCurrencyAmount < 1) { return(APIResponse.BadRequest(APIErrorCode.TradingNotAllowed)); } if (estimation.IsLimitExceeded) { return(APIResponse.BadRequest(APIErrorCode.TradingExchangeLimit, estimation.View.Limits)); } // limit gold amount to max available if (estimation.ResultGoldAmount.FromSumus() > user.UserSumusWallet.BalanceGold) { estimation = await Estimation(rcfg, user.UserSumusWallet.BalanceGold.ToSumus(), TradableCurrency.Eth, exchangeCurrency, model.EthAddress, false, limits.Min, limits.Max); if (!estimation.TradingAllowed || estimation.ResultCurrencyAmount < 1) { return(APIResponse.BadRequest(APIErrorCode.TradingNotAllowed)); } if (estimation.IsLimitExceeded) { return(APIResponse.BadRequest(APIErrorCode.TradingExchangeLimit, estimation.View.Limits)); } } var timeNow = DateTime.UtcNow; // history var finHistory = new DAL.Models.UserFinHistory() { Status = UserFinHistoryStatus.Unconfirmed, Type = UserFinHistoryType.GoldSell, Source = "GOLD", SourceAmount = TextFormatter.FormatTokenAmountFixed(estimation.ResultGoldAmount, TokensPrecision.Sumus), Destination = "ETH", DestinationAmount = TextFormatter.FormatTokenAmountFixed(estimation.ResultCurrencyAmount, TokensPrecision.Ethereum), Comment = "", TimeCreated = timeNow, UserId = user.Id, }; DbContext.UserFinHistory.Add(finHistory); await DbContext.SaveChangesAsync(); // request var request = new DAL.Models.SellGoldEth() { Status = BuySellGoldRequestStatus.Unconfirmed, GoldAmount = estimation.ResultGoldAmount.FromSumus(), Destination = model.EthAddress, EthAmount = estimation.ResultCurrencyAmount.FromSumus(), ExchangeCurrency = exchangeCurrency, GoldRateCents = estimation.CentsPerGoldRate, EthRateCents = estimation.CentsPerAssetRate, TimeCreated = timeNow, RelFinHistoryId = finHistory.Id, UserId = user.Id, }; // add and save DbContext.SellGoldEth.Add(request); await DbContext.SaveChangesAsync(); var assetPerGold = CoreLogic.Finance.Estimation.AssetPerGold(TradableCurrency.Eth, estimation.CentsPerAssetRate, estimation.CentsPerGoldRate); return(APIResponse.Success( new AssetEthView() { RequestId = request.Id, EthRate = estimation.CentsPerAssetRate / 100d, GoldRate = estimation.CentsPerGoldRate / 100d, Currency = exchangeCurrency.ToString().ToUpper(), EthPerGoldRate = assetPerGold.ToString(), Estimation = estimation.View, } )); }
public async Task <APIResponse> Status() { var user = await GetUserFromDb(); var rcfg = RuntimeConfigHolder.Clone(); var ethDepositLimits = v1.User.BuyGoldController.DepositLimits(rcfg, TradableCurrency.Eth); var ethWithdrawLimits = v1.User.SellGoldController.WithdrawalLimits(rcfg, TradableCurrency.Eth); var ccDepositLimits = await v1.User.BuyGoldController.DepositLimits(rcfg, DbContext, user.Id, FiatCurrency.Usd); var ccWithdrawLimits = await v1.User.SellGoldController.WithdrawalLimits(rcfg, DbContext, user.Id, FiatCurrency.Usd); var ret = new StatusView() { Trading = new StatusViewTrading() { EthAllowed = rcfg.Gold.AllowTradingOverall && rcfg.Gold.AllowTradingEth, CreditCardBuyingAllowed = rcfg.Gold.AllowTradingOverall && rcfg.Gold.AllowBuyingCreditCard, CreditCardSellingAllowed = rcfg.Gold.AllowTradingOverall && rcfg.Gold.AllowSellingCreditCard, }, Limits = new StatusViewLimits() { Eth = new StatusViewLimits.Method() { Deposit = new StatusViewLimits.MinMax() { Min = ethDepositLimits.Min.ToString(), Max = ethDepositLimits.Max.ToString(), AccountMax = "0", AccountUsed = "0", }, Withdraw = new StatusViewLimits.MinMax() { Min = ethWithdrawLimits.Min.ToString(), Max = ethWithdrawLimits.Max.ToString(), AccountMax = "0", AccountUsed = "0", } }, CreditCardUsd = new StatusViewLimits.Method() { Deposit = new StatusViewLimits.MinMax() { Min = (long)ccDepositLimits.Min / 100d, Max = (long)ccDepositLimits.Max / 100d, AccountMax = (long)ccDepositLimits.AccountMax / 100d, AccountUsed = (long)ccDepositLimits.AccountUsed / 100d, }, Withdraw = new StatusViewLimits.MinMax() { Min = (long)ccWithdrawLimits.Min / 100d, Max = (long)ccWithdrawLimits.Max / 100d, AccountMax = (long)ccWithdrawLimits.AccountMax / 100d, AccountUsed = (long)ccWithdrawLimits.AccountUsed / 100d, } }, }, }; return(APIResponse.Success(ret)); }
private Task <HexBigInteger> GetWritingGas() { var rc = _runtimeConfig.Clone(); return(Task.FromResult(new HexBigInteger(rc.Ethereum.Gas))); }
public async Task <APIResponse> AssetEth([FromBody] AssetEthModel model) { // validate if (BaseValidableModel.IsInvalid(model, out var errFields)) { return(APIResponse.BadRequest(errFields)); } // try parse amount if (!BigInteger.TryParse(model.Amount, out var inputAmount) || inputAmount < 1) { return(APIResponse.BadRequest(nameof(model.Amount), "Invalid amount")); } // try parse fiat currency var exchangeCurrency = FiatCurrency.Usd; if (Enum.TryParse(model.Currency, true, out FiatCurrency fc)) { exchangeCurrency = fc; } // --- var rcfg = RuntimeConfigHolder.Clone(); var user = await GetUserFromDb(); // --- if (!rcfg.Gold.AllowTradingEth) { return(APIResponse.BadRequest(APIErrorCode.TradingNotAllowed)); } var limits = DepositLimits(rcfg, TradableCurrency.Eth); // estimation var estimation = await Estimation(rcfg, inputAmount, TradableCurrency.Eth, exchangeCurrency, model.Reversed, 0d, limits.Min, limits.Max); if (!estimation.TradingAllowed || estimation.ResultCurrencyAmount < 1) { return(APIResponse.BadRequest(APIErrorCode.TradingNotAllowed)); } if (estimation.IsLimitExceeded) { return(APIResponse.BadRequest(APIErrorCode.TradingExchangeLimit, estimation.View.Limits)); } var timeNow = DateTime.UtcNow; // request var request = new DAL.Models.BuyGoldEth() { Status = BuySellGoldRequestStatus.Unconfirmed, ExchangeCurrency = exchangeCurrency, GoldRateCents = estimation.CentsPerGoldRate, EthRateCents = estimation.CentsPerAssetRate, TimeCreated = timeNow, UserId = user.Id, }; DbContext.BuyGoldEth.Add(request); await DbContext.SaveChangesAsync(); // get a token from eth2gold service var contractToken = ""; { try { var reply = await Bus.Request( Eth2Gold.Subject.Request.OrderCreate, new Eth2Gold.Request.OrderCreate() { ExternalID = (ulong)request.Id, }, Eth2Gold.Request.OrderCreateReply.Parser ); if (reply.ResultCase == Eth2Gold.Request.OrderCreateReply.ResultOneofCase.Token) { if (reply.Token.ToByteArray().Length != 32) { throw new Exception($"token is length of {reply.Token.ToByteArray().Length}"); } contractToken = BitConverter.ToString(reply.Token.ToByteArray()).Replace("-", string.Empty); } else { throw new Exception(reply.Error); } } catch (Exception e) { Logger.Error(e, "Failed to get token from eth2gold service"); return(APIResponse.Failure(APIErrorCode.InternalServerError)); } } var assetPerGold = CoreLogic.Finance.Estimation.AssetPerGold(TradableCurrency.Eth, estimation.CentsPerAssetRate, estimation.CentsPerGoldRate); return(APIResponse.Success( new AssetEthView() { RequestId = request.Id, EthRate = estimation.CentsPerAssetRate / 100d, GoldRate = estimation.CentsPerGoldRate / 100d, EthPerGoldRate = assetPerGold.ToString(), Currency = exchangeCurrency.ToString().ToUpper(), Expires = ((DateTimeOffset)timeNow.AddHours(1)).ToUnixTimeSeconds(), Estimation = estimation.View, ContractToken = contractToken, } )); }