From a5f84ccbd5e1fc7496517e774027995d55453724 Mon Sep 17 00:00:00 2001 From: Brett Cleary <27568879+BrettCleary@users.noreply.github.com> Date: Thu, 9 Apr 2026 13:18:37 +0200 Subject: [PATCH 1/6] allow for rpc url override for public client --- src/services/createPublicClient.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/services/createPublicClient.ts b/src/services/createPublicClient.ts index 892b7ca..e370c61 100644 --- a/src/services/createPublicClient.ts +++ b/src/services/createPublicClient.ts @@ -34,7 +34,10 @@ export function getChainTransport(chainId: number): Transport { } export function createPublicClient(chain: Chain) { - const transport = getBaseUrl() && getApiKey() ? getChainTransport(chain.id) : http() + const transport = + process.env.RPC_URL_OVERRIDE || (getBaseUrl() && getApiKey()) + ? getChainTransport(chain.id) + : http() return viemCreatePublicClient({ chain, transport }) } From 81e5097821525268b931be325f1bd4db1ca39d71 Mon Sep 17 00:00:00 2001 From: Brett Cleary <27568879+BrettCleary@users.noreply.github.com> Date: Thu, 9 Apr 2026 13:23:11 +0200 Subject: [PATCH 2/6] move fallback transport logic to getChainTransport --- src/services/createPublicClient.ts | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/src/services/createPublicClient.ts b/src/services/createPublicClient.ts index e370c61..320b177 100644 --- a/src/services/createPublicClient.ts +++ b/src/services/createPublicClient.ts @@ -17,27 +17,24 @@ const QUICKNODE_SLUGS: Record = { } /** - * Returns an `http()` transport using the paid QuickNode RPC for the given chain. - * Falls back to the default public RPC if the chain has no QuickNode endpoint configured. + * Returns the best available RPC transport for the given chain. + * Priority: RPC_URL_OVERRIDE > QuickNode > default public RPC. */ export function getChainTransport(chainId: number): Transport { - // Local development/testing: route all RPC calls through local anvil if (process.env.RPC_URL_OVERRIDE) { return http(process.env.RPC_URL_OVERRIDE) } - const slug = QUICKNODE_SLUGS[chainId] - if (slug === undefined) { - return http() + + if (getBaseUrl() && getApiKey()) { + const slug = QUICKNODE_SLUGS[chainId] + if (slug !== undefined) { + return http(`${getBaseUrl()}${slug}.quiknode.pro/${getApiKey()}`) + } } - const rpcUrl = `${getBaseUrl()}${slug}.quiknode.pro/${getApiKey()}` - return http(rpcUrl) + + return http() } export function createPublicClient(chain: Chain) { - const transport = - process.env.RPC_URL_OVERRIDE || (getBaseUrl() && getApiKey()) - ? getChainTransport(chain.id) - : http() - - return viemCreatePublicClient({ chain, transport }) + return viemCreatePublicClient({ chain, transport: getChainTransport(chain.id) }) } From 820c9c57d0450cfc6218aea4207df2929bd22f2d Mon Sep 17 00:00:00 2001 From: Brett Cleary <27568879+BrettCleary@users.noreply.github.com> Date: Thu, 9 Apr 2026 13:23:27 +0200 Subject: [PATCH 3/6] bump --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 88d11db..ee3711c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@coinfello/agent-cli", - "version": "0.3.3", + "version": "0.3.4", "description": "CLI for managing a web3 smart account and executing blockchain transactions via CoinFello", "repository": "CoinFello/agent-cli", "homepage": "https://coinfello.com", From 9cb9e09d841ada20d64dfd0c02452e8a050ae65b Mon Sep 17 00:00:00 2001 From: Brett Cleary <27568879+BrettCleary@users.noreply.github.com> Date: Thu, 9 Apr 2026 13:51:56 +0200 Subject: [PATCH 4/6] move unstake to afterall --- tests/e2e/send-prompt-cli.test.ts | 46 ++++++++++++++----------------- 1 file changed, 20 insertions(+), 26 deletions(-) diff --git a/tests/e2e/send-prompt-cli.test.ts b/tests/e2e/send-prompt-cli.test.ts index 4300efd..a0f66e7 100644 --- a/tests/e2e/send-prompt-cli.test.ts +++ b/tests/e2e/send-prompt-cli.test.ts @@ -210,6 +210,26 @@ describe("send_prompt CLI end-to-end", () => { await new Promise((resolve)=>setTimeout(()=>{resolve(1)}, 4000)) }); + afterAll(async () => { + try { + await runCli(["new_chat"]); + const { stdout, stderr } = await runCli([ + "send_prompt", + "swap ALL of my FUSDC to USDC on Base", + ]); + console.log("afterAll unstake stdout:", stdout); + console.error("afterAll unstake stderr:", stderr); + + const { stdout: approveOut, stderr: approveErr } = await runCli([ + "approve_delegation_request", + ]); + console.log("afterAll unstake approve stdout:", approveOut); + console.error("afterAll unstake approve stderr:", approveErr); + } catch (err) { + console.error("Cleanup (unstake FUSDC) failed:", err); + } + }, 120_000); + it("completes the delegation flow when asked to swap ETH for USDC via the CLI", async () => { await runCli(["new_chat"]); @@ -309,32 +329,6 @@ describe("send_prompt CLI end-to-end", () => { }); console.log(`Smart account USDC balance after staking: ${formatUnits(usdcAfterStake, 6)} USDC`); expect(usdcAfterStake).toBeLessThan(usdcBefore); - - // Step 3: Unstake USDC from the fluid vault (send_prompt + approve) - const { stdout: stdout3, stderr: stderr3 } = await runCli([ - "send_prompt", - "swap ALL of my FUSDC to USDC on Base", - ]); - console.log(stdout3); - console.error(stderr3); - - const { stdout: unstakeApproveOut, stderr: unstakeApproveErr } = await runCli([ - "approve_delegation_request", - ]); - console.log(unstakeApproveOut); - console.error(unstakeApproveErr); - - // wait for 2 blocks so balance check gets fresh data - await new Promise((resolve)=>setTimeout(()=>{resolve(1)}, 4000)) - - const usdcAfterUnstake = await basePublicClient.readContract({ - address: USDC_ADDRESS, - abi: ERC20_ABI, - functionName: "balanceOf", - args: [baseSmartAccountAddress], - }); - console.log(`Smart account USDC balance after unstaking: ${formatUnits(usdcAfterUnstake, 6)} USDC`); - expect(usdcAfterUnstake).toBeGreaterThan(usdcAfterStake); }); }) }); From 15c26414edd05a7f3c5a19b1fecae05ec1d0080c Mon Sep 17 00:00:00 2001 From: Brett Cleary <27568879+BrettCleary@users.noreply.github.com> Date: Tue, 14 Apr 2026 19:20:29 -0700 Subject: [PATCH 5/6] update send prompt test --- tests/e2e/send-prompt-cli.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/e2e/send-prompt-cli.test.ts b/tests/e2e/send-prompt-cli.test.ts index a0f66e7..a33ed51 100644 --- a/tests/e2e/send-prompt-cli.test.ts +++ b/tests/e2e/send-prompt-cli.test.ts @@ -215,7 +215,7 @@ describe("send_prompt CLI end-to-end", () => { await runCli(["new_chat"]); const { stdout, stderr } = await runCli([ "send_prompt", - "swap ALL of my FUSDC to USDC on Base", + "swap ALL of my FUSDC to USDC on Base. Do NOT ask me for another confirmation!", ]); console.log("afterAll unstake stdout:", stdout); console.error("afterAll unstake stderr:", stderr); @@ -307,7 +307,7 @@ describe("send_prompt CLI end-to-end", () => { // Step 2: Stake USDC into the fluid vault (send_prompt + approve) const { stdout: stdout2, stderr: stderr2 } = await runCli([ "send_prompt", - "stake 2 USDC into the fluid vault on Base", + "stake 0.5 USDC into the fluid vault on Base", ]); console.log(stdout2); console.error(stderr2); From 904108085d83b22836897189bedef3275214126d Mon Sep 17 00:00:00 2001 From: Brett Cleary <27568879+BrettCleary@users.noreply.github.com> Date: Tue, 14 Apr 2026 19:57:27 -0700 Subject: [PATCH 6/6] run tests sequentially to fix sign in conflicts --- tests/e2e/send-prompt.test.ts | 1 + vite.config.ts | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/tests/e2e/send-prompt.test.ts b/tests/e2e/send-prompt.test.ts index 9a37523..58a7558 100644 --- a/tests/e2e/send-prompt.test.ts +++ b/tests/e2e/send-prompt.test.ts @@ -15,6 +15,7 @@ describe("send_prompt read-only flow", () => { beforeAll(async () => { const privateKey = generatePrivateKey(); const { address } = await createSmartAccount(privateKey, CHAIN); + console.log('send prompt smart acct address: ', address) const config = { private_key: privateKey as Hex, diff --git a/vite.config.ts b/vite.config.ts index cf94911..8a89c25 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -29,5 +29,9 @@ export default defineConfig({ }, test: { testTimeout: 360_000, + fileParallelism: false, + sequence: { + concurrent: false, + }, }, });