I am trying to send a transaction to the Ropsten network, using Infura as the Web3 provider. My transaction is being rejected ("insufficient funds for gas * price + value") and I suspect the reason is that the message is not being properly signed.

This is my code:

const Web3 = require('web3');

let endpoint = "https://ropsten.infura.io/v3/XXXXXXXXXXXXXXXXXXXXXX";
web3 = new Web3(new Web3.providers.HttpProvider(endpoint));



    from: address,
    to: recipient,
    value: '10',
    gas: 50000,

Am I missing something?

  • I would try signing transaction on my end and then use sendSignedTransaction for sending transaction. – Ayushya Mar 6 '19 at 20:07
  • 1
    That worked. I think there might be a bug in web3 causing this. – ig343 Mar 6 '19 at 20:30
  • Okay then. I'll post this as answer. – Ayushya Mar 6 '19 at 20:32

I would try signing transaction on my end and then use sendSignedTransaction for sending transaction.

| improve this answer | |

Try this:

async function signAndSendTransaction() {
    const options = {
        to : recipient,
        value: "10",
        gas: 21000
    const signedTransaction = await web3.eth.accounts.signTransaction(options, private_key);
    return await web3.eth.sendSignedTransaction(signedTransaction.rawTransaction);

| improve this answer | |
  • Are you sure that accounts APIs would be available while using infura? – Ayushya Mar 6 '19 at 20:54
  • @Ayushya: I'm pretty sure that this is a web3 provider-agnostic API. – goodvibration Mar 6 '19 at 21:00

I spent a couple days trying to get web3's amazing send() function (call seems to work well enough) to work Robsten, Kovan, Ganache, nothing works with web3 at the moment! On Kovan I get the Insufficient Funds error that OP reports. On Robsten I got the error:

eth_sendTransaction does not exist/is not available

On ganache, I got something about a missing clientId opcode.

What ended working was implementing sendSignedTransaction

Here's what I wrote in typescript, hope it saves you some time.

import TX from 'ethereumjs-tx'

public async sendRawTx(params: ISignedTxParams) {
  const web3 = await this.getOrInitializeWeb3()
  const from = this.accountAddress
  const nonce = await web3.eth.getTransactionCount(from)
  const gasLimit = web3.utils.toHex(3000000)
  const gasPrice = web3.utils.toHex(5 * 1e9) // 5 gwei
  const txParams = {
    to: params.to,
    value: params.value || 0,
    data: params.data,
  const tx = new TX(txParams)
  tx.sign(new Buffer(this.accountPrivateKey!, 'hex'))
  const serializedTx = tx.serialize()
  console.log('serializedTx : ', serializedTx)
  return new Promise((resolve, reject) => {
      .on('receipt', (r) => {
        console.log("Received Receipt", r)
      .on('confirmation', console.log)
      .on('transactionHash', console.log)
      .on('error', reject)

public async getOrInitializeWeb3(): Promise<Web3> {
  if (this.web3) {
    return this.web3

  const httpProvider = new HttpProvider(this.web3ProviderArgs)
  this.web3 = new Web3(httpProvider)

  if (this.accountPrivateKey) {
    const account = this.web3.eth.accounts.privateKeyToAccount(`0x${this.accountPrivateKey}`)
    if (account.address !== this.accountAddress) {
      throw new Error(`Invalid Eth crypto key pair`)

    this.web3.defaultAccount = account.address

  return this.web3

export interface ISignedTxParams {
  to: string,
  value: string,
  data: Buffer

Then you can call to the sendRawTx like this:

const data = contractInstance.methods.someFunc("Hello", 123).encodeABI()
await this.web3Service.sendRawTx({to: contractInstance.address, data})
| improve this answer | |

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.