Gav Wood
10 years ago
63 changed files with 6708 additions and 5304 deletions
File diff suppressed because it is too large
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,77 +0,0 @@ |
|||
<!doctype> |
|||
<html> |
|||
|
|||
<head> |
|||
<script type="text/javascript" src="../dist/web3.js"></script> |
|||
<script type="text/javascript"> |
|||
|
|||
var web3 = require('web3'); |
|||
web3.setProvider(new web3.providers.HttpProvider()); |
|||
|
|||
// solidity source code |
|||
var source = "" + |
|||
"contract test {\n" + |
|||
" function multiply(uint[] a) returns(uint d) {\n" + |
|||
" return a[0] + a[1];\n" + |
|||
" }\n" + |
|||
"}\n"; |
|||
|
|||
// contract description, this will be autogenerated somehow |
|||
var desc = [{ |
|||
"name": "multiply(uint256[])", |
|||
"type": "function", |
|||
"inputs": [ |
|||
{ |
|||
"name": "a", |
|||
"type": "uint256[]" |
|||
} |
|||
], |
|||
"outputs": [ |
|||
{ |
|||
"name": "d", |
|||
"type": "uint256" |
|||
} |
|||
] |
|||
}]; |
|||
|
|||
var myContract; |
|||
|
|||
function createExampleContract() { |
|||
// hide create button |
|||
document.getElementById('create').style.visibility = 'hidden'; |
|||
document.getElementById('source').innerText = source; |
|||
|
|||
// create contract |
|||
var address = web3.eth.sendTransaction({data: web3.eth.compile.solidity(source)}), |
|||
Contract = web3.eth.contract(desc); |
|||
|
|||
myContract = new Contract(address); |
|||
document.getElementById('call').style.visibility = 'visible'; |
|||
} |
|||
|
|||
function callExampleContract() { |
|||
// this should be generated by ethereum |
|||
var param = parseInt(document.getElementById('value').value); |
|||
var param2 = parseInt(document.getElementById('value2').value); |
|||
|
|||
// call the contract |
|||
var res = myContract.call().multiply([param, param2]); |
|||
document.getElementById('result').innerText = res.toString(10); |
|||
} |
|||
|
|||
</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> |
|||
<input type="number" id="value2" onkeyup='callExampleContract()'></input> |
|||
</div> |
|||
<div id="result"></div> |
|||
</body> |
|||
</html> |
|||
|
@ -1,119 +0,0 @@ |
|||
<!doctype> |
|||
<html> |
|||
<head> |
|||
<script type="text/javascript" src="../dist/web3.js"></script> |
|||
<script type="text/javascript"> |
|||
var web3 = require('web3'); |
|||
web3.setProvider(new web3.providers.HttpProvider('http://localhost:8080')); |
|||
|
|||
var desc = [{ |
|||
"type":"event", |
|||
"inputs": [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"hash256","indexed":false}], |
|||
"name":"Event" |
|||
}, { |
|||
"type":"event", |
|||
"inputs": [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"hash256","indexed":false}], |
|||
"name":"Event2" |
|||
}, { |
|||
"type":"function", |
|||
"inputs": [{"name":"a","type":"uint256"}], |
|||
"name":"foo", |
|||
"outputs": [] |
|||
}]; |
|||
|
|||
var address = '0x01'; |
|||
|
|||
var contract = web3.eth.contract(address, desc); |
|||
|
|||
function test1() { |
|||
// "{"topic":["0x83c9849c","0xc4d76332"],"address":"0x01"}" |
|||
web3.eth.watch(contract).changed(function (res) { |
|||
|
|||
}); |
|||
}; |
|||
|
|||
function test2() { |
|||
// "{"topic":["0x83c9849c"],"address":"0x01"}" |
|||
web3.eth.watch(contract.Event).changed(function (res) { |
|||
|
|||
}); |
|||
}; |
|||
|
|||
function test3() { |
|||
// "{"topic":["0x83c9849c"],"address":"0x01"}" |
|||
contract.Event().changed(function (res) { |
|||
|
|||
}); |
|||
}; |
|||
|
|||
function test4() { |
|||
// "{"topic":["0x83c9849c","0000000000000000000000000000000000000000000000000000000000000045"],"address":"0x01"}" |
|||
contract.Event({a: 69}).changed(function (res) { |
|||
|
|||
}); |
|||
}; |
|||
|
|||
function test5() { |
|||
// "{"topic":["0x83c9849c",["0000000000000000000000000000000000000000000000000000000000000045","000000000000000000000000000000000000000000000000000000000000002a"]],"address":"0x01"}" |
|||
contract.Event({a: [69, 42]}).changed(function (res) { |
|||
|
|||
}); |
|||
}; |
|||
|
|||
function test6() { |
|||
// "{"topic":["0x83c9849c","000000000000000000000000000000000000000000000000000000000000001e"],"max":100,"address":"0x01"}" |
|||
contract.Event({a: 30}, {max: 100}).changed(function (res) { |
|||
|
|||
}); |
|||
}; |
|||
|
|||
function test7() { |
|||
// "{"topic":["0x83c9849c","000000000000000000000000000000000000000000000000000000000000001e"],"address":"0x01"}" |
|||
web3.eth.watch(contract.Event, {a: 30}).changed(function (res) { |
|||
|
|||
}); |
|||
}; |
|||
|
|||
function test8() { |
|||
// "{"topic":["0x83c9849c","000000000000000000000000000000000000000000000000000000000000001e"],"max":100,"address":"0x01"}" |
|||
web3.eth.watch(contract.Event, {a: 30}, {max: 100}).changed(function (res) { |
|||
|
|||
}); |
|||
}; |
|||
|
|||
// not valid |
|||
// function testX() { |
|||
// web3.eth.watch([contract.Event, contract.Event2]).changed(function (res) { |
|||
// }); |
|||
// }; |
|||
|
|||
</script> |
|||
</head> |
|||
|
|||
<body> |
|||
<div> |
|||
<button type="button" onClick="test1();">test1</button> |
|||
</div> |
|||
<div> |
|||
<button type="button" onClick="test2();">test2</button> |
|||
</div> |
|||
<div> |
|||
<button type="button" onClick="test3();">test3</button> |
|||
</div> |
|||
<div> |
|||
<button type="button" onClick="test4();">test4</button> |
|||
</div> |
|||
<div> |
|||
<button type="button" onClick="test5();">test5</button> |
|||
</div> |
|||
<div> |
|||
<button type="button" onClick="test6();">test6</button> |
|||
</div> |
|||
<div> |
|||
<button type="button" onClick="test7();">test7</button> |
|||
</div> |
|||
<div> |
|||
<button type="button" onClick="test8();">test8</button> |
|||
</div> |
|||
</body> |
|||
</html> |
@ -0,0 +1,329 @@ |
|||
/* |
|||
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 coder.js |
|||
* @author Marek Kotewicz <marek@ethdev.com> |
|||
* @date 2015 |
|||
*/ |
|||
|
|||
var BigNumber = require('bignumber.js'); |
|||
var utils = require('../utils/utils'); |
|||
var f = require('./formatters'); |
|||
var SolidityParam = require('./param'); |
|||
|
|||
/** |
|||
* Should be used to check if a type is an array type |
|||
* |
|||
* @method isArrayType |
|||
* @param {String} type |
|||
* @return {Bool} true is the type is an array, otherwise false |
|||
*/ |
|||
var isArrayType = function (type) { |
|||
return type.slice(-2) === '[]'; |
|||
}; |
|||
|
|||
/** |
|||
* SolidityType prototype is used to encode/decode solidity params of certain type |
|||
*/ |
|||
var SolidityType = function (config) { |
|||
this._name = config.name; |
|||
this._match = config.match; |
|||
this._mode = config.mode; |
|||
this._inputFormatter = config.inputFormatter; |
|||
this._outputFormatter = config.outputFormatter; |
|||
}; |
|||
|
|||
/** |
|||
* Should be used to determine if this SolidityType do match given type |
|||
* |
|||
* @method isType |
|||
* @param {String} name |
|||
* @return {Bool} true if type match this SolidityType, otherwise false |
|||
*/ |
|||
SolidityType.prototype.isType = function (name) { |
|||
if (this._match === 'strict') { |
|||
return this._name === name || (name.indexOf(this._name) === 0 && name.slice(this._name.length) === '[]'); |
|||
} else if (this._match === 'prefix') { |
|||
// TODO better type detection!
|
|||
return name.indexOf(this._name) === 0; |
|||
} |
|||
}; |
|||
|
|||
/** |
|||
* Should be used to transform plain param to SolidityParam object |
|||
* |
|||
* @method formatInput |
|||
* @param {Object} param - plain object, or an array of objects |
|||
* @param {Bool} arrayType - true if a param should be encoded as an array |
|||
* @return {SolidityParam} encoded param wrapped in SolidityParam object |
|||
*/ |
|||
SolidityType.prototype.formatInput = function (param, arrayType) { |
|||
if (utils.isArray(param) && arrayType) { // TODO: should fail if this two are not the same
|
|||
var self = this; |
|||
return param.map(function (p) { |
|||
return self._inputFormatter(p); |
|||
}).reduce(function (acc, current) { |
|||
acc.appendArrayElement(current); |
|||
return acc; |
|||
}, new SolidityParam('', f.formatInputInt(param.length).value)); |
|||
} |
|||
return this._inputFormatter(param); |
|||
}; |
|||
|
|||
/** |
|||
* Should be used to transoform SolidityParam to plain param |
|||
* |
|||
* @method formatOutput |
|||
* @param {SolidityParam} byteArray |
|||
* @param {Bool} arrayType - true if a param should be decoded as an array |
|||
* @return {Object} plain decoded param |
|||
*/ |
|||
SolidityType.prototype.formatOutput = function (param, arrayType) { |
|||
if (arrayType) { |
|||
// let's assume, that we solidity will never return long arrays :P
|
|||
var result = []; |
|||
var length = new BigNumber(param.prefix, 16); |
|||
for (var i = 0; i < length * 64; i += 64) { |
|||
result.push(this._outputFormatter(new SolidityParam(param.suffix.slice(i, i + 64)))); |
|||
} |
|||
return result; |
|||
} |
|||
return this._outputFormatter(param); |
|||
}; |
|||
|
|||
/** |
|||
* Should be used to check if a type is variadic |
|||
* |
|||
* @method isVariadicType |
|||
* @param {String} type |
|||
* @returns {Bool} true if the type is variadic |
|||
*/ |
|||
SolidityType.prototype.isVariadicType = function (type) { |
|||
return isArrayType(type) || this._mode === 'bytes'; |
|||
}; |
|||
|
|||
/** |
|||
* Should be used to shift param from params group |
|||
* |
|||
* @method shiftParam |
|||
* @param {String} type |
|||
* @returns {SolidityParam} shifted param |
|||
*/ |
|||
SolidityType.prototype.shiftParam = function (type, param) { |
|||
if (this._mode === 'bytes') { |
|||
return param.shiftBytes(); |
|||
} else if (isArrayType(type)) { |
|||
var length = new BigNumber(param.prefix.slice(0, 64), 16); |
|||
return param.shiftArray(length); |
|||
} |
|||
return param.shiftValue(); |
|||
}; |
|||
|
|||
/** |
|||
* SolidityCoder prototype should be used to encode/decode solidity params of any type |
|||
*/ |
|||
var SolidityCoder = function (types) { |
|||
this._types = types; |
|||
}; |
|||
|
|||
/** |
|||
* This method should be used to transform type to SolidityType |
|||
* |
|||
* @method _requireType |
|||
* @param {String} type |
|||
* @returns {SolidityType} |
|||
* @throws {Error} throws if no matching type is found |
|||
*/ |
|||
SolidityCoder.prototype._requireType = function (type) { |
|||
var solidityType = this._types.filter(function (t) { |
|||
return t.isType(type); |
|||
})[0]; |
|||
|
|||
if (!solidityType) { |
|||
throw Error('invalid solidity type!: ' + type); |
|||
} |
|||
|
|||
return solidityType; |
|||
}; |
|||
|
|||
/** |
|||
* Should be used to transform plain bytes to SolidityParam object |
|||
* |
|||
* @method _bytesToParam |
|||
* @param {Array} types of params |
|||
* @param {String} bytes to be transformed to SolidityParam |
|||
* @return {SolidityParam} SolidityParam for this group of params |
|||
*/ |
|||
SolidityCoder.prototype._bytesToParam = function (types, bytes) { |
|||
var self = this; |
|||
var prefixTypes = types.reduce(function (acc, type) { |
|||
return self._requireType(type).isVariadicType(type) ? acc + 1 : acc; |
|||
}, 0); |
|||
var valueTypes = types.length - prefixTypes; |
|||
|
|||
var prefix = bytes.slice(0, prefixTypes * 64); |
|||
bytes = bytes.slice(prefixTypes * 64); |
|||
var value = bytes.slice(0, valueTypes * 64); |
|||
var suffix = bytes.slice(valueTypes * 64); |
|||
return new SolidityParam(value, prefix, suffix); |
|||
}; |
|||
|
|||
/** |
|||
* Should be used to transform plain param of given type to SolidityParam |
|||
* |
|||
* @method _formatInput |
|||
* @param {String} type of param |
|||
* @param {Object} plain param |
|||
* @return {SolidityParam} |
|||
*/ |
|||
SolidityCoder.prototype._formatInput = function (type, param) { |
|||
return this._requireType(type).formatInput(param, isArrayType(type)); |
|||
}; |
|||
|
|||
/** |
|||
* Should be used to encode plain param |
|||
* |
|||
* @method encodeParam |
|||
* @param {String} type |
|||
* @param {Object} plain param |
|||
* @return {String} encoded plain param |
|||
*/ |
|||
SolidityCoder.prototype.encodeParam = function (type, param) { |
|||
return this._formatInput(type, param).encode(); |
|||
}; |
|||
|
|||
/** |
|||
* Should be used to encode list of params |
|||
* |
|||
* @method encodeParams |
|||
* @param {Array} types |
|||
* @param {Array} params |
|||
* @return {String} encoded list of params |
|||
*/ |
|||
SolidityCoder.prototype.encodeParams = function (types, params) { |
|||
var self = this; |
|||
return types.map(function (type, index) { |
|||
return self._formatInput(type, params[index]); |
|||
}).reduce(function (acc, solidityParam) { |
|||
acc.append(solidityParam); |
|||
return acc; |
|||
}, new SolidityParam()).encode(); |
|||
}; |
|||
|
|||
/** |
|||
* Should be used to transform SolidityParam to plain param |
|||
* |
|||
* @method _formatOutput |
|||
* @param {String} type |
|||
* @param {SolidityParam} param |
|||
* @return {Object} plain param |
|||
*/ |
|||
SolidityCoder.prototype._formatOutput = function (type, param) { |
|||
return this._requireType(type).formatOutput(param, isArrayType(type)); |
|||
}; |
|||
|
|||
/** |
|||
* Should be used to decode bytes to plain param |
|||
* |
|||
* @method decodeParam |
|||
* @param {String} type |
|||
* @param {String} bytes |
|||
* @return {Object} plain param |
|||
*/ |
|||
SolidityCoder.prototype.decodeParam = function (type, bytes) { |
|||
return this._formatOutput(type, this._bytesToParam([type], bytes)); |
|||
}; |
|||
|
|||
/** |
|||
* Should be used to decode list of params |
|||
* |
|||
* @method decodeParam |
|||
* @param {Array} types |
|||
* @param {String} bytes |
|||
* @return {Array} array of plain params |
|||
*/ |
|||
SolidityCoder.prototype.decodeParams = function (types, bytes) { |
|||
var self = this; |
|||
var param = this._bytesToParam(types, bytes); |
|||
return types.map(function (type) { |
|||
var solidityType = self._requireType(type); |
|||
var p = solidityType.shiftParam(type, param); |
|||
return solidityType.formatOutput(p, isArrayType(type)); |
|||
}); |
|||
}; |
|||
|
|||
var coder = new SolidityCoder([ |
|||
new SolidityType({ |
|||
name: 'address', |
|||
match: 'strict', |
|||
mode: 'value', |
|||
inputFormatter: f.formatInputInt, |
|||
outputFormatter: f.formatOutputAddress |
|||
}), |
|||
new SolidityType({ |
|||
name: 'bool', |
|||
match: 'strict', |
|||
mode: 'value', |
|||
inputFormatter: f.formatInputBool, |
|||
outputFormatter: f.formatOutputBool |
|||
}), |
|||
new SolidityType({ |
|||
name: 'int', |
|||
match: 'prefix', |
|||
mode: 'value', |
|||
inputFormatter: f.formatInputInt, |
|||
outputFormatter: f.formatOutputInt, |
|||
}), |
|||
new SolidityType({ |
|||
name: 'uint', |
|||
match: 'prefix', |
|||
mode: 'value', |
|||
inputFormatter: f.formatInputInt, |
|||
outputFormatter: f.formatOutputUInt |
|||
}), |
|||
new SolidityType({ |
|||
name: 'bytes', |
|||
match: 'strict', |
|||
mode: 'bytes', |
|||
inputFormatter: f.formatInputDynamicBytes, |
|||
outputFormatter: f.formatOutputDynamicBytes |
|||
}), |
|||
new SolidityType({ |
|||
name: 'bytes', |
|||
match: 'prefix', |
|||
mode: 'value', |
|||
inputFormatter: f.formatInputBytes, |
|||
outputFormatter: f.formatOutputBytes |
|||
}), |
|||
new SolidityType({ |
|||
name: 'real', |
|||
match: 'prefix', |
|||
mode: 'value', |
|||
inputFormatter: f.formatInputReal, |
|||
outputFormatter: f.formatOutputReal |
|||
}), |
|||
new SolidityType({ |
|||
name: 'ureal', |
|||
match: 'prefix', |
|||
mode: 'value', |
|||
inputFormatter: f.formatInputReal, |
|||
outputFormatter: f.formatOutputUReal |
|||
}) |
|||
]); |
|||
|
|||
module.exports = coder; |
|||
|
@ -0,0 +1,105 @@ |
|||
/* |
|||
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 param.js |
|||
* @author Marek Kotewicz <marek@ethdev.com> |
|||
* @date 2015 |
|||
*/ |
|||
|
|||
/** |
|||
* SolidityParam object prototype. |
|||
* Should be used when encoding, decoding solidity bytes |
|||
*/ |
|||
var SolidityParam = function (value, prefix, suffix) { |
|||
this.prefix = prefix || ''; |
|||
this.value = value || ''; |
|||
this.suffix = suffix || ''; |
|||
}; |
|||
|
|||
/** |
|||
* This method should be used to encode two params one after another |
|||
* |
|||
* @method append |
|||
* @param {SolidityParam} param that it appended after this |
|||
*/ |
|||
SolidityParam.prototype.append = function (param) { |
|||
this.prefix += param.prefix; |
|||
this.value += param.value; |
|||
this.suffix += param.suffix; |
|||
}; |
|||
|
|||
/** |
|||
* This method should be used to encode next param in an array |
|||
* |
|||
* @method appendArrayElement |
|||
* @param {SolidityParam} param that is appended to an array |
|||
*/ |
|||
SolidityParam.prototype.appendArrayElement = function (param) { |
|||
this.suffix += param.value; |
|||
this.prefix += param.prefix; |
|||
// TODO: suffix not supported = it's required for nested arrays;
|
|||
}; |
|||
|
|||
/** |
|||
* This method should be used to create bytearrays from param |
|||
* |
|||
* @method encode |
|||
* @return {String} encoded param(s) |
|||
*/ |
|||
SolidityParam.prototype.encode = function () { |
|||
return this.prefix + this.value + this.suffix; |
|||
}; |
|||
|
|||
/** |
|||
* This method should be used to shift first param from group of params |
|||
* |
|||
* @method shiftValue |
|||
* @return {SolidityParam} first value param |
|||
*/ |
|||
SolidityParam.prototype.shiftValue = function () { |
|||
var value = this.value.slice(0, 64); |
|||
this.value = this.value.slice(64); |
|||
return new SolidityParam(value); |
|||
}; |
|||
|
|||
/** |
|||
* This method should be used to first bytes param from group of params |
|||
* |
|||
* @method shiftBytes |
|||
* @return {SolidityParam} first bytes param |
|||
*/ |
|||
SolidityParam.prototype.shiftBytes = function () { |
|||
return this.shiftArray(1); |
|||
}; |
|||
|
|||
/** |
|||
* This method should be used to shift an array from group of params |
|||
* |
|||
* @method shiftArray |
|||
* @param {Number} size of an array to shift |
|||
* @return {SolidityParam} first array param |
|||
*/ |
|||
SolidityParam.prototype.shiftArray = function (length) { |
|||
var prefix = this.prefix.slice(0, 64); |
|||
this.prefix = this.value.slice(64); |
|||
var suffix = this.suffix.slice(0, 64 * length); |
|||
this.suffix = this.suffix.slice(64 * length); |
|||
return new SolidityParam('', prefix, suffix); |
|||
}; |
|||
|
|||
module.exports = SolidityParam; |
|||
|
@ -1,77 +0,0 @@ |
|||
/* |
|||
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 types.js |
|||
* @authors: |
|||
* Marek Kotewicz <marek@ethdev.com> |
|||
* @date 2015 |
|||
*/ |
|||
|
|||
var f = require('./formatters'); |
|||
|
|||
/// @param expected type prefix (string)
|
|||
/// @returns function which checks if type has matching prefix. if yes, returns true, otherwise false
|
|||
var prefixedType = function (prefix) { |
|||
return function (type) { |
|||
return type.indexOf(prefix) === 0; |
|||
}; |
|||
}; |
|||
|
|||
/// @param expected type name (string)
|
|||
/// @returns function which checks if type is matching expected one. if yes, returns true, otherwise false
|
|||
var namedType = function (name) { |
|||
return function (type) { |
|||
return name === type; |
|||
}; |
|||
}; |
|||
|
|||
/// Setups input formatters for solidity types
|
|||
/// @returns an array of input formatters
|
|||
var inputTypes = function () { |
|||
|
|||
return [ |
|||
{ type: prefixedType('uint'), format: f.formatInputInt }, |
|||
{ type: prefixedType('int'), format: f.formatInputInt }, |
|||
{ type: prefixedType('bytes'), format: f.formatInputString }, |
|||
{ type: prefixedType('real'), format: f.formatInputReal }, |
|||
{ type: prefixedType('ureal'), format: f.formatInputReal }, |
|||
{ type: namedType('address'), format: f.formatInputInt }, |
|||
{ type: namedType('bool'), format: f.formatInputBool } |
|||
]; |
|||
}; |
|||
|
|||
/// Setups output formaters for solidity types
|
|||
/// @returns an array of output formatters
|
|||
var outputTypes = function () { |
|||
|
|||
return [ |
|||
{ type: prefixedType('uint'), format: f.formatOutputUInt }, |
|||
{ type: prefixedType('int'), format: f.formatOutputInt }, |
|||
{ type: prefixedType('bytes'), format: f.formatOutputString }, |
|||
{ type: prefixedType('real'), format: f.formatOutputReal }, |
|||
{ type: prefixedType('ureal'), format: f.formatOutputUReal }, |
|||
{ type: namedType('address'), format: f.formatOutputAddress }, |
|||
{ type: namedType('bool'), format: f.formatOutputBool } |
|||
]; |
|||
}; |
|||
|
|||
module.exports = { |
|||
prefixedType: prefixedType, |
|||
namedType: namedType, |
|||
inputTypes: inputTypes, |
|||
outputTypes: outputTypes |
|||
}; |
|||
|
@ -1,3 +1,3 @@ |
|||
{ |
|||
"version": "0.2.6" |
|||
"version": "0.3.3" |
|||
} |
|||
|
@ -0,0 +1,151 @@ |
|||
/* |
|||
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 function.js |
|||
* @author Marek Kotewicz <marek@ethdev.com> |
|||
* @date 2015 |
|||
*/ |
|||
|
|||
var web3 = require('../web3'); |
|||
var coder = require('../solidity/coder'); |
|||
var utils = require('../utils/utils'); |
|||
|
|||
/** |
|||
* This prototype should be used to call/sendTransaction to solidity functions |
|||
*/ |
|||
var SolidityFunction = function (json, address) { |
|||
this._inputTypes = json.inputs.map(function (i) { |
|||
return i.type; |
|||
}); |
|||
this._outputTypes = json.outputs.map(function (i) { |
|||
return i.type; |
|||
}); |
|||
this._constant = json.constant; |
|||
this._name = utils.transformToFullName(json); |
|||
this._address = address; |
|||
}; |
|||
|
|||
/** |
|||
* Should be used to create payload from arguments |
|||
* |
|||
* @method toPayload |
|||
* @param {...} solidity function params |
|||
* @param {Object} optional payload options |
|||
*/ |
|||
SolidityFunction.prototype.toPayload = function () { |
|||
var args = Array.prototype.slice.call(arguments); |
|||
var options = {}; |
|||
if (args.length > this._inputTypes.length && utils.isObject(args[args.length -1])) { |
|||
options = args.pop(); |
|||
} |
|||
options.to = this._address; |
|||
options.data = '0x' + this.signature() + coder.encodeParams(this._inputTypes, args); |
|||
return options; |
|||
}; |
|||
|
|||
/** |
|||
* Should be used to get function signature |
|||
* |
|||
* @method signature |
|||
* @return {String} function signature |
|||
*/ |
|||
SolidityFunction.prototype.signature = function () { |
|||
return web3.sha3(web3.fromAscii(this._name)).slice(2, 10); |
|||
}; |
|||
|
|||
/** |
|||
* Should be used to call function |
|||
* |
|||
* @method call |
|||
* @param {Object} options |
|||
* @return {String} output bytes |
|||
*/ |
|||
SolidityFunction.prototype.call = function () { |
|||
var payload = this.toPayload.apply(this, Array.prototype.slice.call(arguments)); |
|||
var output = web3.eth.call(payload); |
|||
output = output.length >= 2 ? output.slice(2) : output; |
|||
var result = coder.decodeParams(this._outputTypes, output); |
|||
return result.length === 1 ? result[0] : result; |
|||
}; |
|||
|
|||
/** |
|||
* Should be used to sendTransaction to solidity function |
|||
* |
|||
* @method sendTransaction |
|||
* @param {Object} options |
|||
*/ |
|||
SolidityFunction.prototype.sendTransaction = function () { |
|||
var payload = this.toPayload.apply(this, Array.prototype.slice.call(arguments)); |
|||
web3.eth.sendTransaction(payload); |
|||
}; |
|||
|
|||
/** |
|||
* Should be used to get function display name |
|||
* |
|||
* @method displayName |
|||
* @return {String} display name of the function |
|||
*/ |
|||
SolidityFunction.prototype.displayName = function () { |
|||
return utils.extractDisplayName(this._name); |
|||
}; |
|||
|
|||
/** |
|||
* Should be used to get function type name |
|||
* |
|||
* @method typeName |
|||
* @return {String} type name of the function |
|||
*/ |
|||
SolidityFunction.prototype.typeName = function () { |
|||
return utils.extractTypeName(this._name); |
|||
}; |
|||
|
|||
/** |
|||
* Should be called to execute function |
|||
* |
|||
* @method execute |
|||
*/ |
|||
SolidityFunction.prototype.execute = function () { |
|||
var transaction = !this._constant; |
|||
|
|||
// send transaction
|
|||
if (transaction) { |
|||
return this.sendTransaction.apply(this, Array.prototype.slice.call(arguments)); |
|||
} |
|||
|
|||
// call
|
|||
return this.call.apply(this, Array.prototype.slice.call(arguments)); |
|||
}; |
|||
|
|||
/** |
|||
* Should be called to attach function to contract |
|||
* |
|||
* @method attachToContract |
|||
* @param {Contract} |
|||
*/ |
|||
SolidityFunction.prototype.attachToContract = function (contract) { |
|||
var execute = this.execute.bind(this); |
|||
execute.call = this.call.bind(this); |
|||
execute.sendTransaction = this.sendTransaction.bind(this); |
|||
var displayName = this.displayName(); |
|||
if (!contract[displayName]) { |
|||
contract[displayName] = execute; |
|||
} |
|||
contract[displayName][this.typeName()] = execute; // circular!!!!
|
|||
}; |
|||
|
|||
module.exports = SolidityFunction; |
|||
|
@ -1,42 +0,0 @@ |
|||
/* |
|||
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 signature.js |
|||
* @authors: |
|||
* Marek Kotewicz <marek@ethdev.com> |
|||
* @date 2015 |
|||
*/ |
|||
|
|||
var web3 = require('../web3'); |
|||
var c = require('../utils/config'); |
|||
|
|||
/// @param function name for which we want to get signature
|
|||
/// @returns signature of function with given name
|
|||
var functionSignatureFromAscii = function (name) { |
|||
return web3.sha3(web3.fromAscii(name)).slice(0, 2 + c.ETH_SIGNATURE_LENGTH * 2); |
|||
}; |
|||
|
|||
/// @param event name for which we want to get signature
|
|||
/// @returns signature of event with given name
|
|||
var eventSignatureFromAscii = function (name) { |
|||
return web3.sha3(web3.fromAscii(name)); |
|||
}; |
|||
|
|||
module.exports = { |
|||
functionSignatureFromAscii: functionSignatureFromAscii, |
|||
eventSignatureFromAscii: eventSignatureFromAscii |
|||
}; |
|||
|
@ -1,7 +1,7 @@ |
|||
/* jshint ignore:start */ |
|||
|
|||
if(typeof web3 === 'undefined') { |
|||
web3 = require('ethereum.js'); |
|||
web3 = require('web3'); |
|||
BigNumber = require('bignumber.js'); |
|||
} |
|||
|
|||
|
@ -0,0 +1,68 @@ |
|||
var chai = require('chai'); |
|||
var assert = chai.assert; |
|||
var coder = require('../lib/solidity/coder'); |
|||
var BigNumber = require('bignumber.js'); |
|||
var bn = BigNumber; |
|||
|
|||
|
|||
describe('lib/solidity/coder', function () { |
|||
describe('decodeParam', function () { |
|||
var test = function (t) { |
|||
it('should turn ' + t.value + ' to ' + t.expected, function () { |
|||
assert.deepEqual(coder.decodeParam(t.type, t.value), t.expected); |
|||
}); |
|||
}; |
|||
|
|||
|
|||
test({ type: 'int', expected: new bn(1), value: '0000000000000000000000000000000000000000000000000000000000000001'}); |
|||
test({ type: 'int', expected: new bn(16), value: '0000000000000000000000000000000000000000000000000000000000000010'}); |
|||
test({ type: 'int', expected: new bn(-1), value: 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'}); |
|||
test({ type: 'int256', expected: new bn(1), value: '0000000000000000000000000000000000000000000000000000000000000001'}); |
|||
test({ type: 'int256', expected: new bn(16), value: '0000000000000000000000000000000000000000000000000000000000000010'}); |
|||
test({ type: 'int256', expected: new bn(-1), value: 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'}); |
|||
test({ type: 'bytes32', expected: 'gavofyork', value: '6761766f66796f726b0000000000000000000000000000000000000000000000'}); |
|||
test({ type: 'bytes', expected: 'gavofyork', value: '0000000000000000000000000000000000000000000000000000000000000009' + |
|||
'6761766f66796f726b0000000000000000000000000000000000000000000000'}); |
|||
test({ type: 'int[]', expected: [new bn(3)], value: '0000000000000000000000000000000000000000000000000000000000000001' + |
|||
'0000000000000000000000000000000000000000000000000000000000000003'}); |
|||
test({ type: 'int256[]', expected: [new bn(3)], value: '0000000000000000000000000000000000000000000000000000000000000001' + |
|||
'0000000000000000000000000000000000000000000000000000000000000003'}); |
|||
test({ type: 'int[]', expected: [new bn(1), new bn(2), new bn(3)], |
|||
value: '0000000000000000000000000000000000000000000000000000000000000003' + |
|||
'0000000000000000000000000000000000000000000000000000000000000001' + |
|||
'0000000000000000000000000000000000000000000000000000000000000002' + |
|||
'0000000000000000000000000000000000000000000000000000000000000003'}); |
|||
}); |
|||
}); |
|||
|
|||
describe('lib/solidity/coder', function () { |
|||
describe('decodeParams', function () { |
|||
var test = function (t) { |
|||
it('should turn ' + t.values + ' to ' + t.expected, function () { |
|||
assert.deepEqual(coder.decodeParams(t.types, t.values), t.expected); |
|||
}); |
|||
}; |
|||
|
|||
|
|||
test({ types: ['int'], expected: [new bn(1)], values: '0000000000000000000000000000000000000000000000000000000000000001'}); |
|||
test({ types: ['bytes32', 'int'], expected: ['gavofyork', new bn(5)], |
|||
values: '6761766f66796f726b0000000000000000000000000000000000000000000000' + |
|||
'0000000000000000000000000000000000000000000000000000000000000005'}); |
|||
test({ types: ['int', 'bytes32'], expected: [new bn(5), 'gavofyork'], |
|||
values: '0000000000000000000000000000000000000000000000000000000000000005' + |
|||
'6761766f66796f726b0000000000000000000000000000000000000000000000'}); |
|||
test({ types: ['int', 'bytes', 'int', 'int', 'int', 'int[]'], expected: [new bn(1), 'gavofyork', new bn(2), new bn(3), new bn(4), |
|||
[new bn(5), new bn(6), new bn(7)]], |
|||
values: '0000000000000000000000000000000000000000000000000000000000000009' + |
|||
'0000000000000000000000000000000000000000000000000000000000000003' + |
|||
'0000000000000000000000000000000000000000000000000000000000000001' + |
|||
'0000000000000000000000000000000000000000000000000000000000000002' + |
|||
'0000000000000000000000000000000000000000000000000000000000000003' + |
|||
'0000000000000000000000000000000000000000000000000000000000000004' + |
|||
'6761766f66796f726b0000000000000000000000000000000000000000000000' + |
|||
'0000000000000000000000000000000000000000000000000000000000000005' + |
|||
'0000000000000000000000000000000000000000000000000000000000000006' + |
|||
'0000000000000000000000000000000000000000000000000000000000000007'}); |
|||
}); |
|||
}); |
|||
|
@ -0,0 +1,91 @@ |
|||
var chai = require('chai'); |
|||
var assert = chai.assert; |
|||
var coder = require('../lib/solidity/coder'); |
|||
|
|||
|
|||
describe('lib/solidity/coder', function () { |
|||
describe('encodeParam', function () { |
|||
var test = function (t) { |
|||
it('should turn ' + t.value + ' to ' + t.expected, function () { |
|||
assert.equal(coder.encodeParam(t.type, t.value), t.expected); |
|||
}); |
|||
}; |
|||
|
|||
|
|||
test({ type: 'int', value: 1, expected: '0000000000000000000000000000000000000000000000000000000000000001'}); |
|||
test({ type: 'int', value: 16, expected: '0000000000000000000000000000000000000000000000000000000000000010'}); |
|||
test({ type: 'int', value: -1, expected: 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'}); |
|||
test({ type: 'int256', value: 1, expected: '0000000000000000000000000000000000000000000000000000000000000001'}); |
|||
test({ type: 'int256', value: 16, expected: '0000000000000000000000000000000000000000000000000000000000000010'}); |
|||
test({ type: 'int256', value: -1, expected: 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'}); |
|||
test({ type: 'bytes32', value: 'gavofyork', expected: '6761766f66796f726b0000000000000000000000000000000000000000000000'}); |
|||
test({ type: 'bytes', value: 'gavofyork', expected: '0000000000000000000000000000000000000000000000000000000000000009' + |
|||
'6761766f66796f726b0000000000000000000000000000000000000000000000'}); |
|||
test({ type: 'int[]', value: [3], expected: '0000000000000000000000000000000000000000000000000000000000000001' + |
|||
'0000000000000000000000000000000000000000000000000000000000000003'}); |
|||
test({ type: 'int256[]', value: [3], expected: '0000000000000000000000000000000000000000000000000000000000000001' + |
|||
'0000000000000000000000000000000000000000000000000000000000000003'}); |
|||
test({ type: 'int[]', value: [1,2,3], expected: '0000000000000000000000000000000000000000000000000000000000000003' + |
|||
'0000000000000000000000000000000000000000000000000000000000000001' + |
|||
'0000000000000000000000000000000000000000000000000000000000000002' + |
|||
'0000000000000000000000000000000000000000000000000000000000000003'}); |
|||
}); |
|||
}); |
|||
|
|||
|
|||
describe('lib/solidity/coder', function () { |
|||
describe('encodeParams', function () { |
|||
var test = function (t) { |
|||
it('should turn ' + t.values + ' to ' + t.expected, function () { |
|||
assert.equal(coder.encodeParams(t.types, t.values), t.expected); |
|||
}); |
|||
}; |
|||
|
|||
|
|||
test({ types: ['int'], values: [1], expected: '0000000000000000000000000000000000000000000000000000000000000001'}); |
|||
test({ types: ['int'], values: [16], expected: '0000000000000000000000000000000000000000000000000000000000000010'}); |
|||
test({ types: ['int'], values: [-1], expected: 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'}); |
|||
test({ types: ['int256'], values: [1], expected: '0000000000000000000000000000000000000000000000000000000000000001'}); |
|||
test({ types: ['int256'], values: [16], expected: '0000000000000000000000000000000000000000000000000000000000000010'}); |
|||
test({ types: ['int256'], values: [-1], expected: 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'}); |
|||
test({ types: ['bytes32'], values: ['gavofyork'], expected: '6761766f66796f726b0000000000000000000000000000000000000000000000'}); |
|||
test({ types: ['bytes'], values: ['gavofyork'], expected: '0000000000000000000000000000000000000000000000000000000000000009' + |
|||
'6761766f66796f726b0000000000000000000000000000000000000000000000'}); |
|||
test({ types: ['int[]'], values: [[3]], expected: '0000000000000000000000000000000000000000000000000000000000000001' + |
|||
'0000000000000000000000000000000000000000000000000000000000000003'}); |
|||
test({ types: ['int256[]'], values: [[3]], expected: '0000000000000000000000000000000000000000000000000000000000000001' + |
|||
'0000000000000000000000000000000000000000000000000000000000000003'}); |
|||
test({ types: ['int256[]'], values: [[1,2,3]], expected: '0000000000000000000000000000000000000000000000000000000000000003' + |
|||
'0000000000000000000000000000000000000000000000000000000000000001' + |
|||
'0000000000000000000000000000000000000000000000000000000000000002' + |
|||
'0000000000000000000000000000000000000000000000000000000000000003'}); |
|||
test({ types: ['bytes32', 'int'], values: ['gavofyork', 5], |
|||
expected: '6761766f66796f726b0000000000000000000000000000000000000000000000' + |
|||
'0000000000000000000000000000000000000000000000000000000000000005'}); |
|||
test({ types: ['int', 'bytes32'], values: [5, 'gavofyork'], |
|||
expected: '0000000000000000000000000000000000000000000000000000000000000005' + |
|||
'6761766f66796f726b0000000000000000000000000000000000000000000000'}); |
|||
test({ types: ['bytes', 'int'], values: ['gavofyork', 5], |
|||
expected: '0000000000000000000000000000000000000000000000000000000000000009' + |
|||
'0000000000000000000000000000000000000000000000000000000000000005' + |
|||
'6761766f66796f726b0000000000000000000000000000000000000000000000'}); |
|||
test({ types: ['int', 'bytes'], values: [5, 'gavofyork'], |
|||
expected: '0000000000000000000000000000000000000000000000000000000000000009' + |
|||
'0000000000000000000000000000000000000000000000000000000000000005' + |
|||
'6761766f66796f726b0000000000000000000000000000000000000000000000'}); |
|||
test({ types: ['int', 'bytes', 'int', 'int', 'int', 'int[]'], values: [1, 'gavofyork', 2, 3, 4, [5, 6, 7]], |
|||
expected: '0000000000000000000000000000000000000000000000000000000000000009' + |
|||
'0000000000000000000000000000000000000000000000000000000000000003' + |
|||
'0000000000000000000000000000000000000000000000000000000000000001' + |
|||
'0000000000000000000000000000000000000000000000000000000000000002' + |
|||
'0000000000000000000000000000000000000000000000000000000000000003' + |
|||
'0000000000000000000000000000000000000000000000000000000000000004' + |
|||
'6761766f66796f726b0000000000000000000000000000000000000000000000' + |
|||
'0000000000000000000000000000000000000000000000000000000000000005' + |
|||
'0000000000000000000000000000000000000000000000000000000000000006' + |
|||
'0000000000000000000000000000000000000000000000000000000000000007'}); |
|||
|
|||
}); |
|||
}); |
|||
|
|||
|
@ -0,0 +1,180 @@ |
|||
var chai = require('chai'); |
|||
var assert = chai.assert; |
|||
var BigNumber = require('bignumber.js'); |
|||
var SolidityEvent = require('../lib/web3/event'); |
|||
|
|||
var name = 'event1'; |
|||
var address = '0x1234567890123456789012345678901234567890'; |
|||
|
|||
var tests = [{ |
|||
abi: { |
|||
name: name, |
|||
inputs: [] |
|||
}, |
|||
data: { |
|||
logIndex: '0x1', |
|||
transactionIndex: '0x10', |
|||
transactionHash: '0x1234567890', |
|||
address: address, |
|||
blockHash: '0x1234567890', |
|||
blockNumber: '0x1' |
|||
}, |
|||
expected: { |
|||
event: name, |
|||
args: {}, |
|||
logIndex: 1, |
|||
transactionIndex: 16, |
|||
transactionHash: '0x1234567890', |
|||
address: address, |
|||
blockHash: '0x1234567890', |
|||
blockNumber: 1 |
|||
} |
|||
}, { |
|||
abi: { |
|||
name: name, |
|||
inputs: [{ |
|||
name: 'a', |
|||
type: 'int', |
|||
indexed: false |
|||
}] |
|||
}, |
|||
data: { |
|||
logIndex: '0x1', |
|||
transactionIndex: '0x10', |
|||
transactionHash: '0x1234567890', |
|||
address: address, |
|||
blockHash: '0x1234567890', |
|||
blockNumber: '0x1', |
|||
data: '0x0000000000000000000000000000000000000000000000000000000000000001' |
|||
}, |
|||
expected: { |
|||
event: name, |
|||
args: { |
|||
a: new BigNumber(1) |
|||
}, |
|||
logIndex: 1, |
|||
transactionIndex: 16, |
|||
transactionHash: '0x1234567890', |
|||
address: address, |
|||
blockHash: '0x1234567890', |
|||
blockNumber: 1 |
|||
} |
|||
}, { |
|||
abi: { |
|||
name: name, |
|||
inputs: [{ |
|||
name: 'a', |
|||
type: 'int', |
|||
indexed: false |
|||
}, { |
|||
name: 'b', |
|||
type: 'int', |
|||
indexed: true |
|||
}, { |
|||
name: 'c', |
|||
type: 'int', |
|||
indexed: false |
|||
}, { |
|||
name: 'd', |
|||
type: 'int', |
|||
indexed: true |
|||
}] |
|||
}, |
|||
data: { |
|||
logIndex: '0x1', |
|||
transactionIndex: '0x10', |
|||
transactionHash: '0x1234567890', |
|||
address: address, |
|||
blockHash: '0x1234567890', |
|||
blockNumber: '0x1', |
|||
data: '0x' + |
|||
'0000000000000000000000000000000000000000000000000000000000000001' + |
|||
'0000000000000000000000000000000000000000000000000000000000000004', |
|||
topics: [ |
|||
address, |
|||
'0x000000000000000000000000000000000000000000000000000000000000000a', |
|||
'0x0000000000000000000000000000000000000000000000000000000000000010' |
|||
] |
|||
}, |
|||
expected: { |
|||
event: name, |
|||
args: { |
|||
a: new BigNumber(1), |
|||
b: new BigNumber(10), |
|||
c: new BigNumber(4), |
|||
d: new BigNumber(16) |
|||
}, |
|||
logIndex: 1, |
|||
transactionIndex: 16, |
|||
transactionHash: '0x1234567890', |
|||
address: address, |
|||
blockHash: '0x1234567890', |
|||
blockNumber: 1 |
|||
} |
|||
}, { |
|||
abi: { |
|||
name: name, |
|||
anonymous: true, |
|||
inputs: [{ |
|||
name: 'a', |
|||
type: 'int', |
|||
indexed: false |
|||
}, { |
|||
name: 'b', |
|||
type: 'int', |
|||
indexed: true |
|||
}, { |
|||
name: 'c', |
|||
type: 'int', |
|||
indexed: false |
|||
}, { |
|||
name: 'd', |
|||
type: 'int', |
|||
indexed: true |
|||
}] |
|||
}, |
|||
data: { |
|||
logIndex: '0x1', |
|||
transactionIndex: '0x10', |
|||
transactionHash: '0x1234567890', |
|||
address: address, |
|||
blockHash: '0x1234567890', |
|||
blockNumber: '0x1', |
|||
data: '0x' + |
|||
'0000000000000000000000000000000000000000000000000000000000000001' + |
|||
'0000000000000000000000000000000000000000000000000000000000000004', |
|||
topics: [ |
|||
'0x000000000000000000000000000000000000000000000000000000000000000a', |
|||
'0x0000000000000000000000000000000000000000000000000000000000000010' |
|||
] |
|||
}, |
|||
expected: { |
|||
event: name, |
|||
args: { |
|||
a: new BigNumber(1), |
|||
b: new BigNumber(10), |
|||
c: new BigNumber(4), |
|||
d: new BigNumber(16) |
|||
}, |
|||
logIndex: 1, |
|||
transactionIndex: 16, |
|||
transactionHash: '0x1234567890', |
|||
address: address, |
|||
blockHash: '0x1234567890', |
|||
blockNumber: 1 |
|||
} |
|||
}]; |
|||
|
|||
describe('lib/web3/event', function () { |
|||
describe('decode', function () { |
|||
tests.forEach(function (test, index) { |
|||
it('test no: ' + index, function () { |
|||
var event = new SolidityEvent(test.abi, address); |
|||
|
|||
var result = event.decode(test.data); |
|||
assert.deepEqual(result, test.expected); |
|||
}); |
|||
}); |
|||
}); |
|||
}); |
|||
|
@ -0,0 +1,206 @@ |
|||
var chai = require('chai'); |
|||
var assert = chai.assert; |
|||
var SolidityEvent = require('../lib/web3/event'); |
|||
|
|||
var address = '0x1234567890123456789012345678901234567890'; |
|||
var signature = '0xffff'; |
|||
|
|||
var tests = [{ |
|||
abi: { |
|||
name: 'event1', |
|||
inputs: [] |
|||
}, |
|||
indexed: {}, |
|||
options: {}, |
|||
expected: { |
|||
address: address, |
|||
topics: [ |
|||
signature |
|||
] |
|||
} |
|||
}, { |
|||
abi: { |
|||
name: 'event1', |
|||
inputs: [{ |
|||
type: 'int', |
|||
name: 'a', |
|||
indexed: true |
|||
}] |
|||
}, |
|||
indexed: { |
|||
a: 16 |
|||
}, |
|||
options: {}, |
|||
expected: { |
|||
address: address, |
|||
topics: [ |
|||
signature, |
|||
'0x0000000000000000000000000000000000000000000000000000000000000010' |
|||
] |
|||
} |
|||
},{ |
|||
abi: { |
|||
name: 'event1', |
|||
inputs: [{ |
|||
type: 'int', |
|||
name: 'a', |
|||
indexed: true |
|||
}, { |
|||
type: 'int', |
|||
name: 'b', |
|||
indexed: true |
|||
}, { |
|||
type: 'int', |
|||
name: 'c', |
|||
indexed: false |
|||
}, { |
|||
type: 'int', |
|||
name: 'd', |
|||
indexed: true |
|||
}] |
|||
}, |
|||
indexed: { |
|||
b: 4 |
|||
}, |
|||
options: {}, |
|||
expected: { |
|||
address: address, |
|||
topics: [ |
|||
signature, // signature
|
|||
null, // a
|
|||
'0x0000000000000000000000000000000000000000000000000000000000000004', // b
|
|||
null // d
|
|||
] |
|||
} |
|||
}, { |
|||
abi: { |
|||
name: 'event1', |
|||
inputs: [{ |
|||
type: 'int', |
|||
name: 'a', |
|||
indexed: true |
|||
}, { |
|||
type: 'int', |
|||
name: 'b', |
|||
indexed: true |
|||
}] |
|||
}, |
|||
indexed: { |
|||
a: [16, 1], |
|||
b: 2 |
|||
}, |
|||
options: {}, |
|||
expected: { |
|||
address: address, |
|||
topics: [ |
|||
signature, |
|||
['0x0000000000000000000000000000000000000000000000000000000000000010', '0x0000000000000000000000000000000000000000000000000000000000000001'], |
|||
'0x0000000000000000000000000000000000000000000000000000000000000002' |
|||
] |
|||
} |
|||
}, { |
|||
abi: { |
|||
name: 'event1', |
|||
inputs: [{ |
|||
type: 'int', |
|||
name: 'a', |
|||
indexed: true |
|||
}] |
|||
}, |
|||
indexed: { |
|||
a: null |
|||
}, |
|||
options: {}, |
|||
expected: { |
|||
address: address, |
|||
topics: [ |
|||
signature, |
|||
null |
|||
] |
|||
} |
|||
}, { |
|||
abi: { |
|||
name: 'event1', |
|||
inputs: [{ |
|||
type: 'int', |
|||
name: 'a', |
|||
indexed: true |
|||
}] |
|||
}, |
|||
indexed: { |
|||
a: 1 |
|||
}, |
|||
options: { |
|||
fromBlock: 4, |
|||
toBlock: 10 |
|||
}, |
|||
expected: { |
|||
address: address, |
|||
fromBlock: '0x4', |
|||
toBlock: '0xa', |
|||
topics: [ |
|||
signature, |
|||
'0x0000000000000000000000000000000000000000000000000000000000000001' |
|||
] |
|||
} |
|||
}, { |
|||
abi: { |
|||
name: 'event1', |
|||
inputs: [{ |
|||
type: 'int', |
|||
name: 'a', |
|||
indexed: true |
|||
}], |
|||
anonymous: true |
|||
}, |
|||
indexed: { |
|||
a: 1 |
|||
}, |
|||
options: {}, |
|||
expected: { |
|||
topics: [ |
|||
'0x0000000000000000000000000000000000000000000000000000000000000001' |
|||
] |
|||
} |
|||
}, { |
|||
abi: { |
|||
name: 'event1', |
|||
inputs: [{ |
|||
type: 'int', |
|||
name: 'a', |
|||
indexed: true |
|||
}, { |
|||
type: 'int', |
|||
name: 'b', |
|||
indexed: true |
|||
}], |
|||
anonymous: true |
|||
}, |
|||
indexed: { |
|||
b: 1 |
|||
}, |
|||
options: {}, |
|||
expected: { |
|||
topics: [ |
|||
null, |
|||
'0x0000000000000000000000000000000000000000000000000000000000000001' |
|||
] |
|||
} |
|||
}]; |
|||
|
|||
describe('lib/web3/event', function () { |
|||
describe('encode', function () { |
|||
tests.forEach(function (test, index) { |
|||
it('test no: ' + index, function () { |
|||
var event = new SolidityEvent(test.abi, address); |
|||
event.signature = function () { // inject signature
|
|||
return signature.slice(2); |
|||
}; |
|||
|
|||
var result = event.encode(test.indexed, test.options); |
|||
assert.deepEqual(result, test.expected); |
|||
}); |
|||
}); |
|||
}); |
|||
}); |
|||
|
@ -1,113 +0,0 @@ |
|||
var assert = require('assert'); |
|||
var event = require('../lib/web3/event.js'); |
|||
var f = require('../lib/solidity/formatters.js'); |
|||
|
|||
describe('lib/web3/event', function () { |
|||
describe('inputParser', function () { |
|||
it('should create basic filter input object', function () { |
|||
|
|||
// given
|
|||
var address = '0x012345'; |
|||
var signature = '0x987654'; |
|||
var e = { |
|||
name: 'Event', |
|||
inputs: [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"hash256","indexed":false}] |
|||
}; |
|||
|
|||
// when
|
|||
var impl = event.inputParser(address, signature, e); |
|||
var result = impl(); |
|||
|
|||
// then
|
|||
assert.equal(result.address, address); |
|||
assert.equal(result.topics.length, 1); |
|||
assert.equal(result.topics[0], signature); |
|||
|
|||
}); |
|||
|
|||
it('should create filter input object with options', function () { |
|||
|
|||
// given
|
|||
var address = '0x012345'; |
|||
var signature = '0x987654'; |
|||
var options = { |
|||
fromBlock: 1, |
|||
toBlock: 2, |
|||
}; |
|||
var e = { |
|||
name: 'Event', |
|||
inputs: [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"hash256","indexed":false}] |
|||
}; |
|||
|
|||
// when
|
|||
var impl = event.inputParser(address, signature, e); |
|||
var result = impl({}, options); |
|||
|
|||
// then
|
|||
assert.equal(result.address, address); |
|||
assert.equal(result.topics.length, 1); |
|||
assert.equal(result.topics[0], signature); |
|||
assert.equal(result.fromBlock, options.fromBlock); |
|||
assert.equal(result.toBlock, options.toBlock); |
|||
|
|||
}); |
|||
|
|||
it('should create filter input object with indexed params', function () { |
|||
|
|||
// given
|
|||
var address = '0x012345'; |
|||
var signature = '0x987654'; |
|||
var options = { |
|||
fromBlock: 1, |
|||
toBlock: 2 |
|||
}; |
|||
var e = { |
|||
name: 'Event', |
|||
inputs: [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"hash256","indexed":false}] |
|||
}; |
|||
|
|||
// when
|
|||
var impl = event.inputParser(address, signature, e); |
|||
var result = impl({a: 4}, options); |
|||
|
|||
// then
|
|||
assert.equal(result.address, address); |
|||
assert.equal(result.topics.length, 2); |
|||
assert.equal(result.topics[0], signature); |
|||
assert.equal(result.topics[1], '0x' + f.formatInputInt(4)); |
|||
assert.equal(result.fromBlock, options.fromBlock); |
|||
assert.equal(result.toBlock, options.toBlock); |
|||
|
|||
}); |
|||
|
|||
it('should create filter input object with an array of indexed params', function () { |
|||
|
|||
// given
|
|||
var address = '0x012345'; |
|||
var signature = '0x987654'; |
|||
var options = { |
|||
fromBlock: 1, |
|||
toBlock: 2, |
|||
}; |
|||
var e = { |
|||
name: 'Event', |
|||
inputs: [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"hash256","indexed":false}] |
|||
}; |
|||
|
|||
// when
|
|||
var impl = event.inputParser(address, signature, e); |
|||
var result = impl({a: [4, 69]}, options); |
|||
|
|||
// then
|
|||
assert.equal(result.address, address); |
|||
assert.equal(result.topics.length, 2); |
|||
assert.equal(result.topics[0], signature); |
|||
assert.equal(result.topics[1][0], f.formatInputInt(4)); |
|||
assert.equal(result.topics[1][1], f.formatInputInt(69)); |
|||
assert.equal(result.fromBlock, options.fromBlock); |
|||
assert.equal(result.toBlock, options.toBlock); |
|||
|
|||
}); |
|||
}); |
|||
}); |
|||
|
@ -1,81 +0,0 @@ |
|||
var assert = require('assert'); |
|||
var event = require('../lib/web3/event.js'); |
|||
|
|||
describe('lib/web3/event', function () { |
|||
describe('outputParser', function () { |
|||
it('should parse basic event output object', function () { |
|||
|
|||
// given
|
|||
var output = { |
|||
"address":"0x78dfc5983baecf65f73e3de3a96cee24e6b7981e", |
|||
"data":"0x000000000000000000000000000000000000000000000000000000000000004b", |
|||
"number":2, |
|||
"topics":[ |
|||
"0x6e61ef44ac2747ff8b84d353a908eb8bd5c3fb118334d57698c5cfc7041196ad", |
|||
"0x0000000000000000000000000000000000000000000000000000000000000001" |
|||
] |
|||
}; |
|||
|
|||
var e = { |
|||
name: 'Event', |
|||
inputs: [{"name":"a","type":"bool","indexed":true},{"name":"b","type":"uint256","indexed":false}] |
|||
}; |
|||
|
|||
// when
|
|||
var impl = event.outputParser(e); |
|||
var result = impl(output); |
|||
|
|||
// then
|
|||
assert.equal(result.event, 'Event'); |
|||
assert.equal(result.number, 2); |
|||
assert.equal(Object.keys(result.args).length, 2); |
|||
assert.equal(result.args.a, true); |
|||
assert.equal(result.args.b, 75); |
|||
}); |
|||
|
|||
it('should parse event output object arguments in correct order', function () { |
|||
|
|||
// given
|
|||
var output = { |
|||
"address":"0x78dfc5983baecf65f73e3de3a96cee24e6b7981e", |
|||
"data": "0x" + |
|||
"000000000000000000000000000000000000000000000000000000000000004b" + |
|||
"000000000000000000000000000000000000000000000000000000000000004c" + |
|||
"0000000000000000000000000000000000000000000000000000000000000001", |
|||
"number":3, |
|||
"topics":[ |
|||
"0x6e61ef44ac2747ff8b84d353a908eb8bd5c3fb118334d57698c5cfc7041196ad", |
|||
"0x0000000000000000000000000000000000000000000000000000000000000001", |
|||
"0x0000000000000000000000000000000000000000000000000000000000000005" |
|||
] |
|||
}; |
|||
|
|||
var e = { |
|||
name: 'Event2', |
|||
inputs: [ |
|||
{"name":"a","type":"bool","indexed":true}, |
|||
{"name":"b","type":"int","indexed":false}, |
|||
{"name":"c","type":"int","indexed":false}, |
|||
{"name":"d","type":"int","indexed":true}, |
|||
{"name":"e","type":"bool","indexed":false} |
|||
] |
|||
}; |
|||
|
|||
// when
|
|||
var impl = event.outputParser(e); |
|||
var result = impl(output); |
|||
|
|||
// then
|
|||
assert.equal(result.event, 'Event2'); |
|||
assert.equal(result.number, 3); |
|||
assert.equal(Object.keys(result.args).length, 5); |
|||
assert.equal(result.args.a, true); |
|||
assert.equal(result.args.b, 75); |
|||
assert.equal(result.args.c, 76); |
|||
assert.equal(result.args.d, 5); |
|||
assert.equal(result.args.e, true); |
|||
|
|||
}); |
|||
}); |
|||
}); |
|||
|
@ -0,0 +1,27 @@ |
|||
var FakeHttpProvider = require('./FakeHttpProvider'); |
|||
|
|||
var FakeHttpProvider2 = function () { |
|||
this.counter = 0; |
|||
this.resultList = []; |
|||
}; |
|||
|
|||
FakeHttpProvider2.prototype = new FakeHttpProvider(); |
|||
FakeHttpProvider2.prototype.constructor = FakeHttpProvider2; |
|||
|
|||
FakeHttpProvider2.prototype.injectResultList = function (list) { |
|||
this.resultList = list; |
|||
}; |
|||
|
|||
FakeHttpProvider2.prototype.getResponse = function () { |
|||
var result = this.resultList[this.counter]; |
|||
this.counter++; |
|||
if (result.type === 'batch') { |
|||
this.injectBatchResults(result.result); |
|||
} else { |
|||
this.injectResult(result.result); |
|||
} |
|||
return this.response; |
|||
}; |
|||
|
|||
module.exports = FakeHttpProvider2; |
|||
|
@ -1,48 +0,0 @@ |
|||
var chai = require('chai'); |
|||
var assert = chai.assert; |
|||
var utils = require('../lib/utils/utils'); |
|||
var FakeHttpProvider = require('./helpers/FakeHttpProvider'); |
|||
var signature = require('../lib/web3/signature'); |
|||
var web3 = require('../index'); |
|||
|
|||
var tests = [{ |
|||
method: 'functionSignatureFromAscii', |
|||
call: 'web3_sha3', |
|||
request: 'multiply', |
|||
formattedRequest: utils.fromAscii('multiply'), |
|||
result: '0x255d31552d29a21e93334e96055c6dca7cd329f5420ae74ec166d0c47f9f9843', |
|||
formattedResult: '0x255d3155' |
|||
},{ |
|||
method: 'eventSignatureFromAscii', |
|||
call: 'web3_sha3', |
|||
request: 'multiply', |
|||
formattedRequest: utils.fromAscii('multiply'), |
|||
result: '0x255d31552d29a21e93334e96055c6dca7cd329f5420ae74ec166d0c47f9f9843', |
|||
formattedResult: '0x255d31552d29a21e93334e96055c6dca7cd329f5420ae74ec166d0c47f9f9843' |
|||
}]; |
|||
|
|||
describe('lib/web3/signature', function () { |
|||
tests.forEach(function (test, index) { |
|||
describe(test.method, function () { |
|||
it('should properly format and return signature of solidity functioni ' + index, function () { |
|||
|
|||
// given
|
|||
var provider = new FakeHttpProvider(); |
|||
web3.setProvider(provider); |
|||
provider.injectResult(test.result); |
|||
provider.injectValidation(function (payload) { |
|||
assert.equal(payload.method, test.call); |
|||
assert.equal(payload.jsonrpc, '2.0'); |
|||
assert.equal(payload.params[0], test.formattedRequest); |
|||
}); |
|||
|
|||
// when
|
|||
var result = signature[test.method].call(null, test.request); |
|||
|
|||
// then
|
|||
assert.equal(result, test.formattedResult); |
|||
}); |
|||
}); |
|||
}); |
|||
}); |
|||
|
@ -1,49 +0,0 @@ |
|||
var assert = require('assert'); |
|||
var utils = require('../lib/solidity/utils'); |
|||
|
|||
describe('lib/utils/utils', function() { |
|||
it('should filter functions and events from input array properly', function () { |
|||
|
|||
// given
|
|||
var description = [{ |
|||
"name": "test", |
|||
"type": "function", |
|||
"inputs": [{ |
|||
"name": "a", |
|||
"type": "uint256" |
|||
} |
|||
], |
|||
"outputs": [ |
|||
{ |
|||
"name": "d", |
|||
"type": "uint256" |
|||
} |
|||
], |
|||
}, { |
|||
"name": "test2", |
|||
"type": "event", |
|||
"inputs": [{ |
|||
"name": "a", |
|||
"type": "uint256" |
|||
} |
|||
], |
|||
"outputs": [ |
|||
{ |
|||
"name": "d", |
|||
"type": "uint256" |
|||
} |
|||
] |
|||
}]; |
|||
|
|||
// when
|
|||
var events = utils.filterEvents(description); |
|||
var functions = utils.filterFunctions(description); |
|||
|
|||
// then
|
|||
assert.equal(events.length, 1); |
|||
assert.equal(events[0].name, 'test2'); |
|||
assert.equal(functions.length, 1); |
|||
assert.equal(functions[0].name, 'test'); |
|||
|
|||
}); |
|||
}); |
@ -0,0 +1,49 @@ |
|||
var chai = require('chai'); |
|||
var web3 = require('../index'); |
|||
var testMethod = require('./helpers/test.method.js'); |
|||
|
|||
var method = 'post'; |
|||
|
|||
var tests = [{ |
|||
args: [{ |
|||
from: '0x123123123', |
|||
topics: ['hello_world'], |
|||
payload: '12345', |
|||
ttl: 100, |
|||
workToProve: 101 |
|||
}], |
|||
formattedArgs: [{ |
|||
from: '0x123123123', |
|||
topics: [web3.fromAscii('hello_world')], |
|||
payload: web3.toHex('12345'), |
|||
ttl: web3.toHex('100'), |
|||
workToProve: web3.toHex('101'), |
|||
priority: '0x0' |
|||
}], |
|||
result: true, |
|||
formattedResult: true, |
|||
call: 'shh_'+ method |
|||
}, { |
|||
args: [{ |
|||
from: '0x21312', |
|||
topics: ['hello_world'], |
|||
payload: '0x12345', |
|||
ttl: 0x100, |
|||
workToProve: 0x101, |
|||
priority: 0x15 |
|||
}], |
|||
formattedArgs: [{ |
|||
from: '0x21312', |
|||
topics: [web3.fromAscii('hello_world')], |
|||
payload: '0x12345', |
|||
ttl: '0x100', |
|||
workToProve: '0x101', |
|||
priority: '0x15' |
|||
}], |
|||
result: true, |
|||
formattedResult: true, |
|||
call: 'shh_'+ method |
|||
}]; |
|||
|
|||
testMethod.runTests('shh', method, tests); |
|||
|
Loading…
Reference in new issue