예제 #1
0
        private async Task <List <ApiTransactionResult> > GetWithdrawals(ApiUserTransactionsRequest request)
        {
            var count       = Math.Min(request.Count ?? 100, 1000);
            var cacheResult = await CacheService.GetOrSetHybridAsync(CacheKey.ApiUserTransactions(request.UserId.ToString(), TransactionType.Withdraw), TimeSpan.FromSeconds(60), async() =>
            {
                using (var context = ExchangeDataContextFactory.CreateReadOnlyContext())
                {
                    return(await context.Withdraw
                           .AsNoTracking()
                           .Where(x => x.UserId == request.UserId)
                           .OrderByDescending(x => x.Id)
                           .Take(1000)
                           .Select(x => new ApiTransactionResult
                    {
                        Amount = x.Amount,
                        Confirmations = x.Confirmations,
                        Currency = x.Currency.Symbol,
                        Fee = 0,
                        Id = x.Id,
                        Status = x.Status.ToString(),
                        Timestamp = x.TimeStamp,
                        TxId = x.Txid,
                        Type = "Withdraw",
                        Address = x.Address
                    }).ToListNoLockAsync().ConfigureAwait(false));
                }
            }).ConfigureAwait(false);

            return(cacheResult);
        }
예제 #2
0
        public async Task <UserBalanceItemModel> GetBalance(string userId, int currencyId)
        {
            try
            {
                var currentUser = new Guid(userId);
                using (var context = ExchangeDataContextFactory.CreateReadOnlyContext())
                {
                    var balance = await context.Balance
                                  .AsNoTracking()
                                  .Where(x => x.UserId == currentUser && x.CurrencyId == currencyId)
                                  .Select(x => new UserBalanceItemModel
                    {
                        CurrencyId      = x.CurrencyId,
                        HeldForTrades   = (decimal?)x.HeldForTrades ?? 0,
                        PendingWithdraw = (decimal?)x.PendingWithdraw ?? 0,
                        Name            = x.Currency.Name,
                        Symbol          = x.Currency.Symbol,
                        Status          = x.Currency.Status,
                        ListingStatus   = x.Currency.ListingStatus,
                        StatusMessage   = x.Currency.StatusMessage,
                        Total           = (decimal?)x.Total ?? 0,
                        Unconfirmed     = (decimal?)x.Unconfirmed ?? 0,
                        IsFavorite      = (bool?)x.IsFavorite ?? false,
                        CurrencyType    = x.Currency.Type,
                        BaseAddress     = x.Currency.BaseAddress
                    }).FirstOrDefaultNoLockAsync().ConfigureAwait(false);

                    return(balance);
                }
            }
            catch (Exception)
            {
                return(new UserBalanceItemModel());
            }
        }
예제 #3
0
        public async Task <UserBalanceModel> GetBalances(string userId, bool calculateEstimate)
        {
            try
            {
                var model       = new UserBalanceModel();
                var currentUser = new Guid(userId);
                using (var context = ExchangeDataContextFactory.CreateReadOnlyContext())
                {
                    var query = from currency in context.Currency
                                from balance in context.Balance.Where(b => b.UserId == currentUser && b.CurrencyId == currency.Id).DefaultIfEmpty()
                                //	from address in context.Address.Where(a => a.UserId == currentUser && a.CurrencyId == currency.Id).DefaultIfEmpty()
                                where currency.IsEnabled
                                orderby currency.Name
                                select new UserBalanceItemModel
                    {
                        //Address = address.AddressHash,
                        CurrencyId      = currency.Id,
                        HeldForTrades   = (decimal?)balance.HeldForTrades ?? 0,
                        PendingWithdraw = (decimal?)balance.PendingWithdraw ?? 0,
                        Name            = currency.Name,
                        Symbol          = currency.Symbol,
                        Status          = currency.Status,
                        ListingStatus   = currency.ListingStatus,
                        StatusMessage   = currency.StatusMessage,
                        Total           = (decimal?)balance.Total ?? 0,
                        Unconfirmed     = (decimal?)balance.Unconfirmed ?? 0,
                        IsFavorite      = (bool?)balance.IsFavorite ?? false,
                        CurrencyType    = currency.Type,
                        BaseAddress     = currency.BaseAddress
                    };

                    var balances = await query.ToListNoLockAsync().ConfigureAwait(false);

                    model.Balances = balances.DistinctBy(x => x.CurrencyId).ToList();
                }

                if (calculateEstimate)
                {
                    await model.Balances.ForEachAsync(async b => b.EstimatedBTC = await BalanceEstimationService.GetEstimatedBTC(b.Total, b.CurrencyId));

                    model.BTCEstimate    = model.Balances.Sum(x => x.EstimatedBTC);
                    model.BTCEstimateAlt = model.Balances.Where(x => x.CurrencyId != Constant.BITCOIN_ID).Sum(x => x.EstimatedBTC);

                    var verificationData = await UserVerificationReader.GetVerificationStatus(userId).ConfigureAwait(false);

                    model.HasWithdrawLimit = verificationData.Limit > 0;
                    model.WithdrawLimit    = verificationData.Limit;
                    model.WithdrawTotal    = verificationData.Current;
                }
                return(model);
            }
            catch (Exception)
            {
                return(new UserBalanceModel());
            }
        }
