Ejemplo n.º 1
0
 /// <summary>
 /// Initializes a new instance of the <see cref="RewardProcessor"/> class.
 /// </summary>
 /// <param name="pollPeriod">The poll period.</param>
 /// <param name="cancelToken">The cancel token.</param>
 public RewardProcessor(int pollPeriod, CancellationToken cancelToken)
 {
     _pollPeriod  = pollPeriod;
     _cancelToken = cancelToken;
     ExchangeDataContextFactory = new ExchangeDataContextFactory();
     CreateRewardTypeWeightedList();
 }
Ejemplo n.º 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());
            }
        }
Ejemplo n.º 3
0
        private async Task ProcessInternal(DateTime startOfMonthToProcess)
        {
            Log.Message(LogLevel.Info, $"[Process] - CEFS processing round {startOfMonthToProcess.Date} started.");
            List <string>             transactionIds = new List <string>();
            Dictionary <int, decimal> tradeHistoryFeeByCurrencyTotals    = new Dictionary <int, decimal>();
            Dictionary <int, decimal> paytopiaPaymentFeeByCurrencyTotals = new Dictionary <int, decimal>();
            Dictionary <int, decimal> tradeHistoryPortionsOfCurrency     = new Dictionary <int, decimal>();
            Dictionary <int, decimal> paytopiaPaymentPortionsOfCurrency  = new Dictionary <int, decimal>();

            using (var context = ExchangeDataContextFactory.CreateContext())
            {
                // get users and balances for each user
                var userIdsAndBalances = await GetUsersAndTheirBalanacesForCEFPayments(startOfMonthToProcess, context);

                // if we have some users, do the CEFS processing routine.
                if (userIdsAndBalances.Any())
                {
                    await CalculateFeeTotalsAndPortions(startOfMonthToProcess, tradeHistoryFeeByCurrencyTotals, paytopiaPaymentFeeByCurrencyTotals, tradeHistoryPortionsOfCurrency, paytopiaPaymentPortionsOfCurrency);

                    TransferSumsToSystemStagingUser(transactionIds, tradeHistoryFeeByCurrencyTotals, paytopiaPaymentFeeByCurrencyTotals, context);
                    List <int> Currencies = GetDistinctCurrencyIds(tradeHistoryPortionsOfCurrency, paytopiaPaymentPortionsOfCurrency);

                    List <TransferHistory> transfers = CreateTransferHistoriesForUsersToReceiveCEFSPayments(tradeHistoryPortionsOfCurrency, paytopiaPaymentPortionsOfCurrency, userIdsAndBalances);

                    Log.Message(LogLevel.Info, "Committing CEFS calculations to database.");
                    await SaveTransfersAndAuditAllUserBalances(userIdsAndBalances, transfers, Currencies, context);
                    await PerformWalletTransactionsAndUpdateDepositsWithIds(transactionIds, context);
                }
            }

            Log.Message(LogLevel.Info, "CEFS Processing round complete.");
        }
Ejemplo n.º 4
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);
        }
        public async Task <IWriterResult> DelistCurrency(string adminUserId, UpdateListingStatusModel model)
        {
            model.ListingStatus = CurrencyListingStatus.Delisted;
            var writerResult = await UpdateListingStatus(adminUserId, model);

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

            using (var context = ExchangeDataContextFactory.CreateContext())
            {
                // Checks for closing trade pairs only as it's expected to be in 'delisting' before it's delisted.
                var tradePairs = await context.TradePair.Where(t => t.Status == TradePairStatus.Closing && (t.CurrencyId1 == model.CurrencyId || t.CurrencyId2 == model.CurrencyId)).ToListNoLockAsync();

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

                using (var adminContext = DataContextFactory.CreateContext())
                {
                    adminContext.LogActivity(adminUserId, $"Delisted Currency: {model.Name}");
                    await adminContext.SaveChangesAsync().ConfigureAwait(false);
                }

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

                await CacheService.InvalidateAsync(CacheKey.Currencies(), CacheKey.CurrencyInfo(), CacheKey.CurrencyDataTable(), CacheKey.CurrencySummary(model.CurrencyId)).ConfigureAwait(false);
            }

            writerResult.Message = "Successfully delisted currency.";

            return(writerResult);
        }
        public ReferralProcessor(CancellationToken cancelToken) : base(cancelToken)
        {
#if DEBUG
            _pollPeriod = 1;
#endif
            _cancelToken               = cancelToken;
            DataContextFactory         = new DataContextFactory();
            ExchangeDataContextFactory = new ExchangeDataContextFactory();
        }
