Added constructor and simplified interface.

This commit is contained in:
ricmoo 2017-03-01 02:33:29 -05:00
parent 5ecba670a5
commit a073968597
1 changed files with 104 additions and 28 deletions

View File

@ -1,5 +1,6 @@
'use strict';
// See: https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI
var utils = (function() {
var convert = require('ethers-utils/convert.js');
@ -13,6 +14,8 @@ var utils = (function() {
bigNumberify: require('ethers-utils/bignumber.js').bigNumberify,
getAddress: require('ethers-utils/address').getAddress,
concat: convert.concat,
toUtf8Bytes: utf8.toUtf8Bytes,
@ -126,7 +129,7 @@ var coderAddress = {
if (data.length < offset + 32) { throw new Error('invalid address'); }
return {
consumed: 32,
value: utils.hexlify(data.slice(offset + 12, offset + 32))
value: utils.getAddress(utils.hexlify(data.slice(offset + 12, offset + 32)))
}
}
}
@ -306,34 +309,73 @@ function populateDescription(object, items) {
function CallDescription() { }
utils.defineProperty(CallDescription.prototype, 'type', 'call');
function DeployDescription() { }
utils.defineProperty(DeployDescription.prototype, 'type', 'deploy');
function TransactionDescription() { }
utils.defineProperty(TransactionDescription.prototype, 'type', 'transaction');
function EventDescription() { }
utils.defineProperty(EventDescription.prototype, 'type', 'event');
function UnsupportedDescription() { }
utils.defineProperty(UnsupportedDescription.prototype, 'type', 'unknown');
function Interface(abi) {
if (!(this instanceof Interface)) { throw new Error('missing new'); }
if (typeof(abi) === 'string') {
try {
abi = JSON.parse(abi);
} catch (error) {
throw new Error('invalid abi');
}
}
// Wrap this up as JSON so we can return a "copy" and avoid mutation
defineFrozen(this, 'abi', abi);
var methods = [], events = [];
abi.forEach(function(method) {
var func = null;
var methods = {}, events = {};
function addMethod(method) {
switch (method.type) {
case 'function':
methods.push(method.name);
func = (function() {
case 'constructor':
var func = (function() {
var inputTypes = getKeys(method.inputs, 'type');
var outputTypes = getKeys(method.outputs, 'type');
var outputNames = getKeys(method.outputs, 'name', true);
var func = function(bytecode) {
if (!utils.isHexString(bytecode)) {
throw new Error('invalid bytecode');
}
var params = Array.prototype.slice.call(arguments, 1);
if (params.length < inputTypes.length) {
throw new Error('missing parameter');
} else if (params.length > inputTypes.length) {
throw new Error('too many parameters');
}
var result = {
bytecode: bytecode + Interface.encodeParams(inputTypes, params).substring(2),
}
return populateDescription(new DeployDescription(), result);
}
defineFrozen(func, 'inputs', getKeys(method.inputs, 'name'));
return func;
})();
if (this.deployFunction == null) {
utils.defineProperty(this, 'deployFunction', func);
}
break;
case 'function':
var func = (function() {
var inputTypes = getKeys(method.inputs, 'type');
if (method.constant) {
var outputTypes = getKeys(method.outputs, 'type');
var outputNames = getKeys(method.outputs, 'name', true);
}
var func = function() {
var signature = method.name + '(' + getKeys(method.inputs, 'type').join(',') + ')';
@ -372,11 +414,17 @@ function Interface(abi) {
return func;
})();
if (method.name && methods[method.name] == null) {
utils.defineProperty(methods, method.name, func);
//} else if (this.fallbackFunction == null) {
// utils.defineProperty(this, 'fallbackFunction', func);
}
break;
case 'event':
events.push(method.name);
func = (function() {
var func = (function() {
var inputTypes = getKeys(method.inputs, 'type');
var inputNames = getKeys(method.inputs, 'name', true);
var func = function() {
@ -399,24 +447,28 @@ function Interface(abi) {
defineFrozen(func, 'inputs', getKeys(method.inputs, 'name'));
return func;
})();
if (method.name && events[method.name] == null) {
utils.defineProperty(events, method.name, func);
}
break;
default:
func = (function() {
return function() {
return populateDescription(new UnsupportedDescription(), {});
}
})();
console.log('WARNING: unsupported ABI type - ' + method.type);
break;
}
};
if (method.name) {
utils.defineProperty(this, method.name, func);
}
}, this);
abi.forEach(addMethod, this);
defineFrozen(this, 'methods', methods);
defineFrozen(this, 'events', events);
// If there wasn't a constructor, create the default constructor
if (!this.deployFunction) {
addMethod({type: 'constructor', inputs: []});
}
utils.defineProperty(this, 'functions', methods);
utils.defineProperty(this, 'events', events);
}
@ -491,10 +543,34 @@ utils.defineProperty(Interface, 'decodeParams', function(names, types, data) {
var result = coder.decode(data, offset);
offset += result.consumed;
}
// Add indexed parameter
values[index] = result.value;
if (names[index]) { values[names[index]] = result.value; }
// Add named parameters
if (names[index]) {
var name = names[index];
// We reserve length to make the Result object arrayish
if (name === 'length') {
console.log('WARNING: result length renamed to _length');
name = '_length';
}
if (values[name] == null) {
values[name] = result.value;
} else {
console.log('WARNING: duplicate value - ' + name);
}
}
});
values.length = types.length;
return values;
});
utils.defineProperty(Interface, 'getDeployTransaction', function(bytecode) {
});
module.exports = Interface;