public async Task InsertOrReplace(ICoinEvent coinEvent) { var entity = CoinEventEntity.CreateEntity(coinEvent); var index = new AzureIndex(_operationIdIndex, coinEvent.OperationId, entity); await _table.InsertOrReplaceAsync(entity); await _index.InsertOrReplaceAsync(index); }
public async Task PublishEvent(ICoinEvent coinEvent, bool putInProcessingQueue = true) { await _coinEventRepository.InsertOrReplace(coinEvent); await _coinEventPublisher.PublishEvent(coinEvent); if (putInProcessingQueue) { await _coinTransactionService.PutTransactionToQueue(coinEvent.TransactionHash, coinEvent.OperationId); } }
//return whether we have sent to rabbit or not private async Task <bool> SendCompletedCoinEvent(string transactionHash, string operationId, bool success, QueueTriggeringContext context, CoinTransactionMessage transaction) { try { ICoinEvent coinEvent = await GetCoinEvent(transactionHash, operationId, success); switch (coinEvent.CoinEventType) { case CoinEventType.CashinStarted: ICashinEvent cashinEvent = await _transactionEventsService.GetCashinEvent(transactionHash); if (cashinEvent == null) { SendMessageToTheQueueEnd(context, transaction, 100); return(false); } //transferContract - userAddress await UpdateUserTransferWallet(coinEvent.FromAddress, coinEvent.ToAddress.ToLower()); coinEvent.Amount = cashinEvent.Amount; coinEvent.CoinEventType++; break; case CoinEventType.CashoutStarted: case CoinEventType.TransferStarted: //Say that Event Is completed coinEvent.CoinEventType++; break; default: break; } await _coinEventService.PublishEvent(coinEvent, putInProcessingQueue : false); await _pendingTransactionsRepository.Delete(transactionHash); await _pendingOperationService.MatchHashToOpId(transactionHash, coinEvent.OperationId); return(true); } catch (Exception e) { await _log.WriteErrorAsync("MonitoringCoinTransactionJob", "SendCompletedCoinEvent", $"trHash: {transactionHash}", e, DateTime.UtcNow); SendMessageToTheQueueEnd(context, transaction, 100); return(false); } }
public static CoinEventEntity CreateEntity(ICoinEvent coinEvent) { return(new CoinEventEntity { PartitionKey = GetPartitionKey(), TransactionHash = coinEvent.TransactionHash, Additional = coinEvent.Additional, Amount = coinEvent.Amount, CoinEventType = coinEvent.CoinEventType, ContractAddress = coinEvent.ContractAddress, Success = coinEvent.Success, ToAddress = coinEvent.ToAddress, FromAddress = coinEvent.FromAddress, EventTime = coinEvent.EventTime, OperationId = coinEvent.OperationId }); }
private async Task RepeatOperationTillWin(CoinTransactionMessage message) { ICoinEvent coinEvent = await GetCoinEvent(message.TransactionHash, message.OperationId, true); if (coinEvent == null) { await _eventTraceRepository.InsertAsync(new EventTrace() { Note = $"Operation processing is over. Put it in the garbage. With hash {message.TransactionHash}", OperationId = message.OperationId, TraceDate = DateTime.UtcNow }); return; } switch (coinEvent.CoinEventType) { case CoinEventType.CashinStarted: case CoinEventType.CashinCompleted: await UpdateUserTransferWallet(coinEvent.FromAddress, coinEvent.ToAddress); break; default: break; } await _eventTraceRepository.InsertAsync(new EventTrace() { Note = $"Operation With Id {coinEvent.OperationId} hash {message.TransactionHash} goes to {Constants.PendingOperationsQueue}", OperationId = message.OperationId, TraceDate = DateTime.UtcNow }); await _pendingOperationService.RefreshOperationByIdAsync(coinEvent.OperationId); }
public async Task Execute(CoinTransactionMessage transaction, QueueTriggeringContext context) { ICoinTransaction coinTransaction = null; try { bool isTransactionInMemoryPool = await _ethereumTransactionService.IsTransactionInPool(transaction.TransactionHash); if (isTransactionInMemoryPool) { SendMessageToTheQueueEnd(context, transaction, 100, "Transaction is in memory pool"); return; } coinTransaction = await _coinTransactionService.ProcessTransaction(transaction); } catch (Exception ex) { if (ex.Message != transaction.LastError) { await _log.WriteWarningAsync("MonitoringCoinTransactionJob", "Execute", $"TrHash: [{transaction.TransactionHash}]", ""); } SendMessageToTheQueueEnd(context, transaction, 200, ex.Message); await _log.WriteErrorAsync("MonitoringCoinTransactionJob", "Execute", "", ex); return; } if ((coinTransaction == null) && (DateTime.UtcNow - transaction.PutDateTime > _broadcastMonitoringPeriodSeconds)) { await RepeatOperationTillWin(transaction); await _slackNotifier.ErrorAsync($"EthereumCoreService: Transaction with hash {transaction.TransactionHash} has no confirmations." + $" Reason - unable to find transaction in txPool and in blockchain within {_broadcastMonitoringPeriodSeconds} seconds"); } else { if (coinTransaction != null && coinTransaction.ConfirmationLevel >= CoinTransactionService.Level2Confirm) { if (!coinTransaction.Error) { bool sentToRabbit = await SendCompletedCoinEvent( transaction.TransactionHash, transaction.OperationId, true, context, transaction); if (sentToRabbit) { await _log.WriteInfoAsync("CoinTransactionService", "Execute", "", $"Put coin transaction {transaction.TransactionHash} to rabbit queue with confimation level {coinTransaction?.ConfirmationLevel ?? 0}"); } else { await _log.WriteInfoAsync("CoinTransactionService", "Execute", "", $"Put coin transaction {transaction.TransactionHash} to monitoring queue with confimation level {coinTransaction?.ConfirmationLevel ?? 0}"); } } else { ICoinEvent coinEvent = await GetCoinEvent(transaction.TransactionHash, transaction.OperationId, true); await _slackNotifier.ErrorAsync($"EthereumCoreService: Transaction with hash {transaction.TransactionHash} has an Error!({coinEvent.CoinEventType})"); if (coinEvent.CoinEventType == CoinEventType.CashoutStarted || coinEvent.CoinEventType == CoinEventType.CashoutFailed) { if (coinTransaction.ConfirmationLevel >= 2) { //SEND FAILED CASHOUTS EVENTS HERE AND FILL Black LIST await _blackListAddressesRepository.SaveAsync(new BlackListAddress() { Address = coinEvent.ToAddress }); await SendCompletedCoinEvent(transaction.TransactionHash, transaction.OperationId, false, context, transaction); } else { SendMessageToTheQueueEnd(context, transaction, 200, "Did not recieve confirmation level 3 yet"); } return; } else { await RepeatOperationTillWin(transaction); await _slackNotifier.ErrorAsync($"EthereumCoreService: Transaction with hash {transaction.TransactionHash} has an Error. RETRY!({coinEvent.CoinEventType})"); } } } else { SendMessageToTheQueueEnd(context, transaction, 100); await _log.WriteInfoAsync("CoinTransactionService", "Execute", "", $"Put coin transaction {transaction.TransactionHash} to monitoring queue with confimation level {coinTransaction?.ConfirmationLevel ?? 0}"); } } }
//return whether we have sent to rabbit or not private async Task <bool> SendCompletedCoinEvent(string transactionHash, string operationId, bool success, QueueTriggeringContext context, CoinTransactionMessage transaction) { try { ICoinEvent coinEvent = await GetCoinEvent(transactionHash, operationId, success); switch (coinEvent.CoinEventType) { case CoinEventType.CashinStarted: ICashinEvent cashinEvent = await _transactionEventsService.GetCashinEvent(transactionHash); if (cashinEvent == null) { await _transactionEventsService.IndexEventsForTransaction(coinEvent.ContractAddress, transactionHash); SendMessageToTheQueueEnd(context, transaction, 100); return(false); } //transferContract - userAddress await UpdateUserTransferWallet(coinEvent.FromAddress, coinEvent.ToAddress.ToLower()); coinEvent.Amount = cashinEvent.Amount; coinEvent.CoinEventType++; break; case CoinEventType.CashoutStarted: case CoinEventType.TransferStarted: //Say that Event Is completed coinEvent.CoinEventType++; break; default: break; } #region FailedCashout if (coinEvent.CoinEventType == CoinEventType.CashoutCompleted && !success) { coinEvent.CoinEventType = CoinEventType.CashoutFailed; await _coinEventService.InsertAsync(coinEvent); SendMessageToTheQueueEnd(context, transaction, 200, "Put Failed cashout in the end of the queue"); return(false); } if (coinEvent.CoinEventType == CoinEventType.CashoutFailed && !success) { var historycal = await _pendingOperationService.GetHistoricalAsync(operationId); if (historycal != null) { foreach (var match in historycal) { if (!string.IsNullOrEmpty(match.TransactionHash) && await _ethereumTransactionService.IsTransactionExecuted(match.TransactionHash, Constants.GasForCoinTransaction)) { var @event = await _coinEventService.GetCoinEvent(match.TransactionHash); if (@event != null && @event.TransactionHash.ToLower() == match.TransactionHash.ToLower()) { await _slackNotifier.ErrorAsync($"EthereumCoreService: Transaction with hash {coinEvent.TransactionHash} [{coinEvent.OperationId}]" + $" ({coinEvent.CoinEventType}). Previously was successfully transfered"); return(false); } } } } } #endregion await _coinEventService.PublishEvent(coinEvent, putInProcessingQueue : false); await _pendingTransactionsRepository.Delete(transactionHash); await _pendingOperationService.MatchHashToOpId(transactionHash, coinEvent.OperationId); return(true); } catch (Exception e) { await _log.WriteErrorAsync("MonitoringCoinTransactionJob", "SendCompletedCoinEvent", $"trHash: {transactionHash}", e, DateTime.UtcNow); SendMessageToTheQueueEnd(context, transaction, 100); return(false); } }
public async Task InsertAsync(ICoinEvent coinEvent) { await _coinEventRepository.InsertOrReplace(coinEvent); }
private static Lykke.Job.EthereumCore.Contracts.Events.CoinEvent GetCoinEvent(ICoinEvent coinEvent) { var coinEventType = (Lykke.Job.EthereumCore.Contracts.Enums.CoinEventType)coinEvent.CoinEventType; return(new Lykke.Job.EthereumCore.Contracts.Events.CoinEvent(coinEvent.OperationId, coinEvent.TransactionHash, coinEvent.FromAddress, coinEvent.ToAddress, coinEvent.Amount, coinEventType, coinEvent.ContractAddress, coinEvent.Success, coinEvent.Additional)); }
public async Task PublishEvent(ICoinEvent coinEvent) { var @event = GetCoinEvent(coinEvent); string coinEventSerialized = Newtonsoft.Json.JsonConvert.SerializeObject(@event); await _rabbitPublisher.PublshEvent(coinEventSerialized); }