Beispiel #1
0
        private async Task LogCycleCompleted()
        {
            try
            {
                using (var context = new MsSqlDataAccess())
                {
                    Log.Message(LogLevel.Debug, "[UpdateServerInfo] - Updating timestamp");
                    int rowAffected = await context.ExecuteAsync(_updateServerInfo, new
                    {
                        LastRunTime = DateTime.UtcNow,
                        Host        = _hostname
                    });

                    if (rowAffected > 0)
                    {
                        Log.Message(LogLevel.Debug, "[UpdateServerInfo] - timestamp updated");
                    }
                    else
                    {
                        Log.Message(LogLevel.Error, "[UpdateServerInfo] - timestamp update for host: {0} failed", _hostname);
                    }
                }
            }
            catch (Exception ex)
            {
                LogError(ex, "[UpdateServerInfo]", "Timestamp update for host: {0} failed", _hostname);
            }
        }
 /// <summary>
 /// Audits the user balance.
 /// </summary>
 /// <param name="dataAccess">The data access layer.</param>
 /// <param name="userId">The user identifier.</param>
 /// <param name="currency">The currency.</param>
 private async Task <bool> AuditUserBalance(MsSqlDataAccess dataAccess, Guid userId, int currency)
 {
     Log.Message(LogLevel.Debug, "[AuditUserBalance] - Auditing user balance for CurrencyId: {0}, UserId: {1}...",
                 currency, userId);
     if (await dataAccess.ExecuteAsync("AuditUserBalance", new { UserId = userId, CurrencyId = currency }, CommandType.StoredProcedure) > 0)
     {
         Log.Message(LogLevel.Debug, "[AuditUserBalance] - Successfully audited user balance for CurrencyId: {0}, UserId: {1}", currency, userId);
         return(true);
     }
     LogError("AuditUserBalance", "Failed to audit user balance, CurrencyId: {0}, UserId: {1}", currency, userId);
     return(false);
 }
