Simplified Fragment API
This commit is contained in:
parent
4e94617ea8
commit
992c7eef07
@ -376,7 +376,7 @@ function consumeMutability(tokens: TokenString): string {
|
|||||||
|
|
||||||
// ...a parameter list, returning the ParamType list
|
// ...a parameter list, returning the ParamType list
|
||||||
function consumeParams(tokens: TokenString, allowIndexed?: boolean): Array<ParamType> {
|
function consumeParams(tokens: TokenString, allowIndexed?: boolean): Array<ParamType> {
|
||||||
return tokens.popParams().map((t) => ParamType.fromTokens(t, allowIndexed));
|
return tokens.popParams().map((t) => ParamType.from(t, allowIndexed));
|
||||||
}
|
}
|
||||||
|
|
||||||
// ...a gas limit, returning a BigNumber or null if none
|
// ...a gas limit, returning a BigNumber or null if none
|
||||||
@ -433,7 +433,13 @@ export type FragmentWalkFunc = (type: string, value: any) => any;
|
|||||||
export type FragmentWalkAsyncFunc = (type: string, value: any) => any | Promise<any>;
|
export type FragmentWalkAsyncFunc = (type: string, value: any) => any | Promise<any>;
|
||||||
|
|
||||||
const internal = Symbol.for("_ethers_internal");
|
const internal = Symbol.for("_ethers_internal");
|
||||||
|
|
||||||
const ParamTypeInternal = "_ParamTypeInternal";
|
const ParamTypeInternal = "_ParamTypeInternal";
|
||||||
|
const ErrorFragmentInternal = "_ErrorInternal";
|
||||||
|
const EventFragmentInternal = "_EventInternal";
|
||||||
|
const ConstructorFragmentInternal = "_ConstructorInternal";
|
||||||
|
const FunctionFragmentInternal = "_FunctionInternal";
|
||||||
|
const StructFragmentInternal = "_StructInternal";
|
||||||
|
|
||||||
export class ParamType {
|
export class ParamType {
|
||||||
|
|
||||||
@ -640,8 +646,51 @@ export class ParamType {
|
|||||||
|
|
||||||
static from(obj: any, allowIndexed?: boolean): ParamType {
|
static from(obj: any, allowIndexed?: boolean): ParamType {
|
||||||
if (ParamType.isParamType(obj)) { return obj; }
|
if (ParamType.isParamType(obj)) { return obj; }
|
||||||
if (typeof(obj) === "string") { return ParamType.fromTokens(lex(obj), allowIndexed); }
|
|
||||||
if (obj instanceof TokenString) { return ParamType.fromTokens(obj, allowIndexed); }
|
if (typeof(obj) === "string") {
|
||||||
|
return ParamType.from(lex(obj), allowIndexed);
|
||||||
|
|
||||||
|
} else if (obj instanceof TokenString) {
|
||||||
|
let type = "", baseType = "";
|
||||||
|
let comps: null | Array<ParamType> = null;
|
||||||
|
|
||||||
|
if (consumeKeywords(obj, setify([ "tuple" ])).has("tuple") || obj.peekType("OPEN_PAREN")) {
|
||||||
|
// Tuple
|
||||||
|
baseType = "tuple";
|
||||||
|
comps = obj.popParams().map((t) => ParamType.from(t));
|
||||||
|
type = `tuple(${ comps.map((c) => c.format()).join(",") })`;
|
||||||
|
} else {
|
||||||
|
// Normal
|
||||||
|
type = verifyBasicType(obj.popType("TYPE"));
|
||||||
|
baseType = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for Array
|
||||||
|
let arrayChildren: null | ParamType = null;
|
||||||
|
let arrayLength: null | number = null;
|
||||||
|
|
||||||
|
while (obj.length && obj.peekType("BRACKET")) {
|
||||||
|
const bracket = obj.pop(); //arrays[i];
|
||||||
|
arrayChildren = new ParamType(_guard, "", type, baseType, null, comps, arrayLength, arrayChildren);
|
||||||
|
arrayLength = bracket.value;
|
||||||
|
type += bracket.text;
|
||||||
|
baseType = "array";
|
||||||
|
comps = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let indexed = null;
|
||||||
|
const keywords = consumeKeywords(obj, KwModifiers);
|
||||||
|
if (keywords.has("indexed")) {
|
||||||
|
if (!allowIndexed) { throw new Error(""); }
|
||||||
|
indexed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const name = (obj.peekType("ID") ? obj.pop().text: "");
|
||||||
|
|
||||||
|
if (obj.length) { throw new Error("leftover tokens"); }
|
||||||
|
|
||||||
|
return new ParamType(_guard, name, type, baseType, indexed, comps, arrayLength, arrayChildren);
|
||||||
|
}
|
||||||
|
|
||||||
const name = obj.name;
|
const name = obj.name;
|
||||||
if (name && (typeof(name) !== "string" || !name.match(regexIdentifier))) {
|
if (name && (typeof(name) !== "string" || !name.match(regexIdentifier))) {
|
||||||
@ -681,52 +730,6 @@ export class ParamType {
|
|||||||
return new ParamType(_guard, name, type, type, indexed, null, null, null);
|
return new ParamType(_guard, name, type, type, indexed, null, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromObject(obj: any, allowIndexed?: boolean): ParamType {
|
|
||||||
throw new Error("@TODO");
|
|
||||||
}
|
|
||||||
|
|
||||||
static fromTokens(tokens: TokenString, allowIndexed?: boolean): ParamType {
|
|
||||||
let type = "", baseType = "";
|
|
||||||
let comps: null | Array<ParamType> = null;
|
|
||||||
|
|
||||||
if (consumeKeywords(tokens, setify([ "tuple" ])).has("tuple") || tokens.peekType("OPEN_PAREN")) {
|
|
||||||
// Tuple
|
|
||||||
baseType = "tuple";
|
|
||||||
comps = tokens.popParams().map((t) => ParamType.from(t));
|
|
||||||
type = `tuple(${ comps.map((c) => c.format()).join(",") })`;
|
|
||||||
} else {
|
|
||||||
// Normal
|
|
||||||
type = verifyBasicType(tokens.popType("TYPE"));
|
|
||||||
baseType = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for Array
|
|
||||||
let arrayChildren: null | ParamType = null;
|
|
||||||
let arrayLength: null | number = null;
|
|
||||||
|
|
||||||
while (tokens.length && tokens.peekType("BRACKET")) {
|
|
||||||
const bracket = tokens.pop(); //arrays[i];
|
|
||||||
arrayChildren = new ParamType(_guard, "", type, baseType, null, comps, arrayLength, arrayChildren);
|
|
||||||
arrayLength = bracket.value;
|
|
||||||
type += bracket.text;
|
|
||||||
baseType = "array";
|
|
||||||
comps = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
let indexed = null;
|
|
||||||
const keywords = consumeKeywords(tokens, KwModifiers);
|
|
||||||
if (keywords.has("indexed")) {
|
|
||||||
if (!allowIndexed) { throw new Error(""); }
|
|
||||||
indexed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const name = (tokens.peekType("ID") ? tokens.pop().text: "");
|
|
||||||
|
|
||||||
if (tokens.length) { throw new Error("leftover tokens"); }
|
|
||||||
|
|
||||||
return new ParamType(_guard, name, type, baseType, indexed, comps, arrayLength, arrayChildren);
|
|
||||||
}
|
|
||||||
|
|
||||||
static isParamType(value: any): value is ParamType {
|
static isParamType(value: any): value is ParamType {
|
||||||
return (value && value[internal] === ParamTypeInternal);
|
return (value && value[internal] === ParamTypeInternal);
|
||||||
}
|
}
|
||||||
@ -747,82 +750,60 @@ export abstract class Fragment {
|
|||||||
abstract format(format?: FormatType): string;
|
abstract format(format?: FormatType): string;
|
||||||
|
|
||||||
static from(obj: any): Fragment {
|
static from(obj: any): Fragment {
|
||||||
if (typeof(obj) === "string") { return this.fromString(obj); }
|
if (typeof(obj) === "string") {
|
||||||
if (obj instanceof TokenString) { return this.fromTokens(obj); }
|
try {
|
||||||
if (typeof(obj) === "object") { return this.fromObject(obj); }
|
Fragment.from(JSON.parse(obj));
|
||||||
|
} catch (e) { }
|
||||||
|
|
||||||
|
return Fragment.from(lex(obj));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj instanceof TokenString) {
|
||||||
|
const type = obj.popKeyword(KwTypes);
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case "constructor": return ConstructorFragment.from(obj);
|
||||||
|
case "error": return ErrorFragment.from(obj);
|
||||||
|
case "event": return EventFragment.from(obj);
|
||||||
|
case "function": return FunctionFragment.from(obj);
|
||||||
|
case "struct": return StructFragment.from(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error(`unsupported type: ${ type }`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof(obj) === "object") {
|
||||||
|
switch (obj.type) {
|
||||||
|
case "constructor": return ConstructorFragment.from(obj);
|
||||||
|
case "error": return ErrorFragment.from(obj);
|
||||||
|
case "event": return EventFragment.from(obj);
|
||||||
|
case "function": return FunctionFragment.from(obj);
|
||||||
|
case "struct": return StructFragment.from(obj);
|
||||||
|
}
|
||||||
|
throw new Error(`not implemented yet: ${ obj.type }`);
|
||||||
|
}
|
||||||
|
|
||||||
throw new Error(`unsupported type: ${ obj }`);
|
throw new Error(`unsupported type: ${ obj }`);
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromObject(obj: any): Fragment {
|
|
||||||
switch (obj.type) {
|
|
||||||
case "constructor": return ConstructorFragment.fromObject(obj);
|
|
||||||
case "error": return ErrorFragment.fromObject(obj);
|
|
||||||
case "event": return EventFragment.fromObject(obj);
|
|
||||||
case "function": return FunctionFragment.fromObject(obj);
|
|
||||||
case "struct": return StructFragment.fromObject(obj);
|
|
||||||
}
|
|
||||||
throw new Error(`not implemented yet: ${ obj.type }`);
|
|
||||||
}
|
|
||||||
|
|
||||||
static fromString(text: string): Fragment {
|
|
||||||
try {
|
|
||||||
Fragment.from(JSON.parse(text));
|
|
||||||
} catch (e) { }
|
|
||||||
|
|
||||||
return Fragment.fromTokens(lex(text));
|
|
||||||
}
|
|
||||||
|
|
||||||
static fromTokens(tokens: TokenString): Fragment {
|
|
||||||
const type = tokens.popKeyword(KwTypes);
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case "constructor": return ConstructorFragment.fromTokens(tokens);
|
|
||||||
case "error": return ErrorFragment.fromTokens(tokens);
|
|
||||||
case "event": return EventFragment.fromTokens(tokens);
|
|
||||||
case "function": return FunctionFragment.fromTokens(tokens);
|
|
||||||
case "struct": return StructFragment.fromTokens(tokens);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new Error(`unsupported type: ${ type }`);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
static fromTokens(tokens: TokenString): Fragment {
|
|
||||||
const assertDone = () => {
|
|
||||||
if (tokens.length) { throw new Error(`unexpected tokens: ${ tokens.toString() }`); }
|
|
||||||
});
|
|
||||||
|
|
||||||
const type = (tokens.length && tokens.peek().type === "KEYWORD") ? tokens.peek().text: "unknown";
|
|
||||||
|
|
||||||
const name = consumeName("error", tokens);
|
|
||||||
const inputs = consumeParams(tokens, type === "event");
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case "event": case "struct":
|
|
||||||
assertDone();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
static isConstructor(value: any): value is ConstructorFragment {
|
static isConstructor(value: any): value is ConstructorFragment {
|
||||||
return (value && value.type === "constructor");
|
return ConstructorFragment.isFragment(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static isError(value: any): value is ErrorFragment {
|
static isError(value: any): value is ErrorFragment {
|
||||||
return (value && value.type === "error");
|
return ErrorFragment.isFragment(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static isEvent(value: any): value is EventFragment {
|
static isEvent(value: any): value is EventFragment {
|
||||||
return (value && value.type === "event");
|
return EventFragment.isFragment(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static isFunction(value: any): value is FunctionFragment {
|
static isFunction(value: any): value is FunctionFragment {
|
||||||
return (value && value.type === "function");
|
return FunctionFragment.isFragment(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static isStruct(value: any): value is StructFragment {
|
static isStruct(value: any): value is StructFragment {
|
||||||
return (value && value.type === "struct");
|
return StructFragment.isFragment(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -831,6 +812,9 @@ export abstract class NamedFragment extends Fragment {
|
|||||||
|
|
||||||
constructor(guard: any, type: FragmentType, name: string, inputs: ReadonlyArray<ParamType>) {
|
constructor(guard: any, type: FragmentType, name: string, inputs: ReadonlyArray<ParamType>) {
|
||||||
super(guard, type, inputs);
|
super(guard, type, inputs);
|
||||||
|
if (typeof(name) !== "string" || !name.match(regexIdentifier)) {
|
||||||
|
throwArgumentError("invalid identifier", "name", name);
|
||||||
|
}
|
||||||
inputs = Object.freeze(inputs.slice());
|
inputs = Object.freeze(inputs.slice());
|
||||||
defineProperties<NamedFragment>(this, { name });
|
defineProperties<NamedFragment>(this, { name });
|
||||||
}
|
}
|
||||||
@ -843,6 +827,7 @@ function joinParams(format: FormatType, params: ReadonlyArray<ParamType>): strin
|
|||||||
export class ErrorFragment extends NamedFragment {
|
export class ErrorFragment extends NamedFragment {
|
||||||
constructor(guard: any, name: string, inputs: ReadonlyArray<ParamType>) {
|
constructor(guard: any, name: string, inputs: ReadonlyArray<ParamType>) {
|
||||||
super(guard, "error", name, inputs);
|
super(guard, "error", name, inputs);
|
||||||
|
Object.defineProperty(this, internal, { value: ErrorFragmentInternal });
|
||||||
}
|
}
|
||||||
|
|
||||||
get selector(): string {
|
get selector(): string {
|
||||||
@ -864,21 +849,26 @@ export class ErrorFragment extends NamedFragment {
|
|||||||
return result.join(" ");
|
return result.join(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromObject(obj: any): ErrorFragment {
|
static from(obj: any): ErrorFragment {
|
||||||
|
if (ErrorFragment.isFragment(obj)) { return obj; }
|
||||||
|
|
||||||
|
if (typeof(obj) === "string") {
|
||||||
|
return ErrorFragment.from(lex(obj));
|
||||||
|
|
||||||
|
} else if (obj instanceof TokenString) {
|
||||||
|
const name = consumeName("error", obj);
|
||||||
|
const inputs = consumeParams(obj);
|
||||||
|
consumeEoi(obj);
|
||||||
|
|
||||||
|
return new ErrorFragment(_guard, name, inputs);
|
||||||
|
}
|
||||||
|
|
||||||
return new ErrorFragment(_guard, obj.name,
|
return new ErrorFragment(_guard, obj.name,
|
||||||
obj.inputs ? obj.inputs.map(ParamType.fromObject): [ ]);
|
obj.inputs ? obj.inputs.map(ParamType.from): [ ]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromString(text: string): ErrorFragment {
|
static isFragment(value: any): value is ErrorFragment {
|
||||||
return ErrorFragment.fromTokens(lex(text));
|
return (value && value[internal] === ErrorFragmentInternal);
|
||||||
}
|
|
||||||
|
|
||||||
static fromTokens(tokens: TokenString): ErrorFragment {
|
|
||||||
const name = consumeName("error", tokens);
|
|
||||||
const inputs = consumeParams(tokens);
|
|
||||||
consumeEoi(tokens);
|
|
||||||
|
|
||||||
return new ErrorFragment(_guard, name, inputs);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -888,6 +878,7 @@ export class EventFragment extends NamedFragment {
|
|||||||
|
|
||||||
constructor(guard: any, name: string, inputs: ReadonlyArray<ParamType>, anonymous: boolean) {
|
constructor(guard: any, name: string, inputs: ReadonlyArray<ParamType>, anonymous: boolean) {
|
||||||
super(guard, "event", name, inputs);
|
super(guard, "event", name, inputs);
|
||||||
|
Object.defineProperty(this, internal, { value: EventFragmentInternal });
|
||||||
defineProperties<EventFragment>(this, { anonymous });
|
defineProperties<EventFragment>(this, { anonymous });
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -912,22 +903,27 @@ export class EventFragment extends NamedFragment {
|
|||||||
return result.join(" ");
|
return result.join(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromObject(obj: any): EventFragment {
|
static from(obj: any): EventFragment {
|
||||||
|
if (EventFragment.isFragment(obj)) { return obj; }
|
||||||
|
|
||||||
|
if (typeof(obj) === "string") {
|
||||||
|
return EventFragment.from(lex(obj));
|
||||||
|
|
||||||
|
} else if (obj instanceof TokenString) {
|
||||||
|
const name = consumeName("event", obj);
|
||||||
|
const inputs = consumeParams(obj, true);
|
||||||
|
const anonymous = !!consumeKeywords(obj, setify([ "anonymous" ])).has("anonymous");
|
||||||
|
consumeEoi(obj);
|
||||||
|
|
||||||
|
return new EventFragment(_guard, name, inputs, anonymous);
|
||||||
|
}
|
||||||
|
|
||||||
return new EventFragment(_guard, obj.name,
|
return new EventFragment(_guard, obj.name,
|
||||||
obj.inputs ? obj.inputs.map(ParamType.fromObject): [ ], !!obj.anonymous);
|
obj.inputs ? obj.inputs.map(ParamType.from): [ ], !!obj.anonymous);
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromString(text: string): EventFragment {
|
static isFragment(value: any): value is EventFragment {
|
||||||
return EventFragment.fromTokens(lex(text));
|
return (value && value[internal] === EventFragmentInternal);
|
||||||
}
|
|
||||||
|
|
||||||
static fromTokens(tokens: TokenString): EventFragment {
|
|
||||||
const name = consumeName("event", tokens);
|
|
||||||
const inputs = consumeParams(tokens, true);
|
|
||||||
const anonymous = !!consumeKeywords(tokens, setify([ "anonymous" ])).has("anonymous");
|
|
||||||
consumeEoi(tokens);
|
|
||||||
|
|
||||||
return new EventFragment(_guard, name, inputs, anonymous);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -938,6 +934,7 @@ export class ConstructorFragment extends Fragment {
|
|||||||
|
|
||||||
constructor(guard: any, type: FragmentType, inputs: ReadonlyArray<ParamType>, payable: boolean, gas: null | bigint) {
|
constructor(guard: any, type: FragmentType, inputs: ReadonlyArray<ParamType>, payable: boolean, gas: null | bigint) {
|
||||||
super(guard, type, inputs);
|
super(guard, type, inputs);
|
||||||
|
Object.defineProperty(this, internal, { value: ConstructorFragmentInternal });
|
||||||
defineProperties<ConstructorFragment>(this, { payable, gas });
|
defineProperties<ConstructorFragment>(this, { payable, gas });
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -964,24 +961,29 @@ export class ConstructorFragment extends Fragment {
|
|||||||
return result.join(" ");
|
return result.join(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromObject(obj: any): ConstructorFragment {
|
static from(obj: any): ConstructorFragment {
|
||||||
|
if (ConstructorFragment.isFragment(obj)) { return obj; }
|
||||||
|
|
||||||
|
if (typeof(obj) === "string") {
|
||||||
|
return ConstructorFragment.from(lex(obj));
|
||||||
|
|
||||||
|
} else if (obj instanceof TokenString) {
|
||||||
|
consumeKeywords(obj, setify([ "constructor" ]));
|
||||||
|
const inputs = consumeParams(obj);
|
||||||
|
const payable = !!consumeKeywords(obj, setify([ "payable" ])).has("payable");
|
||||||
|
const gas = consumeGas(obj);
|
||||||
|
consumeEoi(obj);
|
||||||
|
|
||||||
|
return new ConstructorFragment(_guard, "constructor", inputs, payable, gas);
|
||||||
|
}
|
||||||
|
|
||||||
return new ConstructorFragment(_guard, "constructor",
|
return new ConstructorFragment(_guard, "constructor",
|
||||||
obj.inputs ? obj.inputs.map(ParamType.fromObject): [ ],
|
obj.inputs ? obj.inputs.map(ParamType.from): [ ],
|
||||||
!!obj.payable, (obj.gas != null) ? obj.gas: null);
|
!!obj.payable, (obj.gas != null) ? obj.gas: null);
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromString(text: string): ConstructorFragment {
|
static isFragment(value: any): value is ConstructorFragment {
|
||||||
return ConstructorFragment.fromTokens(lex(text));
|
return (value && value[internal] === ConstructorFragmentInternal);
|
||||||
}
|
|
||||||
|
|
||||||
static fromTokens(tokens: TokenString): ConstructorFragment {
|
|
||||||
consumeKeywords(tokens, setify([ "constructor" ]));
|
|
||||||
const inputs = consumeParams(tokens);
|
|
||||||
const payable = !!consumeKeywords(tokens, setify([ "payable" ])).has("payable");
|
|
||||||
const gas = consumeGas(tokens);
|
|
||||||
consumeEoi(tokens);
|
|
||||||
|
|
||||||
return new ConstructorFragment(_guard, "constructor", inputs, payable, gas);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -995,6 +997,7 @@ export class FunctionFragment extends NamedFragment {
|
|||||||
|
|
||||||
constructor(guard: any, name: string, stateMutability: string, inputs: ReadonlyArray<ParamType>, outputs: ReadonlyArray<ParamType>, gas: null | bigint) {
|
constructor(guard: any, name: string, stateMutability: string, inputs: ReadonlyArray<ParamType>, outputs: ReadonlyArray<ParamType>, gas: null | bigint) {
|
||||||
super(guard, "function", name, inputs);
|
super(guard, "function", name, inputs);
|
||||||
|
Object.defineProperty(this, internal, { value: FunctionFragmentInternal });
|
||||||
outputs = Object.freeze(outputs.slice());
|
outputs = Object.freeze(outputs.slice());
|
||||||
const constant = (stateMutability === "view" || stateMutability === "pure");
|
const constant = (stateMutability === "view" || stateMutability === "pure");
|
||||||
const payable = (stateMutability === "payable");
|
const payable = (stateMutability === "payable");
|
||||||
@ -1040,51 +1043,68 @@ export class FunctionFragment extends NamedFragment {
|
|||||||
return result.join(" ");
|
return result.join(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromObject(obj: any): FunctionFragment {
|
static from(obj: any): FunctionFragment {
|
||||||
|
if (FunctionFragment.isFragment(obj)) { return obj; }
|
||||||
|
|
||||||
|
if (typeof(obj) === "string") {
|
||||||
|
return FunctionFragment.from(lex(obj));
|
||||||
|
|
||||||
|
} else if (obj instanceof TokenString) {
|
||||||
|
const name = consumeName("function", obj);
|
||||||
|
const inputs = consumeParams(obj);
|
||||||
|
const mutability = consumeMutability(obj);
|
||||||
|
|
||||||
|
let outputs: Array<ParamType> = [ ];
|
||||||
|
if (consumeKeywords(obj, setify([ "returns" ])).has("returns")) {
|
||||||
|
outputs = consumeParams(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
const gas = consumeGas(obj);
|
||||||
|
|
||||||
|
consumeEoi(obj);
|
||||||
|
|
||||||
|
return new FunctionFragment(_guard, name, mutability, inputs, outputs, gas);
|
||||||
|
}
|
||||||
|
|
||||||
// @TODO: verifyState for stateMutability
|
// @TODO: verifyState for stateMutability
|
||||||
|
|
||||||
return new FunctionFragment(_guard, obj.name, obj.stateMutability,
|
return new FunctionFragment(_guard, obj.name, obj.stateMutability,
|
||||||
obj.inputs ? obj.inputs.map(ParamType.fromObject): [ ],
|
obj.inputs ? obj.inputs.map(ParamType.from): [ ],
|
||||||
obj.outputs ? obj.outputs.map(ParamType.fromObject): [ ],
|
obj.outputs ? obj.outputs.map(ParamType.from): [ ],
|
||||||
(obj.gas != null) ? obj.gas: null);
|
(obj.gas != null) ? obj.gas: null);
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromString(text: string): FunctionFragment {
|
static isFragment(value: any): value is FunctionFragment {
|
||||||
return FunctionFragment.fromTokens(lex(text));
|
return (value && value[internal] === FunctionFragmentInternal);
|
||||||
}
|
|
||||||
|
|
||||||
static fromTokens(tokens: TokenString): FunctionFragment {
|
|
||||||
const name = consumeName("function", tokens);
|
|
||||||
const inputs = consumeParams(tokens);
|
|
||||||
const mutability = consumeMutability(tokens);
|
|
||||||
|
|
||||||
let outputs: Array<ParamType> = [ ];
|
|
||||||
if (consumeKeywords(tokens, setify([ "returns" ])).has("returns")) {
|
|
||||||
outputs = consumeParams(tokens);
|
|
||||||
}
|
|
||||||
|
|
||||||
const gas = consumeGas(tokens);
|
|
||||||
|
|
||||||
consumeEoi(tokens);
|
|
||||||
|
|
||||||
return new FunctionFragment(_guard, name, mutability, inputs, outputs, gas);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class StructFragment extends NamedFragment {
|
export class StructFragment extends NamedFragment {
|
||||||
|
constructor(guard: any, name: string, inputs: ReadonlyArray<ParamType>) {
|
||||||
|
super(guard, "struct", name, inputs);
|
||||||
|
Object.defineProperty(this, internal, { value: StructFragmentInternal });
|
||||||
|
}
|
||||||
|
|
||||||
format(): string {
|
format(): string {
|
||||||
throw new Error("@TODO");
|
throw new Error("@TODO");
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromString(text: string): StructFragment {
|
static from(obj: any): StructFragment {
|
||||||
return StructFragment.fromTokens(lex(text));
|
if (typeof(obj) === "string") {
|
||||||
|
return StructFragment.from(lex(obj));
|
||||||
|
|
||||||
|
} else if (obj instanceof TokenString) {
|
||||||
|
const name = consumeName("struct", obj);
|
||||||
|
const inputs = consumeParams(obj);
|
||||||
|
consumeEoi(obj);
|
||||||
|
return new StructFragment(_guard, name, inputs);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new StructFragment(_guard, obj.name, obj.inputs ? obj.inputs.map(ParamType.from): [ ]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromTokens(tokens: TokenString): StructFragment {
|
static isFragment(value: any): value is FunctionFragment {
|
||||||
const name = consumeName("struct", tokens);
|
return (value && value[internal] === StructFragmentInternal);
|
||||||
const inputs = consumeParams(tokens);
|
|
||||||
consumeEoi(tokens);
|
|
||||||
|
|
||||||
return new StructFragment(_guard, "struct", name, inputs);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,7 +182,9 @@ export class Interface {
|
|||||||
for (const a of abi) {
|
for (const a of abi) {
|
||||||
try {
|
try {
|
||||||
frags.push(Fragment.from(a));
|
frags.push(Fragment.from(a));
|
||||||
} catch (error) { }
|
} catch (error) {
|
||||||
|
console.log("EE", error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
defineProperties<Interface>(this, {
|
defineProperties<Interface>(this, {
|
||||||
@ -233,7 +235,7 @@ export class Interface {
|
|||||||
// If we do not have a constructor add a default
|
// If we do not have a constructor add a default
|
||||||
if (!this.deploy) {
|
if (!this.deploy) {
|
||||||
defineProperties<Interface>(this, {
|
defineProperties<Interface>(this, {
|
||||||
deploy: ConstructorFragment.fromString("constructor()")
|
deploy: ConstructorFragment.from("constructor()")
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -350,7 +352,7 @@ export class Interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Normalize the signature and lookup the function
|
// Normalize the signature and lookup the function
|
||||||
const result = this.#functions.get(FunctionFragment.fromString(key).format());
|
const result = this.#functions.get(FunctionFragment.from(key).format());
|
||||||
if (result) { return result; }
|
if (result) { return result; }
|
||||||
|
|
||||||
return throwArgumentError("no matching function", "signature", key);
|
return throwArgumentError("no matching function", "signature", key);
|
||||||
@ -433,7 +435,7 @@ export class Interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Normalize the signature and lookup the function
|
// Normalize the signature and lookup the function
|
||||||
const result = this.#events.get(EventFragment.fromString(key).format());
|
const result = this.#events.get(EventFragment.from(key).format());
|
||||||
if (result) { return result; }
|
if (result) { return result; }
|
||||||
|
|
||||||
return throwArgumentError("no matching event", "signature", key);
|
return throwArgumentError("no matching event", "signature", key);
|
||||||
@ -476,7 +478,7 @@ export class Interface {
|
|||||||
const selector = key.toLowerCase();
|
const selector = key.toLowerCase();
|
||||||
|
|
||||||
if (BuiltinErrors[selector]) {
|
if (BuiltinErrors[selector]) {
|
||||||
return ErrorFragment.fromString(BuiltinErrors[selector].signature);
|
return ErrorFragment.from(BuiltinErrors[selector].signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const fragment of this.#errors.values()) {
|
for (const fragment of this.#errors.values()) {
|
||||||
@ -493,8 +495,8 @@ export class Interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (matching.length === 0) {
|
if (matching.length === 0) {
|
||||||
if (key === "Error") { return ErrorFragment.fromString("error Error(string)"); }
|
if (key === "Error") { return ErrorFragment.from("error Error(string)"); }
|
||||||
if (key === "Panic") { return ErrorFragment.fromString("error Panic(uint256)"); }
|
if (key === "Panic") { return ErrorFragment.from("error Panic(uint256)"); }
|
||||||
throwArgumentError("no matching error", "name", key);
|
throwArgumentError("no matching error", "name", key);
|
||||||
} else if (matching.length > 1) {
|
} else if (matching.length > 1) {
|
||||||
// @TODO: refine by Typed
|
// @TODO: refine by Typed
|
||||||
@ -505,9 +507,9 @@ export class Interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Normalize the signature and lookup the function
|
// Normalize the signature and lookup the function
|
||||||
key = ErrorFragment.fromString(key).format()
|
key = ErrorFragment.from(key).format()
|
||||||
if (key === "Error(string)") { return ErrorFragment.fromString("error Error(string)"); }
|
if (key === "Error(string)") { return ErrorFragment.from("error Error(string)"); }
|
||||||
if (key === "Panic(uint256)") { return ErrorFragment.fromString("error Panic(uint256)"); }
|
if (key === "Panic(uint256)") { return ErrorFragment.from("error Panic(uint256)"); }
|
||||||
|
|
||||||
const result = this.#errors.get(key);
|
const result = this.#errors.get(key);
|
||||||
if (result) { return result; }
|
if (result) { return result; }
|
||||||
@ -891,7 +893,7 @@ export class Interface {
|
|||||||
eventFragment.inputs.forEach((param, index) => {
|
eventFragment.inputs.forEach((param, index) => {
|
||||||
if (param.indexed) {
|
if (param.indexed) {
|
||||||
if (param.type === "string" || param.type === "bytes" || param.baseType === "tuple" || param.baseType === "array") {
|
if (param.type === "string" || param.type === "bytes" || param.baseType === "tuple" || param.baseType === "array") {
|
||||||
indexed.push(ParamType.fromObject({ type: "bytes32", name: param.name }));
|
indexed.push(ParamType.from({ type: "bytes32", name: param.name }));
|
||||||
dynamic.push(true);
|
dynamic.push(true);
|
||||||
} else {
|
} else {
|
||||||
indexed.push(param);
|
indexed.push(param);
|
||||||
|
Loading…
Reference in New Issue
Block a user