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);
        }
        private async Task StartProcessing(IPendingOperation operation)
        {
            await CreateOperation(operation);

            await _queue.PutRawMessageAsync(JsonConvert.SerializeObject(new OperationHashMatchMessage()
            {
                OperationId = operation.OperationId
            }));

            await _eventTraceRepository.InsertAsync(new EventTrace()
            {
                Note        = $"First appearance for the operation. Put it in{Constants.PendingOperationsQueue}",
                OperationId = operation.OperationId, TraceDate = DateTime.UtcNow
            });
        }
Example #3
0
        public async Task ProcessOperation(OperationHashMatchMessage opMessage, QueueTriggeringContext context,
                                           Func <Guid, string, string, string, BigInteger, string, Task <string> > transferDelegate)
        {
            try
            {
                var operation = await _pendingOperationService.GetOperationAsync(opMessage.OperationId);

                if (operation == null)
                {
                    await _coinEventResubmittQueue.PutRawMessageAsync(JsonConvert.SerializeObject(opMessage));

                    return;
                }

                if (_hotWalletAddress == operation.FromAddress.ToLower() &&
                    opMessage.DequeueCount == 0)
                {
                    opMessage.DequeueCount++;
                    context.MoveMessageToEnd(opMessage.ToJson());
                    context.SetCountQueueBasedDelay(_settings.MaxQueueDelay, 200);

                    return;
                }

                var guid   = Guid.Parse(operation.OperationId);
                var amount = BigInteger.Parse(operation.Amount);

                BigInteger    resultAmount;
                string        transactionHash = null;
                CoinEventType?eventType       = null;
                BigInteger    currentBalance  = await _transferContractService.GetBalanceOnAdapter(
                    operation.CoinAdapterAddress,
                    operation.FromAddress,
                    checkInPendingBlock : true);

                switch (operation.OperationType)
                {
                case OperationTypes.Cashout:
                    eventType    = CoinEventType.CashoutStarted;
                    resultAmount = amount;
                    if (!CheckBalance(currentBalance, resultAmount))
                    {
                        break;
                    }
                    transactionHash = await _exchangeContractService.CashOut(guid,
                                                                             operation.CoinAdapterAddress,
                                                                             operation.FromAddress,
                                                                             operation.ToAddress, amount, operation.SignFrom);

                    break;

                case OperationTypes.Transfer:
                    eventType    = CoinEventType.TransferStarted;
                    resultAmount = amount;
                    if (!CheckBalance(currentBalance, resultAmount))
                    {
                        break;
                    }
                    transactionHash = await transferDelegate(guid, operation.CoinAdapterAddress,
                                                             operation.FromAddress,
                                                             operation.ToAddress, amount, operation.SignFrom);

                    break;

                case OperationTypes.TransferWithChange:
                    eventType = CoinEventType.TransferStarted;
                    BigInteger change = BigInteger.Parse(operation.Change);
                    resultAmount = amount - change;
                    if (!CheckBalance(currentBalance, resultAmount))
                    {
                        break;
                    }
                    transactionHash = await _exchangeContractService.TransferWithChange(guid, operation.CoinAdapterAddress,
                                                                                        operation.FromAddress,
                                                                                        operation.ToAddress, amount, operation.SignFrom, change, operation.SignTo);

                    break;

                default:
                    await _log.WriteWarningAsync("MonitoringOperationJob", "Execute", $"Can't find right operation type for {opMessage.OperationId}", "");

                    break;
                }

                if (transactionHash != null && eventType != null)
                {
                    await _pendingOperationService.MatchHashToOpId(transactionHash, operation.OperationId);

                    await _coinEventService.PublishEvent(new CoinEvent(operation.OperationId.ToString(), transactionHash, operation.FromAddress, operation.ToAddress, resultAmount.ToString(), eventType.Value, operation.CoinAdapterAddress));

                    await _eventTraceRepository.InsertAsync(new EventTrace()
                    {
                        Note        = $"Operation Processed. Put it in the {Constants.TransactionMonitoringQueue}. With hash {transactionHash}",
                        OperationId = operation.OperationId,
                        TraceDate   = DateTime.UtcNow
                    });

                    return;
                }
            }
            catch (ClientSideException clientSideExc) when(clientSideExc.ExceptionType == ExceptionType.OperationWithIdAlreadyExists)
            {
                await _coinEventResubmittQueue.PutRawMessageAsync(JsonConvert.SerializeObject(opMessage));

                return;
            }
            catch (RpcClientException exc)
            {
                await _log.WriteErrorAsync("MonitoringOperationJob", "Execute", "RpcException", exc);

                opMessage.LastError = exc.Message;
                opMessage.DequeueCount++;
                if (opMessage.DequeueCount < 6)
                {
                    context.MoveMessageToEnd(opMessage.ToJson());
                    context.SetCountQueueBasedDelay(_settings.MaxQueueDelay, 200);
                }
                else
                {
                    context.MoveMessageToPoison(opMessage.ToJson());
                }

                return;
            }
            catch (Exception ex)
            {
                if (ex.Message != opMessage.LastError)
                {
                    await _log.WriteWarningAsync("MonitoringOperationJob", "Execute", $"OperationId: [{opMessage.OperationId}]", "");
                }

                opMessage.LastError = ex.Message;
                opMessage.DequeueCount++;
                context.MoveMessageToPoison(opMessage.ToJson());

                await _log.WriteErrorAsync("MonitoringOperationJob", "Execute", "", ex);

                return;
            }

            opMessage.DequeueCount++;
            context.MoveMessageToEnd(opMessage.ToJson());
            context.SetCountQueueBasedDelay(_settings.MaxQueueDelay, 200);
        }