Ejemplo n.º 7
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());
            }
        }
Ejemplo n.º 8
0
        public NzdtProcessor(CancellationToken cancelToken) : base(cancelToken)
        {
            _cancelToken = cancelToken;
            ExchangeDataContextFactory = new ExchangeDataContextFactory();

            _nzdtAssetWalletPort = int.Parse(ConfigurationManager.AppSettings["NzdtAssetWalletPort"]);

            _nzdtAssetWalletIp       = ConfigurationManager.AppSettings["NzdtAssetWalletIp"];
            _nzdtAssetWalletUserName = ConfigurationManager.AppSettings["NzdtAssetWalletUserName"];
            _nzdtAssetWalletPassword = ConfigurationManager.AppSettings["NzdtAssetWalletPassword"];

            if (string.IsNullOrEmpty(_nzdtAssetWalletIp) || string.IsNullOrEmpty(_nzdtAssetWalletUserName) || string.IsNullOrEmpty(_nzdtAssetWalletPassword))
            {
                throw new ArgumentNullException("Nzdt Asset Wallet app.config settings missing");
            }
        }
Ejemplo n.º 9
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));
            }
        }
Ejemplo n.º 10
0
        public async Task <IWriterResult> AddUserToTransaction(string adminUserId, UpdateNzdtTransactionModel model)
        {
            int transactionId;

            using (var context = ExchangeDataContextFactory.CreateContext())
            {
                var transaction = await context.NzdtTransaction.FirstOrDefaultNoLockAsync(x => x.Id == model.TransactionId).ConfigureAwait(false);

                if (transaction == null)
                {
                    return(new WriterResult(false, "Transaction not Found"));
                }
                else if (transaction.TransactionStatus != Enums.NzdtTransactionStatus.ErrorUserNotFound)
                {
                    return(new WriterResult(false, "Transaction not in ErrorUserNotFound Status"));
                }

                var user = await context.Users.FirstOrDefaultNoLockAsync(x => x.UserName == model.UserName).ConfigureAwait(false);

                if (user == null)
                {
                    return(new WriterResult(false, "User not Found"));
                }
                else if (user.VerificationLevel != Enums.VerificationLevel.Level2 && user.VerificationLevel != Enums.VerificationLevel.Level3)
                {
                    return(new WriterResult(false, "User Verification level is not Level2 or Level3"));
                }

                transactionId = transaction.Id;

                transaction.User = user;
                transaction.TransactionStatus = Enums.NzdtTransactionStatus.ReadyForProcessing;

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

            using (var context = HubDataContextFactory.CreateContext())
            {
                var logMessage = $"[NZDT Import] Added User To Transaction with Id {transactionId}";

                context.LogActivity(adminUserId, logMessage);
                await context.SaveChangesAsync().ConfigureAwait(false);
            }

            return(new WriterResult(true, "User Added to Transaction"));
        }
 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 <IWriterResult> UpdateCurrency(string adminUserId, UpdateCurrencyModel model)
        {
            try
            {
                using (var context = ExchangeDataContextFactory.CreateContext())
                {
                    var currency =
                        await context.Currency.Where(c => c.Id == model.Id).FirstOrDefaultNoLockAsync().ConfigureAwait(false);

                    if (currency == null)
                    {
                        return(new WriterResult(false, "Currency not found"));
                    }

                    currency.PoolFee          = model.PoolFee;
                    currency.TradeFee         = model.TradeFee;
                    currency.WithdrawFee      = model.WithdrawFee;
                    currency.WithdrawFeeType  = model.WithdrawFeeType;
                    currency.MinWithdraw      = model.WithdrawMin;
                    currency.MaxWithdraw      = model.WithdrawMax;
                    currency.MinTip           = model.TipMin;
                    currency.MinBaseTrade     = model.MinBaseTrade;
                    currency.MinConfirmations = model.MinConfirmations;
                    currency.Status           = model.Status;
                    currency.StatusMessage    = model.StatusMessage;
                    currency.ListingStatus    = model.ListingStatus;

                    using (var adminContext = DataContextFactory.CreateContext())
                    {
                        adminContext.LogActivity(adminUserId, $"Updated Currency: {currency.Symbol}");
                    }

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

                    await CacheService.InvalidateAsync(CacheKey.Currencies(), CacheKey.CurrencyInfo(), CacheKey.CurrencyDataTable(), CacheKey.CurrencySummary(model.Id)).ConfigureAwait(false);

                    return(new WriterResult(true, "Succesfully updated currency settings."));
                }
            }
            catch (Exception)
            {
                return(null);
            }
        }
        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
                });
            }
        }
