Search code examples
ethereummetamask

Call contract methods with web3 from newly created account


I need to call methods from my contract in Ethereum without using MetaMask. I use Infura API and try to call my methods from account, recently created with web3.eth.create() method. This method returns object like this:

{
    address: "0xb8CE9ab6943e0eCED004cG5834Hfn7d",
    privateKey: "0x348ce564d427a3311b6536bbcff9390d69395b06ed6",
    signTransaction: function(tx){...},
    sign: function(data){...},
    encrypt: function(password){...}
} 

I also using infura provider:

 const web3 = new Web3(new Web3.providers.HttpProvider(
    "https://rinkeby.infura.io/5555666777888"
  ))

So, when I try to write smth like that:

contract.methods.contribute().send({
          from: '0xb8CE9ab6943e0eCED004cG5834Hfn7d', // here I paste recently created address
          value: web3.utils.toWei("0.5", "ether")
        });

I have this error:

Error: No "from" address specified in neither the given options, nor the default options.

How it could be no from address if I write it in from option??

P.S. With Metamask my application works fine. But when I logout from MetaMask and try to create new account and use it, I have that issue.


Solution

  • In fact, we can't just send transactions from newly created address. We must sign this transaction with our private key. For example, we can use ethereumjs-tx module for NodeJS.

    const Web3 = require('web3')
    const Tx = require('ethereumjs-tx')
    
    let web3 = new Web3(
      new Web3.providers.HttpProvider(
        "https://ropsten.infura.io/---your api key-----"
      )
    )
    
    const account = '0x46fC1600b1869b3b4F9097185...'; //Your account address
    const privateKey = Buffer.from('6e4702be2aa6b2c96ca22df40a004c2c944...', 'hex');
    const contractAddress = '0x2b622616e3f338266a4becb32...'; // Deployed manually
    const abi = [Your ABI from contract]
    const contract = new web3.eth.Contract(abi, contractAddress, {
      from: account,
      gasLimit: 3000000,
    });
    
    const contractFunction = contract.methods.createCampaign(0.1); // Here you can call your contract functions
    
    const functionAbi = contractFunction.encodeABI();
    
    let estimatedGas;
    let nonce;
    
    console.log("Getting gas estimate");
    
    contractFunction.estimateGas({from: account}).then((gasAmount) => {
      estimatedGas = gasAmount.toString(16);
    
      console.log("Estimated gas: " + estimatedGas);
    
      web3.eth.getTransactionCount(account).then(_nonce => {
        nonce = _nonce.toString(16);
    
        console.log("Nonce: " + nonce);
        const txParams = {
          gasPrice: 100000,
          gasLimit: 3000000,
          to: contractAddress,
          data: functionAbi,
          from: account,
          nonce: '0x' + nonce
        };
    
        const tx = new Tx(txParams);
        tx.sign(privateKey); // Transaction Signing here
    
        const serializedTx = tx.serialize();
    
        web3.eth.sendSignedTransaction('0x' + serializedTx.toString('hex')).on('receipt', receipt => {
          console.log(receipt);
        })
      });
    });
    

    Transaction time is about 20-30 seconds so you should wait quite a bit.