Exemplo n.º 1
0
 private async Task UpdateUserTransferWallet(string contractAddress, string erc20TokenAddress, string userAddress)
 {
     await TransferWalletSharedService.UpdateUserTransferWalletAsync(_userTransferWalletRepository, contractAddress,
                                                                     erc20TokenAddress, userAddress, "");
 }
Exemplo n.º 2
0
        /// <param name="depositContractAddress"></param>
        /// <param name="erc20TokenAddress"></param>
        /// <param name="destinationAddress"></param>
        /// <returns>TransactionHash</returns>
        public async Task <string> RecievePaymentFromDepositContract(string depositContractAddress,
                                                                     string erc20TokenAddress, string destinationAddress)
        {
            var depositContract = await _contractRepository.GetByContractAddress(depositContractAddress);

            if (depositContract == null)
            {
                throw new ClientSideException(ExceptionType.WrongParams, $"DepositContractAddress {depositContractAddress} does not exist");
            }

            var userWallet = await TransferWalletSharedService.GetUserTransferWalletAsync(_userTransferWalletRepository,
                                                                                          depositContractAddress, erc20TokenAddress, depositContract.UserAddress);

            if (userWallet != null && !string.IsNullOrEmpty(userWallet.LastBalance))
            {
                throw new ClientSideException(ExceptionType.TransferInProcessing, $"Transfer from {depositContractAddress} was started before wait for it to complete");
            }

            var balance = await _ercInterfaceService.GetBalanceForExternalTokenAsync(depositContractAddress, erc20TokenAddress);

            if (balance == 0)
            {
                throw new ClientSideException(ExceptionType.NotEnoughFunds, $"No tokens detected at deposit address {depositContractAddress}");
            }

            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.LykkePay.LykkePayAddress;
            var estimationResult         = await Erc20SharedService.EstimateDepositTransferAsync(_web3,
                                                                                                 _settings.Erc20DepositContract.Abi,
                                                                                                 transactionSenderAddress,
                                                                                                 depositContractAddress,
                                                                                                 erc20TokenAddress,
                                                                                                 destinationAddress);

            if (!estimationResult)
            {
                throw new ClientSideException(ExceptionType.WrongDestination, $"Can't estimate transfer {depositContractAddress}, {erc20TokenAddress}, {destinationAddress}");
            }

            await _operationsRepository.SaveAsync(new HotWalletOperation()
            {
                Amount        = balance,
                FromAddress   = depositContractAddress,
                OperationId   = guidStr,
                OperationType = HotWalletOperationType.Cashin,
                ToAddress     = destinationAddress,
                TokenAddress  = erc20TokenAddress
            });

            await _transferQueue.PutRawMessageAsync(Newtonsoft.Json.JsonConvert.SerializeObject(message));

            await TransferWalletSharedService.UpdateUserTransferWalletAsync(_userTransferWalletRepository,
                                                                            depositContractAddress, erc20TokenAddress, depositContract.UserAddress, balance.ToString());

            return(guidStr);
        }
        //return whether we have sent to rabbit or not
        private async Task <bool> SendCompleteEvent(string transactionHash, string operationId, bool success, QueueTriggeringContext context, CoinTransactionMessage transaction)
        {
            try
            {
                var operation = await GetOperationAsync(transactionHash, operationId);

                if (operation == null)
                {
                    return(false);
                }

                (BigInteger? amount, string blockHash, ulong blockNumber)transferedInfo = (null, null, 0);
                string amount = operation.Amount.ToString();
                switch (operation.OperationType)
                {
                case HotWalletOperationType.Cashout:
                    break;

                case HotWalletOperationType.Cashin:
                    string userAddress = await _erc20DepositContractService.GetUserAddress(operation.FromAddress);

                    await TransferWalletSharedService.UpdateUserTransferWalletAsync(_userTransferWalletRepository, operation.FromAddress,
                                                                                    operation.TokenAddress, userAddress, "");

                    //There will be nothing to index in failed event
                    if (success)
                    {
                        transferedInfo =
                            await _transactionEventsService.IndexCashinEventsForErc20TransactionHashAsync(
                                transactionHash);

                        if (transferedInfo.amount == null ||
                            transferedInfo.amount == 0)
                        {
                            //Not yet indexed
                            SendMessageToTheQueueEnd(context, transaction, 10000);
                            return(false);
                        }

                        amount = transferedInfo.amount.ToString();
                    }

                    break;

                default:
                    return(false);
                }

                EventType     eventType = success ? EventType.Completed : EventType.Failed;
                TransferEvent @event    = new TransferEvent(operation.OperationId,
                                                            transactionHash,
                                                            amount,
                                                            operation.TokenAddress,
                                                            operation.FromAddress,
                                                            operation.ToAddress,
                                                            transferedInfo.blockHash,
                                                            transferedInfo.blockNumber,
                                                            SenderType.EthereumCore,
                                                            eventType,
                                                            WorkflowType.LykkePay,
                                                            DateTime.UtcNow);

                await _rabbitQueuePublisher.PublshEvent(@event);

                return(true);
            }
            catch (Exception e)
            {
                await _log.WriteErrorAsync(nameof(HotWalletMonitoringTransactionJob), "SendCompletedCoinEvent", $"trHash: {transactionHash}", e, DateTime.UtcNow);

                SendMessageToTheQueueEnd(context, transaction, 100);

                return(false);
            }
        }