Gav Wood
10 years ago
27 changed files with 1845 additions and 29 deletions
@ -0,0 +1,5 @@ |
|||
{ |
|||
"directory": "example/js/", |
|||
"cwd": "./", |
|||
"analytics": false |
|||
} |
@ -0,0 +1,12 @@ |
|||
root = true |
|||
|
|||
[*] |
|||
indent_style = space |
|||
indent_size = 4 |
|||
end_of_line = lf |
|||
charset = utf-8 |
|||
trim_trailing_whitespace = true |
|||
insert_final_newline = true |
|||
|
|||
[*.md] |
|||
trim_trailing_whitespace = false |
@ -0,0 +1,18 @@ |
|||
# See http://help.github.com/ignore-files/ for more about ignoring files. |
|||
# |
|||
# If you find yourself ignoring temporary files generated by your text editor |
|||
# or operating system, you probably want to add a global ignore instead: |
|||
# git config --global core.excludesfile ~/.gitignore_global |
|||
|
|||
*.swp |
|||
/tmp |
|||
*/**/*un~ |
|||
*un~ |
|||
.DS_Store |
|||
*/**/.DS_Store |
|||
ethereum/ethereum |
|||
ethereal/ethereal |
|||
example/js |
|||
node_modules |
|||
bower_components |
|||
npm-debug.log |
@ -0,0 +1,50 @@ |
|||
{ |
|||
"predef": [ |
|||
"console", |
|||
"require", |
|||
"equal", |
|||
"test", |
|||
"testBoth", |
|||
"testWithDefault", |
|||
"raises", |
|||
"deepEqual", |
|||
"start", |
|||
"stop", |
|||
"ok", |
|||
"strictEqual", |
|||
"module", |
|||
"expect", |
|||
"reject", |
|||
"impl" |
|||
], |
|||
|
|||
"esnext": true, |
|||
"proto": true, |
|||
"node" : true, |
|||
"browser" : true, |
|||
"browserify" : true, |
|||
|
|||
"boss" : true, |
|||
"curly": false, |
|||
"debug": true, |
|||
"devel": true, |
|||
"eqeqeq": true, |
|||
"evil": true, |
|||
"forin": false, |
|||
"immed": false, |
|||
"laxbreak": false, |
|||
"newcap": true, |
|||
"noarg": true, |
|||
"noempty": false, |
|||
"nonew": false, |
|||
"nomen": false, |
|||
"onevar": false, |
|||
"plusplus": false, |
|||
"regexp": false, |
|||
"undef": true, |
|||
"sub": true, |
|||
"strict": false, |
|||
"white": false, |
|||
"shadow": true, |
|||
"eqnull": true |
|||
} |
@ -0,0 +1,9 @@ |
|||
example/js |
|||
node_modules |
|||
test |
|||
.gitignore |
|||
.editorconfig |
|||
.travis.yml |
|||
.npmignore |
|||
component.json |
|||
testling.html |
@ -0,0 +1,11 @@ |
|||
language: node_js |
|||
node_js: |
|||
- "0.11" |
|||
- "0.10" |
|||
before_script: |
|||
- npm install |
|||
- npm install jshint |
|||
script: |
|||
- "jshint *.js lib" |
|||
after_script: |
|||
- npm run-script gulp |
@ -0,0 +1,14 @@ |
|||
This file is part of ethereum.js. |
|||
|
|||
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. |
|||
|
|||
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. |
|||
|
|||
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/>. |
@ -0,0 +1,79 @@ |
|||
# Ethereum JavaScript API |
|||
|
|||
This is the Ethereum compatible JavaScript API using `Promise`s |
|||
which implements the [Generic JSON RPC](https://github.com/ethereum/wiki/wiki/Generic-JSON-RPC) spec. It's available on npm as a node module and also for bower and component as an embeddable js |
|||
|
|||
[![NPM version][npm-image]][npm-url] [![Build Status][travis-image]][travis-url] [![dependency status][dep-image]][dep-url] [![dev dependency status][dep-dev-image]][dep-dev-url] |
|||
|
|||
<!-- [![browser support](https://ci.testling.com/ethereum/ethereum.js.png)](https://ci.testling.com/ethereum/ethereum.js) --> |
|||
|
|||
## Installation |
|||
|
|||
### Node.js |
|||
|
|||
npm install ethereum.js |
|||
|
|||
### For browser |
|||
Bower |
|||
|
|||
bower install ethereum.js |
|||
|
|||
Component |
|||
|
|||
component install ethereum/ethereum.js |
|||
|
|||
* Include `ethereum.min.js` in your html file. |
|||
* Include [es6-promise](https://github.com/jakearchibald/es6-promise) or another ES6-Shim if your browser doesn't support ECMAScript 6. |
|||
|
|||
## Usage |
|||
Require the library: |
|||
|
|||
var web3 = require('web3'); |
|||
|
|||
Set a provider (QtProvider, WebSocketProvider, HttpRpcProvider) |
|||
|
|||
var web3.setProvider(new web3.providers.WebSocketProvider('ws://localhost:40404/eth')); |
|||
|
|||
There you go, now you can use it: |
|||
|
|||
``` |
|||
web3.eth.coinbase.then(function(result){ |
|||
console.log(result); |
|||
return web3.eth.balanceAt(result); |
|||
}).then(function(balance){ |
|||
console.log(web3.toDecimal(balance)); |
|||
}).catch(function(err){ |
|||
console.log(err); |
|||
}); |
|||
``` |
|||
|
|||
|
|||
For another example see `example/index.html`. |
|||
|
|||
## Building |
|||
|
|||
* `gulp build` |
|||
|
|||
|
|||
### Testing |
|||
|
|||
**Please note this repo is in it's early stage.** |
|||
|
|||
If you'd like to run a WebSocket ethereum node check out |
|||
[go-ethereum](https://github.com/ethereum/go-ethereum). |
|||
|
|||
To install ethereum and spawn a node: |
|||
|
|||
``` |
|||
go get github.com/ethereum/go-ethereum/ethereum |
|||
ethereum -ws -loglevel=4 |
|||
``` |
|||
|
|||
[npm-image]: https://badge.fury.io/js/ethereum.js.png |
|||
[npm-url]: https://npmjs.org/package/ethereum.js |
|||
[travis-image]: https://travis-ci.org/ethereum/ethereum.js.svg |
|||
[travis-url]: https://travis-ci.org/ethereum/ethereum.js |
|||
[dep-image]: https://david-dm.org/ethereum/ethereum.js.svg |
|||
[dep-url]: https://david-dm.org/ethereum/ethereum.js |
|||
[dep-dev-image]: https://david-dm.org/ethereum/ethereum.js/dev-status.svg |
|||
[dep-dev-url]: https://david-dm.org/ethereum/ethereum.js#info=devDependencies |
@ -0,0 +1,51 @@ |
|||
{ |
|||
"name": "ethereum.js", |
|||
"namespace": "ethereum", |
|||
"version": "0.0.3", |
|||
"description": "Ethereum Compatible JavaScript API", |
|||
"main": ["./dist/ethereum.js", "./dist/ethereum.min.js"], |
|||
"dependencies": { |
|||
"es6-promise": "#master" |
|||
}, |
|||
"repository": { |
|||
"type": "git", |
|||
"url": "https://github.com/ethereum/ethereum.js.git" |
|||
}, |
|||
"homepage": "https://github.com/ethereum/ethereum.js", |
|||
"bugs": { |
|||
"url": "https://github.com/ethereum/ethereum.js/issues" |
|||
}, |
|||
"keywords": [ |
|||
"ethereum", |
|||
"javascript", |
|||
"API" |
|||
], |
|||
"authors": [ |
|||
{ |
|||
"name": "Marek Kotewicz", |
|||
"email": "marek@ethdev.com", |
|||
"homepage": "https://github.com/debris" |
|||
}, |
|||
{ |
|||
"name": "Marian Oancea", |
|||
"email": "marian@ethdev.com", |
|||
"homepage": "https://github.com/cubedro" |
|||
} |
|||
], |
|||
"license": "LGPL-3.0", |
|||
"ignore": [ |
|||
"example", |
|||
"lib", |
|||
"node_modules", |
|||
"package.json", |
|||
".bowerrc", |
|||
".editorconfig", |
|||
".gitignore", |
|||
".jshintrc", |
|||
".npmignore", |
|||
".travis.yml", |
|||
"gulpfile.js", |
|||
"index.js", |
|||
"**/*.txt" |
|||
] |
|||
} |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,41 @@ |
|||
<!doctype> |
|||
<html> |
|||
|
|||
<head> |
|||
<script type="text/javascript" src="js/es6-promise/promise.min.js"></script> |
|||
<script type="text/javascript" src="../dist/ethereum.js"></script> |
|||
<script type="text/javascript"> |
|||
|
|||
var web3 = require('web3'); |
|||
web3.setProvider(new web3.providers.AutoProvider()); |
|||
|
|||
function watchBalance() { |
|||
var coinbase = web3.eth.coinbase; |
|||
var originalBalance = 0; |
|||
|
|||
web3.eth.balanceAt(coinbase).then(function (balance) { |
|||
originalBalance = web3.toDecimal(balance); |
|||
document.getElementById('original').innerText = 'original balance: ' + originalBalance + ' watching...'; |
|||
}); |
|||
|
|||
web3.eth.watch({altered: coinbase}).changed(function() { |
|||
web3.eth.balanceAt(coinbase).then(function (balance) { |
|||
var currentBalance = web3.toDecimal(balance); |
|||
document.getElementById("current").innerText = 'current: ' + currentBalance; |
|||
document.getElementById("diff").innerText = 'diff: ' + (currentBalance - originalBalance); |
|||
}); |
|||
}); |
|||
} |
|||
|
|||
</script> |
|||
</head> |
|||
<body> |
|||
<h1>coinbase balance</h1> |
|||
<button type="button" onClick="watchBalance();">watch balance</button> |
|||
<div></div> |
|||
<div id="original"></div> |
|||
<div id="current"></div> |
|||
<div id="diff"></div> |
|||
</body> |
|||
</html> |
|||
|
@ -0,0 +1,75 @@ |
|||
<!doctype> |
|||
<html> |
|||
|
|||
<head> |
|||
<script type="text/javascript" src="js/es6-promise/promise.min.js"></script> |
|||
<script type="text/javascript" src="../dist/ethereum.js"></script> |
|||
<script type="text/javascript"> |
|||
|
|||
var web3 = require('web3'); |
|||
web3.setProvider(new web3.providers.AutoProvider()); |
|||
|
|||
// solidity source code |
|||
var source = "" + |
|||
"contract test {\n" + |
|||
" function multiply(uint a) returns(uint d) {\n" + |
|||
" return a * 7;\n" + |
|||
" }\n" + |
|||
"}\n"; |
|||
|
|||
// contract description, this will be autogenerated somehow |
|||
var desc = [{ |
|||
"name": "multiply", |
|||
"inputs": [ |
|||
{ |
|||
"name": "a", |
|||
"type": "uint256" |
|||
} |
|||
], |
|||
"outputs": [ |
|||
{ |
|||
"name": "d", |
|||
"type": "uint256" |
|||
} |
|||
] |
|||
}]; |
|||
|
|||
var contract; |
|||
|
|||
function createExampleContract() { |
|||
// hide create button |
|||
document.getElementById('create').style.visibility = 'hidden'; |
|||
document.getElementById('source').innerText = source; |
|||
|
|||
// create contract |
|||
web3.eth.transact({code: web3.eth.solidity(source)}).then(function (address) { |
|||
contract = web3.contract(address, desc); |
|||
document.getElementById('call').style.visibility = 'visible'; |
|||
}); |
|||
} |
|||
|
|||
function callExampleContract() { |
|||
// this should be generated by ethereum |
|||
var param = document.getElementById('value').value; |
|||
|
|||
// call the contract |
|||
contract.multiply(param).call().then(function(res) { |
|||
document.getElementById('result').innerText = res[0]; |
|||
}); |
|||
} |
|||
|
|||
</script> |
|||
</head> |
|||
<body> |
|||
<h1>contract</h1> |
|||
<div id="source"></div> |
|||
<div id='create'> |
|||
<button type="button" onClick="createExampleContract();">create example contract</button> |
|||
</div> |
|||
<div id='call' style='visibility: hidden;'> |
|||
<input type="number" id="value" onkeyup='callExampleContract()'></input> |
|||
</div> |
|||
<div id="result"></div> |
|||
</body> |
|||
</html> |
|||
|
@ -0,0 +1,16 @@ |
|||
#!/usr/bin/env node
|
|||
|
|||
require('es6-promise').polyfill(); |
|||
|
|||
var web3 = require("../index.js"); |
|||
|
|||
web3.setProvider(new web3.providers.HttpRpcProvider('http://localhost:8080')); |
|||
|
|||
web3.eth.coinbase.then(function(result){ |
|||
console.log(result); |
|||
return web3.eth.balanceAt(result); |
|||
}).then(function(balance){ |
|||
console.log(web3.toDecimal(balance)); |
|||
}).catch(function(err){ |
|||
console.log(err); |
|||
}); |
@ -0,0 +1,104 @@ |
|||
#!/usr/bin/env node
|
|||
|
|||
'use strict'; |
|||
|
|||
var path = require('path'); |
|||
|
|||
var del = require('del'); |
|||
var gulp = require('gulp'); |
|||
var browserify = require('browserify'); |
|||
var jshint = require('gulp-jshint'); |
|||
var uglify = require('gulp-uglify'); |
|||
var rename = require('gulp-rename'); |
|||
var envify = require('envify/custom'); |
|||
var unreach = require('unreachable-branch-transform'); |
|||
var source = require('vinyl-source-stream'); |
|||
var exorcist = require('exorcist'); |
|||
var bower = require('bower'); |
|||
|
|||
var DEST = './dist/'; |
|||
|
|||
var build = function(src, dst, ugly) { |
|||
var result = browserify({ |
|||
debug: true, |
|||
insert_global_vars: false, |
|||
detectGlobals: false, |
|||
bundleExternal: false |
|||
}) |
|||
.require('./' + src + '.js', {expose: 'web3'}) |
|||
.add('./' + src + '.js') |
|||
.transform('envify', { |
|||
NODE_ENV: 'build' |
|||
}) |
|||
.transform('unreachable-branch-transform'); |
|||
|
|||
if (ugly) { |
|||
result = result.transform('uglifyify', { |
|||
mangle: false, |
|||
compress: { |
|||
dead_code: false, |
|||
conditionals: true, |
|||
unused: false, |
|||
hoist_funs: true, |
|||
hoist_vars: true, |
|||
negate_iife: false |
|||
}, |
|||
beautify: true, |
|||
warnings: true |
|||
}); |
|||
} |
|||
|
|||
return result.bundle() |
|||
.pipe(exorcist(path.join( DEST, dst + '.js.map'))) |
|||
.pipe(source(dst + '.js')) |
|||
.pipe(gulp.dest( DEST )); |
|||
}; |
|||
|
|||
var uglifyFile = function(file) { |
|||
return gulp.src( DEST + file + '.js') |
|||
.pipe(uglify()) |
|||
.pipe(rename(file + '.min.js')) |
|||
.pipe(gulp.dest( DEST )); |
|||
}; |
|||
|
|||
gulp.task('bower', function(cb){ |
|||
bower.commands.install().on('end', function (installed){ |
|||
console.log(installed); |
|||
cb(); |
|||
}); |
|||
}); |
|||
|
|||
gulp.task('clean', ['lint'], function(cb) { |
|||
del([ DEST ], cb); |
|||
}); |
|||
|
|||
gulp.task('lint', function(){ |
|||
return gulp.src(['./*.js', './lib/*.js']) |
|||
.pipe(jshint()) |
|||
.pipe(jshint.reporter('default')); |
|||
}); |
|||
|
|||
gulp.task('build', ['clean'], function () { |
|||
return build('index', 'ethereum', true); |
|||
}); |
|||
|
|||
gulp.task('buildDev', ['clean'], function () { |
|||
return build('index', 'ethereum', false); |
|||
}); |
|||
|
|||
gulp.task('uglify', ['build'], function(){ |
|||
return uglifyFile('ethereum'); |
|||
}); |
|||
|
|||
gulp.task('uglify', ['buildDev'], function(){ |
|||
return uglifyFile('ethereum'); |
|||
}); |
|||
|
|||
gulp.task('watch', function() { |
|||
gulp.watch(['./lib/*.js'], ['lint', 'prepare', 'build']); |
|||
}); |
|||
|
|||
gulp.task('release', ['bower', 'lint', 'build', 'uglify']); |
|||
gulp.task('dev', ['bower', 'lint', 'buildDev', 'uglify']); |
|||
gulp.task('default', ['dev']); |
|||
|
@ -0,0 +1,8 @@ |
|||
var web3 = require('./lib/main'); |
|||
web3.providers.WebSocketProvider = require('./lib/websocket'); |
|||
web3.providers.HttpRpcProvider = require('./lib/httprpc'); |
|||
web3.providers.QtProvider = require('./lib/qt'); |
|||
web3.providers.AutoProvider = require('./lib/autoprovider'); |
|||
web3.contract = require('./lib/contract'); |
|||
|
|||
module.exports = web3; |
@ -0,0 +1,5 @@ |
|||
var web3 = require('./lib/main'); |
|||
web3.providers.QtProvider = require('./lib/qt'); |
|||
web3.contract = require('./lib/contract'); |
|||
|
|||
module.exports = web3; |
@ -0,0 +1,265 @@ |
|||
/* |
|||
This file is part of ethereum.js. |
|||
|
|||
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. |
|||
|
|||
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. |
|||
|
|||
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/>.
|
|||
*/ |
|||
/** @file abi.js |
|||
* @authors: |
|||
* Marek Kotewicz <marek@ethdev.com> |
|||
* Gav Wood <g@ethdev.com> |
|||
* @date 2014 |
|||
*/ |
|||
|
|||
// TODO: is these line is supposed to be here?
|
|||
if (process.env.NODE_ENV !== 'build') { |
|||
var web3 = require('./web3'); // jshint ignore:line
|
|||
} |
|||
|
|||
// 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; |
|||
for (; i < array.length && !end; i++) { |
|||
end = callback(array[i]); |
|||
} |
|||
return end ? i - 1 : -1; |
|||
}; |
|||
|
|||
var findMethodIndex = function (json, methodName) { |
|||
return findIndex(json, function (method) { |
|||
return method.name === methodName; |
|||
}); |
|||
}; |
|||
|
|||
var padLeft = function (string, chars) { |
|||
return new Array(chars - string.length + 1).join("0") + string; |
|||
}; |
|||
|
|||
var calcBitPadding = function (type, expected) { |
|||
var value = type.slice(expected.length); |
|||
if (value === "") { |
|||
return 32; |
|||
} |
|||
return parseInt(value) / 8; |
|||
}; |
|||
|
|||
var calcBytePadding = function (type, expected) { |
|||
var value = type.slice(expected.length); |
|||
if (value === "") { |
|||
return 32; |
|||
} |
|||
return parseInt(value); |
|||
}; |
|||
|
|||
var calcRealPadding = function (type, expected) { |
|||
var value = type.slice(expected.length); |
|||
if (value === "") { |
|||
return 32; |
|||
} |
|||
var sizes = value.split('x'); |
|||
for (var padding = 0, i = 0; i < sizes; i++) { |
|||
padding += (sizes[i] / 8); |
|||
} |
|||
return padding; |
|||
}; |
|||
|
|||
var setupInputTypes = function () { |
|||
|
|||
var prefixedType = function (prefix, calcPadding) { |
|||
return function (type, value) { |
|||
var expected = prefix; |
|||
if (type.indexOf(expected) !== 0) { |
|||
return false; |
|||
} |
|||
|
|||
var padding = calcPadding(type, expected); |
|||
if (typeof value === "number") |
|||
value = value.toString(16); |
|||
else if (typeof value === "string") |
|||
value = web3.toHex(value); |
|||
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 padLeft(formatter ? formatter(value) : value, padding * 2); |
|||
}; |
|||
}; |
|||
|
|||
var formatBool = function (value) { |
|||
return value ? '0x1' : '0x0'; |
|||
}; |
|||
|
|||
return [ |
|||
prefixedType('uint', calcBitPadding), |
|||
prefixedType('int', calcBitPadding), |
|||
prefixedType('hash', calcBitPadding), |
|||
prefixedType('string', calcBytePadding), |
|||
prefixedType('real', calcRealPadding), |
|||
prefixedType('ureal', calcRealPadding), |
|||
namedType('address', 20), |
|||
namedType('bool', 1, formatBool), |
|||
]; |
|||
}; |
|||
|
|||
var inputTypes = setupInputTypes(); |
|||
|
|||
var toAbiInput = function (json, methodName, params) { |
|||
var bytes = ""; |
|||
var index = findMethodIndex(json, methodName); |
|||
|
|||
if (index === -1) { |
|||
return; |
|||
} |
|||
|
|||
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++) { |
|||
found = inputTypes[j](method.inputs[i].type, params[i]); |
|||
} |
|||
if (!found) { |
|||
console.error('unsupported json type: ' + method.inputs[i].type); |
|||
} |
|||
bytes += found; |
|||
} |
|||
return bytes; |
|||
}; |
|||
|
|||
var setupOutputTypes = function () { |
|||
|
|||
var prefixedType = function (prefix, calcPadding) { |
|||
return function (type) { |
|||
var expected = prefix; |
|||
if (type.indexOf(expected) !== 0) { |
|||
return -1; |
|||
} |
|||
|
|||
var padding = calcPadding(type, expected); |
|||
return padding * 2; |
|||
}; |
|||
}; |
|||
|
|||
var namedType = function (name, padding) { |
|||
return function (type) { |
|||
return name === type ? padding * 2 : -1; |
|||
}; |
|||
}; |
|||
|
|||
var formatInt = function (value) { |
|||
return value.length <= 8 ? +parseInt(value, 16) : hexToDec(value); |
|||
}; |
|||
|
|||
var formatHash = function (value) { |
|||
return "0x" + value; |
|||
}; |
|||
|
|||
var formatBool = function (value) { |
|||
return value === '1' ? true : false; |
|||
}; |
|||
|
|||
var formatString = function (value) { |
|||
return web3.toAscii(value); |
|||
}; |
|||
|
|||
return [ |
|||
{ padding: prefixedType('uint', calcBitPadding), format: formatInt }, |
|||
{ padding: prefixedType('int', calcBitPadding), format: formatInt }, |
|||
{ padding: prefixedType('hash', calcBitPadding), format: formatHash }, |
|||
{ padding: prefixedType('string', calcBytePadding), format: formatString }, |
|||
{ padding: prefixedType('real', calcRealPadding), format: formatInt }, |
|||
{ padding: prefixedType('ureal', calcRealPadding), format: formatInt }, |
|||
{ padding: namedType('address', 20) }, |
|||
{ padding: namedType('bool', 1), format: formatBool } |
|||
]; |
|||
}; |
|||
|
|||
var outputTypes = setupOutputTypes(); |
|||
|
|||
var fromAbiOutput = function (json, methodName, output) { |
|||
var index = findMethodIndex(json, methodName); |
|||
|
|||
if (index === -1) { |
|||
return; |
|||
} |
|||
|
|||
output = output.slice(2); |
|||
|
|||
var result = []; |
|||
var method = json[index]; |
|||
for (var i = 0; i < method.outputs.length; i++) { |
|||
var padding = -1; |
|||
for (var j = 0; j < outputTypes.length && padding === -1; j++) { |
|||
padding = outputTypes[j].padding(method.outputs[i].type); |
|||
} |
|||
|
|||
if (padding === -1) { |
|||
// not found output parsing
|
|||
continue; |
|||
} |
|||
var res = output.slice(0, padding); |
|||
var formatter = outputTypes[j - 1].format; |
|||
result.push(formatter ? formatter(res) : ("0x" + res)); |
|||
output = output.slice(padding); |
|||
} |
|||
|
|||
return result; |
|||
}; |
|||
|
|||
var inputParser = function (json) { |
|||
var parser = {}; |
|||
json.forEach(function (method) { |
|||
parser[method.name] = function () { |
|||
var params = Array.prototype.slice.call(arguments); |
|||
return toAbiInput(json, method.name, params); |
|||
}; |
|||
}); |
|||
|
|||
return parser; |
|||
}; |
|||
|
|||
var outputParser = function (json) { |
|||
var parser = {}; |
|||
json.forEach(function (method) { |
|||
parser[method.name] = function (output) { |
|||
return fromAbiOutput(json, method.name, output); |
|||
}; |
|||
}); |
|||
|
|||
return parser; |
|||
}; |
|||
|
|||
module.exports = { |
|||
inputParser: inputParser, |
|||
outputParser: outputParser |
|||
}; |
@ -0,0 +1,102 @@ |
|||
/* |
|||
This file is part of ethereum.js. |
|||
|
|||
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. |
|||
|
|||
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. |
|||
|
|||
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/>.
|
|||
*/ |
|||
/** @file autoprovider.js |
|||
* @authors: |
|||
* Marek Kotewicz <marek@ethdev.com> |
|||
* Marian Oancea <marian@ethdev.com> |
|||
* @date 2014 |
|||
*/ |
|||
|
|||
/* |
|||
* @brief if qt object is available, uses QtProvider, |
|||
* if not tries to connect over websockets |
|||
* if it fails, it uses HttpRpcProvider |
|||
*/ |
|||
|
|||
// TODO: is these line is supposed to be here?
|
|||
if (process.env.NODE_ENV !== 'build') { |
|||
var WebSocket = require('ws'); // jshint ignore:line
|
|||
var web3 = require('./main.js'); // jshint ignore:line
|
|||
} |
|||
|
|||
var AutoProvider = function (userOptions) { |
|||
if (web3.haveProvider()) { |
|||
return; |
|||
} |
|||
|
|||
// before we determine what provider we are, we have to cache request
|
|||
this.sendQueue = []; |
|||
this.onmessageQueue = []; |
|||
|
|||
if (navigator.qt) { |
|||
this.provider = new web3.providers.QtProvider(); |
|||
return; |
|||
} |
|||
|
|||
userOptions = userOptions || {}; |
|||
var options = { |
|||
httprpc: userOptions.httprpc || 'http://localhost:8080', |
|||
websockets: userOptions.websockets || 'ws://localhost:40404/eth' |
|||
}; |
|||
|
|||
var self = this; |
|||
var closeWithSuccess = function (success) { |
|||
ws.close(); |
|||
if (success) { |
|||
self.provider = new web3.providers.WebSocketProvider(options.websockets); |
|||
} else { |
|||
self.provider = new web3.providers.HttpRpcProvider(options.httprpc); |
|||
self.poll = self.provider.poll.bind(self.provider); |
|||
} |
|||
self.sendQueue.forEach(function (payload) { |
|||
self.provider(payload); |
|||
}); |
|||
self.onmessageQueue.forEach(function (handler) { |
|||
self.provider.onmessage = handler; |
|||
}); |
|||
}; |
|||
|
|||
var ws = new WebSocket(options.websockets); |
|||
|
|||
ws.onopen = function() { |
|||
closeWithSuccess(true); |
|||
}; |
|||
|
|||
ws.onerror = function() { |
|||
closeWithSuccess(false); |
|||
}; |
|||
}; |
|||
|
|||
AutoProvider.prototype.send = function (payload) { |
|||
if (this.provider) { |
|||
this.provider.send(payload); |
|||
return; |
|||
} |
|||
this.sendQueue.push(payload); |
|||
}; |
|||
|
|||
Object.defineProperty(AutoProvider.prototype, 'onmessage', { |
|||
set: function (handler) { |
|||
if (this.provider) { |
|||
this.provider.onmessage = handler; |
|||
return; |
|||
} |
|||
this.onmessageQueue.push(handler); |
|||
} |
|||
}); |
|||
|
|||
module.exports = AutoProvider; |
@ -0,0 +1,65 @@ |
|||
/* |
|||
This file is part of ethereum.js. |
|||
|
|||
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. |
|||
|
|||
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. |
|||
|
|||
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/>.
|
|||
*/ |
|||
/** @file contract.js |
|||
* @authors: |
|||
* Marek Kotewicz <marek@ethdev.com> |
|||
* @date 2014 |
|||
*/ |
|||
|
|||
// TODO: is these line is supposed to be here?
|
|||
if (process.env.NODE_ENV !== 'build') { |
|||
var web3 = require('./web3'); // jshint ignore:line
|
|||
} |
|||
|
|||
var abi = require('./abi'); |
|||
|
|||
var contract = function (address, desc) { |
|||
var inputParser = abi.inputParser(desc); |
|||
var outputParser = abi.outputParser(desc); |
|||
|
|||
var contract = {}; |
|||
|
|||
desc.forEach(function (method) { |
|||
contract[method.name] = function () { |
|||
var params = Array.prototype.slice.call(arguments); |
|||
var parsed = inputParser[method.name].apply(null, params); |
|||
|
|||
var onSuccess = function (result) { |
|||
return outputParser[method.name](result); |
|||
}; |
|||
|
|||
return { |
|||
call: function (extra) { |
|||
extra = extra || {}; |
|||
extra.to = address; |
|||
extra.data = parsed; |
|||
return web3.eth.call(extra).then(onSuccess); |
|||
}, |
|||
transact: function (extra) { |
|||
extra = extra || {}; |
|||
extra.to = address; |
|||
extra.data = parsed; |
|||
return web3.eth.transact(extra).then(onSuccess); |
|||
} |
|||
}; |
|||
}; |
|||
}); |
|||
|
|||
return contract; |
|||
}; |
|||
|
|||
module.exports = contract; |
@ -0,0 +1,94 @@ |
|||
/* |
|||
This file is part of ethereum.js. |
|||
|
|||
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. |
|||
|
|||
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. |
|||
|
|||
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/>.
|
|||
*/ |
|||
/** @file httprpc.js |
|||
* @authors: |
|||
* Marek Kotewicz <marek@ethdev.com> |
|||
* Marian Oancea <marian@ethdev.com> |
|||
* @date 2014 |
|||
*/ |
|||
|
|||
// TODO: is these line is supposed to be here?
|
|||
if (process.env.NODE_ENV !== 'build') { |
|||
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest; // jshint ignore:line
|
|||
} |
|||
|
|||
var HttpRpcProvider = function (host) { |
|||
this.handlers = []; |
|||
this.host = host; |
|||
}; |
|||
|
|||
function formatJsonRpcObject(object) { |
|||
return { |
|||
jsonrpc: '2.0', |
|||
method: object.call, |
|||
params: object.args, |
|||
id: object._id |
|||
}; |
|||
} |
|||
|
|||
function formatJsonRpcMessage(message) { |
|||
var object = JSON.parse(message); |
|||
|
|||
return { |
|||
_id: object.id, |
|||
data: object.result, |
|||
error: object.error |
|||
}; |
|||
} |
|||
|
|||
HttpRpcProvider.prototype.sendRequest = function (payload, cb) { |
|||
var data = formatJsonRpcObject(payload); |
|||
|
|||
var request = new XMLHttpRequest(); |
|||
request.open("POST", this.host, true); |
|||
request.send(JSON.stringify(data)); |
|||
request.onreadystatechange = function () { |
|||
if (request.readyState === 4 && cb) { |
|||
cb(request); |
|||
} |
|||
}; |
|||
}; |
|||
|
|||
HttpRpcProvider.prototype.send = function (payload) { |
|||
var self = this; |
|||
this.sendRequest(payload, function (request) { |
|||
self.handlers.forEach(function (handler) { |
|||
handler.call(self, formatJsonRpcMessage(request.responseText)); |
|||
}); |
|||
}); |
|||
}; |
|||
|
|||
HttpRpcProvider.prototype.poll = function (payload, id) { |
|||
var self = this; |
|||
this.sendRequest(payload, function (request) { |
|||
var parsed = JSON.parse(request.responseText); |
|||
if (parsed.error || (parsed.result instanceof Array ? parsed.result.length === 0 : !parsed.result)) { |
|||
return; |
|||
} |
|||
self.handlers.forEach(function (handler) { |
|||
handler.call(self, {_event: payload.call, _id: id, data: parsed.result}); |
|||
}); |
|||
}); |
|||
}; |
|||
|
|||
Object.defineProperty(HttpRpcProvider.prototype, "onmessage", { |
|||
set: function (handler) { |
|||
this.handlers.push(handler); |
|||
} |
|||
}); |
|||
|
|||
module.exports = HttpRpcProvider; |
@ -0,0 +1,508 @@ |
|||
/* |
|||
This file is part of ethereum.js. |
|||
|
|||
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. |
|||
|
|||
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. |
|||
|
|||
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/>.
|
|||
*/ |
|||
/** @file main.js |
|||
* @authors: |
|||
* Jeffrey Wilcke <jeff@ethdev.com> |
|||
* Marek Kotewicz <marek@ethdev.com> |
|||
* Marian Oancea <marian@ethdev.com> |
|||
* Gav Wood <g@ethdev.com> |
|||
* @date 2014 |
|||
*/ |
|||
|
|||
function flattenPromise (obj) { |
|||
if (obj instanceof Promise) { |
|||
return Promise.resolve(obj); |
|||
} |
|||
|
|||
if (obj instanceof Array) { |
|||
return new Promise(function (resolve) { |
|||
var promises = obj.map(function (o) { |
|||
return flattenPromise(o); |
|||
}); |
|||
|
|||
return Promise.all(promises).then(function (res) { |
|||
for (var i = 0; i < obj.length; i++) { |
|||
obj[i] = res[i]; |
|||
} |
|||
resolve(obj); |
|||
}); |
|||
}); |
|||
} |
|||
|
|||
if (obj instanceof Object) { |
|||
return new Promise(function (resolve) { |
|||
var keys = Object.keys(obj); |
|||
var promises = keys.map(function (key) { |
|||
return flattenPromise(obj[key]); |
|||
}); |
|||
|
|||
return Promise.all(promises).then(function (res) { |
|||
for (var i = 0; i < keys.length; i++) { |
|||
obj[keys[i]] = res[i]; |
|||
} |
|||
resolve(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'; |
|||
}; |
|||
|
|||
var uncleCall = function (args) { |
|||
return typeof args[0] === "string" ? 'eth_uncleByHash' : 'eth_uncleByNumber'; |
|||
}; |
|||
|
|||
var methods = [ |
|||
{ name: 'balanceAt', call: 'eth_balanceAt' }, |
|||
{ name: 'stateAt', call: 'eth_stateAt' }, |
|||
{ name: 'storageAt', call: 'eth_storageAt' }, |
|||
{ 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 }, |
|||
{ name: 'compilers', call: 'eth_compilers' }, |
|||
{ name: 'lll', call: 'eth_lll' }, |
|||
{ name: 'solidity', call: 'eth_solidity' }, |
|||
{ name: 'serpent', call: 'eth_serpent' }, |
|||
{ name: 'logs', call: 'eth_logs' } |
|||
]; |
|||
return methods; |
|||
}; |
|||
|
|||
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: 'account', getter: 'eth_account' }, |
|||
{ name: 'accounts', getter: 'eth_accounts' }, |
|||
{ name: 'peerCount', getter: 'eth_peerCount' }, |
|||
{ name: 'defaultBlock', getter: 'eth_defaultBlock', setter: 'eth_setDefaultBlock' }, |
|||
{ name: 'number', getter: 'eth_number'} |
|||
]; |
|||
}; |
|||
|
|||
var dbMethods = function () { |
|||
return [ |
|||
{ name: 'put', call: 'db_put' }, |
|||
{ name: 'get', call: 'db_get' }, |
|||
{ name: 'putString', call: 'db_putString' }, |
|||
{ name: 'getString', call: 'db_getString' } |
|||
]; |
|||
}; |
|||
|
|||
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' } |
|||
]; |
|||
}; |
|||
|
|||
var ethWatchMethods = function () { |
|||
var newFilter = function (args) { |
|||
return typeof args[0] === 'string' ? 'eth_newFilterString' : 'eth_newFilter'; |
|||
}; |
|||
|
|||
return [ |
|||
{ name: 'newFilter', call: newFilter }, |
|||
{ name: 'uninstallFilter', call: 'eth_uninstallFilter' }, |
|||
{ name: 'getMessages', call: 'eth_filterLogs' } |
|||
]; |
|||
}; |
|||
|
|||
var shhWatchMethods = function () { |
|||
return [ |
|||
{ name: 'newFilter', call: 'shh_newFilter' }, |
|||
{ name: 'uninstallFilter', call: 'shh_uninstallFilter' }, |
|||
{ name: 'getMessage', call: 'shh_getMessages' } |
|||
]; |
|||
}; |
|||
|
|||
var setupMethods = function (obj, methods) { |
|||
methods.forEach(function (method) { |
|||
obj[method.name] = function () { |
|||
return flattenPromise(Array.prototype.slice.call(arguments)).then(function (args) { |
|||
var call = typeof method.call === "function" ? method.call(args) : method.call; |
|||
return {call: call, args: args}; |
|||
}).then(function (request) { |
|||
return new Promise(function (resolve, reject) { |
|||
web3.provider.send(request, function (err, result) { |
|||
if (!err) { |
|||
resolve(result); |
|||
return; |
|||
} |
|||
reject(err); |
|||
}); |
|||
}); |
|||
}).catch(function(err) { |
|||
console.error(err); |
|||
}); |
|||
}; |
|||
}); |
|||
}; |
|||
|
|||
var setupProperties = function (obj, properties) { |
|||
properties.forEach(function (property) { |
|||
var proto = {}; |
|||
proto.get = function () { |
|||
return new Promise(function(resolve, reject) { |
|||
web3.provider.send({call: property.getter}, function(err, result) { |
|||
if (!err) { |
|||
resolve(result); |
|||
return; |
|||
} |
|||
reject(err); |
|||
}); |
|||
}); |
|||
}; |
|||
if (property.setter) { |
|||
proto.set = function (val) { |
|||
return flattenPromise([val]).then(function (args) { |
|||
return new Promise(function (resolve) { |
|||
web3.provider.send({call: property.setter, args: args}, function (err, result) { |
|||
if (!err) { |
|||
resolve(result); |
|||
return; |
|||
} |
|||
reject(err); |
|||
}); |
|||
}); |
|||
}).catch(function (err) { |
|||
console.error(err); |
|||
}); |
|||
}; |
|||
} |
|||
Object.defineProperty(obj, property.name, proto); |
|||
}); |
|||
}; |
|||
|
|||
// 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
|
|||
var str = ""; |
|||
var i = 0, l = hex.length; |
|||
if (hex.substring(0, 2) === '0x') |
|||
i = 2; |
|||
for(; i < l; i+=2) { |
|||
var code = hex.charCodeAt(i); |
|||
if(code === 0) { |
|||
break; |
|||
} |
|||
|
|||
str += String.fromCharCode(parseInt(hex.substr(i, 2), 16)); |
|||
} |
|||
|
|||
return str; |
|||
}, |
|||
|
|||
fromAscii: function(str, pad) { |
|||
pad = pad === undefined ? 32 : pad; |
|||
var hex = this.toHex(str); |
|||
while(hex.length < pad*2) |
|||
hex += "00"; |
|||
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); |
|||
var replaceFunction = function($0, $1, $2) { |
|||
return $1 + ',' + $2; |
|||
}; |
|||
|
|||
while (true) { |
|||
var o = s; |
|||
s = s.replace(/(\d)(\d\d\d[\.\,])/, replaceFunction); |
|||
if (o === s) |
|||
break; |
|||
} |
|||
return s + ' ' + units[unit]; |
|||
}, |
|||
|
|||
eth: { |
|||
prototype: Object(), // jshint ignore:line
|
|||
watch: function (params) { |
|||
return new Filter(params, ethWatch); |
|||
} |
|||
}, |
|||
|
|||
db: { |
|||
prototype: Object() // jshint ignore:line
|
|||
}, |
|||
|
|||
shh: { |
|||
prototype: Object(), // jshint ignore:line
|
|||
watch: function (params) { |
|||
return new Filter(params, shhWatch); |
|||
} |
|||
}, |
|||
|
|||
on: function(event, id, cb) { |
|||
if(web3._events[event] === undefined) { |
|||
web3._events[event] = {}; |
|||
} |
|||
|
|||
web3._events[event][id] = cb; |
|||
return this; |
|||
}, |
|||
|
|||
off: function(event, id) { |
|||
if(web3._events[event] !== undefined) { |
|||
delete web3._events[event][id]; |
|||
} |
|||
|
|||
return this; |
|||
}, |
|||
|
|||
trigger: function(event, id, data) { |
|||
var callbacks = web3._events[event]; |
|||
if (!callbacks || !callbacks[id]) { |
|||
return; |
|||
} |
|||
var cb = callbacks[id]; |
|||
cb(data); |
|||
} |
|||
}; |
|||
|
|||
setupMethods(web3, web3Methods()); |
|||
setupMethods(web3.eth, ethMethods()); |
|||
setupProperties(web3.eth, ethProperties()); |
|||
setupMethods(web3.db, dbMethods()); |
|||
setupMethods(web3.shh, shhMethods()); |
|||
|
|||
var ethWatch = { |
|||
changed: 'eth_changed' |
|||
}; |
|||
setupMethods(ethWatch, ethWatchMethods()); |
|||
var shhWatch = { |
|||
changed: 'shh_changed' |
|||
}; |
|||
setupMethods(shhWatch, shhWatchMethods()); |
|||
|
|||
var ProviderManager = function() { |
|||
this.queued = []; |
|||
this.polls = []; |
|||
this.ready = false; |
|||
this.provider = undefined; |
|||
this.id = 1; |
|||
|
|||
var self = this; |
|||
var poll = function () { |
|||
if (self.provider && self.provider.poll) { |
|||
self.polls.forEach(function (data) { |
|||
data.data._id = self.id; |
|||
self.id++; |
|||
self.provider.poll(data.data, data.id); |
|||
}); |
|||
} |
|||
setTimeout(poll, 12000); |
|||
}; |
|||
poll(); |
|||
}; |
|||
|
|||
ProviderManager.prototype.send = function(data, cb) { |
|||
data._id = this.id; |
|||
if (cb) { |
|||
web3._callbacks[data._id] = cb; |
|||
} |
|||
|
|||
data.args = data.args || []; |
|||
this.id++; |
|||
|
|||
if(this.provider !== undefined) { |
|||
this.provider.send(data); |
|||
} else { |
|||
console.warn("provider is not set"); |
|||
this.queued.push(data); |
|||
} |
|||
}; |
|||
|
|||
ProviderManager.prototype.set = function(provider) { |
|||
if(this.provider !== undefined && this.provider.unload !== undefined) { |
|||
this.provider.unload(); |
|||
} |
|||
|
|||
this.provider = provider; |
|||
this.ready = true; |
|||
}; |
|||
|
|||
ProviderManager.prototype.sendQueued = function() { |
|||
for(var i = 0; this.queued.length; i++) { |
|||
// Resend
|
|||
this.send(this.queued[i]); |
|||
} |
|||
}; |
|||
|
|||
ProviderManager.prototype.installed = function() { |
|||
return this.provider !== undefined; |
|||
}; |
|||
|
|||
ProviderManager.prototype.startPolling = function (data, pollId) { |
|||
if (!this.provider || !this.provider.poll) { |
|||
return; |
|||
} |
|||
this.polls.push({data: data, id: pollId}); |
|||
}; |
|||
|
|||
ProviderManager.prototype.stopPolling = function (pollId) { |
|||
for (var i = this.polls.length; i--;) { |
|||
var poll = this.polls[i]; |
|||
if (poll.id === pollId) { |
|||
this.polls.splice(i, 1); |
|||
} |
|||
} |
|||
}; |
|||
|
|||
web3.provider = new ProviderManager(); |
|||
|
|||
web3.setProvider = function(provider) { |
|||
provider.onmessage = messageHandler; |
|||
web3.provider.set(provider); |
|||
web3.provider.sendQueued(); |
|||
}; |
|||
|
|||
web3.haveProvider = function() { |
|||
return !!web3.provider.provider; |
|||
}; |
|||
|
|||
var Filter = function(options, impl) { |
|||
this.impl = impl; |
|||
this.callbacks = []; |
|||
|
|||
var self = this; |
|||
this.promise = impl.newFilter(options); |
|||
this.promise.then(function (id) { |
|||
self.id = id; |
|||
web3.on(impl.changed, id, self.trigger.bind(self)); |
|||
web3.provider.startPolling({call: impl.changed, args: [id]}, id); |
|||
}); |
|||
}; |
|||
|
|||
Filter.prototype.arrived = function(callback) { |
|||
this.changed(callback); |
|||
}; |
|||
|
|||
Filter.prototype.changed = function(callback) { |
|||
var self = this; |
|||
this.promise.then(function(id) { |
|||
self.callbacks.push(callback); |
|||
}); |
|||
}; |
|||
|
|||
Filter.prototype.trigger = function(messages) { |
|||
for(var i = 0; i < this.callbacks.length; i++) { |
|||
this.callbacks[i].call(this, messages); |
|||
} |
|||
}; |
|||
|
|||
Filter.prototype.uninstall = function() { |
|||
var self = this; |
|||
this.promise.then(function (id) { |
|||
self.impl.uninstallFilter(id); |
|||
web3.provider.stopPolling(id); |
|||
web3.off(impl.changed, id); |
|||
}); |
|||
}; |
|||
|
|||
Filter.prototype.messages = function() { |
|||
var self = this; |
|||
return this.promise.then(function (id) { |
|||
return self.impl.getMessages(id); |
|||
}); |
|||
}; |
|||
|
|||
Filter.prototype.logs = function () { |
|||
return this.messages(); |
|||
}; |
|||
|
|||
function messageHandler(data) { |
|||
if(data._event !== undefined) { |
|||
web3.trigger(data._event, data._id, data.data); |
|||
return; |
|||
} |
|||
|
|||
if(data._id) { |
|||
var cb = web3._callbacks[data._id]; |
|||
if (cb) { |
|||
cb.call(this, data.error, data.data); |
|||
delete web3._callbacks[data._id]; |
|||
} |
|||
} |
|||
} |
|||
|
|||
module.exports = web3; |
@ -0,0 +1,45 @@ |
|||
/* |
|||
This file is part of ethereum.js. |
|||
|
|||
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. |
|||
|
|||
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. |
|||
|
|||
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/>.
|
|||
*/ |
|||
/** @file qt.js |
|||
* @authors: |
|||
* Jeffrey Wilcke <jeff@ethdev.com> |
|||
* Marek Kotewicz <marek@ethdev.com> |
|||
* @date 2014 |
|||
*/ |
|||
|
|||
var QtProvider = function() { |
|||
this.handlers = []; |
|||
|
|||
var self = this; |
|||
navigator.qt.onmessage = function (message) { |
|||
self.handlers.forEach(function (handler) { |
|||
handler.call(self, JSON.parse(message.data)); |
|||
}); |
|||
}; |
|||
}; |
|||
|
|||
QtProvider.prototype.send = function(payload) { |
|||
navigator.qt.postMessage(JSON.stringify(payload)); |
|||
}; |
|||
|
|||
Object.defineProperty(QtProvider.prototype, "onmessage", { |
|||
set: function(handler) { |
|||
this.handlers.push(handler); |
|||
} |
|||
}); |
|||
|
|||
module.exports = QtProvider; |
@ -0,0 +1,77 @@ |
|||
/* |
|||
This file is part of ethereum.js. |
|||
|
|||
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. |
|||
|
|||
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. |
|||
|
|||
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/>.
|
|||
*/ |
|||
/** @file websocket.js |
|||
* @authors: |
|||
* Jeffrey Wilcke <jeff@ethdev.com> |
|||
* Marek Kotewicz <marek@ethdev.com> |
|||
* Marian Oancea <marian@ethdev.com> |
|||
* @date 2014 |
|||
*/ |
|||
|
|||
// TODO: is these line is supposed to be here?
|
|||
if (process.env.NODE_ENV !== 'build') { |
|||
var WebSocket = require('ws'); // jshint ignore:line
|
|||
} |
|||
|
|||
var WebSocketProvider = function(host) { |
|||
// onmessage handlers
|
|||
this.handlers = []; |
|||
// queue will be filled with messages if send is invoked before the ws is ready
|
|||
this.queued = []; |
|||
this.ready = false; |
|||
|
|||
this.ws = new WebSocket(host); |
|||
|
|||
var self = this; |
|||
this.ws.onmessage = function(event) { |
|||
for(var i = 0; i < self.handlers.length; i++) { |
|||
self.handlers[i].call(self, JSON.parse(event.data), event); |
|||
} |
|||
}; |
|||
|
|||
this.ws.onopen = function() { |
|||
self.ready = true; |
|||
|
|||
for(var i = 0; i < self.queued.length; i++) { |
|||
// Resend
|
|||
self.send(self.queued[i]); |
|||
} |
|||
}; |
|||
}; |
|||
|
|||
WebSocketProvider.prototype.send = function(payload) { |
|||
if(this.ready) { |
|||
var data = JSON.stringify(payload); |
|||
|
|||
this.ws.send(data); |
|||
} else { |
|||
this.queued.push(payload); |
|||
} |
|||
}; |
|||
|
|||
WebSocketProvider.prototype.onMessage = function(handler) { |
|||
this.handlers.push(handler); |
|||
}; |
|||
|
|||
WebSocketProvider.prototype.unload = function() { |
|||
this.ws.close(); |
|||
}; |
|||
Object.defineProperty(WebSocketProvider.prototype, "onmessage", { |
|||
set: function(provider) { this.onMessage(provider); } |
|||
}); |
|||
|
|||
module.exports = WebSocketProvider; |
@ -0,0 +1,67 @@ |
|||
{ |
|||
"name": "ethereum.js", |
|||
"namespace": "ethereum", |
|||
"version": "0.0.5", |
|||
"description": "Ethereum Compatible JavaScript API", |
|||
"main": "./index.js", |
|||
"directories": { |
|||
"lib": "./lib" |
|||
}, |
|||
"dependencies": { |
|||
"es6-promise": "*", |
|||
"ws": "*", |
|||
"xmlhttprequest": "*" |
|||
}, |
|||
"devDependencies": { |
|||
"bower": ">=1.3.0", |
|||
"browserify": ">=6.0", |
|||
"del": ">=0.1.1", |
|||
"envify": "^3.0.0", |
|||
"exorcist": "^0.1.6", |
|||
"gulp": ">=3.4.0", |
|||
"gulp-jshint": ">=1.5.0", |
|||
"gulp-rename": ">=1.2.0", |
|||
"gulp-uglify": ">=1.0.0", |
|||
"jshint": ">=2.5.0", |
|||
"uglifyify": "^2.6.0", |
|||
"unreachable-branch-transform": "^0.1.0", |
|||
"vinyl-source-stream": "^1.0.0" |
|||
}, |
|||
"scripts": { |
|||
"build": "gulp", |
|||
"watch": "gulp watch", |
|||
"lint": "gulp lint" |
|||
}, |
|||
"repository": { |
|||
"type": "git", |
|||
"url": "https://github.com/ethereum/ethereum.js.git" |
|||
}, |
|||
"homepage": "https://github.com/ethereum/ethereum.js", |
|||
"bugs": { |
|||
"url": "https://github.com/ethereum/ethereum.js/issues" |
|||
}, |
|||
"keywords": [ |
|||
"ethereum", |
|||
"javascript", |
|||
"API" |
|||
], |
|||
"author": "ethdev.com", |
|||
"authors": [ |
|||
{ |
|||
"name": "Jeffery Wilcke", |
|||
"email": "jeff@ethdev.com", |
|||
"url": "https://github.com/obscuren" |
|||
}, |
|||
{ |
|||
"name": "Marek Kotewicz", |
|||
"email": "marek@ethdev.com", |
|||
"url": "https://github.com/debris" |
|||
}, |
|||
{ |
|||
"name": "Marian Oancea", |
|||
"email": "marian@ethdev.com", |
|||
"url": "https://github.com/cubedro" |
|||
} |
|||
], |
|||
"license": "LGPL-3.0" |
|||
} |
Loading…
Reference in new issue