Ejemplo n.º 14
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);
            }
        }
Ejemplo n.º 16
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));
            }
        }
Ejemplo n.º 17
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));
            }
        }
        private async Task <IWriterResult> UpdateListingStatus(string adminUserId, UpdateListingStatusModel model)
        {
            try
            {
                using (var context = ExchangeDataContextFactory.CreateContext())
                {
                    var currency =
                        await context.Currency.Where(c => c.Id == model.CurrencyId).FirstOrDefaultNoLockAsync().ConfigureAwait(false);

                    if (currency == null)
                    {
                        return(new WriterResult(false, "Currency not found"));
                    }

                    var oldStatus = currency.ListingStatus;
                    currency.StatusMessage     = model.StatusMessage;
                    currency.ListingStatus     = model.ListingStatus;
                    currency.Settings.DelistOn = model.DelistOn;

                    using (var adminContext = DataContextFactory.CreateContext())
                    {
                        adminContext.LogActivity(adminUserId, $"Updated Currency listing status from : {oldStatus} to: {model.ListingStatus}");
                        await adminContext.SaveChangesAsync().ConfigureAwait(false);
                    }

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

                    await CacheService.InvalidateAsync(CacheKey.Currencies(), CacheKey.CurrencyInfo(), CacheKey.CurrencyDataTable(), CacheKey.CurrencySummary(model.CurrencyId)).ConfigureAwait(false);

                    return(new WriterResult(true, "Succesfully updated listing status."));
                }
            }
            catch (Exception)
            {
                return(null);
            }
        }
        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));
        }
