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); }
/// <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); } }