Added better CCIP debug tracing.
This commit is contained in:
parent
c85cc72564
commit
96d1eaabf3
@ -71,6 +71,33 @@ function getTag(prefix: string, value: any): string {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type DebugEventAbstractProvider = {
|
||||||
|
action: "sendCcipReadFetchRequest",
|
||||||
|
request: FetchRequest
|
||||||
|
index: number
|
||||||
|
urls: Array<string>
|
||||||
|
} | {
|
||||||
|
action: "receiveCcipReadFetchResult",
|
||||||
|
request: FetchRequest,
|
||||||
|
result: any
|
||||||
|
} | {
|
||||||
|
action: "receiveCcipReadFetchError",
|
||||||
|
request: FetchRequest,
|
||||||
|
result: any
|
||||||
|
} | {
|
||||||
|
action: "sendCcipReadCall",
|
||||||
|
transaction: { to: string, data: string }
|
||||||
|
} | {
|
||||||
|
action: "receiveCcipReadCallResult",
|
||||||
|
transaction: { to: string, data: string }
|
||||||
|
result: string
|
||||||
|
} | {
|
||||||
|
action: "receiveCcipReadCallError",
|
||||||
|
transaction: { to: string, data: string }
|
||||||
|
error: Error
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// Only sub-classes overriding the _getSubscription method will care about this
|
// Only sub-classes overriding the _getSubscription method will care about this
|
||||||
export type Subscription = {
|
export type Subscription = {
|
||||||
type: "block" | "close" | "debug" | "network" | "pending",
|
type: "block" | "close" | "debug" | "network" | "pending",
|
||||||
@ -203,9 +230,9 @@ async function getSubscription(_event: ProviderEvent, provider: AbstractProvider
|
|||||||
|
|
||||||
function getTime(): number { return (new Date()).getTime(); }
|
function getTime(): number { return (new Date()).getTime(); }
|
||||||
|
|
||||||
export interface ProviderPlugin {
|
export interface AbstractProviderPlugin {
|
||||||
readonly name: string;
|
readonly name: string;
|
||||||
validate(provider: Provider): ProviderPlugin;
|
connect(provider: AbstractProvider): AbstractProviderPlugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type PerformActionFilter = {
|
export type PerformActionFilter = {
|
||||||
@ -225,6 +252,9 @@ export interface PerformActionTransaction extends PreparedTransactionRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type PerformActionRequest = {
|
export type PerformActionRequest = {
|
||||||
|
method: "broadcastTransaction",
|
||||||
|
signedTransaction: string
|
||||||
|
} | {
|
||||||
method: "call",
|
method: "call",
|
||||||
transaction: PerformActionTransaction, blockTag: BlockTag
|
transaction: PerformActionTransaction, blockTag: BlockTag
|
||||||
} | {
|
} | {
|
||||||
@ -266,9 +296,6 @@ export type PerformActionRequest = {
|
|||||||
} | {
|
} | {
|
||||||
method: "getTransactionResult",
|
method: "getTransactionResult",
|
||||||
hash: string
|
hash: string
|
||||||
} | {
|
|
||||||
method: "broadcastTransaction", // @TODO: rename to broadcast
|
|
||||||
signedTransaction: string
|
|
||||||
};
|
};
|
||||||
|
|
||||||
type _PerformAccountRequest = {
|
type _PerformAccountRequest = {
|
||||||
@ -290,7 +317,7 @@ type CcipArgs = {
|
|||||||
export class AbstractProvider implements Provider {
|
export class AbstractProvider implements Provider {
|
||||||
|
|
||||||
#subs: Map<string, Sub>;
|
#subs: Map<string, Sub>;
|
||||||
#plugins: Map<string, ProviderPlugin>;
|
#plugins: Map<string, AbstractProviderPlugin>;
|
||||||
|
|
||||||
// null=unpaused, true=paused+dropWhilePaused, false=paused
|
// null=unpaused, true=paused+dropWhilePaused, false=paused
|
||||||
#pausedState: null | boolean;
|
#pausedState: null | boolean;
|
||||||
@ -341,19 +368,19 @@ export class AbstractProvider implements Provider {
|
|||||||
|
|
||||||
get provider(): this { return this; }
|
get provider(): this { return this; }
|
||||||
|
|
||||||
get plugins(): Array<ProviderPlugin> {
|
get plugins(): Array<AbstractProviderPlugin> {
|
||||||
return Array.from(this.#plugins.values());
|
return Array.from(this.#plugins.values());
|
||||||
}
|
}
|
||||||
|
|
||||||
attachPlugin(plugin: ProviderPlugin): this {
|
attachPlugin(plugin: AbstractProviderPlugin): this {
|
||||||
if (this.#plugins.get(plugin.name)) {
|
if (this.#plugins.get(plugin.name)) {
|
||||||
throw new Error(`cannot replace existing plugin: ${ plugin.name } `);
|
throw new Error(`cannot replace existing plugin: ${ plugin.name } `);
|
||||||
}
|
}
|
||||||
this.#plugins.set(plugin.name, plugin.validate(this));
|
this.#plugins.set(plugin.name, plugin.connect(this));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
getPlugin<T extends ProviderPlugin = ProviderPlugin>(name: string): null | T {
|
getPlugin<T extends AbstractProviderPlugin = AbstractProviderPlugin>(name: string): null | T {
|
||||||
return <T>(this.#plugins.get(name)) || null;
|
return <T>(this.#plugins.get(name)) || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -406,13 +433,19 @@ export class AbstractProvider implements Provider {
|
|||||||
request.body = { data, sender };
|
request.body = { data, sender };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.emit("debug", { action: "sendCcipReadFetchRequest", request, index: i, urls });
|
||||||
|
|
||||||
let errorMessage = "unknown error";
|
let errorMessage = "unknown error";
|
||||||
|
|
||||||
const resp = await request.send();
|
const resp = await request.send();
|
||||||
try {
|
try {
|
||||||
const result = resp.bodyJson;
|
const result = resp.bodyJson;
|
||||||
if (result.data) { return result.data; }
|
if (result.data) {
|
||||||
|
this.emit("debug", { action: "receiveCcipReadFetchResult", request, result });
|
||||||
|
return result.data;
|
||||||
|
}
|
||||||
if (result.message) { errorMessage = result.message; }
|
if (result.message) { errorMessage = result.message; }
|
||||||
|
this.emit("debug", { action: "receiveCcipReadFetchError", request, result });
|
||||||
} catch (error) { }
|
} catch (error) { }
|
||||||
|
|
||||||
// 4xx indicates the result is not present; stop
|
// 4xx indicates the result is not present; stop
|
||||||
@ -485,8 +518,9 @@ export class AbstractProvider implements Provider {
|
|||||||
return blockTag;
|
return blockTag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (isHexString(blockTag)) {
|
if (isHexString(blockTag)) {
|
||||||
if (dataLength(blockTag) === 32) { return blockTag; }
|
if (isHexString(blockTag, 32)) { return blockTag; }
|
||||||
return toQuantity(blockTag);
|
return toQuantity(blockTag);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -737,12 +771,20 @@ export class AbstractProvider implements Provider {
|
|||||||
assert(ccipResult != null, "CCIP Read failed to fetch data", "OFFCHAIN_FAULT", {
|
assert(ccipResult != null, "CCIP Read failed to fetch data", "OFFCHAIN_FAULT", {
|
||||||
reason: "FETCH_FAILED", transaction, info: { data: error.data, errorArgs: ccipArgs.errorArgs } });
|
reason: "FETCH_FAILED", transaction, info: { data: error.data, errorArgs: ccipArgs.errorArgs } });
|
||||||
|
|
||||||
return this.#call({
|
const tx = {
|
||||||
to: txSender,
|
to: txSender,
|
||||||
data: concat([
|
data: concat([ ccipArgs.selector, encodeBytes([ ccipResult, ccipArgs.extraData ]) ])
|
||||||
ccipArgs.selector, encodeBytes([ ccipResult, ccipArgs.extraData ])
|
};
|
||||||
]),
|
|
||||||
}, blockTag, attempt + 1);
|
this.emit("debug", { action: "sendCcipReadCall", transaction: tx });
|
||||||
|
try {
|
||||||
|
const result = await this.#call(tx, blockTag, attempt + 1);
|
||||||
|
this.emit("debug", { action: "receiveCcipReadCallResult", transaction: Object.assign({ }, tx), result });
|
||||||
|
return result;
|
||||||
|
} catch (error) {
|
||||||
|
this.emit("debug", { action: "receiveCcipReadCallError", transaction: Object.assign({ }, tx), error });
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw error;
|
throw error;
|
||||||
|
@ -11,7 +11,7 @@ import {
|
|||||||
|
|
||||||
import type { BigNumberish, BytesLike, EthersError } from "../utils/index.js";
|
import type { BigNumberish, BytesLike, EthersError } from "../utils/index.js";
|
||||||
|
|
||||||
import type { AbstractProvider, ProviderPlugin } from "./abstract-provider.js";
|
import type { AbstractProvider, AbstractProviderPlugin } from "./abstract-provider.js";
|
||||||
import type { EnsPlugin } from "./plugins-network.js";
|
import type { EnsPlugin } from "./plugins-network.js";
|
||||||
import type { TransactionRequest, Provider } from "./provider.js";
|
import type { TransactionRequest, Provider } from "./provider.js";
|
||||||
|
|
||||||
@ -117,14 +117,14 @@ export interface AvatarResult {
|
|||||||
url: null | string;
|
url: null | string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export abstract class MulticoinProviderPlugin implements ProviderPlugin {
|
export abstract class MulticoinProviderPlugin implements AbstractProviderPlugin {
|
||||||
readonly name!: string;
|
readonly name!: string;
|
||||||
|
|
||||||
constructor(name: string) {
|
constructor(name: string) {
|
||||||
defineProperties<MulticoinProviderPlugin>(this, { name });
|
defineProperties<MulticoinProviderPlugin>(this, { name });
|
||||||
}
|
}
|
||||||
|
|
||||||
validate(proivder: Provider): ProviderPlugin {
|
connect(proivder: Provider): MulticoinProviderPlugin {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,7 +141,7 @@ export abstract class MulticoinProviderPlugin implements ProviderPlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const BasicMulticoinPluginId = "org.ethers.provider-prugins.basicmulticoin";
|
const BasicMulticoinPluginId = "org.ethers.plugins.BasicMulticoinProviderPlugin";
|
||||||
|
|
||||||
export class BasicMulticoinProviderPlugin extends MulticoinProviderPlugin {
|
export class BasicMulticoinProviderPlugin extends MulticoinProviderPlugin {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
@ -69,7 +69,7 @@ export {
|
|||||||
|
|
||||||
export type {
|
export type {
|
||||||
Subscription, Subscriber,
|
Subscription, Subscriber,
|
||||||
ProviderPlugin,
|
AbstractProviderPlugin,
|
||||||
PerformActionFilter, PerformActionTransaction, PerformActionRequest
|
PerformActionFilter, PerformActionTransaction, PerformActionRequest
|
||||||
} from "./abstract-provider.js"
|
} from "./abstract-provider.js"
|
||||||
export type { ContractRunner } from "./contracts.js";
|
export type { ContractRunner } from "./contracts.js";
|
||||||
|
Loading…
Reference in New Issue
Block a user