Ejemplo n.º 20
0
        public async Task ProcessExchanges()
        {
            using (var context = ExchangeDataContextFactory.CreateContext())
            {
                Log.Message(LogLevel.Info, "[ProcessExchanges] - Creating tradepair map...");
                var tradePairs = await context.TradePair
                                 .Where(x => x.Status == TradePairStatus.OK || x.Status == TradePairStatus.Paused)
                                 .Select(t => new
                {
                    TradePairId = t.Id,
                    Symbol      = t.Currency1.Symbol,
                    BaseSymbol  = t.Currency2.Symbol
                }).ToListNoLockAsync();

                if (tradePairs.IsNullOrEmpty())
                {
                    return;
                }
                var tradePairMap = tradePairs.ToDictionary(k => string.Format("{0}_{1}", k.Symbol, k.BaseSymbol), v => v.TradePairId);
                Log.Message(LogLevel.Info, "[ProcessExchanges] - Tradepair map created.");

                Log.Message(LogLevel.Info, "[ProcessExchanges] - Processing exchanges...");
                foreach (var exchange in _exchanges)
                {
                    if (!_isEnabled)
                    {
                        break;
                    }

                    try
                    {
                        Log.Message(LogLevel.Info, "[ProcessExchanges] - Processing exchange. Exchange: {0}", exchange.Name);
                        var existingData =
                            await context.IntegrationMarketData.Where(x => x.IntegrationExchangeId == exchange.Id).ToListNoLockAsync();

                        var marketData = await exchange.GetMarketData(tradePairMap);

                        if (!marketData.IsNullOrEmpty())
                        {
                            Log.Message(LogLevel.Info, "[ProcessExchanges] - Market data found, Updating database");
                            foreach (var data in marketData)
                            {
                                if (!_isEnabled)
                                {
                                    break;
                                }

                                if (tradePairMap.ContainsKey(data.TradePair))
                                {
                                    var existing = existingData.FirstOrDefault(x => x.TradePairId == tradePairMap[data.TradePair]);
                                    if (existing == null)
                                    {
                                        existing = new IntegrationMarketData
                                        {
                                            IntegrationExchangeId = exchange.Id,
                                            TradePairId           = tradePairMap[data.TradePair]
                                        };
                                        context.IntegrationMarketData.Add(existing);
                                    }

                                    existing.Timestamp  = DateTime.UtcNow;
                                    existing.Ask        = data.Ask;
                                    existing.Bid        = data.Bid;
                                    existing.Last       = data.Last;
                                    existing.Volume     = data.Volume;
                                    existing.BaseVolume = data.BaseVolume;
                                    existing.MarketUrl  = data.MarketUrl;
                                }
                            }
                            await context.SaveChangesAsync();

                            Log.Message(LogLevel.Info, "[ProcessExchanges] - Market data updated.");
                        }

                        var expiredData = existingData.Where(x => x.Timestamp.AddMinutes(_expirePeriod) < DateTime.UtcNow);
                        if (expiredData.Any())
                        {
                            Log.Message(LogLevel.Info, "[ProcessExchanges] - Expired data found, Deleteing...");
                            foreach (var expired in expiredData)
                            {
                                if (!_isEnabled)
                                {
                                    break;
                                }

                                context.IntegrationMarketData.Remove(expired);
                            }
                            await context.SaveChangesAsync();

                            Log.Message(LogLevel.Info, "[ProcessExchanges] - Expired data deleted.");
                        }
                    }
                    catch (Exception ex)
                    {
                        Log.Exception("[ProcessExchanges] - An exception occured processing exchange, Exchange: {0}", ex, exchange.Name);
                    }
                }
                Log.Message(LogLevel.Info, "[ProcessExchanges] - Processing exchanges complete.");
            }
        }