예제 #4
0
        public async Task <DataTablesResponse> GetAddresses(DataTablesModel model)
        {
            using (var context = ExchangeDataContextFactory.CreateReadOnlyContext())
            {
                var query = context.Address
                            .AsNoTracking()
                            .Select(x => new
                {
                    Id       = x.Id,
                    UserName = x.User.UserName,
                    x.AddressHash
                }).Distinct();

                return(await query.GetDataTableResultNoLockAsync(model).ConfigureAwait(false));
            }
        }
 public async Task <UpdateWithdrawalTxModel> GetWithdrawalToUpdate(int id)
 {
     using (var context = ExchangeDataContextFactory.CreateReadOnlyContext())
     {
         return(await context.Withdraw
                .AsNoTracking()
                .Where(x => x.Status == Enums.WithdrawStatus.Processing)
                .Select(x => new UpdateWithdrawalTxModel
         {
             Id = x.Id,
             TxId = x.Txid,
             Status = x.Status,
             Address = x.Address,
             Amount = x.Amount,
             RetryCount = x.RetryCount
         }).FirstOrDefaultNoLockAsync(x => x.Id == id).ConfigureAwait(false));
     }
 }
        public async Task <VerificationStatusModel> GetVerificationStatus(string userId)
        {
            var currentUser = new Guid(userId);
            var lastTime    = DateTime.UtcNow.AddHours(-24);

            using (var context = ExchangeDataContextFactory.CreateReadOnlyContext())
            {
                var user = await context.Users.FirstOrDefaultNoLockAsync(x => x.Id == currentUser);

                if (user == null)
                {
                    return(null);
                }

                var current = 0m;
                if (user.VerificationLevel != VerificationLevel.Legacy)
                {
                    var currentWithdrawDetails = await context.Withdraw
                                                 .Where(x => x.UserId == currentUser && x.Status != Enums.WithdrawStatus.Canceled && x.TimeStamp > lastTime)
                                                 .ToListNoLockAsync();

                    if (currentWithdrawDetails.Any())
                    {
                        current = currentWithdrawDetails.Sum(x => x.EstimatedPrice);
                    }

                    var currentTransferDetails = await context.Transfer
                                                 .Where(x => x.UserId == currentUser && x.Timestamp > lastTime && (x.TransferType == TransferType.User || x.TransferType == TransferType.Tip))
                                                 .ToListNoLockAsync();

                    if (currentTransferDetails.Any())
                    {
                        current += currentTransferDetails.Sum(x => x.EstimatedPrice);
                    }
                }

                return(new VerificationStatusModel
                {
                    Level = user.VerificationLevel,
                    Limit = VerificationLimit(user.VerificationLevel),
                    Current = current
                });
            }
        }
