1

I am creating this very simple program that sends ETH from one address to another. I am using rinkeby.infura.io to get FREE ether and for testing purposes.

My code seems to work fine because when I test it in testrpc on http://localhost:8545 and using the dummy account addresses, everything works just perfectly fine. But when I change to real account addresses and change the HttpProvider to https://rinkeby.infura.io/, I get the below error:

Error: Invalid JSON RPC response: "" at Object.InvalidResponse (D:\Documents\Projects\Eth\node_modules\web3\lib\web3\errors.js:38:16) at HttpProvider.send (D:\Documents\Projects\Eth\node_modules\web3\lib\web3\httpprovider.js:91:22) at RequestManager.send (D:\Documents\Projects\Eth\node_modules\web3\lib\web3\requestmanager.js:58:32) at Eth.send [as sendTransaction] (D:\Documents\Projects\Eth\node_modules\web3\lib\web3\method.js:145:58) at sendBalance (D:\Documents\Projects\Eth\routes\index.js:57:11) at D:\Documents\Projects\Eth\routes\index.js:80:12 at Layer.handle [as handle_request] (D:\Documents\Projects\Eth\node_modules\express\lib\router\layer.js:95:5) at next (D:\Documents\Projects\Eth\node_modules\express\lib\router\route.js:137:13) at Route.dispatch (D:\Documents\Projects\Eth\node_modules\express\lib\router\route.js:112:3) at Layer.handle [as handle_request] (D:\Documents\Projects\Eth\node_modules\express\lib\router\layer.js:95:5)

I noticed I forgot to include a callback function on the part of the code web3.eth.sendTransaction({}), so I changed it to something like web3.eth.sendTransaction({}, function(err, hash){}). It removed the Invalid JSON RPC error message, but it does not perform the entire sendTransaction() at all because I can see the balances were untouched.

Here is the output using the rinkeby.infura.io and with the callback function:

enter image description here

For your reference, below are two versions of my code: (1) with the callback function for sendTransaction(), and (2) without the callback function

(1) With Callback Function

var express = require('express');
var router = express.Router();

var util = require('ethereumjs-util');
var tx = require('ethereumjs-tx');
try {
    var lightwallet = require('eth-lightwallet');
} catch (err) {
delete global._bitcore
    var lightwallet = require('eth-lightwallet');
}
var txutils = lightwallet.txutils;

var Web3 = require('web3');
var web3 = new Web3(new Web3.providers.HttpProvider('https://rinkeby.infura.io/'));

function balance(addr) {
    var start = Date.now();
    var latestBalance = web3.eth.getBalance(addr, "latest");
    var nonce = web3.eth.getTransactionCount(addr, "latest");
    var end = Date.now();
    return nonce;
}

function showBalance(addr) {
    var start = Date.now();
    var latestBalance = web3.eth.getBalance(addr, "latest");
    var nonce = web3.eth.getTransactionCount(addr, "latest");
    var end = Date.now();
    var res = {
        "address": addr,
        "balance": latestBalance + " Wei / " + web3.fromWei(latestBalance).toString() + " ETH",
        "nonce": nonce.toString(),
        "timestamp": (end - start).toString() + "ms"
    }
    return res;
}

function sendBalance(_from, _to) {
    var nonce = balance(_from);
    var amount = 0.05;
    var rawTx = {
        nonce: web3.toHex(nonce),
        gasPrice: web3.toHex(10),
        gasLimit: web3.toHex(21000),
        to: _to,
        value: web3.toHex(amount * 1000000000),
        data: "",
        chainId: 1
    }

    var addFromPrivateKey = new Buffer('4ce80ef53f9c13e5d68737ff078e0660e803f87735fab9c79bf408335be8963d', 'hex');
    var transaction = new tx(rawTx);
    transaction.sign(addFromPrivateKey);
    var res ="";
    var serializedTx = transaction.serialize().toString('hex');
    web3.eth.sendTransaction({ 
        from: _from, 
        to: _to,
        value: web3.toWei(amount, "ether"),
        gas: rawTx.gasLimit,
        price: rawTx.gasPrice,
        nonce: rawTx.nonce
    }, function(error, hash){res = error;});
    var txLog = "";
    // web3.eth.sendRawTransaction('0x' + serializedTx, function(err, result) {
    //  if(err) {
    //      txLog = err;
    //  } else {
    //      txLog = result;
    //  }
    // });
    res = "Status: " + res + " |||| from: " + _from + "\nsendValueETH: " + amount + "\nrawTx: " + JSON.stringify(rawTx, null, 4) + " " + txLog; 
    return res;
}

// Get Homepage
router.get('/', function(req, res) {

    var dti = sendBalance('0xa5d1274a05ab92e3830d81e0e4302498ccb5b22f', '0x6a1366a19b6dbb4d9fe4781f38538e9dc2ec0698');
    dto = showBalance('0xa5d1274a05ab92e3830d81e0e4302498ccb5b22f');
    dtt = showBalance('0x6a1366a19b6dbb4d9fe4781f38538e9dc2ec0698');

    data = {
        "dta": {
            "sender": dto,
            "recipient": dtt,
            "transaction": dti
        }
    }
    res.render('index', {data});
});


