web3.js 9.25 KB
Newer Older
Marian Oancea's avatar
Marian Oancea committed
1
/*
Marian Oancea's avatar
Marian Oancea committed
2
    This file is part of ethereum.js.
Marian Oancea's avatar
Marian Oancea committed
3

Marian Oancea's avatar
Marian Oancea committed
4 5 6 7
    ethereum.js is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
Marian Oancea's avatar
Marian Oancea committed
8

Marian Oancea's avatar
Marian Oancea committed
9 10 11 12
    ethereum.js is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.
Marian Oancea's avatar
Marian Oancea committed
13

Marian Oancea's avatar
Marian Oancea committed
14 15
    You should have received a copy of the GNU Lesser General Public License
    along with ethereum.js.  If not, see <http://www.gnu.org/licenses/>.
Marian Oancea's avatar
Marian Oancea committed
16
*/
17
/** @file web3.js
18 19 20 21
 * @authors:
 *   Jeffrey Wilcke <jeff@ethdev.com>
 *   Marek Kotewicz <marek@ethdev.com>
 *   Marian Oancea <marian@ethdev.com>
Gav Wood's avatar
Gav Wood committed
22
 *   Gav Wood <g@ethdev.com>
23 24
 * @date 2014
 */
Marian Oancea's avatar
Marian Oancea committed
25

26 27 28 29
if (process.env.NODE_ENV !== 'build') {
    var BigNumber = require('bignumber.js');
}

30 31
var utils = require('./utils');

32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
var ETH_UNITS = [ 
    'wei', 
    'Kwei', 
    'Mwei', 
    'Gwei', 
    'szabo', 
    'finney', 
    'ether', 
    'grand', 
    'Mether', 
    'Gether', 
    'Tether', 
    'Pether', 
    'Eether', 
    'Zether', 
    'Yether', 
    'Nether', 
    'Dether', 
    'Vether', 
    'Uether' 
];

54
/// @returns an array of objects describing web3 api methods
Gav Wood's avatar
Gav Wood committed
55 56 57 58 59 60
var web3Methods = function () {
    return [
    { name: 'sha3', call: 'web3_sha3' }
    ];
};

61
/// @returns an array of objects describing web3.eth api methods
Marek Kotewicz's avatar
Marek Kotewicz committed
62 63 64
var ethMethods = function () {
    var blockCall = function (args) {
        return typeof args[0] === "string" ? "eth_blockByHash" : "eth_blockByNumber";
Marian Oancea's avatar
Marian Oancea committed
65 66
    };

Marek Kotewicz's avatar
Marek Kotewicz committed
67
    var transactionCall = function (args) {
Gav Wood's avatar
Gav Wood committed
68
        return typeof args[0] === "string" ? 'eth_transactionByHash' : 'eth_transactionByNumber';
Marian Oancea's avatar
Marian Oancea committed
69 70
    };

Marek Kotewicz's avatar
Marek Kotewicz committed
71
    var uncleCall = function (args) {
Gav Wood's avatar
Gav Wood committed
72
        return typeof args[0] === "string" ? 'eth_uncleByHash' : 'eth_uncleByNumber';
Marian Oancea's avatar
Marian Oancea committed
73 74
    };

Marek Kotewicz's avatar
Marek Kotewicz committed
75 76 77
    var methods = [
    { name: 'balanceAt', call: 'eth_balanceAt' },
    { name: 'stateAt', call: 'eth_stateAt' },
Marek Kotewicz's avatar
Marek Kotewicz committed
78
    { name: 'storageAt', call: 'eth_storageAt' },
Marek Kotewicz's avatar
Marek Kotewicz committed
79 80 81 82 83 84 85
    { name: 'countAt', call: 'eth_countAt'},
    { name: 'codeAt', call: 'eth_codeAt' },
    { name: 'transact', call: 'eth_transact' },
    { name: 'call', call: 'eth_call' },
    { name: 'block', call: blockCall },
    { name: 'transaction', call: transactionCall },
    { name: 'uncle', call: uncleCall },
86
    { name: 'compilers', call: 'eth_compilers' },
Gav Wood's avatar
Gav Wood committed
87
    { name: 'flush', call: 'eth_flush' },
88
    { name: 'lll', call: 'eth_lll' },
89
    { name: 'solidity', call: 'eth_solidity' },
Marek Kotewicz's avatar
Marek Kotewicz committed
90 91
    { name: 'serpent', call: 'eth_serpent' },
    { name: 'logs', call: 'eth_logs' }
Marek Kotewicz's avatar
Marek Kotewicz committed
92 93 94 95
    ];
    return methods;
};