Ejemplo n.º 21
0
        /// <summary>
        /// Processes the lotto items.
        /// </summary>
        private async Task ProcessLotto()
        {
            try
            {
                var payouts = new List <PrizePayout>();
                using (var context = ExchangeDataContextFactory.CreateContext())
                {
                    Log.Message(LogLevel.Info, "[ProcessLotto] - Processing LottoItems...");
                    var dueLottoDraws = await context.LottoItem.Where(x => x.Status != LottoItemStatus.Disabled && DateTime.UtcNow >= x.NextDraw).ToListNoLockAsync();

                    if (dueLottoDraws.IsNullOrEmpty())
                    {
                        // no draws ready
                        Log.Message(LogLevel.Info, "[ProcessLotto] - No lotto draws are due, Waiting...");
                        return;
                    }

                    Log.Message(LogLevel.Info, "[ProcessLotto] - {0} lotto draws found.", dueLottoDraws.Count());
                    foreach (var lottoDraw in dueLottoDraws)
                    {
                        Log.Message(LogLevel.Info, "[ProcessLotto] - Processing LottoItem, Id: {0}, Name: {1}, Currency: {2}", lottoDraw.Id, lottoDraw.Name, lottoDraw.CurrencyId);
                        // 1. sum up total tickets, subtract site fee
                        var tickets = await context.LottoTicket.Where(x => !x.IsArchived && x.LottoItemId == lottoDraw.Id && x.DrawId == lottoDraw.CurrentDrawId).ToListNoLockAsync();

                        if (!tickets.IsNullOrEmpty())
                        {
                            Log.Message(LogLevel.Info, "[ProcessLotto] - {0} tickets found for draw.", tickets.Count());
                            // Archive all the tickets
                            foreach (var ticket in tickets)
                            {
                                ticket.IsArchived = true;
                            }

                            // Calculate prize pool
                            var totalAmount       = lottoDraw.Rate * tickets.Count();
                            var siteFee           = (totalAmount / 100m) * lottoDraw.Fee;
                            var prizePool         = totalAmount - siteFee;
                            var prizePoolFraction = prizePool / 100m;
                            var prizeWeights      = LottoHelpers.GetPrizeWeights(lottoDraw.Prizes);
                            var winningTicketIds  = GetWinningLottoItemIds(tickets.Select(x => x.Id), lottoDraw.Prizes);
                            Log.Message(LogLevel.Info, "[ProcessLotto] - LottoItem draw info, Total: {0}, PrizePool: {1}, Fee: {2}", totalAmount, prizePool, siteFee);

                            // Calculate user prizes
                            var drawTime = lottoDraw.NextDraw;
                            for (int i = 0; i < prizeWeights.Count; i++)
                            {
                                var prizeWeight   = prizeWeights[i];
                                var winningTicket = tickets.FirstOrDefault(x => x.Id == winningTicketIds[i]);
                                var amount        = Math.Round(prizePoolFraction * prizeWeight, 8);
                                payouts.Add(new PrizePayout
                                {
                                    UserId     = winningTicket.UserId,
                                    CurrencyId = lottoDraw.CurrencyId,
                                    Amount     = amount
                                });
                                context.LottoHistory.Add(new LottoHistory
                                {
                                    Amount        = amount,
                                    Percent       = prizeWeight,
                                    LottoItemId   = lottoDraw.Id,
                                    Position      = (i + 1),
                                    Timestamp     = drawTime,
                                    UserId        = winningTicket.UserId,
                                    LottoTicketId = winningTicket.Id,
                                    LottoDrawId   = lottoDraw.CurrentDrawId,
                                    TotalAmount   = prizePool
                                });
                                Log.Message(LogLevel.Info, "[ProcessLotto] - User payout info, UserId: {0}, Position: {1}, Weight: {2}, Amount: {3}", winningTicket.UserId, (i + 1), prizeWeight, amount);
                            }
                        }
                        else
                        {
                            Log.Message(LogLevel.Info, "[ProcessLotto] - No tickets found for draw.");
                        }

                        // 5. update LottoItem
                        lottoDraw.Status = LottoItemStatus.Finished;
                        if (lottoDraw.LottoType == LottoType.Recurring || (lottoDraw.LottoType == LottoType.RecurringExpire && lottoDraw.Expires > DateTime.UtcNow))
                        {
                            lottoDraw.Status        = LottoItemStatus.Active;
                            lottoDraw.CurrentDrawId = lottoDraw.CurrentDrawId + 1;
                            lottoDraw.NextDraw      = lottoDraw.NextDraw.AddHours(lottoDraw.Hours);
                            Log.Message(LogLevel.Info, "[ProcessLotto] - Set next draw date for recurring lotto, NextDraw: {0}", lottoDraw.NextDraw);
                        }

                        Log.Message(LogLevel.Info, "[ProcessLotto] - Processing LottoItem complete.");
                    }

                    // commit the transaction
                    Log.Message(LogLevel.Debug, "[ProcessLotto] - Comitting database transaction...");
                    await context.SaveChangesAsync();

                    Log.Message(LogLevel.Debug, "[ProcessLotto] - Comitted database transaction.");
                }

                // Send Winnings
                await PayoutUsers(payouts);

                Log.Message(LogLevel.Info, "[ProcessLotto] - Processing LottoItems complete.");
            }
            catch (Exception ex)
            {
                Log.Exception("[ProcessLotto] - An exception occured processing LottoItem.", ex);
            }
        }
