diff --git a/lib/abi.js b/lib/abi.js index 3df0fe684..2cff503d3 100644 --- a/lib/abi.js +++ b/lib/abi.js @@ -17,9 +17,19 @@ /** @file abi.js * @authors: * Marek Kotewicz + * Gav Wood * @date 2014 */ +// TODO: make these be actually accurate instead of falling back onto JS's doubles. +var hexToDec = function (hex) { + return parseInt(hex, 16).toString(); +}; + +var decToHex = function (dec) { + return parseInt(dec).toString(16); +}; + var findIndex = function (array, callback) { var end = false; var i = 0; @@ -35,8 +45,8 @@ var findMethodIndex = function (json, methodName) { }); }; -var padLeft = function (number, n) { - return (new Array(n * 2 - number.toString().length + 1)).join("0") + number; +var padLeft = function (string, chars) { + return Array(chars - string.length + 1).join("0") + string; }; var setupInputTypes = function () { @@ -48,27 +58,34 @@ var setupInputTypes = function () { } var padding = parseInt(type.slice(expected.length)) / 8; - return padLeft(value, padding); + if (typeof value === "number") + value = value.toString(16); + else if (value.indexOf('0x') === 0) + value = value.substr(2); + else + value = (+value).toString(16); + return padLeft(value, padding * 2); }; }; var namedType = function (name, padding, formatter) { return function (type, value) { if (type !== name) { - return false; + return false; } - return padLeft(formatter ? value : formatter(value), padding); + return padLeft(formatter ? formatter(value) : value, padding * 2); }; }; var formatBool = function (value) { - return value ? '1' : '0'; + return value ? '0x1' : '0x0'; }; return [ prefixedType('uint'), prefixedType('int'), + prefixedType('hash'), namedType('address', 20), namedType('bool', 1, formatBool), ]; @@ -79,21 +96,18 @@ var inputTypes = setupInputTypes(); var toAbiInput = function (json, methodName, params) { var bytes = ""; var index = findMethodIndex(json, methodName); - + if (index === -1) { return; } - // it needs to be checked in WebThreeStubServer - // something wrong might be with this additional zero - bytes = bytes + index + 'x' + '0'; + bytes = "0x" + padLeft(index.toString(16), 2); var method = json[index]; - + for (var i = 0; i < method.inputs.length; i++) { var found = false; for (var j = 0; j < inputTypes.length && !found; j++) { - var val = parseInt(params[i]).toString(16); - found = inputTypes[j](method.inputs[i].type, val); + found = inputTypes[j](method.inputs[i].type, params[i]); } if (!found) { console.error('unsupported json type: ' + method.inputs[i].type); @@ -110,7 +124,7 @@ var setupOutputTypes = function () { if (type.indexOf(expected) !== 0) { return -1; } - + var padding = parseInt(type.slice(expected.length)) / 8; return padding * 2; }; @@ -118,12 +132,16 @@ var setupOutputTypes = function () { var namedType = function (name, padding) { return function (type) { - return name === type ? padding * 2: -1; + return name === type ? padding * 2 : -1; }; }; var formatInt = function (value) { - return parseInt(value, 16); + return value.length <= 8 ? +parseInt(value, 16) : hexToDec(value); + }; + + var formatHash = function (value) { + return "0x" + value; }; var formatBool = function (value) { @@ -133,6 +151,7 @@ var setupOutputTypes = function () { return [ { padding: prefixedType('uint'), format: formatInt }, { padding: prefixedType('int'), format: formatInt }, + { padding: prefixedType('hash'), format: formatHash }, { padding: namedType('address', 20) }, { padding: namedType('bool', 1), format: formatBool } ]; @@ -146,7 +165,7 @@ var fromAbiOutput = function (json, methodName, output) { if (index === -1) { return; } - + output = output.slice(2); var result = []; @@ -163,7 +182,7 @@ var fromAbiOutput = function (json, methodName, output) { } var res = output.slice(0, padding); var formatter = outputTypes[j - 1].format; - result.push(formatter ? formatter(res): res); + result.push(formatter ? formatter(res) : ("0x" + res)); output = output.slice(padding); } @@ -197,4 +216,3 @@ module.exports = { inputParser: inputParser, outputParser: outputParser }; - diff --git a/lib/autoprovider.js b/lib/autoprovider.js index 735f56349..bfbc3ab6e 100644 --- a/lib/autoprovider.js +++ b/lib/autoprovider.js @@ -26,10 +26,13 @@ * if not tries to connect over websockets * if it fails, it uses HttpRpcProvider */ -if (process.env.NODE_ENV !== 'build') { + +// TODO: work out which of the following two lines it is supposed to be... +//if (process.env.NODE_ENV !== 'build') { +if ("build" !== 'build') {/* var WebSocket = require('ws'); // jshint ignore:line var web3 = require('./main.js'); // jshint ignore:line -} +*/} var AutoProvider = function (userOptions) { if (web3.haveProvider()) { diff --git a/lib/contract.js b/lib/contract.js index 10ceaf869..17b077484 100644 --- a/lib/contract.js +++ b/lib/contract.js @@ -20,9 +20,11 @@ * @date 2014 */ -if (process.env.NODE_ENV !== 'build') { +// TODO: work out which of the following two lines it is supposed to be... +//if (process.env.NODE_ENV !== 'build') { +if ("build" !== 'build') {/* var web3 = require('./web3'); // jshint ignore:line -} +*/} var abi = require('./abi'); var contract = function (address, desc) { @@ -56,7 +58,7 @@ var contract = function (address, desc) { }; }; }); - + return contract; }; diff --git a/lib/httprpc.js b/lib/httprpc.js index 8141a6bae..ee6b5c307 100644 --- a/lib/httprpc.js +++ b/lib/httprpc.js @@ -21,9 +21,11 @@ * @date 2014 */ -if (process.env.NODE_ENV !== "build") { +// TODO: work out which of the following two lines it is supposed to be... +//if (process.env.NODE_ENV !== 'build') { +if ("build" !== "build") {/* var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest; // jshint ignore:line -} +*/} var HttpRpcProvider = function (host) { this.handlers = []; diff --git a/lib/main.js b/lib/main.js index 697cbdbc3..59c60cfa8 100644 --- a/lib/main.js +++ b/lib/main.js @@ -19,6 +19,7 @@ * Jeffrey Wilcke * Marek Kotewicz * Marian Oancea + * Gav Wood * @date 2014 */ @@ -61,17 +62,23 @@ function flattenPromise (obj) { return Promise.resolve(obj); } +var web3Methods = function () { + return [ + { name: 'sha3', call: 'web3_sha3' } + ]; +}; + var ethMethods = function () { var blockCall = function (args) { return typeof args[0] === "string" ? "eth_blockByHash" : "eth_blockByNumber"; }; var transactionCall = function (args) { - return typeof args[0] === "string" ? 'eth_transactionByHash' : 'eth_transactionByNumber'; + return typeof args[0] === "string" ? 'eth_transactionByHash' : 'eth_transactionByNumber'; }; var uncleCall = function (args) { - return typeof args[0] === "string" ? 'eth_uncleByHash' : 'eth_uncleByNumber'; + return typeof args[0] === "string" ? 'eth_uncleByHash' : 'eth_uncleByNumber'; }; var methods = [ @@ -205,19 +212,20 @@ var setupProperties = function (obj, properties) { }); }; +// TODO: import from a dependency, don't duplicate. +var hexToDec = function (hex) { + return parseInt(hex, 16).toString(); +}; + +var decToHex = function (dec) { + return parseInt(dec).toString(16); +}; + + var web3 = { _callbacks: {}, _events: {}, providers: {}, - toHex: function(str) { - var hex = ""; - for(var i = 0; i < str.length; i++) { - var n = str.charCodeAt(i).toString(16); - hex += n.length < 2 ? '0' + n : n; - } - - return hex; - }, toAscii: function(hex) { // Find termination @@ -237,10 +245,6 @@ var web3 = { return str; }, - toDecimal: function (val) { - return parseInt(val, 16); - }, - fromAscii: function(str, pad) { pad = pad === undefined ? 32 : pad; var hex = this.toHex(str); @@ -249,6 +253,33 @@ var web3 = { return "0x" + hex; }, + toDecimal: function (val) { + return hexToDec(val.substring(2)); + }, + + fromDecimal: function (val) { + return "0x" + decToHex(val); + }, + + toEth: function(str) { + var val = typeof str === "string" ? str.indexOf('0x') == 0 ? parseInt(str.substr(2), 16) : parseInt(str) : str; + var unit = 0; + var units = [ 'wei', 'Kwei', 'Mwei', 'Gwei', 'szabo', 'finney', 'ether', 'grand', 'Mether', 'Gether', 'Tether', 'Pether', 'Eether', 'Zether', 'Yether', 'Nether', 'Dether', 'Vether', 'Uether' ]; + while (val > 3000 && unit < units.length - 1) + { + val /= 1000; + unit++; + } + var s = val.toString().length < val.toFixed(2).length ? val.toString() : val.toFixed(2); + while (true) { + var o = s; + s = s.replace(/(\d)(\d\d\d[\.\,])/, function($0, $1, $2) { return $1 + ',' + $2; }); + if (o == s) + break; + } + return s + ' ' + units[unit]; + }, + eth: { prototype: Object(), // jshint ignore:line watch: function (params) { @@ -294,6 +325,7 @@ var web3 = { } }; +setupMethods(web3, web3Methods()); setupMethods(web3.eth, ethMethods()); setupProperties(web3.eth, ethProperties()); setupMethods(web3.db, dbMethods()); @@ -460,4 +492,3 @@ function messageHandler(data) { } module.exports = web3; - diff --git a/lib/websocket.js b/lib/websocket.js index 0c7563062..24a072531 100644 --- a/lib/websocket.js +++ b/lib/websocket.js @@ -22,9 +22,11 @@ * @date 2014 */ -if (process.env.NODE_ENV !== "build") { +// TODO: work out which of the following two lines it is supposed to be... +//if (process.env.NODE_ENV !== 'build') { +if ("build" !== "build") {/* var WebSocket = require('ws'); // jshint ignore:line -} +*/} var WebSocketProvider = function(host) { // onmessage handlers