protected override async Task OnUpdate() { _dbContext.DetachEverything(); var rows = await (from r in _dbContext.EthSending where r.Status == EthereumOperationStatus.Initial select r) .Include(_ => _.User) .Include(_ => _.RelFinHistory) .AsTracking() .Take(_rowsPerRound) .ToArrayAsync(CancellationToken) ; if (IsCancelled() || rows.Length == 0) { return; } var ethAmount = await _ethReader.GetEtherBalance(await _ethWriter.GetEthSender()); foreach (var r in rows) { if (IsCancelled() || ethAmount < r.Amount.ToEther()) { return; } try { r.Status = EthereumOperationStatus.BlockchainInit; _dbContext.SaveChanges(); var tx = await _ethWriter.SendEth(r.Address, r.Amount.ToEther()); r.Status = EthereumOperationStatus.BlockchainConfirm; r.Transaction = tx; r.TimeNextCheck = DateTime.UtcNow.AddSeconds(60); ethAmount -= r.Amount.ToEther(); try { // notification await EmailComposer.FromTemplate(await _templateProvider.GetEmailTemplate(EmailTemplate.ExchangeEthTransferred, Locale.En)) .ReplaceBodyTag("REQUEST_ID", r.Id.ToString()) .ReplaceBodyTag("ETHERSCAN_LINK", _appConfig.Services.Ethereum.EtherscanTxView + tx) .ReplaceBodyTag("DETAILS_SOURCE", r.RelFinHistory?.SourceAmount ?? "?" + " GOLD") .ReplaceBodyTag("DETAILS_ESTIMATED", r.RelFinHistory?.DestinationAmount ?? "?" + " ETH") .ReplaceBodyTag("DETAILS_ADDRESS", TextFormatter.MaskBlockchainAddress(r.Address)) .Send(r.User.Email, r.User.UserName, _notificationQueue) ; } catch { } } catch (Exception e) { Logger.Error(e, $"Failed to process #{r.Id}"); } } }