Comparing version 0.5.10 to 0.6.0
406
index.js
@@ -84,6 +84,2 @@ /** | ||
etherscanApi: "https://testnet.etherscan.io/api", | ||
etherscan: false, | ||
nodes: { | ||
@@ -172,3 +168,2 @@ hosted: HOSTED_NODES.slice(), | ||
var results, len, err; | ||
// console.log(response); | ||
try { | ||
@@ -178,3 +173,3 @@ if (response && typeof response === "string") { | ||
} | ||
if (response && typeof response === "object" && response !== null) { | ||
if (response !== undefined && typeof response === "object" && response !== null) { | ||
if (response.error) { | ||
@@ -193,4 +188,3 @@ response = { | ||
if (response.result && response.result.length > 2 && | ||
response.result.slice(0,2) === "0x") | ||
{ | ||
response.result.slice(0,2) === "0x") { | ||
response.result = abi.remove_leading_zeros(response.result); | ||
@@ -247,2 +241,3 @@ response.result = abi.prefix_hex(response.result); | ||
var returns; | ||
if (tx.method === "eth_coinbase") return "address"; | ||
if (tx.params !== undefined && tx.params.length && tx.params[0]) { | ||
@@ -442,209 +437,157 @@ if (tx.params[0].returns) { | ||
if (!this.etherscan) { | ||
if (!command || (command.constructor === Object && !command.method) || | ||
(command.constructor === Array && !command.length)) | ||
{ | ||
if (!callback) return null; | ||
return callback(null); | ||
} | ||
if (this.debug.logs) { | ||
if (command.method === "eth_call" || command.method === "eth_sendTransaction") { | ||
if (command.params && (!command.params.length || !command.params[0].from)) { | ||
console.log( | ||
"**************************\n"+ | ||
"* OH GOD WHAT DID YOU DO *\n"+ | ||
"**************************" | ||
); | ||
var network = this.version(); | ||
var contracts = this.contracts(network); | ||
var contract; | ||
for (var address in contracts) { | ||
if (!contracts.hasOwnProperty(address)) continue; | ||
if (contracts[address] === command.params[0].to) { | ||
contract = address; | ||
break; | ||
} | ||
if (!command || (command.constructor === Object && !command.method) || | ||
(command.constructor === Array && !command.length)) { | ||
if (!callback) return null; | ||
return callback(null); | ||
} | ||
if (this.debug.logs) { | ||
if (command.method === "eth_call" || command.method === "eth_sendTransaction") { | ||
if (command.params && (!command.params.length || !command.params[0].from)) { | ||
console.log( | ||
"**************************\n"+ | ||
"* OH GOD WHAT DID YOU DO *\n"+ | ||
"**************************" | ||
); | ||
var network = this.version(); | ||
var contracts = this.contracts(network); | ||
var contract; | ||
for (var address in contracts) { | ||
if (!contracts.hasOwnProperty(address)) continue; | ||
if (contracts[address] === command.params[0].to) { | ||
contract = address; | ||
break; | ||
} | ||
console.log( | ||
"network:", network, "\n"+ | ||
"contract:", contract, "[" + command.params[0].to + "]\n"+ | ||
"method:", command.method, "\n"+ | ||
"params:", JSON.stringify(command.params, null, 2) | ||
); | ||
if (command.debug) { | ||
console.log("tx:", JSON.stringify(command.debug, null, 2)); | ||
delete command.debug; | ||
} | ||
} | ||
console.log( | ||
"network:", network, "\n"+ | ||
"contract:", contract, "[" + command.params[0].to + "]\n"+ | ||
"method:", command.method, "\n"+ | ||
"params:", JSON.stringify(command.params, null, 2) | ||
); | ||
if (command.debug) { | ||
console.log("tx:", JSON.stringify(command.debug, null, 2)); | ||
delete command.debug; | ||
} | ||
} | ||
} | ||
} | ||
// parse batched commands and strip "returns" and "invocation" fields | ||
if (command.constructor === Array) { | ||
numCommands = command.length; | ||
returns = new Array(numCommands); | ||
for (var i = 0; i < numCommands; ++i) { | ||
returns[i] = this.strip(command[i]); | ||
} | ||
// parse batched commands and strip "returns" and "invocation" fields | ||
if (command.constructor === Array) { | ||
numCommands = command.length; | ||
returns = new Array(numCommands); | ||
for (var i = 0; i < numCommands; ++i) { | ||
returns[i] = this.strip(command[i]); | ||
} | ||
// parse commands and strip "returns" and "invocation" fields | ||
} else { | ||
returns = this.strip(command); | ||
// parse commands and strip "returns" and "invocation" fields | ||
} else { | ||
returns = this.strip(command); | ||
} | ||
// if we're on Node, use IPC if available and ipcpath is specified | ||
if (NODE_JS && this.ipcpath && command.method && | ||
command.method.indexOf("Filter") === -1) | ||
{ | ||
var loopback = this.nodes.local && ( | ||
(this.nodes.local.indexOf("127.0.0.1") > -1 || | ||
this.nodes.local.indexOf("localhost") > -1) | ||
); | ||
if (!isFunction(callback) && !loopback) { | ||
throw new this.Error(errors.LOOPBACK_NOT_FOUND); | ||
} | ||
// if we're on Node, use IPC if available and ipcpath is specified | ||
if (NODE_JS && this.ipcpath && command.method && | ||
command.method.indexOf("Filter") === -1) | ||
{ | ||
var loopback = this.nodes.local && ( | ||
(this.nodes.local.indexOf("127.0.0.1") > -1 || | ||
this.nodes.local.indexOf("localhost") > -1) | ||
); | ||
if (!isFunction(callback) && !loopback) { | ||
throw new this.Error(errors.LOOPBACK_NOT_FOUND); | ||
} | ||
if (isFunction(callback) && command.constructor !== Array) { | ||
var received = ''; | ||
var socket = new net.Socket(); | ||
socket.setEncoding("utf8"); | ||
socket.connect({path: this.ipcpath}, function () { | ||
socket.write(JSON.stringify(command)); | ||
}); | ||
socket.on("data", function (data) { | ||
received += data; | ||
self.parse(received, returns, function (parsed) { | ||
if (parsed && parsed.error === 409) return; | ||
socket.destroy(); | ||
callback(parsed); | ||
}); | ||
}); | ||
socket.on("error", function (err) { | ||
if (isFunction(callback) && command.constructor !== Array) { | ||
var received = ''; | ||
var socket = new net.Socket(); | ||
socket.setEncoding("utf8"); | ||
socket.connect({path: this.ipcpath}, function () { | ||
socket.write(JSON.stringify(command)); | ||
}); | ||
socket.on("data", function (data) { | ||
received += data; | ||
self.parse(received, returns, function (parsed) { | ||
if (parsed && parsed.error === 409) return; | ||
socket.destroy(); | ||
callback(err); | ||
callback(parsed); | ||
}); | ||
return; | ||
} | ||
}); | ||
socket.on("error", function (err) { | ||
socket.destroy(); | ||
callback(err); | ||
}); | ||
return; | ||
} | ||
} | ||
// make sure the ethereum node list isn't empty | ||
if (!this.nodes.local && !this.nodes.hosted.length && !this.ipcpath) { | ||
if (isFunction(callback)) return callback(errors.ETHEREUM_NOT_FOUND); | ||
throw new this.Error(errors.ETHEREUM_NOT_FOUND); | ||
} | ||
// make sure the ethereum node list isn't empty | ||
if (!this.nodes.local && !this.nodes.hosted.length && !this.ipcpath) { | ||
if (isFunction(callback)) return callback(errors.ETHEREUM_NOT_FOUND); | ||
throw new this.Error(errors.ETHEREUM_NOT_FOUND); | ||
} | ||
// select local / hosted node(s) to receive RPC | ||
nodes = this.selectNodes(); | ||
// select local / hosted node(s) to receive RPC | ||
nodes = this.selectNodes(); | ||
// asynchronous request if callback exists | ||
if (isFunction(callback)) { | ||
async.eachSeries(nodes, function (node, nextNode) { | ||
if (!completed) { | ||
// asynchronous request if callback exists | ||
if (isFunction(callback)) { | ||
async.eachSeries(nodes, function (node, nextNode) { | ||
if (!completed) { | ||
if (self.debug.logs) { | ||
console.log("nodes:", JSON.stringify(nodes)); | ||
console.log("post", command.method, "to:", node); | ||
} | ||
if (self.balancer) { | ||
start = new Date().getTime(); | ||
} | ||
self.post(node, command, returns, function (res) { | ||
if (self.debug.logs) { | ||
console.log("nodes:", JSON.stringify(nodes)); | ||
console.log("post", command.method, "to:", node); | ||
if (res && res.constructor === BigNumber) { | ||
console.log(node, "response:", abi.string(res)); | ||
} else { | ||
console.log(node, "response:", res); | ||
} | ||
} | ||
if (self.balancer) { | ||
start = new Date().getTime(); | ||
} | ||
self.post(node, command, returns, function (res) { | ||
if (self.debug.logs) { | ||
if (res && res.constructor === BigNumber) { | ||
console.log(node, "response:", abi.string(res)); | ||
} else { | ||
console.log(node, "response:", res); | ||
} | ||
if (node === nodes[nodes.length - 1] || | ||
(res !== undefined && res !== null && | ||
!res.error && res !== "0x")) | ||
{ | ||
completed = true; | ||
if (self.balancer) { | ||
self.updateMeanLatency(node, new Date().getTime() - start); | ||
} | ||
if (node === nodes[nodes.length - 1] || | ||
(res !== undefined && res !== null && | ||
!res.error && res !== "0x")) | ||
{ | ||
completed = true; | ||
if (self.balancer) { | ||
self.updateMeanLatency(node, new Date().getTime() - start); | ||
} | ||
return nextNode({ output: res }); | ||
} | ||
nextNode(); | ||
}); | ||
} | ||
}, function (res) { | ||
if (!res && res.output === undefined) return callback(); | ||
callback(res.output); | ||
}); | ||
// use synchronous http if no callback provided | ||
} else { | ||
for (var j = 0, len = nodes.length; j < len; ++j) { | ||
try { | ||
if (this.debug.logs) { | ||
console.log("nodes:", JSON.stringify(nodes)); | ||
console.log("synchronous post", command.method, "to:", nodes[j]); | ||
return nextNode({ output: res }); | ||
} | ||
if (this.balancer) { | ||
start = new Date().getTime(); | ||
} | ||
result = this.postSync(nodes[j], command, returns); | ||
if (this.balancer) { | ||
this.updateMeanLatency(nodes[j], new Date().getTime() - start); | ||
} | ||
} catch (e) { | ||
if (this.nodes.local) { | ||
throw new this.Error(errors.LOCAL_NODE_FAILURE); | ||
} else if (this.excision) { | ||
this.exciseNode(e, nodes[j]); | ||
} | ||
} | ||
if (result) return result; | ||
nextNode(); | ||
}); | ||
} | ||
throw new this.Error(errors.NO_RESPONSE); | ||
} | ||
}, function (res) { | ||
if (!res && res.output === undefined) return callback(); | ||
callback(res.output); | ||
}); | ||
// etherscan API | ||
// use synchronous http if no callback provided | ||
} else { | ||
var timeout; | ||
if (command.returns) { | ||
returns = command.returns; | ||
delete command.returns; | ||
} | ||
if (command.timeout) { | ||
timeout = command.timeout; | ||
delete command.timeout; | ||
} else { | ||
timeout = this.POST_TIMEOUT; | ||
} | ||
var rpcUrl = this.etherscanApi + "?" + Object.keys(command).map(function (k) { | ||
return encodeURIComponent(k) + '=' + encodeURIComponent(command[k]); | ||
}).join('&'); | ||
console.log("[ethrpc] url:", rpcUrl); | ||
if (!isFunction(callback)) { | ||
var req; | ||
if (NODE_JS) { | ||
req = syncRequest("GET", rpcUrl, {timeout: timeout}); | ||
var response = req.getBody().toString(); | ||
return this.parse(response, returns); | ||
for (var j = 0, len = nodes.length; j < len; ++j) { | ||
try { | ||
if (this.debug.logs) { | ||
console.log("nodes:", JSON.stringify(nodes)); | ||
console.log("synchronous post", command.method, "to:", nodes[j]); | ||
} | ||
if (this.balancer) { | ||
start = new Date().getTime(); | ||
} | ||
result = this.postSync(nodes[j], command, returns); | ||
if (this.balancer) { | ||
this.updateMeanLatency(nodes[j], new Date().getTime() - start); | ||
} | ||
} catch (e) { | ||
if (this.nodes.local) { | ||
throw new this.Error(errors.LOCAL_NODE_FAILURE); | ||
} else if (this.excision) { | ||
this.exciseNode(e, nodes[j]); | ||
} | ||
} | ||
console.warn("[ethrpc] synchronous RPC request to " + rpcUrl + ":", command); | ||
if (window.XMLHttpRequest) { | ||
req = new window.XMLHttpRequest(); | ||
} else { | ||
req = new window.ActiveXObject("Microsoft.XMLHTTP"); | ||
} | ||
req.open("GET", rpcUrl, false); | ||
req.setRequestHeader("Content-type", "application/json"); | ||
// req.send(); | ||
return this.parse(req.responseText, returns); | ||
if (result !== undefined) return result; | ||
} | ||
request({ | ||
url: rpcUrl, | ||
method: "GET", | ||
timeout: timeout | ||
}, function (e, response, body) { | ||
if (e) { | ||
console.error("etherscan eth_call error:", e); | ||
self.etherscan = false; | ||
callback(e); | ||
} else if (response.statusCode === 200) { | ||
self.parse(body, returns, callback); | ||
} | ||
}); | ||
throw new this.Error(errors.NO_RESPONSE); | ||
} | ||
@@ -662,42 +605,35 @@ }, | ||
// direct-to-geth | ||
if (!this.etherscan || !this.etherscannable(action)) { | ||
payload = { | ||
id: this.requests++, | ||
jsonrpc: "2.0", | ||
method: action | ||
}; | ||
if (params !== undefined && params !== null) { | ||
if (params.constructor === Object) { | ||
if (this.debug.broadcast && params.debug) { | ||
payload.debug = abi.copy(params.debug); | ||
delete params.debug; | ||
} | ||
if (params.timeout) { | ||
payload.timeout = params.timeout; | ||
delete params.timeout; | ||
} | ||
if (JSON.stringify(params) === "{}") { | ||
params = []; | ||
} | ||
payload = { | ||
id: this.requests++, | ||
jsonrpc: "2.0", | ||
method: action | ||
}; | ||
if (params !== undefined && params !== null) { | ||
if (params.constructor === Object) { | ||
if (this.debug.broadcast && params.debug) { | ||
payload.debug = abi.copy(params.debug); | ||
delete params.debug; | ||
} | ||
if (params.constructor === Array) { | ||
for (var i = 0, len = params.length; i < len; ++i) { | ||
if (params[i].constructor === Number) { | ||
params[i] = params[i].toString(); | ||
} | ||
if (params.timeout) { | ||
payload.timeout = params.timeout; | ||
delete params.timeout; | ||
} | ||
if (JSON.stringify(params) === "{}") { | ||
params = []; | ||
} | ||
} | ||
if (params.constructor === Array) { | ||
for (var i = 0, len = params.length; i < len; ++i) { | ||
if (params[i].constructor === Number) { | ||
params[i] = abi.prefix_hex(params[i].toString(16)); | ||
} | ||
payload.params = params; | ||
} else { | ||
payload.params = [params]; | ||
} | ||
payload.params = params; | ||
} else { | ||
payload.params = []; | ||
payload.params = [params]; | ||
} | ||
return payload; | ||
} else { | ||
payload.params = []; | ||
} | ||
// use etherscan geth proxy | ||
params.module = "proxy"; | ||
params.action = action; | ||
return params; | ||
return payload; | ||
}, | ||
@@ -799,6 +735,6 @@ | ||
txCount: function (address, f) { | ||
return this.broadcast(this.marshal("getTransactionCount", address), f); | ||
return this.broadcast(this.marshal("getTransactionCount", [address, "latest"]), f); | ||
}, | ||
getTransactionCount: function (address, f) { | ||
return this.broadcast(this.marshal("getTransactionCount", address), f); | ||
return this.broadcast(this.marshal("getTransactionCount", [address, "latest"]), f); | ||
}, | ||
@@ -891,3 +827,3 @@ pendingTxCount: function (address, f) { | ||
tx.to = tx.to || ""; | ||
tx.gas = (tx.gas) ? tx.gas : this.DEFAULT_GAS; | ||
tx.gas = tx.gas || this.DEFAULT_GAS; | ||
return this.broadcast(this.marshal("call", [tx, "latest"]), f); | ||
@@ -1061,4 +997,4 @@ }, | ||
} | ||
if (tx.to) tx.to = abi.prefix_hex(tx.to); | ||
if (tx.from) tx.from = abi.prefix_hex(tx.from); | ||
if (tx.to) tx.to = abi.format_address(tx.to); | ||
if (tx.from) tx.from = abi.format_address(tx.from); | ||
dataAbi = abi.encode(tx); | ||
@@ -1131,4 +1067,4 @@ if (dataAbi) { | ||
} | ||
if (tx.from) tx.from = abi.prefix_hex(tx.from); | ||
tx.to = abi.prefix_hex(tx.to); | ||
if (tx.from) tx.from = abi.format_address(tx.from); | ||
tx.to = abi.format_address(tx.to); | ||
dataAbi = abi.encode(tx); | ||
@@ -1155,3 +1091,3 @@ if (dataAbi) { | ||
invocation = (tx.send) ? "sendTransaction" : "call"; | ||
rpclist[i] = this.marshal(invocation, packaged); | ||
rpclist[i] = this.marshal(invocation, [packaged, "latest"]); | ||
} else { | ||
@@ -1158,0 +1094,0 @@ console.error("unable to package commands for batch RPC"); |
{ | ||
"name": "ethrpc", | ||
"version": "0.5.10", | ||
"version": "0.6.0", | ||
"description": "Ethereum JSON RPC", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
586724
10842