Ejemplo n.º 22
0
 /// <summary>
 /// Initializes a new instance of the <see cref="LottoProcessor"/> class.
 /// </summary>
 /// <param name="cancelToken">The cancel token.</param>
 public LottoProcessor(CancellationToken cancelToken)
 {
     _cancelToken = cancelToken;
     ExchangeDataContextFactory = new ExchangeDataContextFactory();
 }
Ejemplo n.º 23
0
        private async Task ProcessPaytopiaItems()
        {
            try
            {
                var now            = DateTime.UtcNow;
                var beginingOfWeek = now.StartOfWeek(DayOfWeek.Monday);
                var endOfWeek      = beginingOfWeek.AddDays(7);
                var featuredItems  = new List <FeaturedInfo>();
                using (var context = DataContextFactory.CreateContext())
                {
                    featuredItems = await context.PaytopiaPayments
                                    .Where(x => x.Begins >= beginingOfWeek && x.Ends <= endOfWeek && (x.PaytopiaItem.Type == PaytopiaItemType.FeaturedCurrency || x.PaytopiaItem.Type == PaytopiaItemType.FeaturedPool))
                                    .Select(x => new FeaturedInfo
                    {
                        Id         = x.ReferenceId,
                        Type       = x.PaytopiaItem.Type,
                        ExpireTime = x.Ends
                    }).ToListNoLockAsync();
                }

                if (!featuredItems.Any())
                {
                    return;
                }

                // update currencies
                using (var context = ExchangeDataContextFactory.CreateContext())
                {
                    var currencyIds = featuredItems.Where(x => x.Type == PaytopiaItemType.FeaturedCurrency).Select(x => x.Id).ToList();
                    var currencies  = await context.Currency.Where(x => currencyIds.Contains(x.Id)).ToListNoLockAsync();

                    foreach (var currency in currencies)
                    {
                        var featureExpireTime = featuredItems.First(x => x.Type == PaytopiaItemType.FeaturedCurrency && x.Id == currency.Id).ExpireTime;
                        if (featureExpireTime != currency.FeaturedExpires)
                        {
                            currency.FeaturedExpires = featureExpireTime;
                        }
                    }
                    await context.SaveChangesAsync();
                }

                // update pools
                using (var context = PoolDataContextFactory.CreateContext())
                {
                    var poolIds = featuredItems.Where(x => x.Type == PaytopiaItemType.FeaturedPool).Select(x => x.Id).ToList();
                    var pools   = await context.Pool.Where(x => poolIds.Contains(x.Id)).ToListNoLockAsync();

                    foreach (var pool in pools)
                    {
                        var featureExpireTime = featuredItems.First(x => x.Type == PaytopiaItemType.FeaturedPool && x.Id == pool.Id).ExpireTime;
                        if (featureExpireTime != pool.FeaturedExpires)
                        {
                            pool.FeaturedExpires = featureExpireTime;
                        }
                    }
                    await context.SaveChangesAsync();
                }
            }
            catch (Exception ex)
            {
                Log.Exception("[ProcessPaytopiaItems] - An exception occurred processing Paytopia items.", ex);
            }
        }
Ejemplo n.º 24
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.");
        }
Ejemplo n.º 25
0
 public CEFSProcessor(CancellationToken cancelToken) : base(cancelToken)
 {
     _token                     = cancelToken;
     DataContextFactory         = new DataContextFactory();
     ExchangeDataContextFactory = new ExchangeDataContextFactory();
 }
