Skip to content

Commit e04d06c

Browse files
jarrodwattsclaude
andcommitted
fix: use readContract for view/pure functions, remove session load log
contract write now checks ABI stateMutability — view/pure functions use eth_call via publicClient instead of sending a transaction. Also removes the noisy "Loaded session for" log on every command. Bumps CLI to 0.1.5. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 45ff1a6 commit e04d06c

4 files changed

Lines changed: 39 additions & 10 deletions

File tree

packages/agw-cli/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@abstract-foundation/agw-cli",
3-
"version": "0.1.4",
3+
"version": "0.1.5",
44
"type": "module",
55
"description": "Agent-first CLI for Abstract Global Wallet workflows",
66
"license": "MIT",

packages/agw-cli/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ async function main(): Promise<void> {
145145
program
146146
.name("agw-cli")
147147
.description("Agent-first CLI for Abstract Global Wallet workflows.")
148-
.version("0.1.4")
148+
.version("0.1.5")
149149
.showHelpAfterError();
150150

151151
program

packages/agw-core/src/session/manager.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ export class SessionManager {
4343
}
4444

4545
this.session = session;
46-
this.logger.info(`Loaded session for ${session.accountAddress}`);
4746
}
4847

4948
getSession(): AgwSessionData | null {

packages/agw-core/src/tools/write-contract.ts

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
1-
import { encodeFunctionData, isAddress, type Abi, type Address } from "viem";
1+
import { createPublicClient, encodeFunctionData, http, isAddress, type Abi, type AbiFunction, type Address } from "viem";
22
import { buildExplorerUrl } from "../utils/explorer.js";
33
import { assertToolCapability } from "./capability-guard.js";
44
import { resolveToolNetworkConfig } from "./network.js";
55
import type { ToolHandler } from "./types.js";
66

7+
function isViewOrPure(abi: Abi, functionName: string): boolean {
8+
const fn = abi.find(
9+
(item): item is AbiFunction =>
10+
item.type === "function" && item.name === functionName,
11+
);
12+
return fn?.stateMutability === "view" || fn?.stateMutability === "pure";
13+
}
14+
715
function assertAddress(value: unknown, field: string): Address {
816
if (typeof value !== "string" || !isAddress(value)) {
917
throw new Error(`${field} must be a valid 0x-prefixed address`);
@@ -80,16 +88,39 @@ export const writeContractTool: ToolHandler = {
8088
throw new Error("invalid abi/functionName/args payload");
8189
}
8290

83-
const status = context.sessionManager.getSessionStatus();
84-
if (status !== "active") {
85-
throw new Error(`session must be active (current status: ${status})`);
86-
}
87-
8891
const session = context.sessionManager.getSession();
8992
if (!session) {
9093
throw new Error("session is missing");
9194
}
9295

96+
const networkConfig = resolveToolNetworkConfig(context, session.chainId);
97+
98+
if (isViewOrPure(abi, functionName)) {
99+
const publicClient = createPublicClient({
100+
chain: networkConfig.chain,
101+
transport: http(networkConfig.rpcUrl),
102+
});
103+
104+
const result = await publicClient.readContract({
105+
address,
106+
abi,
107+
functionName,
108+
args,
109+
} as never);
110+
111+
return {
112+
result,
113+
accountAddress: session.accountAddress,
114+
chainId: session.chainId,
115+
contract: { address, functionName, args: args ?? [] },
116+
};
117+
}
118+
119+
const status = context.sessionManager.getSessionStatus();
120+
if (status !== "active") {
121+
throw new Error(`session must be active (current status: ${status})`);
122+
}
123+
93124
const abstractClient = await context.sessionManager.getAbstractClient();
94125
const txHash = await abstractClient.writeContract({
95126
address,
@@ -99,7 +130,6 @@ export const writeContractTool: ToolHandler = {
99130
value,
100131
} as never);
101132

102-
const networkConfig = resolveToolNetworkConfig(context, session.chainId);
103133
const explorerBase = networkConfig.chain.blockExplorers?.default?.url ?? null;
104134

105135
return {

0 commit comments

Comments
 (0)