예제 #7
0
        public async Task <DataTablesResponse> GetTransfers(DataTablesModel model)
        {
            using (var context = ExchangeDataContextFactory.CreateReadOnlyContext())
            {
                var query = context.Transfer
                            .AsNoTracking()
                            .Select(x => new
                {
                    Id        = x.Id,
                    Sender    = x.User.UserName,
                    Receiver  = x.ToUser.UserName,
                    Amount    = x.Amount,
                    Type      = x.TransferType,
                    Timestamp = x.Timestamp
                });

                return(await query.GetDataTableResultNoLockAsync(model).ConfigureAwait(false));
            }
        }
        public async Task <DataTablesResponse> GetIncompleteWithdrawals(DataTablesModel model)
        {
            var        newest             = DateTime.Now.AddHours(-2.0);
            List <int> pendingApprovalIds = null;

            using (var approvalContext = DataContextFactory.CreateReadOnlyContext())
            {
                var approvals = await approvalContext.ApprovalQueue
                                .Where(a => a.Type == ApprovalQueueType.WithdrawalReprocessing && a.Status == ApprovalQueueStatus.Pending)
                                .Select(a => a)
                                .ToListNoLockAsync().ConfigureAwait(false);

                pendingApprovalIds = approvals.Select(a =>
                {
                    int id;
                    bool success = int.TryParse(JsonConvert.DeserializeObject <ReprocessingApprovalDataModel>(a.Data).WithdrawalId, out id);
                    return(new { success, id });
                })
                                     .Where(x => x.success)
                                     .Select(x => x.id).ToList();
            }

            using (var context = ExchangeDataContextFactory.CreateReadOnlyContext())
            {
                var query = context.Withdraw
                            .AsNoTracking()
                            .Where(w => w.Status == Enums.WithdrawStatus.Processing && w.Confirmed <= newest && !pendingApprovalIds.Contains(w.Id))
                            .Select(x => new
                {
                    Id         = x.Id,
                    UserName   = x.User.UserName,
                    Currency   = x.Currency.Symbol,
                    Amount     = x.Amount,
                    Address    = x.Address,
                    Confirmed  = x.Confirmed,
                    RetryCount = x.RetryCount
                });

                var result = await query.GetDataTableResultNoLockAsync(model).ConfigureAwait(false);

                return(result);
            }
        }
예제 #9
0
        public async Task <DataTablesResponse> GetDeposits(DataTablesModel model)
        {
            using (var context = ExchangeDataContextFactory.CreateReadOnlyContext())
            {
                var query = context.Deposit
                            .AsNoTracking()
                            .Select(x => new
                {
                    Id        = x.Id,
                    UserName  = x.User.UserName,
                    Amount    = x.Amount,
                    Status    = x.Status,
                    Type      = x.Type.ToString(),
                    TxId      = x.Txid,
                    Conf      = x.Confirmations,
                    Timestamp = x.TimeStamp
                });

                return(await query.GetDataTableResultNoLockAsync(model).ConfigureAwait(false));
            }
        }
예제 #10
0
        public async Task <DataTablesResponse> GetWithdrawals(DataTablesModel model)
        {
            using (var context = ExchangeDataContextFactory.CreateReadOnlyContext())
            {
                var query = context.Withdraw
                            .AsNoTracking()
                            .Select(x => new
                {
                    Id        = x.Id,
                    UserName  = x.User.UserName,
                    Amount    = x.Amount,
                    Status    = x.Status,
                    Confirmed = x.Confirmed,
                    TxId      = x.Txid,
                    Address   = x.Address,
                    Conf      = x.Confirmations,
                    Timestamp = x.TimeStamp,
                    Init      = x.IsApi ? "API" : "UI"
                });

                return(await query.GetDataTableResultNoLockAsync(model).ConfigureAwait(false));
            }
        }
        public async Task <DataTablesResponse> GetWalletTransactions(WalletTxRequestModel model, DataTablesModel tableModel)
        {
            var cacheResult = await CacheService.GetOrSetMemoryAsync(CacheKey.WalletTransactions(model.Currency), TimeSpan.FromMinutes(10), async() =>
            {
                int currencyId = -1;

                using (var context = ExchangeDataContextFactory.CreateReadOnlyContext())
                {
                    Entity.Currency selectedCurrency = await context.Currency.FirstOrDefaultNoLockAsync(c => c.Symbol.Equals(model.Currency));

                    if (selectedCurrency != null)
                    {
                        currencyId = selectedCurrency.Id;
                    }
                }

                if (currencyId == -1)
                {
                    return(null);
                }

                List <WalletTransaction> transactions = new List <WalletTransaction>();
                using (var service = new AdmintopiaServiceClient())
                    transactions = await service.GetWalletTransactionsSinceAsync(AdmintopiaService.TransactionDataType.Withdraw, currencyId, WalletTimeoutMinutes, model.BlockLength);

                return(transactions.Select(x => new
                {
                    Type = x.Type,
                    Amount = x.Amount,
                    Txid = x.Txid,
                    Address = x.Address
                }));
            });

            return(cacheResult.GetDataTableResult(tableModel, true));
        }
