0

I'm trying to get my JS-code to call a smart contract on Ethereum (kovan testnet) that will write something on the blockchain and therefore needs ether (actually gas). I called a view function which worked fine but I don't know how to get my address and private key into the script so that my function call will be executed by using ether from my address.

var mqtt = require('mqtt');
var client = mqtt.connect('mqtt://localhost:1234');
var topic = 'test123';
const Web3 = require('web3');
const web3 = new Web3(new Web3.providers.HttpProvider("https://kovan.infura.io/v3/---address---"));
var contract;
var address = "0x---address";
var abi = ---abi---;

contract = new web3.eth.Contract(abi, address);

client.on('message', (topic, message)=>{
    message = message.toString()
    console.log("The following data was sent: " + message);
    if (message == '5202'){
        contract.methods.viewNewestComment().call().then(console.log); // this is the function that views only and which works just fine
        contract.methods.addCommentToNewest("hello").call().then(console.log);//this is function that writes on the blockchain
    } else {
        console.log('Number not defined!');
    }
});

client.on('connect', ()=>{
    client.subscribe(topic)
});

So what my code does it takes an MQTT signal and if it is '5202' the code should be executed. Is my problem that I enter with infura and I can't pay with infura? How do I link my address with test ether on it to my JS-code?

I know this question seems pretty basic but I searched many sites and many questions on stackexchange but I can't find a solution. I would love to hear your solution! :)

EDIT with suggestion of goodvibration:

const Web3 = require('web3');
var Tx = require('ethereumjs-tx')
const web3 = new Web3(new Web3.providers.HttpProvider("https://kovan.infura.io/v3/---XXX---"));
var contract;
var address = "---XXX---";
var abi = [---XXX---];



const account = "---XXX---";
const privateKey = process.env.PRIVATE_KEY;
const privateKey2 = "---XXX---";
var comment = "test1234";

contract = new web3.eth.Contract(abi, address);
contract.methods.viewNewestComment().call().then(console.log);

async function addCommentToNewest(web3, privateKey2, comment) {
    const account = web3.eth.accounts.privateKeyToAccount(privateKey2);
    const receipt = await send(web3, account, contract.methods.addCommentToNewest(comment));
    console.log(JSON.stringify(receipt, null, 4));
}

addCommentToNewest()

edit2: I added my smart contract that I deployed on remix, so it may help to understand what I do with my "addCommentToNewest"

pragma solidity ^0.5.12;

contract NewContract {

    struct Location {
        string JSON;
        uint time;
        string comment;
    }

    Location[] locations;

    function createLocation(string memory _json) public {
        locations.push(Location(_json, now, 'no comment'));
    }

    function addComment(string memory _comment, uint _id) public {
        locations[_id].comment = _comment;
    }

    function addCommentToNewest(string memory _comment) public {
        uint _id = locations.length - 1;
        locations[_id].comment = _comment;
    }

    function viewLocation(uint _id) public view returns(string memory) {
        string memory result = locations[_id].JSON;
        return result;
    }

    function viewTimestamp(uint _id) public view returns(uint) {
        uint result = locations[_id].time;
        return result;
    }

    function viewComment(uint _id) public view returns(string memory) {
        string memory result = locations[_id].comment;
        return result;
    }

    function viewEverything(uint _id) public view returns(string memory, uint, string memory) {
        string memory result1 = locations[_id].JSON;
        uint result2 = locations[_id].time;
        string memory result3 = locations[_id].comment;
        return (result1, result2, result3);
    }

    function viewNewestLocation() public view returns(string memory) {
        uint _id = locations.length - 1;
        string memory result = locations[_id].JSON;
        return result;
    } 

    function viewNewestTimestamp() public view returns(uint) {
        uint _id = locations.length - 1;
        uint result = locations[_id].time;
        return result;
    }

    function viewNewestComment() public view returns(string memory) {
        uint _id = locations.length - 1;
        string memory result = locations[_id].comment;
        return result;
    }

    function viewNewestEverything() public view returns(string memory, uint, string memory) {
        uint _id = locations.length - 1;
        string memory result1 = locations[_id].JSON;
        uint result2 = locations[_id].time;
        string memory result3 = locations[_id].comment;
        return (result1, result2, result3);
    }   
}
0

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

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, account, transaction, value = 0) {
    while (true) {
        try {
            const options = {
                to      : transaction._parent._address,
                data    : transaction.encodeABI(),
                gas     : await transaction.estimateGas({from: account.address}),
                gasPrice: await getGasPrice(web3),
                value   : value,
            };
            const signed  = await web3.eth.accounts.signTransaction(options, account.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 addCommentToNewest(web3, privateKey, comment) {
    const account = web3.eth.accounts.privateKeyToAccount(privateKey);
    const receipt = await send(web3, account, contract.methods.addCommentToNewest(comment));
    console.log(JSON.stringify(receipt, null, 4));
}
| improve this answer | |
  • thank you so much for taking your time to answer :). Unfortunately I am a little lost because I'm not sure how to implement your code into my js.file and where I have to enter my account address and private key. (I started coding two months ago, so I would absolutely love to hear an "beginner" friendly approach) – Mr. 124 Mar 21 at 15:48
  • @user13027703: You need to call addCommentToNewest(web3, YOUR_PRIVATE_KEY, comment). – goodvibration Mar 21 at 15:55
  • This will return a Promise object which you will need to resolve. – goodvibration Mar 21 at 16:00
  • For example: const promise = addCommentToNewest(...);. – goodvibration Mar 21 at 16:00
  • And then: const receipt = await promise; (from inside an async function). – goodvibration Mar 21 at 16:01

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.