Example #4
0
        public async Task TransferToCoinContract(TransferContractTransaction contractTransferTr)
        {
            try
            {
                var contractEntity = await _transferContractRepository.GetAsync(contractTransferTr.ContractAddress);

                var balance = await _transferContractService.GetBalance(contractTransferTr.ContractAddress);

                if (balance == 0)
                {
                    await UpdateUserTransferWallet(contractTransferTr);

                    await _logger.WriteInfoAsync("TransferContractTransactionService", "TransferToCoinContract", "",
                                                 $"Can't cashin: there is no funds on the transfer contract {contractTransferTr.ContractAddress}", DateTime.UtcNow);

                    return;
                }

                var userAddress = await _transferContractService.GetUserAddressForTransferContract(contractTransferTr.ContractAddress);

                if (string.IsNullOrEmpty(userAddress) || userAddress == Constants.EmptyEthereumAddress)
                {
                    await UpdateUserTransferWallet(contractTransferTr);

                    await _logger.WriteInfoAsync("TransferContractTransactionService", "TransferToCoinContract", "",
                                                 $"Can't cashin: there is no user assigned to the transfer contract {contractTransferTr.ContractAddress}", DateTime.UtcNow);

                    return;
                }

                var opId            = $"InternalOperation-{Guid.NewGuid().ToString()}";
                var transactionHash = await _transferContractService.RecievePaymentFromTransferContract(contractEntity.ContractAddress, contractEntity.CoinAdapterAddress);

                await _coinEventService.PublishEvent(new CoinEvent(opId,
                                                                   transactionHash, contractTransferTr.ContractAddress, contractTransferTr.UserAddress,
                                                                   balance.ToString(), CoinEventType.CashinStarted, contractEntity.CoinAdapterAddress));

                await _eventTraceRepository.InsertAsync(new EventTrace()
                {
                    Note        = $"First Cashin appearance {transactionHash} put in {Constants.TransactionMonitoringQueue}",
                    OperationId = opId,
                    TraceDate   = DateTime.UtcNow
                });

                await _userPaymentHistoryRepository.SaveAsync(new UserPaymentHistory()
                {
                    Amount          = balance.ToString(),
                    ToAddress       = contractEntity.ContractAddress,
                    AdapterAddress  = contractEntity.CoinAdapterAddress,
                    CreatedDate     = DateTime.UtcNow,
                    Note            = $"Cashin from transfer contract {contractEntity.ContractAddress}",
                    TransactionHash = transactionHash,
                    UserAddress     = contractTransferTr.UserAddress
                });

                //await UpdateUserTransferWallet(contractTransferTr);
                await _logger.WriteInfoAsync("ContractTransferTransactionService", "TransferToCoinContract", "",
                                             $"Transfered {balance} from transfer contract to \"{contractTransferTr.CoinAdapterAddress}\" by transaction \"{transactionHash}\". Receiver = {contractEntity.UserAddress}");
            }
            catch (Exception e)
            {
                await _logger.WriteErrorAsync("TransferContractTransactionService", "TransferToCoinContract",
                                              $"{contractTransferTr.ContractAddress} - {contractTransferTr.CoinAdapterAddress} - {contractTransferTr.Amount}", e);

                throw;
            }
        }