Exemplo n.º 1
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}");
        }