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 EthereumWriter(AppConfig appConfig, RuntimeConfigHolder runtimeConfig, ILogger logFactory) : base(appConfig, logFactory) { _runtimeConfig = runtimeConfig; _gmEthSender = new Nethereum.Web3.Accounts.Account(appConfig.Services.Ethereum.EthSenderPk); // uses semaphore inside: _gmEthSender.NonceService = new Nethereum.RPC.NonceServices.InMemoryNonceService(_gmEthSender.Address, EthProvider); }
protected Test(Xunit.Abstractions.ITestOutputHelper testOutput) { _testOutput = testOutput; Log.Logger = new LoggerConfiguration().MinimumLevel.Verbose().WriteTo.Console().CreateLogger(); RuntimeConfigHolder = new RuntimeConfigHolder(Log.Logger); RuntimeConfigLoader = new DebugRuntimeConfigLoader(); RuntimeConfigHolder.SetLoader(RuntimeConfigLoader); RuntimeConfigHolder.Reload().Wait(); }
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)); }
public void TradingDisallowed() { _ratesProvider.SetSpread(0d); _ratesDispatcher.OnProviderCurrencyRate(_ratesProvider.RequestGoldPrice(TimeSpan.Zero).Result); _ratesDispatcher.OnProviderCurrencyRate(_ratesProvider.RequestEthPrice(TimeSpan.Zero).Result); _ratesDispatcher.ForceUpdate().Wait(); // ok Assert.True(CoreLogic.Finance.Estimation.BuyGoldFiat(_services, FiatCurrency.Usd, 1).Result.Status == CoreLogic.Finance.Estimation.BuyGoldStatus.Success); Assert.True(CoreLogic.Finance.Estimation.BuyGoldCrypto(_services, TradableCurrency.Eth, FiatCurrency.Usd, 1).Result.Status == CoreLogic.Finance.Estimation.BuyGoldStatus.Success); Assert.True(CoreLogic.Finance.Estimation.BuyGoldFiatRev(_services, FiatCurrency.Usd, 1).Result.Status == CoreLogic.Finance.Estimation.BuyGoldStatus.Success); Assert.True(CoreLogic.Finance.Estimation.BuyGoldCryptoRev(_services, TradableCurrency.Eth, FiatCurrency.Usd, 1).Result.Status == CoreLogic.Finance.Estimation.BuyGoldStatus.Success); Assert.True(CoreLogic.Finance.Estimation.SellGoldFiat(_services, FiatCurrency.Usd, 1).Result.Status == CoreLogic.Finance.Estimation.SellGoldStatus.Success); Assert.True(CoreLogic.Finance.Estimation.SellGoldCrypto(_services, TradableCurrency.Eth, FiatCurrency.Usd, 1).Result.Status == CoreLogic.Finance.Estimation.SellGoldStatus.Success); Assert.True(CoreLogic.Finance.Estimation.SellGoldFiatRev(_services, FiatCurrency.Usd, 1).Result.Status == CoreLogic.Finance.Estimation.SellGoldStatus.Success); Assert.True(CoreLogic.Finance.Estimation.SellGoldCryptoRev(_services, TradableCurrency.Eth, FiatCurrency.Usd, 1).Result.Status == CoreLogic.Finance.Estimation.SellGoldStatus.Success); // disallow trading RuntimeConfigLoader.EditConfig(cfg => { cfg.Gold.AllowTradingOverall = false; }); RuntimeConfigHolder.Reload().Wait(); // disallowed Assert.True(CoreLogic.Finance.Estimation.BuyGoldFiat(_services, FiatCurrency.Usd, 1).Result.Status == CoreLogic.Finance.Estimation.BuyGoldStatus.TradingDisallowed); Assert.True(CoreLogic.Finance.Estimation.BuyGoldCrypto(_services, TradableCurrency.Eth, FiatCurrency.Usd, 1).Result.Status == CoreLogic.Finance.Estimation.BuyGoldStatus.TradingDisallowed); Assert.True(CoreLogic.Finance.Estimation.BuyGoldFiatRev(_services, FiatCurrency.Usd, 1).Result.Status == CoreLogic.Finance.Estimation.BuyGoldStatus.TradingDisallowed); Assert.True(CoreLogic.Finance.Estimation.BuyGoldCryptoRev(_services, TradableCurrency.Eth, FiatCurrency.Usd, 1).Result.Status == CoreLogic.Finance.Estimation.BuyGoldStatus.TradingDisallowed); Assert.True(CoreLogic.Finance.Estimation.SellGoldFiat(_services, FiatCurrency.Usd, 1).Result.Status == CoreLogic.Finance.Estimation.SellGoldStatus.TradingDisallowed); Assert.True(CoreLogic.Finance.Estimation.SellGoldCrypto(_services, TradableCurrency.Eth, FiatCurrency.Usd, 1).Result.Status == CoreLogic.Finance.Estimation.SellGoldStatus.TradingDisallowed); Assert.True(CoreLogic.Finance.Estimation.SellGoldFiatRev(_services, FiatCurrency.Usd, 1).Result.Status == CoreLogic.Finance.Estimation.SellGoldStatus.TradingDisallowed); Assert.True(CoreLogic.Finance.Estimation.SellGoldCryptoRev(_services, TradableCurrency.Eth, FiatCurrency.Usd, 1).Result.Status == CoreLogic.Finance.Estimation.SellGoldStatus.TradingDisallowed); // but ok for fiat-ops (with known gold rate) var knownGoldRate = 666L; Assert.True(CoreLogic.Finance.Estimation.BuyGoldFiat(_services, FiatCurrency.Usd, 1, knownGoldRate).Result.Status == CoreLogic.Finance.Estimation.BuyGoldStatus.Success); Assert.True(CoreLogic.Finance.Estimation.BuyGoldCrypto(_services, TradableCurrency.Eth, FiatCurrency.Usd, 1, knownGoldRate).Result.Status == CoreLogic.Finance.Estimation.BuyGoldStatus.TradingDisallowed); Assert.True(CoreLogic.Finance.Estimation.BuyGoldFiatRev(_services, FiatCurrency.Usd, 1, knownGoldRate).Result.Status == CoreLogic.Finance.Estimation.BuyGoldStatus.Success); Assert.True(CoreLogic.Finance.Estimation.BuyGoldCryptoRev(_services, TradableCurrency.Eth, FiatCurrency.Usd, 1, knownGoldRate).Result.Status == CoreLogic.Finance.Estimation.BuyGoldStatus.TradingDisallowed); Assert.True(CoreLogic.Finance.Estimation.SellGoldFiat(_services, FiatCurrency.Usd, 1, knownGoldRate).Result.Status == CoreLogic.Finance.Estimation.SellGoldStatus.Success); Assert.True(CoreLogic.Finance.Estimation.SellGoldCrypto(_services, TradableCurrency.Eth, FiatCurrency.Usd, 1, knownGoldRate).Result.Status == CoreLogic.Finance.Estimation.SellGoldStatus.TradingDisallowed); Assert.True(CoreLogic.Finance.Estimation.SellGoldFiatRev(_services, FiatCurrency.Usd, 1, knownGoldRate).Result.Status == CoreLogic.Finance.Estimation.SellGoldStatus.Success); Assert.True(CoreLogic.Finance.Estimation.SellGoldCryptoRev(_services, TradableCurrency.Eth, FiatCurrency.Usd, 1, knownGoldRate).Result.Status == CoreLogic.Finance.Estimation.SellGoldStatus.TradingDisallowed); // but ok for all ops (with known gold and crypto rate) var knownCryptoRate = 777L; Assert.True(CoreLogic.Finance.Estimation.BuyGoldFiat(_services, FiatCurrency.Usd, 1, knownGoldRate).Result.Status == CoreLogic.Finance.Estimation.BuyGoldStatus.Success); Assert.True(CoreLogic.Finance.Estimation.BuyGoldCrypto(_services, TradableCurrency.Eth, FiatCurrency.Usd, 1, knownGoldRate, knownCryptoRate).Result.Status == CoreLogic.Finance.Estimation.BuyGoldStatus.Success); Assert.True(CoreLogic.Finance.Estimation.BuyGoldFiatRev(_services, FiatCurrency.Usd, 1, knownGoldRate).Result.Status == CoreLogic.Finance.Estimation.BuyGoldStatus.Success); Assert.True(CoreLogic.Finance.Estimation.BuyGoldCryptoRev(_services, TradableCurrency.Eth, FiatCurrency.Usd, 1, knownGoldRate, knownCryptoRate).Result.Status == CoreLogic.Finance.Estimation.BuyGoldStatus.Success); Assert.True(CoreLogic.Finance.Estimation.SellGoldFiat(_services, FiatCurrency.Usd, 1, knownGoldRate).Result.Status == CoreLogic.Finance.Estimation.SellGoldStatus.Success); Assert.True(CoreLogic.Finance.Estimation.SellGoldCrypto(_services, TradableCurrency.Eth, FiatCurrency.Usd, 1, knownGoldRate, knownCryptoRate).Result.Status == CoreLogic.Finance.Estimation.SellGoldStatus.Success); Assert.True(CoreLogic.Finance.Estimation.SellGoldFiatRev(_services, FiatCurrency.Usd, 1, knownGoldRate).Result.Status == CoreLogic.Finance.Estimation.SellGoldStatus.Success); Assert.True(CoreLogic.Finance.Estimation.SellGoldCryptoRev(_services, TradableCurrency.Eth, FiatCurrency.Usd, 1, knownGoldRate, knownCryptoRate).Result.Status == CoreLogic.Finance.Estimation.SellGoldStatus.Success); }
public Startup(IHostingEnvironment env, IConfiguration configuration) { _environment = env; _configuration = configuration; // globlization System.Globalization.CultureInfo.DefaultThreadCurrentCulture = System.Globalization.CultureInfo.InvariantCulture; System.Globalization.CultureInfo.DefaultThreadCurrentUICulture = System.Globalization.CultureInfo.InvariantCulture; var curDir = Directory.GetCurrentDirectory(); Console.OutputEncoding = Encoding.UTF8; // config try { var cfgDir = Environment.GetEnvironmentVariable("ASPNETCORE_CONFIGPATH"); _configuration = new ConfigurationBuilder() .SetBasePath(cfgDir) .AddJsonFile("appsettings.json", optional: false) .AddJsonFile($"appsettings.{_environment.EnvironmentName}.json", optional: false) .Build() ; _appConfig = new AppConfig(); _configuration.Bind(_appConfig); } catch (Exception e) { throw new Exception("Failed to get app settings", e); } // serilog config var logConf = new LoggerConfiguration(); { if (_environment.IsDevelopment()) { logConf.MinimumLevel.Verbose(); } logConf.WriteTo.Console(outputTemplate: "{Timestamp:dd-MMM-yyyy-HH:mm} [{Level:u3}] {Message} at {SourceContext}{NewLine}{Exception}"); } var logger = Log.Logger = logConf.CreateLogger(); logger.Information("Starting"); // runtime config _runtimeConfigHolder = new RuntimeConfigHolder(logger); }
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 PriceDispatcher(IGoldPriceProvider goldPvd, IEthPriceProvider ethPvd, RuntimeConfigHolder runtimeConfigHolder, ILogger logFactory, Action <Options> opts) { _goldPvd = goldPvd; _ethPvd = ethPvd; _runtimeConfigHolder = runtimeConfigHolder; _logger = logFactory.GetLoggerFor(this); _opts = new Options() { PriceRequestPeriod = TimeSpan.FromSeconds(60), PriceRequestTimeout = TimeSpan.FromSeconds(10), }; opts?.Invoke(_opts); _startStopMonitor = new object(); _workerCTS = new CancellationTokenSource(); _ratesLock = new ReaderWriterLockSlim(); _rates = new Dictionary <Common.CurrencyPrice, Models.CurrencyPrice>(); }
// --- public static void Main(string[] args) { AppDomain.CurrentDomain.ProcessExit += onStop; Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e) { if (e.SpecialKey == ConsoleSpecialKey.ControlC) { e.Cancel = true; new Thread(delegate() { Environment.Exit(2); }).Start(); } }; // globlization System.Globalization.CultureInfo.DefaultThreadCurrentCulture = System.Globalization.CultureInfo.InvariantCulture; System.Globalization.CultureInfo.DefaultThreadCurrentUICulture = System.Globalization.CultureInfo.InvariantCulture; _environment = new Microsoft.AspNetCore.Hosting.Internal.HostingEnvironment(); _environment.EnvironmentName = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"); var curDir = Directory.GetCurrentDirectory(); Console.OutputEncoding = Encoding.UTF8; _shutdownToken = new CancellationTokenSource(); _shutdownCompletedEvent = new ManualResetEventSlim(); // config try { var cfgDir = Environment.GetEnvironmentVariable("ASPNETCORE_CONFIGPATH"); _configuration = new ConfigurationBuilder() .SetBasePath(cfgDir) .AddJsonFile("appsettings.json", optional: false) .AddJsonFile($"appsettings.{_environment.EnvironmentName}.json", optional: false) .AddJsonFile($"appsettings.{_environment.EnvironmentName}.PK.json", optional: _environment.IsDevelopment()) .Build() ; _appConfig = new AppConfig(); _configuration.Bind(_appConfig); } catch (Exception e) { throw new Exception("Failed to get app settings", e); } // serilog config var logConf = new LoggerConfiguration(); { if (_environment.IsDevelopment()) { logConf.MinimumLevel.Verbose(); } logConf.WriteTo.Console(outputTemplate: "{Timestamp:dd-MMM-yyyy-HH:mm} [{Level:u3}] {Message} at {SourceContext}{NewLine}{Exception}"); } var logger = Log.Logger = logConf.CreateLogger(); logger.Information("Starting"); // runtime config _runtimeConfigHolder = new RuntimeConfigHolder(logger); // setup services var servicesCollection = new ServiceCollection(); SetupCommonServices(servicesCollection); var services = servicesCollection.BuildServiceProvider(); // config loader _runtimeConfigHolder.SetLoader(services.GetRequiredService <IRuntimeConfigLoader>()); // setup ms logger // services.GetRequiredService<Microsoft.Extensions.Logging.ILoggerFactory>().AddNLog(); // start required services StartServices(); // run workers and wait for completion RunWorkers(services); // cleanup StopServices(); Log.CloseAndFlush(); if (_environment.IsDevelopment() && Environment.UserInteractive) { Console.WriteLine("Press space"); do { while (!Console.KeyAvailable) { Thread.Sleep(100); } } while (Console.ReadKey(true).Key != ConsoleKey.Spacebar); } logger.Information("Stopped"); _shutdownCompletedEvent.Set(); }
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)); }
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, } )); }