Skip to content

Commit

Permalink
Merge pull request #12 from debris/master
Browse files Browse the repository at this point in the history
simplifie contract creation && calls, improved added examples
  • Loading branch information
obscuren committed Nov 14, 2014
2 parents 7ffba22 + ea8db7a commit 42713c6
Show file tree
Hide file tree
Showing 7 changed files with 354 additions and 40 deletions.
12 changes: 7 additions & 5 deletions dist/ethereum.js

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions dist/ethereum.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/ethereum.min.js

Large diffs are not rendered by default.

75 changes: 75 additions & 0 deletions example/contract.html
Original file line number Diff line number Diff line change
@@ -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>

51 changes: 24 additions & 27 deletions example/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,41 +4,38 @@
<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">
if (window.Promise === undefined) {
window.Promise = ES6Promise.Promise;
}
var web3 = require('web3');
web3.setProvider(new web3.providers.AutoProvider());

var web3 = require('web3');
function watchBalance() {
var coinbase = web3.eth.coinbase;
var originalBalance = 0;

//web3.setProvider(new web3.providers.QtProvider());
//web3.setProvider(new web3.providers.HttpRpcProvider("http://localhost:8080"));
// web3.setProvider(new web3.providers.WebSocketProvider("ws://localhost:40404/eth"));
web3.setProvider(new web3.providers.AutoProvider());
web3.eth.balanceAt(coinbase).then(function (balance) {
originalBalance = web3.toDecimal(balance);
document.getElementById('original').innerText = 'original balance: ' + originalBalance + ' watching...';
});

function testSnippet() {
web3.eth.watch({altered: web3.eth.coinbase}).changed(function() {
web3.eth.balanceAt(web3.eth.coinbase).then(function (balance) {
console.log(parseInt(balance,16));
console.log(typeof balance);
document.getElementById("result").innerText = +balance;
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>std::name_reg</h1>
<input type="text" id="name"></input>
<button type="button" onClick="testSnippet();">test snippet</button>

<div></div>
result: <div id="result"></div>

<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>

200 changes: 200 additions & 0 deletions lib/abi.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
/*
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 <[email protected]>
* @date 2014
*/

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 (number, n) {
return (new Array(n * 2 - number.toString().length + 1)).join("0") + number;
};

var setupInputTypes = function () {
var prefixedType = function (prefix) {
return function (type, value) {
var expected = prefix;
if (type.indexOf(expected) !== 0) {
return false;
}

var padding = parseInt(type.slice(expected.length)) / 8;
return padLeft(value, padding);
};
};

var namedType = function (name, padding, formatter) {
return function (type, value) {
if (type !== name) {
return false;
}

return padLeft(formatter ? value : formatter(value), padding);
};
};

var formatBool = function (value) {
return value ? '1' : '0';
};

return [
prefixedType('uint'),
prefixedType('int'),
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;
}

// it needs to be checked in WebThreeStubServer
// something wrong might be with this additional zero
bytes = bytes + index + 'x' + '0';
var method = json[index];

for (var i = 0; i < method.inputs.length; i++) {
var found = false;
for (var j = 0; j < inputTypes.length && !found; j++) {
var val = parseInt(params[i]).toString(16);
found = inputTypes[j](method.inputs[i].type, val);
}
if (!found) {
console.error('unsupported json type: ' + method.inputs[i].type);
}
bytes += found;
}
return bytes;
};

var setupOutputTypes = function () {
var prefixedType = function (prefix) {
return function (type) {
var expected = prefix;
if (type.indexOf(expected) !== 0) {
return -1;
}

var padding = parseInt(type.slice(expected.length)) / 8;
return padding * 2;
};
};

var namedType = function (name, padding) {
return function (type) {
return name === type ? padding * 2: -1;
};
};

var formatInt = function (value) {
return parseInt(value, 16);
};

var formatBool = function (value) {
return value === '1' ? true : false;
};

return [
{ padding: prefixedType('uint'), format: formatInt },
{ padding: prefixedType('int'), 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): 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
};

Loading

0 comments on commit 42713c6

Please sign in to comment.