예제 #12
0
        public async Task <ApiUserTradeHistoryResponse> GetUserTradeHistory(ApiUserTradeHistoryRequest request)
        {
            var count = Math.Min(request.Count ?? 100, 1000);

            if (request.TradePairId.HasValue || !string.IsNullOrEmpty(request.Market))
            {
                var tradepair = request.TradePairId.HasValue
                                        ? await TradePairReader.GetTradePair(request.TradePairId.Value, true).ConfigureAwait(false)
                                        : await TradePairReader.GetTradePair(request.Market.Replace('/', '_'), true).ConfigureAwait(false);

                if (tradepair == null)
                {
                    return new ApiUserTradeHistoryResponse {
                               Success = false, Error = "Market not found."
                    }
                }
                ;

                var cacheResult = await CacheService.GetOrSetMemoryAsync(CacheKey.ApiUserTradeHistory(request.UserId.ToString(), tradepair.TradePairId), TimeSpan.FromSeconds(1), async() =>
                {
                    using (var context = ExchangeDataContextFactory.CreateReadOnlyContext())
                    {
                        var history = context.TradeHistory
                                      .AsNoTracking()
                                      .Where(x => x.TradePairId == tradepair.TradePairId && (x.UserId == request.UserId || x.ToUserId == request.UserId))
                                      .OrderByDescending(x => x.Id)
                                      .Take(1000)
                                      .Select(x => new ApiTradeHistory
                        {
                            Market  = string.Concat(x.TradePair.Currency1.Symbol, "/", x.TradePair.Currency2.Symbol),
                            TradeId = x.Id,
                            Amount  = x.Amount,
                            Rate    = x.Rate,
                            Type    = x.UserId == request.UserId
                                                                        ? TradeHistoryType.Buy.ToString()
                                                                        : TradeHistoryType.Sell.ToString(),
                            TimeStamp   = x.Timestamp,
                            TradePairId = x.TradePairId,
                            Fee         = x.Fee
                        });
                        return(await history.ToListNoLockAsync().ConfigureAwait(false));
                    }
                }).ConfigureAwait(false);

                return(new ApiUserTradeHistoryResponse
                {
                    Success = true,
                    Data = cacheResult.Take(count).ToList()
                });
            }
            else
            {
                var cacheResult = await CacheService.GetOrSetHybridAsync(CacheKey.ApiUserTradeHistory(request.UserId.ToString()), TimeSpan.FromSeconds(20), async() =>
                {
                    using (var context = ExchangeDataContextFactory.CreateReadOnlyContext())
                    {
                        var history = context.TradeHistory
                                      .AsNoTracking()
                                      .Where(x => x.UserId == request.UserId || x.ToUserId == request.UserId)
                                      .OrderByDescending(x => x.Id)
                                      .Take(1000)
                                      .Select(x => new ApiTradeHistory
                        {
                            Market  = string.Concat(x.TradePair.Currency1.Symbol, "/", x.TradePair.Currency2.Symbol),
                            TradeId = x.Id,
                            Amount  = x.Amount,
                            Rate    = x.Rate,
                            Type    = x.UserId == request.UserId
                                                                        ? TradeHistoryType.Buy.ToString()
                                                                        : TradeHistoryType.Sell.ToString(),
                            TimeStamp   = x.Timestamp,
                            TradePairId = x.TradePairId,
                            Fee         = x.Fee
                        });

                        return(await history.ToListNoLockAsync().ConfigureAwait(false));
                    }
                }).ConfigureAwait(false);

                return(new ApiUserTradeHistoryResponse
                {
                    Success = true,
                    Data = cacheResult.Take(count).ToList()
                });
            }
        }
