0

I would like to read the csv text file and make a transaction via web3.js like what I did with web3.py

Here is my python code

#!/usr/bin/python3.7
import os
import time
import pandas as pd

from pathlib import Path

from web3 import Web3, IPCProvider
from pathlib import Path

ipc_file = os.path.join('IPC')

sending_account = "ACC"
private_key = 'PRI'

web3 = Web3(IPCProvider(ipc_file))

addresses_df = pd.read_csv(
    'test.txt',
    header=None, names=['id', 'address', 'balance']
)

nonce_count = web3.eth.getTransactionCount(sending_account)

for row in addresses_df.itertuples():
    nonce_cnt = int(nonce_count)
    transaction = {
        'to': row.address,
        'value': int(row.balance),
        'gas': 21000,
        'gasPrice': 1000000000,
        'nonce': nonce_cnt
    }
    signed = web3.eth.account.signTransaction(transaction, private_key)
    TxHash = web3.eth.sendRawTransaction(signed.rawTransaction)
    print("Address:",row.address,"Nonce:",nonce_cnt,"TX:",TxHash.hex())
    nonce_count += 1
    time.sleep(1)

and here is my csv file

0,0x843fd22c88d59e57ae1856a871a5d95e95b0a656,52500000000000

Thanks in advance.

2
  • What does the first element in the row stand for? – goodvibration Feb 15 '20 at 20:48
  • Just a random number from csv, nothing special – Chance Han Feb 15 '20 at 21:07
1

Try this (tested with web3.js v1.2.1):

const fs   = require("fs");
const os   = require("os");
const Web3 = require("web3");

const NODE_ADDRESS = "YourNodeAddress";
const PRIVATE_KEY  = "0x4c0883a69102937d6231471b5dbb6204fe5129617082792ae468d01a3f362318";
const INPUT_FILE   = "test.txt";

async function scan(message) {
    process.stdout.write(message);
    return await new Promise(function(resolve, reject) {
        process.stdin.resume();
        process.stdin.once("data", function(data) {
            process.stdin.pause();
            resolve(data.toString().trim());
        });
    });
}

async function getGasPrice(web3) {
    while (true) {
        const nodeGasPrice = await web3.eth.getGasPrice();
        const userGasPrice = await scan(`Enter gas-price or leave empty to use ${nodeGasPrice}: `);
        if (/^\d+$/.test(userGasPrice))
            return userGasPrice;
        if (userGasPrice == "")
            return nodeGasPrice;
        console.log("Illegal gas-price");
    }
}

async function getTransactionReceipt(web3) {
    while (true) {
        const hash = await scan("Enter transaction-hash or leave empty to retry: ");
        if (/^0x([0-9A-Fa-f]{64})$/.test(hash)) {
            const receipt = await web3.eth.getTransactionReceipt(hash);
            if (receipt)
                return receipt;
            console.log("Invalid transaction-hash");
        }
        else if (hash) {
            console.log("Illegal transaction-hash");
        }
        else {
            return null;
        }
    }
}

async function send(web3, to, value, gasPrice, privateKey) {
    while (true) {
        try {
            const options = {
                to      : to,
                value   : value,
                gasPrice: gasPrice,
                gas     : 21000
            };
            const signed  = await web3.eth.accounts.signTransaction(options, privateKey);
            const receipt = await web3.eth.sendSignedTransaction(signed.rawTransaction);
            return receipt;
        }
        catch (error) {
            console.log(error.message);
            const receipt = await getTransactionReceipt(web3);
            if (receipt)
                return receipt;
        }
    }
}

async function run() {
    const web3 = new Web3(NODE_ADDRESS);
    const gasPrice = await getGasPrice(web3);
    const lines = fs.readFileSync(INPUT_FILE_NAME, {encoding: "utf8"}).split(os.EOL);
    for (const line of lines) {
        const [id, to, value] = line.split(",");
        const receipt = await send(web3, to, value, gasPrice, PRIVATE_KEY);
        console.log(`transaction ${id} executed at block #${receipt.blockNumber}`);
    }
}

run();

If you have a new-line character at the end of the last line in the input file, then change this:

const lines = fs.readFileSync(INPUT_FILE_NAME, {encoding: "utf8"}).split(os.EOL);

To this:

const lines = fs.readFileSync(INPUT_FILE_NAME, {encoding: "utf8"}).split(os.EOL).slice(0, -1);
4
  • You forgot nonce_count and async function getGasPrice(web3) {, async function getTransactionReceipt(web3) { is unnessary – Chance Han Feb 15 '20 at 21:18
  • @ChanceHan: 1. I did not forget nonce, it is not needed (handled by the node). 2. Functions getGasPrice and getTransactionReceipt are there to help you managing the whole thing; from my personal experience, when it comes to a large batch of transactions, they prove quite useful. 3. I just gave you a full porting solution to you code; a bit a gratitude wouldn't hurt in this case (in fact, it would be quite appropriate)! – goodvibration Feb 15 '20 at 21:30
  • 1. counting nonce for transactions are appropriate manner in case you had a transaction on account, I've tested the script and it says low nonce from node. 2. You can hardcode the gasprice, I prefer more simple code for maintainence. 3. Why do I need gettransactionreceipt? I only need signtransaction – Chance Han Feb 15 '20 at 21:40
  • @ChanceHan: Sometimes the node doesn't return a response within 720 seconds, and function sendSignedTransaction times out (throwing an exception). In this case, you don't know for sure whether the transaction has passed or not (in fact, neither has yet happened). For such cases, function getTransactionReceipt allows you (the user) to manually find the transaction hash (for example, on Etherscan), and provide it to the program. – goodvibration Feb 15 '20 at 21:49
0

Here is my fixed code

const fs   = require("fs");
const os   = require("os");
const Web3 = require("web3");
const net  = require('net');

const NODE_ADDRESS = "IPC";
const SEND_ACCOUNT = "ACC";
const PRIVATE_KEY  = "PRI";
const INPUT_FILE   = "CSV";

async function run() {
    const web3      = new Web3(NODE_ADDRESS, net);
    let nonce_count = await web3.eth.getTransactionCount(SEND_ACCOUNT);

    const lines     = fs.readFileSync(INPUT_FILE, {encoding: "utf8"}).split(os.EOL);
    for (const line of lines) {
        const [id, address, balance] = line.split(",");
        const options = {
            to       : address,
            value    : balance,
            gasPrice : 1000000000,
            gas      : 21000,
            nonce    : nonce_count
        };
        const signed  = await web3.eth.accounts.signTransaction(options, PRIVATE_KEY);
        const receipt = await web3.eth.sendSignedTransaction(signed.rawTransaction);
        console.log("Address:",address,"Balance:",balance,"Nonce:",nonce_count);
        nonce_count++
    }
}

run();
1
  • TO-DO: Fix sendSignedTransaction, Use batchrequest – Chance Han Feb 15 '20 at 23:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.