public async Task Erc20ServiceUnitTest_WrongSignAndCommitTransaction()
        {
            bool             isExceptionProcessed = false;
            string           from           = TestConstants.PW_ADDRESS;
            Erc20Transaction ethTransaction = new Erc20Transaction()
            {
                FromAddress  = from,
                GasAmount    = 21000,
                GasPrice     = 30000000000,
                ToAddress    = _contractAddress,
                TokenAddress = _contractAddress,
                TokenAmount  = 30000000000
            };

            string transactionHex = await _erc20Service.GetTransferTransactionRaw(ethTransaction);

            string wrongKey          = _privateKey.Remove(2, 1).Insert(2, "3");
            string signedTransaction = SignRawTransaction(transactionHex, wrongKey);

            try
            {
                string transactionHash = await _erc20Service.SubmitSignedTransaction(from, signedTransaction);
            }
            catch (ClientSideException exc) when(exc.ExceptionType == ExceptionType.WrongSign)
            {
                isExceptionProcessed = true;
            }

            Assert.IsTrue(isExceptionProcessed);
        }
        public async Task Erc20ServiceUnitTest_SignAndCommitTransaction()
        {
            string           from           = TestConstants.PW_ADDRESS;
            Erc20Transaction ethTransaction = new Erc20Transaction()
            {
                FromAddress  = from,
                GasAmount    = 21000,
                GasPrice     = 30000000000,
                ToAddress    = _contractAddress,
                TokenAddress = _contractAddress,
                TokenAmount  = 30000000000
            };

            string transactionHex = await _erc20Service.GetTransferTransactionRaw(ethTransaction);

            string signedTransaction = SignRawTransaction(transactionHex, _privateKey);
            string transactionHash   = await _erc20Service.SubmitSignedTransaction(from, signedTransaction);

            Nethereum.Signer.Transaction transaction = new Nethereum.Signer.Transaction(signedTransaction.HexToByteArray());

            _client.Verify(x => x.SendRequestAsync <string>(It.IsAny <Nethereum.JsonRpc.Client.RpcRequest>(), null), Times.Once);
            Assert.AreEqual(from, transaction.Key.GetPublicAddress());
            Assert.AreEqual(_nonceCalc._nonceStorage[from].Value, new HexBigInteger(transaction.Nonce.ToHex()));
            Assert.AreEqual(ethTransaction.GasAmount, new HexBigInteger(transaction.GasLimit.ToHex()));
            Assert.AreEqual(new HexBigInteger(0).Value, new HexBigInteger(transaction.Value.ToHex()));
            Assert.AreEqual(ethTransaction.GasPrice, new HexBigInteger(transaction.GasPrice.ToHex()));
            Assert.AreEqual(ethTransaction.ToAddress.ToLower(), transaction.ReceiveAddress.ToHex().EnsureHexPrefix());
        }
        public async Task <IActionResult> GetTransaction([FromBody] PrivateWalletErc20Transaction ercTransaction)
        {
            if (!ModelState.IsValid)
            {
                throw new ClientSideException(ExceptionType.WrongParams, JsonConvert.SerializeObject(ModelState.Errors()));
            }

            string serialized = JsonConvert.SerializeObject(ercTransaction);
            await _log.WriteInfoAsync("PrivateWalletController", "GetTransaction", serialized, "Get transaction for signing", DateTime.UtcNow);

            Erc20Transaction transaction = new Erc20Transaction()
            {
                TokenAddress = ercTransaction.TokenAddress,
                TokenAmount  = BigInteger.Parse(ercTransaction.TokenAmount),
                FromAddress  = ercTransaction.FromAddress,
                GasAmount    = BigInteger.Parse(ercTransaction.GasAmount),
                GasPrice     = BigInteger.Parse(ercTransaction.GasPrice),
                ToAddress    = ercTransaction.ToAddress,
                Value        = BigInteger.Parse(ercTransaction.Value),
            };
            await _erc20Service.ValidateInput(transaction);

            string transactionHex = await _erc20Service.GetTransferTransactionRaw(transaction);

            await _log.WriteInfoAsync("PrivateWalletController", "GetTransaction", $"{serialized} + TransactionHex:{transactionHex}",
                                      "Recieved transaction for signing", DateTime.UtcNow);

            return(Ok(new EthTransactionRaw()
            {
                FromAddress = ercTransaction.FromAddress,
                TransactionHex = transactionHex
            }));
        }
        public async Task <string> GetTransferTransactionRaw(Erc20Transaction erc20Transaction, bool useTxPool = false)
        {
            Contract   contract            = GetContract(erc20Transaction.TokenAddress);
            Function   transferFunction    = contract.GetFunction("transfer");
            string     functionDataEncoded = transferFunction.GetData(erc20Transaction.ToAddress, erc20Transaction.TokenAmount);
            BigInteger nonce = await _nonceCalculator.GetNonceAsync(erc20Transaction.FromAddress, useTxPool);

            var transaction = CreateTransactionInput(functionDataEncoded, erc20Transaction.TokenAddress, erc20Transaction.FromAddress,
                                                     erc20Transaction.GasAmount, erc20Transaction.GasPrice, nonce, 0);
            string raw = transaction.GetRLPEncoded().ToHex();

            return(raw);
        }
        public async Task PrivateWalletServiceTest_TestBroadcastingMultiple()
        {
            string           fromAddress = "0x46Ea3e8d85A06cBBd8c6a491a09409f5B59BEa28";
            Erc20Transaction transaction = new Erc20Transaction()
            {
                FromAddress  = fromAddress,
                GasAmount    = 200000,
                GasPrice     = 30000000000,
                ToAddress    = "0xaA4981d084120AEf4BbaEeCB9abdBc7D180C7EdB",
                TokenAddress = "0xce2ef46ecc168226f33b6f6b8a56e90450d0d2c0",
                TokenAmount  = 10
            };

            string trRaw = await _erc20Service.GetTransferTransactionRaw(transaction);

            string signedRawTr = SignRawTransaction(trRaw, _privateKey);
            string trHash1     = await _erc20Service.SubmitSignedTransaction(fromAddress, signedRawTr);
        }
        public async Task Erc20ServiceUnitTest_TestGetTransaction()
        {
            string           from           = TestConstants.PW_ADDRESS;
            Erc20Transaction ethTransaction = new Erc20Transaction()
            {
                FromAddress  = from,
                GasAmount    = 21000,
                GasPrice     = 30000000000,
                ToAddress    = _contractAddress,
                TokenAddress = _contractAddress,
                TokenAmount  = 30000000000
            };

            string transactionHex = await _erc20Service.GetTransferTransactionRaw(ethTransaction);

            Nethereum.Signer.Transaction transaction = new Nethereum.Signer.Transaction(transactionHex.HexToByteArray());

            Assert.AreEqual(_nonceCalc._nonceStorage[from].Value, new HexBigInteger(transaction.Nonce.ToHex()));
            Assert.AreEqual(ethTransaction.GasAmount, new HexBigInteger(transaction.GasLimit.ToHex()));
            Assert.AreEqual(new HexBigInteger(0).Value, new HexBigInteger(transaction.Value.ToHex()));
            Assert.AreEqual(ethTransaction.GasPrice, new HexBigInteger(transaction.GasPrice.ToHex()));
            Assert.AreEqual(ethTransaction.ToAddress.ToLower(), transaction.ReceiveAddress.ToHex().EnsureHexPrefix());
            Assert.IsNotNull(transaction.Data.ToHex().EnsureHexPrefix());
        }
