ethers.js/packages/abi/lib/fragments.js

821 lines
30 KiB
JavaScript
Raw Permalink Normal View History

2019-05-14 18:48:48 -04: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 __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
var bignumber_1 = require("@ethersproject/bignumber");
var properties_1 = require("@ethersproject/properties");
2019-08-02 02:10:58 -04:00
var logger_1 = require("@ethersproject/logger");
var _version_1 = require("./_version");
var logger = new logger_1.Logger(_version_1.version);
2019-05-14 18:48:48 -04:00
;
var _constructorGuard = {};
2019-07-20 20:13:00 -03:00
var ModifiersBytes = { calldata: true, memory: true, storage: true };
2020-05-01 17:00:44 -04:00
var ModifiersNest = { calldata: true, memory: true };
2019-07-20 20:13:00 -03:00
function checkModifier(type, name) {
if (type === "bytes" || type === "string") {
if (ModifiersBytes[name]) {
return true;
}
}
else if (type === "address") {
if (name === "payable") {
return true;
}
}
2020-05-01 17:00:44 -04:00
else if (type.indexOf("[") >= 0 || type === "tuple") {
if (ModifiersNest[name]) {
return true;
}
}
2019-07-20 20:13:00 -03:00
if (ModifiersBytes[name] || name === "payable") {
2019-08-02 02:10:58 -04:00
logger.throwArgumentError("invalid modifier", "name", name);
2019-07-20 20:13:00 -03:00
}
return false;
}
2019-05-14 18:48:48 -04: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) {
2020-04-15 18:28:04 -04:00
logger.throwArgumentError("unexpected character at position " + i, "param", param);
2019-05-14 18:48:48 -04:00
}
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 "(":
2019-11-20 18:57:38 +09:00
if (node.state.allowType && node.type === "") {
node.type = "tuple";
}
else if (!node.state.allowParams) {
2019-05-14 18:48:48 -04:00
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-24 18:15:42 -04:00
if (node.name === "indexed") {
if (!allowIndexed) {
throwError(i);
2019-05-14 18:48:48 -04:00
}
2019-05-24 18:15:42 -04:00
node.indexed = true;
node.name = "";
}
2019-07-20 20:13:00 -03:00
if (checkModifier(node.type, node.name)) {
2019-05-24 18:15:42 -04:00
node.name = "";
2019-05-14 18:48:48 -04: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-24 18:15:42 -04:00
if (node.name === "indexed") {
if (!allowIndexed) {
throwError(i);
2019-05-14 18:48:48 -04:00
}
2019-05-24 18:15:42 -04:00
node.indexed = true;
node.name = "";
}
2019-07-20 20:13:00 -03:00
if (checkModifier(node.type, node.name)) {
2019-05-24 18:15:42 -04:00
node.name = "";
2019-05-14 18:48:48 -04: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-24 18:15:42 -04:00
if (node.name === "indexed") {
if (!allowIndexed) {
throwError(i);
2019-05-14 18:48:48 -04:00
}
2019-05-24 18:15:42 -04:00
if (node.indexed) {
throwError(i);
}
node.indexed = true;
node.name = "";
}
2019-07-20 20:13:00 -03:00
else if (checkModifier(node.type, node.name)) {
2019-05-24 18:15:42 -04:00
node.name = "";
2019-05-14 18:48:48 -04: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) {
2020-04-15 18:28:04 -04:00
logger.throwArgumentError("unexpected eof", "param", param);
2019-05-14 18:48:48 -04:00
}
delete parent.state;
2019-05-24 18:15:42 -04:00
if (node.name === "indexed") {
if (!allowIndexed) {
throwError(originalParam.length - 7);
}
if (node.indexed) {
throwError(originalParam.length - 7);
2019-05-14 18:48:48 -04:00
}
2019-05-24 18:15:42 -04:00
node.indexed = true;
node.name = "";
}
2019-07-20 20:13:00 -03:00
else if (checkModifier(node.type, node.name)) {
2019-05-24 18:15:42 -04:00
node.name = "";
2019-05-14 18:48:48 -04:00
}
parent.type = verifyType(parent.type);
return parent;
}
function populate(object, params) {
for (var key in params) {
properties_1.defineReadOnly(object, key, params[key]);
}
}
2019-07-20 20:13:00 -03:00
exports.FormatTypes = Object.freeze({
// Bare formatting, as is needed for computing a sighash of an event or function
sighash: "sighash",
// Human-Readable with Minimal spacing and without names (compact human-readable)
minimal: "minimal",
// Human-Readble with nice spacing, including all names
full: "full",
// JSON-format a la Solidity
json: "json"
});
2019-05-14 18:48:48 -04:00
var paramTypeArray = new RegExp(/^(.*)\[([0-9]*)\]$/);
var ParamType = /** @class */ (function () {
function ParamType(constructorGuard, params) {
if (constructorGuard !== _constructorGuard) {
2020-04-15 18:28:04 -04:00
logger.throwError("use fromString", logger_1.Logger.errors.UNSUPPORTED_OPERATION, {
operation: "new ParamType()"
});
2019-05-14 18:48:48 -04:00
}
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)
});
}
2019-06-11 17:57:04 -04:00
this._isParamType = true;
Object.freeze(this);
2019-05-14 18:48:48 -04:00
}
// Format the parameter fragment
2019-07-20 20:13:00 -03:00
// - sighash: "(uint256,address)"
// - minimal: "tuple(uint256,address) indexed"
// - full: "tuple(uint256 foo, addres bar) indexed baz"
ParamType.prototype.format = function (format) {
if (!format) {
format = exports.FormatTypes.sighash;
}
if (!exports.FormatTypes[format]) {
2019-08-02 02:10:58 -04:00
logger.throwArgumentError("invalid format type", "format", format);
2019-07-20 20:13:00 -03:00
}
if (format === exports.FormatTypes.json) {
var result_1 = {
type: ((this.baseType === "tuple") ? "tuple" : this.type),
name: (this.name || undefined)
};
if (typeof (this.indexed) === "boolean") {
result_1.indexed = this.indexed;
}
if (this.components) {
result_1.components = this.components.map(function (comp) { return JSON.parse(comp.format(format)); });
}
return JSON.stringify(result_1);
}
2019-05-14 18:48:48 -04:00
var result = "";
// Array
if (this.baseType === "array") {
2019-07-20 20:13:00 -03:00
result += this.arrayChildren.format(format);
2019-05-14 18:48:48 -04:00
result += "[" + (this.arrayLength < 0 ? "" : String(this.arrayLength)) + "]";
}
else {
if (this.baseType === "tuple") {
2019-07-20 20:13:00 -03:00
if (format !== exports.FormatTypes.sighash) {
2019-05-14 18:48:48 -04:00
result += this.type;
}
2019-07-20 20:13:00 -03:00
result += "(" + this.components.map(function (comp) { return comp.format(format); }).join((format === exports.FormatTypes.full) ? ", " : ",") + ")";
2019-05-14 18:48:48 -04:00
}
else {
result += this.type;
}
}
2019-07-20 20:13:00 -03:00
if (format !== exports.FormatTypes.sighash) {
2019-05-14 18:48:48 -04:00
if (this.indexed === true) {
result += " indexed";
}
2019-07-20 20:13:00 -03:00
if (format === exports.FormatTypes.full && this.name) {
2019-05-14 18:48:48 -04:00
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) {
2019-06-11 17:57:04 -04:00
if (ParamType.isParamType(value)) {
2019-05-14 18:48:48 -04:00
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));
};
2019-06-11 17:57:04 -04:00
ParamType.isParamType = function (value) {
return !!(value != null && value._isParamType);
};
2019-05-14 18:48:48 -04:00
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) {
2020-04-15 18:28:04 -04:00
logger.throwError("use a static from method", logger_1.Logger.errors.UNSUPPORTED_OPERATION, {
operation: "new Fragment()"
});
2019-05-14 18:48:48 -04:00
}
populate(this, params);
2019-06-11 17:57:04 -04:00
this._isFragment = true;
Object.freeze(this);
2019-05-14 18:48:48 -04:00
}
Fragment.from = function (value) {
2019-06-11 17:57:04 -04:00
if (Fragment.isFragment(value)) {
return value;
}
2019-05-14 18:48:48 -04:00
if (typeof (value) === "string") {
return Fragment.fromString(value);
}
return Fragment.fromObject(value);
};
Fragment.fromObject = function (value) {
2019-06-11 17:57:04 -04:00
if (Fragment.isFragment(value)) {
2019-05-14 18:48:48 -04:00
return value;
}
2020-03-21 12:48:22 -04:00
switch (value.type) {
case "function":
return FunctionFragment.fromObject(value);
case "event":
return EventFragment.fromObject(value);
case "constructor":
return ConstructorFragment.fromObject(value);
case "fallback":
case "receive":
// @TODO: Something? Maybe return a FunctionFragment? A custom DefaultFunctionFragment?
return null;
2019-05-14 18:48:48 -04:00
}
2019-08-02 02:10:58 -04:00
return logger.throwArgumentError("invalid fragment object", "value", value);
2019-05-14 18:48:48 -04:00
};
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());
}
2020-04-15 18:28:04 -04:00
return logger.throwArgumentError("unsupported fragment", "value", value);
2019-05-14 18:48:48 -04:00
};
2019-06-11 17:57:04 -04:00
Fragment.isFragment = function (value) {
return !!(value && value._isFragment);
};
2019-05-14 18:48:48 -04:00
return Fragment;
}());
exports.Fragment = Fragment;
var EventFragment = /** @class */ (function (_super) {
__extends(EventFragment, _super);
function EventFragment() {
return _super !== null && _super.apply(this, arguments) || this;
}
2019-07-20 20:13:00 -03:00
EventFragment.prototype.format = function (format) {
if (!format) {
format = exports.FormatTypes.sighash;
}
if (!exports.FormatTypes[format]) {
2019-08-02 02:10:58 -04:00
logger.throwArgumentError("invalid format type", "format", format);
2019-07-20 20:13:00 -03:00
}
if (format === exports.FormatTypes.json) {
return JSON.stringify({
type: "event",
anonymous: this.anonymous,
name: this.name,
inputs: this.inputs.map(function (input) { return JSON.parse(input.format(format)); })
});
}
var result = "";
if (format !== exports.FormatTypes.sighash) {
result += "event ";
}
result += this.name + "(" + this.inputs.map(function (input) { return input.format(format); }).join((format === exports.FormatTypes.full) ? ", " : ",") + ") ";
if (format !== exports.FormatTypes.sighash) {
if (this.anonymous) {
result += "anonymous ";
}
}
return result.trim();
};
2019-05-14 18:48:48 -04:00
EventFragment.from = function (value) {
if (typeof (value) === "string") {
return EventFragment.fromString(value);
}
return EventFragment.fromObject(value);
};
EventFragment.fromObject = function (value) {
2019-06-11 17:57:04 -04:00
if (EventFragment.isEventFragment(value)) {
2019-05-14 18:48:48 -04:00
return value;
}
if (value.type !== "event") {
2020-04-15 18:28:04 -04:00
logger.throwArgumentError("invalid event object", "value", value);
2019-05-14 18:48:48 -04:00
}
2020-04-25 03:54:54 -04:00
var params = {
2019-05-14 18:48:48 -04:00
name: verifyIdentifier(value.name),
anonymous: value.anonymous,
inputs: (value.inputs ? value.inputs.map(ParamType.fromObject) : []),
type: "event"
2020-04-25 03:54:54 -04:00
};
return new EventFragment(_constructorGuard, params);
2019-05-14 18:48:48 -04:00
};
EventFragment.fromString = function (value) {
var match = value.match(regexParen);
if (!match) {
2020-04-15 18:28:04 -04:00
logger.throwArgumentError("invalid event string", "value", value);
2019-05-14 18:48:48 -04:00
}
var anonymous = false;
match[3].split(" ").forEach(function (modifier) {
switch (modifier.trim()) {
case "anonymous":
anonymous = true;
break;
case "":
break;
default:
2019-08-02 02:10:58 -04:00
logger.warn("unknown modifier: " + modifier);
2019-05-14 18:48:48 -04:00
}
});
return EventFragment.fromObject({
name: match[1].trim(),
anonymous: anonymous,
inputs: parseParams(match[2], true),
type: "event"
});
};
2019-06-11 17:57:04 -04:00
EventFragment.isEventFragment = function (value) {
return (value && value._isFragment && value.type === "event");
};
2019-05-14 18:48:48 -04:00
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) {
2020-04-15 18:28:04 -04:00
logger.throwArgumentError("invalid human-readable ABI signature", "value", value);
2019-05-14 18:48:48 -04:00
}
if (!comps[1].match(/^[0-9]+$/)) {
2020-04-23 23:35:39 -04:00
logger.throwArgumentError("invalid human-readable ABI signature gas", "value", value);
2019-05-14 18:48:48 -04:00
}
params.gas = bignumber_1.BigNumber.from(comps[1]);
return comps[0];
}
return value;
}
function parseModifiers(value, params) {
params.constant = false;
params.payable = false;
2019-05-24 18:15:42 -04:00
params.stateMutability = "nonpayable";
2019-05-14 18:48:48 -04:00
value.split(" ").forEach(function (modifier) {
switch (modifier.trim()) {
case "constant":
params.constant = true;
break;
case "payable":
params.payable = true;
params.stateMutability = "payable";
break;
2020-06-12 04:57:38 -04:00
case "nonpayable":
params.payable = false;
params.stateMutability = "nonpayable";
break;
2019-05-14 18:48:48 -04:00
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);
}
});
}
2019-07-20 20:13:00 -03:00
function verifyState(value) {
var result = {
constant: false,
payable: true,
stateMutability: "payable"
};
if (value.stateMutability != null) {
result.stateMutability = value.stateMutability;
2020-04-03 22:13:06 -04:00
// Set (and check things are consistent) the constant property
2019-07-20 20:13:00 -03:00
result.constant = (result.stateMutability === "view" || result.stateMutability === "pure");
if (value.constant != null) {
if ((!!value.constant) !== result.constant) {
2020-04-15 18:28:04 -04:00
logger.throwArgumentError("cannot have constant function with mutability " + result.stateMutability, "value", value);
2019-07-20 20:13:00 -03:00
}
}
2020-04-03 22:13:06 -04:00
// Set (and check things are consistent) the payable property
2019-07-20 20:13:00 -03:00
result.payable = (result.stateMutability === "payable");
if (value.payable != null) {
if ((!!value.payable) !== result.payable) {
2020-04-15 18:28:04 -04:00
logger.throwArgumentError("cannot have payable function with mutability " + result.stateMutability, "value", value);
2019-07-20 20:13:00 -03:00
}
}
}
else if (value.payable != null) {
result.payable = !!value.payable;
2020-04-03 22:13:06 -04:00
// If payable we can assume non-constant; otherwise we can't assume
if (value.constant == null && !result.payable && value.type !== "constructor") {
2020-04-15 18:28:04 -04:00
logger.throwArgumentError("unable to determine stateMutability", "value", value);
2020-04-03 22:13:06 -04:00
}
result.constant = !!value.constant;
if (result.constant) {
result.stateMutability = "view";
}
else {
result.stateMutability = (result.payable ? "payable" : "nonpayable");
}
if (result.payable && result.constant) {
2020-04-15 18:28:04 -04:00
logger.throwArgumentError("cannot have constant payable function", "value", value);
2019-07-20 20:13:00 -03:00
}
}
else if (value.constant != null) {
result.constant = !!value.constant;
result.payable = !result.constant;
result.stateMutability = (result.constant ? "view" : "payable");
}
2020-04-03 22:13:06 -04:00
else if (value.type !== "constructor") {
2020-04-15 18:28:04 -04:00
logger.throwArgumentError("unable to determine stateMutability", "value", value);
2020-04-03 22:13:06 -04:00
}
2019-07-20 20:13:00 -03:00
return result;
}
2019-05-14 18:48:48 -04:00
var ConstructorFragment = /** @class */ (function (_super) {
__extends(ConstructorFragment, _super);
function ConstructorFragment() {
return _super !== null && _super.apply(this, arguments) || this;
}
2019-07-20 20:13:00 -03:00
ConstructorFragment.prototype.format = function (format) {
if (!format) {
format = exports.FormatTypes.sighash;
}
if (!exports.FormatTypes[format]) {
2019-08-02 02:10:58 -04:00
logger.throwArgumentError("invalid format type", "format", format);
2019-07-20 20:13:00 -03:00
}
if (format === exports.FormatTypes.json) {
return JSON.stringify({
type: "constructor",
stateMutability: ((this.stateMutability !== "nonpayable") ? this.stateMutability : undefined),
payble: this.payable,
gas: (this.gas ? this.gas.toNumber() : undefined),
inputs: this.inputs.map(function (input) { return JSON.parse(input.format(format)); })
});
}
if (format === exports.FormatTypes.sighash) {
2019-08-02 02:10:58 -04:00
logger.throwError("cannot format a constructor for sighash", logger_1.Logger.errors.UNSUPPORTED_OPERATION, {
2019-07-20 20:13:00 -03:00
operation: "format(sighash)"
});
}
var result = "constructor(" + this.inputs.map(function (input) { return input.format(format); }).join((format === exports.FormatTypes.full) ? ", " : ",") + ") ";
if (this.stateMutability && this.stateMutability !== "nonpayable") {
result += this.stateMutability + " ";
}
return result.trim();
};
2019-05-14 18:48:48 -04:00
ConstructorFragment.from = function (value) {
if (typeof (value) === "string") {
return ConstructorFragment.fromString(value);
}
return ConstructorFragment.fromObject(value);
};
ConstructorFragment.fromObject = function (value) {
2019-06-11 17:57:04 -04:00
if (ConstructorFragment.isConstructorFragment(value)) {
2019-05-14 18:48:48 -04:00
return value;
}
if (value.type !== "constructor") {
2020-04-15 18:28:04 -04:00
logger.throwArgumentError("invalid constructor object", "value", value);
2019-05-14 18:48:48 -04:00
}
2019-07-20 20:13:00 -03:00
var state = verifyState(value);
if (state.constant) {
2020-04-15 18:28:04 -04:00
logger.throwArgumentError("constructor cannot be constant", "value", value);
2019-07-20 20:13:00 -03:00
}
2020-04-25 03:54:54 -04:00
var params = {
2020-01-06 19:00:55 -05:00
name: null,
2019-05-14 18:48:48 -04:00
type: value.type,
inputs: (value.inputs ? value.inputs.map(ParamType.fromObject) : []),
2019-07-20 20:13:00 -03:00
payable: state.payable,
2020-04-25 03:54:54 -04:00
stateMutability: state.stateMutability,
2019-05-14 18:48:48 -04:00
gas: (value.gas ? bignumber_1.BigNumber.from(value.gas) : null)
2020-04-25 03:54:54 -04:00
};
return new ConstructorFragment(_constructorGuard, params);
2019-05-14 18:48:48 -04:00
};
ConstructorFragment.fromString = function (value) {
var params = { type: "constructor" };
value = parseGas(value, params);
var parens = value.match(regexParen);
2020-04-15 18:28:04 -04:00
if (!parens || parens[1].trim() !== "constructor") {
logger.throwArgumentError("invalid constructor string", "value", value);
2019-05-14 18:48:48 -04:00
}
params.inputs = parseParams(parens[2].trim(), false);
parseModifiers(parens[3].trim(), params);
return ConstructorFragment.fromObject(params);
};
2019-06-11 17:57:04 -04:00
ConstructorFragment.isConstructorFragment = function (value) {
return (value && value._isFragment && value.type === "constructor");
};
2019-05-14 18:48:48 -04:00
return ConstructorFragment;
}(Fragment));
exports.ConstructorFragment = ConstructorFragment;
var FunctionFragment = /** @class */ (function (_super) {
__extends(FunctionFragment, _super);
function FunctionFragment() {
return _super !== null && _super.apply(this, arguments) || this;
}
2019-07-20 20:13:00 -03:00
FunctionFragment.prototype.format = function (format) {
if (!format) {
format = exports.FormatTypes.sighash;
}
if (!exports.FormatTypes[format]) {
2019-08-02 02:10:58 -04:00
logger.throwArgumentError("invalid format type", "format", format);
2019-07-20 20:13:00 -03:00
}
if (format === exports.FormatTypes.json) {
return JSON.stringify({
type: "function",
name: this.name,
constant: this.constant,
stateMutability: ((this.stateMutability !== "nonpayable") ? this.stateMutability : undefined),
payble: this.payable,
gas: (this.gas ? this.gas.toNumber() : undefined),
inputs: this.inputs.map(function (input) { return JSON.parse(input.format(format)); }),
ouputs: this.outputs.map(function (output) { return JSON.parse(output.format(format)); }),
});
}
var result = "";
if (format !== exports.FormatTypes.sighash) {
result += "function ";
}
result += this.name + "(" + this.inputs.map(function (input) { return input.format(format); }).join((format === exports.FormatTypes.full) ? ", " : ",") + ") ";
if (format !== exports.FormatTypes.sighash) {
if (this.stateMutability) {
if (this.stateMutability !== "nonpayable") {
result += (this.stateMutability + " ");
}
}
else if (this.constant) {
result += "view ";
}
if (this.outputs && this.outputs.length) {
result += "returns (" + this.outputs.map(function (output) { return output.format(format); }).join(", ") + ") ";
}
if (this.gas != null) {
result += "@" + this.gas.toString() + " ";
}
}
return result.trim();
};
2019-05-14 18:48:48 -04:00
FunctionFragment.from = function (value) {
if (typeof (value) === "string") {
return FunctionFragment.fromString(value);
}
return FunctionFragment.fromObject(value);
};
FunctionFragment.fromObject = function (value) {
2019-06-11 17:57:04 -04:00
if (FunctionFragment.isFunctionFragment(value)) {
2019-05-14 18:48:48 -04:00
return value;
}
if (value.type !== "function") {
2020-04-15 18:28:04 -04:00
logger.throwArgumentError("invalid function object", "value", value);
2019-05-14 18:48:48 -04:00
}
2019-07-20 20:13:00 -03:00
var state = verifyState(value);
2020-04-25 03:54:54 -04:00
var params = {
2019-05-14 18:48:48 -04:00
type: value.type,
name: verifyIdentifier(value.name),
2019-07-20 20:13:00 -03:00
constant: state.constant,
2019-05-14 18:48:48 -04:00
inputs: (value.inputs ? value.inputs.map(ParamType.fromObject) : []),
outputs: (value.outputs ? value.outputs.map(ParamType.fromObject) : []),
2019-07-20 20:13:00 -03:00
payable: state.payable,
stateMutability: state.stateMutability,
2019-05-14 18:48:48 -04:00
gas: (value.gas ? bignumber_1.BigNumber.from(value.gas) : null)
2020-04-25 03:54:54 -04:00
};
return new FunctionFragment(_constructorGuard, params);
2019-05-14 18:48:48 -04:00
};
FunctionFragment.fromString = function (value) {
var params = { type: "function" };
value = parseGas(value, params);
var comps = value.split(" returns ");
if (comps.length > 2) {
2020-04-15 18:28:04 -04:00
logger.throwArgumentError("invalid function string", "value", value);
2019-05-14 18:48:48 -04:00
}
var parens = comps[0].match(regexParen);
if (!parens) {
2020-04-15 18:28:04 -04:00
logger.throwArgumentError("invalid function signature", "value", value);
2019-05-14 18:48:48 -04:00
}
params.name = parens[1].trim();
2020-04-15 18:28:04 -04:00
if (params.name) {
verifyIdentifier(params.name);
2019-05-14 18:48:48 -04:00
}
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() != "") {
2020-04-15 18:28:04 -04:00
logger.throwArgumentError("unexpected tokens", "value", value);
2019-05-14 18:48:48 -04:00
}
params.outputs = parseParams(returns[2], false);
}
else {
params.outputs = [];
}
return FunctionFragment.fromObject(params);
};
2019-06-11 17:57:04 -04:00
FunctionFragment.isFunctionFragment = function (value) {
return (value && value._isFragment && value.type === "function");
};
2019-05-14 18:48:48 -04:00
return FunctionFragment;
}(ConstructorFragment));
exports.FunctionFragment = FunctionFragment;
//export class ErrorFragment extends Fragment {
//}
//export class StructFragment extends Fragment {
//}
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)) {
2020-04-15 18:28:04 -04:00
logger.throwArgumentError("invalid identifier \"" + value + "\"", "value", value);
2019-05-14 18:48:48 -04:00
}
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) {
2020-04-23 23:35:39 -04:00
logger.throwArgumentError("unbalanced parenthesis", "value", value);
2019-05-14 18:48:48 -04:00
}
}
}
}
if (accum) {
result.push(accum);
}
return result;
}
2020-07-13 08:03:56 -04:00
//# sourceMappingURL=fragments.js.map