public async Task Execute(LykkePayErc20TransferMessage transaction, QueueTriggeringContext context) { IHotWalletOperation operation = null; if (string.IsNullOrEmpty(transaction?.OperationId)) { await _logger.WriteWarningAsync(nameof(Erc20DepositTransferStarterJob), "Execute", "", "Empty message skipped"); return; } try { operation = await _operationsRepository.GetAsync(transaction.OperationId); if (operation == null) { await _logger.WriteWarningAsync(nameof(Erc20DepositTransferStarterJob), "Execute", transaction.ToJson(), $"No operation for id {transaction?.OperationId} message skipped"); return; } var transactionSenderAddress = _settings.Airlines.AirlinesAddress; var balance = await _ercInterfaceService.GetPendingBalanceForExternalTokenAsync(operation.FromAddress, operation.TokenAddress); if (balance < operation.Amount) { await _logger.WriteWarningAsync(nameof(Erc20DepositTransferStarterJob), "Execute", transaction.ToJson(), $"Sendig Failed Event: DepositAddress: {operation.FromAddress}, " + $"TokenAddress: {operation.TokenAddress}, " + $"DesiredAmount: {operation.Amount} " + $"CurrentBalance {balance}"); TransferEvent @event = new TransferEvent(transaction.OperationId, "", operation.Amount.ToString(), operation.TokenAddress, operation.FromAddress, operation.ToAddress, "", 0, SenderType.EthereumCore, EventType.NotEnoughFunds, WorkflowType.Airlines, DateTime.UtcNow); await _rabbitQueuePublisher.PublshEvent(@event); return; } var trHash = await Erc223SharedService.StartDepositTransferAsync(_web3, _settings.EthereumCore.Erc223DepositContract.Abi, transactionSenderAddress, operation.FromAddress, operation.TokenAddress, operation.ToAddress, operation.Amount); await _hotWalletTransactionRepository.SaveAsync(new HotWalletCashoutTransaction() { OperationId = transaction.OperationId, TransactionHash = trHash }); var message = new CoinTransactionMessage() { OperationId = transaction.OperationId, TransactionHash = trHash }; //Observe transaction await _transactionMonitoringQueue.PutRawMessageAsync(message.ToJson()); var notificationMessage = new LykkePayErc20TransferNotificationMessage() { OperationId = transaction.OperationId, TransactionHash = trHash, Balance = operation.Amount.ToString() }; await _transactionStartedNotificationQueue.PutRawMessageAsync(notificationMessage.ToJson()); } catch (ClientSideException ex) { if (operation == null) { return; } TransferEvent @event = new TransferEvent(transaction.OperationId, "", operation.Amount.ToString(), operation.TokenAddress, operation.FromAddress, operation.ToAddress, "", 0, SenderType.EthereumCore, EventType.Failed, WorkflowType.Airlines, DateTime.UtcNow); _logger.WriteWarning("Execute", operation.ToJson(), "ClientSideException", ex); await _rabbitQueuePublisher.PublshEvent(@event); } catch (Exception ex) { if (transaction == null) { return; } if (ex.Message != transaction.LastError) { _logger.WriteWarning("Execute", transaction.ToJson(), $"{transaction.OperationId}"); } transaction.LastError = ex.Message; transaction.DequeueCount++; context.MoveMessageToEnd(transaction.ToJson()); context.SetCountQueueBasedDelay(_settings.EthereumCore.MaxQueueDelay, 200); _logger.WriteError("Execute", transaction.ToJson(), ex); } }
/// <param name="depositContractAddress"></param> /// <param name="erc20TokenAddress"></param> /// <param name="destinationAddress"></param> /// <returns>TransactionHash</returns> public async Task <string> RecievePaymentFromDepositContractAsync(string depositContractAddress, string erc20TokenAddress, string destinationAddress, string tokenAmount) { var depositContract = await _contractRepository.GetByContractAddress(depositContractAddress); if (depositContract == null) { throw new ClientSideException(ExceptionType.WrongParams, $"DepositContractAddress {depositContractAddress} does not exist"); } var amount = System.Numerics.BigInteger.Parse(tokenAmount); var balance = await _ercInterfaceService.GetBalanceForExternalTokenAsync(depositContractAddress, erc20TokenAddress); if (balance == 0 || amount > balance) { throw new ClientSideException(ExceptionType.NotEnoughFunds, $"Not enough tokens to proceed with withdrawal detected at deposit address {depositContractAddress}. " + $"Current balance: {balance}"); } var guidStr = Guid.NewGuid().ToString(); var message = new Lykke.Service.EthereumCore.Core.Messages.LykkePay.LykkePayErc20TransferMessage() { OperationId = guidStr }; var existingOperation = await _operationsRepository.GetAsync(guidStr); if (existingOperation != null) { throw new ClientSideException(ExceptionType.EntityAlreadyExists, "Try again later"); } var transactionSenderAddress = _appSettings.Airlines.AirlinesAddress; var estimationResult = await Erc223SharedService.EstimateDepositTransferAsync(_web3, _appSettings.EthereumCore.Erc223DepositContract.Abi, transactionSenderAddress, depositContractAddress, erc20TokenAddress, destinationAddress, amount); if (!estimationResult) { throw new ClientSideException(ExceptionType.WrongDestination, $"Can't estimate transfer {depositContractAddress}, {erc20TokenAddress}, {destinationAddress}"); } await _operationsRepository.SaveAsync(new HotWalletOperation() { Amount = amount, FromAddress = depositContractAddress, OperationId = guidStr, OperationType = HotWalletOperationType.Cashin, ToAddress = destinationAddress, TokenAddress = erc20TokenAddress }); await _transferQueue.PutRawMessageAsync(Newtonsoft.Json.JsonConvert.SerializeObject(message)); return(guidStr); }