public async Task TestCashoutTokens()
        {
            var colorCoin = await _coinRepository.GetCoinByAddress(_tokenAdapterAddress);

            await CashinTokens(_externalTokenAddress, _clientTokenTransferAddress, new BigInteger(100), _tokenAdapterAddress, _clientA);

            var transferUser = await _transferContractService.GetTransferAddressUser(colorCoin.AdapterAddress, _clientTokenTransferAddress);

            var oldBalance = await _transferContractService.GetBalanceOnAdapter(colorCoin.AdapterAddress, _clientA);

            Assert.AreEqual(_clientA.ToLower(), transferUser);

            var guid         = Guid.NewGuid();
            var externalSign = await _exchangeService.GetSign(guid, _tokenAdapterAddress, _clientA, _clientA, oldBalance);

            var cashout = await _exchangeService.CashOut(guid, colorCoin.AdapterAddress, _clientA, _clientA,
                                                         oldBalance, externalSign);

            while (await _transactionService.GetTransactionReceipt(cashout) == null)
            {
                await Task.Delay(100);
            }

            Assert.IsTrue(await _transactionService.IsTransactionExecuted(cashout, Constants.GasForCoinTransaction));
            var currentBalance = await _transferContractService.GetBalanceOnAdapter(colorCoin.AdapterAddress, _clientA);

            var newBalance = await _ercService.GetBalanceForExternalTokenAsync(_clientA, _externalTokenAddress);

            Assert.IsTrue(oldBalance <= newBalance);
            Assert.IsTrue(currentBalance == 0);
        }
Ejemplo n.º 2
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);
        }