public async Task HandleAsync(string hash) { if (string.IsNullOrEmpty(hash)) { _log.Warning("Hash is empty"); return; } var statusUpdateResult = await _operationStatusUpdater.SucceedAsync(hash); if (statusUpdateResult.Error == OperationStatusUpdateError.OperationNotFound) { _log.Info("Operation was not found by hash in PBF. Trying to find it via call to Executor", context: hash); statusUpdateResult = await _operationStatusUpdater.SyncWithBlockchainAsync(hash); } if (statusUpdateResult.Error != OperationStatusUpdateError.None) { _log.Warning("Operation status was not updated to succeeded", context: new { hash, error = statusUpdateResult.Error.ToString() }); return; } var operation = await _operationsFetcher.GetByHashAsync(hash); if (operation == null) { _log.Info("Succeeded in BC Operation was not found by hash", context: $"hash: {hash}"); return; } await _transactionSucceededPublisher.PublishAsync(new TransactionSucceededEvent { OperationId = operation.Id.ToString() }); }
public async Task HandleAsync(string hash) { if (string.IsNullOrEmpty(hash)) { _log.Warning("Hash is empty"); return; } var statusUpdateResult = await _operationStatusUpdater.FailAsync(hash); if (statusUpdateResult.Error == OperationStatusUpdateError.OperationNotFound) { _log.Info("Operation was not found by hash in PBF. Trying to find it via call to Executor", context: hash); statusUpdateResult = await _operationStatusUpdater.SyncWithBlockchainAsync(hash); } if (statusUpdateResult.Error != OperationStatusUpdateError.None) { _log.Warning("Operation status was not updated to failed", context: new { hash, error = statusUpdateResult.Error.ToString() }); return; } var operation = await _operationsFetcher.GetByHashAsync(hash); if (operation == null) { _log.Info("Failed in BC Operation was not found by hash", context: $"hash: {hash}"); return; } await _transactionFailedPublisher.PublishAsync(new TransactionFailedEvent { OperationId = operation.Id.ToString() }); switch (operation.Type) { case OperationType.TokensTransfer: await ProcessTransferOperationFailure(operation); break; case OperationType.WalletLinking: await ProcessWalletLinkingOperationFailure(operation); break; case OperationType.WalletUnlinking: await ProcessWalletUnlinkingOperationFailure(operation); break; case OperationType.TransferToExternal: await ProcessTransferToExternalFailure(operation); break; case OperationType.CustomerWalletCreation: case OperationType.CustomerBonusReward: case OperationType.GenericOperation: case OperationType.StakeOperation: case OperationType.TransferToInternal: case OperationType.SetTransferToPublicFee: case OperationType.SeizeToInternal: LogErrorForFailure(operation); break; default: throw new ArgumentOutOfRangeException(nameof(operation.Type)); } }
public async Task HandleAsync( string sourceAddress, string targetAddress, Money18 amount, string transactionHash, DateTime observedAt) { #region Validation if (string.IsNullOrEmpty(sourceAddress)) { _log.Warning("Source address is empty"); return; } if (string.IsNullOrEmpty(targetAddress)) { _log.Warning("Target address is empty"); return; } if (sourceAddress.Equals(EmptyWalletAddress) || targetAddress.Equals(EmptyWalletAddress)) { return; } if (amount <= 0) { _log.Warning("Amount is less or equal 0"); return; } if (string.IsNullOrEmpty(transactionHash)) { _log.Warning("Transaction hash is empty"); return; } #endregion #region Find operation var operation = await _operationsFetcher.GetByHashAsync(transactionHash); if (operation == null) { var transactionState = await _executorClient.TransactionsApi.GetTransactionStateAsync(transactionHash); if (transactionState.Error != GetTransactionStateError.None) { _log.Error(message: "Already processed operation was not found by hash", context: new { transactionHash, sourceAddress, targetAddress }); return; } if (!transactionState.OperationId.HasValue) { _log.Warning("Operation id is empty", context: new { transactionHash, sourceAddress, targetAddress }); return; } operation = await _operationsFetcher.GetByIdAsync(transactionState.OperationId.Value); if (operation == null) { _log.Error(message: "Already processed operation was not found by id", context: new { id = transactionState.OperationId.Value, transactionHash, sourceAddress, targetAddress }); return; } } #endregion var tasksForBalanceUpdate = new List <Task>(); var sourceWalletOwner = await _walletOwnersRepository.GetByWalletAddressAsync(sourceAddress); if (sourceWalletOwner == null) { _log.Info("Transfer with unknown source wallet owner", context: sourceAddress); } else { tasksForBalanceUpdate.Add(_balanceService.ForceBalanceUpdateAsync(sourceWalletOwner.OwnerId, operation.Type, operation.Id)); } var targetWalletOwner = await _walletOwnersRepository.GetByWalletAddressAsync(targetAddress); if (targetWalletOwner == null) { _log.Info("Transfer with unknown target wallet owner", context: targetAddress); } else { tasksForBalanceUpdate.Add(_balanceService.ForceBalanceUpdateAsync(targetWalletOwner.OwnerId, operation.Type, operation.Id)); } await Task.WhenAll(tasksForBalanceUpdate); var context = JsonConvert.DeserializeObject <TokensTransferContext>(operation.ContextJson); //If there is not customer behind one of the wallets then this is not P2P transfer if (sourceWalletOwner != null && targetWalletOwner != null) { await _p2PTransferPublisher.PublishAsync(new P2PTransferDetectedEvent { TransactionHash = transactionHash, SenderCustomerId = sourceWalletOwner.OwnerId, ReceiverCustomerId = targetWalletOwner.OwnerId, Amount = amount, Timestamp = observedAt, RequestId = context.RequestId }); } await _transferDetectedPublisher.PublishAsync(new TransferDetectedEvent { TransactionHash = transactionHash, SenderCustomerId = sourceWalletOwner?.OwnerId, ReceiverCustomerId = targetWalletOwner?.OwnerId, Amount = amount, Timestamp = observedAt, RequestId = context.RequestId }); }
public async Task HandleAsync(string transactionHash, Money18 amount, string walletAddress, DateTime observedAt) { if (string.IsNullOrEmpty(transactionHash)) { _log.Warning("Mint event with empty hash received"); return; } if (amount <= 0) { _log.Warning("Invalid amount for handling MintEvent", context: new { amount, hash = transactionHash }); return; } var walletOwner = await _walletOwnersRepository.GetByWalletAddressAsync(walletAddress); if (walletOwner == null) { _log.Error(message: "Mint event for wallet address which does not exist", context: walletAddress); return; } var operation = await _operationsFetcher.GetByHashAsync(transactionHash); if (operation == null) { var transactionState = await _executorClient.TransactionsApi.GetTransactionStateAsync(transactionHash); if (transactionState.Error != GetTransactionStateError.None) { _log.Error(message: "Already processed operation was not found by hash", context: new { hash = transactionHash, walletOwner, walletAddress }); return; } if (!transactionState.OperationId.HasValue) { _log.Warning("Operation id is empty", context: new { hash = transactionHash, amount, walletAddress }); return; } operation = await _operationsFetcher.GetByIdAsync(transactionState.OperationId.Value); if (operation == null) { _log.Error(message: "Already processed operation was not found by id", context: new { id = transactionState.OperationId.Value, transactionHash, walletOwner, walletAddress }); return; } } await _balanceService.ForceBalanceUpdateAsync(walletOwner.OwnerId, operation.Type, operation.Id); var bonusRewardContext = JsonConvert.DeserializeObject <CustomerBonusRewardContext>(operation.ContextJson); await _bonusRewardDetectedPublisher.PublishAsync(new BonusRewardDetectedEvent { Amount = amount, Timestamp = observedAt, CustomerId = walletOwner.OwnerId, RequestId = bonusRewardContext.RequestId, BonusReason = bonusRewardContext.BonusReason, CampaignId = bonusRewardContext.CampaignId, ConditionId = bonusRewardContext.ConditionId }); }