예제 #13
0
        public async Task <ApiSubmitUserWithdrawResponse> SubmitUserWithdraw(ApiSubmitUserWithdrawRequest request)
        {
            var currency = request.CurrencyId.HasValue
                                        ? await CurrencyReader.GetCurrency(request.CurrencyId.Value).ConfigureAwait(false)
                                        : await CurrencyReader.GetCurrency(request.Currency).ConfigureAwait(false);

            if (currency == null)
            {
                return new ApiSubmitUserWithdrawResponse {
                           Success = false, Error = "Currency not found."
                }
            }
            ;

            if (currency.Status == CurrencyStatus.Maintenance || currency.Status == CurrencyStatus.Offline || currency.Status == CurrencyStatus.NoConnections)
            {
                return new ApiSubmitUserWithdrawResponse {
                           Success = false, Error = $"Currency is currently not available for withdraw, Status: {currency.Status}"
                }
            }
            ;

            if (request.Amount < currency.WithdrawMin)
            {
                return new ApiSubmitUserWithdrawResponse {
                           Success = false, Error = $"Withdraw amount is below the minimum, Minimum: {currency.WithdrawMin:F8} {currency.Symbol}"
                }
            }
            ;

            if (request.Amount > currency.WithdrawMax)
            {
                return new ApiSubmitUserWithdrawResponse {
                           Success = false, Error = $"Withdraw amount is above the maximum, Maximum: {currency.WithdrawMax:F8} {currency.Symbol}"
                }
            }
            ;

            var balance = await UserBalanceReader.GetBalance(request.UserId.ToString(), currency.CurrencyId).ConfigureAwait(false);

            if (balance == null || request.Amount > balance.Available)
            {
                return new ApiSubmitUserWithdrawResponse {
                           Success = false, Error = "Insufficient funds."
                }
            }
            ;

            var user = await UserReader.GetUserById(request.UserId.ToString()).ConfigureAwait(false);

            if (user == null || !user.IsApiWithdrawEnabled)
            {
                return new ApiSubmitUserWithdrawResponse {
                           Success = false, Error = "Your API withdraw setting is currently disabled."
                }
            }
            ;

            var address = request.Address;

            if (currency.AddressType != AddressType.Standard)
            {
                address = $"{request.Address}:{request.PaymentId ?? string.Empty}";
            }
            if (currency.Type == CurrencyType.Fiat)
            {
                address = address.TrimEnd(':');
            }

            if (!user.IsApiUnsafeWithdrawEnabled)
            {
                using (var context = ExchangeDataContextFactory.CreateReadOnlyContext())
                {
                    var validAddress = await context.AddressBook
                                       .AsNoTracking()
                                       .FirstOrDefaultAsync(x => x.UserId == request.UserId && x.CurrencyId == currency.CurrencyId && x.Address == address && x.IsEnabled).ConfigureAwait(false);

                    if (validAddress == null)
                    {
                        return new ApiSubmitUserWithdrawResponse {
                                   Success = false, Error = $"Address does not exist in your secure Withdraw Address Book"
                        }
                    }
                    ;
                }
            }
            else
            {
                if (currency.CurrencyId == Constant.NZDT_ID && !UserVerificationReader.IsVerified(user.VerificationLevel))
                {
                    return(new ApiSubmitUserWithdrawResponse {
                        Success = false, Error = $"Id verification required for NZDT services."
                    });
                }

                if (!await DepositService.ValidateAddress(currency.CurrencyId, address))
                {
                    return new ApiSubmitUserWithdrawResponse {
                               Success = false, Error = $"Invalid {currency.Symbol} address."
                    }
                }
                ;
            }

            var response = await TradeService.CreateWithdraw(request.UserId.ToString(), new CreateWithdrawModel
            {
                Address        = address,
                Amount         = Math.Max(0, request.Amount),
                CurrencyId     = balance.CurrencyId,
                TwoFactorToken = string.Empty,
                Type           = WithdrawType.Normal
            }, true).ConfigureAwait(false);

            if (response.IsError)
            {
                return new ApiSubmitUserWithdrawResponse {
                           Success = false, Error = response.Error
                }
            }
            ;

            return(new ApiSubmitUserWithdrawResponse
            {
                Success = true,
                Data = response.WithdrawId
            });
        }
