Ejemplo n.º 1
0
        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(),
            }
                       ));
        }
Ejemplo n.º 2
0
        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);
        }
Ejemplo n.º 3
0
 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();
 }
Ejemplo n.º 4
0
        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));
        }
Ejemplo n.º 5
0
        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);
        }
Ejemplo n.º 6
0
        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);
        }
Ejemplo n.º 7
0
        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);
        }
Ejemplo n.º 8
0
        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>();
        }
Ejemplo n.º 9
0
        // ---

        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();
        }
Ejemplo n.º 10
0
        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,
            }
                       ));
        }
Ejemplo n.º 11
0
        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));
        }
Ejemplo n.º 12
0
        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,
            }
                       ));
        }