Ejemplo n.º 26
0
        private async Task ProcessTransactions()
        {
            Log.Message(LogLevel.Info, "[ProcessNZDT] - Processing NZDT Transactions...");

            List <NzdtTransaction> nzdtTransactions;

            using (var context = ExchangeDataContextFactory.CreateContext())
            {
                nzdtTransactions = await context.NzdtTransaction
                                   .Where(x => x.TransactionStatus == NzdtTransactionStatus.ReadyForProcessing)
                                   .Where(x => DbFunctions.AddHours(x.CreatedOn, 1) <= DateTime.UtcNow)
                                   .ToListNoLockAsync();

                Log.Message(LogLevel.Info, $"[ProcessNZDT] - {nzdtTransactions.Count()} transactions found, processing...");

                foreach (var transaction in nzdtTransactions)
                {
                    transaction.TransactionStatus = NzdtTransactionStatus.Processed;
                }

                await context.SaveChangesAsync();
            }

            var wallet = new WalletConnector(_nzdtAssetWalletIp, _nzdtAssetWalletPort, _nzdtAssetWalletUserName, _nzdtAssetWalletPassword, 30000);

            foreach (var transaction in nzdtTransactions)
            {
                try
                {
                    var sendResult = await wallet.SendToAddressAsync(Constant.NzdtBaseExchangeAddress, transaction.Amount);

                    using (var context = ExchangeDataContextFactory.CreateContext())
                    {
                        var deposit = new Deposit
                        {
                            Txid          = string.IsNullOrEmpty(sendResult?.Txid) ? $"{transaction.Id}" : sendResult.Txid,
                            Amount        = transaction.Amount,
                            TimeStamp     = DateTime.UtcNow,
                            CurrencyId    = Constant.NZDT_ID,
                            Status        = DepositStatus.Confirmed,
                            Confirmations = 20,
                            UserId        = transaction.UserId.Value,
                            Type          = DepositType.Normal
                        };

                        var tx = await context.NzdtTransaction.FirstNoLockAsync(x => x.Id == transaction.Id);

                        tx.Deposit = deposit;

                        await context.SaveChangesAsync();

                        await context.AuditUserBalance(transaction.UserId.Value, Constant.NZDT_ID);

                        await context.SaveChangesAsync();
                    }
                }
                catch (Exception ex)
                {
                    Log.Exception($"[ProcessNZDT] Insert Deposit failed for transaction {transaction.Id}", ex);
                }
            }

            Log.Message(LogLevel.Info, $"[ProcessNZDT] - Processing NZDT Transactions complete.");
        }
Ejemplo n.º 27
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
            });
        }