예제 #14
0
        public async Task CalculateFeeTotalsAndPortions(DateTime startOfMonthToProcess, Dictionary <int, decimal> tradeHistoryFeeByCurrencyTotals, Dictionary <int, decimal> paytopiaPaymentFeeByCurrencyTotals, Dictionary <int, decimal> tradeHistoryPortionsOfCurrency, Dictionary <int, decimal> paytopiaPaymentPortionsOfCurrency)
        {
            Log.Message(LogLevel.Info, "CalculateFeeTotalsAndPortions entered.");
            List <string> auditMessages = new List <string>();

            auditMessages.Add($"CEFS Process. Calculating total fees and portion sizes for CEFS holders.");

            // get trade histories from the start of last month to the start of this month
            // (i.e. 1 Oct (incl) - 1 Nov (excl)).
            var startOfFollowingMonth = startOfMonthToProcess.AddMonths(1).Date;

            using (var context = ExchangeDataContextFactory.CreateReadOnlyContext())
            {
                var tradeHistoryFeesByCurrency = await(from h in context.TradeHistory
                                                       join tp in context.TradePair on h.TradePairId equals tp.Id
                                                       join c in context.Currency on tp.CurrencyId2 equals c.Id
                                                       where h.Timestamp < startOfFollowingMonth &&
                                                       h.Timestamp >= startOfMonthToProcess
                                                       group h.Fee by c.Id into g
                                                       select new { CurrencyId = g.Key, TotalFees = g.Sum() * 2 }).ToListAsync();                                          // multiplied by two to account for both sides of the trade

                foreach (var history in tradeHistoryFeesByCurrency)
                {
                    var tradeHistoryPortionSize = (history.TotalFees * FOUR_POINT_FIVE_PERCENT) / TOTAL_PORTIONS;
                    tradeHistoryPortionsOfCurrency.Add(history.CurrencyId, tradeHistoryPortionSize);
                    tradeHistoryFeeByCurrencyTotals.Add(history.CurrencyId, history.TotalFees);

                    // add auditing to be able to check if there is anything wrong after deployment.
                    auditMessages.Add($"Trade History Total for {history.CurrencyId}: {history.TotalFees}");
                    auditMessages.Add($"Trade History portion size for {history.CurrencyId}: {tradeHistoryPortionSize}");
                }
            }

            using (var hubContext = DataContextFactory.CreateContext())
            {
                var paytopiaPaymentsByCurrency = await(from p in hubContext.PaytopiaPayments
                                                       join pi in hubContext.PaytopiaItems on p.PaytopiaItemId equals pi.Id
                                                       where p.Timestamp < startOfFollowingMonth &&
                                                       p.Timestamp >= startOfMonthToProcess &&
                                                       p.Status == PaytopiaPaymentStatus.Complete &&
                                                       pi.CurrencyId == 2
                                                       group pi.Price by pi.CurrencyId into g
                                                       select new { CurrencyId = g.Key, TotalPayments = g.Sum() }).ToListAsync();

                var paytopiaRefundsByCurrency = await(from p in hubContext.PaytopiaPayments
                                                      join pi in hubContext.PaytopiaItems on p.PaytopiaItemId equals pi.Id
                                                      where p.Timestamp < startOfFollowingMonth &&
                                                      p.Timestamp >= startOfMonthToProcess &&
                                                      p.Status == PaytopiaPaymentStatus.Refunded &&
                                                      pi.CurrencyId == 2
                                                      group pi.Price by pi.CurrencyId into g
                                                      select new { CurrencyId = g.Key, TotalRefunds = g.Sum() }).ToListAsync();

                foreach (var payment in paytopiaPaymentsByCurrency)
                {
                    var     refund = paytopiaRefundsByCurrency.FirstOrDefault(x => x.CurrencyId == payment.CurrencyId);
                    decimal total  = 0;

                    if (refund == null)
                    {
                        total = payment.TotalPayments;
                    }
                    else
                    {
                        total = payment.TotalPayments - refund.TotalRefunds;
                    }

                    var portionSize = (total * FOUR_POINT_FIVE_PERCENT) / TOTAL_PORTIONS;
                    paytopiaPaymentPortionsOfCurrency.Add(payment.CurrencyId, portionSize);
                    paytopiaPaymentFeeByCurrencyTotals.Add(payment.CurrencyId, total);

                    auditMessages.Add($"Paytopia Payments Total for {payment.CurrencyId}: {payment.TotalPayments}");

                    if (refund != null)
                    {
                        auditMessages.Add($"Paytopia Payment refunds total for {payment.CurrencyId}: {refund.TotalRefunds}");
                    }

                    auditMessages.Add($"Paytopia Payment portion size for {payment.CurrencyId}: {portionSize}");
                }

                auditMessages.Add($"CEFS Process. Calculation complete.");

                foreach (var message in auditMessages)
                {
                    hubContext.LogActivity(Constant.SYSTEM_USER_CEFS.ToString(), message);
                }

                await hubContext.SaveChangesAsync();
            }

            Log.Message(LogLevel.Info, "CalculateFeeTotalsAndPortions exited.");
        }
