From fe86e954b1b17a7e473b9097be1d5a6281b6b713 Mon Sep 17 00:00:00 2001 From: karooolis Date: Thu, 24 Oct 2024 15:25:51 +0300 Subject: [PATCH] send user op via observer --- packages/explorer/src/observer/decorator.ts | 172 ++++++++++---------- packages/explorer/src/observer/messages.ts | 8 + packages/explorer/src/observer/store.ts | 49 ++++-- 3 files changed, 134 insertions(+), 95 deletions(-) diff --git a/packages/explorer/src/observer/decorator.ts b/packages/explorer/src/observer/decorator.ts index 048a823dfc..646ec2e585 100644 --- a/packages/explorer/src/observer/decorator.ts +++ b/packages/explorer/src/observer/decorator.ts @@ -1,33 +1,9 @@ -import { - Account, - Chain, - Client, - Hex, - Transport, - WalletActions, - decodeFunctionData, - getAbiItem, - parseAbi, - parseEventLogs, -} from "viem"; -import { - entryPoint07Abi, - entryPoint07Address, - getUserOperation, - getUserOperationHash, - sendUserOperation, - waitForUserOperationReceipt, -} from "viem/account-abstraction"; +import { Account, Chain, Client, Hex, Transport, WalletActions, decodeFunctionData, getAbiItem, parseAbi } from "viem"; +import { entryPoint07Abi, entryPoint07Address, sendUserOperation } from "viem/account-abstraction"; import { getTransaction, waitForTransactionReceipt, writeContract } from "viem/actions"; import { formatAbiItem, getAction } from "viem/utils"; -import IBaseWorldAbi from "@latticexyz/world/out/IBaseWorld.sol/IBaseWorld.abi.json"; -import { - doomWorldAbi, - userOperationEventAbi, -} from "../app/(explorer)/[chainName]/worlds/[worldAddress]/observe/TransactionsWatcher"; import { createBridge } from "./bridge"; import { ReceiptSummary } from "./common"; -import { getUserOperationHashV07 } from "./utils"; export type WaitForTransaction = (hash: Hex) => Promise; @@ -48,64 +24,92 @@ export function observer({ explorerUrl = "http://localhost:13690", waitForTransa const emit = createBridge({ url: `${explorerUrl}/internal/observer-relay` }); return (client) => { - // if (client.type === "bundlerClient") { - // return { - // async sendUserOperation(args) { - // console.log("observerWrite sendUserOperation args:", args); - - // const write = getAction(client, sendUserOperation, "sendUserOperation")(args); - // const calls = args.calls; - - // // for (const call of calls) { - // const call = calls[0]; - // const writeId = `${client.uid}-${++writeCounter}`; // TODO: rename write to send ? - // const { to, args: functionArgs, abi, functionName } = call; - - // console.log("observerWrite call", call); - - // const functionAbiItem = getAbiItem({ - // abi, - // name: functionName, - // args, - // } as never)!; - - // emit("write", { - // writeId, - // address: to, - // from: client.account!.address, - // functionSignature: formatAbiItem(functionAbiItem), - // args: (functionArgs.args ?? []) as never, - // value: functionArgs.value, - // }); - - // write.then((hash) => { - // const receipt = getAction(client, waitForUserOperationReceipt, "waitForUserOperationReceipt")({ hash }); - // Promise.allSettled([receipt]).then(async ([result]) => { - // console.log("observerWrite waitForUserOperationReceipt result:", result); - - // const logs = result.value?.logs; - // const parsedLogs = parseEventLogs({ - // abi: [...doomWorldAbi, userOperationEventAbi], - // logs, - // }); - - // const receiptLogs = result.value?.receipt?.logs; - // const parsedReceiptLogs = parseEventLogs({ - // abi: [...doomWorldAbi, userOperationEventAbi], - // logs: receiptLogs, - // }); - - // console.log("observerWrite parsedLogs:", parsedLogs); - // console.log("observerWrite parsedReceiptLogs:", parsedReceiptLogs); - - // // TODO: emit("waitForTransactionReceipt", { hash: txHash, writeId }); - // }); - // }); - - // return write; - // }, - // }; - // } + if (client.type === "bundlerClient") { + return { + async sendUserOperation(args) { + console.log("observerWrite sendUserOperation args:", args); + + const writeId = `${client.uid}-${++writeCounter}`; // TODO: rename write to send ? + const write = getAction(client, sendUserOperation, "sendUserOperation")(args); + const calls = args.calls; + + emit("send", { + writeId, + calls: calls.map((call) => { + const functionAbiItem = getAbiItem({ + abi: call.abi, + name: call.functionName, + args: call.args, + } as never)!; + + return { + to: call.to, + functionSignature: formatAbiItem(functionAbiItem), + args: call.args, + }; + }), + }); + + // emit("write", { + // writeId, + + // address: args.address, + // from: client.account!.address, + // functionSignature: "batch call", // formatAbiItem(functionAbiItem), + // args: (args.args ?? []) as never, + // value: args.value, + // }); + + // // for (const call of calls) { + // const call = calls[0]; + // + // const { to, args: functionArgs, abi, functionName } = call; + + // console.log("observerWrite call", call); + + // const functionAbiItem = getAbiItem({ + // abi, + // name: functionName, + // args, + // } as never)!; + + // emit("write", { + // writeId, + // address: to, + // from: client.account!.address, + // functionSignature: formatAbiItem(functionAbiItem), + // args: (functionArgs.args ?? []) as never, + // value: functionArgs.value, + // }); + + // write.then((hash) => { + // const receipt = getAction(client, waitForUserOperationReceipt, "waitForUserOperationReceipt")({ hash }); + // Promise.allSettled([receipt]).then(async ([result]) => { + // console.log("observerWrite waitForUserOperationReceipt result:", result); + + // const logs = result.value?.logs; + // const parsedLogs = parseEventLogs({ + // abi: [...doomWorldAbi, userOperationEventAbi], + // logs, + // }); + + // const receiptLogs = result.value?.receipt?.logs; + // const parsedReceiptLogs = parseEventLogs({ + // abi: [...doomWorldAbi, userOperationEventAbi], + // logs: receiptLogs, + // }); + + // console.log("observerWrite parsedLogs:", parsedLogs); + // console.log("observerWrite parsedReceiptLogs:", parsedReceiptLogs); + + // // TODO: emit("waitForTransactionReceipt", { hash: txHash, writeId }); + // }); + // }); + + return write; + }, + }; + } return { async writeContract(args) { diff --git a/packages/explorer/src/observer/messages.ts b/packages/explorer/src/observer/messages.ts index 2526a25fbe..2448f87d0e 100644 --- a/packages/explorer/src/observer/messages.ts +++ b/packages/explorer/src/observer/messages.ts @@ -3,6 +3,14 @@ import { ReceiptSummary } from "./common"; export type Messages = { ping: {}; + send: { + writeId: string; + calls: { + to: Address; + functionSignature: string; + args: unknown[]; + }[]; + }; write: { writeId: string; address: Address; diff --git a/packages/explorer/src/observer/store.ts b/packages/explorer/src/observer/store.ts index f7145a04c3..fdeb6249dc 100644 --- a/packages/explorer/src/observer/store.ts +++ b/packages/explorer/src/observer/store.ts @@ -21,14 +21,27 @@ export type Write = { error?: Error; }; +export type Send = { + writeId: string; + calls: { + to: Address; + functionSignature: string; + args: unknown[]; + }[]; +}; + export type State = { writes: { [id: string]: Write; }; + sends: { + [id: string]: Send; + }; }; export const store = createStore(() => ({ writes: {}, + sends: {}, })); debug("listening for relayed messages", relayChannelName); @@ -36,17 +49,31 @@ const channel = new BroadcastChannel(relayChannelName); channel.addEventListener("message", ({ data }: MessageEvent) => { if (data.type === "ping") return; store.setState((state) => { - const write = data.type === "write" ? ({ ...data, events: [] } satisfies Write) : state.writes[data.writeId]; - return { - writes: { - ...state.writes, - [data.writeId]: { - ...write, - type: data.type, - hash: data.type === "waitForTransactionReceipt" ? data.hash : write.hash, - events: [...write.events, data], + if (data.type === "send") { + return { + ...state, + sends: { + ...state.sends, + [data.writeId]: { + writeId: data.writeId, + calls: data.calls, + }, + }, + }; + } else { + const write = data.type === "write" ? ({ ...data, events: [] } satisfies Write) : state.writes[data.writeId]; + return { + ...state, + writes: { + ...state.writes, + [data.writeId]: { + ...write, + type: data.type, + hash: data.type === "waitForTransactionReceipt" ? data.hash : write.hash, + events: [...write.events, data], + }, }, - }, - }; + }; + } }); });