module.exports = router;

(2) Without Callback Function

var express = require('express');
var router = express.Router();

var util = require('ethereumjs-util');
var tx = require('ethereumjs-tx');
try {
    var lightwallet = require('eth-lightwallet');
} catch (err) {
delete global._bitcore
    var lightwallet = require('eth-lightwallet');
}
var txutils = lightwallet.txutils;

var Web3 = require('web3');
var web3 = new Web3(new Web3.providers.HttpProvider('https://rinkeby.infura.io/'));

function balance(addr) {
    var start = Date.now();
    var latestBalance = web3.eth.getBalance(addr, "latest");
    var nonce = web3.eth.getTransactionCount(addr, "latest");
    var end = Date.now();
    return nonce;
}

function showBalance(addr) {
    var start = Date.now();
    var latestBalance = web3.eth.getBalance(addr, "latest");
    var nonce = web3.eth.getTransactionCount(addr, "latest");
    var end = Date.now();
    var res = {
        "address": addr,
        "balance": latestBalance + " Wei / " + web3.fromWei(latestBalance).toString() + " ETH",
        "nonce": nonce.toString(),
        "timestamp": (end - start).toString() + "ms"
    }
    return res;
}

function sendBalance(_from, _to) {
    var nonce = balance(_from);
    var amount = 0.05;
    var rawTx = {
        nonce: web3.toHex(nonce),
        gasPrice: web3.toHex(10),
        gasLimit: web3.toHex(21000),
        to: _to,
        value: web3.toHex(amount * 1000000000),
        data: "",
        chainId: 1
    }

    var addFromPrivateKey = new Buffer('4ce80ef53f9c13e5d68737ff078e0660e803f87735fab9c79bf408335be8963d', 'hex');
    var transaction = new tx(rawTx);
    transaction.sign(addFromPrivateKey);
    var res ="";
    var serializedTx = transaction.serialize().toString('hex');
    web3.eth.sendTransaction({ 
        from: _from, 
        to: _to,
        value: web3.toWei(amount, "ether"),
        gas: rawTx.gasLimit,
        price: rawTx.gasPrice,
        nonce: rawTx.nonce
    });
    var txLog = "";
    // web3.eth.sendRawTransaction('0x' + serializedTx, function(err, result) {
    //  if(err) {
    //      txLog = err;
    //  } else {
    //      txLog = result;
    //  }
    // });
    res = "Status: " + res + " |||| from: " + _from + "\nsendValueETH: " + amount + "\nrawTx: " + JSON.stringify(rawTx, null, 4) + " " + txLog; 
    return res;
}

// Get Homepage
router.get('/', function(req, res) {

    var dti = sendBalance('0xa5d1274a05ab92e3830d81e0e4302498ccb5b22f', '0x6a1366a19b6dbb4d9fe4781f38538e9dc2ec0698');
    dto = showBalance('0xa5d1274a05ab92e3830d81e0e4302498ccb5b22f');
    dtt = showBalance('0x6a1366a19b6dbb4d9fe4781f38538e9dc2ec0698');

    data = {
        "dta": {
            "sender": dto,
            "recipient": dtt,
            "transaction": dti
        }
    }
    res.render('index', {data});
});


module.exports = router;

P.S. It's worth mentioning that those are sample private key and addresses only for presentation purposes here. And also, you may disregard anything about rawTx :)

Here is a sample successful output using testrpc:

enter image description here

Again, it works on testrpc, but not on rinkeby.infura. I think it definitely will not work on the real ethereum network too. I am new to ethereum and blockchain development. Any help i.e. solution to my issue, suggestions on my code, I would greatly appreciate it guys! Thanks in advance!

1 Answer 1

0

The error message is still there. It just happens to not render as part of the result, after having included the callback function, because the error is set asynchronously. If you change res = error to console.error(error), for example, you will be able to see it on the spot: Error: Invalid JSON RPC response: "".

The reason for Invalid JSON RPC response is that Infura does not support the sendTransaction method, since it depends on account details. According to the documentation [1]:

INFURA supports a subset of Ethereum's JSON-RPC methods. Most of the unsupported methods have to do with private keys.

In addition to reading back the error directly from sendTransaction callback, it is possible to use something like curl to make a request and confirm the method is indeed not available.
Example:

curl -i -X POST -H "Content-Type: application/json" \
    --data '{"jsonrpc": "2.0", "id": 1, "method": "eth_sendTransaction", "params": []}' \
    "https://rinkeby.infura.io/"

Outputs:

HTTP/1.1 405 Method Not Allowed
[...]

This behavior is also documented:

If you try to use a method that is not on this list, you will receive a 405 Method Not Allowed HTTP response.

You should use opt to sendRawTransaction instead, which is in the provided code, as you mentioned, to send the already signed transaction data to Infura.

[1] https://github.com/INFURA/infura/blob/master/docs/source/index.html.md#supported-json-rpc-methods

Stay super!

/Javi

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.