Skip to content

Commit

Permalink
display multiple fn names
Browse files Browse the repository at this point in the history
  • Loading branch information
karooolis committed Oct 24, 2024
1 parent aaf5a8b commit 38ebb01
Show file tree
Hide file tree
Showing 5 changed files with 163 additions and 225 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,16 +45,21 @@ export const columns = [
);
},
}),
columnHelper.accessor("functionData.functionName", {
columnHelper.accessor("calls", {
header: "Function",
cell: (row) => {
const functionName = row.getValue();
const calls = row.getValue();
const status = row.row.original.status;
return (
<div className="flex items-center">
<Badge variant="secondary">
<WalletIcon className="mr-2 h-3 w-3" /> {functionName}
</Badge>
<div className="flex gap-2">
{calls?.map((call, idx) => (
<Badge variant="secondary" key={idx}>
{call.functionName}
</Badge>
))}
</div>

{status === "pending" && <CheckCheckIcon className="ml-2 h-4 w-4 text-white/60" />}
{status === "success" && <CheckCheckIcon className="ml-2 h-4 w-4 text-green-400" />}
{(status === "reverted" || status === "rejected") && <XIcon className="ml-2 h-4 w-4 text-red-400" />}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ export type ObservedTransaction = {
timestamp?: bigint;
transaction?: Transaction;
functionData?: DecodeFunctionDataReturnType;

calls?: DecodeFunctionDataReturnType[]; // TODO: rename to functions?

value?: bigint;
receipt?: TransactionReceipt;
status: "pending" | "success" | "reverted" | "rejected" | "unknown";
Expand All @@ -35,63 +38,58 @@ export type ObservedTransaction = {
error?: BaseError;
};

const arr = [];

Check failure on line 41 in packages/explorer/src/app/(explorer)/[chainName]/worlds/[worldAddress]/observe/useObservedTransactions.ts

View workflow job for this annotation

GitHub Actions / Run lint

'arr' is assigned a value but never used

export function useObservedTransactions() {
const { worldAddress } = useParams<{ worldAddress: string }>();
const transactions = useStore(worldStore, (state) => state.transactions);
const observerWrites = useStore(observerStore, (state) => state.writes);
const observerSends = useStore(observerStore, (state) => state.sends);

// console.log("observerWrites", observerWrites);
console.log("observerSends", observerSends);

// const sendsTransactions = useMemo(() => {
// return Object.values(observerSends).flatMap((send) => {
// return send.calls.map((call) => {
// const parsedAbiItem = parseAbiItem(`function ${call.functionSignature}`) as AbiFunction;

// return {
// writeId: `${send.writeId}-${call.functionSignature}`,
// from: "0x123", // TODO: send.from
// hash: "0x123", // TODO: send.hash
// status: "pending",
// timestamp: undefined,
// functionData: {
// functionName: parsedAbiItem.name,
// args: call.args,
// },
// value: 0n, // TODO: send.value
// error: undefined, // TODO: send.error
// ...call,
// };
// });
// });
// }, [observerSends]);

// console.log("sendsTransactions", sendsTransactions);
console.log("observerWrites", observerWrites);

const mergedTransactions = useMemo((): ObservedTransaction[] => {
const mergedMap = new Map<string | undefined, ObservedTransaction>();

for (const write of Object.values(observerWrites)) {
if (write.address.toLowerCase() !== worldAddress.toLowerCase()) continue; // TODO: filter entrypoint
if (write.clientType === "bundlerClient") {
mergedMap.set(write.hash || write.writeId, {
hash: write.hash,
writeId: write.writeId,
from: write.from,
status: "pending",
timestamp: BigInt(write.time) / 1000n,
functionData: {
functionName: "multiple",
args: [],
},
calls: write.calls, // TODO: rename to functions?
value: 0n,
error: undefined,
});
} else {
// TODO: original
if (write.address.toLowerCase() !== worldAddress.toLowerCase()) continue; // TODO: filter entrypoint

const parsedAbiItem = parseAbiItem(`function ${write.functionSignature}`) as AbiFunction;
const writeResult = write.events.find((event): event is Message<"write:result"> => event.type === "write:result");
const parsedAbiItem = parseAbiItem(`function ${write.functionSignature}`) as AbiFunction;
const writeResult = write.events.find(
(event): event is Message<"write:result"> => event.type === "write:result",
);

mergedMap.set(write.hash || write.writeId, {
hash: write.hash,
writeId: write.writeId,
from: write.from,
status: writeResult?.status === "rejected" ? "rejected" : "pending",
timestamp: BigInt(write.time) / 1000n,
functionData: {
functionName: parsedAbiItem.name,
args: write.args,
},
value: write.value,
error: writeResult && "reason" in writeResult ? (writeResult.reason as BaseError) : undefined,
write,
});
mergedMap.set(write.hash || write.writeId, {
hash: write.hash,
writeId: write.writeId,
from: write.from,
status: writeResult?.status === "rejected" ? "rejected" : "pending",
timestamp: BigInt(write.time) / 1000n,
functionData: {
functionName: parsedAbiItem.name,
args: write.args,
},
value: write.value,
error: writeResult && "reason" in writeResult ? (writeResult.reason as BaseError) : undefined,
write,
});
}
}

for (const transaction of transactions) {
Expand All @@ -103,13 +101,10 @@ export function useObservedTransactions() {
}
}

// Add sendsTransactions to the mergedMap
// for (const sendTransaction of sendsTransactions) {
// mergedMap.set(sendTransaction.writeId + Math.random().toString(), sendTransaction);
// }

return Array.from(mergedMap.values()).sort((a, b) => Number(b.timestamp ?? 0n) - Number(a.timestamp ?? 0n));
}, [observerWrites, transactions, worldAddress]);

console.log("mergedTransactions", mergedTransactions);

return mergedTransactions;
}
144 changes: 45 additions & 99 deletions packages/explorer/src/observer/decorator.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Account, Chain, Client, Hex, Transport, WalletActions, decodeFunctionData, getAbiItem, parseAbi } from "viem";
import {
BundlerActions,
entryPoint07Abi,
entryPoint07Address,
sendUserOperation,
Expand All @@ -23,119 +24,63 @@ export type ObserverOptions = {

let writeCounter = 0;

// type ObservedTransaction = {
// writeId: string;
// hash?: Hex;
// from?: Address;
// timestamp?: bigint;
// transaction?: Transaction;
// functionData?: DecodeFunctionDataReturnType;
// value?: bigint;
// receipt?: TransactionReceipt;
// status: "pending" | "success" | "reverted" | "rejected" | "unknown";
// write?: Write;
// logs?: Log[];
// error?: BaseError;
// }

export function observer({ explorerUrl = "http://localhost:13690", waitForTransaction }: ObserverOptions = {}): <
transport extends Transport,
chain extends Chain | undefined = Chain | undefined,
account extends Account | undefined = Account | undefined,
>(
client: Client<transport, chain, account>,
) => Pick<WalletActions<chain, account>, "writeContract"> {
) => Pick<WalletActions<chain, account>, "writeContract"> & Pick<BundlerActions, "sendUserOperation"> {
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 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,
};
}),
});
return {
async sendUserOperation(args) {
console.log("observerWrite sendUserOperation args:", args);

write.then((hash) => {
const receipt = getAction(client, waitForUserOperationReceipt, "waitForUserOperationReceipt")({ hash });

emit("waitForUserOperationReceipt", { writeId, hash });
Promise.allSettled([receipt]).then(async ([result]) => {
emit("waitForUserOperationReceipt:result", { ...result.value, writeId });

// 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);
const writeId = `${client.uid}-${++writeCounter}`; // TODO: rename write to send ?
const write = getAction(client, sendUserOperation, "sendUserOperation")(args);
const calls = args.calls;

emit("write", {
writeId,
clientType: client.type,
from: client.account!.address,
calls: calls.map((call) => {
const functionAbiItem = getAbiItem({
abi: call.abi,
name: call.functionName,
args: call.args,
} as never)!;

return {
to: call.to, // TODO: rename to `to`
functionSignature: formatAbiItem(functionAbiItem),
functionName: call.functionName,
args: call.args,
};
}),
});
Promise.allSettled([write]).then(([result]) => {
emit("write:result", { ...result, writeId });
});

write.then((hash) => {
const receipt = getAction(client, waitForUserOperationReceipt, "waitForUserOperationReceipt")({ hash });

emit("waitForUserOperationReceipt", { writeId, hash });
Promise.allSettled([receipt]).then(async ([result]) => {
emit("waitForUserOperationReceipt:result", {
...result.value,
hash: result.value.receipt.transactionHash,
writeId,
});
});
});

// 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,
// });

return write;
},
};
}
return write;
},

return {
async writeContract(args) {
const writeId = `${client.uid}-${++writeCounter}`;
const write = getAction(client, writeContract, "writeContract")(args);
Expand All @@ -149,6 +94,7 @@ export function observer({ explorerUrl = "http://localhost:13690", waitForTransa

emit("write", {
writeId,
clientType: client.type,
address: args.address,
from: client.account!.address,
functionSignature: formatAbiItem(functionAbiItem),
Expand Down
17 changes: 9 additions & 8 deletions packages/explorer/src/observer/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@ import { ReceiptSummary } from "./common";

export type Messages = {
ping: {};
send: {
writeId: string;
calls: {
to: Address;
functionSignature: string;
args: unknown[];
}[];
};
// send: {
// writeId: string;
// calls: {
// to: Address;
// functionSignature: string;
// args: unknown[];
// }[];
// };
// "send:result": PromiseSettledResult<Hash> & { writeId: string };
waitForUserOperationReceipt: {
writeId: string;
hash: Hash;
Expand Down
Loading

0 comments on commit 38ebb01

Please sign in to comment.