示例#1
0
        private void HandleMessage(object _, MsgHandlerEventArgs args)
        {
            try {
                _dbContext.DetachEverything();

                var evt = Eth2Gold.Event.OrderDeposited.Parser.ParseFrom(args.Message.Data);

                // find request
                var id  = (long)evt.ExternalID;
                var row =
                    (from r in _dbContext.BuyGoldEth where r.Id == id select r)
                    .AsTracking()
                    .LastOrDefault()
                ;

                BigInteger ethAmount = BigInteger.Zero;
                try {
                    if (row == null)
                    {
                        throw new Exception("Order not found by given external id");
                    }
                    if (!BigInteger.TryParse(evt.EthAmount, out ethAmount) || ethAmount <= 0)
                    {
                        throw new Exception("Failed to parse ETH amount");
                    }
                } catch (Exception e) {
                    Logger.Error(e, $"Failed to process order #{id}");
                    return;
                }

                if (row.Status == BuySellGoldRequestStatus.Confirmed)
                {
                    long?dealGoldPrice = row.GoldRateCents;
                    long?dealEthPrice  = row.EthRateCents;

                    // use fresh prices (see BuyGoldCrypto())
                    if ((DateTime.UtcNow - row.TimeCreated) >= TimeSpan.FromHours(1))
                    {
                        dealGoldPrice = null;
                        dealEthPrice  = null;
                    }

                    var estimation = CoreLogic.Finance.Estimation.BuyGoldCrypto(
                        services: _services,
                        ethereumToken: TradableCurrency.Eth,
                        fiatCurrency: row.ExchangeCurrency,
                        cryptoAmount: ethAmount,
                        knownGoldRateCents: dealGoldPrice,
                        knownCryptoRateCents: dealEthPrice
                        ).Result;

                    // price provider failed
                    if (!estimation.Allowed)
                    {
                        Logger.Error($"Failed to process order #{id}, estimation failed");
                        return;
                    }

                    try {
                        // history
                        var finHistory = new DAL.Models.UserFinHistory()
                        {
                            Status            = UserFinHistoryStatus.Completed,
                            Type              = UserFinHistoryType.GoldDeposit,
                            Source            = "ETH",
                            SourceAmount      = TextFormatter.FormatTokenAmountFixed(ethAmount, TokensPrecision.Ethereum),
                            Destination       = "GOLD",
                            DestinationAmount = TextFormatter.FormatTokenAmountFixed(estimation.ResultGoldAmount, TokensPrecision.Sumus),
                            Comment           = "",
                            TimeCreated       = DateTime.UtcNow,
                            UserId            = row.UserId,
                        };
                        _dbContext.UserFinHistory.Add(finHistory);
                        _dbContext.SaveChanges();

                        row.Status          = BuySellGoldRequestStatus.Success;
                        row.TimeCompleted   = DateTime.UtcNow;
                        row.RelFinHistoryId = finHistory.Id;
                        _dbContext.SaveChanges();

                        var ok = CoreLogic.Finance.SumusWallet.Refill(_services, row.UserId, estimation.ResultGoldAmount.FromSumus(), SumusToken.Gold).Result;
                        if (!ok)
                        {
                            Logger.Error($"Deposit request #{row.Id} completed but wallet not refilled with {estimation.ResultGoldAmount.FromSumus()} GOLD");
                        }
                        else
                        {
                            Logger.Information($"Deposit request #{row.Id} completed");
                        }
                    } catch (Exception e) {
                        Logger.Error(e, $"Failed to process order #{id}, while saving to DB");
                        return;
                    }
                }

                // reply
                args.Message.ArrivalSubcription.Connection.Publish(
                    args.Message.Reply, new Eth2Gold.Event.OrderDepositedAck().ToByteArray()
                    );
            }
            catch (Exception e) {
                Logger.Error(e, $"Failed to process message");
            }
        }
示例#2
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,
            }
                       ));
        }
示例#3
0
        private void HandleMessage(object _, MsgHandlerEventArgs args)
        {
            try {
                _dbContext.DetachEverything();

                var request = MintSender.Watcher.Event.Refill.Parser.ParseFrom(args.Message.Data);

                if (request.Service != "core_gold_deposit")
                {
                    return;
                }

                // find wallet
                var row =
                    (from r in _dbContext.UserSumusWallet where r.PublicKey == request.PublicKey select r)
                    .AsNoTracking()
                    .LastOrDefault()
                ;
                if (row == null)
                {
                    throw new Exception($"Wallet #{request.PublicKey} not found");
                }

                // parse amount
                var ok = decimal.TryParse(request.Amount, System.Globalization.NumberStyles.AllowDecimalPoint, System.Globalization.CultureInfo.InvariantCulture, out var amount);
                if (!ok)
                {
                    throw new Exception($"Failed to parse amount");
                }
                // truncate
                amount = amount.ToSumus().FromSumus();

                // parse token
                ok = Common.Sumus.Token.ParseToken(request.Token, out var token);
                if (!ok)
                {
                    throw new Exception($"Failed to parse token");
                }

                // history
                var finHistory = new DAL.Models.UserFinHistory()
                {
                    Status            = UserFinHistoryStatus.Completed,
                    Type              = UserFinHistoryType.GoldDeposit,
                    Source            = "",
                    SourceAmount      = "",
                    Destination       = "GOLD",
                    DestinationAmount = TextFormatter.FormatTokenAmountFixed(amount),
                    Comment           = "",
                    TimeCreated       = DateTime.UtcNow,
                    UserId            = row.UserId,
                };
                _dbContext.UserFinHistory.Add(finHistory);
                _dbContext.SaveChanges();

                // refill
                if (!CoreLogic.Finance.SumusWallet.Refill(_services, row.UserId, amount, token).Result)
                {
                    throw new Exception($"Failed to process refilling");
                }

                // reply
                args.Message.ArrivalSubcription.Connection.Publish(
                    args.Message.Reply, new MintSender.Watcher.Event.RefillAck()
                {
                    Success = true
                }.ToByteArray()
                    );
            }
            catch (Exception e) {
                Logger.Error(e, $"Failed to process message");

                // reply
                args.Message.ArrivalSubcription.Connection.Publish(
                    args.Message.Reply, new MintSender.Watcher.Event.RefillAck()
                {
                    Success = false, Error = e.ToString()
                }.ToByteArray()
                    );
            }
        }