Interface returns null instead of throws on missing fragment.
This commit is contained in:
parent
c2a2edc9d8
commit
32f605eb7b
@ -292,7 +292,7 @@ export class Interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Find a function definition by any means necessary (unless it is ambiguous)
|
// Find a function definition by any means necessary (unless it is ambiguous)
|
||||||
#getFunction(key: string, values: null | Array<any | Typed>, forceUnique: boolean): FunctionFragment {
|
#getFunction(key: string, values: null | Array<any | Typed>, forceUnique: boolean): null | FunctionFragment {
|
||||||
|
|
||||||
// Selector
|
// Selector
|
||||||
if (isHexString(key)) {
|
if (isHexString(key)) {
|
||||||
@ -300,7 +300,7 @@ export class Interface {
|
|||||||
for (const fragment of this.#functions.values()) {
|
for (const fragment of this.#functions.values()) {
|
||||||
if (selector === fragment.selector) { return fragment; }
|
if (selector === fragment.selector) { return fragment; }
|
||||||
}
|
}
|
||||||
assertArgument(false, "no matching function", "selector", key);
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// It is a bare name, look up the function (will return null if ambiguous)
|
// It is a bare name, look up the function (will return null if ambiguous)
|
||||||
@ -361,11 +361,11 @@ export class Interface {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assertArgument(matching.length !== 0, "no matching function", "name", key);
|
if (matching.length === 0) { return null; }
|
||||||
|
|
||||||
if (matching.length > 1 && forceUnique) {
|
if (matching.length > 1 && forceUnique) {
|
||||||
const matchStr = matching.map((m) => JSON.stringify(m.format())).join(", ");
|
const matchStr = matching.map((m) => JSON.stringify(m.format())).join(", ");
|
||||||
assertArgument(false, `multiple matching functions (i.e. ${ matchStr })`, "name", key);
|
assertArgument(false, `ambiguous function description (i.e. matches ${ matchStr })`, "key", key);
|
||||||
}
|
}
|
||||||
|
|
||||||
return matching[0];
|
return matching[0];
|
||||||
@ -375,7 +375,7 @@ export class Interface {
|
|||||||
const result = this.#functions.get(FunctionFragment.from(key).format());
|
const result = this.#functions.get(FunctionFragment.from(key).format());
|
||||||
if (result) { return result; }
|
if (result) { return result; }
|
||||||
|
|
||||||
assertArgument(false, "no matching function", "signature", key);
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -383,7 +383,9 @@ export class Interface {
|
|||||||
* function name or function signature that belongs to the ABI.
|
* function name or function signature that belongs to the ABI.
|
||||||
*/
|
*/
|
||||||
getFunctionName(key: string): string {
|
getFunctionName(key: string): string {
|
||||||
return (this.#getFunction(key, null, false)).name;
|
const fragment = this.#getFunction(key, null, false);
|
||||||
|
assertArgument(fragment, "no matching function", "key", key);
|
||||||
|
return fragment.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -396,8 +398,8 @@ export class Interface {
|
|||||||
* If the %%key%% and %%values%% do not refine to a single function in
|
* If the %%key%% and %%values%% do not refine to a single function in
|
||||||
* the ABI, this will throw.
|
* the ABI, this will throw.
|
||||||
*/
|
*/
|
||||||
getFunction(key: string, values?: Array<any | Typed>): FunctionFragment {
|
getFunction(key: string, values?: Array<any | Typed>): null | FunctionFragment {
|
||||||
return this.#getFunction(key, values || null, true)
|
return this.#getFunction(key, values || null, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -414,7 +416,7 @@ export class Interface {
|
|||||||
|
|
||||||
|
|
||||||
// Find an event definition by any means necessary (unless it is ambiguous)
|
// Find an event definition by any means necessary (unless it is ambiguous)
|
||||||
#getEvent(key: string, values: null | Array<null | any | Typed>, forceUnique: boolean): EventFragment {
|
#getEvent(key: string, values: null | Array<null | any | Typed>, forceUnique: boolean): null | EventFragment {
|
||||||
|
|
||||||
// EventTopic
|
// EventTopic
|
||||||
if (isHexString(key)) {
|
if (isHexString(key)) {
|
||||||
@ -422,7 +424,7 @@ export class Interface {
|
|||||||
for (const fragment of this.#events.values()) {
|
for (const fragment of this.#events.values()) {
|
||||||
if (eventTopic === fragment.topicHash) { return fragment; }
|
if (eventTopic === fragment.topicHash) { return fragment; }
|
||||||
}
|
}
|
||||||
assertArgument(false, "no matching event", "eventTopic", key);
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// It is a bare name, look up the function (will return null if ambiguous)
|
// It is a bare name, look up the function (will return null if ambiguous)
|
||||||
@ -456,10 +458,11 @@ export class Interface {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assertArgument(matching.length > 0, "no matching event", "name", key);
|
if (matching.length === 0) { return null; }
|
||||||
|
|
||||||
if (matching.length > 1 && forceUnique) {
|
if (matching.length > 1 && forceUnique) {
|
||||||
// @TODO: refine by Typed
|
const matchStr = matching.map((m) => JSON.stringify(m.format())).join(", ");
|
||||||
assertArgument(false, "multiple matching events", "name", key);
|
assertArgument(false, `ambiguous event description (i.e. matches ${ matchStr })`, "key", key);
|
||||||
}
|
}
|
||||||
|
|
||||||
return matching[0];
|
return matching[0];
|
||||||
@ -469,7 +472,7 @@ export class Interface {
|
|||||||
const result = this.#events.get(EventFragment.from(key).format());
|
const result = this.#events.get(EventFragment.from(key).format());
|
||||||
if (result) { return result; }
|
if (result) { return result; }
|
||||||
|
|
||||||
assertArgument(false, "no matching event", "signature", key);
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -477,7 +480,10 @@ export class Interface {
|
|||||||
* event name or event signature that belongs to the ABI.
|
* event name or event signature that belongs to the ABI.
|
||||||
*/
|
*/
|
||||||
getEventName(key: string): string {
|
getEventName(key: string): string {
|
||||||
return (this.#getEvent(key, null, false)).name;
|
const fragment = this.#getEvent(key, null, false);
|
||||||
|
assertArgument(fragment, "no matching event", "key", key);
|
||||||
|
|
||||||
|
return fragment.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -490,7 +496,7 @@ export class Interface {
|
|||||||
* If the %%key%% and %%values%% do not refine to a single event in
|
* If the %%key%% and %%values%% do not refine to a single event in
|
||||||
* the ABI, this will throw.
|
* the ABI, this will throw.
|
||||||
*/
|
*/
|
||||||
getEvent(key: string, values?: Array<any | Typed>): EventFragment {
|
getEvent(key: string, values?: Array<any | Typed>): null | EventFragment {
|
||||||
return this.#getEvent(key, values || null, true)
|
return this.#getEvent(key, values || null, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -516,7 +522,7 @@ export class Interface {
|
|||||||
* If the %%key%% and %%values%% do not refine to a single error in
|
* If the %%key%% and %%values%% do not refine to a single error in
|
||||||
* the ABI, this will throw.
|
* the ABI, this will throw.
|
||||||
*/
|
*/
|
||||||
getError(key: string, values?: Array<any | Typed>): ErrorFragment {
|
getError(key: string, values?: Array<any | Typed>): null | ErrorFragment {
|
||||||
if (isHexString(key)) {
|
if (isHexString(key)) {
|
||||||
const selector = key.toLowerCase();
|
const selector = key.toLowerCase();
|
||||||
|
|
||||||
@ -527,7 +533,8 @@ export class Interface {
|
|||||||
for (const fragment of this.#errors.values()) {
|
for (const fragment of this.#errors.values()) {
|
||||||
if (selector === fragment.selector) { return fragment; }
|
if (selector === fragment.selector) { return fragment; }
|
||||||
}
|
}
|
||||||
assertArgument(false, "no matching error", "selector", key);
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// It is a bare name, look up the function (will return null if ambiguous)
|
// It is a bare name, look up the function (will return null if ambiguous)
|
||||||
@ -540,10 +547,10 @@ export class Interface {
|
|||||||
if (matching.length === 0) {
|
if (matching.length === 0) {
|
||||||
if (key === "Error") { return ErrorFragment.from("error Error(string)"); }
|
if (key === "Error") { return ErrorFragment.from("error Error(string)"); }
|
||||||
if (key === "Panic") { return ErrorFragment.from("error Panic(uint256)"); }
|
if (key === "Panic") { return ErrorFragment.from("error Panic(uint256)"); }
|
||||||
assertArgument(false, "no matching error", "name", key);
|
return null;
|
||||||
} else if (matching.length > 1) {
|
} else if (matching.length > 1) {
|
||||||
// @TODO: refine by Typed
|
const matchStr = matching.map((m) => JSON.stringify(m.format())).join(", ");
|
||||||
assertArgument(false, "multiple matching errors", "name", key);
|
assertArgument(false, `ambiguous error description (i.e. ${ matchStr })`, "name", key);
|
||||||
}
|
}
|
||||||
|
|
||||||
return matching[0];
|
return matching[0];
|
||||||
@ -557,7 +564,7 @@ export class Interface {
|
|||||||
const result = this.#errors.get(key);
|
const result = this.#errors.get(key);
|
||||||
if (result) { return result; }
|
if (result) { return result; }
|
||||||
|
|
||||||
assertArgument(false, "no matching error", "signature", key);
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -629,7 +636,11 @@ export class Interface {
|
|||||||
* corresponding error.
|
* corresponding error.
|
||||||
*/
|
*/
|
||||||
decodeErrorResult(fragment: ErrorFragment | string, data: BytesLike): Result {
|
decodeErrorResult(fragment: ErrorFragment | string, data: BytesLike): Result {
|
||||||
if (typeof(fragment) === "string") { fragment = this.getError(fragment); }
|
if (typeof(fragment) === "string") {
|
||||||
|
const f = this.getError(fragment);
|
||||||
|
assertArgument(f, "unknown error", "fragment", fragment);
|
||||||
|
fragment = f;
|
||||||
|
}
|
||||||
|
|
||||||
assertArgument(dataSlice(data, 0, 4) === fragment.selector,
|
assertArgument(dataSlice(data, 0, 4) === fragment.selector,
|
||||||
`data signature does not match error ${ fragment.name }.`, "data", data);
|
`data signature does not match error ${ fragment.name }.`, "data", data);
|
||||||
@ -640,13 +651,17 @@ export class Interface {
|
|||||||
/**
|
/**
|
||||||
* Encodes the transaction revert data for a call result that
|
* Encodes the transaction revert data for a call result that
|
||||||
* reverted from the the Contract with the sepcified %%error%%
|
* reverted from the the Contract with the sepcified %%error%%
|
||||||
* (see [[getError]] for valid values for %%key%%) with the %%values%%.
|
* (see [[getError]] for valid values for %%fragment%%) with the %%values%%.
|
||||||
*
|
*
|
||||||
* This is generally not used by most developers, unless trying to mock
|
* This is generally not used by most developers, unless trying to mock
|
||||||
* a result from a Contract.
|
* a result from a Contract.
|
||||||
*/
|
*/
|
||||||
encodeErrorResult(key: ErrorFragment | string, values?: ReadonlyArray<any>): string {
|
encodeErrorResult(fragment: ErrorFragment | string, values?: ReadonlyArray<any>): string {
|
||||||
const fragment = (typeof(key) === "string") ? this.getError(key): key;
|
if (typeof(fragment) === "string") {
|
||||||
|
const f = this.getError(fragment);
|
||||||
|
assertArgument(f, "unknown error", "fragment", fragment);
|
||||||
|
fragment = f;
|
||||||
|
}
|
||||||
|
|
||||||
return concat([
|
return concat([
|
||||||
fragment.selector,
|
fragment.selector,
|
||||||
@ -657,13 +672,17 @@ export class Interface {
|
|||||||
/**
|
/**
|
||||||
* Decodes the %%data%% from a transaction ``tx.data`` for
|
* Decodes the %%data%% from a transaction ``tx.data`` for
|
||||||
* the function specified (see [[getFunction]] for valid values
|
* the function specified (see [[getFunction]] for valid values
|
||||||
* for %%key%%).
|
* for %%fragment%%).
|
||||||
*
|
*
|
||||||
* Most developers should prefer the [[parseTransaction]] method
|
* Most developers should prefer the [[parseTransaction]] method
|
||||||
* instead, which will automatically detect the fragment.
|
* instead, which will automatically detect the fragment.
|
||||||
*/
|
*/
|
||||||
decodeFunctionData(key: FunctionFragment | string, data: BytesLike): Result {
|
decodeFunctionData(fragment: FunctionFragment | string, data: BytesLike): Result {
|
||||||
const fragment = (typeof(key) === "string") ? this.getFunction(key): key;
|
if (typeof(fragment) === "string") {
|
||||||
|
const f = this.getFunction(fragment);
|
||||||
|
assertArgument(f, "unknown function", "fragment", fragment);
|
||||||
|
fragment = f;
|
||||||
|
}
|
||||||
|
|
||||||
assertArgument(dataSlice(data, 0, 4) === fragment.selector,
|
assertArgument(dataSlice(data, 0, 4) === fragment.selector,
|
||||||
`data signature does not match function ${ fragment.name }.`, "data", data);
|
`data signature does not match function ${ fragment.name }.`, "data", data);
|
||||||
@ -673,11 +692,15 @@ export class Interface {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Encodes the ``tx.data`` for a transaction that calls the function
|
* Encodes the ``tx.data`` for a transaction that calls the function
|
||||||
* specified (see [[getFunction]] for valid values for %%key%%) with
|
* specified (see [[getFunction]] for valid values for %%fragment%%) with
|
||||||
* the %%values%%.
|
* the %%values%%.
|
||||||
*/
|
*/
|
||||||
encodeFunctionData(key: FunctionFragment | string, values?: ReadonlyArray<any>): string {
|
encodeFunctionData(fragment: FunctionFragment | string, values?: ReadonlyArray<any>): string {
|
||||||
const fragment = (typeof(key) === "string") ? this.getFunction(key): key;
|
if (typeof(fragment) === "string") {
|
||||||
|
const f = this.getFunction(fragment);
|
||||||
|
assertArgument(f, "unknown function", "fragment", fragment);
|
||||||
|
fragment = f;
|
||||||
|
}
|
||||||
|
|
||||||
return concat([
|
return concat([
|
||||||
fragment.selector,
|
fragment.selector,
|
||||||
@ -695,7 +718,11 @@ export class Interface {
|
|||||||
* corresponding error.
|
* corresponding error.
|
||||||
*/
|
*/
|
||||||
decodeFunctionResult(fragment: FunctionFragment | string, data: BytesLike): Result {
|
decodeFunctionResult(fragment: FunctionFragment | string, data: BytesLike): Result {
|
||||||
if (typeof(fragment) === "string") { fragment = this.getFunction(fragment); }
|
if (typeof(fragment) === "string") {
|
||||||
|
const f = this.getFunction(fragment);
|
||||||
|
assertArgument(f, "unknown function", "fragment", fragment);
|
||||||
|
fragment = f;
|
||||||
|
}
|
||||||
|
|
||||||
let message = "invalid length for result data";
|
let message = "invalid length for result data";
|
||||||
|
|
||||||
@ -725,8 +752,8 @@ export class Interface {
|
|||||||
const selector = hexlify(data.slice(0, 4));
|
const selector = hexlify(data.slice(0, 4));
|
||||||
|
|
||||||
error.message = "execution reverted (unknown custom error)";
|
error.message = "execution reverted (unknown custom error)";
|
||||||
try {
|
const ef = this.getError(selector);
|
||||||
const ef = this.getError(selector);
|
if (ef) {
|
||||||
try {
|
try {
|
||||||
error.revert = {
|
error.revert = {
|
||||||
name: ef.name,
|
name: ef.name,
|
||||||
@ -738,8 +765,6 @@ export class Interface {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
error.message = `execution reverted (coult not decode custom error)`
|
error.message = `execution reverted (coult not decode custom error)`
|
||||||
}
|
}
|
||||||
} catch (error) {
|
|
||||||
console.log(error); // @TODO: remove
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -759,13 +784,17 @@ export class Interface {
|
|||||||
/**
|
/**
|
||||||
* Encodes the result data (e.g. from an ``eth_call``) for the
|
* Encodes the result data (e.g. from an ``eth_call``) for the
|
||||||
* specified function (see [[getFunction]] for valid values
|
* specified function (see [[getFunction]] for valid values
|
||||||
* for %%key%%) with %%values%%.
|
* for %%fragment%%) with %%values%%.
|
||||||
*
|
*
|
||||||
* This is generally not used by most developers, unless trying to mock
|
* This is generally not used by most developers, unless trying to mock
|
||||||
* a result from a Contract.
|
* a result from a Contract.
|
||||||
*/
|
*/
|
||||||
encodeFunctionResult(key: FunctionFragment | string, values?: ReadonlyArray<any>): string {
|
encodeFunctionResult(fragment: FunctionFragment | string, values?: ReadonlyArray<any>): string {
|
||||||
const fragment = (typeof(key) === "string") ? this.getFunction(key): key;
|
if (typeof(fragment) === "string") {
|
||||||
|
const f = this.getFunction(fragment);
|
||||||
|
assertArgument(f, "unknown function", "fragment", fragment);
|
||||||
|
fragment = f;
|
||||||
|
}
|
||||||
return hexlify(this.#abiCoder.encode(fragment.outputs, values || [ ]));
|
return hexlify(this.#abiCoder.encode(fragment.outputs, values || [ ]));
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@ -799,16 +828,18 @@ export class Interface {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
// Create the filter for the event with search criteria (e.g. for eth_filterLog)
|
// Create the filter for the event with search criteria (e.g. for eth_filterLog)
|
||||||
encodeFilterTopics(eventFragment: EventFragment | string, values: ReadonlyArray<any>): Array<null | string | Array<string>> {
|
encodeFilterTopics(fragment: EventFragment | string, values: ReadonlyArray<any>): Array<null | string | Array<string>> {
|
||||||
if (typeof(eventFragment) === "string") {
|
if (typeof(fragment) === "string") {
|
||||||
eventFragment = this.getEvent(eventFragment);
|
const f = this.getEvent(fragment);
|
||||||
|
assertArgument(f, "unknown event", "eventFragment", fragment);
|
||||||
|
fragment = f;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(values.length <= eventFragment.inputs.length, `too many arguments for ${ eventFragment.format() }`,
|
assert(values.length <= fragment.inputs.length, `too many arguments for ${ fragment.format() }`,
|
||||||
"UNEXPECTED_ARGUMENT", { count: values.length, expectedCount: eventFragment.inputs.length })
|
"UNEXPECTED_ARGUMENT", { count: values.length, expectedCount: fragment.inputs.length })
|
||||||
|
|
||||||
const topics: Array<null | string | Array<string>> = [];
|
const topics: Array<null | string | Array<string>> = [];
|
||||||
if (!eventFragment.anonymous) { topics.push(eventFragment.topicHash); }
|
if (!fragment.anonymous) { topics.push(fragment.topicHash); }
|
||||||
|
|
||||||
// @TODO: Use the coders for this; to properly support tuples, etc.
|
// @TODO: Use the coders for this; to properly support tuples, etc.
|
||||||
const encodeTopic = (param: ParamType, value: any): string => {
|
const encodeTopic = (param: ParamType, value: any): string => {
|
||||||
@ -834,7 +865,7 @@ export class Interface {
|
|||||||
|
|
||||||
values.forEach((value, index) => {
|
values.forEach((value, index) => {
|
||||||
|
|
||||||
const param = (<EventFragment>eventFragment).inputs[index];
|
const param = (<EventFragment>fragment).inputs[index];
|
||||||
|
|
||||||
if (!param.indexed) {
|
if (!param.indexed) {
|
||||||
assertArgument(value == null,
|
assertArgument(value == null,
|
||||||
@ -861,9 +892,11 @@ export class Interface {
|
|||||||
return topics;
|
return topics;
|
||||||
}
|
}
|
||||||
|
|
||||||
encodeEventLog(eventFragment: EventFragment | string, values: ReadonlyArray<any>): { data: string, topics: Array<string> } {
|
encodeEventLog(fragment: EventFragment | string, values: ReadonlyArray<any>): { data: string, topics: Array<string> } {
|
||||||
if (typeof(eventFragment) === "string") {
|
if (typeof(fragment) === "string") {
|
||||||
eventFragment = this.getEvent(eventFragment);
|
const f = this.getEvent(fragment);
|
||||||
|
assertArgument(f, "unknown event", "eventFragment", fragment);
|
||||||
|
fragment = f;
|
||||||
}
|
}
|
||||||
|
|
||||||
const topics: Array<string> = [ ];
|
const topics: Array<string> = [ ];
|
||||||
@ -871,14 +904,14 @@ export class Interface {
|
|||||||
const dataTypes: Array<ParamType> = [ ];
|
const dataTypes: Array<ParamType> = [ ];
|
||||||
const dataValues: Array<string> = [ ];
|
const dataValues: Array<string> = [ ];
|
||||||
|
|
||||||
if (!eventFragment.anonymous) {
|
if (!fragment.anonymous) {
|
||||||
topics.push(eventFragment.topicHash);
|
topics.push(fragment.topicHash);
|
||||||
}
|
}
|
||||||
|
|
||||||
assertArgument(values.length === eventFragment.inputs.length,
|
assertArgument(values.length === fragment.inputs.length,
|
||||||
"event arguments/values mismatch", "values", values);
|
"event arguments/values mismatch", "values", values);
|
||||||
|
|
||||||
eventFragment.inputs.forEach((param, index) => {
|
fragment.inputs.forEach((param, index) => {
|
||||||
const value = values[index];
|
const value = values[index];
|
||||||
if (param.indexed) {
|
if (param.indexed) {
|
||||||
if (param.type === "string") {
|
if (param.type === "string") {
|
||||||
@ -904,13 +937,15 @@ export class Interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Decode a filter for the event and the search criteria
|
// Decode a filter for the event and the search criteria
|
||||||
decodeEventLog(eventFragment: EventFragment | string, data: BytesLike, topics?: ReadonlyArray<string>): Result {
|
decodeEventLog(fragment: EventFragment | string, data: BytesLike, topics?: ReadonlyArray<string>): Result {
|
||||||
if (typeof(eventFragment) === "string") {
|
if (typeof(fragment) === "string") {
|
||||||
eventFragment = this.getEvent(eventFragment);
|
const f = this.getEvent(fragment);
|
||||||
|
assertArgument(f, "unknown event", "eventFragment", fragment);
|
||||||
|
fragment = f;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (topics != null && !eventFragment.anonymous) {
|
if (topics != null && !fragment.anonymous) {
|
||||||
const eventTopic = eventFragment.topicHash;
|
const eventTopic = fragment.topicHash;
|
||||||
assertArgument(isHexString(topics[0], 32) && topics[0].toLowerCase() === eventTopic,
|
assertArgument(isHexString(topics[0], 32) && topics[0].toLowerCase() === eventTopic,
|
||||||
"fragment/topic mismatch", "topics[0]", topics[0]);
|
"fragment/topic mismatch", "topics[0]", topics[0]);
|
||||||
topics = topics.slice(1);
|
topics = topics.slice(1);
|
||||||
@ -920,7 +955,7 @@ export class Interface {
|
|||||||
const nonIndexed: Array<ParamType> = [];
|
const nonIndexed: Array<ParamType> = [];
|
||||||
const dynamic: Array<boolean> = [];
|
const dynamic: Array<boolean> = [];
|
||||||
|
|
||||||
eventFragment.inputs.forEach((param, index) => {
|
fragment.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.from({ type: "bytes32", name: param.name }));
|
indexed.push(ParamType.from({ type: "bytes32", name: param.name }));
|
||||||
@ -942,7 +977,7 @@ export class Interface {
|
|||||||
const values: Array<any> = [ ];
|
const values: Array<any> = [ ];
|
||||||
const keys: Array<null | string> = [ ];
|
const keys: Array<null | string> = [ ];
|
||||||
let nonIndexedIndex = 0, indexedIndex = 0;
|
let nonIndexedIndex = 0, indexedIndex = 0;
|
||||||
eventFragment.inputs.forEach((param, index) => {
|
fragment.inputs.forEach((param, index) => {
|
||||||
let value = null;
|
let value = null;
|
||||||
if (param.indexed) {
|
if (param.indexed) {
|
||||||
if (resultIndexed == null) {
|
if (resultIndexed == null) {
|
||||||
|
@ -195,11 +195,19 @@ class WrappedMethod<A extends Array<any> = Array<any>, R = any, D extends R | Co
|
|||||||
|
|
||||||
// Only works on non-ambiguous keys (refined fragment is always non-ambiguous)
|
// Only works on non-ambiguous keys (refined fragment is always non-ambiguous)
|
||||||
get fragment(): FunctionFragment {
|
get fragment(): FunctionFragment {
|
||||||
return this._contract.interface.getFunction(this._key);
|
const fragment = this._contract.interface.getFunction(this._key);
|
||||||
|
assert(fragment, "no matching fragment", "UNSUPPORTED_OPERATION", {
|
||||||
|
operation: "fragment"
|
||||||
|
});
|
||||||
|
return fragment;
|
||||||
}
|
}
|
||||||
|
|
||||||
getFragment(...args: ContractMethodArgs<A>): FunctionFragment {
|
getFragment(...args: ContractMethodArgs<A>): FunctionFragment {
|
||||||
return this._contract.interface.getFunction(this._key, args);
|
const fragment = this._contract.interface.getFunction(this._key, args);
|
||||||
|
assert(fragment, "no matching fragment", "UNSUPPORTED_OPERATION", {
|
||||||
|
operation: "fragment"
|
||||||
|
});
|
||||||
|
return fragment;
|
||||||
}
|
}
|
||||||
|
|
||||||
async populateTransaction(...args: ContractMethodArgs<A>): Promise<ContractTransaction> {
|
async populateTransaction(...args: ContractMethodArgs<A>): Promise<ContractTransaction> {
|
||||||
@ -299,11 +307,23 @@ class WrappedEvent<A extends Array<any> = Array<any>> extends _WrappedEventBase(
|
|||||||
|
|
||||||
// Only works on non-ambiguous keys
|
// Only works on non-ambiguous keys
|
||||||
get fragment(): EventFragment {
|
get fragment(): EventFragment {
|
||||||
return this._contract.interface.getEvent(this._key);
|
const fragment = this._contract.interface.getEvent(this._key);
|
||||||
|
|
||||||
|
assert(fragment, "no matching fragment", "UNSUPPORTED_OPERATION", {
|
||||||
|
operation: "fragment"
|
||||||
|
});
|
||||||
|
|
||||||
|
return fragment;
|
||||||
}
|
}
|
||||||
|
|
||||||
getFragment(...args: ContractEventArgs<A>): EventFragment {
|
getFragment(...args: ContractEventArgs<A>): EventFragment {
|
||||||
return this._contract.interface.getEvent(this._key, args);
|
const fragment = this._contract.interface.getEvent(this._key, args);
|
||||||
|
|
||||||
|
assert(fragment, "no matching fragment", "UNSUPPORTED_OPERATION", {
|
||||||
|
operation: "fragment"
|
||||||
|
});
|
||||||
|
|
||||||
|
return fragment;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -355,7 +375,9 @@ async function getSubInfo(contract: BaseContract, event: ContractEventName): Pro
|
|||||||
if (Array.isArray(event)) {
|
if (Array.isArray(event)) {
|
||||||
const topicHashify = function(name: string): string {
|
const topicHashify = function(name: string): string {
|
||||||
if (isHexString(name, 32)) { return name; }
|
if (isHexString(name, 32)) { return name; }
|
||||||
return contract.interface.getEvent(name).topicHash;
|
const fragment = contract.interface.getEvent(name);
|
||||||
|
assertArgument(fragment, "unknown fragment", "name", name);
|
||||||
|
return fragment.topicHash;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Array of Topics and Names; e.g. `[ "0x1234...89ab", "Transfer(address)" ]`
|
// Array of Topics and Names; e.g. `[ "0x1234...89ab", "Transfer(address)" ]`
|
||||||
@ -375,6 +397,7 @@ async function getSubInfo(contract: BaseContract, event: ContractEventName): Pro
|
|||||||
} else {
|
} else {
|
||||||
// Name or Signature; e.g. `"Transfer", `"Transfer(address)"`
|
// Name or Signature; e.g. `"Transfer", `"Transfer(address)"`
|
||||||
fragment = contract.interface.getEvent(event);
|
fragment = contract.interface.getEvent(event);
|
||||||
|
assertArgument(fragment, "unknown fragment", "event", event);
|
||||||
topics = [ fragment.topicHash ];
|
topics = [ fragment.topicHash ];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user