Example #7
0
        public void Sync(BigInteger fromBlock, BigInteger toBlock)
        {
            Console.WriteLine($"Getting transactions from block {fromBlock} to {toBlock}");

            bool isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
            bool isLinux   = RuntimeInformation.IsOSPlatform(OSPlatform.Linux);

            string python3 = "python";

            if (isLinux)
            {
                python3 = "python3";
            }

            // Run etl to extract data
            System.Diagnostics.Process          process   = new System.Diagnostics.Process();
            System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();

            // Create command
            string dir = Directory.GetCurrentDirectory();

            if (dir.IndexOf("EtherChain") > 0)
            {
                dir = dir.Substring(0, dir.IndexOf("EtherChain") + 10);
            }
            dir += "/deps/ethereum-etl";
            startInfo.WorkingDirectory = dir;
            string cmd = "";

            if (_blockChain == "ETH")
            {
                cmd =
                    $"{python3} ethereumetl.py export_blocks_and_transactions --start-block {fromBlock} --end-block {toBlock} --provider-uri https://mainnet.infura.io --transactions-output tx.csv";
            }
            else if (_blockChain == "ERC20")
            {
                cmd =
                    $"{python3} ethereumetl.py export_token_transfers --start-block {fromBlock} --end-block {toBlock} --provider-uri wss://mainnet.infura.io/ws --output erc20.csv -w 1";
            }
            if (_blockChain == "ETC")
            {
                cmd =
                    $"{python3} ethereumetl.py export_blocks_and_transactions --start-block {fromBlock} --end-block {toBlock} --provider-uri https://ethereumclassic.network --transactions-output etc.csv";
            }

            if (isWindows)
            {
                startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
                startInfo.FileName    = "cmd.exe";
                startInfo.Arguments   = $"/C {cmd}";
            }
            else if (isLinux)
            {
                startInfo.FileName        = "/bin/bash";
                startInfo.Arguments       = $"-c \"{cmd}\"";
                startInfo.UseShellExecute = false;
                startInfo.CreateNoWindow  = true;
            }

            process.StartInfo = startInfo;
            process.Start();
            process.WaitForExit();

            if (_blockChain == "ETH" && !File.Exists(dir + "/tx.csv"))
            {
                Console.WriteLine("ERROR: tx.csv file not created.");
                Thread.Sleep(1000);
                return;
            }

            if (_blockChain == "ETC" && !File.Exists(dir + "/etc.csv"))
            {
                Console.WriteLine("ERROR: etc.csv file not created.");
                Thread.Sleep(1000);
                return;
            }

            if (_blockChain == "ERC20" && !File.Exists(dir + "/erc20.csv"))
            {
                Console.WriteLine("ERROR: erc20.csv file not created.");
                Thread.Sleep(1000);
                return;
            }

            // Open the tx.csv file and extract it.
            string filename = "tx.csv";

            if (_blockChain == "ETC")
            {
                filename = "etc.csv";
            }
            else if (_blockChain == "ERC20")
            {
                filename = "erc20.csv";
            }
            string[] lines = File.ReadAllLines(dir + "/" + filename);
            File.Delete(dir + "/" + filename);
            int        c       = 2;
            Block      block   = new Block();
            BigInteger blockNo = 0;

            while (c < lines.Length)
            {
                var data = lines[c].Split(',');
                if (_blockChain == "ETH" || _blockChain == "ETC")
                {
                    /*
                     * 0 hash hex_string
                     * 1 nonce bigint
                     * 2 block_hash hex_string
                     * 3 block_number bigint
                     * 4 transaction_index bigint
                     * 5 from_address address
                     * 6 to_address address
                     * 7 value numeric
                     * 8 gas bigint
                     * 9 gas_price bigint
                     * 10 input hex_string
                     */
                    Transaction tr = new Transaction
                    {
                        Amount      = BigInteger.Parse(data[7]),
                        Block       = BigInteger.Parse(data[3]),
                        FromAddress = data[5],
                        Gas         = BigInteger.Parse(data[8]),
                        GasPrice    = BigInteger.Parse(data[9]),
                        Hash        = data[0],
                        ToAddress   = data[6],
                        Nonce       = BigInteger.Parse(data[1])
                    };

                    // Check if we need to create a new block
                    if (string.IsNullOrEmpty(block.Hash))
                    {
                        block.Hash = data[2];
                        blockNo    = tr.Block;
                    }
                    else if (blockNo != tr.Block)
                    {
                        _db.AddBlock(blockNo, block, _blockChain);
                        block   = new Block();
                        blockNo = tr.Block;
                    }

                    _db.AddTransaction(tr, _blockChain, ref block);
                }
                else if (_blockChain == "ERC20")
                {
                    /*
                     * 0 token_address	    address
                     * 1 from_address	    address
                     * 2 to_address	        address
                     * 3 value	            numeric
                     * 4 transaction_hash	hex_string
                     * 5 log_index	        bigint
                     * 6 block_number	    bigint
                     */
                    var tr = new Erc20Transaction
                    {
                        Amount      = BigInteger.Parse(data[3]),
                        Block       = BigInteger.Parse(data[6]),
                        FromAddress = data[1],
                        ToAddress   = data[2],
                        Hash        = data[4],
                        LogIndex    = BigInteger.Parse(data[5])
                    };

                    // Check if we need to create a new block
                    if (string.IsNullOrEmpty(block.Hash))
                    {
                        Web3 web3 = getWeb3();
                        block.Hash = web3.Eth.Blocks.GetBlockWithTransactionsHashesByNumber.SendRequestAsync(
                            new HexBigInteger(tr.Block)).Result.BlockHash;
                        blockNo = tr.Block;
                    }
                    else if (blockNo != tr.Block)
                    {
                        _db.AddBlock(blockNo, block, _blockChain);
                        block   = new Block();
                        blockNo = tr.Block;
                    }

                    _db.AddTransaction(tr, data[0], ref block);
                }

                c += 2;
            }
            _db.AddBlock(blockNo, block, _blockChain);

            // Update last synced block
            _lastSyncedBlock = toBlock;
            _db.Put("lastblock", _lastSyncedBlock.ToString(), _blockChain);

            Console.WriteLine($"{_blockChain}: Done getting transactions from block {fromBlock} to {toBlock}");
        }
        public async Task ValidateInput(Erc20Transaction transaction)
        {
            await _transactionValidationService.ValidateAddressBalanceAsync(transaction.FromAddress, transaction.Value, transaction.GasAmount, transaction.GasPrice);

            await ValidateTokenAddressBalanceAsync(transaction.FromAddress, transaction.TokenAddress, transaction.TokenAmount);
        }