예제 #15
0
        public async Task <ApiUserOpenOrdersResponse> GetUserOpenOrders(ApiUserOpenOrdersRequest request)
        {
            if (request.TradePairId.HasValue || !string.IsNullOrEmpty(request.Market))
            {
                var tradepair = request.TradePairId.HasValue
                                        ? await TradePairReader.GetTradePair(request.TradePairId.Value, true).ConfigureAwait(false)
                                        : await TradePairReader.GetTradePair(request.Market.Replace('/', '_'), true).ConfigureAwait(false);

                if (tradepair == null)
                {
                    return new ApiUserOpenOrdersResponse {
                               Success = false, Error = "Market not found."
                    }
                }
                ;

                using (var context = ExchangeDataContextFactory.CreateReadOnlyContext())
                {
                    var openOrders = context.Trade
                                     .AsNoTracking()
                                     .Where(x => x.UserId == request.UserId && x.TradePairId == tradepair.TradePairId && (x.Status == TradeStatus.Partial || x.Status == TradeStatus.Pending))
                                     .OrderByDescending(x => x.Id)
                                     .Select(x => new ApiOpenOrder
                    {
                        Amount      = x.Amount,
                        Market      = string.Concat(x.TradePair.Currency1.Symbol, "/", x.TradePair.Currency2.Symbol),
                        OrderId     = x.Id,
                        Rate        = x.Rate,
                        Remaining   = x.Remaining,
                        TimeStamp   = x.Timestamp,
                        TradePairId = x.TradePairId,
                        Type        = x.Type.ToString()
                    });

                    return(new ApiUserOpenOrdersResponse
                    {
                        Success = true,
                        Data = await openOrders.ToListNoLockAsync().ConfigureAwait(false)
                    });
                }
            }
            else
            {
                using (var context = ExchangeDataContextFactory.CreateReadOnlyContext())
                {
                    var openOrders = context.Trade
                                     .AsNoTracking()
                                     .Where(x => x.UserId == request.UserId && (x.Status == TradeStatus.Partial || x.Status == TradeStatus.Pending))
                                     .OrderByDescending(x => x.Id)
                                     .Select(x => new ApiOpenOrder
                    {
                        Amount      = x.Amount,
                        Market      = string.Concat(x.TradePair.Currency1.Symbol, "/", x.TradePair.Currency2.Symbol),
                        OrderId     = x.Id,
                        Rate        = x.Rate,
                        Remaining   = x.Remaining,
                        TimeStamp   = x.Timestamp,
                        TradePairId = x.TradePairId,
                        Type        = x.Type.ToString()
                    });

                    return(new ApiUserOpenOrdersResponse
                    {
                        Success = true,
                        Data = await openOrders.ToListNoLockAsync().ConfigureAwait(false)
                    });
                }
            }
        }