96
/// @returns an array of objects describing web3.eth api properties
Marek Kotewicz's avatar
Marek Kotewicz committed
97 98 99 100 101 102 103 104 105 106 107 108 109
var ethProperties = function () {
    return [
    { name: 'coinbase', getter: 'eth_coinbase', setter: 'eth_setCoinbase' },
    { name: 'listening', getter: 'eth_listening', setter: 'eth_setListening' },
    { name: 'mining', getter: 'eth_mining', setter: 'eth_setMining' },
    { name: 'gasPrice', getter: 'eth_gasPrice' },
    { name: 'accounts', getter: 'eth_accounts' },
    { name: 'peerCount', getter: 'eth_peerCount' },
    { name: 'defaultBlock', getter: 'eth_defaultBlock', setter: 'eth_setDefaultBlock' },
    { name: 'number', getter: 'eth_number'}
    ];
};

110
/// @returns an array of objects describing web3.db api methods
Marek Kotewicz's avatar
Marek Kotewicz committed
111 112 113 114 115 116 117 118 119
var dbMethods = function () {
    return [
    { name: 'put', call: 'db_put' },
    { name: 'get', call: 'db_get' },
    { name: 'putString', call: 'db_putString' },
    { name: 'getString', call: 'db_getString' }
    ];
};

120
/// @returns an array of objects describing web3.shh api methods
Marek Kotewicz's avatar
Marek Kotewicz committed
121 122 123 124 125 126 127 128 129 130
var shhMethods = function () {
    return [
    { name: 'post', call: 'shh_post' },
    { name: 'newIdentity', call: 'shh_newIdentity' },
    { name: 'haveIdentity', call: 'shh_haveIdentity' },
    { name: 'newGroup', call: 'shh_newGroup' },
    { name: 'addToGroup', call: 'shh_addToGroup' }
    ];
};

131
/// @returns an array of objects describing web3.eth.watch api methods
Marek Kotewicz's avatar
Marek Kotewicz committed
132 133 134
var ethWatchMethods = function () {
    var newFilter = function (args) {
        return typeof args[0] === 'string' ? 'eth_newFilterString' : 'eth_newFilter';
Marian Oancea's avatar
Marian Oancea committed
135 136
    };

Marek Kotewicz's avatar
Marek Kotewicz committed
137 138 139
    return [
    { name: 'newFilter', call: newFilter },
    { name: 'uninstallFilter', call: 'eth_uninstallFilter' },
Marek Kotewicz's avatar
Marek Kotewicz committed
140
    { name: 'getMessages', call: 'eth_filterLogs' }
Marek Kotewicz's avatar
Marek Kotewicz committed
141 142 143
    ];
};

144
/// @returns an array of objects describing web3.shh.watch api methods
Marek Kotewicz's avatar
Marek Kotewicz committed
145 146 147 148
var shhWatchMethods = function () {
    return [
    { name: 'newFilter', call: 'shh_newFilter' },
    { name: 'uninstallFilter', call: 'shh_uninstallFilter' },
149
    { name: 'getMessages', call: 'shh_getMessages' }
Marek Kotewicz's avatar
Marek Kotewicz committed
150 151 152
    ];
};

153 154
/// creates methods in a given object based on method description on input
/// setups api calls for these methods
Marek Kotewicz's avatar
Marek Kotewicz committed
155 156 157
var setupMethods = function (obj, methods) {
    methods.forEach(function (method) {
        obj[method.name] = function () {
Marek Kotewicz's avatar
Marek Kotewicz committed
158 159
            var args = Array.prototype.slice.call(arguments);
            var call = typeof method.call === 'function' ? method.call(args) : method.call;
160
            return web3.provider.send({
Marek Kotewicz's avatar
Marek Kotewicz committed
161 162
                call: call,
                args: args
Marek Kotewicz's avatar
Marek Kotewicz committed
163
            });
Marian Oancea's avatar
Marian Oancea committed
164
        };
Marek Kotewicz's avatar
Marek Kotewicz committed
165 166 167
    });
};

