2019-05-15 01:48:48 +03:00
|
|
|
"use strict";
|
|
|
|
var __extends = (this && this.__extends) || (function () {
|
|
|
|
var extendStatics = function (d, b) {
|
|
|
|
extendStatics = Object.setPrototypeOf ||
|
|
|
|
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
|
|
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
|
|
|
return extendStatics(d, b);
|
|
|
|
};
|
|
|
|
return function (d, b) {
|
|
|
|
extendStatics(d, b);
|
|
|
|
function __() { this.constructor = d; }
|
|
|
|
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
|
|
};
|
|
|
|
})();
|
|
|
|
var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
|
if (mod && mod.__esModule) return mod;
|
|
|
|
var result = {};
|
|
|
|
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
|
|
|
result["default"] = mod;
|
|
|
|
return result;
|
|
|
|
};
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
|
var bignumber_1 = require("@ethersproject/bignumber");
|
|
|
|
var errors = __importStar(require("@ethersproject/errors"));
|
|
|
|
var properties_1 = require("@ethersproject/properties");
|
|
|
|
;
|
|
|
|
var _constructorGuard = {};
|
2019-05-25 01:15:42 +03:00
|
|
|
var storageClasses = { calldata: true, memory: true, storage: true };
|
2019-05-15 01:48:48 +03:00
|
|
|
// @TODO: Make sure that children of an indexed tuple are marked with a null indexed
|
|
|
|
function parseParamType(param, allowIndexed) {
|
|
|
|
var originalParam = param;
|
|
|
|
function throwError(i) {
|
|
|
|
throw new Error("unexpected character '" + originalParam[i] + "' at position " + i + " in '" + originalParam + "'");
|
|
|
|
}
|
|
|
|
param = param.replace(/\s/g, " ");
|
|
|
|
function newNode(parent) {
|
|
|
|
var node = { type: "", name: "", parent: parent, state: { allowType: true } };
|
|
|
|
if (allowIndexed) {
|
|
|
|
node.indexed = false;
|
|
|
|
}
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
var parent = { type: "", name: "", state: { allowType: true } };
|
|
|
|
var node = parent;
|
|
|
|
for (var i = 0; i < param.length; i++) {
|
|
|
|
var c = param[i];
|
|
|
|
switch (c) {
|
|
|
|
case "(":
|
|
|
|
if (!node.state.allowParams) {
|
|
|
|
throwError(i);
|
|
|
|
}
|
|
|
|
node.state.allowType = false;
|
|
|
|
node.type = verifyType(node.type);
|
|
|
|
node.components = [newNode(node)];
|
|
|
|
node = node.components[0];
|
|
|
|
break;
|
|
|
|
case ")":
|
|
|
|
delete node.state;
|
2019-05-25 01:15:42 +03:00
|
|
|
if (node.name === "indexed") {
|
|
|
|
if (!allowIndexed) {
|
|
|
|
throwError(i);
|
2019-05-15 01:48:48 +03:00
|
|
|
}
|
2019-05-25 01:15:42 +03:00
|
|
|
node.indexed = true;
|
|
|
|
node.name = "";
|
|
|
|
}
|
|
|
|
if (storageClasses[node.name]) {
|
|
|
|
node.name = "";
|
2019-05-15 01:48:48 +03:00
|
|
|
}
|
|
|
|
node.type = verifyType(node.type);
|
|
|
|
var child = node;
|
|
|
|
node = node.parent;
|
|
|
|
if (!node) {
|
|
|
|
throwError(i);
|
|
|
|
}
|
|
|
|
delete child.parent;
|
|
|
|
node.state.allowParams = false;
|
|
|
|
node.state.allowName = true;
|
|
|
|
node.state.allowArray = true;
|
|
|
|
break;
|
|
|
|
case ",":
|
|
|
|
delete node.state;
|
2019-05-25 01:15:42 +03:00
|
|
|
if (node.name === "indexed") {
|
|
|
|
if (!allowIndexed) {
|
|
|
|
throwError(i);
|
2019-05-15 01:48:48 +03:00
|
|
|
}
|
2019-05-25 01:15:42 +03:00
|
|
|
node.indexed = true;
|
|
|
|
node.name = "";
|
|
|
|
}
|
|
|
|
if (storageClasses[node.name]) {
|
|
|
|
node.name = "";
|
2019-05-15 01:48:48 +03:00
|
|
|
}
|
|
|
|
node.type = verifyType(node.type);
|
|
|
|
var sibling = newNode(node.parent);
|
|
|
|
//{ type: "", name: "", parent: node.parent, state: { allowType: true } };
|
|
|
|
node.parent.components.push(sibling);
|
|
|
|
delete node.parent;
|
|
|
|
node = sibling;
|
|
|
|
break;
|
|
|
|
// Hit a space...
|
|
|
|
case " ":
|
|
|
|
// If reading type, the type is done and may read a param or name
|
|
|
|
if (node.state.allowType) {
|
|
|
|
if (node.type !== "") {
|
|
|
|
node.type = verifyType(node.type);
|
|
|
|
delete node.state.allowType;
|
|
|
|
node.state.allowName = true;
|
|
|
|
node.state.allowParams = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// If reading name, the name is done
|
|
|
|
if (node.state.allowName) {
|
|
|
|
if (node.name !== "") {
|
2019-05-25 01:15:42 +03:00
|
|
|
if (node.name === "indexed") {
|
|
|
|
if (!allowIndexed) {
|
|
|
|
throwError(i);
|
2019-05-15 01:48:48 +03:00
|
|
|
}
|
2019-05-25 01:15:42 +03:00
|
|
|
if (node.indexed) {
|
|
|
|
throwError(i);
|
|
|
|
}
|
|
|
|
node.indexed = true;
|
|
|
|
node.name = "";
|
|
|
|
}
|
|
|
|
else if (storageClasses[node.name]) {
|
|
|
|
node.name = "";
|
2019-05-15 01:48:48 +03:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
node.state.allowName = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case "[":
|
|
|
|
if (!node.state.allowArray) {
|
|
|
|
throwError(i);
|
|
|
|
}
|
|
|
|
node.type += c;
|
|
|
|
node.state.allowArray = false;
|
|
|
|
node.state.allowName = false;
|
|
|
|
node.state.readArray = true;
|
|
|
|
break;
|
|
|
|
case "]":
|
|
|
|
if (!node.state.readArray) {
|
|
|
|
throwError(i);
|
|
|
|
}
|
|
|
|
node.type += c;
|
|
|
|
node.state.readArray = false;
|
|
|
|
node.state.allowArray = true;
|
|
|
|
node.state.allowName = true;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
if (node.state.allowType) {
|
|
|
|
node.type += c;
|
|
|
|
node.state.allowParams = true;
|
|
|
|
node.state.allowArray = true;
|
|
|
|
}
|
|
|
|
else if (node.state.allowName) {
|
|
|
|
node.name += c;
|
|
|
|
delete node.state.allowArray;
|
|
|
|
}
|
|
|
|
else if (node.state.readArray) {
|
|
|
|
node.type += c;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
throwError(i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (node.parent) {
|
|
|
|
throw new Error("unexpected eof");
|
|
|
|
}
|
|
|
|
delete parent.state;
|
2019-05-25 01:15:42 +03:00
|
|
|
if (node.name === "indexed") {
|
|
|
|
if (!allowIndexed) {
|
|
|
|
throwError(originalParam.length - 7);
|
|
|
|
}
|
|
|
|
if (node.indexed) {
|
|
|
|
throwError(originalParam.length - 7);
|
2019-05-15 01:48:48 +03:00
|
|
|
}
|
2019-05-25 01:15:42 +03:00
|
|
|
node.indexed = true;
|
|
|
|
node.name = "";
|
|
|
|
}
|
|
|
|
else if (storageClasses[node.name]) {
|
|
|
|
node.name = "";
|
2019-05-15 01:48:48 +03:00
|
|
|
}
|
|
|
|
parent.type = verifyType(parent.type);
|
|
|
|
return parent;
|
|
|
|
}
|
|
|
|
function populate(object, params) {
|
|
|
|
for (var key in params) {
|
|
|
|
properties_1.defineReadOnly(object, key, params[key]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
var paramTypeArray = new RegExp(/^(.*)\[([0-9]*)\]$/);
|
|
|
|
var ParamType = /** @class */ (function () {
|
|
|
|
function ParamType(constructorGuard, params) {
|
|
|
|
if (constructorGuard !== _constructorGuard) {
|
|
|
|
throw new Error("use fromString");
|
|
|
|
}
|
|
|
|
populate(this, params);
|
|
|
|
var match = this.type.match(paramTypeArray);
|
|
|
|
if (match) {
|
|
|
|
populate(this, {
|
|
|
|
arrayLength: parseInt(match[2] || "-1"),
|
|
|
|
arrayChildren: ParamType.fromObject({
|
|
|
|
type: match[1],
|
|
|
|
components: this.components
|
|
|
|
}),
|
|
|
|
baseType: "array"
|
|
|
|
});
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
populate(this, {
|
|
|
|
arrayLength: null,
|
|
|
|
arrayChildren: null,
|
|
|
|
baseType: ((this.components != null) ? "tuple" : this.type)
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Format the parameter fragment
|
|
|
|
// - non-expanded: "(uint256,address)"
|
|
|
|
// - expanded: "tuple(uint256 foo, addres bar) indexed baz"
|
|
|
|
ParamType.prototype.format = function (expanded) {
|
|
|
|
var result = "";
|
|
|
|
// Array
|
|
|
|
if (this.baseType === "array") {
|
|
|
|
result += this.arrayChildren.format(expanded);
|
|
|
|
result += "[" + (this.arrayLength < 0 ? "" : String(this.arrayLength)) + "]";
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (this.baseType === "tuple") {
|
|
|
|
if (expanded) {
|
|
|
|
result += this.type;
|
|
|
|
}
|
|
|
|
result += "(" + this.components.map(function (c) { return c.format(expanded); }).join(expanded ? ", " : ",") + ")";
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
result += this.type;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (expanded) {
|
|
|
|
if (this.indexed === true) {
|
|
|
|
result += " indexed";
|
|
|
|
}
|
|
|
|
if (this.name) {
|
|
|
|
result += " " + this.name;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
};
|
|
|
|
ParamType.from = function (value, allowIndexed) {
|
|
|
|
if (typeof (value) === "string") {
|
|
|
|
return ParamType.fromString(value, allowIndexed);
|
|
|
|
}
|
|
|
|
return ParamType.fromObject(value);
|
|
|
|
};
|
|
|
|
ParamType.fromObject = function (value) {
|
|
|
|
if (properties_1.isNamedInstance(ParamType, value)) {
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
return new ParamType(_constructorGuard, {
|
|
|
|
name: (value.name || null),
|
|
|
|
type: verifyType(value.type),
|
|
|
|
indexed: ((value.indexed == null) ? null : !!value.indexed),
|
|
|
|
components: (value.components ? value.components.map(ParamType.fromObject) : null)
|
|
|
|
});
|
|
|
|
};
|
|
|
|
ParamType.fromString = function (value, allowIndexed) {
|
|
|
|
function ParamTypify(node) {
|
|
|
|
return ParamType.fromObject({
|
|
|
|
name: node.name,
|
|
|
|
type: node.type,
|
|
|
|
indexed: node.indexed,
|
|
|
|
components: node.components
|
|
|
|
});
|
|
|
|
}
|
|
|
|
return ParamTypify(parseParamType(value, !!allowIndexed));
|
|
|
|
};
|
|
|
|
return ParamType;
|
|
|
|
}());
|
|
|
|
exports.ParamType = ParamType;
|
|
|
|
;
|
|
|
|
function parseParams(value, allowIndex) {
|
|
|
|
return splitNesting(value).map(function (param) { return ParamType.fromString(param, allowIndex); });
|
|
|
|
}
|
|
|
|
var Fragment = /** @class */ (function () {
|
|
|
|
function Fragment(constructorGuard, params) {
|
|
|
|
if (constructorGuard !== _constructorGuard) {
|
|
|
|
throw new Error("use a static from method");
|
|
|
|
}
|
|
|
|
populate(this, params);
|
|
|
|
}
|
|
|
|
// @TOOD: move logic to sub-classes; make this abstract
|
|
|
|
Fragment.prototype.format = function (expanded) {
|
|
|
|
var result = "";
|
|
|
|
if (this.type === "constructor") {
|
|
|
|
result += "constructor";
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (expanded) {
|
|
|
|
result += this.type + " ";
|
|
|
|
}
|
|
|
|
result += this.name;
|
|
|
|
}
|
|
|
|
result += "(" + this.inputs.map(function (i) { return i.format(expanded); }).join(expanded ? ", " : ",") + ") ";
|
|
|
|
// @TODO: Handle returns, modifiers, etc.
|
|
|
|
if (expanded) {
|
|
|
|
result += "public ";
|
|
|
|
if (this.mutabilityState) {
|
|
|
|
result += this.mutabilityState + " ";
|
|
|
|
}
|
|
|
|
else if (this.constant) {
|
|
|
|
result += "view ";
|
|
|
|
}
|
|
|
|
if (this.outputs && this.outputs.length) {
|
|
|
|
result += "(" + this.outputs.map(function (i) { return i.format(expanded); }).join(", ") + ") ";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result.trim();
|
|
|
|
};
|
|
|
|
Fragment.from = function (value) {
|
|
|
|
if (typeof (value) === "string") {
|
|
|
|
return Fragment.fromString(value);
|
|
|
|
}
|
|
|
|
return Fragment.fromObject(value);
|
|
|
|
};
|
|
|
|
Fragment.fromObject = function (value) {
|
|
|
|
if (properties_1.isNamedInstance(Fragment, value)) {
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
if (value.type === "function") {
|
|
|
|
return FunctionFragment.fromObject(value);
|
|
|
|
}
|
|
|
|
else if (value.type === "event") {
|
|
|
|
return EventFragment.fromObject(value);
|
|
|
|
}
|
|
|
|
else if (value.type === "constructor") {
|
|
|
|
return ConstructorFragment.fromObject(value);
|
|
|
|
}
|
|
|
|
else if (value.type === "fallback") {
|
|
|
|
// @TODO:
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
return errors.throwError("invalid fragment object", errors.INVALID_ARGUMENT, {
|
|
|
|
argument: "value",
|
|
|
|
value: value
|
|
|
|
});
|
|
|
|
};
|
|
|
|
Fragment.fromString = function (value) {
|
|
|
|
// Make sure the "returns" is surrounded by a space and all whitespace is exactly one space
|
|
|
|
value = value.replace(/\s/g, " ");
|
|
|
|
value = value.replace(/\(/g, " (").replace(/\)/g, ") ").replace(/\s+/g, " ");
|
|
|
|
value = value.trim();
|
|
|
|
if (value.split(" ")[0] === "event") {
|
|
|
|
return EventFragment.fromString(value.substring(5).trim());
|
|
|
|
}
|
|
|
|
else if (value.split(" ")[0] === "function") {
|
|
|
|
return FunctionFragment.fromString(value.substring(8).trim());
|
|
|
|
}
|
|
|
|
else if (value.split("(")[0].trim() === "constructor") {
|
|
|
|
return ConstructorFragment.fromString(value.trim());
|
|
|
|
}
|
|
|
|
throw new Error("unknown fragment");
|
|
|
|
};
|
|
|
|
return Fragment;
|
|
|
|
}());
|
|
|
|
exports.Fragment = Fragment;
|
|
|
|
var EventFragment = /** @class */ (function (_super) {
|
|
|
|
__extends(EventFragment, _super);
|
|
|
|
function EventFragment() {
|
|
|
|
return _super !== null && _super.apply(this, arguments) || this;
|
|
|
|
}
|
|
|
|
EventFragment.from = function (value) {
|
|
|
|
if (typeof (value) === "string") {
|
|
|
|
return EventFragment.fromString(value);
|
|
|
|
}
|
|
|
|
return EventFragment.fromObject(value);
|
|
|
|
};
|
|
|
|
EventFragment.fromObject = function (value) {
|
|
|
|
if (properties_1.isNamedInstance(EventFragment, value)) {
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
if (value.type !== "event") {
|
|
|
|
throw new Error("invalid event object - " + value.type);
|
|
|
|
}
|
|
|
|
return new EventFragment(_constructorGuard, {
|
|
|
|
name: verifyIdentifier(value.name),
|
|
|
|
anonymous: value.anonymous,
|
|
|
|
inputs: (value.inputs ? value.inputs.map(ParamType.fromObject) : []),
|
|
|
|
type: "event"
|
|
|
|
});
|
|
|
|
};
|
|
|
|
EventFragment.fromString = function (value) {
|
|
|
|
var match = value.match(regexParen);
|
|
|
|
if (!match) {
|
|
|
|
throw new Error("invalid event: " + value);
|
|
|
|
}
|
|
|
|
var anonymous = false;
|
|
|
|
match[3].split(" ").forEach(function (modifier) {
|
|
|
|
switch (modifier.trim()) {
|
|
|
|
case "anonymous":
|
|
|
|
anonymous = true;
|
|
|
|
break;
|
|
|
|
case "":
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
errors.warn("unknown modifier: " + modifier);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
return EventFragment.fromObject({
|
|
|
|
name: match[1].trim(),
|
|
|
|
anonymous: anonymous,
|
|
|
|
inputs: parseParams(match[2], true),
|
|
|
|
type: "event"
|
|
|
|
});
|
|
|
|
};
|
|
|
|
return EventFragment;
|
|
|
|
}(Fragment));
|
|
|
|
exports.EventFragment = EventFragment;
|
|
|
|
function parseGas(value, params) {
|
|
|
|
params.gas = null;
|
|
|
|
var comps = value.split("@");
|
|
|
|
if (comps.length !== 1) {
|
|
|
|
if (comps.length > 2) {
|
|
|
|
throw new Error("invalid signature");
|
|
|
|
}
|
|
|
|
if (!comps[1].match(/^[0-9]+$/)) {
|
|
|
|
throw new Error("invalid signature gas");
|
|
|
|
}
|
|
|
|
params.gas = bignumber_1.BigNumber.from(comps[1]);
|
|
|
|
return comps[0];
|
|
|
|
}
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
function parseModifiers(value, params) {
|
|
|
|
params.constant = false;
|
|
|
|
params.payable = false;
|
|
|
|
// @TODO: Should this be initialized to "nonpayable"?
|
2019-05-25 01:15:42 +03:00
|
|
|
params.stateMutability = "nonpayable";
|
2019-05-15 01:48:48 +03:00
|
|
|
value.split(" ").forEach(function (modifier) {
|
|
|
|
switch (modifier.trim()) {
|
|
|
|
case "constant":
|
|
|
|
params.constant = true;
|
|
|
|
break;
|
|
|
|
case "payable":
|
|
|
|
params.payable = true;
|
|
|
|
params.stateMutability = "payable";
|
|
|
|
break;
|
|
|
|
case "pure":
|
|
|
|
params.constant = true;
|
|
|
|
params.stateMutability = "pure";
|
|
|
|
break;
|
|
|
|
case "view":
|
|
|
|
params.constant = true;
|
|
|
|
params.stateMutability = "view";
|
|
|
|
break;
|
|
|
|
case "external":
|
|
|
|
case "public":
|
|
|
|
case "":
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
console.log("unknown modifier: " + modifier);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
var ConstructorFragment = /** @class */ (function (_super) {
|
|
|
|
__extends(ConstructorFragment, _super);
|
|
|
|
function ConstructorFragment() {
|
|
|
|
return _super !== null && _super.apply(this, arguments) || this;
|
|
|
|
}
|
|
|
|
ConstructorFragment.from = function (value) {
|
|
|
|
if (typeof (value) === "string") {
|
|
|
|
return ConstructorFragment.fromString(value);
|
|
|
|
}
|
|
|
|
return ConstructorFragment.fromObject(value);
|
|
|
|
};
|
|
|
|
ConstructorFragment.fromObject = function (value) {
|
|
|
|
if (properties_1.isNamedInstance(ConstructorFragment, value)) {
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
if (value.type !== "constructor") {
|
|
|
|
throw new Error("invalid constructor object - " + value.type);
|
|
|
|
}
|
|
|
|
return new ConstructorFragment(_constructorGuard, {
|
|
|
|
type: value.type,
|
|
|
|
inputs: (value.inputs ? value.inputs.map(ParamType.fromObject) : []),
|
|
|
|
payable: ((value.payable == null) ? true : !!value.payable),
|
|
|
|
gas: (value.gas ? bignumber_1.BigNumber.from(value.gas) : null)
|
|
|
|
});
|
|
|
|
};
|
|
|
|
ConstructorFragment.fromString = function (value) {
|
|
|
|
var params = { type: "constructor" };
|
|
|
|
value = parseGas(value, params);
|
|
|
|
var parens = value.match(regexParen);
|
|
|
|
if (!parens) {
|
|
|
|
throw new Error("invalid constructor: " + value);
|
|
|
|
}
|
|
|
|
if (parens[1].trim() !== "constructor") {
|
|
|
|
throw new Error("invalid constructor");
|
|
|
|
}
|
|
|
|
params.inputs = parseParams(parens[2].trim(), false);
|
|
|
|
parseModifiers(parens[3].trim(), params);
|
|
|
|
return ConstructorFragment.fromObject(params);
|
|
|
|
};
|
|
|
|
return ConstructorFragment;
|
|
|
|
}(Fragment));
|
|
|
|
exports.ConstructorFragment = ConstructorFragment;
|
|
|
|
var FunctionFragment = /** @class */ (function (_super) {
|
|
|
|
__extends(FunctionFragment, _super);
|
|
|
|
function FunctionFragment() {
|
|
|
|
return _super !== null && _super.apply(this, arguments) || this;
|
|
|
|
}
|
|
|
|
FunctionFragment.from = function (value) {
|
|
|
|
if (typeof (value) === "string") {
|
|
|
|
return FunctionFragment.fromString(value);
|
|
|
|
}
|
|
|
|
return FunctionFragment.fromObject(value);
|
|
|
|
};
|
|
|
|
FunctionFragment.fromObject = function (value) {
|
|
|
|
if (properties_1.isNamedInstance(FunctionFragment, value)) {
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
if (value.type !== "function") {
|
|
|
|
throw new Error("invalid function object - " + value.type);
|
|
|
|
}
|
|
|
|
return new FunctionFragment(_constructorGuard, {
|
|
|
|
type: value.type,
|
|
|
|
name: verifyIdentifier(value.name),
|
|
|
|
constant: !!value.constant,
|
|
|
|
inputs: (value.inputs ? value.inputs.map(ParamType.fromObject) : []),
|
|
|
|
outputs: (value.outputs ? value.outputs.map(ParamType.fromObject) : []),
|
|
|
|
payable: ((value.payable == null) ? true : !!value.payable),
|
|
|
|
stateMutability: ((value.stateMutability != null) ? verifyString(value.stateMutability) : null),
|
|
|
|
gas: (value.gas ? bignumber_1.BigNumber.from(value.gas) : null)
|
|
|
|
});
|
|
|
|
};
|
|
|
|
FunctionFragment.fromString = function (value) {
|
|
|
|
var params = { type: "function" };
|
|
|
|
value = parseGas(value, params);
|
|
|
|
var comps = value.split(" returns ");
|
|
|
|
if (comps.length > 2) {
|
|
|
|
throw new Error("invalid function");
|
|
|
|
}
|
|
|
|
var parens = comps[0].match(regexParen);
|
|
|
|
if (!parens) {
|
|
|
|
throw new Error("invalid signature");
|
|
|
|
}
|
|
|
|
params.name = parens[1].trim();
|
|
|
|
if (!params.name.match(regexIdentifier)) {
|
|
|
|
throw new Error("invalid identifier: '" + params.name + "'");
|
|
|
|
}
|
|
|
|
params.inputs = parseParams(parens[2], false);
|
|
|
|
parseModifiers(parens[3].trim(), params);
|
|
|
|
// We have outputs
|
|
|
|
if (comps.length > 1) {
|
|
|
|
var returns = comps[1].match(regexParen);
|
|
|
|
if (returns[1].trim() != "" || returns[3].trim() != "") {
|
|
|
|
throw new Error("unexpected tokens");
|
|
|
|
}
|
|
|
|
params.outputs = parseParams(returns[2], false);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
params.outputs = [];
|
|
|
|
}
|
|
|
|
return FunctionFragment.fromObject(params);
|
|
|
|
};
|
|
|
|
return FunctionFragment;
|
|
|
|
}(ConstructorFragment));
|
|
|
|
exports.FunctionFragment = FunctionFragment;
|
|
|
|
//export class ErrorFragment extends Fragment {
|
|
|
|
//}
|
|
|
|
//export class StructFragment extends Fragment {
|
|
|
|
//}
|
|
|
|
function verifyString(value) {
|
|
|
|
if (typeof (value) !== "string") {
|
|
|
|
throw new Error("requires a string");
|
|
|
|
}
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
function verifyType(type) {
|
|
|
|
// These need to be transformed to their full description
|
|
|
|
if (type.match(/^uint($|[^1-9])/)) {
|
|
|
|
type = "uint256" + type.substring(4);
|
|
|
|
}
|
|
|
|
else if (type.match(/^int($|[^1-9])/)) {
|
|
|
|
type = "int256" + type.substring(3);
|
|
|
|
}
|
|
|
|
// @TODO: more verification
|
|
|
|
return type;
|
|
|
|
}
|
|
|
|
var regexIdentifier = new RegExp("^[A-Za-z_][A-Za-z0-9_]*$");
|
|
|
|
function verifyIdentifier(value) {
|
|
|
|
if (!value || !value.match(regexIdentifier)) {
|
|
|
|
throw new Error("invalid identifier: '" + value + "'");
|
|
|
|
}
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
var regexParen = new RegExp("^([^)(]*)\\((.*)\\)([^)(]*)$");
|
|
|
|
function splitNesting(value) {
|
|
|
|
value = value.trim();
|
|
|
|
var result = [];
|
|
|
|
var accum = "";
|
|
|
|
var depth = 0;
|
|
|
|
for (var offset = 0; offset < value.length; offset++) {
|
|
|
|
var c = value[offset];
|
|
|
|
if (c === "," && depth === 0) {
|
|
|
|
result.push(accum);
|
|
|
|
accum = "";
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
accum += c;
|
|
|
|
if (c === "(") {
|
|
|
|
depth++;
|
|
|
|
}
|
|
|
|
else if (c === ")") {
|
|
|
|
depth--;
|
|
|
|
if (depth === -1) {
|
|
|
|
throw new Error("unbalanced parenthsis");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (accum) {
|
|
|
|
result.push(accum);
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|