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); }
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); }