168 169
/// creates properties in a given object based on properties description on input
/// setups api calls for these properties
Marek Kotewicz's avatar
Marek Kotewicz committed
170 171 172 173
var setupProperties = function (obj, properties) {
    properties.forEach(function (property) {
        var proto = {};
        proto.get = function () {
174
            return web3.provider.send({
Marek Kotewicz's avatar
Marek Kotewicz committed
175
                call: property.getter
Marek Kotewicz's avatar
Marek Kotewicz committed
176 177
            });
        };
178

Marek Kotewicz's avatar
Marek Kotewicz committed
179 180
        if (property.setter) {
            proto.set = function (val) {
181
                return web3.provider.send({
Marek Kotewicz's avatar
Marek Kotewicz committed
182 183
                    call: property.setter,
                    args: [val]
Marian Oancea's avatar
Marian Oancea committed
184 185
                });
            };
Marek Kotewicz's avatar
Marek Kotewicz committed
186 187 188 189 190
        }
        Object.defineProperty(obj, property.name, proto);
    });
};

191
/// setups web3 object, and it's in-browser executed methods
Marek Kotewicz's avatar
Marek Kotewicz committed
192 193 194 195 196
var web3 = {
    _callbacks: {},
    _events: {},
    providers: {},

Marek Kotewicz's avatar
Marek Kotewicz committed
197
    /// @returns ascii string representation of hex value prefixed with 0x
198
    toAscii: utils.toAscii,
Marek Kotewicz's avatar
Marek Kotewicz committed
199

Marek Kotewicz's avatar
Marek Kotewicz committed
200
    /// @returns hex representation (prefixed by 0x) of ascii string
201
    fromAscii: utils.fromAscii,
Marek Kotewicz's avatar
Marek Kotewicz committed
202

Marek Kotewicz's avatar
Marek Kotewicz committed
203
    /// @returns decimal representaton of hex value prefixed by 0x
Gav Wood's avatar
Gav Wood committed
204
    toDecimal: function (val) {
Marek Kotewicz's avatar
Marek Kotewicz committed
205 206 207
        // remove 0x and place 0, if it's required
        val = val.length > 2 ? val.substring(2) : "0";
        return (new BigNumber(val, 16).toString(10));
Gav Wood's avatar
Gav Wood committed
208 209
    },

Marek Kotewicz's avatar
Marek Kotewicz committed
210
    /// @returns hex representation (prefixed by 0x) of decimal value
Gav Wood's avatar
Gav Wood committed
211
    fromDecimal: function (val) {
212
        return "0x" + (new BigNumber(val).toString(16));
Gav Wood's avatar
Gav Wood committed
213 214
    },

Marek Kotewicz's avatar
Marek Kotewicz committed
215
    /// used to transform value/string to eth string
216
    /// TODO: use BigNumber.js to parse int
Gav Wood's avatar
Gav Wood committed
217
    toEth: function(str) {
Marek Kotewicz's avatar
Marek Kotewicz committed
218
        var val = typeof str === "string" ? str.indexOf('0x') === 0 ? parseInt(str.substr(2), 16) : parseInt(str) : str;
Gav Wood's avatar
Gav Wood committed
219
        var unit = 0;
220
        var units = ETH_UNITS;
Gav Wood's avatar
Gav Wood committed
221 222 223 224 225 226
        while (val > 3000 && unit < units.length - 1)
        {
            val /= 1000;
            unit++;
        }
        var s = val.toString().length < val.toFixed(2).length ? val.toString() : val.toFixed(2);
Marek Kotewicz's avatar
Marek Kotewicz committed
227 228 229
        var replaceFunction = function($0, $1, $2) {
            return $1 + ',' + $2;
        };
Marek Kotewicz's avatar
Marek Kotewicz committed
230

Gav Wood's avatar
Gav Wood committed
231 232
        while (true) {
            var o = s;
Marek Kotewicz's avatar
Marek Kotewicz committed
233 234
            s = s.replace(/(\d)(\d\d\d[\.\,])/, replaceFunction);
            if (o === s)
Gav Wood's avatar
Gav Wood committed
235 236 237 238 239
                break;
        }
        return s + ' ' + units[unit];
    },

Marek Kotewicz's avatar
Marek Kotewicz committed
240
    /// eth object prototype
Marek Kotewicz's avatar
Marek Kotewicz committed
241
    eth: {
242 243 244 245 246 247 248 249 250
        contractFromAbi: function (abi) {
            return function(addr) {
                // Default to address of Config. TODO: rremove prior to genesis.
                addr = addr || '0xc6d9d2cd449a754c494264e1809c50e34d64562b';
                var ret = web3.eth.contract(addr, abi);
                ret.address = addr;
                return ret;
            };
        },
Marek Kotewicz's avatar
Marek Kotewicz committed
251 252

        /// @param filter may be a string, object or event
253 254 255
        /// @param indexed is optional, this is an object with optional event indexed params
        /// @param options is optional, this is an object with optional event options ('max'...)
        watch: function (filter, indexed, options) {
Marek Kotewicz's avatar
Marek Kotewicz committed
256
            if (filter._isEvent) {
257
                return filter(indexed, options);
Marek Kotewicz's avatar
Marek Kotewicz committed
258 259
            }
            return new web3.filter(filter, ethWatch);
Marian Oancea's avatar
Marian Oancea committed
260
        }
Marek Kotewicz's avatar
Marek Kotewicz committed
261
    },
Marian Oancea's avatar
Marian Oancea committed
262

Marek Kotewicz's avatar
Marek Kotewicz committed
263 264
    /// db object prototype
    db: {},
Marian Oancea's avatar
Marian Oancea committed
265

Marek Kotewicz's avatar
Marek Kotewicz committed
266
    /// shh object prototype
Marek Kotewicz's avatar
Marek Kotewicz committed
267
    shh: {
Marek Kotewicz's avatar
Marek Kotewicz committed
268 269 270
        
        /// @param filter may be a string, object or event
        watch: function (filter, indexed) {
Marek Kotewicz's avatar
Marek Kotewicz committed
271
            return new web3.filter(filter, shhWatch);
Marian Oancea's avatar
Marian Oancea committed
272
        }
Marek Kotewicz's avatar
Marek Kotewicz committed
273
    },
Marian Oancea's avatar
Marian Oancea committed
274

Marek Kotewicz's avatar
Marek Kotewicz committed
275 276 277
    /// @returns true if provider is installed
    haveProvider: function() {
        return !!web3.provider.provider;
Marek Kotewicz's avatar
Marek Kotewicz committed
278 279 280
    }
};

281
/// setups all api methods
Gav Wood's avatar
Gav Wood committed
282
setupMethods(web3, web3Methods());
283 284
setupMethods(web3.eth, ethMethods());
setupProperties(web3.eth, ethProperties());
Marek Kotewicz's avatar
Marek Kotewicz committed
285 286 287 288 289 290
setupMethods(web3.db, dbMethods());
setupMethods(web3.shh, shhMethods());

var ethWatch = {
    changed: 'eth_changed'
};
291

Marek Kotewicz's avatar
Marek Kotewicz committed
292
setupMethods(ethWatch, ethWatchMethods());
293

Marek Kotewicz's avatar
Marek Kotewicz committed
294 295 296
var shhWatch = {
    changed: 'shh_changed'
};
297

Marek Kotewicz's avatar
Marek Kotewicz committed
298 299 300
setupMethods(shhWatch, shhWatchMethods());

web3.setProvider = function(provider) {
301
    //provider.onmessage = messageHandler; // there will be no async calls, to remove
Marek Kotewicz's avatar
Marek Kotewicz committed
302 303 304
    web3.provider.set(provider);
};

305 306
module.exports = web3;