Beispiel #3
0
 public static IDataConnection InitDataBase(DbInitData data = null)
 {
     if (data == null)
     {
         data = DbInit;
     }
     switch (data.ProviderName)
     {
     case "MsSql":
         DataConnection = new MsSqlDataAccess(data);
         break;
     }
     return(DataConnection);
 }
 /// <summary>
 /// Gets all the pending withdraws from the database.
 /// </summary>
 private List <WithdrawResult> GetPendingWithdraws()
 {
     Log.Message(LogLevel.Debug, "[GetPendingWithdraws] - Getting pending withdrawals..");
     using (var dataAccess = new MsSqlDataAccess())
     {
         dataAccess.DataContext.Connection.Open();
         using (var dbTransaction = dataAccess.DataContext.Connection.BeginTransaction(System.Data.IsolationLevel.Snapshot))
         {
             dataAccess.DataContext.Transaction = dbTransaction;
             try
             {
                 var pendingWithdraws = dataAccess.DataContext.ExecuteQuery <WithdrawResult>("EXEC WalletGetPendingWithdraws").ToList();
                 if (!pendingWithdraws.Any())
                 {
                     try
                     {
                         if (dbTransaction != null)
                         {
                             dbTransaction.Rollback();
                         }
                     }
                     catch
                     {
                     }
                     return(new List <WithdrawResult>());
                 }
                 dbTransaction.Commit();
                 Log.Message(LogLevel.Debug, "[GetPendingWithdraws] - Getting pending withdrawals complete.");
                 return(pendingWithdraws);
             }
             catch (Exception ex)
             {
                 try
                 {
                     if (dbTransaction != null)
                     {
                         dbTransaction.Rollback();
                     }
                 }
                 catch
                 {
                 }
                 LogError(ex, "GetPendingWithdraws", "An exception occured in GetPendingWithdraws");
             }
         }
     }
     return(new List <WithdrawResult>());
 }
        public IDatabaseHandler CreateDatabase()
        {
            IDatabaseHandler database = null;

            switch (connectionStringSettings.ProviderName.ToLower())
            {
            case "system.data.sqlclient":
                database = new MsSqlDataAccess(connectionStringSettings.ConnectionString);
                break;

            case "mysql.data.mysqlclient":
                database = new MySqlDataAccess(connectionStringSettings.ConnectionString);
                break;

            case "npgsql":
                database = new PostgreSqlDataAccess(connectionStringSettings.ConnectionString);
                break;

            default:
                break;
            }

            return(database);
        }
        /// <summary>
        /// Processes the withrawals.
        /// </summary>
        /// <returns></returns>
        private async Task ProcessWithrawals()
        {
            using (var dataAccess = new MsSqlDataAccess())
                using (var balanceRepo = new Repository <Balance>())
                    using (var currencyRepo = new Repository <Currency>())
                    {
                        var start = DateTime.Now;
                        Log.Message(LogLevel.Info, "[ProcessWithrawals] - Processing pending withdrawals...");
                        var pendingWithdraws = GetPendingWithdraws();
                        if (!pendingWithdraws.Any())
                        {
                            Log.Message(LogLevel.Info, "[ProcessWithrawals] - No pending withdraws found.");
                            return;
                        }

                        Log.Message(LogLevel.Info, "[ProcessWithrawals] - {0} pending withdraws found, Processing...", pendingWithdraws.Count);
                        foreach (var currency in await currencyRepo.GetAllAsync(x => x.IsEnabled))
                        {
                            if (!_isEnabled)
                            {
                                return;
                            }

                            try
                            {
                                Log.Message(LogLevel.Info, "[ProcessWithrawals] - Processing pending withdraws for {0}...", currency.Symbol);
                                if (!IsWalletOnline(currency.Status))
                                {
                                    Log.Message(LogLevel.Info, "[ProcessWithrawals] - {0} wallet current status is '{1}', skipping.", currency.Symbol,
                                                currency.Status);
                                    continue;
                                }

                                var wallet    = new WalletConnector(currency.WalletHost, currency.WalletPort, currency.WalletUser, currency.WalletPass, 60000 * 4);
                                var withdraws = pendingWithdraws.Where(x => x.CurrencyId == currency.Id);
                                if (withdraws.IsNullOrEmpty())
                                {
                                    Log.Message(LogLevel.Info, "[ProcessWithrawals] - No pending withdraws found for {0}...", currency.Symbol);
                                    continue;                     // next coin
                                }

                                foreach (var withdraw in withdraws)
                                {
                                    Log.Message(LogLevel.Info, "[ProcessWithrawals] - Processing withdraw #{0}...", withdraw.Id);
                                    try
                                    {
                                        //await SendNotification(withdraw.UserId, "Processing {0} withdraw #{1}, {2}{0}", currency.Symbol, withdraw.Id, withdraw.Amount.ToString("F8"));
                                        //Run a balance order to ensure we have the correct balance information
                                        if (!await AuditUserBalance(dataAccess, withdraw.UserId, withdraw.CurrencyId))
                                        {
                                            continue;
                                        }

                                        // get the users balance information has enough in locked in pending
                                        var balance = await balanceRepo.GetOrDefaultAsync(x => x.UserId == withdraw.UserId && x.CurrencyId == withdraw.CurrencyId);

                                        if (balance == null || balance.Total <= 0)
                                        {
                                            //await SendErrorNotification(withdraw.UserId, "{0} withdraw #{1}, Insufficient funds.", currency.Symbol, withdraw.Id);
                                            LogError("ProcessWithrawals", "Withdraw Failed, {0} withdraw #{1}, Insufficient funds.", currency.Symbol, withdraw.Id);
                                            continue;
                                        }
                                        if (balance.Total < withdraw.Amount || balance.PendingWithdraw < withdraw.Amount || balance.PendingWithdraw > balance.Total)
                                        {
                                            //await SendErrorNotification(withdraw.UserId, "{0} withdraw #{1}, Insufficient funds.", currency.Symbol, withdraw.Id);
                                            LogError("ProcessWithrawals", "Withdraw Failed, {0} withdraw #{1}, Insufficient funds.", currency.Symbol, withdraw.Id);
                                            continue;
                                        }

                                        // again check if its a valid address
                                        if (!await wallet.ValidateAddressAsync(withdraw.Address))
                                        {
                                            LogError("ProcessWithrawals", "Withdraw Failed, Invalid {0} address, WithdrawId: {1}", currency.Symbol, withdraw.Id);
                                            continue;
                                        }


                                        //decimal amountExcludingFees = currency.WithdrawFeeType == WithdrawFeeType.Normal
                                        //	? withdraw.Amount - currency.WithdrawFee
                                        //	: withdraw.Amount - ((withdraw.Amount / 100m) * currency.WithdrawFee);
                                        decimal withdrawFee         = GetWithdrawFee(wallet, currency, withdraw.Amount);
                                        decimal amountExcludingFees = withdraw.Amount - withdrawFee;
                                        var     withdrawResult      = await wallet.SendToAddressAsync(withdraw.Address, amountExcludingFees);

                                        if (withdrawResult == null || string.IsNullOrEmpty(withdrawResult.Txid))
                                        {
                                            LogError("ProcessWithrawals", "Withdraw Failed, Failed to send {0} transaction, WithdrawId: {1}", currency.Symbol, withdraw.Id);
                                            continue;
                                        }

                                        // Update the withdraw with the txid and set to completed
                                        if (await dataAccess.ExecuteAsync("WalletSetWithdrawTxId", new { WithdrawId = withdraw.Id, TxId = withdrawResult.Txid }, CommandType.StoredProcedure) <= 0)
                                        {
                                            LogError("ProcessWithrawals", "Withdraw Failed, Failed to update {0} withdraw transaction id, WithdrawId: {1}, TxId: {2}", currency.Symbol, withdraw.Id, withdrawResult.Txid);
                                            continue;
                                        }

                                        //Run a balance audit to ensure we have the correct balance information
                                        if (!await AuditUserBalance(dataAccess, withdraw.UserId, withdraw.CurrencyId))
                                        {
                                            continue;
                                        }

                                        //await SendNotification(withdraw.UserId, "{0} withdrawal #{1} successfully processed.", currency.Symbol, withdraw.Id);
                                        //await SendBalanceNotification(withdraw.UserId, currency.Id, currency.Symbol);
                                    }
                                    catch (Exception ex)
                                    {
                                        LogError(ex, "ProcessWithrawals", "An exception occured processing Currency: {0}, WithdrawId: {1}", ex, currency.Symbol, withdraw.Id);
                                        continue;
                                    }
                                    Log.Message(LogLevel.Info, "[ProcessWithrawals] - Processing withdraw #{0} complete.", withdraw.Id);
                                }
                            }
                            catch (Exception ex)
                            {
                                LogError(ex, "ProcessWithrawals", "An exception occured processing Currency: {0}", ex, currency.Symbol);
                                continue;
                            }
                            Log.Message(LogLevel.Info, "[ProcessWithrawals] - Processing pending withdraws for {0} complete.", currency.Symbol);
                        }
                        Log.Message(LogLevel.Info, "[ProcessWithrawals] - Processing pending withdrawals complete. Elapsed: {0}", DateTime.Now - start);
                    }
        }