Ejemplo n.º 28
0
        public async Task <IServiceResult <NzdtUploadResultModel> > ValidateAndUpload(string adminUserId, Stream inputStream)
        {
            var processResult = await ProcessCsv(inputStream);

            if (!processResult.Success || !processResult.HasResult)
            {
                return(new ServiceResult <NzdtUploadResultModel>(false, processResult.Message));
            }

            var csvTransactionItems = processResult.Result;
            var firstDate           = csvTransactionItems.Min(x => x.Date);

            var resultModel = new NzdtUploadResultModel
            {
                TotalCount = csvTransactionItems.Count
            };

            List <NzdtTransaction> transactionsToUpload = new List <NzdtTransaction>();

            long firstUploadedTransactionUniqueId = 0;
            long lastUploadedTransactionUniqueId  = 0;

            using (var context = ExchangeDataContextFactory.CreateContext())
            {
                var transactions = await context.NzdtTransaction
                                   .Where(t => t.Date >= firstDate)
                                   .ToListNoLockAsync().ConfigureAwait(false);

                var addressProjections = await context.Address
                                         .Where(a => a.CurrencyId == Constant.NZDT_ID)
                                         .Select(a => new AddressProjection
                {
                    UserId            = a.UserId,
                    UserName          = a.User.UserName,
                    VerificationLevel = a.User.VerificationLevel,
                    AddressHash       = a.AddressHash,
                }).ToListNoLockAsync().ConfigureAwait(false);

                foreach (var item in csvTransactionItems)
                {
                    var matchingTransaction = transactions.FirstOrDefault(x => x.UniqueId == item.UniqueId);
                    var matchingAddress     = addressProjections.FirstOrDefault(x => item.Memo.ToUpper().Contains(x.Address));

                    if (matchingTransaction != null)
                    {
                        //Transaction Exists
                        resultModel.ExistingCount++;
                        continue;
                    }

                    if (matchingAddress != null)
                    {
                        var isVerificationValid = (matchingAddress.VerificationLevel == VerificationLevel.Level2 || matchingAddress.VerificationLevel == VerificationLevel.Level3);

                        if (isVerificationValid)
                        {
                            transactionsToUpload.Add(new NzdtTransaction
                            {
                                TransactionStatus = NzdtTransactionStatus.ReadyForProcessing,
                                UserId            = matchingAddress.UserId,

                                Date         = item.Date,
                                UniqueId     = item.UniqueId,
                                TranType     = item.TranType,
                                ChequeNumber = item.ChequeNumber,
                                Payee        = item.Payee,
                                Memo         = item.Memo,
                                Amount       = item.Amount,

                                CreatedOn = DateTime.UtcNow
                            });

                            resultModel.ReadyForProcessingCount++;
                        }
                        else
                        {
                            transactionsToUpload.Add(new NzdtTransaction
                            {
                                TransactionStatus = NzdtTransactionStatus.ErrorUserNotVerified,
                                UserId            = matchingAddress.UserId,

                                Date         = item.Date,
                                UniqueId     = item.UniqueId,
                                TranType     = item.TranType,
                                ChequeNumber = item.ChequeNumber,
                                Payee        = item.Payee,
                                Memo         = item.Memo,
                                Amount       = item.Amount,

                                CreatedOn = DateTime.UtcNow
                            });

                            resultModel.ErroredCount++;
                        }
                    }
                    else
                    {
                        transactionsToUpload.Add(new NzdtTransaction
                        {
                            TransactionStatus = NzdtTransactionStatus.ErrorUserNotFound,

                            Date         = item.Date,
                            UniqueId     = item.UniqueId,
                            TranType     = item.TranType,
                            ChequeNumber = item.ChequeNumber,
                            Payee        = item.Payee,
                            Memo         = item.Memo,
                            Amount       = item.Amount,

                            CreatedOn = DateTime.UtcNow
                        });

                        resultModel.ErroredCount++;
                    }
                }

                if (resultModel.TotalCount != (resultModel.ExistingCount + resultModel.ReadyForProcessingCount + resultModel.ErroredCount))
                {
                    return(new ServiceResult <NzdtUploadResultModel>(false, "Error. Processed Transaction Count was out from Total Count"));
                }

                if (transactionsToUpload.Any())
                {
                    firstUploadedTransactionUniqueId = transactionsToUpload.First().UniqueId;
                    lastUploadedTransactionUniqueId  = transactionsToUpload.Last().UniqueId;
                }

                context.NzdtTransaction.AddRange(transactionsToUpload);
                await context.SaveChangesAsync().ConfigureAwait(false);
            }

            using (var context = HubDataContextFactory.CreateContext())
            {
                var logMessage = $"[NZDT Import] Imported {resultModel.ReadyForProcessingCount}. ";

                if (resultModel.ReadyForProcessingCount > 0)
                {
                    logMessage += $"UniqueIds between {firstUploadedTransactionUniqueId} and {lastUploadedTransactionUniqueId}";
                }

                context.LogActivity(adminUserId, logMessage);
                await context.SaveChangesAsync().ConfigureAwait(false);
            }

            return(new ServiceResult <NzdtUploadResultModel>(true, resultModel));
        }
Ejemplo n.º 29
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);
        }