예제 #16
0
        public async Task <PaytopiaPaymentModel> GetPayment(int id)
        {
            PaytopiaPaymentModel item;
            string  currencySymbol;
            dynamic refCurrency;

            Entity.Pool refPool;

            using (var context = DataContextFactory.CreateReadOnlyContext())
            {
                item = await context.PaytopiaPayments
                       .AsNoTracking()
                       .Where(x => x.Id == id)
                       .Select(payment => new PaytopiaPaymentModel
                {
                    Id            = payment.Id,
                    Type          = payment.PaytopiaItem.Type,
                    CurrencyId    = payment.PaytopiaItem.CurrencyId,
                    Amount        = payment.Amount,
                    Status        = payment.Status,
                    UserName      = payment.User.UserName,
                    IsAnonymous   = payment.IsAnonymous,
                    Begins        = payment.Begins,
                    Ends          = payment.Ends,
                    Timestamp     = payment.Timestamp,
                    TransferId    = payment.TransferId,
                    RefundId      = payment.RefundId,
                    ReferenceCode = payment.ReferenceCode,
                    ReferenceId   = payment.ReferenceId,
                    RefundReason  = payment.RefundReason,
                    RequestData   = payment.RequestData,
                }).FirstOrDefaultNoLockAsync().ConfigureAwait(false);
            }

            using (var exchangeContext = ExchangeDataContextFactory.CreateReadOnlyContext())
            {
                currencySymbol = await exchangeContext.Currency.Where(c => c.Id == item.CurrencyId).Select(c => c.Symbol).FirstOrDefaultNoLockAsync();

                refCurrency = await exchangeContext.Currency.Where(c => c.Id == item.ReferenceId).Select(c => new {
                    Name     = c.Name,
                    AlgoType = c.Info.AlgoType,
                    Symbol   = c.Symbol
                }).FirstOrDefaultNoLockAsync();
            }

            using (var poolContext = PoolDataContextFactory.CreateContext())
            {
                refPool = await poolContext.Pool.Where(p => p.IsEnabled && p.Id == item.ReferenceId).FirstOrDefaultNoLockAsync();
            }

            item.Symbol = currencySymbol;

            if (item.ReferenceId > 0)
            {
                if (item.Type == PaytopiaItemType.FeaturedCurrency || item.Type == PaytopiaItemType.LottoSlot || item.Type == PaytopiaItemType.RewardSlot || item.Type == PaytopiaItemType.TipSlot)
                {
                    if (refCurrency != null)
                    {
                        item.ReferenceName   = refCurrency.Name;
                        item.ReferenceAlgo   = refCurrency.AlgoType;
                        item.ReferenceSymbol = refCurrency.Symbol;
                    }
                }
                else if (item.Type == PaytopiaItemType.FeaturedPool || item.Type == PaytopiaItemType.PoolListing)
                {
                    if (refPool != null)
                    {
                        item.ReferenceName   = refPool.Name;
                        item.ReferenceAlgo   = refPool.AlgoType;
                        item.ReferenceSymbol = refPool.Symbol;
                    }
                }
            }

            return(item);
        }
        public async Task <IWriterResult> BeginDelistingCurrency(string adminUserId, UpdateListingStatusModel model)
        {
            model.ListingStatus = CurrencyListingStatus.Delisting;

            if (model.DelistOn == null)
            {
                return(new WriterResult(false, "Delist date cannot be null"));
            }

            var writerResult = await UpdateListingStatus(adminUserId, model);

            if (!writerResult.Success)
            {
                return(writerResult);
            }

            using (var context = ExchangeDataContextFactory.CreateContext())
            {
                // Checks for open trade pairs only to avoid accidentally relisting delisted currencies.
                var tradePairs = await context.TradePair.Where(t => (t.Status == TradePairStatus.OK || t.Status == TradePairStatus.Paused) && (t.CurrencyId1 == model.CurrencyId || t.CurrencyId2 == model.CurrencyId)).ToListNoLockAsync();

                foreach (var tradePair in tradePairs)
                {
                    tradePair.Status = TradePairStatus.Closing;
                }

                using (var adminContext = DataContextFactory.CreateContext())
                {
                    adminContext.LogActivity(adminUserId, "Closing TradePair due to delisting");
                    await adminContext.SaveChangesAsync().ConfigureAwait(false);
                }

                await context.SaveChangesAsync().ConfigureAwait(false);

                await CacheService.InvalidateAsync(CacheKey.AllTradePairs(), CacheKey.TradePairs()).ConfigureAwait(false);
            }

            writerResult.Message = "Successfully started the delisting process.";

            try
            {
                var email = new EmailMessageModel
                {
                    EmailType        = EmailTemplateType.CoinDelisting,
                    BodyParameters   = new object[0],
                    SystemIdentifier = model.Symbol
                };

                using (var context = ExchangeDataContextFactory.CreateReadOnlyContext())
                {
                    var balances = await context.Balance.Include(b => b.User).Where(b => b.Currency.Name == model.Name && b.Total > 0).OrderBy(b => b.User.Email).ToListNoLockAsync();

                    if (!balances.Any())
                    {
                        writerResult.Message = "Successfully started the delisting process but no non zero balances found so no emails were sent.";
                        return(writerResult);
                    }

                    var personalisations = new List <IEmailPersonalisation>(balances.Select(balance => new EmailPersonalisation {
                        Tos = new List <string> {
                            balance.User.Email
                        },
                        Substitutions = new Dictionary <string, string>
                        {
                            { "-name-", balance.User.UserName },
                            { "-coinName-", model.Name },
                            { "-coinSymbol-", model.Symbol },
                            { "-delistDate-", model.DelistOn.Value.ToString("R") },
                            { "-delistReason-", model.StatusMessage },
                            { "-balance-", balance.Total.ToString(CultureInfo.InvariantCulture) }
                        }
                    })
                                                                            .ToList());

                    var hasSentSuccessfully = await EmailService.SendEmails(email, personalisations);

                    if (!hasSentSuccessfully)
                    {
                        writerResult.Success = false;
                        writerResult.Message = "Successfully started the delisting process but emails failed to send.";
                        return(writerResult);
                    }
                }

                using (var adminContext = DataContextFactory.CreateContext())
                {
                    adminContext.LogActivity(adminUserId, $"Started Currency Delisting Process for: {model.Name}");
                    await adminContext.SaveChangesAsync().ConfigureAwait(false);
                }
            }
            catch (Exception)
            {
                return(new WriterResult(false, "Sending emails failed"));
            }
            return(writerResult);
        }