Beispiel #7
0
        private async Task QueryDeposits()
        {
            try
            {
                using (var context = new MsSqlDataAccess())
                    using (var userRepo = new Repository <User>())
                        using (var currencyRepo = new Repository <Currency>())
                            using (var depositRepo = new Repository <Deposit>())
                                using (var addressRepo = new Repository <Address>())
                                {
                                    // Cache some data
                                    var userTable   = userRepo.GetAll().ToListNoLock();
                                    var currencies  = currencyRepo.GetAll().Where(x => x.WalletHost == _hostname && x.IsEnabled).ToListNoLock();
                                    var currencyIds = currencies.Select(x => x.Id).ToList();
                                    var addresses   = addressRepo.GetAll().Where(x => currencyIds.Contains(x.CurrencyId)).ToListNoLock();
                                    var allDeposits = depositRepo.GetAll().Where(x => currencyIds.Contains(x.CurrencyId)).ToListNoLock();
                                    foreach (var currency in currencies)
                                    {
                                        if (!_isEnabled)
                                        {
                                            return;
                                        }

                                        try
                                        {
                                            var start = DateTime.Now;
                                            Log.Message(LogLevel.Debug, "[QueryDeposits] - Processing Currency: {0}", currency.Symbol);
                                            if (!IsWalletOnline(currency.Status))
                                            {
                                                Log.Message(LogLevel.Info, "[QueryDeposits] - {0} wallet current status is '{1}', skipping.", currency.Symbol, currency.Status);
                                                continue;
                                            }

                                            // Get everything we need
                                            bool   updateLastBlockHash = true;
                                            string lastBlockHash       = currency.LastBlockHash;

                                            // Get all transactiosn since the last deposit we confirmed
                                            var walletDeposits = GetDeposits(currency);
                                            if (!walletDeposits.IsNullOrEmpty())
                                            {
                                                Log.Message(LogLevel.Debug, "[QueryDeposits] - {0} deposits found since last block.", walletDeposits.Count());
                                                foreach (var walletDeposit in walletDeposits.OrderBy(x => x.Time))
                                                {
                                                    if (!_isEnabled)
                                                    {
                                                        return;
                                                    }

                                                    try
                                                    {
                                                        var user = userTable.FirstOrDefault(u => u.Id == GetUserId(walletDeposit.Account));
                                                        if (user == null)
                                                        {
                                                            var address =
                                                                addresses.FirstOrDefault(x => x.CurrencyId == currency.Id && x.AddressHash == walletDeposit.Address);
                                                            if (address == null)
                                                            {
                                                                continue;
                                                            }

                                                            user = userTable.FirstOrDefault(u => u.Id == address.UserId);
                                                            if (user == null)
                                                            {
                                                                continue;
                                                            }
                                                        }

                                                        // See if it already exists
                                                        var existingDeposit =
                                                            allDeposits.FirstOrDefault(
                                                                x => x.CurrencyId == currency.Id && x.Txid == walletDeposit.Txid && x.UserId == user.Id);
                                                        if (existingDeposit == null)
                                                        {
                                                            // Insert new deposit
                                                            Log.Message(LogLevel.Debug, "[QueryDeposits] - New deposit found. TxId: {0}", walletDeposit.Txid);
                                                            var depositStatus = walletDeposit.Confirmations >= currency.MinConfirmations
                                                                                                ? DepositStatus.Confirmed
                                                                                                : DepositStatus.UnConfirmed;
                                                            await InsertDeposit(context, user.Id, currency.Id, walletDeposit, DepositType.Normal, depositStatus);
                                                            await AuditUserBalance(context, user.Id, currency.Id);

                                                            Log.Message(LogLevel.Debug, "[QueryDeposits] - New deposit inserted. TxId: {0}", walletDeposit.Txid);
                                                            if (depositStatus == DepositStatus.Confirmed)
                                                            {
                                                                lastBlockHash = walletDeposit.Blockhash;
                                                            }

                                                            //await SendBalanceNotification(user.Id, currency.Id, currency.Symbol);
                                                            continue;
                                                        }
                                                        else
                                                        {
                                                            // Chech confirmations for the unconfirmed deposits
                                                            if (existingDeposit.DepositStatus == DepositStatus.UnConfirmed)
                                                            {
                                                                if (existingDeposit.Confirmations == walletDeposit.Confirmations)
                                                                {
                                                                    continue;
                                                                }

                                                                // Update and check if confirmed
                                                                Log.Message(LogLevel.Debug, "[QueryDeposits] - Updating deposit confirmations. DepositId: {0}",
                                                                            existingDeposit.Id);
                                                                if (existingDeposit.Confirmations >= currency.MinConfirmations)
                                                                {
                                                                    Log.Message(LogLevel.Debug, "[QueryDeposits] - Confirming Deposit. DepositId: {0}", existingDeposit.Id);

                                                                    // Depoist is now confirmed, update syatus and notify user
                                                                    await UpdateDeposit(context, existingDeposit.Id, walletDeposit.Confirmations, DepositStatus.Confirmed);
                                                                    await AuditUserBalance(context, user.Id, currency.Id);

                                                                    //await SendNotification(new WalletNotification(user.Id, string.Format("Deposit #{0} Confirmed", existingDeposit.Id), string.Format("{0} {1} has been added to your balance.", existingDeposit.Amount, currency.Symbol)));
                                                                    //await SendBalanceNotification(user.Id, currency.Id, currency.Symbol);

                                                                    lastBlockHash = walletDeposit.Blockhash;
                                                                    Log.Message(LogLevel.Debug, "[QueryDeposits] - Deposit confirmed. DepositId: {0}", existingDeposit.Id);
                                                                    continue;
                                                                }
                                                                await UpdateDeposit(context, existingDeposit.Id, walletDeposit.Confirmations, DepositStatus.UnConfirmed);

                                                                continue;
                                                            }
                                                        }
                                                    }
                                                    catch (Exception ex)
                                                    {
                                                        // dont update the block hash on error so we can try pick up the errord deposit next poll
                                                        updateLastBlockHash = false;
                                                        LogError(ex, "QueryDeposits", "Failed to process deposit, Currency: {0}, TxId: {1}", currency.Symbol, walletDeposit.Txid);
                                                    }
                                                }
                                            }

                                            // Update the last block we processed
                                            if (updateLastBlockHash && lastBlockHash != currency.LastBlockHash)
                                            {
                                                Log.Message(LogLevel.Debug, "[QueryDeposits] - Updating currency last block hash: {0}", lastBlockHash);
                                                await UpdateLastBlockHash(context, currency.Id, lastBlockHash);
                                            }

                                            Log.Message(LogLevel.Debug, "[QueryDeposits] - Processing Currency: {0} complete. Elapsed {1}", currency.Symbol,
                                                        DateTime.Now - start);
                                        }
                                        catch (Exception ex)
                                        {
                                            LogError(ex, "QueryDeposits", "Failed to query currency for deposits, Currency: {0}", currency.Symbol);
                                        }
                                    }
                                }
            }
            catch (Exception ex)
            {
                LogError(ex, "QueryDeposits", "Failed to query deposits");
            }
        }