0

I have a web3.js application which uses truffle and interacts with smart contracts deployed on Ganache. How do I deploy my smart contract on a Test Network and interact with it through my application?

2 Answers 2

0

You first need to install MetaMask and chose the network you're willing to test on . then you need to connect to MetaMask. it will automatically go on the test network you have chosen. read the Metamask documentation and learn how to connect in here

0

Here is how I do it (tested with web3.js v1.2.1):

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

const MIN_GAS_LIMIT = 100000;
const CFG_FILE_NAME = "SomeFile.txt";
const NODE_ADDRESS  = "YourNodeURL";
const PRIVATE_KEY   = "YourPrivateKey";
const ARTIFACTS_DIR = __dirname + "/RelativePathToYourBinAndAbiFolder";

function get() {
    return JSON.parse(fs.readFileSync(CFG_FILE_NAME, {encoding: "utf8"}));
}

function set(record) {
    fs.writeFileSync(CFG_FILE_NAME, JSON.stringify({...get(), ...record}, null, 4));
}

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, gasPrice, transaction, value = 0) {
    while (true) {
        try {
            const options = {
                to      : transaction._parent._address,
                data    : transaction.encodeABI(),
                gas     : Math.max(await transaction.estimateGas({from: account.address, value: value}), MIN_GAS_LIMIT),
                gasPrice: gasPrice ? 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 deploy(web3, account, gasPrice, contractId, contractName, contractArgs) {
    if (get()[contractId] == undefined) {
        const abi = fs.readFileSync(ARTIFACTS_DIR + contractName + ".abi", {encoding: "utf8"});
        const bin = fs.readFileSync(ARTIFACTS_DIR + contractName + ".bin", {encoding: "utf8"});
        const contract = new web3.eth.Contract(JSON.parse(abi));
        const options = {data: "0x" + bin, arguments: contractArgs};
        const transaction = contract.deploy(options);
        const receipt = await send(web3, account, gasPrice, transaction);
        const args = transaction.encodeABI().slice(options.data.length);
        console.log(`${contractId} deployed at ${receipt.contractAddress}`);
        set({[contractId]: {name: contractName, addr: receipt.contractAddress, args: args}});
    }
    return deployed(web3, contractName, get()[contractId].addr);
}

function deployed(web3, contractName, contractAddr) {
    const abi = fs.readFileSync(ARTIFACTS_DIR + contractName + ".abi", {encoding: "utf8"});
    return new web3.eth.Contract(JSON.parse(abi), contractAddr);
}

async function run() {
    const web3 = new Web3(NODE_ADDRESS);

    const gasPrice = await getGasPrice(web3);
    const account  = web3.eth.accounts.privateKeyToAccount(PRIVATE_KEY);
    const web3Func = (func, ...args) => func(web3, account, gasPrice, ...args);

    let phase = 0;
    if (get().phase == undefined)
        set({phase});
    const execute = async (transaction, ...args) => {
        if (get().phase == phase++) {
            await web3Func(send, transaction, ...args);
            console.log(`phase ${phase} executed`);
            set({phase});
        }
    };

    const contract1 = await web3Func(deploy, "contract1", "MyContract1", [arg1, arg2, arg3]);
    const contract2 = await web3Func(deploy, "contract2", "MyContract1", [arg4, arg5, arg6]);
    const contract3 = await web3Func(deploy, "contract3", "MyContract2", []);

    await execute(contract1.methods.setSomeValue(123));
    await execute(contract2.methods.setSomeValue(456));
    await execute(contract3.methods.doSomeStuff(true));

    if (web3.currentProvider.constructor.name == "WebsocketProvider")
        web3.currentProvider.connection.close();
}

run();

Note that you need to define the following variables at the beginning of your script:

const MIN_GAS_LIMIT = 100000;
const CFG_FILE_NAME = "SomeFile.txt";
const NODE_ADDRESS  = "YourNodeURL";
const PRIVATE_KEY   = "YourPrivateKey";
const ARTIFACTS_DIR = __dirname + "/RelativePathToYourBinAndAbiFolder";

Alternatively, you can pass them to the script via command-line arguments, and read them via:

const MIN_GAS_LIMIT = process.argv[2];
const CFG_FILE_NAME = process.argv[3];
const NODE_ADDRESS  = process.argv[4];
const PRIVATE_KEY   = process.argv[5];
const ARTIFACTS_DIR = process.argv[6];

Then, in the main function (run) at the bottom of the script, you should implement your initialization scenario instead of my coding example:

    const contract1 = await web3Func(deploy, "contract1", "MyContract1", [arg1, arg2, arg3]);
    const contract2 = await web3Func(deploy, "contract2", "MyContract1", [arg4, arg5, arg6]);
    const contract3 = await web3Func(deploy, "contract3", "MyContract2", []);

    await execute(contract1.methods.setSomeValue(123));
    await execute(contract2.methods.setSomeValue(456));
    await execute(contract3.methods.doSomeStuff(true));

This script is designed to resume from the last point of execution (i.e., if previously aborted).

1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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