@sherwoodagent/cli 0.82.0 → 0.83.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/dist/{addresses-FGJ4I4IG.js → addresses-MS6BB7AB.js} +3 -3
  2. package/dist/{agent-QUINV725.js → agent-C5XZSK7Z.js} +6 -6
  3. package/dist/{chat-5TUHBSIA.js → chat-FGTYCJ4B.js} +7 -7
  4. package/dist/{chunk-Y6XOH23Y.js → chunk-4GO7I33U.js} +4 -4
  5. package/dist/{chunk-4KJUX5SS.js → chunk-4WAEM2TC.js} +4 -4
  6. package/dist/{chunk-LZEV772I.js → chunk-AJ46XIGY.js} +4 -4
  7. package/dist/chunk-AJ46XIGY.js.map +1 -0
  8. package/dist/{chunk-MC5QEPW3.js → chunk-AOL2DJTK.js} +5 -5
  9. package/dist/{chunk-EPQR6PJ4.js → chunk-AQPTBVEA.js} +20 -4
  10. package/dist/chunk-AQPTBVEA.js.map +1 -0
  11. package/dist/{chunk-6BVA4RIH.js → chunk-CCNOXDZ7.js} +2 -2
  12. package/dist/{chunk-UHGWEJ24.js → chunk-G34TNE53.js} +2 -2
  13. package/dist/{chunk-PMRYC6SF.js → chunk-I7TMY7AS.js} +2 -2
  14. package/dist/{chunk-54CLRBPB.js → chunk-M34JVPJO.js} +4 -4
  15. package/dist/chunk-M34JVPJO.js.map +1 -0
  16. package/dist/{chunk-27XY2HXV.js → chunk-MBWFTXF5.js} +4 -4
  17. package/dist/{chunk-76DLC7CM.js → chunk-NKRMMFQG.js} +3 -3
  18. package/dist/{chunk-3TLKNRZV.js → chunk-ZW2VKCFZ.js} +2 -2
  19. package/dist/chunk-ZW2VKCFZ.js.map +1 -0
  20. package/dist/{client-VNSFNDF4.js → client-OPZ2ORWW.js} +3 -3
  21. package/dist/{cron-QMLRWDJG.js → cron-E3UAZF5B.js} +1 -1
  22. package/dist/cron-E3UAZF5B.js.map +1 -0
  23. package/dist/{eas-PJ3Y4NDB.js → eas-32PEJETG.js} +5 -5
  24. package/dist/{governor-4ASVLOCI.js → governor-GSCXEZWI.js} +5 -5
  25. package/dist/index.js +1041 -944
  26. package/dist/index.js.map +1 -1
  27. package/dist/{network-RI54LT2Y.js → network-HCFCNZUI.js} +2 -2
  28. package/dist/{price-JX2LFKFW.js → price-OUL7WIXQ.js} +5 -5
  29. package/dist/{providers-F6MNPMR4.js → providers-4HQHB7V5.js} +4 -4
  30. package/dist/{research-5ZJTRILJ.js → research-2RWAMWWH.js} +7 -7
  31. package/dist/{session-AXLPYJHX.js → session-SIOJZO6P.js} +10 -10
  32. package/dist/{trade-BZM7K2F4.js → trade-ZEIY3MCL.js} +15 -15
  33. package/dist/trade-ZEIY3MCL.js.map +1 -0
  34. package/dist/{vault-AWQBFD4C.js → vault-VDADZFSV.js} +7 -7
  35. package/dist/{xmtp-M74BRF3G.js → xmtp-2U7CSBXM.js} +5 -5
  36. package/package.json +5 -2
  37. package/scripts/pin-xmtp-bindings.cjs +26 -10
  38. package/dist/chunk-3TLKNRZV.js.map +0 -1
  39. package/dist/chunk-54CLRBPB.js.map +0 -1
  40. package/dist/chunk-EPQR6PJ4.js.map +0 -1
  41. package/dist/chunk-LZEV772I.js.map +0 -1
  42. package/dist/cron-QMLRWDJG.js.map +0 -1
  43. package/dist/trade-BZM7K2F4.js.map +0 -1
  44. /package/dist/{addresses-FGJ4I4IG.js.map → addresses-MS6BB7AB.js.map} +0 -0
  45. /package/dist/{agent-QUINV725.js.map → agent-C5XZSK7Z.js.map} +0 -0
  46. /package/dist/{chat-5TUHBSIA.js.map → chat-FGTYCJ4B.js.map} +0 -0
  47. /package/dist/{chunk-Y6XOH23Y.js.map → chunk-4GO7I33U.js.map} +0 -0
  48. /package/dist/{chunk-4KJUX5SS.js.map → chunk-4WAEM2TC.js.map} +0 -0
  49. /package/dist/{chunk-MC5QEPW3.js.map → chunk-AOL2DJTK.js.map} +0 -0
  50. /package/dist/{chunk-6BVA4RIH.js.map → chunk-CCNOXDZ7.js.map} +0 -0
  51. /package/dist/{chunk-UHGWEJ24.js.map → chunk-G34TNE53.js.map} +0 -0
  52. /package/dist/{chunk-PMRYC6SF.js.map → chunk-I7TMY7AS.js.map} +0 -0
  53. /package/dist/{chunk-27XY2HXV.js.map → chunk-MBWFTXF5.js.map} +0 -0
  54. /package/dist/{chunk-76DLC7CM.js.map → chunk-NKRMMFQG.js.map} +0 -0
  55. /package/dist/{client-VNSFNDF4.js.map → client-OPZ2ORWW.js.map} +0 -0
  56. /package/dist/{eas-PJ3Y4NDB.js.map → eas-32PEJETG.js.map} +0 -0
  57. /package/dist/{governor-4ASVLOCI.js.map → governor-GSCXEZWI.js.map} +0 -0
  58. /package/dist/{network-RI54LT2Y.js.map → network-HCFCNZUI.js.map} +0 -0
  59. /package/dist/{price-JX2LFKFW.js.map → price-OUL7WIXQ.js.map} +0 -0
  60. /package/dist/{providers-F6MNPMR4.js.map → providers-4HQHB7V5.js.map} +0 -0
  61. /package/dist/{research-5ZJTRILJ.js.map → research-2RWAMWWH.js.map} +0 -0
  62. /package/dist/{session-AXLPYJHX.js.map → session-SIOJZO6P.js.map} +0 -0
  63. /package/dist/{vault-AWQBFD4C.js.map → vault-VDADZFSV.js.map} +0 -0
  64. /package/dist/{xmtp-M74BRF3G.js.map → xmtp-2U7CSBXM.js.map} +0 -0
package/dist/index.js CHANGED
@@ -15,7 +15,7 @@ import {
15
15
  checkApiKeyValid,
16
16
  listModels,
17
17
  provisionApiKey
18
- } from "./chunk-6BVA4RIH.js";
18
+ } from "./chunk-CCNOXDZ7.js";
19
19
  import {
20
20
  approveDepositor,
21
21
  deposit,
@@ -38,8 +38,8 @@ import {
38
38
  removeDepositor,
39
39
  setAgentFeeBps,
40
40
  setVaultAddress
41
- } from "./chunk-MC5QEPW3.js";
42
- import "./chunk-76DLC7CM.js";
41
+ } from "./chunk-AOL2DJTK.js";
42
+ import "./chunk-NKRMMFQG.js";
43
43
  import {
44
44
  HYPERLIQUID_PERP_STRATEGY_ABI,
45
45
  applySlippage,
@@ -51,7 +51,7 @@ import {
51
51
  getMultiHopQuote,
52
52
  getQuote,
53
53
  resolveToken
54
- } from "./chunk-LZEV772I.js";
54
+ } from "./chunk-AJ46XIGY.js";
55
55
  import {
56
56
  createApproval,
57
57
  createJoinRequest,
@@ -62,20 +62,20 @@ import {
62
62
  queryJoinRequests,
63
63
  revokeJoinRequest,
64
64
  stripReferrerPrefix
65
- } from "./chunk-54CLRBPB.js";
65
+ } from "./chunk-M34JVPJO.js";
66
66
  import {
67
67
  createFund,
68
68
  getActiveFunds,
69
69
  getFund,
70
70
  subdomainExists,
71
71
  updateMetadata
72
- } from "./chunk-4KJUX5SS.js";
72
+ } from "./chunk-4WAEM2TC.js";
73
73
  import {
74
74
  resolveFund,
75
75
  resolveVaultFund,
76
76
  searchFundAcrossChains,
77
77
  setTextRecord
78
- } from "./chunk-27XY2HXV.js";
78
+ } from "./chunk-MBWFTXF5.js";
79
79
  import {
80
80
  PROPOSAL_STATE,
81
81
  PROPOSAL_STATES,
@@ -109,7 +109,7 @@ import {
109
109
  setVotingPeriod,
110
110
  settleProposal,
111
111
  vote
112
- } from "./chunk-Y6XOH23Y.js";
112
+ } from "./chunk-4GO7I33U.js";
113
113
  import {
114
114
  AERODROME,
115
115
  AGENT_REGISTRY,
@@ -119,7 +119,7 @@ import {
119
119
  TOKENS,
120
120
  UNISWAP,
121
121
  VENICE
122
- } from "./chunk-PMRYC6SF.js";
122
+ } from "./chunk-I7TMY7AS.js";
123
123
  import {
124
124
  GAS_UNITS,
125
125
  estimateGasCushion,
@@ -130,7 +130,7 @@ import {
130
130
  sendTxWithRetry,
131
131
  waitForReceipt,
132
132
  writeContractWithRetry
133
- } from "./chunk-EPQR6PJ4.js";
133
+ } from "./chunk-AQPTBVEA.js";
134
134
  import {
135
135
  DEFAULT_NETWORK,
136
136
  VALID_NETWORKS,
@@ -142,7 +142,7 @@ import {
142
142
  isTestnet,
143
143
  setNetwork,
144
144
  withNetwork
145
- } from "./chunk-3TLKNRZV.js";
145
+ } from "./chunk-ZW2VKCFZ.js";
146
146
  import {
147
147
  addFund,
148
148
  cacheGroupId,
@@ -189,9 +189,9 @@ import {
189
189
  import { config as loadDotenv } from "dotenv";
190
190
  import { createRequire } from "module";
191
191
  import { Command, Option } from "commander";
192
- import { parseUnits as parseUnits9, formatUnits as formatUnits7, isAddress as isAddress10 } from "viem";
193
- import chalk16 from "chalk";
194
- import ora9 from "ora";
192
+ import { parseUnits as parseUnits11, formatUnits as formatUnits10, isAddress as isAddress12 } from "viem";
193
+ import chalk18 from "chalk";
194
+ import ora10 from "ora";
195
195
  import { input, confirm, select } from "@inquirer/prompts";
196
196
 
197
197
  // src/lib/generated/contract-constants.ts
@@ -228,11 +228,9 @@ function parseBigIntArg(value, name) {
228
228
  }
229
229
 
230
230
  // src/commands/strategy-template.ts
231
- import { parseUnits as parseUnits2, formatUnits as formatUnits3, isAddress as isAddress3, erc20Abi, encodeAbiParameters as encodeAbiParameters3, decodeAbiParameters } from "viem";
232
- import chalk2 from "chalk";
233
- import ora2 from "ora";
234
- import { writeFileSync, mkdirSync } from "fs";
235
- import { resolve } from "path";
231
+ import { formatUnits as formatUnits6, isAddress as isAddress5, erc20Abi as erc20Abi3, encodeAbiParameters as encodeAbiParameters5, decodeAbiParameters as decodeAbiParameters3 } from "viem";
232
+ import chalk4 from "chalk";
233
+ import ora3 from "ora";
236
234
 
237
235
  // src/lib/clone.ts
238
236
  import { concat } from "viem";
@@ -290,13 +288,29 @@ var HYPERLIQUID_GRID_STRATEGY_ABI = [
290
288
  }
291
289
  ];
292
290
 
293
- // src/lib/batch.ts
294
- function formatBatch(calls) {
295
- return calls.map((call, i) => {
296
- const selector = call.data.slice(0, 10);
297
- return ` ${i + 1}. ${call.target} :: ${selector}... (${call.value > 0n ? call.value + " wei" : "no value"})`;
298
- }).join("\n");
299
- }
291
+ // src/commands/strategy-template-lib.ts
292
+ import { parseUnits as parseUnits2, formatUnits as formatUnits4, erc20Abi } from "viem";
293
+ import chalk2 from "chalk";
294
+
295
+ // src/lib/proposer-bond-error.ts
296
+ import { formatUnits } from "viem";
297
+ var InsufficientProposerBondWood = class extends Error {
298
+ constructor(requiredWood, balanceWood) {
299
+ const need = formatUnits(requiredWood, 18);
300
+ const have = formatUnits(balanceWood, 18);
301
+ super(
302
+ `InsufficientProposerBondWood: wallet holds ${have} WOOD but the quoted proposer bond is ${need} WOOD. The CLI can set WOOD allowance to ProposerBondEscrow, but the wallet must HOLD the WOOD. On the Robinhood mainnet fork, the faucet grant covers a 10k owner stake plus a small-book bond (example only: ~230 WOOD for a 100 USDG book at a then-current fork price \u2014 quote via ExposureLedger.proposerBondWood; the amount scales). This is a second WOOD pull at propose, not the owner stake.`
303
+ );
304
+ this.requiredWood = requiredWood;
305
+ this.balanceWood = balanceWood;
306
+ }
307
+ name = "InsufficientProposerBondWood";
308
+ };
309
+
310
+ // src/commands/guardian-delegate.ts
311
+ import chalk from "chalk";
312
+ import ora from "ora";
313
+ import { formatUnits as formatUnits3, isAddress as isAddress2, parseUnits } from "viem";
300
314
 
301
315
  // src/lib/calldata.ts
302
316
  var _calldataOnly = false;
@@ -310,11 +324,6 @@ function emitCalldata(action) {
310
324
  process.stdout.write(JSON.stringify(action, null, 2) + "\n");
311
325
  }
312
326
 
313
- // src/commands/guardian-delegate.ts
314
- import chalk from "chalk";
315
- import ora from "ora";
316
- import { formatUnits as formatUnits2, isAddress as isAddress2, parseUnits } from "viem";
317
-
318
327
  // ../sdk/dist/types.js
319
328
  var CHAIN_IDS = {
320
329
  BASE: 8453,
@@ -1349,7 +1358,7 @@ function encodeDeposit(args, chainId) {
1349
1358
  txs.push(encodeApproveTx(asset, vault, maxUint256, chainId));
1350
1359
  }
1351
1360
  txs.push(encodeDepositTx(vault, args.assets, receiver, chainId));
1352
- const minDecimal = formatUnits(args.assets, args.assetDecimals);
1361
+ const minDecimal = formatUnits2(args.assets, args.assetDecimals);
1353
1362
  let description;
1354
1363
  if (wrapped) {
1355
1364
  description = needsApprove ? `Wrap ETH\u2192WETH, approve ${args.assetSymbol} for ${vault}, then deposit ${minDecimal} ${args.assetSymbol}.` : `Wrap ETH\u2192WETH, then deposit ${minDecimal} ${args.assetSymbol}.`;
@@ -1380,7 +1389,7 @@ function encodeDeposit(args, chainId) {
1380
1389
  note: "Both txs are gated by vault state. If `redemptionsLocked()` is true the deposit reverts unless live NAV is available; check the vault read endpoint before broadcasting."
1381
1390
  };
1382
1391
  }
1383
- function formatUnits(value, decimals) {
1392
+ function formatUnits2(value, decimals) {
1384
1393
  if (decimals === 0)
1385
1394
  return value.toString();
1386
1395
  const negative = value < 0n;
@@ -2291,8 +2300,8 @@ function registerGuardianCommands(program2) {
2291
2300
  SEP();
2292
2301
  console.log(W(` Address: ${G(target)}`));
2293
2302
  console.log(W(` Active guardian: ${active ? G("yes") : DIM("no")}`));
2294
- console.log(W(` Own stake: ${BOLD(formatUnits2(stake, 18))} WOOD`));
2295
- console.log(W(` Delegated inbound: ${BOLD(formatUnits2(delegatedIn, 18))} WOOD`));
2303
+ console.log(W(` Own stake: ${BOLD(formatUnits3(stake, 18))} WOOD`));
2304
+ console.log(W(` Delegated inbound: ${BOLD(formatUnits3(delegatedIn, 18))} WOOD`));
2296
2305
  console.log(W(` Commission: ${BOLD(`${Number(commission) / 100}%`)}`));
2297
2306
  SEP();
2298
2307
  console.log();
@@ -2487,7 +2496,7 @@ function registerGuardianCommands(program2) {
2487
2496
  });
2488
2497
  }
2489
2498
 
2490
- // src/commands/strategy-template.ts
2499
+ // src/commands/strategy-template-lib.ts
2491
2500
  var ZERO = "0x0000000000000000000000000000000000000000";
2492
2501
  var TEMPLATES = [
2493
2502
  {
@@ -2645,206 +2654,115 @@ function capsForCalls(calls, strategy2, maxCapital) {
2645
2654
  return seen === 1 ? share + remainder : share;
2646
2655
  });
2647
2656
  }
2648
- async function ensureProposerBondAllowance(vault) {
2657
+ async function ensureProposerBondAllowance(vault, requiredCoverage, asset) {
2649
2658
  try {
2659
+ const publicClient = getPublicClient();
2650
2660
  const governor = await getGovernorOf(vault);
2651
- const escrow = await getPublicClient().readContract({
2661
+ const govViews = [
2662
+ {
2663
+ type: "function",
2664
+ name: "bondEscrow",
2665
+ inputs: [],
2666
+ outputs: [{ type: "address" }],
2667
+ stateMutability: "view"
2668
+ },
2669
+ {
2670
+ type: "function",
2671
+ name: "exposureLedger",
2672
+ inputs: [],
2673
+ outputs: [{ type: "address" }],
2674
+ stateMutability: "view"
2675
+ }
2676
+ ];
2677
+ const escrow = await publicClient.readContract({
2652
2678
  address: governor,
2653
- abi: [
2654
- {
2655
- type: "function",
2656
- name: "bondEscrow",
2657
- inputs: [],
2658
- outputs: [{ type: "address" }],
2659
- stateMutability: "view"
2660
- }
2661
- ],
2679
+ abi: govViews,
2662
2680
  functionName: "bondEscrow"
2663
2681
  });
2664
- if (!escrow || escrow === "0x0000000000000000000000000000000000000000") return;
2665
- console.log(chalk2.dim(` Proposer bond escrow: ${escrow} \u2014 ensuring WOOD allowance`));
2666
- await ensureWoodAllowance(2n ** 255n, escrow, "WOOD (proposer bond)");
2667
- } catch {
2668
- }
2669
- }
2670
- function registerStrategyTemplateCommands(strategy2) {
2671
- strategy2.command("list").description("List available strategy templates").action(() => {
2672
- const templates = STRATEGY_TEMPLATES();
2673
- const network = getNetwork();
2674
- console.log();
2675
- console.log(chalk2.bold("Strategy Templates"), chalk2.dim(`(${network})`));
2676
- console.log(chalk2.dim("\u2500".repeat(60)));
2677
- let availableCount = 0;
2678
- for (const t of TEMPLATES) {
2679
- const addr = templates[t.addressKey];
2680
- if (addr !== ZERO) {
2681
- availableCount++;
2682
- console.log();
2683
- console.log(` ${chalk2.bold(t.name)} (${chalk2.cyan(t.key)})`);
2684
- console.log(` ${t.description}`);
2685
- console.log(` Template: ${chalk2.green(addr)}`);
2686
- }
2687
- }
2688
- if (availableCount === 0) {
2689
- console.log();
2690
- console.log(chalk2.yellow(" No strategy templates deployed on this network."));
2691
- }
2692
- const unavailable2 = TEMPLATES.filter((t) => templates[t.addressKey] === ZERO);
2693
- if (unavailable2.length > 0) {
2694
- console.log();
2695
- console.log(chalk2.dim(` Not available on ${network}:`));
2696
- for (const t of unavailable2) {
2697
- console.log(chalk2.dim(` ${t.name} (${t.key})`));
2698
- }
2699
- }
2700
- console.log();
2701
- console.log(chalk2.dim("Clone a template: sherwood strategy clone <template> --vault <addr> ..."));
2702
- console.log(chalk2.dim("Full proposal: sherwood strategy propose <template> --vault <addr> ..."));
2703
- console.log();
2704
- });
2705
- strategy2.command("clone").description("Clone a strategy template and initialize it").argument("<template>", "Template: moonwell-supply, aerodrome-lp, venice-inference, wsteth-moonwell, mamo-yield, portfolio, hyperliquid-perp, hyperliquid-grid").requiredOption("--vault <address>", "Vault address").option("--amount <n>", "Asset amount to deploy").option("--min-redeem <n>", "Min asset on settlement (Moonwell)").option("--token <symbol>", "Asset token symbol (default: USDC)").option("--asset <symbol>", "Asset token (USDC, VVV, or address)").option("--agent <address>", "Agent wallet (Venice, default: your wallet)").option("--min-vvv <n>", "Min VVV from swap (Venice)").option("--single-hop", "Single-hop Aerodrome swap (Venice)").option("--token-a <address>", "Token A (Aerodrome)").option("--token-b <address>", "Token B (Aerodrome)").option("--amount-a <n>", "Token A amount (Aerodrome)").option("--amount-b <n>", "Token B amount (Aerodrome)").option("--stable", "Stable pool (Aerodrome)").option("--gauge <address>", "Gauge address (Aerodrome)").option("--lp-token <address>", "LP token address (Aerodrome)").option("--min-a-out <n>", "Min token A on settle (Aerodrome)").option("--min-b-out <n>", "Min token B on settle (Aerodrome)").option("--slippage <bps>", "Slippage tolerance in bps (wstETH, default: 500 = 5%)").option("--mamo-factory <address>", "Mamo StrategyFactory address (Mamo)").option("--tokens <list>", "Comma-separated token addresses or symbols (Portfolio)").option("--weights <list>", "Comma-separated weights in bps, must sum to 10000 (Portfolio)").option("--max-slippage <bps>", "Max slippage bps (Portfolio, default: 500)").option("--fee-tier <n>", "Pool fee tier (Portfolio, default: 3000)").option("--swap-adapter <address>", "Swap adapter address (Portfolio)").option("--feed-ids <list>", "Comma-separated Chainlink feed ids/addresses per token (Portfolio; auto-resolved from registry in push-feed mode)").option("--price-decimals <list>", "Comma-separated raw feed decimals per token (Portfolio; default 8 push / 18 Data Streams)").option("--swap-routes <list>", "Comma-separated per-token swap route spec (Portfolio). Per token: 'v3:<fee>' (mode 0), 'v4:<fee>:<tickSpacing>' (mode 2), or 'v4path:<hop>+<hop>...' (mode 3) where hop='<currency>@<fee>:<tickSpacing>', currency='eth'/'native'=ETH or 'self'=this token or an address. Empty entry = auto-detect / robinhood default.").option(
2706
- "--max-drawdown-bps <bps>",
2707
- "Declared loss allowance for this proposal, in bps of --amount (0-10000, default 2000 = 20%). This is the envelope voters and guardians are asked to accept, and the basis the settle-price guard sizes its tolerance from \u2014 not a formality."
2708
- ).option("--max-price-ages <list>", "Comma-separated per-token max Chainlink push-feed staleness in seconds (Portfolio, push mode; robinhood-mainnet equity feeds default to 345600 = 96h, crypto/stable feeds to the contract default). Empty entry = registry default.").option("--leverage <number>", "Leverage multiplier (Hyperliquid Perp, default: 10)").option("--asset-index <number>", "Perp asset index (Hyperliquid Perp, default: 0 for BTC)").option("--max-position <amount>", "Max position size in USD (Hyperliquid Perp, default: 100000)").option("--max-trades-per-day <n>", "Max trades per day (Hyperliquid Perp, default: 50)").option("--max-order-size <amount>", "Max single-order size in asset units (Hyperliquid Grid, default: 10000)").option("--max-orders-per-tick <n>", "Max orders per tick (Hyperliquid Grid, default: 20)").option("--asset-indices <list>", "Comma-separated perp asset indices (Hyperliquid Grid, default: 0)").action(async (templateKey, opts) => {
2709
- const vault = opts.vault;
2710
- if (!isAddress3(vault)) {
2711
- console.error(chalk2.red("Invalid vault address"));
2712
- process.exit(1);
2713
- }
2714
- const { def, address: templateAddr } = resolveTemplate(templateKey);
2715
- const cloneSpinner = ora2(`Cloning ${def.name} template...`).start();
2716
- let clone;
2717
- let cloneHash;
2682
+ if (!escrow || escrow === ZERO) return;
2683
+ let quotedBond = 0n;
2718
2684
  try {
2719
- const result = await cloneTemplate(templateAddr);
2720
- clone = result.clone;
2721
- cloneHash = result.hash;
2722
- cloneSpinner.succeed(`Cloned: ${chalk2.green(clone)}`);
2723
- console.log(chalk2.dim(` Tx: ${getExplorerUrl(cloneHash)}`));
2724
- } catch (err) {
2725
- cloneSpinner.fail("Clone failed");
2726
- console.error(chalk2.red(formatContractError(err)));
2727
- process.exit(1);
2728
- }
2729
- const initSpinner = ora2("Initializing strategy...").start();
2730
- try {
2731
- const { initData } = await resolveAndBuildInitData(templateKey, opts, vault);
2732
- const account = getAccount();
2733
- const initHash = await writeContractWithRetry({
2734
- account,
2735
- chain: getChain(),
2736
- address: clone,
2737
- abi: BASE_STRATEGY_ABI,
2738
- functionName: "initialize",
2739
- args: [vault, account.address, initData]
2685
+ const ledger = await publicClient.readContract({
2686
+ address: governor,
2687
+ abi: govViews,
2688
+ functionName: "exposureLedger"
2740
2689
  });
2741
- const receipt = await waitForReceipt(initHash);
2742
- if (receipt.status === "reverted") {
2743
- throw new Error("Initialize transaction reverted on-chain");
2744
- }
2745
- initSpinner.succeed("Initialized");
2746
- } catch (err) {
2747
- initSpinner.fail("Initialize failed");
2748
- console.error(chalk2.red(formatContractError(err)));
2749
- process.exit(1);
2750
- }
2751
- if (templateKey === "hyperliquid-grid" || templateKey === "hyperliquid-perp") {
2752
- const hcSpinner = ora2("Registering clone with HyperCore...").start();
2753
- try {
2754
- const account = getAccount();
2755
- const hcHash = await writeContractWithRetry({
2756
- account,
2757
- chain: getChain(),
2758
- address: clone,
2759
- abi: templateKey === "hyperliquid-grid" ? HYPERLIQUID_GRID_STRATEGY_ABI : HYPERLIQUID_PERP_STRATEGY_ABI,
2760
- functionName: "finalizeForHyperCore",
2761
- args: [0n, 1, 0n]
2762
- // token=USDC, variant=FirstStorageSlot(1), nonce unused
2690
+ if (ledger && ledger !== ZERO && requiredCoverage > 0n) {
2691
+ quotedBond = await publicClient.readContract({
2692
+ address: ledger,
2693
+ abi: [
2694
+ {
2695
+ type: "function",
2696
+ name: "proposerBondWood",
2697
+ inputs: [
2698
+ { name: "asset", type: "address" },
2699
+ { name: "requiredCoverage", type: "uint256" }
2700
+ ],
2701
+ outputs: [{ type: "uint256" }],
2702
+ stateMutability: "view"
2703
+ }
2704
+ ],
2705
+ functionName: "proposerBondWood",
2706
+ args: [asset, requiredCoverage]
2763
2707
  });
2764
- await waitForReceipt(hcHash);
2765
- hcSpinner.succeed("HyperCore registration sent (active after next block)");
2766
- } catch (err) {
2767
- hcSpinner.warn("HyperCore registration failed \u2014 run finalizeForHyperCore manually");
2768
- console.error(chalk2.yellow(formatContractError(err)));
2769
2708
  }
2709
+ } catch {
2770
2710
  }
2771
- console.log();
2772
- console.log(chalk2.bold("Strategy clone ready:"), chalk2.green(clone));
2773
- console.log(chalk2.dim("Use this address in your proposal batch calls."));
2774
- console.log();
2775
- });
2776
- strategy2.command("init").description("Initialize an already-deployed but uninitialized strategy clone").argument("<template>", "Template: moonwell-supply, aerodrome-lp, venice-inference, wsteth-moonwell, mamo-yield, portfolio, hyperliquid-perp, hyperliquid-grid").requiredOption("--clone <address>", "Clone address to initialize").requiredOption("--vault <address>", "Vault address").option("--amount <n>", "Asset amount to deploy").option("--min-redeem <n>", "Min asset on settlement (Moonwell)").option("--token <symbol>", "Asset token symbol (default: USDC)").option("--asset <symbol>", "Asset token (USDC, VVV, or address)").option("--agent <address>", "Agent wallet (Venice, default: your wallet)").option("--min-vvv <n>", "Min VVV from swap (Venice)").option("--single-hop", "Single-hop Aerodrome swap (Venice)").option("--token-a <address>", "Token A (Aerodrome)").option("--token-b <address>", "Token B (Aerodrome)").option("--amount-a <n>", "Token A amount (Aerodrome)").option("--amount-b <n>", "Token B amount (Aerodrome)").option("--stable", "Stable pool (Aerodrome)").option("--gauge <address>", "Gauge address (Aerodrome)").option("--lp-token <address>", "LP token address (Aerodrome)").option("--min-a-out <n>", "Min token A on settle (Aerodrome)").option("--min-b-out <n>", "Min token B on settle (Aerodrome)").option("--slippage <bps>", "Slippage tolerance in bps (wstETH, default: 500 = 5%)").option("--mamo-factory <address>", "Mamo StrategyFactory address (Mamo)").option("--tokens <list>", "Comma-separated token addresses or symbols (Portfolio)").option("--weights <list>", "Comma-separated weights in bps, must sum to 10000 (Portfolio)").option("--max-slippage <bps>", "Max slippage bps (Portfolio, default: 500)").option("--fee-tier <n>", "Pool fee tier (Portfolio, default: 3000)").option("--swap-adapter <address>", "Swap adapter address (Portfolio)").option("--feed-ids <list>", "Comma-separated Chainlink feed ids/addresses per token (Portfolio; auto-resolved from registry in push-feed mode)").option("--price-decimals <list>", "Comma-separated raw feed decimals per token (Portfolio; default 8 push / 18 Data Streams)").option("--swap-routes <list>", "Comma-separated per-token swap route spec (Portfolio). Per token: 'v3:<fee>' (mode 0), 'v4:<fee>:<tickSpacing>' (mode 2), or 'v4path:<hop>+<hop>...' (mode 3) where hop='<currency>@<fee>:<tickSpacing>', currency='eth'/'native'=ETH or 'self'=this token or an address. Empty entry = auto-detect / robinhood default.").option(
2777
- "--max-drawdown-bps <bps>",
2778
- "Declared loss allowance for this proposal, in bps of --amount (0-10000, default 2000 = 20%). This is the envelope voters and guardians are asked to accept, and the basis the settle-price guard sizes its tolerance from \u2014 not a formality."
2779
- ).option("--max-price-ages <list>", "Comma-separated per-token max Chainlink push-feed staleness in seconds (Portfolio, push mode; robinhood-mainnet equity feeds default to 345600 = 96h, crypto/stable feeds to the contract default). Empty entry = registry default.").option("--leverage <number>", "Leverage multiplier (Hyperliquid Perp, default: 10)").option("--asset-index <number>", "Perp asset index (Hyperliquid Perp, default: 0 for BTC)").option("--max-position <amount>", "Max position size in USD (Hyperliquid Perp, default: 100000)").option("--max-trades-per-day <n>", "Max trades per day (Hyperliquid Perp, default: 50)").option("--max-order-size <amount>", "Max single-order size in asset units (Hyperliquid Grid, default: 10000)").option("--max-orders-per-tick <n>", "Max orders per tick (Hyperliquid Grid, default: 20)").option("--asset-indices <list>", "Comma-separated perp asset indices (Hyperliquid Grid, default: 0)").action(async (templateKey, opts) => {
2780
- const clone = opts.clone;
2781
- const vault = opts.vault;
2782
- if (!isAddress3(clone)) {
2783
- console.error(chalk2.red("Invalid clone address"));
2784
- process.exit(1);
2785
- }
2786
- if (!isAddress3(vault)) {
2787
- console.error(chalk2.red("Invalid vault address"));
2788
- process.exit(1);
2789
- }
2790
- resolveTemplate(templateKey);
2791
- const publicClient = getPublicClient();
2792
- const currentVault = await publicClient.readContract({
2793
- address: clone,
2794
- abi: BASE_STRATEGY_ABI,
2795
- functionName: "vault"
2796
- });
2797
- if (currentVault !== "0x0000000000000000000000000000000000000000") {
2798
- console.error(chalk2.red(`Clone already initialized (vault: ${currentVault})`));
2799
- process.exit(1);
2800
- }
2801
- const initSpinner = ora2("Initializing strategy clone...").start();
2802
- try {
2803
- const { initData } = await resolveAndBuildInitData(templateKey, opts, vault);
2804
- const account = getAccount();
2805
- const initHash = await writeContractWithRetry({
2806
- account,
2807
- chain: getChain(),
2808
- address: clone,
2809
- abi: BASE_STRATEGY_ABI,
2810
- functionName: "initialize",
2811
- args: [vault, account.address, initData]
2711
+ console.log(
2712
+ chalk2.dim(
2713
+ ` Quoted proposer bond: ${formatUnits4(quotedBond, 18)} WOOD (via ExposureLedger.proposerBondWood; ~1% of extractable value at default proposerBondBps, WOOD-denominated and price-dependent \u2014 not a fixed WOOD amount)`
2714
+ )
2715
+ );
2716
+ console.log(chalk2.dim(` Proposer bond escrow: ${escrow} \u2014 ensuring WOOD allowance`));
2717
+ if (quotedBond > 0n) {
2718
+ const wood2 = SHERWOOD().WOOD_TOKEN;
2719
+ const holder = getAccount().address;
2720
+ const balance = await publicClient.readContract({
2721
+ address: wood2,
2722
+ abi: erc20Abi,
2723
+ functionName: "balanceOf",
2724
+ args: [holder]
2812
2725
  });
2813
- const receipt = await waitForReceipt(initHash);
2814
- if (receipt.status === "reverted") {
2815
- throw new Error("Initialize transaction reverted on-chain");
2726
+ if (balance < quotedBond) {
2727
+ throw new InsufficientProposerBondWood(quotedBond, balance);
2816
2728
  }
2817
- initSpinner.succeed("Initialized");
2818
- console.log(chalk2.dim(` Tx: ${getExplorerUrl(initHash)}`));
2819
- } catch (err) {
2820
- initSpinner.fail("Initialize failed");
2821
- console.error(chalk2.red(formatContractError(err)));
2822
- process.exit(1);
2823
2729
  }
2824
- const verifiedVault = await publicClient.readContract({
2825
- address: clone,
2826
- abi: BASE_STRATEGY_ABI,
2827
- functionName: "vault"
2828
- });
2829
- console.log();
2830
- console.log(chalk2.bold("Clone initialized:"), chalk2.green(clone));
2831
- console.log(` Vault: ${chalk2.green(verifiedVault)}`);
2832
- console.log(` Proposer: ${chalk2.green(getAccount().address)}`);
2833
- console.log();
2834
- });
2730
+ await ensureWoodAllowance(2n ** 255n, escrow, "WOOD (proposer bond)");
2731
+ } catch (err) {
2732
+ if (err instanceof InsufficientProposerBondWood) throw err;
2733
+ }
2734
+ }
2735
+
2736
+ // src/commands/strategy-propose.ts
2737
+ import { formatUnits as formatUnits5, isAddress as isAddress4, erc20Abi as erc20Abi2 } from "viem";
2738
+ import chalk3 from "chalk";
2739
+ import ora2 from "ora";
2740
+ import { writeFileSync, mkdirSync } from "fs";
2741
+ import { resolve } from "path";
2742
+
2743
+ // src/lib/batch.ts
2744
+ function formatBatch(calls) {
2745
+ return calls.map((call, i) => {
2746
+ const selector = call.data.slice(0, 10);
2747
+ return ` ${i + 1}. ${call.target} :: ${selector}... (${call.value > 0n ? call.value + " wei" : "no value"})`;
2748
+ }).join("\n");
2749
+ }
2750
+
2751
+ // src/commands/strategy-propose.ts
2752
+ function registerStrategyProposeCommands(strategy2) {
2835
2753
  strategy2.command("propose").description("Clone + init + build calls + submit governance proposal (all-in-one)").argument("<template>", "Template: moonwell-supply, aerodrome-lp, venice-inference, wsteth-moonwell, mamo-yield, portfolio, hyperliquid-perp, hyperliquid-grid").requiredOption("--vault <address>", "Vault address").option("--write-calls <dir>", "Write execute/settle JSON to directory (skip proposal submission)").option("--name <name>", "Proposal name").option("--description <text>", "Proposal description").option("--duration <duration>", "Strategy duration (7d, 24h, etc.)").option("--proposer <address>", "Proposer/agent address (required for --calldata-only \u2014 the external signer)").option("--metadata-uri <uri>", "Metadata URI (required for --calldata-only \u2014 IPFS pin needs a signer)").option("--salt <bytes32>", "CREATE2 salt for the deterministic clone (--calldata-only; default: derived from inputs)").option("--amount <n>", "Asset amount to deploy").option("--min-redeem <n>", "Min asset on settlement (Moonwell)").option("--token <symbol>", "Asset token symbol (default: USDC)").option("--asset <symbol>", "Asset token (USDC, VVV, or address)").option("--agent <address>", "Agent wallet (Venice, default: your wallet)").option("--min-vvv <n>", "Min VVV from swap (Venice)").option("--single-hop", "Single-hop Aerodrome swap (Venice)").option("--token-a <address>", "Token A (Aerodrome)").option("--token-b <address>", "Token B (Aerodrome)").option("--amount-a <n>", "Token A amount (Aerodrome)").option("--amount-b <n>", "Token B amount (Aerodrome)").option("--stable", "Stable pool (Aerodrome)").option("--gauge <address>", "Gauge address (Aerodrome)").option("--lp-token <address>", "LP token address (Aerodrome)").option("--min-a-out <n>", "Min token A on settle (Aerodrome)").option("--min-b-out <n>", "Min token B on settle (Aerodrome)").option("--slippage <bps>", "Slippage tolerance in bps (wstETH, default: 500 = 5%)").option("--mamo-factory <address>", "Mamo StrategyFactory address (Mamo)").option("--tokens <list>", "Comma-separated token addresses or symbols (Portfolio)").option("--weights <list>", "Comma-separated weights in bps, must sum to 10000 (Portfolio)").option("--max-slippage <bps>", "Max slippage bps (Portfolio, default: 500)").option("--fee-tier <n>", "Pool fee tier (Portfolio, default: 3000)").option("--swap-adapter <address>", "Swap adapter address (Portfolio)").option("--feed-ids <list>", "Comma-separated Chainlink feed ids/addresses per token (Portfolio; auto-resolved from registry in push-feed mode)").option("--price-decimals <list>", "Comma-separated raw feed decimals per token (Portfolio; default 8 push / 18 Data Streams)").option("--swap-routes <list>", "Comma-separated per-token swap route spec (Portfolio). Per token: 'v3:<fee>' (mode 0), 'v4:<fee>:<tickSpacing>' (mode 2), or 'v4path:<hop>+<hop>...' (mode 3) where hop='<currency>@<fee>:<tickSpacing>', currency='eth'/'native'=ETH or 'self'=this token or an address. Empty entry = auto-detect / robinhood default.").option(
2836
2754
  "--max-drawdown-bps <bps>",
2837
2755
  "Declared loss allowance for this proposal, in bps of --amount (0-10000, default 2000 = 20%). This is the envelope voters and guardians are asked to accept, and the basis the settle-price guard sizes its tolerance from \u2014 not a formality."
2838
2756
  ).option("--max-price-ages <list>", "Comma-separated per-token max Chainlink push-feed staleness in seconds (Portfolio, push mode; robinhood-mainnet equity feeds default to 345600 = 96h, crypto/stable feeds to the contract default). Empty entry = registry default.").option("--leverage <number>", "Leverage multiplier (Hyperliquid Perp, default: 10)").option("--asset-index <number>", "Perp asset index (Hyperliquid Perp, default: 0 for BTC)").option("--max-position <amount>", "Max position size in USD (Hyperliquid Perp, default: 100000)").option("--max-trades-per-day <n>", "Max trades per day (Hyperliquid Perp, default: 50)").option("--max-order-size <amount>", "Max single-order size in asset units (Hyperliquid Grid, default: 10000)").option("--max-orders-per-tick <n>", "Max orders per tick (Hyperliquid Grid, default: 20)").option("--asset-indices <list>", "Comma-separated perp asset indices (Hyperliquid Grid, default: 0)").action(async (templateKey, opts) => {
2839
2757
  const vault = opts.vault;
2840
- if (!isAddress3(vault)) {
2841
- console.error(chalk2.red("Invalid vault address"));
2758
+ if (!isAddress4(vault)) {
2759
+ console.error(chalk3.red("Invalid vault address"));
2842
2760
  process.exit(1);
2843
2761
  }
2844
2762
  const { def, address: templateAddr } = resolveTemplate(templateKey);
2845
2763
  const maxDrawdownBps = opts.maxDrawdownBps === void 0 ? 2e3 : Number(opts.maxDrawdownBps);
2846
2764
  if (!Number.isInteger(maxDrawdownBps) || maxDrawdownBps < 0 || maxDrawdownBps > 1e4) {
2847
- console.error(chalk2.red(` --max-drawdown-bps must be an integer 0-10000 (got ${opts.maxDrawdownBps})`));
2765
+ console.error(chalk3.red(` --max-drawdown-bps must be an integer 0-10000 (got ${opts.maxDrawdownBps})`));
2848
2766
  process.exit(1);
2849
2767
  }
2850
2768
  if (isCalldataOnly()) {
@@ -2853,12 +2771,12 @@ function registerStrategyTemplateCommands(strategy2) {
2853
2771
  if (!opts.metadataUri) missing.push("--metadata-uri <uri> (IPFS pin needs a signer)");
2854
2772
  if (!opts.duration) missing.push("--duration <d>");
2855
2773
  if (missing.length > 0) {
2856
- console.error(chalk2.red(`--calldata-only requires: ${missing.join(", ")}`));
2774
+ console.error(chalk3.red(`--calldata-only requires: ${missing.join(", ")}`));
2857
2775
  process.exit(1);
2858
2776
  }
2859
2777
  const proposer = opts.proposer;
2860
- if (!isAddress3(proposer)) {
2861
- console.error(chalk2.red("Invalid --proposer address"));
2778
+ if (!isAddress4(proposer)) {
2779
+ console.error(chalk3.red("Invalid --proposer address"));
2862
2780
  process.exit(1);
2863
2781
  }
2864
2782
  try {
@@ -2878,15 +2796,15 @@ function registerStrategyTemplateCommands(strategy2) {
2878
2796
  ]);
2879
2797
  if (!isRegistered) {
2880
2798
  console.error(
2881
- chalk2.red(
2799
+ chalk3.red(
2882
2800
  `--proposer ${proposer} is not a registered agent on ${vault}; cloneAndInitDeterministic and propose will both revert.`
2883
2801
  )
2884
2802
  );
2885
- console.error(chalk2.yellow(` Register first: sherwood fund approve --wallet ${proposer}`));
2803
+ console.error(chalk3.yellow(` Register first: sherwood fund approve --wallet ${proposer}`));
2886
2804
  process.exit(1);
2887
2805
  }
2888
2806
  if (paused) {
2889
- console.error(chalk2.red(`Vault ${vault} is paused \u2014 the proposal would revert.`));
2807
+ console.error(chalk3.red(`Vault ${vault} is paused \u2014 the proposal would revert.`));
2890
2808
  process.exit(1);
2891
2809
  }
2892
2810
  for (const check of computeProposalAssetChecks(templateKey, opts)) {
@@ -2894,32 +2812,32 @@ function registerStrategyTemplateCommands(strategy2) {
2894
2812
  const [balance, decimals] = await Promise.all([
2895
2813
  publicClient.readContract({
2896
2814
  address: check.asset,
2897
- abi: erc20Abi,
2815
+ abi: erc20Abi2,
2898
2816
  functionName: "balanceOf",
2899
2817
  args: [vault]
2900
2818
  }),
2901
2819
  publicClient.readContract({
2902
2820
  address: check.asset,
2903
- abi: erc20Abi,
2821
+ abi: erc20Abi2,
2904
2822
  functionName: "decimals"
2905
2823
  })
2906
2824
  ]);
2907
2825
  if (balance < check.amount) {
2908
2826
  console.error(
2909
- chalk2.red(
2910
- `Vault ${vault} holds ${formatUnits3(balance, decimals)} ${check.label} but the proposal needs ${formatUnits3(check.amount, decimals)} ${check.label}.`
2827
+ chalk3.red(
2828
+ `Vault ${vault} holds ${formatUnits5(balance, decimals)} ${check.label} but the proposal needs ${formatUnits5(check.amount, decimals)} ${check.label}.`
2911
2829
  )
2912
2830
  );
2913
- console.error(chalk2.yellow(` Hint: --amount is in human units (e.g. "10" = 10 ${check.label}), not raw decimals.`));
2831
+ console.error(chalk3.yellow(` Hint: --amount is in human units (e.g. "10" = 10 ${check.label}), not raw decimals.`));
2914
2832
  process.exit(1);
2915
2833
  }
2916
2834
  }
2917
2835
  } catch (err) {
2918
- console.error(chalk2.red(`Preflight read failed: ${err instanceof Error ? err.message : String(err)}`));
2836
+ console.error(chalk3.red(`Preflight read failed: ${err instanceof Error ? err.message : String(err)}`));
2919
2837
  process.exit(1);
2920
2838
  }
2921
2839
  if (!opts.agent) opts.agent = proposer;
2922
- const { parseDuration: parseDuration3, getGovernorOf: getGovernorOf2 } = await import("./governor-4ASVLOCI.js");
2840
+ const { parseDuration: parseDuration3, getGovernorOf: getGovernorOf2 } = await import("./governor-GSCXEZWI.js");
2923
2841
  const strategyDuration2 = parseDuration3(opts.duration);
2924
2842
  const chainId = getChain().id;
2925
2843
  try {
@@ -2970,7 +2888,7 @@ function registerStrategyTemplateCommands(strategy2) {
2970
2888
  note: "Broadcast SEQUENTIALLY: send tx 1 (cloneAndInitDeterministic) and WAIT for it to confirm, then send tx 2 (propose). If tx 1 reverts \u2014 proposer not a registered agent, proposer != tx-1 signer, template not allowlisted, or vault unregistered \u2014 do NOT send tx 2: it would create a proposal referencing an undeployed strategy. Send tx 1 from the --proposer wallet (the factory requires proposer == msg.sender, and msg.sender must be a vault owner/agent). The clone address is pinned by (factory, template, vault, salt) and is already baked into tx 2 + the execute/settle calls. The factory binds the salt to the vault and only the vault's owner/agents may deploy there, so the predicted address can't be front-run."
2971
2889
  });
2972
2890
  } catch (err) {
2973
- console.error(chalk2.red(err instanceof Error ? err.message : String(err)));
2891
+ console.error(chalk3.red(err instanceof Error ? err.message : String(err)));
2974
2892
  process.exit(1);
2975
2893
  }
2976
2894
  return;
@@ -2988,7 +2906,7 @@ function registerStrategyTemplateCommands(strategy2) {
2988
2906
  if (!isRegistered) {
2989
2907
  preflightSpinner.fail("Preflight failed");
2990
2908
  console.error(
2991
- chalk2.red(
2909
+ chalk3.red(
2992
2910
  ` Signer ${account.address} is not a registered agent on ${vault}.
2993
2911
  Register first via: sherwood fund approve --wallet ${account.address}`
2994
2912
  )
@@ -3002,7 +2920,7 @@ function registerStrategyTemplateCommands(strategy2) {
3002
2920
  });
3003
2921
  if (paused) {
3004
2922
  preflightSpinner.fail("Preflight failed");
3005
- console.error(chalk2.red(` Vault ${vault} is paused. Cannot propose.`));
2923
+ console.error(chalk3.red(` Vault ${vault} is paused. Cannot propose.`));
3006
2924
  process.exit(1);
3007
2925
  }
3008
2926
  const checks = computeProposalAssetChecks(templateKey, opts);
@@ -3011,25 +2929,25 @@ function registerStrategyTemplateCommands(strategy2) {
3011
2929
  const [balance, decimals] = await Promise.all([
3012
2930
  publicClient.readContract({
3013
2931
  address: check.asset,
3014
- abi: erc20Abi,
2932
+ abi: erc20Abi2,
3015
2933
  functionName: "balanceOf",
3016
2934
  args: [vault]
3017
2935
  }),
3018
2936
  publicClient.readContract({
3019
2937
  address: check.asset,
3020
- abi: erc20Abi,
2938
+ abi: erc20Abi2,
3021
2939
  functionName: "decimals"
3022
2940
  })
3023
2941
  ]);
3024
2942
  if (balance < check.amount) {
3025
2943
  preflightSpinner.fail("Preflight failed");
3026
2944
  console.error(
3027
- chalk2.red(
3028
- ` Vault ${vault} holds ${formatUnits3(balance, decimals)} ${check.label} but proposal requires ${formatUnits3(check.amount, decimals)} ${check.label}.`
2945
+ chalk3.red(
2946
+ ` Vault ${vault} holds ${formatUnits5(balance, decimals)} ${check.label} but proposal requires ${formatUnits5(check.amount, decimals)} ${check.label}.`
3029
2947
  )
3030
2948
  );
3031
2949
  console.error(
3032
- chalk2.yellow(
2950
+ chalk3.yellow(
3033
2951
  ` Hint: --amount is in human units (e.g. "10" = 10 ${check.label}), not raw decimals.`
3034
2952
  )
3035
2953
  );
@@ -3039,7 +2957,7 @@ function registerStrategyTemplateCommands(strategy2) {
3039
2957
  preflightSpinner.succeed("Preflight OK");
3040
2958
  } catch (err) {
3041
2959
  preflightSpinner.fail("Preflight failed");
3042
- console.error(chalk2.red(formatContractError(err)));
2960
+ console.error(chalk3.red(formatContractError(err)));
3043
2961
  process.exit(1);
3044
2962
  }
3045
2963
  const cloneSpinner = ora2(`Cloning ${def.name} template...`).start();
@@ -3047,11 +2965,11 @@ function registerStrategyTemplateCommands(strategy2) {
3047
2965
  try {
3048
2966
  const result = await cloneTemplate(templateAddr);
3049
2967
  clone = result.clone;
3050
- cloneSpinner.succeed(`Cloned: ${chalk2.green(clone)}`);
3051
- console.log(chalk2.dim(` Tx: ${getExplorerUrl(result.hash)}`));
2968
+ cloneSpinner.succeed(`Cloned: ${chalk3.green(clone)}`);
2969
+ console.log(chalk3.dim(` Tx: ${getExplorerUrl(result.hash)}`));
3052
2970
  } catch (err) {
3053
2971
  cloneSpinner.fail("Clone failed");
3054
- console.error(chalk2.red(formatContractError(err)));
2972
+ console.error(chalk3.red(formatContractError(err)));
3055
2973
  process.exit(1);
3056
2974
  }
3057
2975
  const initSpinner = ora2("Initializing strategy...").start();
@@ -3078,7 +2996,7 @@ function registerStrategyTemplateCommands(strategy2) {
3078
2996
  initSpinner.succeed("Initialized");
3079
2997
  } catch (err) {
3080
2998
  initSpinner.fail("Initialize failed");
3081
- console.error(chalk2.red(formatContractError(err)));
2999
+ console.error(chalk3.red(formatContractError(err)));
3082
3000
  process.exit(1);
3083
3001
  }
3084
3002
  if (templateKey === "hyperliquid-grid" || templateKey === "hyperliquid-perp") {
@@ -3097,9 +3015,9 @@ function registerStrategyTemplateCommands(strategy2) {
3097
3015
  hcSpinner.succeed("HyperCore registration sent (active after next block)");
3098
3016
  } catch (err) {
3099
3017
  hcSpinner.fail("HyperCore registration failed \u2014 aborting proposal submission");
3100
- console.error(chalk2.red(formatContractError(err)));
3018
+ console.error(chalk3.red(formatContractError(err)));
3101
3019
  console.error(
3102
- chalk2.yellow(
3020
+ chalk3.yellow(
3103
3021
  `Retry by calling finalizeForHyperCore(0, 1, 0) on ${clone}, then re-run propose.`
3104
3022
  )
3105
3023
  );
@@ -3114,9 +3032,9 @@ function registerStrategyTemplateCommands(strategy2) {
3114
3032
  extraApprovals
3115
3033
  );
3116
3034
  console.log();
3117
- console.log(chalk2.bold(`Execute calls (${executeCalls.length}):`));
3035
+ console.log(chalk3.bold(`Execute calls (${executeCalls.length}):`));
3118
3036
  console.log(formatBatch(executeCalls));
3119
- console.log(chalk2.bold(`Settle calls (${settleCalls.length}):`));
3037
+ console.log(chalk3.bold(`Settle calls (${settleCalls.length}):`));
3120
3038
  console.log(formatBatch(settleCalls));
3121
3039
  if (opts.writeCalls) {
3122
3040
  const dir = resolve(opts.writeCalls);
@@ -3126,33 +3044,33 @@ function registerStrategyTemplateCommands(strategy2) {
3126
3044
  writeFileSync(execPath, serializeCalls(executeCalls));
3127
3045
  writeFileSync(settlePath, serializeCalls(settleCalls));
3128
3046
  console.log();
3129
- console.log(chalk2.green(`Execute calls: ${execPath}`));
3130
- console.log(chalk2.green(`Settle calls: ${settlePath}`));
3131
- console.log(chalk2.green(`Clone address: ${clone}`));
3047
+ console.log(chalk3.green(`Execute calls: ${execPath}`));
3048
+ console.log(chalk3.green(`Settle calls: ${settlePath}`));
3049
+ console.log(chalk3.green(`Clone address: ${clone}`));
3132
3050
  console.log();
3133
- console.log(chalk2.dim("Submit with:"));
3134
- console.log(chalk2.dim(` sherwood proposal create \\`));
3135
- console.log(chalk2.dim(` --vault ${vault} \\`));
3136
- console.log(chalk2.dim(` --name "..." --description "..." \\`));
3137
- console.log(chalk2.dim(` --duration 7d \\`));
3138
- console.log(chalk2.dim(` --execute-calls ${execPath} \\`));
3139
- console.log(chalk2.dim(` --settle-calls ${settlePath}`));
3051
+ console.log(chalk3.dim("Submit with:"));
3052
+ console.log(chalk3.dim(` sherwood proposal create \\`));
3053
+ console.log(chalk3.dim(` --vault ${vault} \\`));
3054
+ console.log(chalk3.dim(` --name "..." --description "..." \\`));
3055
+ console.log(chalk3.dim(` --duration 7d \\`));
3056
+ console.log(chalk3.dim(` --execute-calls ${execPath} \\`));
3057
+ console.log(chalk3.dim(` --settle-calls ${settlePath}`));
3140
3058
  if (templateKey === "venice-inference") {
3141
3059
  console.log();
3142
- console.log(chalk2.yellow("Reminder: before settlement, agent must approve repayment:"));
3143
- console.log(chalk2.yellow(` asset.approve(${clone}, <repaymentAmount>)`));
3144
- console.log(chalk2.yellow(" Agent can update repayment via strategy.updateParams(newRepayment, 0, 0)"));
3060
+ console.log(chalk3.yellow("Reminder: before settlement, agent must approve repayment:"));
3061
+ console.log(chalk3.yellow(` asset.approve(${clone}, <repaymentAmount>)`));
3062
+ console.log(chalk3.yellow(" Agent can update repayment via strategy.updateParams(newRepayment, 0, 0)"));
3145
3063
  }
3146
3064
  console.log();
3147
3065
  return;
3148
3066
  }
3149
3067
  if (!opts.name || !opts.duration) {
3150
- console.error(chalk2.red("Missing --name or --duration. Use --write-calls to skip proposal submission."));
3068
+ console.error(chalk3.red("Missing --name or --duration. Use --write-calls to skip proposal submission."));
3151
3069
  process.exit(1);
3152
3070
  }
3153
- const { propose: propose2 } = await import("./governor-4ASVLOCI.js");
3071
+ const { propose: propose2 } = await import("./governor-GSCXEZWI.js");
3154
3072
  const { pinJSON } = await import("./ipfs-EJ7IHXCU.js");
3155
- const { parseDuration: parseDuration2 } = await import("./governor-4ASVLOCI.js");
3073
+ const { parseDuration: parseDuration2 } = await import("./governor-GSCXEZWI.js");
3156
3074
  const strategyDuration = parseDuration2(opts.duration);
3157
3075
  const metaSpinner = ora2("Pinning metadata to IPFS...").start();
3158
3076
  let metadataURI;
@@ -3184,16 +3102,24 @@ function registerStrategyTemplateCommands(strategy2) {
3184
3102
  metadataURI = `data:application/json;base64,${Buffer.from(inline).toString("base64")}`;
3185
3103
  }
3186
3104
  try {
3187
- const { getAgentFeeBps: getAgentFeeBps2 } = await import("./vault-AWQBFD4C.js");
3105
+ const { getAgentFeeBps: getAgentFeeBps2 } = await import("./vault-VDADZFSV.js");
3188
3106
  const feeBps = await getAgentFeeBps2(vault);
3189
3107
  console.log(
3190
- chalk2.yellow(
3108
+ chalk3.yellow(
3191
3109
  ` Agent fee for this proposal: ${Number(feeBps) / 100}% (the vault's current agentFeeBps). Run \`sherwood fund set-agent-fee --bps <bps>\` first to change it.`
3192
3110
  )
3193
3111
  );
3194
3112
  } catch {
3195
3113
  }
3196
- await ensureProposerBondAllowance(vault);
3114
+ try {
3115
+ await ensureProposerBondAllowance(vault, assetAmount, asset);
3116
+ } catch (err) {
3117
+ if (err instanceof InsufficientProposerBondWood) {
3118
+ console.error(chalk3.red(err.message));
3119
+ process.exit(1);
3120
+ }
3121
+ throw err;
3122
+ }
3197
3123
  const proposeSpinner = ora2("Submitting proposal...").start();
3198
3124
  try {
3199
3125
  const executeCallCaps = capsForCalls(executeCalls, clone, assetAmount);
@@ -3211,33 +3137,202 @@ function registerStrategyTemplateCommands(strategy2) {
3211
3137
  );
3212
3138
  proposeSpinner.succeed(`Proposal #${proposalId} created \u2014 strategy=${clone} set on proposal`);
3213
3139
  console.log(`Proposal #${proposalId}`);
3214
- console.log(chalk2.dim(` Tx: ${getExplorerUrl(hash)}`));
3215
- console.log(chalk2.dim(` Clone: ${clone}`));
3140
+ console.log(chalk3.dim(` Tx: ${getExplorerUrl(hash)}`));
3141
+ console.log(chalk3.dim(` Clone: ${clone}`));
3216
3142
  } catch (err) {
3217
3143
  proposeSpinner.fail("Proposal failed");
3218
- console.error(chalk2.red(formatContractError(err)));
3144
+ console.error(chalk3.red(formatContractError(err)));
3219
3145
  process.exit(1);
3220
3146
  }
3221
3147
  if (templateKey === "venice-inference") {
3222
3148
  console.log();
3223
- console.log(chalk2.yellow("Next steps:"));
3224
- console.log(chalk2.yellow(" 1. After execution: sherwood venice provision"));
3225
- console.log(chalk2.yellow(" 2. Use inference: sherwood venice infer --model <id> --prompt '...'"));
3226
- console.log(chalk2.yellow(" 3. Before settlement: approve repayment (principal + profit):"));
3227
- console.log(chalk2.yellow(` asset.approve(${clone}, <repaymentAmount>)`));
3149
+ console.log(chalk3.yellow("Next steps:"));
3150
+ console.log(chalk3.yellow(" 1. After execution: sherwood venice provision"));
3151
+ console.log(chalk3.yellow(" 2. Use inference: sherwood venice infer --model <id> --prompt '...'"));
3152
+ console.log(chalk3.yellow(" 3. Before settlement: approve repayment (principal + profit):"));
3153
+ console.log(chalk3.yellow(` asset.approve(${clone}, <repaymentAmount>)`));
3154
+ }
3155
+ console.log();
3156
+ });
3157
+ }
3158
+
3159
+ // src/commands/strategy-template.ts
3160
+ function registerStrategyTemplateCommands(strategy2) {
3161
+ strategy2.command("list").description("List available strategy templates").action(() => {
3162
+ const templates = STRATEGY_TEMPLATES();
3163
+ const network = getNetwork();
3164
+ console.log();
3165
+ console.log(chalk4.bold("Strategy Templates"), chalk4.dim(`(${network})`));
3166
+ console.log(chalk4.dim("\u2500".repeat(60)));
3167
+ let availableCount = 0;
3168
+ for (const t of TEMPLATES) {
3169
+ const addr = templates[t.addressKey];
3170
+ if (addr !== ZERO) {
3171
+ availableCount++;
3172
+ console.log();
3173
+ console.log(` ${chalk4.bold(t.name)} (${chalk4.cyan(t.key)})`);
3174
+ console.log(` ${t.description}`);
3175
+ console.log(` Template: ${chalk4.green(addr)}`);
3176
+ }
3177
+ }
3178
+ if (availableCount === 0) {
3179
+ console.log();
3180
+ console.log(chalk4.yellow(" No strategy templates deployed on this network."));
3181
+ }
3182
+ const unavailable2 = TEMPLATES.filter((t) => templates[t.addressKey] === ZERO);
3183
+ if (unavailable2.length > 0) {
3184
+ console.log();
3185
+ console.log(chalk4.dim(` Not available on ${network}:`));
3186
+ for (const t of unavailable2) {
3187
+ console.log(chalk4.dim(` ${t.name} (${t.key})`));
3188
+ }
3228
3189
  }
3229
3190
  console.log();
3191
+ console.log(chalk4.dim("Clone a template: sherwood strategy clone <template> --vault <addr> ..."));
3192
+ console.log(chalk4.dim("Full proposal: sherwood strategy propose <template> --vault <addr> ..."));
3193
+ console.log();
3230
3194
  });
3195
+ strategy2.command("clone").description("Clone a strategy template and initialize it").argument("<template>", "Template: moonwell-supply, aerodrome-lp, venice-inference, wsteth-moonwell, mamo-yield, portfolio, hyperliquid-perp, hyperliquid-grid").requiredOption("--vault <address>", "Vault address").option("--amount <n>", "Asset amount to deploy").option("--min-redeem <n>", "Min asset on settlement (Moonwell)").option("--token <symbol>", "Asset token symbol (default: USDC)").option("--asset <symbol>", "Asset token (USDC, VVV, or address)").option("--agent <address>", "Agent wallet (Venice, default: your wallet)").option("--min-vvv <n>", "Min VVV from swap (Venice)").option("--single-hop", "Single-hop Aerodrome swap (Venice)").option("--token-a <address>", "Token A (Aerodrome)").option("--token-b <address>", "Token B (Aerodrome)").option("--amount-a <n>", "Token A amount (Aerodrome)").option("--amount-b <n>", "Token B amount (Aerodrome)").option("--stable", "Stable pool (Aerodrome)").option("--gauge <address>", "Gauge address (Aerodrome)").option("--lp-token <address>", "LP token address (Aerodrome)").option("--min-a-out <n>", "Min token A on settle (Aerodrome)").option("--min-b-out <n>", "Min token B on settle (Aerodrome)").option("--slippage <bps>", "Slippage tolerance in bps (wstETH, default: 500 = 5%)").option("--mamo-factory <address>", "Mamo StrategyFactory address (Mamo)").option("--tokens <list>", "Comma-separated token addresses or symbols (Portfolio)").option("--weights <list>", "Comma-separated weights in bps, must sum to 10000 (Portfolio)").option("--max-slippage <bps>", "Max slippage bps (Portfolio, default: 500)").option("--fee-tier <n>", "Pool fee tier (Portfolio, default: 3000)").option("--swap-adapter <address>", "Swap adapter address (Portfolio)").option("--feed-ids <list>", "Comma-separated Chainlink feed ids/addresses per token (Portfolio; auto-resolved from registry in push-feed mode)").option("--price-decimals <list>", "Comma-separated raw feed decimals per token (Portfolio; default 8 push / 18 Data Streams)").option("--swap-routes <list>", "Comma-separated per-token swap route spec (Portfolio). Per token: 'v3:<fee>' (mode 0), 'v4:<fee>:<tickSpacing>' (mode 2), or 'v4path:<hop>+<hop>...' (mode 3) where hop='<currency>@<fee>:<tickSpacing>', currency='eth'/'native'=ETH or 'self'=this token or an address. Empty entry = auto-detect / robinhood default.").option(
3196
+ "--max-drawdown-bps <bps>",
3197
+ "Declared loss allowance for this proposal, in bps of --amount (0-10000, default 2000 = 20%). This is the envelope voters and guardians are asked to accept, and the basis the settle-price guard sizes its tolerance from \u2014 not a formality."
3198
+ ).option("--max-price-ages <list>", "Comma-separated per-token max Chainlink push-feed staleness in seconds (Portfolio, push mode; robinhood-mainnet equity feeds default to 345600 = 96h, crypto/stable feeds to the contract default). Empty entry = registry default.").option("--leverage <number>", "Leverage multiplier (Hyperliquid Perp, default: 10)").option("--asset-index <number>", "Perp asset index (Hyperliquid Perp, default: 0 for BTC)").option("--max-position <amount>", "Max position size in USD (Hyperliquid Perp, default: 100000)").option("--max-trades-per-day <n>", "Max trades per day (Hyperliquid Perp, default: 50)").option("--max-order-size <amount>", "Max single-order size in asset units (Hyperliquid Grid, default: 10000)").option("--max-orders-per-tick <n>", "Max orders per tick (Hyperliquid Grid, default: 20)").option("--asset-indices <list>", "Comma-separated perp asset indices (Hyperliquid Grid, default: 0)").action(async (templateKey, opts) => {
3199
+ const vault = opts.vault;
3200
+ if (!isAddress5(vault)) {
3201
+ console.error(chalk4.red("Invalid vault address"));
3202
+ process.exit(1);
3203
+ }
3204
+ const { def, address: templateAddr } = resolveTemplate(templateKey);
3205
+ const cloneSpinner = ora3(`Cloning ${def.name} template...`).start();
3206
+ let clone;
3207
+ let cloneHash;
3208
+ try {
3209
+ const result = await cloneTemplate(templateAddr);
3210
+ clone = result.clone;
3211
+ cloneHash = result.hash;
3212
+ cloneSpinner.succeed(`Cloned: ${chalk4.green(clone)}`);
3213
+ console.log(chalk4.dim(` Tx: ${getExplorerUrl(cloneHash)}`));
3214
+ } catch (err) {
3215
+ cloneSpinner.fail("Clone failed");
3216
+ console.error(chalk4.red(formatContractError(err)));
3217
+ process.exit(1);
3218
+ }
3219
+ const initSpinner = ora3("Initializing strategy...").start();
3220
+ try {
3221
+ const { initData } = await resolveAndBuildInitData(templateKey, opts, vault);
3222
+ const account = getAccount();
3223
+ const initHash = await writeContractWithRetry({
3224
+ account,
3225
+ chain: getChain(),
3226
+ address: clone,
3227
+ abi: BASE_STRATEGY_ABI,
3228
+ functionName: "initialize",
3229
+ args: [vault, account.address, initData]
3230
+ });
3231
+ const receipt = await waitForReceipt(initHash);
3232
+ if (receipt.status === "reverted") {
3233
+ throw new Error("Initialize transaction reverted on-chain");
3234
+ }
3235
+ initSpinner.succeed("Initialized");
3236
+ } catch (err) {
3237
+ initSpinner.fail("Initialize failed");
3238
+ console.error(chalk4.red(formatContractError(err)));
3239
+ process.exit(1);
3240
+ }
3241
+ if (templateKey === "hyperliquid-grid" || templateKey === "hyperliquid-perp") {
3242
+ const hcSpinner = ora3("Registering clone with HyperCore...").start();
3243
+ try {
3244
+ const account = getAccount();
3245
+ const hcHash = await writeContractWithRetry({
3246
+ account,
3247
+ chain: getChain(),
3248
+ address: clone,
3249
+ abi: templateKey === "hyperliquid-grid" ? HYPERLIQUID_GRID_STRATEGY_ABI : HYPERLIQUID_PERP_STRATEGY_ABI,
3250
+ functionName: "finalizeForHyperCore",
3251
+ args: [0n, 1, 0n]
3252
+ // token=USDC, variant=FirstStorageSlot(1), nonce unused
3253
+ });
3254
+ await waitForReceipt(hcHash);
3255
+ hcSpinner.succeed("HyperCore registration sent (active after next block)");
3256
+ } catch (err) {
3257
+ hcSpinner.warn("HyperCore registration failed \u2014 run finalizeForHyperCore manually");
3258
+ console.error(chalk4.yellow(formatContractError(err)));
3259
+ }
3260
+ }
3261
+ console.log();
3262
+ console.log(chalk4.bold("Strategy clone ready:"), chalk4.green(clone));
3263
+ console.log(chalk4.dim("Use this address in your proposal batch calls."));
3264
+ console.log();
3265
+ });
3266
+ strategy2.command("init").description("Initialize an already-deployed but uninitialized strategy clone").argument("<template>", "Template: moonwell-supply, aerodrome-lp, venice-inference, wsteth-moonwell, mamo-yield, portfolio, hyperliquid-perp, hyperliquid-grid").requiredOption("--clone <address>", "Clone address to initialize").requiredOption("--vault <address>", "Vault address").option("--amount <n>", "Asset amount to deploy").option("--min-redeem <n>", "Min asset on settlement (Moonwell)").option("--token <symbol>", "Asset token symbol (default: USDC)").option("--asset <symbol>", "Asset token (USDC, VVV, or address)").option("--agent <address>", "Agent wallet (Venice, default: your wallet)").option("--min-vvv <n>", "Min VVV from swap (Venice)").option("--single-hop", "Single-hop Aerodrome swap (Venice)").option("--token-a <address>", "Token A (Aerodrome)").option("--token-b <address>", "Token B (Aerodrome)").option("--amount-a <n>", "Token A amount (Aerodrome)").option("--amount-b <n>", "Token B amount (Aerodrome)").option("--stable", "Stable pool (Aerodrome)").option("--gauge <address>", "Gauge address (Aerodrome)").option("--lp-token <address>", "LP token address (Aerodrome)").option("--min-a-out <n>", "Min token A on settle (Aerodrome)").option("--min-b-out <n>", "Min token B on settle (Aerodrome)").option("--slippage <bps>", "Slippage tolerance in bps (wstETH, default: 500 = 5%)").option("--mamo-factory <address>", "Mamo StrategyFactory address (Mamo)").option("--tokens <list>", "Comma-separated token addresses or symbols (Portfolio)").option("--weights <list>", "Comma-separated weights in bps, must sum to 10000 (Portfolio)").option("--max-slippage <bps>", "Max slippage bps (Portfolio, default: 500)").option("--fee-tier <n>", "Pool fee tier (Portfolio, default: 3000)").option("--swap-adapter <address>", "Swap adapter address (Portfolio)").option("--feed-ids <list>", "Comma-separated Chainlink feed ids/addresses per token (Portfolio; auto-resolved from registry in push-feed mode)").option("--price-decimals <list>", "Comma-separated raw feed decimals per token (Portfolio; default 8 push / 18 Data Streams)").option("--swap-routes <list>", "Comma-separated per-token swap route spec (Portfolio). Per token: 'v3:<fee>' (mode 0), 'v4:<fee>:<tickSpacing>' (mode 2), or 'v4path:<hop>+<hop>...' (mode 3) where hop='<currency>@<fee>:<tickSpacing>', currency='eth'/'native'=ETH or 'self'=this token or an address. Empty entry = auto-detect / robinhood default.").option(
3267
+ "--max-drawdown-bps <bps>",
3268
+ "Declared loss allowance for this proposal, in bps of --amount (0-10000, default 2000 = 20%). This is the envelope voters and guardians are asked to accept, and the basis the settle-price guard sizes its tolerance from \u2014 not a formality."
3269
+ ).option("--max-price-ages <list>", "Comma-separated per-token max Chainlink push-feed staleness in seconds (Portfolio, push mode; robinhood-mainnet equity feeds default to 345600 = 96h, crypto/stable feeds to the contract default). Empty entry = registry default.").option("--leverage <number>", "Leverage multiplier (Hyperliquid Perp, default: 10)").option("--asset-index <number>", "Perp asset index (Hyperliquid Perp, default: 0 for BTC)").option("--max-position <amount>", "Max position size in USD (Hyperliquid Perp, default: 100000)").option("--max-trades-per-day <n>", "Max trades per day (Hyperliquid Perp, default: 50)").option("--max-order-size <amount>", "Max single-order size in asset units (Hyperliquid Grid, default: 10000)").option("--max-orders-per-tick <n>", "Max orders per tick (Hyperliquid Grid, default: 20)").option("--asset-indices <list>", "Comma-separated perp asset indices (Hyperliquid Grid, default: 0)").action(async (templateKey, opts) => {
3270
+ const clone = opts.clone;
3271
+ const vault = opts.vault;
3272
+ if (!isAddress5(clone)) {
3273
+ console.error(chalk4.red("Invalid clone address"));
3274
+ process.exit(1);
3275
+ }
3276
+ if (!isAddress5(vault)) {
3277
+ console.error(chalk4.red("Invalid vault address"));
3278
+ process.exit(1);
3279
+ }
3280
+ resolveTemplate(templateKey);
3281
+ const publicClient = getPublicClient();
3282
+ const currentVault = await publicClient.readContract({
3283
+ address: clone,
3284
+ abi: BASE_STRATEGY_ABI,
3285
+ functionName: "vault"
3286
+ });
3287
+ if (currentVault !== "0x0000000000000000000000000000000000000000") {
3288
+ console.error(chalk4.red(`Clone already initialized (vault: ${currentVault})`));
3289
+ process.exit(1);
3290
+ }
3291
+ const initSpinner = ora3("Initializing strategy clone...").start();
3292
+ try {
3293
+ const { initData } = await resolveAndBuildInitData(templateKey, opts, vault);
3294
+ const account = getAccount();
3295
+ const initHash = await writeContractWithRetry({
3296
+ account,
3297
+ chain: getChain(),
3298
+ address: clone,
3299
+ abi: BASE_STRATEGY_ABI,
3300
+ functionName: "initialize",
3301
+ args: [vault, account.address, initData]
3302
+ });
3303
+ const receipt = await waitForReceipt(initHash);
3304
+ if (receipt.status === "reverted") {
3305
+ throw new Error("Initialize transaction reverted on-chain");
3306
+ }
3307
+ initSpinner.succeed("Initialized");
3308
+ console.log(chalk4.dim(` Tx: ${getExplorerUrl(initHash)}`));
3309
+ } catch (err) {
3310
+ initSpinner.fail("Initialize failed");
3311
+ console.error(chalk4.red(formatContractError(err)));
3312
+ process.exit(1);
3313
+ }
3314
+ const verifiedVault = await publicClient.readContract({
3315
+ address: clone,
3316
+ abi: BASE_STRATEGY_ABI,
3317
+ functionName: "vault"
3318
+ });
3319
+ console.log();
3320
+ console.log(chalk4.bold("Clone initialized:"), chalk4.green(clone));
3321
+ console.log(` Vault: ${chalk4.green(verifiedVault)}`);
3322
+ console.log(` Proposer: ${chalk4.green(getAccount().address)}`);
3323
+ console.log();
3324
+ });
3325
+ registerStrategyProposeCommands(strategy2);
3231
3326
  strategy2.command("status").description("Show portfolio strategy status \u2014 allocations, balances, drift, PnL (Portfolio only)").argument("<clone>", "Strategy clone address").option("--json", "Output machine-readable JSON for agent consumption").action(async (cloneArg, opts) => {
3232
- if (!isAddress3(cloneArg)) {
3233
- console.error(chalk2.red("Invalid clone address"));
3327
+ if (!isAddress5(cloneArg)) {
3328
+ console.error(chalk4.red("Invalid clone address"));
3234
3329
  process.exit(1);
3235
3330
  }
3236
3331
  const clone = cloneArg;
3237
3332
  const publicClient = getPublicClient();
3238
3333
  const network = getNetwork();
3239
3334
  const jsonMode = !!opts.json;
3240
- const spinner = jsonMode ? null : ora2("Reading strategy state...").start();
3335
+ const spinner = jsonMode ? null : ora3("Reading strategy state...").start();
3241
3336
  try {
3242
3337
  const [stateRaw, vault, proposer, assetAddr, totalAmount, maxSlippage, allocations, swapExtraData] = await Promise.all([
3243
3338
  publicClient.readContract({ address: clone, abi: PORTFOLIO_STRATEGY_ABI, functionName: "state" }),
@@ -3252,24 +3347,24 @@ function registerStrategyTemplateCommands(strategy2) {
3252
3347
  const stateNames = ["Pending", "Executed", "Settled"];
3253
3348
  const stateStr = stateNames[Number(stateRaw)] || `Unknown(${stateRaw})`;
3254
3349
  const [assetDecimals, assetSymbol] = await Promise.all([
3255
- publicClient.readContract({ address: assetAddr, abi: erc20Abi, functionName: "decimals" }),
3256
- publicClient.readContract({ address: assetAddr, abi: erc20Abi, functionName: "symbol" })
3350
+ publicClient.readContract({ address: assetAddr, abi: erc20Abi3, functionName: "decimals" }),
3351
+ publicClient.readContract({ address: assetAddr, abi: erc20Abi3, functionName: "symbol" })
3257
3352
  ]);
3258
3353
  const tokenReads = allocations.map((a) => Promise.all([
3259
- publicClient.readContract({ address: a.token, abi: erc20Abi, functionName: "balanceOf", args: [clone] }),
3260
- publicClient.readContract({ address: a.token, abi: erc20Abi, functionName: "symbol" }),
3261
- publicClient.readContract({ address: a.token, abi: erc20Abi, functionName: "decimals" })
3354
+ publicClient.readContract({ address: a.token, abi: erc20Abi3, functionName: "balanceOf", args: [clone] }),
3355
+ publicClient.readContract({ address: a.token, abi: erc20Abi3, functionName: "symbol" }),
3356
+ publicClient.readContract({ address: a.token, abi: erc20Abi3, functionName: "decimals" })
3262
3357
  ]));
3263
3358
  const tokenData = await Promise.all(tokenReads);
3264
3359
  const assetBalance = await publicClient.readContract({
3265
3360
  address: assetAddr,
3266
- abi: erc20Abi,
3361
+ abi: erc20Abi3,
3267
3362
  functionName: "balanceOf",
3268
3363
  args: [clone]
3269
3364
  });
3270
3365
  const feeTiers = swapExtraData.map((data) => {
3271
3366
  try {
3272
- const [fee] = decodeAbiParameters([{ type: "uint24" }], data);
3367
+ const [fee] = decodeAbiParameters3([{ type: "uint24" }], data);
3273
3368
  return Number(fee) > 0 && Number(fee) <= 1e5 ? Number(fee) : 3e3;
3274
3369
  } catch {
3275
3370
  return 3e3;
@@ -3278,7 +3373,7 @@ function registerStrategyTemplateCommands(strategy2) {
3278
3373
  let prices = [];
3279
3374
  let priceSource = null;
3280
3375
  try {
3281
- const { getTokenPricesInAsset } = await import("./price-JX2LFKFW.js");
3376
+ const { getTokenPricesInAsset } = await import("./price-OUL7WIXQ.js");
3282
3377
  prices = await getTokenPricesInAsset({
3283
3378
  tokens: allocations.map((a, i) => ({
3284
3379
  token: a.token,
@@ -3292,13 +3387,13 @@ function registerStrategyTemplateCommands(strategy2) {
3292
3387
  } catch {
3293
3388
  }
3294
3389
  const pricesAvailable = prices.some((p) => p !== null);
3295
- const assetBalanceNum = Number(formatUnits3(assetBalance, assetDecimals));
3390
+ const assetBalanceNum = Number(formatUnits6(assetBalance, assetDecimals));
3296
3391
  let totalPortfolioValue = assetBalanceNum;
3297
3392
  let totalInvested = 0n;
3298
3393
  const allocStatuses = allocations.map((alloc, i) => {
3299
3394
  const [balance, symbol, decimals] = tokenData[i];
3300
- const balanceNum = Number(formatUnits3(balance, decimals));
3301
- const investedNum = Number(formatUnits3(alloc.investedAmount, assetDecimals));
3395
+ const balanceNum = Number(formatUnits6(balance, decimals));
3396
+ const investedNum = Number(formatUnits6(alloc.investedAmount, assetDecimals));
3302
3397
  totalInvested += alloc.investedAmount;
3303
3398
  const price = prices[i];
3304
3399
  let currentValue = null;
@@ -3311,9 +3406,9 @@ function registerStrategyTemplateCommands(strategy2) {
3311
3406
  symbol,
3312
3407
  decimals,
3313
3408
  targetWeightBps: Number(alloc.targetWeightBps),
3314
- balance: formatUnits3(balance, decimals),
3409
+ balance: formatUnits6(balance, decimals),
3315
3410
  balanceRaw: balance.toString(),
3316
- investedAmount: formatUnits3(alloc.investedAmount, assetDecimals),
3411
+ investedAmount: formatUnits6(alloc.investedAmount, assetDecimals),
3317
3412
  currentPrice: price?.price ?? null,
3318
3413
  currentValue,
3319
3414
  actualWeightBps: null,
@@ -3337,7 +3432,7 @@ function registerStrategyTemplateCommands(strategy2) {
3337
3432
  }
3338
3433
  }
3339
3434
  }
3340
- const totalInvestedNum = Number(formatUnits3(totalInvested, assetDecimals));
3435
+ const totalInvestedNum = Number(formatUnits6(totalInvested, assetDecimals));
3341
3436
  const totalPnl = pricesAvailable ? totalPortfolioValue - totalInvestedNum : null;
3342
3437
  const totalPnlPct = totalPnl !== null && totalInvestedNum > 0 ? totalPnl / totalInvestedNum * 100 : null;
3343
3438
  spinner?.succeed("Strategy state loaded");
@@ -3349,9 +3444,9 @@ function registerStrategyTemplateCommands(strategy2) {
3349
3444
  state: stateStr,
3350
3445
  network,
3351
3446
  asset: { address: assetAddr, symbol: assetSymbol, decimals: assetDecimals },
3352
- totalDeployed: formatUnits3(totalAmount, assetDecimals),
3447
+ totalDeployed: formatUnits6(totalAmount, assetDecimals),
3353
3448
  maxSlippageBps: Number(maxSlippage),
3354
- assetBalance: formatUnits3(assetBalance, assetDecimals),
3449
+ assetBalance: formatUnits6(assetBalance, assetDecimals),
3355
3450
  pricesAvailable,
3356
3451
  priceSource,
3357
3452
  portfolio: {
@@ -3367,87 +3462,87 @@ function registerStrategyTemplateCommands(strategy2) {
3367
3462
  process.stdout.write(JSON.stringify(result) + "\n");
3368
3463
  return;
3369
3464
  }
3370
- const stateColor = stateStr === "Executed" ? chalk2.green : stateStr === "Settled" ? chalk2.blue : chalk2.yellow;
3465
+ const stateColor = stateStr === "Executed" ? chalk4.green : stateStr === "Settled" ? chalk4.blue : chalk4.yellow;
3371
3466
  console.log();
3372
- console.log(chalk2.bold("Portfolio Strategy Status"));
3373
- console.log(chalk2.dim("\u2500".repeat(70)));
3374
- console.log(` Clone: ${chalk2.cyan(clone)}`);
3375
- console.log(` Vault: ${chalk2.cyan(vault)}`);
3376
- console.log(` Proposer: ${chalk2.cyan(proposer)}`);
3467
+ console.log(chalk4.bold("Portfolio Strategy Status"));
3468
+ console.log(chalk4.dim("\u2500".repeat(70)));
3469
+ console.log(` Clone: ${chalk4.cyan(clone)}`);
3470
+ console.log(` Vault: ${chalk4.cyan(vault)}`);
3471
+ console.log(` Proposer: ${chalk4.cyan(proposer)}`);
3377
3472
  console.log(` State: ${stateColor(stateStr)}`);
3378
3473
  console.log(` Asset: ${assetSymbol} (${assetAddr})`);
3379
- console.log(` Deployed: ${formatUnits3(totalAmount, assetDecimals)} ${assetSymbol}`);
3474
+ console.log(` Deployed: ${formatUnits6(totalAmount, assetDecimals)} ${assetSymbol}`);
3380
3475
  console.log(` Max Slip: ${Number(maxSlippage) / 100}%`);
3381
- console.log(` Asset held: ${formatUnits3(assetBalance, assetDecimals)} ${assetSymbol}`);
3476
+ console.log(` Asset held: ${formatUnits6(assetBalance, assetDecimals)} ${assetSymbol}`);
3382
3477
  if (pricesAvailable) {
3383
3478
  const pvStr = totalPortfolioValue.toFixed(6);
3384
3479
  const pnlStr = totalPnl !== null ? (totalPnl >= 0 ? "+" : "") + totalPnl.toFixed(6) : "n/a";
3385
3480
  const pnlPctStr = totalPnlPct !== null ? (totalPnlPct >= 0 ? "+" : "") + totalPnlPct.toFixed(1) + "%" : "";
3386
- const pnlColor = totalPnl !== null && totalPnl >= 0 ? chalk2.green : chalk2.red;
3481
+ const pnlColor = totalPnl !== null && totalPnl >= 0 ? chalk4.green : chalk4.red;
3387
3482
  console.log(` Value: ${pvStr} ${assetSymbol} | PnL: ${pnlColor(`${pnlStr} (${pnlPctStr})`)}`);
3388
3483
  console.log(` Price src: ${priceSource}`);
3389
3484
  }
3390
3485
  console.log();
3391
- console.log(chalk2.bold("Allocations"));
3392
- console.log(chalk2.dim("\u2500".repeat(70)));
3486
+ console.log(chalk4.bold("Allocations"));
3487
+ console.log(chalk4.dim("\u2500".repeat(70)));
3393
3488
  if (pricesAvailable) {
3394
3489
  console.log(
3395
- chalk2.dim(" Token".padEnd(10)) + chalk2.dim("Target".padEnd(9)) + chalk2.dim("Actual".padEnd(9)) + chalk2.dim("Drift".padEnd(8)) + chalk2.dim("Value".padEnd(16)) + chalk2.dim("PnL".padEnd(16)) + chalk2.dim("Balance")
3490
+ chalk4.dim(" Token".padEnd(10)) + chalk4.dim("Target".padEnd(9)) + chalk4.dim("Actual".padEnd(9)) + chalk4.dim("Drift".padEnd(8)) + chalk4.dim("Value".padEnd(16)) + chalk4.dim("PnL".padEnd(16)) + chalk4.dim("Balance")
3396
3491
  );
3397
3492
  for (const a of allocStatuses) {
3398
3493
  const targetStr = (a.targetWeightBps / 100).toFixed(1) + "%";
3399
3494
  const actualStr = a.actualWeightBps !== null ? (a.actualWeightBps / 100).toFixed(1) + "%" : "\u2014";
3400
3495
  const driftStr = a.driftBps !== null ? (a.driftBps >= 0 ? "+" : "") + a.driftBps : "\u2014";
3401
- const driftColor = a.driftBps !== null ? Math.abs(a.driftBps) > 500 ? chalk2.red : Math.abs(a.driftBps) > 200 ? chalk2.yellow : chalk2.dim : chalk2.dim;
3496
+ const driftColor = a.driftBps !== null ? Math.abs(a.driftBps) > 500 ? chalk4.red : Math.abs(a.driftBps) > 200 ? chalk4.yellow : chalk4.dim : chalk4.dim;
3402
3497
  const valueStr = a.currentValue !== null ? a.currentValue.toFixed(6) : "\u2014";
3403
3498
  const pnlPctStr = a.pnlPct !== null ? (a.pnlPct >= 0 ? "+" : "") + a.pnlPct.toFixed(1) + "%" : "\u2014";
3404
- const pnlColor = a.pnlPct !== null ? a.pnlPct >= 0 ? chalk2.green : chalk2.red : chalk2.dim;
3499
+ const pnlColor = a.pnlPct !== null ? a.pnlPct >= 0 ? chalk4.green : chalk4.red : chalk4.dim;
3405
3500
  console.log(
3406
- ` ${chalk2.bold(a.symbol.padEnd(8))}${targetStr.padEnd(9)}${actualStr.padEnd(9)}${driftColor(driftStr.toString().padEnd(8))}${valueStr.padEnd(16)}${pnlColor(pnlPctStr.padEnd(16))}${a.balance}`
3501
+ ` ${chalk4.bold(a.symbol.padEnd(8))}${targetStr.padEnd(9)}${actualStr.padEnd(9)}${driftColor(driftStr.toString().padEnd(8))}${valueStr.padEnd(16)}${pnlColor(pnlPctStr.padEnd(16))}${a.balance}`
3407
3502
  );
3408
3503
  }
3409
3504
  } else {
3410
- console.log(chalk2.dim(" Prices unavailable \u2014 showing raw balances only."));
3505
+ console.log(chalk4.dim(" Prices unavailable \u2014 showing raw balances only."));
3411
3506
  console.log();
3412
3507
  console.log(
3413
- chalk2.dim(" Token".padEnd(12)) + chalk2.dim("Weight".padEnd(10)) + chalk2.dim("Invested".padEnd(18)) + chalk2.dim("Balance".padEnd(18)) + chalk2.dim("Address")
3508
+ chalk4.dim(" Token".padEnd(12)) + chalk4.dim("Weight".padEnd(10)) + chalk4.dim("Invested".padEnd(18)) + chalk4.dim("Balance".padEnd(18)) + chalk4.dim("Address")
3414
3509
  );
3415
3510
  for (const a of allocStatuses) {
3416
3511
  const weightPct = (a.targetWeightBps / 100).toFixed(1) + "%";
3417
3512
  console.log(
3418
- ` ${chalk2.bold(a.symbol.padEnd(10))}${weightPct.padEnd(10)}${a.investedAmount.padEnd(18)}${a.balance.padEnd(18)}${chalk2.dim(a.token)}`
3513
+ ` ${chalk4.bold(a.symbol.padEnd(10))}${weightPct.padEnd(10)}${a.investedAmount.padEnd(18)}${a.balance.padEnd(18)}${chalk4.dim(a.token)}`
3419
3514
  );
3420
3515
  }
3421
3516
  }
3422
- console.log(chalk2.dim("\u2500".repeat(70)));
3423
- console.log(` Total invested: ${formatUnits3(totalInvested, assetDecimals)} ${assetSymbol}`);
3517
+ console.log(chalk4.dim("\u2500".repeat(70)));
3518
+ console.log(` Total invested: ${formatUnits6(totalInvested, assetDecimals)} ${assetSymbol}`);
3424
3519
  if (pricesAvailable && maxDriftToken) {
3425
3520
  const absMaxDrift = Math.abs(maxDriftBps);
3426
- const driftColor = absMaxDrift > 500 ? chalk2.red : absMaxDrift > 200 ? chalk2.yellow : chalk2.green;
3521
+ const driftColor = absMaxDrift > 500 ? chalk4.red : absMaxDrift > 200 ? chalk4.yellow : chalk4.green;
3427
3522
  console.log(` Max drift: ${driftColor(`${maxDriftBps > 0 ? "+" : ""}${maxDriftBps} bps`)} (${maxDriftToken})`);
3428
3523
  }
3429
3524
  if (stateStr === "Executed") {
3430
3525
  console.log();
3431
- console.log(chalk2.dim("Rebalance: sherwood strategy rebalance " + clone));
3432
- console.log(chalk2.dim("With new weights: sherwood strategy rebalance " + clone + " --new-weights 2500,2500,2000,1500,1500"));
3526
+ console.log(chalk4.dim("Rebalance: sherwood strategy rebalance " + clone));
3527
+ console.log(chalk4.dim("With new weights: sherwood strategy rebalance " + clone + " --new-weights 2500,2500,2000,1500,1500"));
3433
3528
  }
3434
3529
  console.log();
3435
3530
  } catch (err) {
3436
3531
  spinner?.fail("Failed to read strategy state");
3437
- console.error(chalk2.red(formatContractError(err)));
3532
+ console.error(chalk4.red(formatContractError(err)));
3438
3533
  process.exit(1);
3439
3534
  }
3440
3535
  });
3441
3536
  strategy2.command("rebalance").description("Rebalance a portfolio strategy \u2014 sell all positions, re-buy at target weights (Portfolio only)").argument("<clone>", "Strategy clone address").option("--new-weights <list>", "Comma-separated new weights in bps (must sum to 10000). Updates weights before rebalancing.").option("--max-slippage <bps>", "New max slippage bps (used with --new-weights)").option("--dry-run", "Show what would happen without executing").action(async (cloneArg, opts) => {
3442
- if (!isAddress3(cloneArg)) {
3443
- console.error(chalk2.red("Invalid clone address"));
3537
+ if (!isAddress5(cloneArg)) {
3538
+ console.error(chalk4.red("Invalid clone address"));
3444
3539
  process.exit(1);
3445
3540
  }
3446
3541
  const clone = cloneArg;
3447
3542
  const publicClient = getPublicClient();
3448
3543
  const account = getAccount();
3449
3544
  const chain = getChain();
3450
- const verifySpinner = ora2("Verifying strategy state...").start();
3545
+ const verifySpinner = ora3("Verifying strategy state...").start();
3451
3546
  try {
3452
3547
  const [stateRaw, proposer, assetAddr, allocations] = await Promise.all([
3453
3548
  publicClient.readContract({ address: clone, abi: PORTFOLIO_STRATEGY_ABI, functionName: "state" }),
@@ -3465,56 +3560,56 @@ function registerStrategyTemplateCommands(strategy2) {
3465
3560
  process.exit(1);
3466
3561
  }
3467
3562
  const [assetDecimals, assetSymbol] = await Promise.all([
3468
- publicClient.readContract({ address: assetAddr, abi: erc20Abi, functionName: "decimals" }),
3469
- publicClient.readContract({ address: assetAddr, abi: erc20Abi, functionName: "symbol" })
3563
+ publicClient.readContract({ address: assetAddr, abi: erc20Abi3, functionName: "decimals" }),
3564
+ publicClient.readContract({ address: assetAddr, abi: erc20Abi3, functionName: "symbol" })
3470
3565
  ]);
3471
3566
  const tokenReads = allocations.map((a) => Promise.all([
3472
- publicClient.readContract({ address: a.token, abi: erc20Abi, functionName: "balanceOf", args: [clone] }),
3473
- publicClient.readContract({ address: a.token, abi: erc20Abi, functionName: "symbol" }),
3474
- publicClient.readContract({ address: a.token, abi: erc20Abi, functionName: "decimals" })
3567
+ publicClient.readContract({ address: a.token, abi: erc20Abi3, functionName: "balanceOf", args: [clone] }),
3568
+ publicClient.readContract({ address: a.token, abi: erc20Abi3, functionName: "symbol" }),
3569
+ publicClient.readContract({ address: a.token, abi: erc20Abi3, functionName: "decimals" })
3475
3570
  ]));
3476
3571
  const tokenData = await Promise.all(tokenReads);
3477
3572
  verifySpinner.succeed("Strategy is Executed \u2014 ready to rebalance");
3478
3573
  console.log();
3479
- console.log(chalk2.bold("Current Allocations"));
3480
- console.log(chalk2.dim("\u2500".repeat(50)));
3574
+ console.log(chalk4.bold("Current Allocations"));
3575
+ console.log(chalk4.dim("\u2500".repeat(50)));
3481
3576
  for (let i = 0; i < allocations.length; i++) {
3482
3577
  const alloc = allocations[i];
3483
3578
  const [balance, symbol, decimals] = tokenData[i];
3484
3579
  const weightPct = (Number(alloc.targetWeightBps) / 100).toFixed(1) + "%";
3485
3580
  console.log(
3486
- ` ${chalk2.bold(symbol.padEnd(8))} ${weightPct.padEnd(8)} bal: ${formatUnits3(balance, decimals)}`
3581
+ ` ${chalk4.bold(symbol.padEnd(8))} ${weightPct.padEnd(8)} bal: ${formatUnits6(balance, decimals)}`
3487
3582
  );
3488
3583
  }
3489
3584
  let newWeightsBps;
3490
3585
  if (opts.newWeights) {
3491
3586
  newWeightsBps = opts.newWeights.split(",").map((w) => Number(w.trim()));
3492
3587
  if (newWeightsBps.length !== allocations.length) {
3493
- console.error(chalk2.red(`--new-weights must have ${allocations.length} values (one per token)`));
3588
+ console.error(chalk4.red(`--new-weights must have ${allocations.length} values (one per token)`));
3494
3589
  process.exit(1);
3495
3590
  }
3496
3591
  const weightSum = newWeightsBps.reduce((a, b) => a + b, 0);
3497
3592
  if (weightSum !== 1e4) {
3498
- console.error(chalk2.red(`Weights must sum to 10000, got ${weightSum}`));
3593
+ console.error(chalk4.red(`Weights must sum to 10000, got ${weightSum}`));
3499
3594
  process.exit(1);
3500
3595
  }
3501
3596
  console.log();
3502
- console.log(chalk2.bold("New Target Weights"));
3503
- console.log(chalk2.dim("\u2500".repeat(50)));
3597
+ console.log(chalk4.bold("New Target Weights"));
3598
+ console.log(chalk4.dim("\u2500".repeat(50)));
3504
3599
  for (let i = 0; i < allocations.length; i++) {
3505
3600
  const [, symbol] = tokenData[i];
3506
3601
  const oldPct = (Number(allocations[i].targetWeightBps) / 100).toFixed(1);
3507
3602
  const newPct = (newWeightsBps[i] / 100).toFixed(1);
3508
- const arrow = oldPct !== newPct ? chalk2.yellow("\u2192") : chalk2.dim("\u2192");
3509
- console.log(` ${chalk2.bold(symbol.padEnd(8))} ${oldPct}% ${arrow} ${newPct}%`);
3603
+ const arrow = oldPct !== newPct ? chalk4.yellow("\u2192") : chalk4.dim("\u2192");
3604
+ console.log(` ${chalk4.bold(symbol.padEnd(8))} ${oldPct}% ${arrow} ${newPct}%`);
3510
3605
  }
3511
3606
  }
3512
3607
  if (opts.dryRun) {
3513
3608
  console.log();
3514
- console.log(chalk2.yellow("Dry run \u2014 no transactions sent."));
3515
- console.log(chalk2.dim("The rebalance would:"));
3516
- console.log(chalk2.dim(" 1. Sell all current token positions back to " + assetSymbol));
3517
- console.log(chalk2.dim(" 2. Re-buy at " + (newWeightsBps ? "new" : "current") + " target weights"));
3609
+ console.log(chalk4.yellow("Dry run \u2014 no transactions sent."));
3610
+ console.log(chalk4.dim("The rebalance would:"));
3611
+ console.log(chalk4.dim(" 1. Sell all current token positions back to " + assetSymbol));
3612
+ console.log(chalk4.dim(" 2. Re-buy at " + (newWeightsBps ? "new" : "current") + " target weights"));
3518
3613
  console.log();
3519
3614
  return;
3520
3615
  }
@@ -3525,9 +3620,9 @@ function registerStrategyTemplateCommands(strategy2) {
3525
3620
  abi: PORTFOLIO_STRATEGY_ABI,
3526
3621
  functionName: "getSwapExtraData"
3527
3622
  });
3528
- const updateSpinner = ora2("Updating target weights...").start();
3623
+ const updateSpinner = ora3("Updating target weights...").start();
3529
3624
  try {
3530
- const innerData = encodeAbiParameters3(
3625
+ const innerData = encodeAbiParameters5(
3531
3626
  [{ type: "uint256[]" }, { type: "uint256" }, { type: "bytes[]" }],
3532
3627
  [newWeightsBps.map((w) => BigInt(w)), BigInt(maxSlip), swapData]
3533
3628
  );
@@ -3542,14 +3637,14 @@ function registerStrategyTemplateCommands(strategy2) {
3542
3637
  const receipt = await waitForReceipt(updateHash);
3543
3638
  if (receipt.status === "reverted") throw new Error("updateParams reverted");
3544
3639
  updateSpinner.succeed("Target weights updated");
3545
- console.log(chalk2.dim(` Tx: ${getExplorerUrl(updateHash)}`));
3640
+ console.log(chalk4.dim(` Tx: ${getExplorerUrl(updateHash)}`));
3546
3641
  } catch (err) {
3547
3642
  updateSpinner.fail("Failed to update weights");
3548
- console.error(chalk2.red(formatContractError(err)));
3643
+ console.error(chalk4.red(formatContractError(err)));
3549
3644
  process.exit(1);
3550
3645
  }
3551
3646
  }
3552
- const rebalanceSpinner = ora2("Rebalancing portfolio (sell all \u2192 re-buy at targets)...").start();
3647
+ const rebalanceSpinner = ora3("Rebalancing portfolio (sell all \u2192 re-buy at targets)...").start();
3553
3648
  try {
3554
3649
  const rebalanceHash = await writeContractWithRetry({
3555
3650
  account,
@@ -3561,44 +3656,44 @@ function registerStrategyTemplateCommands(strategy2) {
3561
3656
  const receipt = await waitForReceipt(rebalanceHash);
3562
3657
  if (receipt.status === "reverted") throw new Error("rebalance() reverted on-chain");
3563
3658
  rebalanceSpinner.succeed("Portfolio rebalanced");
3564
- console.log(chalk2.dim(` Tx: ${getExplorerUrl(rebalanceHash)}`));
3659
+ console.log(chalk4.dim(` Tx: ${getExplorerUrl(rebalanceHash)}`));
3565
3660
  } catch (err) {
3566
3661
  rebalanceSpinner.fail("Rebalance failed");
3567
- console.error(chalk2.red(formatContractError(err)));
3662
+ console.error(chalk4.red(formatContractError(err)));
3568
3663
  process.exit(1);
3569
3664
  }
3570
- const postSpinner = ora2("Reading updated allocations...").start();
3665
+ const postSpinner = ora3("Reading updated allocations...").start();
3571
3666
  const postAllocations = await publicClient.readContract({
3572
3667
  address: clone,
3573
3668
  abi: PORTFOLIO_STRATEGY_ABI,
3574
3669
  functionName: "getAllocations"
3575
3670
  });
3576
3671
  const postReads = postAllocations.map((a) => Promise.all([
3577
- publicClient.readContract({ address: a.token, abi: erc20Abi, functionName: "balanceOf", args: [clone] }),
3578
- publicClient.readContract({ address: a.token, abi: erc20Abi, functionName: "symbol" }),
3579
- publicClient.readContract({ address: a.token, abi: erc20Abi, functionName: "decimals" })
3672
+ publicClient.readContract({ address: a.token, abi: erc20Abi3, functionName: "balanceOf", args: [clone] }),
3673
+ publicClient.readContract({ address: a.token, abi: erc20Abi3, functionName: "symbol" }),
3674
+ publicClient.readContract({ address: a.token, abi: erc20Abi3, functionName: "decimals" })
3580
3675
  ]));
3581
3676
  const postData = await Promise.all(postReads);
3582
3677
  postSpinner.succeed("Updated allocations");
3583
3678
  console.log();
3584
- console.log(chalk2.bold("Post-Rebalance Allocations"));
3585
- console.log(chalk2.dim("\u2500".repeat(50)));
3679
+ console.log(chalk4.bold("Post-Rebalance Allocations"));
3680
+ console.log(chalk4.dim("\u2500".repeat(50)));
3586
3681
  for (let i = 0; i < postAllocations.length; i++) {
3587
3682
  const alloc = postAllocations[i];
3588
3683
  const [balance, symbol, decimals] = postData[i];
3589
3684
  const weightPct = (Number(alloc.targetWeightBps) / 100).toFixed(1) + "%";
3590
- const investedStr = formatUnits3(alloc.investedAmount, assetDecimals);
3685
+ const investedStr = formatUnits6(alloc.investedAmount, assetDecimals);
3591
3686
  console.log(
3592
- ` ${chalk2.bold(symbol.padEnd(8))} ${weightPct.padEnd(8)} invested: ${investedStr.padEnd(14)} bal: ${formatUnits3(balance, decimals)}`
3687
+ ` ${chalk4.bold(symbol.padEnd(8))} ${weightPct.padEnd(8)} invested: ${investedStr.padEnd(14)} bal: ${formatUnits6(balance, decimals)}`
3593
3688
  );
3594
3689
  }
3595
3690
  console.log();
3596
- console.log(chalk2.green("\u2713 Rebalance complete"));
3691
+ console.log(chalk4.green("\u2713 Rebalance complete"));
3597
3692
  console.log();
3598
3693
  } catch (err) {
3599
3694
  if (err.code === "ERR_MODULE_NOT_FOUND" || err instanceof TypeError) throw err;
3600
3695
  verifySpinner.fail("Pre-flight check failed");
3601
- console.error(chalk2.red(formatContractError(err)));
3696
+ console.error(chalk4.red(formatContractError(err)));
3602
3697
  process.exit(1);
3603
3698
  }
3604
3699
  });
@@ -3671,9 +3766,9 @@ async function getActiveFunds2(creator) {
3671
3766
  }
3672
3767
 
3673
3768
  // src/commands/venice.ts
3674
- import { formatUnits as formatUnits4, isAddress as isAddress4, parseUnits as parseUnits3 } from "viem";
3675
- import chalk3 from "chalk";
3676
- import ora3 from "ora";
3769
+ import { formatUnits as formatUnits7, isAddress as isAddress6, parseUnits as parseUnits5 } from "viem";
3770
+ import chalk5 from "chalk";
3771
+ import ora4 from "ora";
3677
3772
  import { readFileSync } from "fs";
3678
3773
  import { createInterface } from "readline/promises";
3679
3774
  function registerVeniceCommands(program2) {
@@ -3681,7 +3776,7 @@ function registerVeniceCommands(program2) {
3681
3776
  venice.command("provision").description("Self-provision a Venice API key (requires sVVV in wallet)").action(async () => {
3682
3777
  const account = getAccount();
3683
3778
  const client = getPublicClient();
3684
- const checkSpinner = ora3("Checking sVVV balance...").start();
3779
+ const checkSpinner = ora4("Checking sVVV balance...").start();
3685
3780
  try {
3686
3781
  const sVvvBalance = await client.readContract({
3687
3782
  address: VENICE().STAKING,
@@ -3691,33 +3786,33 @@ function registerVeniceCommands(program2) {
3691
3786
  });
3692
3787
  if (sVvvBalance === 0n) {
3693
3788
  checkSpinner.fail("No sVVV found in wallet");
3694
- console.log(chalk3.yellow(" Your wallet must hold staked VVV (sVVV) to provision a Venice API key."));
3695
- console.log(chalk3.yellow(" Use the VeniceInferenceStrategy via a proposal to distribute sVVV to agents."));
3789
+ console.log(chalk5.yellow(" Your wallet must hold staked VVV (sVVV) to provision a Venice API key."));
3790
+ console.log(chalk5.yellow(" Use the VeniceInferenceStrategy via a proposal to distribute sVVV to agents."));
3696
3791
  process.exit(1);
3697
3792
  }
3698
- checkSpinner.succeed(`sVVV balance: ${formatUnits4(sVvvBalance, 18)}`);
3793
+ checkSpinner.succeed(`sVVV balance: ${formatUnits7(sVvvBalance, 18)}`);
3699
3794
  } catch (err) {
3700
3795
  checkSpinner.fail("Failed to check sVVV balance");
3701
- console.error(chalk3.red(formatContractError(err)));
3796
+ console.error(chalk5.red(formatContractError(err)));
3702
3797
  process.exit(1);
3703
3798
  }
3704
- const keySpinner = ora3("Provisioning Venice API key...").start();
3799
+ const keySpinner = ora4("Provisioning Venice API key...").start();
3705
3800
  try {
3706
3801
  const apiKey = await provisionApiKey();
3707
3802
  keySpinner.succeed("Venice API key provisioned");
3708
- console.log(chalk3.dim(` Key: ${apiKey.slice(0, 8)}...${apiKey.slice(-4)}`));
3709
- console.log(chalk3.dim(" Saved to ~/.sherwood/config.json"));
3803
+ console.log(chalk5.dim(` Key: ${apiKey.slice(0, 8)}...${apiKey.slice(-4)}`));
3804
+ console.log(chalk5.dim(" Saved to ~/.sherwood/config.json"));
3710
3805
  try {
3711
- const { createVeniceProvisionAttestation, getEasScanUrl: getEasScanUrl2 } = await import("./eas-PJ3Y4NDB.js");
3806
+ const { createVeniceProvisionAttestation, getEasScanUrl: getEasScanUrl2 } = await import("./eas-32PEJETG.js");
3712
3807
  const { uid } = await createVeniceProvisionAttestation(account.address);
3713
3808
  if (uid !== "0x0000000000000000000000000000000000000000000000000000000000000000") {
3714
- console.log(chalk3.dim(` Attested: ${getEasScanUrl2(uid)}`));
3809
+ console.log(chalk5.dim(` Attested: ${getEasScanUrl2(uid)}`));
3715
3810
  }
3716
3811
  } catch {
3717
3812
  }
3718
3813
  } catch (err) {
3719
3814
  keySpinner.fail("Failed to provision API key");
3720
- console.error(chalk3.red(formatContractError(err)));
3815
+ console.error(chalk5.red(formatContractError(err)));
3721
3816
  process.exit(1);
3722
3817
  }
3723
3818
  });
@@ -3726,8 +3821,8 @@ function registerVeniceCommands(program2) {
3726
3821
  const client = getPublicClient();
3727
3822
  const chain = getChain();
3728
3823
  const veniceAddrs = VENICE();
3729
- const amount = parseUnits3(opts.amount, 18);
3730
- const balSpinner = ora3("Checking VVV balance...").start();
3824
+ const amount = parseUnits5(opts.amount, 18);
3825
+ const balSpinner = ora4("Checking VVV balance...").start();
3731
3826
  try {
3732
3827
  const vvvBalance = await client.readContract({
3733
3828
  address: veniceAddrs.VVV,
@@ -3736,16 +3831,16 @@ function registerVeniceCommands(program2) {
3736
3831
  args: [account.address]
3737
3832
  });
3738
3833
  if (vvvBalance < amount) {
3739
- balSpinner.fail(`Insufficient VVV: have ${formatUnits4(vvvBalance, 18)}, need ${opts.amount}`);
3834
+ balSpinner.fail(`Insufficient VVV: have ${formatUnits7(vvvBalance, 18)}, need ${opts.amount}`);
3740
3835
  process.exit(1);
3741
3836
  }
3742
- balSpinner.succeed(`VVV balance: ${formatUnits4(vvvBalance, 18)}`);
3837
+ balSpinner.succeed(`VVV balance: ${formatUnits7(vvvBalance, 18)}`);
3743
3838
  } catch (err) {
3744
3839
  balSpinner.fail("Failed to check VVV balance");
3745
- console.error(chalk3.red(formatContractError(err)));
3840
+ console.error(chalk5.red(formatContractError(err)));
3746
3841
  process.exit(1);
3747
3842
  }
3748
- const approveSpinner = ora3("Approving VVV for staking contract...").start();
3843
+ const approveSpinner = ora4("Approving VVV for staking contract...").start();
3749
3844
  try {
3750
3845
  const approveHash = await writeContractWithRetry({
3751
3846
  account,
@@ -3759,10 +3854,10 @@ function registerVeniceCommands(program2) {
3759
3854
  approveSpinner.succeed("VVV approved");
3760
3855
  } catch (err) {
3761
3856
  approveSpinner.fail("Approve failed");
3762
- console.error(chalk3.red(formatContractError(err)));
3857
+ console.error(chalk5.red(formatContractError(err)));
3763
3858
  process.exit(1);
3764
3859
  }
3765
- const stakeSpinner = ora3(`Staking ${opts.amount} VVV...`).start();
3860
+ const stakeSpinner = ora4(`Staking ${opts.amount} VVV...`).start();
3766
3861
  try {
3767
3862
  const stakeHash = await writeContractWithRetry({
3768
3863
  account,
@@ -3779,11 +3874,11 @@ function registerVeniceCommands(program2) {
3779
3874
  functionName: "balanceOf",
3780
3875
  args: [account.address]
3781
3876
  });
3782
- stakeSpinner.succeed(`Staked ${opts.amount} VVV \u2192 ${formatUnits4(sVvvBalance, 18)} sVVV`);
3783
- console.log(chalk3.dim(" You can now run: sherwood venice provision"));
3877
+ stakeSpinner.succeed(`Staked ${opts.amount} VVV \u2192 ${formatUnits7(sVvvBalance, 18)} sVVV`);
3878
+ console.log(chalk5.dim(" You can now run: sherwood venice provision"));
3784
3879
  } catch (err) {
3785
3880
  stakeSpinner.fail("Stake failed");
3786
- console.error(chalk3.red(formatContractError(err)));
3881
+ console.error(chalk5.red(formatContractError(err)));
3787
3882
  process.exit(1);
3788
3883
  }
3789
3884
  });
@@ -3792,13 +3887,13 @@ function registerVeniceCommands(program2) {
3792
3887
  const client = getPublicClient();
3793
3888
  const chain = getChain();
3794
3889
  const { STAKING, DIEM } = VENICE();
3795
- const amount = parseUnits3(opts.amount, 18);
3890
+ const amount = parseUnits5(opts.amount, 18);
3796
3891
  const slippageBps = BigInt(opts.slippage ?? "500");
3797
3892
  if (slippageBps < 0n || slippageBps > 10000n) {
3798
- console.error(chalk3.red(`Invalid slippage bps: ${opts.slippage} (must be 0\u201310000)`));
3893
+ console.error(chalk5.red(`Invalid slippage bps: ${opts.slippage} (must be 0\u201310000)`));
3799
3894
  process.exit(1);
3800
3895
  }
3801
- const balSpinner = ora3("Checking sVVV balance...").start();
3896
+ const balSpinner = ora4("Checking sVVV balance...").start();
3802
3897
  let sVvvBalance;
3803
3898
  try {
3804
3899
  sVvvBalance = await client.readContract({
@@ -3809,18 +3904,18 @@ function registerVeniceCommands(program2) {
3809
3904
  });
3810
3905
  } catch (err) {
3811
3906
  balSpinner.fail("Failed to read sVVV balance");
3812
- console.error(chalk3.red(formatContractError(err)));
3907
+ console.error(chalk5.red(formatContractError(err)));
3813
3908
  process.exit(1);
3814
3909
  }
3815
3910
  if (sVvvBalance < amount) {
3816
3911
  balSpinner.fail(
3817
- `Insufficient sVVV: have ${formatUnits4(sVvvBalance, 18)}, need ${opts.amount}`
3912
+ `Insufficient sVVV: have ${formatUnits7(sVvvBalance, 18)}, need ${opts.amount}`
3818
3913
  );
3819
- console.log(chalk3.yellow(" Stake VVV first (see VeniceInferenceStrategy proposal flow)."));
3914
+ console.log(chalk5.yellow(" Stake VVV first (see VeniceInferenceStrategy proposal flow)."));
3820
3915
  process.exit(1);
3821
3916
  }
3822
- balSpinner.succeed(`sVVV balance: ${formatUnits4(sVvvBalance, 18)}`);
3823
- const quoteSpinner = ora3("Quoting DIEM output...").start();
3917
+ balSpinner.succeed(`sVVV balance: ${formatUnits7(sVvvBalance, 18)}`);
3918
+ const quoteSpinner = ora4("Quoting DIEM output...").start();
3824
3919
  let expected;
3825
3920
  try {
3826
3921
  expected = await client.readContract({
@@ -3831,7 +3926,7 @@ function registerVeniceCommands(program2) {
3831
3926
  });
3832
3927
  } catch (err) {
3833
3928
  quoteSpinner.fail("Failed to quote DIEM output");
3834
- console.error(chalk3.red(formatContractError(err)));
3929
+ console.error(chalk5.red(formatContractError(err)));
3835
3930
  process.exit(1);
3836
3931
  }
3837
3932
  if (expected === 0n) {
@@ -3840,9 +3935,9 @@ function registerVeniceCommands(program2) {
3840
3935
  }
3841
3936
  const minOut = expected * (10000n - slippageBps) / 10000n;
3842
3937
  quoteSpinner.succeed(
3843
- `Expected: ${formatUnits4(expected, 18)} DIEM (minOut @ ${slippageBps}bps: ${formatUnits4(minOut, 18)})`
3938
+ `Expected: ${formatUnits7(expected, 18)} DIEM (minOut @ ${slippageBps}bps: ${formatUnits7(minOut, 18)})`
3844
3939
  );
3845
- const MIN_SPENDABLE_DIEM = parseUnits3("0.1", 18);
3940
+ const MIN_SPENDABLE_DIEM = parseUnits5("0.1", 18);
3846
3941
  let currentDiem = 0n;
3847
3942
  try {
3848
3943
  currentDiem = await client.readContract({
@@ -3858,27 +3953,27 @@ function registerVeniceCommands(program2) {
3858
3953
  const shortfall = MIN_SPENDABLE_DIEM - projectedDiem;
3859
3954
  const sVvvNeeded = (amount * shortfall + expected - 1n) / expected;
3860
3955
  console.log();
3861
- console.log(chalk3.red(" \u26A0 Venice requires \u2265 0.1 DIEM minimum before ANY DIEM credit"));
3862
- console.log(chalk3.red(" becomes spendable on inference calls."));
3863
- console.log(chalk3.red(` Projected DIEM after mint: ${formatUnits4(projectedDiem, 18)} (short by ${formatUnits4(shortfall, 18)})`));
3864
- console.log(chalk3.red(` Approx additional sVVV needed: ${formatUnits4(sVvvNeeded, 18)}`));
3865
- console.log(chalk3.dim(" Below threshold, this DIEM sits idle \u2014 consider acquiring"));
3866
- console.log(chalk3.dim(" more sVVV first, or use x402 USDC pay-per-request."));
3956
+ console.log(chalk5.red(" \u26A0 Venice requires \u2265 0.1 DIEM minimum before ANY DIEM credit"));
3957
+ console.log(chalk5.red(" becomes spendable on inference calls."));
3958
+ console.log(chalk5.red(` Projected DIEM after mint: ${formatUnits7(projectedDiem, 18)} (short by ${formatUnits7(shortfall, 18)})`));
3959
+ console.log(chalk5.red(` Approx additional sVVV needed: ${formatUnits7(sVvvNeeded, 18)}`));
3960
+ console.log(chalk5.dim(" Below threshold, this DIEM sits idle \u2014 consider acquiring"));
3961
+ console.log(chalk5.dim(" more sVVV first, or use x402 USDC pay-per-request."));
3867
3962
  }
3868
3963
  console.log();
3869
- console.log(chalk3.yellow(" \u26A0 Locked sVVV cannot be unstaked directly. To recover it you must"));
3870
- console.log(chalk3.yellow(" first call `staking.burnDiem(amount)` (burns DIEM, unlocks sVVV"));
3871
- console.log(chalk3.yellow(" at your average mint rate), then `initiateUnstake` + wait the"));
3872
- console.log(chalk3.yellow(" 7-day staking cooldown, then `finalizeUnstake`."));
3873
- console.log(chalk3.dim(" x402 alternative (pay-per-request in USDC, no DIEM lock):"));
3874
- console.log(chalk3.dim(" https://docs.venice.ai/overview/guides/generating-api-key-agent#paying-for-inference"));
3964
+ console.log(chalk5.yellow(" \u26A0 Locked sVVV cannot be unstaked directly. To recover it you must"));
3965
+ console.log(chalk5.yellow(" first call `staking.burnDiem(amount)` (burns DIEM, unlocks sVVV"));
3966
+ console.log(chalk5.yellow(" at your average mint rate), then `initiateUnstake` + wait the"));
3967
+ console.log(chalk5.yellow(" 7-day staking cooldown, then `finalizeUnstake`."));
3968
+ console.log(chalk5.dim(" x402 alternative (pay-per-request in USDC, no DIEM lock):"));
3969
+ console.log(chalk5.dim(" https://docs.venice.ai/overview/guides/generating-api-key-agent#paying-for-inference"));
3875
3970
  console.log();
3876
3971
  if (!opts.yes) {
3877
3972
  const rl = createInterface({ input: process.stdin, output: process.stdout });
3878
3973
  try {
3879
3974
  const answer = (await rl.question(` Lock ${opts.amount} sVVV for DIEM credits? [y/N] `)).trim().toLowerCase();
3880
3975
  if (answer !== "y" && answer !== "yes") {
3881
- console.log(chalk3.dim(" Aborted."));
3976
+ console.log(chalk5.dim(" Aborted."));
3882
3977
  process.exit(0);
3883
3978
  }
3884
3979
  } finally {
@@ -3886,7 +3981,7 @@ function registerVeniceCommands(program2) {
3886
3981
  }
3887
3982
  }
3888
3983
  const diemBefore = currentDiem;
3889
- const mintSpinner = ora3(`Minting DIEM from ${opts.amount} sVVV...`).start();
3984
+ const mintSpinner = ora4(`Minting DIEM from ${opts.amount} sVVV...`).start();
3890
3985
  try {
3891
3986
  const hash = await writeContractWithRetry({
3892
3987
  account,
@@ -3905,28 +4000,28 @@ function registerVeniceCommands(program2) {
3905
4000
  });
3906
4001
  const delta = diemAfter - diemBefore;
3907
4002
  mintSpinner.succeed(
3908
- `Minted ${formatUnits4(delta > 0n ? delta : diemAfter, 18)} DIEM` + (delta > 0n ? ` (balance: ${formatUnits4(diemAfter, 18)})` : "")
4003
+ `Minted ${formatUnits7(delta > 0n ? delta : diemAfter, 18)} DIEM` + (delta > 0n ? ` (balance: ${formatUnits7(diemAfter, 18)})` : "")
3909
4004
  );
3910
- console.log(chalk3.dim(` Tx: ${hash}`));
3911
- console.log(chalk3.yellow(" Note: Venice requires \u2265 0.1 DIEM to spend ANY DIEM credit, and"));
3912
- console.log(chalk3.yellow(" refreshes daily allocation at 00:00 UTC. Below threshold,"));
3913
- console.log(chalk3.yellow(" inference will continue to 402."));
3914
- console.log(chalk3.dim(' Once over threshold: sherwood venice infer --model <id> --prompt "..."'));
4005
+ console.log(chalk5.dim(` Tx: ${hash}`));
4006
+ console.log(chalk5.yellow(" Note: Venice requires \u2265 0.1 DIEM to spend ANY DIEM credit, and"));
4007
+ console.log(chalk5.yellow(" refreshes daily allocation at 00:00 UTC. Below threshold,"));
4008
+ console.log(chalk5.yellow(" inference will continue to 402."));
4009
+ console.log(chalk5.dim(' Once over threshold: sherwood venice infer --model <id> --prompt "..."'));
3915
4010
  } catch (err) {
3916
4011
  mintSpinner.fail("mintDiem failed");
3917
- console.error(chalk3.red(formatContractError(err)));
4012
+ console.error(chalk5.red(formatContractError(err)));
3918
4013
  process.exit(1);
3919
4014
  }
3920
4015
  });
3921
4016
  venice.command("status").description("Show Venice inference status: sVVV balances, DIEM, API key").requiredOption("--vault <address>", "Vault address").action(async (opts) => {
3922
4017
  const vaultAddress = opts.vault;
3923
- if (!isAddress4(vaultAddress)) {
3924
- console.error(chalk3.red(`Invalid vault address: ${opts.vault}`));
4018
+ if (!isAddress6(vaultAddress)) {
4019
+ console.error(chalk5.red(`Invalid vault address: ${opts.vault}`));
3925
4020
  process.exit(1);
3926
4021
  }
3927
4022
  const client = getPublicClient();
3928
4023
  const account = getAccount();
3929
- const spinner = ora3("Loading Venice status...").start();
4024
+ const spinner = ora4("Loading Venice status...").start();
3930
4025
  try {
3931
4026
  const [assetAddress, totalDeposited, agents] = await Promise.all([
3932
4027
  client.readContract({ address: vaultAddress, abi: SYNDICATE_VAULT_ABI, functionName: "asset" }),
@@ -3980,34 +4075,34 @@ function registerVeniceCommands(program2) {
3980
4075
  spinner.stop();
3981
4076
  const profit = assetBalance > totalDeposited ? assetBalance - totalDeposited : 0n;
3982
4077
  console.log();
3983
- console.log(chalk3.bold("Venice Inference Status"));
3984
- console.log(chalk3.dim("\u2500".repeat(50)));
3985
- console.log(chalk3.bold("\n Vault"));
3986
- console.log(` Profit available: ${formatUnits4(profit, assetDecimals)} ${assetSymbol}`);
3987
- console.log(` VVV (unstaked): ${formatUnits4(vaultVvvBalance, 18)}`);
3988
- console.log(chalk3.bold("\n Agent sVVV Balances"));
4078
+ console.log(chalk5.bold("Venice Inference Status"));
4079
+ console.log(chalk5.dim("\u2500".repeat(50)));
4080
+ console.log(chalk5.bold("\n Vault"));
4081
+ console.log(` Profit available: ${formatUnits7(profit, assetDecimals)} ${assetSymbol}`);
4082
+ console.log(` VVV (unstaked): ${formatUnits7(vaultVvvBalance, 18)}`);
4083
+ console.log(chalk5.bold("\n Agent sVVV Balances"));
3989
4084
  for (const { agent, balance } of agentBalances) {
3990
4085
  const isMe = agent.toLowerCase() === account.address.toLowerCase();
3991
- const label = isMe ? chalk3.green(`${agent} (you)`) : agent;
3992
- console.log(` ${label}: ${formatUnits4(balance, 18)} sVVV`);
3993
- }
3994
- console.log(chalk3.bold("\n Your Wallet"));
3995
- console.log(` sVVV: ${formatUnits4(mySvvv, 18)}`);
3996
- console.log(` Pending rewards: ${formatUnits4(myPending, 18)} VVV`);
3997
- console.log(` DIEM (credits): ${formatUnits4(myDiem, 18)}`);
3998
- console.log(chalk3.dim(" (mint via `sherwood venice mint-diem --amount <sVVV>`)"));
3999
- console.log(chalk3.bold("\n Venice API"));
4000
- console.log(` Key: ${apiKey ? `${apiKey.slice(0, 8)}...${apiKey.slice(-4)}` : chalk3.dim("not provisioned")}`);
4001
- console.log(` Status: ${apiKeyValid ? chalk3.green("valid") : chalk3.red("invalid/missing")}`);
4086
+ const label = isMe ? chalk5.green(`${agent} (you)`) : agent;
4087
+ console.log(` ${label}: ${formatUnits7(balance, 18)} sVVV`);
4088
+ }
4089
+ console.log(chalk5.bold("\n Your Wallet"));
4090
+ console.log(` sVVV: ${formatUnits7(mySvvv, 18)}`);
4091
+ console.log(` Pending rewards: ${formatUnits7(myPending, 18)} VVV`);
4092
+ console.log(` DIEM (credits): ${formatUnits7(myDiem, 18)}`);
4093
+ console.log(chalk5.dim(" (mint via `sherwood venice mint-diem --amount <sVVV>`)"));
4094
+ console.log(chalk5.bold("\n Venice API"));
4095
+ console.log(` Key: ${apiKey ? `${apiKey.slice(0, 8)}...${apiKey.slice(-4)}` : chalk5.dim("not provisioned")}`);
4096
+ console.log(` Status: ${apiKeyValid ? chalk5.green("valid") : chalk5.red("invalid/missing")}`);
4002
4097
  console.log();
4003
4098
  } catch (err) {
4004
4099
  spinner.fail("Failed to load status");
4005
- console.error(chalk3.red(formatContractError(err)));
4100
+ console.error(chalk5.red(formatContractError(err)));
4006
4101
  process.exit(1);
4007
4102
  }
4008
4103
  });
4009
4104
  venice.command("models").description("List available Venice inference models").action(async () => {
4010
- const spinner = ora3("Fetching Venice models...").start();
4105
+ const spinner = ora4("Fetching Venice models...").start();
4011
4106
  try {
4012
4107
  const models = await listModels();
4013
4108
  spinner.succeed(`${models.length} models available`);
@@ -4018,7 +4113,7 @@ function registerVeniceCommands(program2) {
4018
4113
  console.log();
4019
4114
  } catch (err) {
4020
4115
  spinner.fail("Failed to list models");
4021
- console.error(chalk3.red(formatContractError(err)));
4116
+ console.error(chalk5.red(formatContractError(err)));
4022
4117
  process.exit(1);
4023
4118
  }
4024
4119
  });
@@ -4038,13 +4133,13 @@ ${data}
4038
4133
 
4039
4134
  ${opts.prompt}`;
4040
4135
  } catch (err) {
4041
- console.error(chalk3.red(`Failed to read data file: ${opts.data}`));
4042
- console.error(chalk3.red(formatContractError(err)));
4136
+ console.error(chalk5.red(`Failed to read data file: ${opts.data}`));
4137
+ console.error(chalk5.red(formatContractError(err)));
4043
4138
  process.exit(1);
4044
4139
  }
4045
4140
  }
4046
4141
  messages.push({ role: "user", content: userContent });
4047
- const spinner = ora3(`Running inference (${opts.model})...`).start();
4142
+ const spinner = ora4(`Running inference (${opts.model})...`).start();
4048
4143
  try {
4049
4144
  const result = await chatCompletion({
4050
4145
  model: opts.model,
@@ -4061,13 +4156,13 @@ ${opts.prompt}`;
4061
4156
  console.log();
4062
4157
  console.log(result.content);
4063
4158
  console.log();
4064
- console.log(chalk3.dim(`Model: ${result.model} | Tokens: ${result.usage.promptTokens} in, ${result.usage.completionTokens} out, ${result.usage.totalTokens} total`));
4159
+ console.log(chalk5.dim(`Model: ${result.model} | Tokens: ${result.usage.promptTokens} in, ${result.usage.completionTokens} out, ${result.usage.totalTokens} total`));
4065
4160
  }
4066
4161
  try {
4067
- const { createVeniceInferenceAttestation, getEasScanUrl: getEasScanUrl2 } = await import("./eas-PJ3Y4NDB.js");
4162
+ const { createVeniceInferenceAttestation, getEasScanUrl: getEasScanUrl2 } = await import("./eas-32PEJETG.js");
4068
4163
  const { keccak256: keccak2563, toHex, isAddress: isAddr } = await import("viem");
4069
4164
  const { getChainContracts: getChainContracts2 } = await import("./config-ZGFS4I7K.js");
4070
- const { getChain: getActiveChain } = await import("./network-RI54LT2Y.js");
4165
+ const { getChain: getActiveChain } = await import("./network-HCFCNZUI.js");
4071
4166
  const vaultRecipient = opts.vault && isAddr(opts.vault) ? opts.vault : getChainContracts2(getActiveChain().id).vault;
4072
4167
  const promptHash = keccak2563(toHex(userContent)).slice(0, 18);
4073
4168
  const { uid } = await createVeniceInferenceAttestation(
@@ -4078,27 +4173,27 @@ ${opts.prompt}`;
4078
4173
  vaultRecipient
4079
4174
  );
4080
4175
  if (uid !== "0x0000000000000000000000000000000000000000000000000000000000000000") {
4081
- console.log(chalk3.dim(`Attested: ${getEasScanUrl2(uid)}`));
4176
+ console.log(chalk5.dim(`Attested: ${getEasScanUrl2(uid)}`));
4082
4177
  }
4083
4178
  } catch {
4084
4179
  }
4085
4180
  } catch (err) {
4086
4181
  spinner.fail("Inference failed");
4087
- console.error(chalk3.red(formatContractError(err)));
4182
+ console.error(chalk5.red(formatContractError(err)));
4088
4183
  process.exit(1);
4089
4184
  }
4090
4185
  });
4091
4186
  }
4092
4187
 
4093
4188
  // src/commands/allowance.ts
4094
- import { parseUnits as parseUnits5, formatUnits as formatUnits5, isAddress as isAddress5 } from "viem";
4095
- import chalk4 from "chalk";
4096
- import ora4 from "ora";
4189
+ import { parseUnits as parseUnits7, formatUnits as formatUnits8, isAddress as isAddress7 } from "viem";
4190
+ import chalk6 from "chalk";
4191
+ import ora5 from "ora";
4097
4192
 
4098
4193
  // src/strategies/allowance-disburse.ts
4099
- import { encodeFunctionData as encodeFunctionData8, parseUnits as parseUnits4 } from "viem";
4194
+ import { encodeFunctionData as encodeFunctionData8, parseUnits as parseUnits6 } from "viem";
4100
4195
  function buildDisburseBatch(config, vaultAddress, agents, assetAddress, assetDecimals, minUsdc, swapPath) {
4101
- const assetAmount = parseUnits4(config.amount, assetDecimals);
4196
+ const assetAmount = parseUnits6(config.amount, assetDecimals);
4102
4197
  const isUsdc = assetAddress.toLowerCase() === TOKENS().USDC.toLowerCase();
4103
4198
  const isWeth = assetAddress.toLowerCase() === TOKENS().WETH.toLowerCase();
4104
4199
  const calls = [];
@@ -4172,18 +4267,18 @@ function registerAllowanceCommands(program2) {
4172
4267
  const allowance = program2.command("allowance").description("Disburse vault profits to agent wallets");
4173
4268
  allowance.command("disburse").description("Swap vault profits \u2192 USDC \u2192 distribute to all agent operator wallets").requiredOption("--vault <address>", "Vault address").requiredOption("--amount <amount>", "Deposit token amount to convert & distribute (e.g. 500)").option("--fee <tier>", "Fee tier for asset \u2192 USDC swap (500, 3000, 10000)", "3000").option("--slippage <bps>", "Slippage tolerance in bps", "100").option("--execute", "Unavailable \u2014 the vault has no owner-direct batch path (V-C3); fails with guidance", false).action(async (opts) => {
4174
4269
  const vaultAddress = opts.vault;
4175
- if (!isAddress5(vaultAddress)) {
4176
- console.error(chalk4.red(`Invalid vault address: ${opts.vault}`));
4270
+ if (!isAddress7(vaultAddress)) {
4271
+ console.error(chalk6.red(`Invalid vault address: ${opts.vault}`));
4177
4272
  process.exit(1);
4178
4273
  }
4179
4274
  if (opts.execute) {
4180
4275
  console.error(
4181
- chalk4.red(
4276
+ chalk6.red(
4182
4277
  "allowance disburse --execute is not available: the vault no longer exposes owner-direct batch execution (executeBatch was removed on-chain, V-C3)."
4183
4278
  )
4184
4279
  );
4185
4280
  console.error(
4186
- chalk4.dim(
4281
+ chalk6.dim(
4187
4282
  "Vault funds can only move through governor-approved batches (executeGovernorBatch via the proposal lifecycle). Run without --execute to simulate the batch."
4188
4283
  )
4189
4284
  );
@@ -4191,12 +4286,12 @@ function registerAllowanceCommands(program2) {
4191
4286
  }
4192
4287
  const fee = Number(opts.fee);
4193
4288
  if (!VALID_FEES.includes(fee)) {
4194
- console.error(chalk4.red(`Invalid fee tier. Valid: ${VALID_FEES.join(", ")}`));
4289
+ console.error(chalk6.red(`Invalid fee tier. Valid: ${VALID_FEES.join(", ")}`));
4195
4290
  process.exit(1);
4196
4291
  }
4197
4292
  const slippageBps = Number(opts.slippage);
4198
4293
  const client = getPublicClient();
4199
- const spinner = ora4("Reading vault state...").start();
4294
+ const spinner = ora5("Reading vault state...").start();
4200
4295
  let assetAddress;
4201
4296
  let assetDecimals;
4202
4297
  let assetSymbol;
@@ -4217,25 +4312,25 @@ function registerAllowanceCommands(program2) {
4217
4312
  spinner.stop();
4218
4313
  } catch (err) {
4219
4314
  spinner.fail("Failed to read vault state");
4220
- console.error(chalk4.red(formatContractError(err)));
4315
+ console.error(chalk6.red(formatContractError(err)));
4221
4316
  process.exit(1);
4222
4317
  }
4223
4318
  if (agents.length === 0) {
4224
- console.error(chalk4.red("No agents registered in vault. Register agents first."));
4319
+ console.error(chalk6.red("No agents registered in vault. Register agents first."));
4225
4320
  process.exit(1);
4226
4321
  }
4227
- const requestedAmount = parseUnits5(opts.amount, assetDecimals);
4322
+ const requestedAmount = parseUnits7(opts.amount, assetDecimals);
4228
4323
  const profit = assetBalance > totalDeposited ? assetBalance - totalDeposited : 0n;
4229
4324
  const isUsdc = assetAddress.toLowerCase() === TOKENS().USDC.toLowerCase();
4230
4325
  const isWeth = assetAddress.toLowerCase() === TOKENS().WETH.toLowerCase();
4231
4326
  console.log();
4232
- console.log(chalk4.bold("Allowance Disburse"));
4233
- console.log(chalk4.dim("\u2500".repeat(40)));
4327
+ console.log(chalk6.bold("Allowance Disburse"));
4328
+ console.log(chalk6.dim("\u2500".repeat(40)));
4234
4329
  console.log(` Asset: ${assetSymbol} (${assetDecimals} decimals)`);
4235
4330
  console.log(` Amount: ${opts.amount} ${assetSymbol}`);
4236
- console.log(` Vault balance: ${formatUnits5(assetBalance, assetDecimals)} ${assetSymbol}`);
4237
- console.log(` Net deposited (est.): ${formatUnits5(totalDeposited, assetDecimals)} ${assetSymbol}`);
4238
- console.log(` Profit: ${formatUnits5(profit, assetDecimals)} ${assetSymbol}`);
4331
+ console.log(` Vault balance: ${formatUnits8(assetBalance, assetDecimals)} ${assetSymbol}`);
4332
+ console.log(` Net deposited (est.): ${formatUnits8(totalDeposited, assetDecimals)} ${assetSymbol}`);
4333
+ console.log(` Profit: ${formatUnits8(profit, assetDecimals)} ${assetSymbol}`);
4239
4334
  console.log(` Agents: ${agents.length} (USDC will be split equally)`);
4240
4335
  if (!isUsdc) {
4241
4336
  console.log(` Routing: ${isWeth ? `WETH \u2192 USDC (fee ${fee})` : `${assetSymbol} \u2192 WETH \u2192 USDC (fee ${fee})`}`);
@@ -4244,8 +4339,8 @@ function registerAllowanceCommands(program2) {
4244
4339
  console.log(` Vault: ${vaultAddress}`);
4245
4340
  console.log();
4246
4341
  if (requestedAmount > profit) {
4247
- console.warn(chalk4.yellow(` Warning: amount (${opts.amount}) exceeds available profit (${formatUnits5(profit, assetDecimals)})`));
4248
- console.warn(chalk4.yellow(" This will use deposited capital, not just profits."));
4342
+ console.warn(chalk6.yellow(` Warning: amount (${opts.amount}) exceeds available profit (${formatUnits8(profit, assetDecimals)})`));
4343
+ console.warn(chalk6.yellow(" This will use deposited capital, not just profits."));
4249
4344
  console.log();
4250
4345
  }
4251
4346
  let minUsdc;
@@ -4253,7 +4348,7 @@ function registerAllowanceCommands(program2) {
4253
4348
  if (isUsdc) {
4254
4349
  minUsdc = requestedAmount;
4255
4350
  } else {
4256
- const quoteSpinner = ora4("Fetching Uniswap quote...").start();
4351
+ const quoteSpinner = ora5("Fetching Uniswap quote...").start();
4257
4352
  try {
4258
4353
  let amountOut;
4259
4354
  if (isWeth) {
@@ -4278,17 +4373,17 @@ function registerAllowanceCommands(program2) {
4278
4373
  }
4279
4374
  minUsdc = applySlippage(amountOut, slippageBps);
4280
4375
  quoteSpinner.succeed(
4281
- `Quote: ${formatUnits5(amountOut, 6)} USDC (min: ${formatUnits5(minUsdc, 6)}, per agent: ${formatUnits5(minUsdc / BigInt(agents.length), 6)})`
4376
+ `Quote: ${formatUnits8(amountOut, 6)} USDC (min: ${formatUnits8(minUsdc, 6)}, per agent: ${formatUnits8(minUsdc / BigInt(agents.length), 6)})`
4282
4377
  );
4283
4378
  } catch (err) {
4284
4379
  quoteSpinner.fail("Failed to fetch quote");
4285
- console.error(chalk4.red(formatContractError(err)));
4380
+ console.error(chalk6.red(formatContractError(err)));
4286
4381
  process.exit(1);
4287
4382
  }
4288
4383
  }
4289
4384
  const perAgent = minUsdc / BigInt(agents.length);
4290
4385
  if (isUsdc) {
4291
- console.log(chalk4.dim(` Per agent: ${formatUnits5(perAgent, 6)} USDC`));
4386
+ console.log(chalk6.dim(` Per agent: ${formatUnits8(perAgent, 6)} USDC`));
4292
4387
  console.log();
4293
4388
  }
4294
4389
  const config = {
@@ -4298,24 +4393,24 @@ function registerAllowanceCommands(program2) {
4298
4393
  };
4299
4394
  const calls = buildDisburseBatch(config, vaultAddress, agents, assetAddress, assetDecimals, minUsdc, swapPath);
4300
4395
  console.log();
4301
- console.log(chalk4.bold(`Batch calls (${calls.length}):`));
4396
+ console.log(chalk6.bold(`Batch calls (${calls.length}):`));
4302
4397
  console.log(formatBatch(calls));
4303
4398
  console.log();
4304
4399
  console.log();
4305
4400
  console.log(
4306
- chalk4.yellow(
4401
+ chalk6.yellow(
4307
4402
  "Dry run complete. On-chain execution is unavailable \u2014 the vault has no owner-direct batch path (V-C3); disbursement requires a governor proposal."
4308
4403
  )
4309
4404
  );
4310
4405
  });
4311
4406
  allowance.command("status").description("Show vault profit and agent USDC balances").requiredOption("--vault <address>", "Vault address").action(async (opts) => {
4312
4407
  const vaultAddress = opts.vault;
4313
- if (!isAddress5(vaultAddress)) {
4314
- console.error(chalk4.red(`Invalid vault address: ${opts.vault}`));
4408
+ if (!isAddress7(vaultAddress)) {
4409
+ console.error(chalk6.red(`Invalid vault address: ${opts.vault}`));
4315
4410
  process.exit(1);
4316
4411
  }
4317
4412
  const client = getPublicClient();
4318
- const spinner = ora4("Loading allowance status...").start();
4413
+ const spinner = ora5("Loading allowance status...").start();
4319
4414
  try {
4320
4415
  const [assetAddress, totalDeposited, agents] = await Promise.all([
4321
4416
  client.readContract({ address: vaultAddress, abi: SYNDICATE_VAULT_ABI, functionName: "asset" }),
@@ -4342,23 +4437,23 @@ function registerAllowanceCommands(program2) {
4342
4437
  const profit = assetBalance > totalDeposited ? assetBalance - totalDeposited : 0n;
4343
4438
  const account = getAccount();
4344
4439
  console.log();
4345
- console.log(chalk4.bold("Allowance Status"));
4346
- console.log(chalk4.dim("\u2500".repeat(50)));
4347
- console.log(chalk4.bold("\n Vault"));
4440
+ console.log(chalk6.bold("Allowance Status"));
4441
+ console.log(chalk6.dim("\u2500".repeat(50)));
4442
+ console.log(chalk6.bold("\n Vault"));
4348
4443
  console.log(` Asset: ${assetSymbol}`);
4349
- console.log(` Balance: ${formatUnits5(assetBalance, assetDecimals)} ${assetSymbol}`);
4350
- console.log(` Net deposited (est.): ${formatUnits5(totalDeposited, assetDecimals)} ${assetSymbol}`);
4351
- console.log(` Profit: ${formatUnits5(profit, assetDecimals)} ${assetSymbol}`);
4352
- console.log(chalk4.bold("\n Agent USDC Balances"));
4444
+ console.log(` Balance: ${formatUnits8(assetBalance, assetDecimals)} ${assetSymbol}`);
4445
+ console.log(` Net deposited (est.): ${formatUnits8(totalDeposited, assetDecimals)} ${assetSymbol}`);
4446
+ console.log(` Profit: ${formatUnits8(profit, assetDecimals)} ${assetSymbol}`);
4447
+ console.log(chalk6.bold("\n Agent USDC Balances"));
4353
4448
  for (const { agent, balance } of agentBalances) {
4354
4449
  const isMe = agent.toLowerCase() === account.address.toLowerCase();
4355
- const label = isMe ? chalk4.green(`${agent} (you)`) : agent;
4356
- console.log(` ${label}: ${formatUnits5(balance, 6)} USDC`);
4450
+ const label = isMe ? chalk6.green(`${agent} (you)`) : agent;
4451
+ console.log(` ${label}: ${formatUnits8(balance, 6)} USDC`);
4357
4452
  }
4358
4453
  console.log();
4359
4454
  } catch (err) {
4360
4455
  spinner.fail("Failed to load status");
4361
- console.error(chalk4.red(formatContractError(err)));
4456
+ console.error(chalk6.red(formatContractError(err)));
4362
4457
  process.exit(1);
4363
4458
  }
4364
4459
  });
@@ -4366,14 +4461,14 @@ function registerAllowanceCommands(program2) {
4366
4461
 
4367
4462
  // src/commands/identity.ts
4368
4463
  import { generatePrivateKey } from "viem/accounts";
4369
- import chalk5 from "chalk";
4370
- import ora5 from "ora";
4464
+ import chalk7 from "chalk";
4465
+ import ora6 from "ora";
4371
4466
  import { SDK } from "agent0-sdk";
4372
4467
 
4373
4468
  // src/lib/virtuals.ts
4374
4469
  import { execFile } from "child_process";
4375
4470
  import { promisify } from "util";
4376
- import { createPublicClient, http, recoverMessageAddress, isAddress as isAddress6 } from "viem";
4471
+ import { createPublicClient, http, recoverMessageAddress, isAddress as isAddress8 } from "viem";
4377
4472
  import { base, baseSepolia } from "viem/chains";
4378
4473
  var execFileAsync = promisify(execFile);
4379
4474
  var BINDING_VERSION = "v1";
@@ -4460,7 +4555,7 @@ function parseVidTag(message) {
4460
4555
  if (message.indexOf("[vid:") !== message.lastIndexOf("[vid:")) return null;
4461
4556
  const match = message.match(VID_TAG_RE);
4462
4557
  if (!match) return null;
4463
- if (!isAddress6(match[4])) return null;
4558
+ if (!isAddress8(match[4])) return null;
4464
4559
  return {
4465
4560
  version: match[1],
4466
4561
  issuingChainId: parseInt(match[2], 10),
@@ -4567,7 +4662,7 @@ async function acpWalletAddress() {
4567
4662
  if (!json) return null;
4568
4663
  for (const key of ["address", "evmAddress", "evm", "wallet"]) {
4569
4664
  const value = json[key];
4570
- if (typeof value === "string" && isAddress6(value)) return value;
4665
+ if (typeof value === "string" && isAddress8(value)) return value;
4571
4666
  }
4572
4667
  return null;
4573
4668
  }
@@ -4626,11 +4721,11 @@ function registerIdentityCommands(program2) {
4626
4721
  const account = getAccount();
4627
4722
  const existingId = getAgentId();
4628
4723
  if (existingId) {
4629
- console.log(chalk5.yellow(`You already have an agent identity saved: #${existingId}`));
4630
- console.log(chalk5.dim(" Minting a new one anyway. The old ID is not affected."));
4724
+ console.log(chalk7.yellow(`You already have an agent identity saved: #${existingId}`));
4725
+ console.log(chalk7.dim(" Minting a new one anyway. The old ID is not affected."));
4631
4726
  console.log();
4632
4727
  }
4633
- const spinner = ora5("Initializing Agent0 SDK...").start();
4728
+ const spinner = ora6("Initializing Agent0 SDK...").start();
4634
4729
  try {
4635
4730
  const sdk = getAgent0SDK();
4636
4731
  spinner.text = "Creating agent profile...";
@@ -4642,22 +4737,22 @@ function registerIdentityCommands(program2) {
4642
4737
  const agentId = agent.agentId;
4643
4738
  if (!agentId) {
4644
4739
  spinner.warn("Identity registered but could not read agentId");
4645
- console.log(chalk5.dim(" Check the transaction on the explorer."));
4740
+ console.log(chalk7.dim(" Check the transaction on the explorer."));
4646
4741
  return;
4647
4742
  }
4648
4743
  const tokenId = Number(agentId.includes(":") ? agentId.split(":")[1] : agentId);
4649
4744
  setAgentId(tokenId);
4650
4745
  spinner.succeed(`Agent identity registered: #${tokenId}`);
4651
- console.log(chalk5.dim(` Agent0 ID: ${agentId}`));
4652
- console.log(chalk5.dim(` Name: ${opts.name}`));
4653
- console.log(chalk5.dim(` Owner: ${account.address}`));
4654
- console.log(chalk5.dim(` Saved to ~/.sherwood/config.json`));
4746
+ console.log(chalk7.dim(` Agent0 ID: ${agentId}`));
4747
+ console.log(chalk7.dim(` Name: ${opts.name}`));
4748
+ console.log(chalk7.dim(` Owner: ${account.address}`));
4749
+ console.log(chalk7.dim(` Saved to ~/.sherwood/config.json`));
4655
4750
  console.log();
4656
- console.log(chalk5.green("You can now create funds:"));
4657
- console.log(chalk5.dim(` sherwood fund create --agent-id ${tokenId} --subdomain <name> --name <name>`));
4751
+ console.log(chalk7.green("You can now create funds:"));
4752
+ console.log(chalk7.dim(` sherwood fund create --agent-id ${tokenId} --subdomain <name> --name <name>`));
4658
4753
  } catch (err) {
4659
4754
  spinner.fail("Failed to register identity");
4660
- console.error(chalk5.red(formatContractError(err)));
4755
+ console.error(chalk7.red(formatContractError(err)));
4661
4756
  process.exit(1);
4662
4757
  }
4663
4758
  });
@@ -4666,7 +4761,7 @@ function registerIdentityCommands(program2) {
4666
4761
  const client = getPublicClient();
4667
4762
  const registry = AGENT_REGISTRY().IDENTITY_REGISTRY;
4668
4763
  const tokenId = Number(opts.id);
4669
- const spinner = ora5(`Verifying ownership of agent #${tokenId}...`).start();
4764
+ const spinner = ora6(`Verifying ownership of agent #${tokenId}...`).start();
4670
4765
  try {
4671
4766
  const owner = await client.readContract({
4672
4767
  address: registry,
@@ -4680,11 +4775,11 @@ function registerIdentityCommands(program2) {
4680
4775
  }
4681
4776
  setAgentId(tokenId);
4682
4777
  spinner.succeed(`Agent #${tokenId} loaded and saved to config`);
4683
- console.log(chalk5.dim(` Owner: ${account.address}`));
4684
- console.log(chalk5.dim(` Saved to ~/.sherwood/config.json`));
4778
+ console.log(chalk7.dim(` Owner: ${account.address}`));
4779
+ console.log(chalk7.dim(` Saved to ~/.sherwood/config.json`));
4685
4780
  } catch (err) {
4686
4781
  spinner.fail("Failed to load identity");
4687
- console.error(chalk5.red(formatContractError(err)));
4782
+ console.error(chalk7.red(formatContractError(err)));
4688
4783
  process.exit(1);
4689
4784
  }
4690
4785
  });
@@ -4692,10 +4787,10 @@ function registerIdentityCommands(program2) {
4692
4787
  const account = getAccount();
4693
4788
  const issuingChainId = opts.walletOnly ? WALLET_ONLY_CHAIN_ID : parseInt(opts.chainId, 10);
4694
4789
  if (!opts.walletOnly && !ISSUING_CHAINS[issuingChainId]) {
4695
- console.error(chalk5.red(`Unsupported issuing chain ${opts.chainId}. Supported: ${Object.keys(ISSUING_CHAINS).join(", ")}`));
4790
+ console.error(chalk7.red(`Unsupported issuing chain ${opts.chainId}. Supported: ${Object.keys(ISSUING_CHAINS).join(", ")}`));
4696
4791
  process.exit(1);
4697
4792
  }
4698
- const spinner = ora5("Resolving economyOS agent...").start();
4793
+ const spinner = ora6("Resolving economyOS agent...").start();
4699
4794
  try {
4700
4795
  let virtualsWallet = opts.wallet;
4701
4796
  let virtualsAgentId;
@@ -4708,8 +4803,8 @@ function registerIdentityCommands(program2) {
4708
4803
  }
4709
4804
  if (!virtualsWallet) {
4710
4805
  spinner.fail("Could not resolve the economyOS agent wallet");
4711
- console.error(chalk5.dim(" Install + authenticate the acp CLI (npm i -g @virtuals-protocol/acp-cli; acp configure)"));
4712
- console.error(chalk5.dim(" or pass --wallet <address> explicitly."));
4806
+ console.error(chalk7.dim(" Install + authenticate the acp CLI (npm i -g @virtuals-protocol/acp-cli; acp configure)"));
4807
+ console.error(chalk7.dim(" or pass --wallet <address> explicitly."));
4713
4808
  process.exit(1);
4714
4809
  }
4715
4810
  let tokenId;
@@ -4730,10 +4825,10 @@ function registerIdentityCommands(program2) {
4730
4825
  });
4731
4826
  if (results.length === 0) {
4732
4827
  spinner.fail(`No ERC-8004 registration found for ${virtualsWallet} on chain ${issuingChainId}`);
4733
- console.error(chalk5.dim(" Register first via the Virtuals CLI:"));
4734
- console.error(chalk5.dim(` acp agent register-erc8004 --agent-id ${virtualsAgentId ?? "<id>"} --chain-id ${issuingChainId}`));
4735
- console.error(chalk5.dim(" Then re-run this command (or pass --agent-id <tokenId> directly)."));
4736
- console.error(chalk5.dim(" No registration possible yet? Link without one: --wallet-only"));
4828
+ console.error(chalk7.dim(" Register first via the Virtuals CLI:"));
4829
+ console.error(chalk7.dim(` acp agent register-erc8004 --agent-id ${virtualsAgentId ?? "<id>"} --chain-id ${issuingChainId}`));
4830
+ console.error(chalk7.dim(" Then re-run this command (or pass --agent-id <tokenId> directly)."));
4831
+ console.error(chalk7.dim(" No registration possible yet? Link without one: --wallet-only"));
4737
4832
  process.exit(1);
4738
4833
  }
4739
4834
  if (results.length > 1) {
@@ -4741,9 +4836,9 @@ function registerIdentityCommands(program2) {
4741
4836
  for (const a of results) {
4742
4837
  const idStr2 = String(a.agentId);
4743
4838
  const tid = idStr2.includes(":") ? idStr2.split(":")[1] : idStr2;
4744
- console.error(chalk5.dim(` #${tid} ${a.name || "(no name)"}`));
4839
+ console.error(chalk7.dim(` #${tid} ${a.name || "(no name)"}`));
4745
4840
  }
4746
- console.error(chalk5.green(" Re-run with: sherwood identity link-virtuals --agent-id <tokenId>"));
4841
+ console.error(chalk7.green(" Re-run with: sherwood identity link-virtuals --agent-id <tokenId>"));
4747
4842
  process.exit(1);
4748
4843
  }
4749
4844
  const idStr = String(results[0].agentId);
@@ -4770,17 +4865,17 @@ function registerIdentityCommands(program2) {
4770
4865
  spinner.text = "Requesting binding signature from the economyOS wallet (acp wallet sign-message)...";
4771
4866
  bindingSig = await acpSignMessage(bindingMessage) ?? void 0;
4772
4867
  if (bindingSig) {
4773
- console.log(chalk5.dim(" Binding signed automatically via acp."));
4868
+ console.log(chalk7.dim(" Binding signed automatically via acp."));
4774
4869
  }
4775
4870
  }
4776
4871
  if (!bindingSig) {
4777
4872
  spinner.fail("Binding signature required (economyOS wallet differs from your Sherwood wallet)");
4778
4873
  console.error();
4779
- console.error(chalk5.bold(" Sign this exact message with the economyOS agent wallet:"));
4780
- console.error(chalk5.green(` ${bindingMessage}`));
4874
+ console.error(chalk7.bold(" Sign this exact message with the economyOS agent wallet:"));
4875
+ console.error(chalk7.green(` ${bindingMessage}`));
4781
4876
  console.error();
4782
- console.error(chalk5.dim(` acp wallet sign-message --message "${bindingMessage}" --json`));
4783
- console.error(chalk5.dim(" Then re-run with --binding-sig <signature>."));
4877
+ console.error(chalk7.dim(` acp wallet sign-message --message "${bindingMessage}" --json`));
4878
+ console.error(chalk7.dim(" Then re-run with --binding-sig <signature>."));
4784
4879
  process.exit(1);
4785
4880
  }
4786
4881
  spinner.text = "Verifying binding signature...";
@@ -4793,8 +4888,8 @@ function registerIdentityCommands(program2) {
4793
4888
  });
4794
4889
  if (!ok) {
4795
4890
  spinner.fail("Binding signature does not recover to the economyOS wallet");
4796
- console.error(chalk5.dim(` Expected signer: ${virtualsWallet}`));
4797
- console.error(chalk5.dim(` Signed message must be exactly: ${bindingMessage}`));
4891
+ console.error(chalk7.dim(` Expected signer: ${virtualsWallet}`));
4892
+ console.error(chalk7.dim(` Signed message must be exactly: ${bindingMessage}`));
4798
4893
  process.exit(1);
4799
4894
  }
4800
4895
  binding = { sig: bindingSig, message: bindingMessage };
@@ -4807,25 +4902,25 @@ function registerIdentityCommands(program2) {
4807
4902
  spinner.succeed(
4808
4903
  opts.walletOnly ? "Virtuals identity linked: wallet-only (no ERC-8004 \u2014 upgrade later by re-linking after registration)" : `Virtuals identity linked: agent #${tokenId} (chain ${issuingChainId})`
4809
4904
  );
4810
- console.log(chalk5.dim(` economyOS wallet: ${virtualsWallet}`));
4811
- if (virtualsAgentId) console.log(chalk5.dim(` Virtuals agent: ${virtualsAgentId}`));
4812
- console.log(chalk5.dim(` Sherwood wallet: ${account.address}${self ? " (same as economyOS wallet \u2014 no binding needed)" : " (bound via signature)"}`));
4813
- console.log(chalk5.dim(` Saved to ~/.sherwood/config.json`));
4905
+ console.log(chalk7.dim(` economyOS wallet: ${virtualsWallet}`));
4906
+ if (virtualsAgentId) console.log(chalk7.dim(` Virtuals agent: ${virtualsAgentId}`));
4907
+ console.log(chalk7.dim(` Sherwood wallet: ${account.address}${self ? " (same as economyOS wallet \u2014 no binding needed)" : " (bound via signature)"}`));
4908
+ console.log(chalk7.dim(` Saved to ~/.sherwood/config.json`));
4814
4909
  console.log();
4815
- console.log(chalk5.green("You can now create or join funds with this identity:"));
4816
- console.log(chalk5.dim(` sherwood fund create --agent-id ${tokenId} --subdomain <name> --name <name>`));
4910
+ console.log(chalk7.green("You can now create or join funds with this identity:"));
4911
+ console.log(chalk7.dim(` sherwood fund create --agent-id ${tokenId} --subdomain <name> --name <name>`));
4817
4912
  } catch (err) {
4818
4913
  spinner.fail("Failed to link Virtuals identity");
4819
- console.error(chalk5.red(formatContractError(err)));
4914
+ console.error(chalk7.red(formatContractError(err)));
4820
4915
  process.exit(1);
4821
4916
  }
4822
4917
  });
4823
4918
  identity.command("find").description("Search ERC-8004 agents by wallet address or name (recover a lost agent ID)").option("--wallet <address>", "Filter by owner / wallet address").option("--name <text>", "Filter by agent name (exact or substring match, depending on registry)").option("--all-chains", "Search across all chains, not just the active one").action(async (opts) => {
4824
4919
  if (!opts.wallet && !opts.name) {
4825
- console.error(chalk5.red("Pass --wallet <address> or --name <text> (or both)."));
4920
+ console.error(chalk7.red("Pass --wallet <address> or --name <text> (or both)."));
4826
4921
  process.exit(1);
4827
4922
  }
4828
- const spinner = ora5("Searching ERC-8004 registry...").start();
4923
+ const spinner = ora6("Searching ERC-8004 registry...").start();
4829
4924
  try {
4830
4925
  const sdk = getAgent0SDK();
4831
4926
  const filters = {};
@@ -4835,32 +4930,32 @@ function registerIdentityCommands(program2) {
4835
4930
  const results = await sdk.searchAgents(filters);
4836
4931
  spinner.stop();
4837
4932
  if (results.length === 0) {
4838
- console.log(chalk5.dim("No agents found matching those filters."));
4839
- console.log(chalk5.dim("If you minted on a different chain, retry with --all-chains."));
4933
+ console.log(chalk7.dim("No agents found matching those filters."));
4934
+ console.log(chalk7.dim("If you minted on a different chain, retry with --all-chains."));
4840
4935
  return;
4841
4936
  }
4842
4937
  console.log();
4843
- console.log(chalk5.bold(`Found ${results.length} agent${results.length === 1 ? "" : "s"}`));
4844
- console.log(chalk5.dim("\u2500".repeat(50)));
4938
+ console.log(chalk7.bold(`Found ${results.length} agent${results.length === 1 ? "" : "s"}`));
4939
+ console.log(chalk7.dim("\u2500".repeat(50)));
4845
4940
  for (const a of results) {
4846
4941
  const idStr = String(a.agentId);
4847
4942
  const tokenId = idStr.includes(":") ? idStr.split(":")[1] : idStr;
4848
- console.log(` ${chalk5.bold(`#${tokenId}`)} ${a.name || chalk5.dim("(no name)")}`);
4849
- console.log(chalk5.dim(` Chain: ${a.chainId}`));
4850
- console.log(chalk5.dim(` Full: ${idStr}`));
4943
+ console.log(` ${chalk7.bold(`#${tokenId}`)} ${a.name || chalk7.dim("(no name)")}`);
4944
+ console.log(chalk7.dim(` Chain: ${a.chainId}`));
4945
+ console.log(chalk7.dim(` Full: ${idStr}`));
4851
4946
  if (a.owners?.length) {
4852
- console.log(chalk5.dim(` Owner: ${a.owners[0]}`));
4947
+ console.log(chalk7.dim(` Owner: ${a.owners[0]}`));
4853
4948
  }
4854
4949
  if (a.walletAddress) {
4855
- console.log(chalk5.dim(` Wallet: ${a.walletAddress}`));
4950
+ console.log(chalk7.dim(` Wallet: ${a.walletAddress}`));
4856
4951
  }
4857
4952
  }
4858
4953
  console.log();
4859
- console.log(chalk5.green("To bind one of these to this machine:"));
4860
- console.log(chalk5.dim(` sherwood identity load --id <tokenId>`));
4954
+ console.log(chalk7.green("To bind one of these to this machine:"));
4955
+ console.log(chalk7.dim(` sherwood identity load --id <tokenId>`));
4861
4956
  } catch (err) {
4862
4957
  spinner.fail("Search failed");
4863
- console.error(chalk5.red(formatContractError(err)));
4958
+ console.error(chalk7.red(formatContractError(err)));
4864
4959
  process.exit(1);
4865
4960
  }
4866
4961
  });
@@ -4871,16 +4966,16 @@ function registerIdentityCommands(program2) {
4871
4966
  const savedId = getAgentId();
4872
4967
  const issuingChainId = getIdentityChainId();
4873
4968
  console.log();
4874
- console.log(chalk5.bold("Agent Identity (ERC-8004 via Virtuals economyOS)"));
4875
- console.log(chalk5.dim("\u2500".repeat(40)));
4969
+ console.log(chalk7.bold("Agent Identity (ERC-8004 via Virtuals economyOS)"));
4970
+ console.log(chalk7.dim("\u2500".repeat(40)));
4876
4971
  console.log(` Sherwood wallet: ${account.address}`);
4877
- console.log(` economyOS wallet: ${virtuals?.wallet ?? chalk5.red("(missing)")}`);
4972
+ console.log(` economyOS wallet: ${virtuals?.wallet ?? chalk7.red("(missing)")}`);
4878
4973
  if (virtuals?.agentId) console.log(` Virtuals agent: ${virtuals.agentId}`);
4879
4974
  const walletOnly = issuingChainId === WALLET_ONLY_CHAIN_ID;
4880
- console.log(` Issuing chain: ${walletOnly ? chalk5.yellow("wallet-only (no ERC-8004)") : issuingChainId ?? chalk5.red("(missing)")}`);
4881
- console.log(` Saved ID: ${savedId != null ? walletOnly ? chalk5.dim("0 (wallet-only)") : `#${savedId}` : chalk5.red("(missing)")}`);
4975
+ console.log(` Issuing chain: ${walletOnly ? chalk7.yellow("wallet-only (no ERC-8004)") : issuingChainId ?? chalk7.red("(missing)")}`);
4976
+ console.log(` Saved ID: ${savedId != null ? walletOnly ? chalk7.dim("0 (wallet-only)") : `#${savedId}` : chalk7.red("(missing)")}`);
4882
4977
  if (virtuals?.wallet && savedId != null && issuingChainId != null) {
4883
- const spinner2 = ora5("Re-verifying link...").start();
4978
+ const spinner2 = ora6("Re-verifying link...").start();
4884
4979
  try {
4885
4980
  let ownerOk = true;
4886
4981
  let owner;
@@ -4900,21 +4995,21 @@ function registerIdentityCommands(program2) {
4900
4995
  }
4901
4996
  spinner2.stop();
4902
4997
  if (walletOnly) {
4903
- console.log(` NFT ownership: ${chalk5.dim("n/a (wallet-only link)")}`);
4998
+ console.log(` NFT ownership: ${chalk7.dim("n/a (wallet-only link)")}`);
4904
4999
  } else {
4905
- console.log(` NFT ownership: ${ownerOk ? chalk5.green("verified") : chalk5.red(`FAILED (owner is ${owner})`)}`);
5000
+ console.log(` NFT ownership: ${ownerOk ? chalk7.green("verified") : chalk7.red(`FAILED (owner is ${owner})`)}`);
4906
5001
  }
4907
- console.log(` Binding: ${bindingOk ? chalk5.green("verified") : chalk5.red("FAILED")}`);
5002
+ console.log(` Binding: ${bindingOk ? chalk7.green("verified") : chalk7.red("FAILED")}`);
4908
5003
  if (!ownerOk) {
4909
- console.log(chalk5.yellow(" The NFT moved since linking \u2014 re-run 'sherwood identity link-virtuals'."));
5004
+ console.log(chalk7.yellow(" The NFT moved since linking \u2014 re-run 'sherwood identity link-virtuals'."));
4910
5005
  }
4911
5006
  if (walletOnly) {
4912
- console.log(chalk5.dim(" Upgrade to a registered link once ERC-8004 registration is available:"));
4913
- console.log(chalk5.dim(" acp agent register-erc8004 ... && sherwood identity link-virtuals"));
5007
+ console.log(chalk7.dim(" Upgrade to a registered link once ERC-8004 registration is available:"));
5008
+ console.log(chalk7.dim(" acp agent register-erc8004 ... && sherwood identity link-virtuals"));
4914
5009
  }
4915
5010
  } catch (err) {
4916
5011
  spinner2.warn("Could not re-verify against the issuing chain");
4917
- console.log(chalk5.dim(` ${err.message}`));
5012
+ console.log(chalk7.dim(` ${err.message}`));
4918
5013
  }
4919
5014
  }
4920
5015
  console.log();
@@ -4922,7 +5017,7 @@ function registerIdentityCommands(program2) {
4922
5017
  }
4923
5018
  const registry = AGENT_REGISTRY().IDENTITY_REGISTRY;
4924
5019
  const client = getPublicClient();
4925
- const spinner = ora5("Checking identity...").start();
5020
+ const spinner = ora6("Checking identity...").start();
4926
5021
  try {
4927
5022
  const balance = await client.readContract({
4928
5023
  address: registry,
@@ -4933,8 +5028,8 @@ function registerIdentityCommands(program2) {
4933
5028
  spinner.stop();
4934
5029
  const savedId = getAgentId();
4935
5030
  console.log();
4936
- console.log(chalk5.bold("Agent Identity (ERC-8004)"));
4937
- console.log(chalk5.dim("\u2500".repeat(40)));
5031
+ console.log(chalk7.bold("Agent Identity (ERC-8004)"));
5032
+ console.log(chalk7.dim("\u2500".repeat(40)));
4938
5033
  console.log(` Wallet: ${account.address}`);
4939
5034
  console.log(` Registry: ${registry}`);
4940
5035
  console.log(` NFTs owned: ${balance.toString()}`);
@@ -4947,25 +5042,25 @@ function registerIdentityCommands(program2) {
4947
5042
  args: [BigInt(savedId)]
4948
5043
  });
4949
5044
  const isOwner = owner.toLowerCase() === account.address.toLowerCase();
4950
- console.log(` Saved ID: #${savedId} ${isOwner ? chalk5.green("(verified)") : chalk5.red("(owned by " + owner + ")")}`);
5045
+ console.log(` Saved ID: #${savedId} ${isOwner ? chalk7.green("(verified)") : chalk7.red("(owned by " + owner + ")")}`);
4951
5046
  if (isOwner) {
4952
5047
  try {
4953
5048
  const sdk = getAgent0SDK();
4954
5049
  const agent = await sdk.loadAgent(`${getChain().id}:${savedId}`);
4955
5050
  if (agent.name) console.log(` Name: ${agent.name}`);
4956
- if (agent.description) console.log(` Desc: ${chalk5.dim(agent.description)}`);
5051
+ if (agent.description) console.log(` Desc: ${chalk7.dim(agent.description)}`);
4957
5052
  if (agent.walletAddress) console.log(` Wallet: ${agent.walletAddress}`);
4958
5053
  } catch {
4959
5054
  }
4960
5055
  }
4961
5056
  } catch {
4962
- console.log(` Saved ID: #${savedId} ${chalk5.red("(token not found)")}`);
5057
+ console.log(` Saved ID: #${savedId} ${chalk7.red("(token not found)")}`);
4963
5058
  }
4964
5059
  console.log();
4965
5060
  } else if (balance > 0n) {
4966
- console.log(` Saved ID: ${chalk5.yellow("none (but this wallet owns NFTs \u2014 listing below)")}`);
5061
+ console.log(` Saved ID: ${chalk7.yellow("none (but this wallet owns NFTs \u2014 listing below)")}`);
4967
5062
  console.log();
4968
- const lookupSpinner = ora5("Resolving owned token IDs via Agent0 SDK...").start();
5063
+ const lookupSpinner = ora6("Resolving owned token IDs via Agent0 SDK...").start();
4969
5064
  try {
4970
5065
  const sdk = getAgent0SDK();
4971
5066
  const results = await sdk.searchAgents({
@@ -4974,56 +5069,56 @@ function registerIdentityCommands(program2) {
4974
5069
  });
4975
5070
  lookupSpinner.stop();
4976
5071
  if (results.length === 0) {
4977
- console.log(chalk5.dim(" No agents resolved for this wallet on the active chain."));
4978
- console.log(chalk5.dim(" If you minted on a different chain, try:"));
4979
- console.log(chalk5.dim(" sherwood identity find --wallet " + account.address + " --all-chains"));
5072
+ console.log(chalk7.dim(" No agents resolved for this wallet on the active chain."));
5073
+ console.log(chalk7.dim(" If you minted on a different chain, try:"));
5074
+ console.log(chalk7.dim(" sherwood identity find --wallet " + account.address + " --all-chains"));
4980
5075
  } else {
4981
- console.log(chalk5.bold(` Owned identities on this chain (${results.length}):`));
5076
+ console.log(chalk7.bold(` Owned identities on this chain (${results.length}):`));
4982
5077
  for (const a of results) {
4983
5078
  const idStr = String(a.agentId);
4984
5079
  const tokenId = idStr.includes(":") ? idStr.split(":")[1] : idStr;
4985
- console.log(` ${chalk5.bold(`#${tokenId}`)} ${a.name || chalk5.dim("(no name)")}`);
5080
+ console.log(` ${chalk7.bold(`#${tokenId}`)} ${a.name || chalk7.dim("(no name)")}`);
4986
5081
  }
4987
5082
  console.log();
4988
- console.log(chalk5.green(" Bind one to this machine:"));
5083
+ console.log(chalk7.green(" Bind one to this machine:"));
4989
5084
  if (results.length === 1) {
4990
5085
  const idStr = String(results[0].agentId);
4991
5086
  const tokenId = idStr.includes(":") ? idStr.split(":")[1] : idStr;
4992
- console.log(chalk5.dim(` sherwood identity load --id ${tokenId}`));
5087
+ console.log(chalk7.dim(` sherwood identity load --id ${tokenId}`));
4993
5088
  } else {
4994
- console.log(chalk5.dim(" sherwood identity load --id <tokenId>"));
5089
+ console.log(chalk7.dim(" sherwood identity load --id <tokenId>"));
4995
5090
  }
4996
5091
  }
4997
5092
  } catch (err) {
4998
5093
  lookupSpinner.warn("Could not resolve owned token IDs via Agent0 SDK");
4999
- console.log(chalk5.dim(` ${err.message}`));
5000
- console.log(chalk5.dim(" Try: sherwood identity find --wallet " + account.address));
5094
+ console.log(chalk7.dim(` ${err.message}`));
5095
+ console.log(chalk7.dim(" Try: sherwood identity find --wallet " + account.address));
5001
5096
  }
5002
5097
  console.log();
5003
5098
  } else {
5004
- console.log(` Saved ID: ${chalk5.dim("none \u2014 run 'sherwood identity mint --name <name>'")}`);
5099
+ console.log(` Saved ID: ${chalk7.dim("none \u2014 run 'sherwood identity mint --name <name>'")}`);
5005
5100
  console.log();
5006
5101
  }
5007
5102
  } catch (err) {
5008
5103
  spinner.fail("Failed to check identity");
5009
- console.error(chalk5.red(formatContractError(err)));
5104
+ console.error(chalk7.red(formatContractError(err)));
5010
5105
  process.exit(1);
5011
5106
  }
5012
5107
  });
5013
5108
  }
5014
5109
 
5015
5110
  // src/commands/proposal.ts
5016
- import { isAddress as isAddress7, encodeFunctionData as encodeFunctionData10, parseUnits as parseUnits6 } from "viem";
5017
- import chalk7 from "chalk";
5018
- import ora6 from "ora";
5111
+ import { isAddress as isAddress9, encodeFunctionData as encodeFunctionData10, parseUnits as parseUnits8 } from "viem";
5112
+ import chalk9 from "chalk";
5113
+ import ora7 from "ora";
5019
5114
  import { readFileSync as readFileSync2 } from "fs";
5020
5115
 
5021
5116
  // src/lib/simulate.ts
5022
5117
  import { decodeFunctionData as decodeFunctionData2, encodeFunctionData as encodeFunctionData9 } from "viem";
5023
- import chalk6 from "chalk";
5118
+ import chalk8 from "chalk";
5024
5119
 
5025
5120
  // src/lib/risk.ts
5026
- import { decodeFunctionData, erc20Abi as erc20Abi2 } from "viem";
5121
+ import { decodeFunctionData, erc20Abi as erc20Abi4 } from "viem";
5027
5122
  var MOONWELL_CTOKEN_ABI = [
5028
5123
  { name: "mint", type: "function", stateMutability: "nonpayable", inputs: [{ name: "mintAmount", type: "uint256" }], outputs: [{ name: "", type: "uint256" }] },
5029
5124
  { name: "redeem", type: "function", stateMutability: "nonpayable", inputs: [{ name: "redeemTokens", type: "uint256" }], outputs: [{ name: "", type: "uint256" }] },
@@ -5099,7 +5194,7 @@ function tryDecode(abi, data) {
5099
5194
  }
5100
5195
  }
5101
5196
  function decodeCallArgs(data) {
5102
- return tryDecode(erc20Abi2, data) ?? tryDecode(MOONWELL_CTOKEN_ABI, data) ?? tryDecode(MOONWELL_COMPTROLLER_ABI, data) ?? tryDecode(SWAP_ROUTER_SINGLE_ABI, data) ?? // exactInputSingle (single-hop)
5197
+ return tryDecode(erc20Abi4, data) ?? tryDecode(MOONWELL_CTOKEN_ABI, data) ?? tryDecode(MOONWELL_COMPTROLLER_ABI, data) ?? tryDecode(SWAP_ROUTER_SINGLE_ABI, data) ?? // exactInputSingle (single-hop)
5103
5198
  tryDecode(SWAP_ROUTER_MULTI_ABI, data);
5104
5199
  }
5105
5200
  function analyzeRisk(calls, callResults, context) {
@@ -5229,11 +5324,11 @@ function analyzeRisk(calls, callResults, context) {
5229
5324
  }
5230
5325
 
5231
5326
  // src/lib/simulate.ts
5232
- var G2 = chalk6.green;
5233
- var W2 = chalk6.white;
5234
- var DIM2 = chalk6.gray;
5235
- var BOLD2 = chalk6.white.bold;
5236
- var LABEL2 = chalk6.green.bold;
5327
+ var G2 = chalk8.green;
5328
+ var W2 = chalk8.white;
5329
+ var DIM2 = chalk8.gray;
5330
+ var BOLD2 = chalk8.white.bold;
5331
+ var LABEL2 = chalk8.green.bold;
5237
5332
  var SEP2 = () => console.log(DIM2("\u2500".repeat(60)));
5238
5333
  var MOONWELL_CTOKEN_ABI2 = [
5239
5334
  {
@@ -5651,17 +5746,17 @@ function printSimulationResult(result, callType) {
5651
5746
  SEP2();
5652
5747
  const sourceLabel = result.source === "api" ? "Tenderly (via API)" : `eth_call ${DIM2("(configure Tenderly for detailed results)")}`;
5653
5748
  console.log(W2(` Source: ${sourceLabel}`));
5654
- const statusIcon = result.success ? G2("\u2713 PASS") : chalk6.red("\u2716 FAIL");
5749
+ const statusIcon = result.success ? G2("\u2713 PASS") : chalk8.red("\u2716 FAIL");
5655
5750
  console.log(W2(` Status: ${statusIcon}`));
5656
5751
  if (result.totalGasUsed > 0) {
5657
5752
  console.log(W2(` Total Gas: ${result.totalGasUsed.toLocaleString()}`));
5658
5753
  }
5659
5754
  if (result.errorMessage && !result.success) {
5660
- console.log(chalk6.red(` Error: ${result.errorMessage.slice(0, 120)}`));
5755
+ console.log(chalk8.red(` Error: ${result.errorMessage.slice(0, 120)}`));
5661
5756
  }
5662
5757
  console.log();
5663
5758
  for (const cr of result.callResults) {
5664
- const icon = cr.success ? G2("\u2713") : chalk6.red("\u2716");
5759
+ const icon = cr.success ? G2("\u2713") : chalk8.red("\u2716");
5665
5760
  const funcName = cr.decodedFunction || `${cr.selector}... ${DIM2("(unknown)")}`;
5666
5761
  console.log(W2(` [${cr.index + 1}] ${icon} ${funcName}`));
5667
5762
  const label = getAddressLabel(cr.target);
@@ -5677,18 +5772,18 @@ function printSimulationResult(result, callType) {
5677
5772
  const warnings = result.risks.filter((r) => r.level === "warning");
5678
5773
  const infos = result.risks.filter((r) => r.level === "info");
5679
5774
  if (criticals.length > 0) {
5680
- console.log(chalk6.red.bold(` \u2716 CRITICAL RISKS (${criticals.length})`));
5775
+ console.log(chalk8.red.bold(` \u2716 CRITICAL RISKS (${criticals.length})`));
5681
5776
  for (const r of criticals) {
5682
5777
  const ref = r.callIndex !== void 0 ? ` [call #${r.callIndex + 1}]` : "";
5683
- console.log(chalk6.red(` \u2716${ref} ${r.code} \u2014 ${r.message}`));
5778
+ console.log(chalk8.red(` \u2716${ref} ${r.code} \u2014 ${r.message}`));
5684
5779
  }
5685
5780
  console.log();
5686
5781
  }
5687
5782
  if (warnings.length > 0) {
5688
- console.log(chalk6.yellow.bold(` \u26A0 WARNINGS (${warnings.length})`));
5783
+ console.log(chalk8.yellow.bold(` \u26A0 WARNINGS (${warnings.length})`));
5689
5784
  for (const r of warnings) {
5690
5785
  const ref = r.callIndex !== void 0 ? ` [call #${r.callIndex + 1}]` : "";
5691
- console.log(chalk6.yellow(` \u26A0${ref} ${r.code} \u2014 ${r.message}`));
5786
+ console.log(chalk8.yellow(` \u26A0${ref} ${r.code} \u2014 ${r.message}`));
5692
5787
  }
5693
5788
  console.log();
5694
5789
  }
@@ -5701,9 +5796,9 @@ function printSimulationResult(result, callType) {
5701
5796
  }
5702
5797
  }
5703
5798
  if (result.warnings.length > 0) {
5704
- console.log(chalk6.yellow(` \u26A0 Simulation Warnings`));
5799
+ console.log(chalk8.yellow(` \u26A0 Simulation Warnings`));
5705
5800
  for (const w of result.warnings) {
5706
- console.log(chalk6.yellow(` - ${w}`));
5801
+ console.log(chalk8.yellow(` - ${w}`));
5707
5802
  }
5708
5803
  console.log();
5709
5804
  }
@@ -5711,8 +5806,8 @@ function printSimulationResult(result, callType) {
5711
5806
  }
5712
5807
  async function sendSimulationAlert(subdomain, proposalId, vault, execResult, settleResult) {
5713
5808
  try {
5714
- const xmtp = await import("./xmtp-M74BRF3G.js");
5715
- const { getAccount: getAccount2 } = await import("./client-VNSFNDF4.js");
5809
+ const xmtp = await import("./xmtp-2U7CSBXM.js");
5810
+ const { getAccount: getAccount2 } = await import("./client-OPZ2ORWW.js");
5716
5811
  const group = await xmtp.getGroup("", subdomain);
5717
5812
  const allRisks = [...execResult.risks, ...settleResult?.risks ?? []];
5718
5813
  const criticals = allRisks.filter((r) => r.level === "critical");
@@ -5788,16 +5883,16 @@ async function sendSimulationAlert(subdomain, proposalId, vault, execResult, set
5788
5883
  });
5789
5884
  } catch (err) {
5790
5885
  const message = err instanceof Error ? err.message : String(err);
5791
- console.log(chalk6.yellow(` \u26A0 Failed to send XMTP alert: ${message.slice(0, 100)}`));
5886
+ console.log(chalk8.yellow(` \u26A0 Failed to send XMTP alert: ${message.slice(0, 100)}`));
5792
5887
  }
5793
5888
  }
5794
5889
 
5795
5890
  // src/commands/proposal.ts
5796
- var G3 = chalk7.green;
5797
- var W3 = chalk7.white;
5798
- var DIM3 = chalk7.gray;
5799
- var BOLD3 = chalk7.white.bold;
5800
- var LABEL3 = chalk7.green.bold;
5891
+ var G3 = chalk9.green;
5892
+ var W3 = chalk9.white;
5893
+ var DIM3 = chalk9.gray;
5894
+ var BOLD3 = chalk9.white.bold;
5895
+ var LABEL3 = chalk9.green.bold;
5801
5896
  var SEP3 = () => console.log(DIM3("\u2500".repeat(60)));
5802
5897
  function formatTimestamp(ts) {
5803
5898
  if (ts === 0n) return "\u2014";
@@ -5805,9 +5900,9 @@ function formatTimestamp(ts) {
5805
5900
  }
5806
5901
  function parseVaultOption(raw, spinner) {
5807
5902
  const vault = String(raw);
5808
- if (!isAddress7(vault)) {
5903
+ if (!isAddress9(vault)) {
5809
5904
  if (spinner) spinner.fail(`Invalid vault address: ${vault}`);
5810
- else console.error(chalk7.red(`Invalid vault address: ${vault}`));
5905
+ else console.error(chalk9.red(`Invalid vault address: ${vault}`));
5811
5906
  process.exit(1);
5812
5907
  }
5813
5908
  return vault;
@@ -5836,8 +5931,7 @@ var GUARDIAN_REGISTRY_ABI2 = [
5836
5931
  outputs: [
5837
5932
  { name: "opened", type: "bool" },
5838
5933
  { name: "resolved", type: "bool" },
5839
- { name: "blocked", type: "bool" },
5840
- { name: "cohortTooSmall", type: "bool" }
5934
+ { name: "blocked", type: "bool" }
5841
5935
  ],
5842
5936
  stateMutability: "view"
5843
5937
  }
@@ -5846,7 +5940,7 @@ function getRegistryAddress() {
5846
5940
  const addr = SHERWOOD().GUARDIAN_REGISTRY;
5847
5941
  if (addr === "0x0000000000000000000000000000000000000000") {
5848
5942
  console.error(
5849
- chalk7.red(
5943
+ chalk9.red(
5850
5944
  `GUARDIAN_REGISTRY is not deployed on ${getNetwork()}. Update cli/src/lib/addresses.ts after deploy.`
5851
5945
  )
5852
5946
  );
@@ -5856,7 +5950,7 @@ function getRegistryAddress() {
5856
5950
  }
5857
5951
  async function resolveRiskEnvelope(opts, vault) {
5858
5952
  if (opts.maxCapital === void 0) {
5859
- console.error(chalk7.red(" --max-capital is required (the ceiling this proposal may deploy, in asset units)."));
5953
+ console.error(chalk9.red(" --max-capital is required (the ceiling this proposal may deploy, in asset units)."));
5860
5954
  process.exit(1);
5861
5955
  }
5862
5956
  const asset = await getAssetAddress();
@@ -5865,14 +5959,14 @@ async function resolveRiskEnvelope(opts, vault) {
5865
5959
  abi: ERC20_ABI,
5866
5960
  functionName: "decimals"
5867
5961
  });
5868
- const maxCapital = parseUnits6(String(opts.maxCapital), decimals);
5962
+ const maxCapital = parseUnits8(String(opts.maxCapital), decimals);
5869
5963
  if (maxCapital === 0n) {
5870
- console.error(chalk7.red(" --max-capital must be greater than zero."));
5964
+ console.error(chalk9.red(" --max-capital must be greater than zero."));
5871
5965
  process.exit(1);
5872
5966
  }
5873
5967
  const maxDrawdownBps = opts.maxDrawdownBps === void 0 ? 2e3 : Number(opts.maxDrawdownBps);
5874
5968
  if (!Number.isInteger(maxDrawdownBps) || maxDrawdownBps < 0 || maxDrawdownBps > 1e4) {
5875
- console.error(chalk7.red(` --max-drawdown-bps must be an integer 0-10000 (got ${opts.maxDrawdownBps})`));
5969
+ console.error(chalk9.red(` --max-drawdown-bps must be an integer 0-10000 (got ${opts.maxDrawdownBps})`));
5876
5970
  process.exit(1);
5877
5971
  }
5878
5972
  return { maxCapital, maxDrawdownBps };
@@ -5885,7 +5979,7 @@ function resolveCaps(list, callCount, fallbackTotal, flag) {
5885
5979
  const parts = list.split(",").map((x) => x.trim()).filter((x) => x.length > 0);
5886
5980
  if (parts.length !== callCount) {
5887
5981
  console.error(
5888
- chalk7.red(` ${flag} has ${parts.length} entries for ${callCount} calls \u2014 every call must declare exactly one cap.`)
5982
+ chalk9.red(` ${flag} has ${parts.length} entries for ${callCount} calls \u2014 every call must declare exactly one cap.`)
5889
5983
  );
5890
5984
  process.exit(1);
5891
5985
  }
@@ -5908,8 +6002,8 @@ function registerProposalCommands(program2) {
5908
6002
  ).option("--metadata-uri <uri>", "Override \u2014 skip IPFS upload and use this URI directly").option("--simulate", "Simulate calls via Tenderly before submitting").option("--force", "Submit even if simulation fails (requires --simulate)").action(async (opts) => {
5909
6003
  try {
5910
6004
  const vault = opts.vault;
5911
- if (!isAddress7(vault)) {
5912
- console.error(chalk7.red(`Invalid vault address: ${opts.vault}`));
6005
+ if (!isAddress9(vault)) {
6006
+ console.error(chalk9.red(`Invalid vault address: ${opts.vault}`));
5913
6007
  process.exit(1);
5914
6008
  }
5915
6009
  const strategyDuration = parseDuration(opts.duration);
@@ -5918,8 +6012,8 @@ function registerProposalCommands(program2) {
5918
6012
  const ZERO_STRATEGY = "0x0000000000000000000000000000000000000000";
5919
6013
  let strategy2 = ZERO_STRATEGY;
5920
6014
  if (opts.strategy) {
5921
- if (!isAddress7(opts.strategy)) {
5922
- console.error(chalk7.red(`Invalid strategy address: ${opts.strategy}`));
6015
+ if (!isAddress9(opts.strategy)) {
6016
+ console.error(chalk9.red(`Invalid strategy address: ${opts.strategy}`));
5923
6017
  process.exit(1);
5924
6018
  }
5925
6019
  strategy2 = opts.strategy;
@@ -5927,7 +6021,7 @@ function registerProposalCommands(program2) {
5927
6021
  if (isCalldataOnly()) {
5928
6022
  if (!opts.metadataUri) {
5929
6023
  console.error(
5930
- chalk7.red(
6024
+ chalk9.red(
5931
6025
  "--calldata-only requires --metadata-uri (IPFS metadata upload needs a signing wallet)"
5932
6026
  )
5933
6027
  );
@@ -5963,14 +6057,14 @@ function registerProposalCommands(program2) {
5963
6057
  )
5964
6058
  );
5965
6059
  } catch (err) {
5966
- console.error(chalk7.red(err instanceof Error ? err.message : String(err)));
6060
+ console.error(chalk9.red(err instanceof Error ? err.message : String(err)));
5967
6061
  process.exit(1);
5968
6062
  }
5969
6063
  return;
5970
6064
  }
5971
6065
  let metadataURI = opts.metadataUri || "";
5972
6066
  if (!metadataURI) {
5973
- const spinner2 = ora6({ text: W3("Uploading metadata to IPFS..."), color: "green" }).start();
6067
+ const spinner2 = ora7({ text: W3("Uploading metadata to IPFS..."), color: "green" }).start();
5974
6068
  try {
5975
6069
  const account = getAccount();
5976
6070
  const metadata = {
@@ -5992,7 +6086,7 @@ function registerProposalCommands(program2) {
5992
6086
  metadataURI = await uploadMetadata(proposalMeta);
5993
6087
  spinner2.succeed(G3(`Metadata pinned: ${DIM3(metadataURI)}`));
5994
6088
  } catch (err) {
5995
- spinner2.warn(chalk7.yellow("IPFS upload failed \u2014 using inline metadata"));
6089
+ spinner2.warn(chalk9.yellow("IPFS upload failed \u2014 using inline metadata"));
5996
6090
  const json = JSON.stringify({ name: opts.name, description: opts.description, vault });
5997
6091
  metadataURI = `data:application/json;base64,${Buffer.from(json).toString("base64")}`;
5998
6092
  }
@@ -6020,31 +6114,31 @@ function registerProposalCommands(program2) {
6020
6114
  if (preFetchedGovParams) {
6021
6115
  createRiskContext = { ...createRiskContext, governorParams: preFetchedGovParams };
6022
6116
  }
6023
- const simSpinner = ora6({ text: W3("Simulating execute calls..."), color: "green" }).start();
6117
+ const simSpinner = ora7({ text: W3("Simulating execute calls..."), color: "green" }).start();
6024
6118
  const execResult = await simulateBatchCalls(vault, executeCalls, "execute", createRiskContext);
6025
6119
  simSpinner.stop();
6026
6120
  printSimulationResult(execResult, "execute");
6027
6121
  if (settleCalls.length > 0) {
6028
- const settleSpinner = ora6({ text: W3("Simulating settlement calls..."), color: "green" }).start();
6122
+ const settleSpinner = ora7({ text: W3("Simulating settlement calls..."), color: "green" }).start();
6029
6123
  const settleResult = await simulateBatchCalls(vault, settleCalls, "settlement", createRiskContext);
6030
6124
  settleSpinner.stop();
6031
6125
  printSimulationResult(settleResult, "settlement");
6032
6126
  if (!settleResult.success && !opts.force) {
6033
- console.error(chalk7.red("\n \u2716 Settlement simulation failed. Use --force to submit anyway."));
6127
+ console.error(chalk9.red("\n \u2716 Settlement simulation failed. Use --force to submit anyway."));
6034
6128
  process.exit(1);
6035
6129
  }
6036
6130
  }
6037
6131
  if (!execResult.success && !opts.force) {
6038
- console.error(chalk7.red("\n \u2716 Execution simulation failed. Use --force to submit anyway."));
6132
+ console.error(chalk9.red("\n \u2716 Execution simulation failed. Use --force to submit anyway."));
6039
6133
  process.exit(1);
6040
6134
  }
6041
6135
  const hasCriticalRisks = execResult.risks.some((r) => r.level === "critical");
6042
6136
  if (hasCriticalRisks && !opts.force) {
6043
- console.error(chalk7.red("\n \u2716 Critical risks detected. Use --force to submit anyway."));
6137
+ console.error(chalk9.red("\n \u2716 Critical risks detected. Use --force to submit anyway."));
6044
6138
  process.exit(1);
6045
6139
  }
6046
6140
  }
6047
- const spinner = ora6({ text: W3("Submitting proposal..."), color: "green" }).start();
6141
+ const spinner = ora7({ text: W3("Submitting proposal..."), color: "green" }).start();
6048
6142
  const envelope = await resolveRiskEnvelope(opts, vault);
6049
6143
  const executeCallCaps = resolveCaps(
6050
6144
  opts.executeCaps,
@@ -6078,13 +6172,13 @@ function registerProposalCommands(program2) {
6078
6172
  SEP3();
6079
6173
  console.log();
6080
6174
  } catch (err) {
6081
- console.error(chalk7.red(`
6175
+ console.error(chalk9.red(`
6082
6176
  \u2716 ${formatContractError(err)}`));
6083
6177
  process.exit(1);
6084
6178
  }
6085
6179
  });
6086
6180
  proposal.command("list").description("List a vault's proposals (per-vault governor \u2014 IDs are scoped to the vault)").requiredOption("--vault <address>", "Vault whose proposals to list").option("--state <filter>", "Filter by state: draft, pending, approved, executed, settled, all", "all").action(async (opts) => {
6087
- const spinner = ora6("Loading proposals...").start();
6181
+ const spinner = ora7("Loading proposals...").start();
6088
6182
  try {
6089
6183
  const vault = parseVaultOption(opts.vault, spinner);
6090
6184
  const count = await proposalCount(vault);
@@ -6132,12 +6226,12 @@ function registerProposalCommands(program2) {
6132
6226
  console.log();
6133
6227
  } catch (err) {
6134
6228
  spinner.fail("Failed to load proposals");
6135
- console.error(chalk7.red(formatContractError(err)));
6229
+ console.error(chalk9.red(formatContractError(err)));
6136
6230
  process.exit(1);
6137
6231
  }
6138
6232
  });
6139
6233
  proposal.command("show").description("Show full proposal details").argument("<id>", "Proposal ID").requiredOption("--vault <address>", "Vault the proposal belongs to (per-vault governor)").action(async (idStr, opts) => {
6140
- const spinner = ora6("Loading proposal...").start();
6234
+ const spinner = ora7("Loading proposal...").start();
6141
6235
  try {
6142
6236
  const vault = parseVaultOption(opts.vault, spinner);
6143
6237
  const id = parseBigIntArg(idStr, "proposal ID");
@@ -6211,7 +6305,7 @@ function registerProposalCommands(program2) {
6211
6305
  console.log();
6212
6306
  } catch (err) {
6213
6307
  spinner.fail("Failed to load proposal");
6214
- console.error(chalk7.red(formatContractError(err)));
6308
+ console.error(chalk9.red(formatContractError(err)));
6215
6309
  process.exit(1);
6216
6310
  }
6217
6311
  });
@@ -6222,7 +6316,7 @@ function registerProposalCommands(program2) {
6222
6316
  const supportRaw = String(opts.support).toLowerCase();
6223
6317
  const support = supportRaw === "yes" || supportRaw === "for" ? VOTE_TYPE.For : supportRaw === "no" || supportRaw === "against" ? VOTE_TYPE.Against : supportRaw === "abstain" ? VOTE_TYPE.Abstain : null;
6224
6318
  if (support === null) {
6225
- console.error(chalk7.red(`Invalid support value "${opts.support}". Use for|against|abstain.`));
6319
+ console.error(chalk9.red(`Invalid support value "${opts.support}". Use for|against|abstain.`));
6226
6320
  process.exit(1);
6227
6321
  }
6228
6322
  if (isCalldataOnly()) {
@@ -6236,7 +6330,7 @@ function registerProposalCommands(program2) {
6236
6330
  return;
6237
6331
  }
6238
6332
  const account = getAccount();
6239
- const spinner = ora6("Loading proposal...").start();
6333
+ const spinner = ora7("Loading proposal...").start();
6240
6334
  const p = await getProposal(vault, proposalId);
6241
6335
  const state = await getProposalState(vault, proposalId);
6242
6336
  if (state !== PROPOSAL_STATE.Pending) {
@@ -6256,17 +6350,17 @@ function registerProposalCommands(program2) {
6256
6350
  console.log(W3(` Proposal: #${proposalId}`));
6257
6351
  console.log(W3(` Vault: ${G3(p.vault)}`));
6258
6352
  console.log(W3(
6259
- ` Support: ${support === VOTE_TYPE.For ? G3("FOR") : support === VOTE_TYPE.Against ? chalk7.red("AGAINST") : DIM3("ABSTAIN")}`
6353
+ ` Support: ${support === VOTE_TYPE.For ? G3("FOR") : support === VOTE_TYPE.Against ? chalk9.red("AGAINST") : DIM3("ABSTAIN")}`
6260
6354
  ));
6261
6355
  console.log(W3(` Weight: ${formatShares(weight)} shares`));
6262
6356
  SEP3();
6263
- const voteSpinner = ora6({ text: W3("Submitting vote..."), color: "green" }).start();
6357
+ const voteSpinner = ora7({ text: W3("Submitting vote..."), color: "green" }).start();
6264
6358
  const hash = await vote(vault, proposalId, support);
6265
6359
  voteSpinner.succeed(G3("Vote cast"));
6266
6360
  console.log(DIM3(` ${getExplorerUrl(hash)}`));
6267
6361
  console.log();
6268
6362
  } catch (err) {
6269
- console.error(chalk7.red(`
6363
+ console.error(chalk9.red(`
6270
6364
  \u2716 ${formatContractError(err)}`));
6271
6365
  process.exit(1);
6272
6366
  }
@@ -6284,7 +6378,7 @@ function registerProposalCommands(program2) {
6284
6378
  );
6285
6379
  return;
6286
6380
  }
6287
- const spinner = ora6("Loading proposal...").start();
6381
+ const spinner = ora7("Loading proposal...").start();
6288
6382
  const [state, p, latestBlock] = await Promise.all([
6289
6383
  getProposalState(vault, proposalId),
6290
6384
  getProposal(vault, proposalId),
@@ -6347,7 +6441,7 @@ function registerProposalCommands(program2) {
6347
6441
  }
6348
6442
  console.log();
6349
6443
  } catch (err) {
6350
- console.error(chalk7.red(`
6444
+ console.error(chalk9.red(`
6351
6445
  \u2716 ${formatContractError(err)}`));
6352
6446
  process.exit(1);
6353
6447
  }
@@ -6369,7 +6463,7 @@ function registerProposalCommands(program2) {
6369
6463
  return;
6370
6464
  }
6371
6465
  const account = getAccount();
6372
- const spinner = ora6("Loading proposal...").start();
6466
+ const spinner = ora7("Loading proposal...").start();
6373
6467
  const [p, state, latestBlock] = await Promise.all([
6374
6468
  getProposal(vault, proposalId),
6375
6469
  getProposalState(vault, proposalId),
@@ -6403,7 +6497,7 @@ function registerProposalCommands(program2) {
6403
6497
  console.log(DIM3(` ${getExplorerUrl(hash)}`));
6404
6498
  console.log();
6405
6499
  } catch (err) {
6406
- console.error(chalk7.red(`
6500
+ console.error(chalk9.red(`
6407
6501
  \u2716 ${formatContractError(err)}`));
6408
6502
  process.exit(1);
6409
6503
  }
@@ -6427,7 +6521,7 @@ function registerProposalCommands(program2) {
6427
6521
  return;
6428
6522
  }
6429
6523
  const account = getAccount();
6430
- const spinner = ora6("Loading proposal...").start();
6524
+ const spinner = ora7("Loading proposal...").start();
6431
6525
  const p = await getProposal(vault, proposalId);
6432
6526
  const state = await getProposalState(vault, proposalId);
6433
6527
  if (state !== PROPOSAL_STATE.Executed) {
@@ -6508,7 +6602,7 @@ function registerProposalCommands(program2) {
6508
6602
  return;
6509
6603
  }
6510
6604
  if (!opts.yes) {
6511
- process.stdout.write(chalk7.yellow(" Proceed? [y/N] "));
6605
+ process.stdout.write(chalk9.yellow(" Proceed? [y/N] "));
6512
6606
  const answer = await new Promise((resolve3) => {
6513
6607
  process.stdin.resume();
6514
6608
  process.stdin.setEncoding("utf-8");
@@ -6520,7 +6614,7 @@ function registerProposalCommands(program2) {
6520
6614
  return;
6521
6615
  }
6522
6616
  }
6523
- const send = ora6("Broadcasting emergencySettle...").start();
6617
+ const send = ora7("Broadcasting emergencySettle...").start();
6524
6618
  const hash = await emergencySettle(vault, proposalId, fallbackCalls);
6525
6619
  send.succeed(G3("Vault unstuck \u2014 proposal Settled"));
6526
6620
  console.log(DIM3(` ${getExplorerUrl(hash)}`));
@@ -6529,20 +6623,20 @@ function registerProposalCommands(program2) {
6529
6623
  console.log(G3(" redemptionsLocked cleared \u2713"));
6530
6624
  } else {
6531
6625
  console.log(
6532
- chalk7.yellow(
6626
+ chalk9.yellow(
6533
6627
  ` \u26A0 getActiveProposal(vault) still returns ${stillActive} \u2014 check manually.`
6534
6628
  )
6535
6629
  );
6536
6630
  }
6537
6631
  console.log();
6538
6632
  } catch (err) {
6539
- console.error(chalk7.red(`
6633
+ console.error(chalk9.red(`
6540
6634
  \u2716 ${formatContractError(err)}`));
6541
6635
  process.exit(1);
6542
6636
  }
6543
6637
  });
6544
6638
  proposal.command("resolve-reviews").description("Keeper: resolve guardian reviews whose review window has elapsed").requiredOption("--vault <address>", "Vault whose governor's reviews to scan (per-vault governor)").option("--dry-run", "List resolvable reviews without sending transactions").action(async (opts) => {
6545
- const spinner = ora6("Scanning proposals for resolvable reviews...").start();
6639
+ const spinner = ora7("Scanning proposals for resolvable reviews...").start();
6546
6640
  try {
6547
6641
  const vault = parseVaultOption(opts.vault, spinner);
6548
6642
  const registryAddr = getRegistryAddress();
@@ -6620,7 +6714,7 @@ function registerProposalCommands(program2) {
6620
6714
  }
6621
6715
  const resolved = [];
6622
6716
  for (const c of resolvable) {
6623
- const txSpinner = ora6(`Resolving review for proposal #${c.id}...`).start();
6717
+ const txSpinner = ora7(`Resolving review for proposal #${c.id}...`).start();
6624
6718
  try {
6625
6719
  const { result: blocked } = await pc.simulateContract({
6626
6720
  address: registryAddr,
@@ -6640,7 +6734,7 @@ function registerProposalCommands(program2) {
6640
6734
  await waitForReceipt(hash);
6641
6735
  resolved.push({ id: c.id, blocked, hash });
6642
6736
  txSpinner.succeed(
6643
- G3(`Proposal #${c.id} resolved \u2014 blocked=${blocked ? chalk7.red("true") : "false"}`)
6737
+ G3(`Proposal #${c.id} resolved \u2014 blocked=${blocked ? chalk9.red("true") : "false"}`)
6644
6738
  );
6645
6739
  } catch (err) {
6646
6740
  txSpinner.fail(`Proposal #${c.id} resolve failed: ${formatContractError(err)}`);
@@ -6651,7 +6745,7 @@ function registerProposalCommands(program2) {
6651
6745
  SEP3();
6652
6746
  for (const r of resolved) {
6653
6747
  console.log(
6654
- W3(` Proposal #${r.id} blocked=${r.blocked ? chalk7.red("true") : "false"} `) + DIM3(getExplorerUrl(r.hash))
6748
+ W3(` Proposal #${r.id} blocked=${r.blocked ? chalk9.red("true") : "false"} `) + DIM3(getExplorerUrl(r.hash))
6655
6749
  );
6656
6750
  }
6657
6751
  SEP3();
@@ -6659,7 +6753,7 @@ function registerProposalCommands(program2) {
6659
6753
  if (resolved.length < resolvable.length) process.exit(1);
6660
6754
  } catch (err) {
6661
6755
  spinner.fail("Failed to scan reviews");
6662
- console.error(chalk7.red(formatContractError(err)));
6756
+ console.error(chalk9.red(formatContractError(err)));
6663
6757
  process.exit(1);
6664
6758
  }
6665
6759
  });
@@ -6676,7 +6770,7 @@ function registerProposalCommands(program2) {
6676
6770
  );
6677
6771
  return;
6678
6772
  }
6679
- const spinner = ora6("Loading proposal...").start();
6773
+ const spinner = ora7("Loading proposal...").start();
6680
6774
  const state = await getProposalState(vault, proposalId);
6681
6775
  if (state === PROPOSAL_STATE.Settled || state === PROPOSAL_STATE.Cancelled) {
6682
6776
  spinner.fail(`Proposal is already ${PROPOSAL_STATES[state]}`);
@@ -6717,7 +6811,7 @@ function registerProposalCommands(program2) {
6717
6811
  console.log(DIM3(` ${getExplorerUrl(hash)}`));
6718
6812
  console.log();
6719
6813
  } catch (err) {
6720
- console.error(chalk7.red(`
6814
+ console.error(chalk9.red(`
6721
6815
  \u2716 ${formatContractError(err)}`));
6722
6816
  process.exit(1);
6723
6817
  }
@@ -6730,13 +6824,13 @@ function registerProposalCommands(program2) {
6730
6824
  let riskContext = {};
6731
6825
  let proposalId;
6732
6826
  if (opts.id) {
6733
- if (!opts.vault || !isAddress7(opts.vault)) {
6734
- console.error(chalk7.red("\n \u2716 --vault is required when using --id (proposal IDs are per-vault)"));
6827
+ if (!opts.vault || !isAddress9(opts.vault)) {
6828
+ console.error(chalk9.red("\n \u2716 --vault is required when using --id (proposal IDs are per-vault)"));
6735
6829
  process.exit(1);
6736
6830
  }
6737
6831
  vault = opts.vault;
6738
6832
  proposalId = parseBigIntArg(opts.id, "proposal ID");
6739
- const spinner2 = ora6("Loading proposal...").start();
6833
+ const spinner2 = ora7("Loading proposal...").start();
6740
6834
  const p = await getProposal(vault, proposalId);
6741
6835
  executeCalls = await getExecuteCalls(vault, proposalId);
6742
6836
  settlementCalls = await getSettlementCalls(vault, proposalId);
@@ -6754,8 +6848,8 @@ function registerProposalCommands(program2) {
6754
6848
  console.log(DIM3(`
6755
6849
  Simulating proposal #${proposalId} on vault ${vault.slice(0, 10)}...`));
6756
6850
  } else if (opts.executeCalls) {
6757
- if (!opts.vault || !isAddress7(opts.vault)) {
6758
- console.error(chalk7.red("\n \u2716 --vault is required when using --execute-calls"));
6851
+ if (!opts.vault || !isAddress9(opts.vault)) {
6852
+ console.error(chalk9.red("\n \u2716 --vault is required when using --execute-calls"));
6759
6853
  process.exit(1);
6760
6854
  }
6761
6855
  vault = opts.vault;
@@ -6765,22 +6859,22 @@ function registerProposalCommands(program2) {
6765
6859
  }
6766
6860
  riskContext = { vault };
6767
6861
  } else {
6768
- console.error(chalk7.red("\n \u2716 Provide --id <proposalId> or --execute-calls <path>"));
6862
+ console.error(chalk9.red("\n \u2716 Provide --id <proposalId> or --execute-calls <path>"));
6769
6863
  process.exit(1);
6770
6864
  }
6771
- const spinner = ora6({ text: W3("Simulating execute calls..."), color: "green" }).start();
6865
+ const spinner = ora7({ text: W3("Simulating execute calls..."), color: "green" }).start();
6772
6866
  const execResult = await simulateBatchCalls(vault, executeCalls, "execute", riskContext);
6773
6867
  spinner.stop();
6774
6868
  printSimulationResult(execResult, "execute");
6775
6869
  let settleResult;
6776
6870
  if (settlementCalls.length > 0) {
6777
- const settleSpinner = ora6({ text: W3("Simulating settlement calls..."), color: "green" }).start();
6871
+ const settleSpinner = ora7({ text: W3("Simulating settlement calls..."), color: "green" }).start();
6778
6872
  settleResult = await simulateBatchCalls(vault, settlementCalls, "settlement", riskContext);
6779
6873
  settleSpinner.stop();
6780
6874
  printSimulationResult(settleResult, "settlement");
6781
6875
  }
6782
6876
  if (opts.notify && proposalId !== void 0) {
6783
- const notifySpinner = ora6({ text: W3("Sending XMTP alert..."), color: "green" }).start();
6877
+ const notifySpinner = ora7({ text: W3("Sending XMTP alert..."), color: "green" }).start();
6784
6878
  await sendSimulationAlert(opts.notify, proposalId, vault, execResult, settleResult);
6785
6879
  notifySpinner.succeed(G3("Risk report sent to chat"));
6786
6880
  }
@@ -6789,7 +6883,7 @@ function registerProposalCommands(program2) {
6789
6883
  process.exit(1);
6790
6884
  }
6791
6885
  } catch (err) {
6792
- console.error(chalk7.red(`
6886
+ console.error(chalk9.red(`
6793
6887
  \u2716 ${err instanceof Error ? err.message : String(err)}`));
6794
6888
  process.exit(1);
6795
6889
  }
@@ -6797,9 +6891,9 @@ function registerProposalCommands(program2) {
6797
6891
  }
6798
6892
 
6799
6893
  // src/commands/queue.ts
6800
- import { parseUnits as parseUnits7, formatUnits as formatUnits6, isAddress as isAddress8, parseEventLogs } from "viem";
6801
- import chalk8 from "chalk";
6802
- import ora7 from "ora";
6894
+ import { parseUnits as parseUnits9, formatUnits as formatUnits9, isAddress as isAddress10, parseEventLogs } from "viem";
6895
+ import chalk10 from "chalk";
6896
+ import ora8 from "ora";
6803
6897
  var WETH_ABI2 = [
6804
6898
  { name: "deposit", type: "function", stateMutability: "payable", inputs: [], outputs: [] }
6805
6899
  ];
@@ -6933,8 +7027,8 @@ var QUEUE_ABI = [
6933
7027
  ];
6934
7028
  var KIND_LABELS = ["Redeem", "Deposit"];
6935
7029
  function resolveVaultAddress(opt) {
6936
- if (!opt || !isAddress8(opt)) {
6937
- console.error(chalk8.red(`Invalid or missing --vault address: ${opt ?? "(none)"}`));
7030
+ if (!opt || !isAddress10(opt)) {
7031
+ console.error(chalk10.red(`Invalid or missing --vault address: ${opt ?? "(none)"}`));
6938
7032
  process.exit(1);
6939
7033
  }
6940
7034
  return opt;
@@ -6964,10 +7058,10 @@ function registerQueueCommands(program2) {
6964
7058
  const vault = resolveVaultAddress(opts.vault);
6965
7059
  const account = getAccount();
6966
7060
  const client = getPublicClient();
6967
- const spinner = ora7(`Queueing deposit of ${opts.amount}...`).start();
7061
+ const spinner = ora8(`Queueing deposit of ${opts.amount}...`).start();
6968
7062
  try {
6969
7063
  const { asset, decimals } = await getVaultAsset(vault);
6970
- const assets = parseUnits7(opts.amount, decimals);
7064
+ const assets = parseUnits9(opts.amount, decimals);
6971
7065
  if (opts.useEth) {
6972
7066
  if (asset.toLowerCase() !== TOKENS().WETH.toLowerCase()) {
6973
7067
  throw new Error("--use-eth is only supported for WETH vaults.");
@@ -6986,7 +7080,7 @@ function registerQueueCommands(program2) {
6986
7080
  );
6987
7081
  if (ethBalance < shortfall + minGas) {
6988
7082
  throw new Error(
6989
- `Insufficient ETH on ${getChain().name}. Have ${formatUnits6(ethBalance, 18)} ETH, need ${formatUnits6(shortfall, 18)} to wrap + ~${formatUnits6(minGas, 18)} for gas.`
7083
+ `Insufficient ETH on ${getChain().name}. Have ${formatUnits9(ethBalance, 18)} ETH, need ${formatUnits9(shortfall, 18)} to wrap + ~${formatUnits9(minGas, 18)} for gas.`
6990
7084
  );
6991
7085
  }
6992
7086
  spinner.text = "Wrapping ETH \u2192 WETH...";
@@ -7038,16 +7132,16 @@ function registerQueueCommands(program2) {
7038
7132
  const id = logs[0]?.args?.requestId;
7039
7133
  if (id === void 0) {
7040
7134
  spinner.fail("Deposit queued but could not read requestId from logs");
7041
- console.log(chalk8.dim(` ${getExplorerUrl(hash)}`));
7135
+ console.log(chalk10.dim(` ${getExplorerUrl(hash)}`));
7042
7136
  process.exit(1);
7043
7137
  }
7044
7138
  const req = await readRequest(await getQueueAddress(vault), id);
7045
7139
  spinner.succeed(`Queued deposit request #${id} (pid ${req.pid})`);
7046
7140
  console.log(`Queued deposit request #${id} (pid ${req.pid})`);
7047
- console.log(chalk8.dim(` ${getExplorerUrl(hash)}`));
7141
+ console.log(chalk10.dim(` ${getExplorerUrl(hash)}`));
7048
7142
  } catch (err) {
7049
7143
  spinner.fail("Queue deposit failed");
7050
- console.error(chalk8.red(formatContractError(err)));
7144
+ console.error(chalk10.red(formatContractError(err)));
7051
7145
  process.exit(1);
7052
7146
  }
7053
7147
  });
@@ -7055,7 +7149,7 @@ function registerQueueCommands(program2) {
7055
7149
  const vault = resolveVaultAddress(opts.vault);
7056
7150
  const account = getAccount();
7057
7151
  const shares = BigInt(opts.shares);
7058
- const spinner = ora7(`Queueing redeem of ${opts.shares} shares...`).start();
7152
+ const spinner = ora8(`Queueing redeem of ${opts.shares} shares...`).start();
7059
7153
  try {
7060
7154
  const hash = await writeContractWithRetry({
7061
7155
  account,
@@ -7074,16 +7168,16 @@ function registerQueueCommands(program2) {
7074
7168
  const id = logs[0]?.args?.requestId;
7075
7169
  if (id === void 0) {
7076
7170
  spinner.fail("Redeem queued but could not read requestId from logs");
7077
- console.log(chalk8.dim(` ${getExplorerUrl(hash)}`));
7171
+ console.log(chalk10.dim(` ${getExplorerUrl(hash)}`));
7078
7172
  process.exit(1);
7079
7173
  }
7080
7174
  const req = await readRequest(await getQueueAddress(vault), id);
7081
7175
  spinner.succeed(`Queued redeem request #${id} (pid ${req.pid})`);
7082
7176
  console.log(`Queued redeem request #${id} (pid ${req.pid})`);
7083
- console.log(chalk8.dim(` ${getExplorerUrl(hash)}`));
7177
+ console.log(chalk10.dim(` ${getExplorerUrl(hash)}`));
7084
7178
  } catch (err) {
7085
7179
  spinner.fail("Queue redeem failed");
7086
- console.error(chalk8.red(formatContractError(err)));
7180
+ console.error(chalk10.red(formatContractError(err)));
7087
7181
  process.exit(1);
7088
7182
  }
7089
7183
  });
@@ -7091,7 +7185,7 @@ function registerQueueCommands(program2) {
7091
7185
  const vault = resolveVaultAddress(opts.vault);
7092
7186
  const account = getAccount();
7093
7187
  const id = BigInt(opts.id);
7094
- const spinner = ora7(`Claiming request #${id}...`).start();
7188
+ const spinner = ora8(`Claiming request #${id}...`).start();
7095
7189
  try {
7096
7190
  const queueAddr = await getQueueAddress(vault);
7097
7191
  const hash = await writeContractWithRetry({
@@ -7108,10 +7202,10 @@ function registerQueueCommands(program2) {
7108
7202
  const unit = req.kind === 1 ? "shares" : "assets";
7109
7203
  void receipt;
7110
7204
  spinner.succeed(`Claimed ${label} request #${id} \u2192 received ${unit}`);
7111
- console.log(chalk8.dim(` ${getExplorerUrl(hash)}`));
7205
+ console.log(chalk10.dim(` ${getExplorerUrl(hash)}`));
7112
7206
  } catch (err) {
7113
7207
  spinner.fail("Claim failed");
7114
- console.error(chalk8.red(formatContractError(err)));
7208
+ console.error(chalk10.red(formatContractError(err)));
7115
7209
  process.exit(1);
7116
7210
  }
7117
7211
  });
@@ -7119,7 +7213,7 @@ function registerQueueCommands(program2) {
7119
7213
  const vault = resolveVaultAddress(opts.vault);
7120
7214
  const account = getAccount();
7121
7215
  const id = BigInt(opts.id);
7122
- const spinner = ora7(`Cancelling request #${id}...`).start();
7216
+ const spinner = ora8(`Cancelling request #${id}...`).start();
7123
7217
  try {
7124
7218
  const queueAddr = await getQueueAddress(vault);
7125
7219
  const hash = await writeContractWithRetry({
@@ -7132,10 +7226,10 @@ function registerQueueCommands(program2) {
7132
7226
  });
7133
7227
  await waitForReceipt(hash);
7134
7228
  spinner.succeed(`Cancelled request #${id}`);
7135
- console.log(chalk8.dim(` ${getExplorerUrl(hash)}`));
7229
+ console.log(chalk10.dim(` ${getExplorerUrl(hash)}`));
7136
7230
  } catch (err) {
7137
7231
  spinner.fail("Cancel failed (request may already be settled \u2014 cancel is only allowed before the price is stamped)");
7138
- console.error(chalk8.red(formatContractError(err)));
7232
+ console.error(chalk10.red(formatContractError(err)));
7139
7233
  process.exit(1);
7140
7234
  }
7141
7235
  });
@@ -7143,7 +7237,7 @@ function registerQueueCommands(program2) {
7143
7237
  const vault = resolveVaultAddress(opts.vault);
7144
7238
  const account = getAccount();
7145
7239
  const client = getPublicClient();
7146
- const spinner = ora7("Loading queue requests...").start();
7240
+ const spinner = ora8("Loading queue requests...").start();
7147
7241
  try {
7148
7242
  const queueAddr = await getQueueAddress(vault);
7149
7243
  const ids = await client.readContract({
@@ -7154,16 +7248,16 @@ function registerQueueCommands(program2) {
7154
7248
  });
7155
7249
  if (ids.length === 0) {
7156
7250
  spinner.stop();
7157
- console.log(chalk8.dim(" No queue requests for this address."));
7251
+ console.log(chalk10.dim(" No queue requests for this address."));
7158
7252
  return;
7159
7253
  }
7160
7254
  const requests = await Promise.all(ids.map((id) => readRequest(queueAddr, id)));
7161
7255
  spinner.stop();
7162
7256
  console.log();
7163
- console.log(chalk8.bold(`Queue requests (${ids.length}) \u2014 ${account.address}`));
7164
- console.log(chalk8.dim("\u2500".repeat(72)));
7257
+ console.log(chalk10.bold(`Queue requests (${ids.length}) \u2014 ${account.address}`));
7258
+ console.log(chalk10.dim("\u2500".repeat(72)));
7165
7259
  console.log(
7166
- chalk8.dim(
7260
+ chalk10.dim(
7167
7261
  ` ${"id".padEnd(6)}${"kind".padEnd(9)}${"amount".padEnd(26)}${"pid".padEnd(6)}${"claimed".padEnd(9)}cancelled`
7168
7262
  )
7169
7263
  );
@@ -7177,26 +7271,26 @@ function registerQueueCommands(program2) {
7177
7271
  console.log();
7178
7272
  } catch (err) {
7179
7273
  spinner.fail("Failed to load queue requests");
7180
- console.error(chalk8.red(formatContractError(err)));
7274
+ console.error(chalk10.red(formatContractError(err)));
7181
7275
  process.exit(1);
7182
7276
  }
7183
7277
  });
7184
7278
  }
7185
7279
 
7186
7280
  // src/commands/governor.ts
7187
- import chalk9 from "chalk";
7188
- import ora8 from "ora";
7189
- import { isAddress as isAddress9 } from "viem";
7190
- var G4 = chalk9.green;
7191
- var W4 = chalk9.white;
7192
- var DIM4 = chalk9.gray;
7193
- var BOLD4 = chalk9.white.bold;
7194
- var LABEL4 = chalk9.green.bold;
7281
+ import chalk11 from "chalk";
7282
+ import ora9 from "ora";
7283
+ import { isAddress as isAddress11 } from "viem";
7284
+ var G4 = chalk11.green;
7285
+ var W4 = chalk11.white;
7286
+ var DIM4 = chalk11.gray;
7287
+ var BOLD4 = chalk11.white.bold;
7288
+ var LABEL4 = chalk11.green.bold;
7195
7289
  var SEP4 = () => console.log(DIM4("\u2500".repeat(60)));
7196
7290
  function parseVaultArg(raw) {
7197
7291
  const vault = String(raw);
7198
- if (!isAddress9(vault)) {
7199
- console.error(chalk9.red(`Invalid vault address: ${vault}`));
7292
+ if (!isAddress11(vault)) {
7293
+ console.error(chalk11.red(`Invalid vault address: ${vault}`));
7200
7294
  process.exit(1);
7201
7295
  }
7202
7296
  return vault;
@@ -7215,19 +7309,19 @@ function registerParamSetter(governor, spec) {
7215
7309
  )
7216
7310
  );
7217
7311
  } catch (err) {
7218
- console.error(chalk9.red(formatContractError(err)));
7312
+ console.error(chalk11.red(formatContractError(err)));
7219
7313
  process.exit(1);
7220
7314
  }
7221
7315
  return;
7222
7316
  }
7223
- const spinner = ora8(spec.spinnerText).start();
7317
+ const spinner = ora9(spec.spinnerText).start();
7224
7318
  try {
7225
7319
  const hash = await spec.setter(vault, parseBigIntArg(rawValue, spec.valueLabel));
7226
7320
  spinner.succeed(G4(spec.succeed(rawValue)));
7227
7321
  console.log(DIM4(` ${getExplorerUrl(hash)}`));
7228
7322
  } catch (err) {
7229
7323
  spinner.fail(spec.failText);
7230
- console.error(chalk9.red(formatContractError(err)));
7324
+ console.error(chalk11.red(formatContractError(err)));
7231
7325
  process.exit(1);
7232
7326
  }
7233
7327
  });
@@ -7236,7 +7330,7 @@ function registerGovernorCommands(program2) {
7236
7330
  const governor = program2.command("governor").description("Per-vault governor parameters");
7237
7331
  governor.command("info").description("Display a vault's governor address and parameters").requiredOption("--vault <address>", "Vault whose governor to inspect").action(async (opts) => {
7238
7332
  const vault = parseVaultArg(opts.vault);
7239
- const spinner = ora8("Loading governor info...").start();
7333
+ const spinner = ora9("Loading governor info...").start();
7240
7334
  try {
7241
7335
  const [governorAddress, params] = await Promise.all([
7242
7336
  getGovernorOf(vault),
@@ -7258,7 +7352,7 @@ function registerGovernorCommands(program2) {
7258
7352
  console.log();
7259
7353
  } catch (err) {
7260
7354
  spinner.fail("Failed to load governor info");
7261
- console.error(chalk9.red(formatContractError(err)));
7355
+ console.error(chalk11.red(formatContractError(err)));
7262
7356
  process.exit(1);
7263
7357
  }
7264
7358
  });
@@ -7346,12 +7440,12 @@ function registerGovernorCommands(program2) {
7346
7440
  )
7347
7441
  );
7348
7442
  } catch (err) {
7349
- console.error(chalk9.red(formatContractError(err)));
7443
+ console.error(chalk11.red(formatContractError(err)));
7350
7444
  process.exit(1);
7351
7445
  }
7352
7446
  return;
7353
7447
  }
7354
- const spinner = ora8("Setting protocol fee...").start();
7448
+ const spinner = ora9("Setting protocol fee...").start();
7355
7449
  try {
7356
7450
  const hash = await setProtocolFeeBps(parseBigIntArg(rawValue, "bps"));
7357
7451
  const configAddress = await getProtocolConfigAddress();
@@ -7361,23 +7455,23 @@ function registerGovernorCommands(program2) {
7361
7455
  console.log(DIM4(` ${getExplorerUrl(hash)}`));
7362
7456
  } catch (err) {
7363
7457
  spinner.fail("Failed to set protocol fee");
7364
- console.error(chalk9.red(formatContractError(err)));
7458
+ console.error(chalk11.red(formatContractError(err)));
7365
7459
  process.exit(1);
7366
7460
  }
7367
7461
  });
7368
7462
  }
7369
7463
 
7370
7464
  // src/commands/grid.ts
7371
- import chalk15 from "chalk";
7465
+ import chalk17 from "chalk";
7372
7466
  import { createInterface as createInterface2 } from "readline/promises";
7373
7467
 
7374
7468
  // src/grid/loop.ts
7375
- import chalk14 from "chalk";
7469
+ import chalk16 from "chalk";
7376
7470
  import { appendFile, mkdir as mkdir4 } from "fs/promises";
7377
7471
  import { dirname as dirname4 } from "path";
7378
7472
 
7379
7473
  // src/grid/manager.ts
7380
- import chalk10 from "chalk";
7474
+ import chalk12 from "chalk";
7381
7475
 
7382
7476
  // src/grid/portfolio.ts
7383
7477
  import { readFile, writeFile, rename, mkdir } from "fs/promises";
@@ -7596,7 +7690,7 @@ var GridManager = class {
7596
7690
  return { fills: 0, roundTrips: 0, pnlUsd: 0, paused: state.paused };
7597
7691
  }
7598
7692
  if (regime === "high-volatility") {
7599
- console.error(chalk10.dim(` [grid] Paused: high-volatility regime \u2014 too risky for grid`));
7693
+ console.error(chalk12.dim(` [grid] Paused: high-volatility regime \u2014 too risky for grid`));
7600
7694
  return { fills: 0, roundTrips: 0, pnlUsd: 0, paused: false };
7601
7695
  }
7602
7696
  this.portfolio.resetDailyStats(state);
@@ -7642,13 +7736,13 @@ var GridManager = class {
7642
7736
  async buildGrid(grid, currentPrice) {
7643
7737
  const candles = await this.candleFetcher(grid.token, "4h", 14 * 24 * 60 * 60 * 1e3);
7644
7738
  if (!candles || candles.length < this.config.atrPeriod) {
7645
- console.error(chalk10.dim(` [grid] Cannot build grid for ${grid.token}: insufficient candle data`));
7739
+ console.error(chalk12.dim(` [grid] Cannot build grid for ${grid.token}: insufficient candle data`));
7646
7740
  return;
7647
7741
  }
7648
7742
  const signals = getLatestSignals(candles);
7649
7743
  const atr = signals.atr;
7650
7744
  if (!Number.isFinite(atr) || atr <= 0) {
7651
- console.error(chalk10.dim(` [grid] Cannot build grid for ${grid.token}: invalid ATR (${atr})`));
7745
+ console.error(chalk12.dim(` [grid] Cannot build grid for ${grid.token}: invalid ATR (${atr})`));
7652
7746
  return;
7653
7747
  }
7654
7748
  const TREND_LOOKBACK_BARS = 14;
@@ -7691,7 +7785,7 @@ var GridManager = class {
7691
7785
  grid.atr = atr;
7692
7786
  grid.trend = trend;
7693
7787
  grid.stats.lastRebalanceAt = Date.now();
7694
- console.error(chalk10.dim(
7788
+ console.error(chalk12.dim(
7695
7789
  ` [grid] Built ${grid.token} grid: center=$${currentPrice.toFixed(2)} ATR=$${atr.toFixed(2)} range=$${(currentPrice - range).toFixed(2)}-$${(currentPrice + range).toFixed(2)} spacing=$${spacing.toFixed(2)} qty=${quantity.toFixed(6)} trend=${(trend * 100).toFixed(1)}%${inDowntrend ? " [DOWNTREND: 1 buy / " + this.config.levelsPerSide + " sells]" : ""}`
7696
7790
  ));
7697
7791
  }
@@ -7731,7 +7825,7 @@ var GridManager = class {
7731
7825
  pnlUsd: 0,
7732
7826
  closedAt: 0
7733
7827
  });
7734
- console.error(chalk10.dim(
7828
+ console.error(chalk12.dim(
7735
7829
  ` [grid] BUY fill ${grid.token} @ $${level.price.toFixed(2)} qty=${level.quantity.toFixed(6)}`
7736
7830
  ));
7737
7831
  }
@@ -7741,7 +7835,7 @@ var GridManager = class {
7741
7835
  fills++;
7742
7836
  grid.stats.totalFills++;
7743
7837
  grid.stats.todayFills++;
7744
- console.error(chalk10.dim(
7838
+ console.error(chalk12.dim(
7745
7839
  ` [grid] SELL level ${grid.token} @ $${level.price.toFixed(2)} qty=${level.quantity.toFixed(6)}`
7746
7840
  ));
7747
7841
  }
@@ -7760,7 +7854,7 @@ var GridManager = class {
7760
7854
  grid.stats.totalPnlUsd += profit;
7761
7855
  grid.stats.todayPnlUsd += profit;
7762
7856
  grid.allocation += profit;
7763
- console.error(chalk10.green(
7857
+ console.error(chalk12.green(
7764
7858
  ` [grid] ROUND-TRIP ${grid.token}: buy $${openFill.buyPrice.toFixed(2)} \u2192 sell $${currentPrice.toFixed(2)} = +$${profit.toFixed(2)}`
7765
7859
  ));
7766
7860
  }
@@ -7779,7 +7873,7 @@ var GridManager = class {
7779
7873
  grid.stats.totalPnlUsd += realizedLoss;
7780
7874
  grid.stats.todayPnlUsd += realizedLoss;
7781
7875
  grid.allocation += realizedLoss;
7782
- console.error(chalk10.red(
7876
+ console.error(chalk12.red(
7783
7877
  ` [grid] STOP-LOSS ${grid.token}: buy $${openFill.buyPrice.toFixed(2)} \u2192 close $${currentPrice.toFixed(2)} = $${realizedLoss.toFixed(2)}`
7784
7878
  ));
7785
7879
  }
@@ -7804,7 +7898,7 @@ var GridManager = class {
7804
7898
  }
7805
7899
  /** Shift the grid to re-center on the current price. */
7806
7900
  async shiftGrid(grid, currentPrice) {
7807
- console.error(chalk10.dim(
7901
+ console.error(chalk12.dim(
7808
7902
  ` [grid] Shifting ${grid.token} grid: center $${grid.centerPrice.toFixed(2)} \u2192 $${currentPrice.toFixed(2)}`
7809
7903
  ));
7810
7904
  await this.buildGrid(grid, currentPrice);
@@ -7928,7 +8022,7 @@ var DEFAULT_GRID_CONFIG = {
7928
8022
  // src/grid/hedge.ts
7929
8023
  import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
7930
8024
  import { dirname as dirname2 } from "path";
7931
- import chalk11 from "chalk";
8025
+ import chalk13 from "chalk";
7932
8026
  var HEDGE_RATIO_DEFAULT = Number.isFinite(Number(process.env.HEDGE_RATIO)) ? Number(process.env.HEDGE_RATIO) : 0.3;
7933
8027
  function hedgeRatioFor(marketTrend) {
7934
8028
  if (process.env.HEDGE_RATIO !== void 0 && Number.isFinite(Number(process.env.HEDGE_RATIO))) {
@@ -8011,7 +8105,7 @@ var GridHedgeManager = class {
8011
8105
  state.totalRealizedPnl += closePnl;
8012
8106
  state.todayRealizedPnl += closePnl;
8013
8107
  existing.realizedPnl += closePnl;
8014
- console.error(chalk11.yellow(
8108
+ console.error(chalk13.yellow(
8015
8109
  ` [hedge] CLOSE ${fill.token} short ${existing.quantity.toFixed(6)} @ $${price.toFixed(2)} PnL: $${closePnl.toFixed(2)}`
8016
8110
  ));
8017
8111
  existing.quantity = 0;
@@ -8028,7 +8122,7 @@ var GridHedgeManager = class {
8028
8122
  lastAdjustedAt: Date.now(),
8029
8123
  realizedPnl: 0
8030
8124
  });
8031
- console.error(chalk11.magenta(
8125
+ console.error(chalk13.magenta(
8032
8126
  ` [hedge] OPEN ${fill.token} short ${desiredShortQty.toFixed(6)} @ $${price.toFixed(2)} (${(activeRatio * 100).toFixed(0)}% of ${fill.fillCount} open fills)`
8033
8127
  ));
8034
8128
  adjustments++;
@@ -8041,7 +8135,7 @@ var GridHedgeManager = class {
8041
8135
  existing.entryPrice = newAvgEntry;
8042
8136
  existing.quantity = desiredShortQty;
8043
8137
  existing.lastAdjustedAt = Date.now();
8044
- console.error(chalk11.magenta(
8138
+ console.error(chalk13.magenta(
8045
8139
  ` [hedge] INCREASE ${fill.token} short to ${desiredShortQty.toFixed(6)} @ avg $${newAvgEntry.toFixed(2)}`
8046
8140
  ));
8047
8141
  adjustments++;
@@ -8053,7 +8147,7 @@ var GridHedgeManager = class {
8053
8147
  existing.realizedPnl += closePnl;
8054
8148
  existing.quantity = desiredShortQty;
8055
8149
  existing.lastAdjustedAt = Date.now();
8056
- console.error(chalk11.magenta(
8150
+ console.error(chalk13.magenta(
8057
8151
  ` [hedge] DECREASE ${fill.token} short to ${desiredShortQty.toFixed(6)}, closed ${closeQty.toFixed(6)} PnL: $${closePnl.toFixed(2)}`
8058
8152
  ));
8059
8153
  adjustments++;
@@ -8065,7 +8159,7 @@ var GridHedgeManager = class {
8065
8159
  existing.entryPrice = price;
8066
8160
  existing.quantity = desiredShortQty;
8067
8161
  existing.lastAdjustedAt = Date.now();
8068
- console.error(chalk11.magenta(
8162
+ console.error(chalk13.magenta(
8069
8163
  ` [hedge] REOPEN ${fill.token} short ${desiredShortQty.toFixed(6)} @ $${price.toFixed(2)}`
8070
8164
  ));
8071
8165
  adjustments++;
@@ -8080,7 +8174,7 @@ var GridHedgeManager = class {
8080
8174
  state.totalRealizedPnl += closePnl;
8081
8175
  state.todayRealizedPnl += closePnl;
8082
8176
  pos.realizedPnl += closePnl;
8083
- console.error(chalk11.yellow(
8177
+ console.error(chalk13.yellow(
8084
8178
  ` [hedge] CLOSE orphaned ${pos.token} short, PnL: $${closePnl.toFixed(2)}`
8085
8179
  ));
8086
8180
  pos.quantity = 0;
@@ -8140,7 +8234,7 @@ var GridHedgeManager = class {
8140
8234
  };
8141
8235
 
8142
8236
  // src/grid/executor.ts
8143
- import chalk12 from "chalk";
8237
+ import chalk14 from "chalk";
8144
8238
  var GridExecutor = class {
8145
8239
  cfg;
8146
8240
  constructor(cfg) {
@@ -8163,7 +8257,7 @@ var GridExecutor = class {
8163
8257
  try {
8164
8258
  await hlCancelAllOrders(coin);
8165
8259
  cancelled++;
8166
- console.error(chalk12.dim(` [grid-exec] Cancelled all orders for ${coin}`));
8260
+ console.error(chalk14.dim(` [grid-exec] Cancelled all orders for ${coin}`));
8167
8261
  } catch (e) {
8168
8262
  errors.push(`Cancel ${coin} failed: ${e.message}`);
8169
8263
  }
@@ -8190,16 +8284,16 @@ var GridExecutor = class {
8190
8284
  };
8191
8285
 
8192
8286
  // src/grid/onchain-executor.ts
8193
- import chalk13 from "chalk";
8287
+ import chalk15 from "chalk";
8194
8288
  import { mkdir as mkdir3, readFile as readFile3, rename as rename2, writeFile as writeFile3 } from "fs/promises";
8195
8289
  import { dirname as dirname3 } from "path";
8196
- import { encodeAbiParameters as encodeAbiParameters5, parseUnits as parseUnits8 } from "viem";
8290
+ import { encodeAbiParameters as encodeAbiParameters7, parseUnits as parseUnits10 } from "viem";
8197
8291
 
8198
8292
  // src/grid/cloid.ts
8199
- import { keccak256 as keccak2562, encodeAbiParameters as encodeAbiParameters4 } from "viem";
8293
+ import { keccak256 as keccak2562, encodeAbiParameters as encodeAbiParameters6 } from "viem";
8200
8294
  function gridCloid(strategy2, assetIndex, isBuy, levelIndex, nonce) {
8201
8295
  const hash = keccak2562(
8202
- encodeAbiParameters4(
8296
+ encodeAbiParameters6(
8203
8297
  [
8204
8298
  { type: "address" },
8205
8299
  { type: "uint32" },
@@ -8275,13 +8369,13 @@ var OnchainGridExecutor = class {
8275
8369
  for (const [tok, cloids] of Object.entries(state.placedCloids)) {
8276
8370
  this.placedCloids.set(tok, cloids.map((s) => BigInt(s)));
8277
8371
  }
8278
- console.error(chalk13.dim(` [grid-onchain] Loaded state: ${this.nonces.size} tokens`));
8372
+ console.error(chalk15.dim(` [grid-onchain] Loaded state: ${this.nonces.size} tokens`));
8279
8373
  } catch (e) {
8280
8374
  const code = e.code;
8281
8375
  if (code === "ENOENT") {
8282
8376
  } else {
8283
8377
  console.error(
8284
- chalk13.yellow(
8378
+ chalk15.yellow(
8285
8379
  ` [grid-onchain] Failed to load state (${e.message}) \u2014 starting fresh. Existing on-chain orders may be orphaned.`
8286
8380
  )
8287
8381
  );
@@ -8401,8 +8495,8 @@ var OnchainGridExecutor = class {
8401
8495
  const encoded = orders.map((o, i) => {
8402
8496
  const cloid = gridCloid(this.cfg.strategyAddress, assetIndex, o.isBuy, i, nonce);
8403
8497
  cloids.push(cloid);
8404
- const limitPx = parseUnits8(o.price.toFixed(meta.pxDecimals), meta.pxDecimals);
8405
- const sz = parseUnits8(o.quantity.toFixed(meta.szDecimals), meta.szDecimals);
8498
+ const limitPx = parseUnits10(o.price.toFixed(meta.pxDecimals), meta.pxDecimals);
8499
+ const sz = parseUnits10(o.quantity.toFixed(meta.szDecimals), meta.szDecimals);
8406
8500
  if (limitPx > UINT64_MAX || sz > UINT64_MAX) {
8407
8501
  throw new Error(
8408
8502
  `Order exceeds uint64: token=${o.token} px=${limitPx} sz=${sz}`
@@ -8426,7 +8520,7 @@ var OnchainGridExecutor = class {
8426
8520
  for (const chunk of chunks) {
8427
8521
  const nonce = this.bumpNonce(token);
8428
8522
  const { encoded, cloids } = this.encodeOrders(assetIndex, chunk, meta, nonce);
8429
- const data = encodeAbiParameters5(
8523
+ const data = encodeAbiParameters7(
8430
8524
  [{ type: "uint8" }, { type: "tuple[]", components: [...GRID_ORDER_COMPONENTS] }],
8431
8525
  [ACTION_PLACE_GRID, encoded]
8432
8526
  );
@@ -8444,7 +8538,7 @@ var OnchainGridExecutor = class {
8444
8538
  this.bumpNonce(token);
8445
8539
  return "0x";
8446
8540
  }
8447
- const data = encodeAbiParameters5(
8541
+ const data = encodeAbiParameters7(
8448
8542
  [{ type: "uint8" }, { type: "uint32" }, { type: "uint128[]" }],
8449
8543
  [ACTION_CANCEL_ALL, assetIndex, cloids]
8450
8544
  );
@@ -8473,7 +8567,7 @@ var OnchainGridExecutor = class {
8473
8567
  const { encoded, cloids } = this.encodeOrders(assetIndex, chunk, meta, newNonce);
8474
8568
  let data;
8475
8569
  if (i === 0) {
8476
- data = encodeAbiParameters5(
8570
+ data = encodeAbiParameters7(
8477
8571
  [
8478
8572
  { type: "uint8" },
8479
8573
  { type: "uint32" },
@@ -8483,7 +8577,7 @@ var OnchainGridExecutor = class {
8483
8577
  [ACTION_CANCEL_AND_PLACE, assetIndex, oldCloids, encoded]
8484
8578
  );
8485
8579
  } else {
8486
- data = encodeAbiParameters5(
8580
+ data = encodeAbiParameters7(
8487
8581
  [{ type: "uint8" }, { type: "tuple[]", components: [...GRID_ORDER_COMPONENTS] }],
8488
8582
  [ACTION_PLACE_GRID, encoded]
8489
8583
  );
@@ -8554,7 +8648,7 @@ var OnchainGridExecutor = class {
8554
8648
  if (receipt.status !== "success") {
8555
8649
  throw new Error(`Tx ${tx} reverted on-chain`);
8556
8650
  }
8557
- console.error(chalk13.dim(` [grid-onchain] tx ${tx.slice(0, 10)}... confirmed`));
8651
+ console.error(chalk15.dim(` [grid-onchain] tx ${tx.slice(0, 10)}... confirmed`));
8558
8652
  return tx;
8559
8653
  }
8560
8654
  };
@@ -8605,7 +8699,7 @@ var GridLoop = class {
8605
8699
  async start() {
8606
8700
  this.running = true;
8607
8701
  const shutdown = () => {
8608
- console.error(chalk14.yellow("\n [grid-loop] Shutting down\u2026"));
8702
+ console.error(chalk16.yellow("\n [grid-loop] Shutting down\u2026"));
8609
8703
  this.running = false;
8610
8704
  if (this.timer) {
8611
8705
  clearTimeout(this.timer);
@@ -8618,7 +8712,7 @@ var GridLoop = class {
8618
8712
  if (this.executor instanceof OnchainGridExecutor) {
8619
8713
  await this.executor.load();
8620
8714
  }
8621
- console.error(chalk14.cyan(
8715
+ console.error(chalk16.cyan(
8622
8716
  `
8623
8717
  [grid-loop] Started \u2014 capital=$${this.cfg.capital.toFixed(0)} cycle=${(this.cfg.cycle / 1e3).toFixed(0)}s tokens=[${this.gridConfig.tokens.join(", ")}] leverage=${this.gridConfig.leverage}x levels=${this.gridConfig.levelsPerSide}/side state-dir=${gridStateDir(this.cfg.stateDir)}
8624
8718
  `
@@ -8627,7 +8721,7 @@ var GridLoop = class {
8627
8721
  try {
8628
8722
  await this.tick();
8629
8723
  } catch (err) {
8630
- console.error(chalk14.red(` [grid-loop] Tick error: ${err.message}`));
8724
+ console.error(chalk16.red(` [grid-loop] Tick error: ${err.message}`));
8631
8725
  }
8632
8726
  if (this.running) {
8633
8727
  await new Promise((resolve3) => {
@@ -8637,7 +8731,7 @@ var GridLoop = class {
8637
8731
  }
8638
8732
  process.off("SIGINT", shutdown);
8639
8733
  process.off("SIGTERM", shutdown);
8640
- console.error(chalk14.yellow(" [grid-loop] Stopped."));
8734
+ console.error(chalk16.yellow(" [grid-loop] Stopped."));
8641
8735
  }
8642
8736
  /** Execute one grid cycle. */
8643
8737
  async tick() {
@@ -8651,7 +8745,7 @@ var GridLoop = class {
8651
8745
  }
8652
8746
  }
8653
8747
  if (Object.keys(prices).length === 0) {
8654
- console.error(chalk14.dim(` [grid-loop] #${this.cycleCount} \u2014 no prices, skipping`));
8748
+ console.error(chalk16.dim(` [grid-loop] #${this.cycleCount} \u2014 no prices, skipping`));
8655
8749
  return;
8656
8750
  }
8657
8751
  const result = await this.manager.tick(prices);
@@ -8661,20 +8755,20 @@ var GridLoop = class {
8661
8755
  if (plan.ordersToPlace.length > 0 || plan.assetsToCancel.length > 0) {
8662
8756
  const res = await this.executor.execute(plan);
8663
8757
  if (res.errors.length > 0) {
8664
- console.error(chalk14.yellow(` [grid-loop] Executor errors: ${res.errors.join("; ")}`));
8758
+ console.error(chalk16.yellow(` [grid-loop] Executor errors: ${res.errors.join("; ")}`));
8665
8759
  }
8666
8760
  if (res.placed > 0 || res.cancelled > 0) {
8667
- console.error(chalk14.cyan(` [grid-loop] Live: placed=${res.placed} cancelled=${res.cancelled}`));
8761
+ console.error(chalk16.cyan(` [grid-loop] Live: placed=${res.placed} cancelled=${res.cancelled}`));
8668
8762
  }
8669
8763
  }
8670
8764
  }
8671
8765
  if (result.roundTrips > 0) {
8672
- console.error(chalk14.green(
8766
+ console.error(chalk16.green(
8673
8767
  ` [grid-loop] #${this.cycleCount} \u2014 ${result.roundTrips} RT(s), +$${result.pnlUsd.toFixed(2)} PnL, ${result.fills} fill(s) [${elapsed}ms]`
8674
8768
  ));
8675
8769
  }
8676
8770
  if (result.fills > 0 && result.roundTrips === 0) {
8677
- console.error(chalk14.dim(
8771
+ console.error(chalk16.dim(
8678
8772
  ` [grid-loop] #${this.cycleCount} \u2014 ${result.fills} fill(s), 0 RTs [${elapsed}ms]`
8679
8773
  ));
8680
8774
  }
@@ -8682,7 +8776,7 @@ var GridLoop = class {
8682
8776
  const marketTrend = this.manager.getMarketTrend();
8683
8777
  const hedgeResult = await this.hedge.tick(openExposure, prices, Date.now(), marketTrend, result.paused);
8684
8778
  if (hedgeResult.adjustments > 0) {
8685
- console.error(chalk14.magenta(
8779
+ console.error(chalk16.magenta(
8686
8780
  ` [hedge] ${hedgeResult.adjustments} adjustment(s), unrealized: $${hedgeResult.unrealizedPnl.toFixed(2)}, total realized: $${hedgeResult.totalRealizedPnl.toFixed(2)}`
8687
8781
  ));
8688
8782
  }
@@ -8711,7 +8805,7 @@ var GridLoop = class {
8711
8805
  if (stats2) {
8712
8806
  const hedgeStatus = this.hedge.getStatus();
8713
8807
  const hedgeInfo = hedgeStatus && hedgeStatus.positions.length > 0 ? ` hedge=$${hedgeResult.unrealizedPnl.toFixed(2)}unr/$${hedgeStatus.totalRealizedPnl.toFixed(2)}real` : "";
8714
- console.error(chalk14.cyan(
8808
+ console.error(chalk16.cyan(
8715
8809
  ` [grid-loop] Status #${this.cycleCount} \u2014 totalPnL=$${stats2.totalPnlUsd.toFixed(2)} todayPnL=$${stats2.todayPnlUsd.toFixed(2)} RTs=${stats2.totalRoundTrips} alloc=$${stats2.allocation.toFixed(0)}${hedgeInfo}${stats2.paused ? " (PAUSED)" : ""}`
8716
8810
  ));
8717
8811
  }
@@ -9462,10 +9556,10 @@ async function runSweep(opts) {
9462
9556
  var DEFAULT_PAUSE_REASON = "Manually paused by operator";
9463
9557
  var DEFAULT_FLATTEN_REASON = "Manually flattened by operator";
9464
9558
  var CONFIRM_TIMEOUT_SECONDS = 60;
9465
- var DIM5 = chalk15.gray;
9466
- var G5 = chalk15.green;
9467
- var BOLD5 = chalk15.white.bold;
9468
- var W5 = chalk15.white;
9559
+ var DIM5 = chalk17.gray;
9560
+ var G5 = chalk17.green;
9561
+ var BOLD5 = chalk17.white.bold;
9562
+ var W5 = chalk17.white;
9469
9563
  var SEP5 = () => console.log(DIM5("\u2500".repeat(60)));
9470
9564
  function printSummary(r) {
9471
9565
  const dd = r.drawdown;
@@ -9499,7 +9593,7 @@ function printSummary(r) {
9499
9593
  console.log();
9500
9594
  console.log(BOLD5(" Per token:"));
9501
9595
  for (const t of r.perToken) {
9502
- const tokPnl = t.pnlUsd >= 0 ? G5(`+$${t.pnlUsd.toFixed(2)}`) : chalk15.red(`-$${Math.abs(t.pnlUsd).toFixed(2)}`);
9596
+ const tokPnl = t.pnlUsd >= 0 ? G5(`+$${t.pnlUsd.toFixed(2)}`) : chalk17.red(`-$${Math.abs(t.pnlUsd).toFixed(2)}`);
9503
9597
  console.log(W5(` ${t.token.padEnd(10)} $${t.allocation.initial.toFixed(0).padStart(6)} \u2192 $${t.allocation.final.toFixed(0).padStart(6)} ${tokPnl} RTs=${t.roundTrips} fills=${t.fills}`));
9504
9598
  }
9505
9599
  if (r.liquidations.events.length > 0) {
@@ -9511,7 +9605,7 @@ function printSummary(r) {
9511
9605
  }
9512
9606
  if (r.liquidations.haltedAt !== null) {
9513
9607
  const haltDate = new Date(r.liquidations.haltedAt).toISOString().slice(0, 10);
9514
- console.log(chalk15.red.bold(` RUN HALTED on ${haltDate} \u2014 all tokens liquidated.`));
9608
+ console.log(chalk17.red.bold(` RUN HALTED on ${haltDate} \u2014 all tokens liquidated.`));
9515
9609
  }
9516
9610
  }
9517
9611
  console.log();
@@ -9536,7 +9630,7 @@ function printSweepSummary(s) {
9536
9630
  for (let i = 0; i < s.runs.length; i++) {
9537
9631
  const r = s.runs[i];
9538
9632
  const rank = String(i + 1).padStart(4);
9539
- const surv = r.survived ? G5(" \u2713 ") : chalk15.red(" \u2717 ");
9633
+ const surv = r.survived ? G5(" \u2713 ") : chalk17.red(" \u2717 ");
9540
9634
  const lev = String(r.config.leverage ?? "").padStart(3);
9541
9635
  const lvls = String(r.config.levelsPerSide ?? "").padStart(6);
9542
9636
  const atr = String(r.config.atrMultiplier ?? "").padStart(4);
@@ -9546,7 +9640,7 @@ function printSweepSummary(s) {
9546
9640
  const netPct = `${(r.capital.pnlPct * 100).toFixed(1)}%`.padStart(8);
9547
9641
  const ddPct = `${(r.drawdown.maxPct * 100).toFixed(1)}%`.padStart(8);
9548
9642
  const ra = r.riskAdjusted.toFixed(2).padStart(8);
9549
- const pnlColor = r.capital.pnlUsd >= 0 ? G5 : chalk15.red;
9643
+ const pnlColor = r.capital.pnlUsd >= 0 ? G5 : chalk17.red;
9550
9644
  console.log(` ${rank} ${surv} ${lev} ${lvls} ${atr} ${drift} ${rts} ${pnlColor(netPnl)} ${pnlColor(netPct)} ${ddPct} ${ra}`);
9551
9645
  }
9552
9646
  console.log(DIM5(" " + "\u2500".repeat(102)));
@@ -9661,7 +9755,7 @@ function registerGridCommand(program2) {
9661
9755
  console.log(G5.bold(" Grid Portfolio"));
9662
9756
  SEP5();
9663
9757
  console.log(W5(` Allocation: $${state.totalAllocation.toLocaleString()}`));
9664
- console.log(W5(` Status: ${state.paused ? chalk15.red("PAUSED \u2014 " + state.pauseReason) : G5("Active")}`));
9758
+ console.log(W5(` Status: ${state.paused ? chalk17.red("PAUSED \u2014 " + state.pauseReason) : G5("Active")}`));
9665
9759
  console.log(W5(` Initialized: ${new Date(state.initializedAt).toLocaleString()}`));
9666
9760
  SEP5();
9667
9761
  console.log();
@@ -9674,13 +9768,13 @@ function registerGridCommand(program2) {
9674
9768
  const pnl = `$${g.stats.totalPnlUsd.toFixed(2)}`.padStart(10);
9675
9769
  const todayPnl = `$${g.stats.todayPnlUsd.toFixed(2)}`.padStart(10);
9676
9770
  const fills = String(g.stats.totalFills).padStart(6);
9677
- const pnlColor = g.stats.totalPnlUsd >= 0 ? G5 : chalk15.red;
9678
- const todayColor = g.stats.todayPnlUsd >= 0 ? G5 : chalk15.red;
9771
+ const pnlColor = g.stats.totalPnlUsd >= 0 ? G5 : chalk17.red;
9772
+ const todayColor = g.stats.todayPnlUsd >= 0 ? G5 : chalk17.red;
9679
9773
  console.log(` ${W5(name)} ${alloc} ${rts} ${pnlColor(pnl)} ${todayColor(todayPnl)} ${fills}`);
9680
9774
  }
9681
9775
  console.log(DIM5(" " + "\u2500".repeat(72)));
9682
- const totalPnlColor = agg.totalPnlUsd >= 0 ? G5 : chalk15.red;
9683
- const todayTotalColor = agg.todayPnlUsd >= 0 ? G5 : chalk15.red;
9776
+ const totalPnlColor = agg.totalPnlUsd >= 0 ? G5 : chalk17.red;
9777
+ const todayTotalColor = agg.todayPnlUsd >= 0 ? G5 : chalk17.red;
9684
9778
  console.log(` ${BOLD5("TOTAL".padEnd(13))} ${`$${state.totalAllocation.toFixed(0)}`.padStart(8)} ${String(agg.totalRoundTrips).padStart(6)} ${totalPnlColor(`$${agg.totalPnlUsd.toFixed(2)}`.padStart(10))} ${todayTotalColor(`$${agg.todayPnlUsd.toFixed(2)}`.padStart(10))} ${String(agg.todayFills).padStart(6)}`);
9685
9779
  console.log();
9686
9780
  });
@@ -9786,7 +9880,7 @@ function registerGridCommand(program2) {
9786
9880
  state.pauseReason = opts.reason;
9787
9881
  await portfolio.save(state);
9788
9882
  console.log();
9789
- console.log(chalk15.yellow(` Grid paused. Reason: ${state.pauseReason}`));
9883
+ console.log(chalk17.yellow(` Grid paused. Reason: ${state.pauseReason}`));
9790
9884
  console.log(DIM5(" Next manager.tick will be a no-op until you run `sherwood grid resume`."));
9791
9885
  console.log();
9792
9886
  });
@@ -9810,7 +9904,7 @@ function registerGridCommand(program2) {
9810
9904
  await portfolio.save(state);
9811
9905
  console.log();
9812
9906
  if (wasCircuitBroken) {
9813
- console.log(chalk15.yellow(` Hard circuit breaker cleared.`));
9907
+ console.log(chalk17.yellow(` Hard circuit breaker cleared.`));
9814
9908
  }
9815
9909
  console.log(G5(` Grid resumed. (was paused: ${wasReason || "<unknown>"})`));
9816
9910
  console.log();
@@ -9846,7 +9940,7 @@ function registerGridCommand(program2) {
9846
9940
  console.log(W5(` Will pause: yes \u2014 reason: "${opts.reason}"`));
9847
9941
  SEP5();
9848
9942
  if (opts.dryRun) {
9849
- console.log(chalk15.yellow(" --dry-run set \u2014 no state or chain mutation."));
9943
+ console.log(chalk17.yellow(" --dry-run set \u2014 no state or chain mutation."));
9850
9944
  console.log();
9851
9945
  return;
9852
9946
  }
@@ -9859,7 +9953,7 @@ function registerGridCommand(program2) {
9859
9953
  const timer = setTimeout(() => ac.abort(), CONFIRM_TIMEOUT_SECONDS * 1e3);
9860
9954
  let answer;
9861
9955
  try {
9862
- answer = (await rl.question(chalk15.yellow(" Proceed with flatten? [y/N] "), { signal: ac.signal })).trim().toLowerCase();
9956
+ answer = (await rl.question(chalk17.yellow(" Proceed with flatten? [y/N] "), { signal: ac.signal })).trim().toLowerCase();
9863
9957
  } catch (e) {
9864
9958
  if (e.name === "AbortError") {
9865
9959
  console.log(DIM5(`
@@ -9889,7 +9983,7 @@ function registerGridCommand(program2) {
9889
9983
  console.log(DIM5(` Skipped (no tracked CLOIDs): ${res.skipped.join(", ")}`));
9890
9984
  }
9891
9985
  if (res.errors.length > 0) {
9892
- for (const err of res.errors) console.log(chalk15.red(` Cancel error: ${err}`));
9986
+ for (const err of res.errors) console.log(chalk17.red(` Cancel error: ${err}`));
9893
9987
  }
9894
9988
  }
9895
9989
  if (openHedges.length > 0) {
@@ -9907,7 +10001,7 @@ function registerGridCommand(program2) {
9907
10001
  }
9908
10002
  }
9909
10003
  if (hres.skipped.length > 0) {
9910
- console.log(chalk15.yellow(` Hedge skipped (no mark price): ${hres.skipped.join(", ")}`));
10004
+ console.log(chalk17.yellow(` Hedge skipped (no mark price): ${hres.skipped.join(", ")}`));
9911
10005
  }
9912
10006
  console.log(W5(` Total hedge realized PnL: $${hres.totalRealizedPnl.toFixed(2)}`));
9913
10007
  } else {
@@ -9917,7 +10011,7 @@ function registerGridCommand(program2) {
9917
10011
  state.paused = true;
9918
10012
  state.pauseReason = opts.reason;
9919
10013
  await portfolio.save(state);
9920
- console.log(chalk15.yellow(` Grid paused. Reason: ${state.pauseReason}`));
10014
+ console.log(chalk17.yellow(` Grid paused. Reason: ${state.pauseReason}`));
9921
10015
  } else {
9922
10016
  console.log(DIM5(` Grid was already paused: ${state.pauseReason}`));
9923
10017
  }
@@ -9933,22 +10027,22 @@ try {
9933
10027
  } catch {
9934
10028
  }
9935
10029
  var require2 = createRequire(import.meta.url);
9936
- var CLI_VERSION = "0.82.0";
10030
+ var CLI_VERSION = "0.83.1";
9937
10031
  async function loadXmtp() {
9938
- return import("./xmtp-M74BRF3G.js");
10032
+ return import("./xmtp-2U7CSBXM.js");
9939
10033
  }
9940
10034
  async function loadCron() {
9941
- return import("./cron-QMLRWDJG.js");
10035
+ return import("./cron-E3UAZF5B.js");
9942
10036
  }
9943
- var G6 = chalk16.green;
9944
- var W6 = chalk16.white;
9945
- var DIM6 = chalk16.gray;
9946
- var BOLD6 = chalk16.white.bold;
9947
- var LABEL5 = chalk16.green.bold;
10037
+ var G6 = chalk18.green;
10038
+ var W6 = chalk18.white;
10039
+ var DIM6 = chalk18.gray;
10040
+ var BOLD6 = chalk18.white.bold;
10041
+ var LABEL5 = chalk18.green.bold;
9948
10042
  var SEP6 = () => console.log(DIM6("\u2500".repeat(60)));
9949
10043
  function validateAddress(value, name) {
9950
- if (!isAddress10(value)) {
9951
- console.error(chalk16.red(`Invalid ${name} address: ${value}`));
10044
+ if (!isAddress12(value)) {
10045
+ console.error(chalk18.red(`Invalid ${name} address: ${value}`));
9952
10046
  process.exit(1);
9953
10047
  }
9954
10048
  return value;
@@ -9964,7 +10058,10 @@ function resolveVault(opts) {
9964
10058
  }
9965
10059
  var program = new Command();
9966
10060
  program.name("sherwood").description("CLI for agent-managed investment funds").version(CLI_VERSION).addOption(
9967
- new Option("--chain <network>", "Target network").choices(VALID_NETWORKS).default(DEFAULT_NETWORK)
10061
+ new Option(
10062
+ "--chain <network>",
10063
+ "Target network (default: robinhood-fork, chain 9994663 \u2014 where the product lives; robinhood-testnet is chain 46630)"
10064
+ ).choices(VALID_NETWORKS).default(DEFAULT_NETWORK)
9968
10065
  ).option(
9969
10066
  "--calldata-only",
9970
10067
  "Print unsigned EIP-5792 calldata as JSON instead of signing/sending (for external signers \u2014 no private key required)",
@@ -10024,13 +10121,13 @@ fund.command("create").description("Create a new fund via the factory (interacti
10024
10121
  asset = opts.asset;
10025
10122
  } else {
10026
10123
  const supported = Object.keys(ASSET_SYMBOLS).join(", ");
10027
- console.error(chalk16.red(` Unknown asset "${opts.asset}". Use a symbol (${supported}) or a 0x address.`));
10124
+ console.error(chalk18.red(` Unknown asset "${opts.asset}". Use a symbol (${supported}) or a 0x address.`));
10028
10125
  process.exit(1);
10029
10126
  }
10030
10127
  } else if (nonInteractive) {
10031
10128
  const preferred = ["USDC", "USDG", "WETH"].find((s) => ASSET_SYMBOLS[s]);
10032
10129
  if (!preferred) {
10033
- console.error(chalk16.red(" No known vault asset on this chain. Pass --asset <0xaddress>."));
10130
+ console.error(chalk18.red(" No known vault asset on this chain. Pass --asset <0xaddress>."));
10034
10131
  process.exit(1);
10035
10132
  }
10036
10133
  asset = ASSET_SYMBOLS[preferred];
@@ -10046,7 +10143,7 @@ fund.command("create").description("Create a new fund via the factory (interacti
10046
10143
  description: DESCRIPTIONS[s]
10047
10144
  }));
10048
10145
  if (choices.length === 0) {
10049
- console.error(chalk16.red(" No known vault asset on this chain. Pass --asset <0xaddress>."));
10146
+ console.error(chalk18.red(" No known vault asset on this chain. Pass --asset <0xaddress>."));
10050
10147
  process.exit(1);
10051
10148
  }
10052
10149
  const assetChoice = await select({
@@ -10070,7 +10167,7 @@ fund.command("create").description("Create a new fund via the factory (interacti
10070
10167
  console.log(W6(` Agent ID: #${agentIdStr}`));
10071
10168
  console.log(W6(` Asset: ${assetSymbol} (${asset.slice(0, 10)}...)`));
10072
10169
  console.log(W6(` Share token: ${symbol}`));
10073
- console.log(W6(` Open deposits: ${openDeposits ? chalk16.yellow("yes (anyone can deposit)") : G6("no (whitelist)")}`));
10170
+ console.log(W6(` Open deposits: ${openDeposits ? chalk18.yellow("yes (anyone can deposit)") : G6("no (whitelist)")}`));
10074
10171
  SEP6();
10075
10172
  if (!nonInteractive) {
10076
10173
  const go = await confirm({ message: G6("Deploy fund?"), default: true });
@@ -10081,7 +10178,7 @@ fund.command("create").description("Create a new fund via the factory (interacti
10081
10178
  }
10082
10179
  let metadataURI = opts.metadataUri || "";
10083
10180
  if (!metadataURI) {
10084
- const spinner2 = ora9({ text: W6("Uploading metadata to IPFS..."), color: "green" }).start();
10181
+ const spinner2 = ora10({ text: W6("Uploading metadata to IPFS..."), color: "green" }).start();
10085
10182
  try {
10086
10183
  const metadata = {
10087
10184
  schema: "sherwood/fund/v1",
@@ -10097,7 +10194,7 @@ fund.command("create").description("Create a new fund via the factory (interacti
10097
10194
  metadataURI = await uploadMetadata(metadata);
10098
10195
  spinner2.succeed(G6(`Metadata pinned: ${DIM6(metadataURI)}`));
10099
10196
  } catch (err) {
10100
- spinner2.warn(chalk16.yellow(`IPFS upload failed \u2014 using inline metadata`));
10197
+ spinner2.warn(chalk18.yellow(`IPFS upload failed \u2014 using inline metadata`));
10101
10198
  const json = JSON.stringify({ name, description, subdomain, asset: assetSymbol, openDeposits, createdBy: "@sherwoodagent/cli" });
10102
10199
  metadataURI = `data:application/json;base64,${Buffer.from(json).toString("base64")}`;
10103
10200
  }
@@ -10124,15 +10221,15 @@ fund.command("create").description("Create a new fund via the factory (interacti
10124
10221
  const existingInfo = await getFund(existingId);
10125
10222
  const callerAddress = getAccount().address.toLowerCase();
10126
10223
  if (existingInfo.creator.toLowerCase() !== callerAddress) {
10127
- console.error(chalk16.red(`
10224
+ console.error(chalk18.red(`
10128
10225
  \u2716 Subdomain '${subdomain}' is already taken by another fund.
10129
10226
  `));
10130
10227
  process.exit(1);
10131
10228
  }
10132
- console.log(chalk16.yellow(`
10229
+ console.log(chalk18.yellow(`
10133
10230
  \u26A0 Fund '${subdomain}' already exists \u2014 resuming setup...
10134
10231
  `));
10135
- const spinner2 = ora9({ text: W6("Resuming setup..."), color: "green" }).start();
10232
+ const spinner2 = ora10({ text: W6("Resuming setup..."), color: "green" }).start();
10136
10233
  const chainId2 = getChain().id;
10137
10234
  setChainContract(chainId2, "vault", existingInfo.vault);
10138
10235
  addFund(chainId2, { subdomain, vault: existingInfo.vault, role: "creator" });
@@ -10160,11 +10257,11 @@ fund.command("create").description("Create a new fund via the factory (interacti
10160
10257
  try {
10161
10258
  await setTextRecord(subdomain, "xmtpGroupId", groupId, existingInfo.vault);
10162
10259
  } catch {
10163
- console.log(chalk16.dim(" ENS text record skipped (metadata fallback active)"));
10260
+ console.log(chalk18.dim(" ENS text record skipped (metadata fallback active)"));
10164
10261
  }
10165
10262
  }
10166
10263
  } catch {
10167
- console.warn(chalk16.yellow("\n \u26A0 Could not set up XMTP chat group"));
10264
+ console.warn(chalk18.yellow("\n \u26A0 Could not set up XMTP chat group"));
10168
10265
  }
10169
10266
  try {
10170
10267
  const cron = await loadCron();
@@ -10186,7 +10283,7 @@ fund.command("create").description("Create a new fund via the factory (interacti
10186
10283
  console.log();
10187
10284
  return;
10188
10285
  }
10189
- const spinner = ora9({ text: W6("Deploying vault via factory..."), color: "green" }).start();
10286
+ const spinner = ora10({ text: W6("Deploying vault via factory..."), color: "green" }).start();
10190
10287
  const result = await createFund({
10191
10288
  creatorAgentId: BigInt(agentIdStr),
10192
10289
  metadataURI,
@@ -10211,7 +10308,7 @@ fund.command("create").description("Create a new fund via the factory (interacti
10211
10308
  // agentAddress = creator EOA (direct execution)
10212
10309
  );
10213
10310
  } catch (regErr) {
10214
- console.warn(chalk16.yellow("\n \u26A0 Could not auto-register creator as agent \u2014 register manually with `fund add`"));
10311
+ console.warn(chalk18.yellow("\n \u26A0 Could not auto-register creator as agent \u2014 register manually with `fund add`"));
10215
10312
  }
10216
10313
  spinner.text = W6("Setting up chat...");
10217
10314
  try {
@@ -10222,11 +10319,11 @@ fund.command("create").description("Create a new fund via the factory (interacti
10222
10319
  try {
10223
10320
  await setTextRecord(subdomain, "xmtpGroupId", groupId, result.vault);
10224
10321
  } catch {
10225
- console.log(chalk16.dim(" ENS text record skipped (metadata fallback active)"));
10322
+ console.log(chalk18.dim(" ENS text record skipped (metadata fallback active)"));
10226
10323
  }
10227
10324
  } catch {
10228
- console.warn(chalk16.yellow("\n \u26A0 Could not create XMTP chat group"));
10229
- console.warn(chalk16.dim(` Recover later with: sherwood chat ${subdomain} init`));
10325
+ console.warn(chalk18.yellow("\n \u26A0 Could not create XMTP chat group"));
10326
+ console.warn(chalk18.dim(` Recover later with: sherwood chat ${subdomain} init`));
10230
10327
  }
10231
10328
  try {
10232
10329
  const cron = await loadCron();
@@ -10254,13 +10351,13 @@ fund.command("create").description("Create a new fund via the factory (interacti
10254
10351
  console.log(G6(" \u2713 Fund saved to ~/.sherwood/config.json (set as primary)"));
10255
10352
  console.log();
10256
10353
  } catch (err) {
10257
- console.error(chalk16.red(`
10354
+ console.error(chalk18.red(`
10258
10355
  \u2716 ${formatContractError(err)}`));
10259
10356
  process.exit(1);
10260
10357
  }
10261
10358
  });
10262
10359
  fund.command("list").description("List active funds (queries subgraph, falls back to on-chain)").option("--creator <address>", "Filter by creator address").option("--all-chains", "Aggregate active funds across all supported chains (on-chain only)").action(async (opts) => {
10263
- const spinner = ora9("Loading funds...").start();
10360
+ const spinner = ora10("Loading funds...").start();
10264
10361
  try {
10265
10362
  let funds = [];
10266
10363
  if (opts.allChains) {
@@ -10303,43 +10400,43 @@ fund.command("list").description("List active funds (queries subgraph, falls bac
10303
10400
  }
10304
10401
  spinner.stop();
10305
10402
  if (funds.length === 0) {
10306
- console.log(chalk16.dim("No active funds found."));
10403
+ console.log(chalk18.dim("No active funds found."));
10307
10404
  return;
10308
10405
  }
10309
10406
  console.log();
10310
- console.log(chalk16.bold(`Active Funds (${funds.length})`));
10407
+ console.log(chalk18.bold(`Active Funds (${funds.length})`));
10311
10408
  if (!process.env.SUBGRAPH_URL && !opts.allChains) {
10312
- console.log(chalk16.dim(" (Set SUBGRAPH_URL for faster indexed queries)"));
10409
+ console.log(chalk18.dim(" (Set SUBGRAPH_URL for faster indexed queries)"));
10313
10410
  }
10314
10411
  if (opts.allChains) {
10315
- console.log(chalk16.dim(" (Aggregated across chains via on-chain factory calls; SUBGRAPH_URL is single-chain only)"));
10412
+ console.log(chalk18.dim(" (Aggregated across chains via on-chain factory calls; SUBGRAPH_URL is single-chain only)"));
10316
10413
  }
10317
- console.log(chalk16.dim("\u2500".repeat(70)));
10414
+ console.log(chalk18.dim("\u2500".repeat(70)));
10318
10415
  for (const s of funds) {
10319
10416
  const ts = typeof s.createdAt === "string" ? Number(s.createdAt) : Number(s.createdAt);
10320
10417
  const date = new Date(ts * 1e3).toLocaleDateString();
10321
10418
  const ensName = s.subdomain ? `${s.subdomain}.sherwoodagent.eth` : "";
10322
- const chainTag = s.chain ? chalk16.dim(`[${s.chain}] `) : "";
10323
- console.log(` ${chainTag}#${s.id} ${chalk16.bold(ensName || String(s.vault))}`);
10324
- if (ensName) console.log(` Vault: ${chalk16.cyan(String(s.vault))}`);
10419
+ const chainTag = s.chain ? chalk18.dim(`[${s.chain}] `) : "";
10420
+ console.log(` ${chainTag}#${s.id} ${chalk18.bold(ensName || String(s.vault))}`);
10421
+ if (ensName) console.log(` Vault: ${chalk18.cyan(String(s.vault))}`);
10325
10422
  console.log(` Creator: ${s.creator}`);
10326
10423
  console.log(` Created: ${date}`);
10327
10424
  if (s.totalDeposits) {
10328
10425
  console.log(` Deposits: ${s.totalDeposits} USDC`);
10329
10426
  }
10330
10427
  if (s.metadataURI) {
10331
- console.log(` Metadata: ${chalk16.dim(s.metadataURI)}`);
10428
+ console.log(` Metadata: ${chalk18.dim(s.metadataURI)}`);
10332
10429
  }
10333
10430
  console.log();
10334
10431
  }
10335
10432
  } catch (err) {
10336
10433
  spinner.fail("Failed to load funds");
10337
- console.error(chalk16.red(formatContractError(err)));
10434
+ console.error(chalk18.red(formatContractError(err)));
10338
10435
  process.exit(1);
10339
10436
  }
10340
10437
  });
10341
10438
  fund.command("info").description("Display fund details by ID or subdomain").argument("<id>", "Fund ID or subdomain name").action(async (idStr) => {
10342
- const spinner = ora9("Loading fund info...").start();
10439
+ const spinner = ora10("Loading fund info...").start();
10343
10440
  try {
10344
10441
  let id;
10345
10442
  let crossChainHint = null;
@@ -10374,38 +10471,38 @@ fund.command("info").description("Display fund details by ID or subdomain").argu
10374
10471
  spinner.stop();
10375
10472
  if (crossChainHint) {
10376
10473
  const others = crossChainHint.others.length > 0 ? ` (also on: ${crossChainHint.others.join(", ")})` : "";
10377
- console.log(chalk16.yellow(` Found on chain: ${chalk16.bold(crossChainHint.network)}${others}`));
10378
- console.log(chalk16.dim(` Re-run with --chain ${crossChainHint.network} to interact with this fund.`));
10474
+ console.log(chalk18.yellow(` Found on chain: ${chalk18.bold(crossChainHint.network)}${others}`));
10475
+ console.log(chalk18.dim(` Re-run with --chain ${crossChainHint.network} to interact with this fund.`));
10379
10476
  console.log();
10380
10477
  }
10381
10478
  if (!info.vault || info.vault === "0x0000000000000000000000000000000000000000") {
10382
- console.log(chalk16.red(`Fund #${id} not found.`));
10479
+ console.log(chalk18.red(`Fund #${id} not found.`));
10383
10480
  process.exit(1);
10384
10481
  }
10385
10482
  const date = new Date(Number(info.createdAt) * 1e3).toLocaleDateString();
10386
10483
  console.log();
10387
- console.log(chalk16.bold(`Fund #${info.id}`));
10388
- console.log(chalk16.dim("\u2500".repeat(40)));
10484
+ console.log(chalk18.bold(`Fund #${info.id}`));
10485
+ console.log(chalk18.dim("\u2500".repeat(40)));
10389
10486
  if (info.subdomain) {
10390
- console.log(` ENS: ${chalk16.bold(`${info.subdomain}.sherwoodagent.eth`)}`);
10487
+ console.log(` ENS: ${chalk18.bold(`${info.subdomain}.sherwoodagent.eth`)}`);
10391
10488
  }
10392
- console.log(` Vault: ${chalk16.cyan(info.vault)}`);
10489
+ console.log(` Vault: ${chalk18.cyan(info.vault)}`);
10393
10490
  console.log(` Creator: ${info.creator}`);
10394
10491
  console.log(` Created: ${date}`);
10395
- console.log(` Active: ${info.active ? chalk16.green("yes") : chalk16.red("no")}`);
10492
+ console.log(` Active: ${info.active ? chalk18.green("yes") : chalk18.red("no")}`);
10396
10493
  if (info.metadataURI) {
10397
- console.log(` Metadata: ${chalk16.dim(info.metadataURI)}`);
10494
+ console.log(` Metadata: ${chalk18.dim(info.metadataURI)}`);
10398
10495
  }
10399
10496
  if (info.subdomain) {
10400
10497
  const xmtpGroupId = getCachedGroupId(info.subdomain);
10401
10498
  if (xmtpGroupId) {
10402
- console.log(` XMTP Group: ${chalk16.cyan(xmtpGroupId)}`);
10499
+ console.log(` XMTP Group: ${chalk18.cyan(xmtpGroupId)}`);
10403
10500
  }
10404
10501
  }
10405
10502
  setVaultAddress(info.vault);
10406
10503
  const vaultInfo = crossChainHint ? await withNetwork(crossChainHint.network, () => getVaultInfo()) : await getVaultInfo();
10407
10504
  console.log();
10408
- console.log(chalk16.bold(" Vault Stats"));
10505
+ console.log(chalk18.bold(" Vault Stats"));
10409
10506
  console.log(` Total Assets: ${vaultInfo.totalAssets}`);
10410
10507
  console.log(` Agent Count: ${vaultInfo.agentCount}`);
10411
10508
  console.log(` Redemptions Locked: ${vaultInfo.redemptionsLocked}`);
@@ -10413,12 +10510,12 @@ fund.command("info").description("Display fund details by ID or subdomain").argu
10413
10510
  console.log();
10414
10511
  } catch (err) {
10415
10512
  spinner.fail("Failed to load fund info");
10416
- console.error(chalk16.red(formatContractError(err)));
10513
+ console.error(chalk18.red(formatContractError(err)));
10417
10514
  process.exit(1);
10418
10515
  }
10419
10516
  });
10420
10517
  fund.command("update-metadata").description("Update fund metadata (creator only)").requiredOption("--id <id>", "Fund ID").option("--name <name>", "Fund name").option("--description <text>", "Short description").option("--uri <uri>", "Direct metadata URI (skips IPFS upload)").action(async (opts) => {
10421
- const spinner = ora9({ text: W6("Loading fund..."), color: "green" }).start();
10518
+ const spinner = ora10({ text: W6("Loading fund..."), color: "green" }).start();
10422
10519
  try {
10423
10520
  const fundId = BigInt(opts.id);
10424
10521
  let metadataURI = opts.uri;
@@ -10434,7 +10531,7 @@ fund.command("update-metadata").description("Update fund metadata (creator only)
10434
10531
  current = await fetchMetadata(info.metadataURI);
10435
10532
  } catch (fetchErr) {
10436
10533
  console.warn(
10437
- chalk16.yellow(
10534
+ chalk18.yellow(
10438
10535
  " \u26A0 Could not fetch current metadata \u2014 rebuilding from flags (unknown fields like xmtpGroupId may be dropped)"
10439
10536
  )
10440
10537
  );
@@ -10456,7 +10553,7 @@ fund.command("update-metadata").description("Update fund metadata (creator only)
10456
10553
  console.log(DIM6(` ${getExplorerUrl(hash)}`));
10457
10554
  } catch (err) {
10458
10555
  spinner.fail("Metadata update failed");
10459
- console.error(chalk16.red(formatContractError(err)));
10556
+ console.error(chalk18.red(formatContractError(err)));
10460
10557
  process.exit(1);
10461
10558
  }
10462
10559
  });
@@ -10472,28 +10569,28 @@ fund.command("approve-depositor").description("Approve an address to deposit (ow
10472
10569
  );
10473
10570
  return;
10474
10571
  }
10475
- const spinner = ora9("Approving depositor...").start();
10572
+ const spinner = ora10("Approving depositor...").start();
10476
10573
  try {
10477
10574
  const hash = await approveDepositor(depositor);
10478
10575
  spinner.succeed(`Depositor approved: ${hash}`);
10479
- console.log(chalk16.dim(` ${getExplorerUrl(hash)}`));
10576
+ console.log(chalk18.dim(` ${getExplorerUrl(hash)}`));
10480
10577
  } catch (err) {
10481
10578
  spinner.fail("Approval failed");
10482
- console.error(chalk16.red(formatContractError(err)));
10579
+ console.error(chalk18.red(formatContractError(err)));
10483
10580
  process.exit(1);
10484
10581
  }
10485
10582
  });
10486
10583
  fund.command("remove-depositor").description("Remove an address from the depositor whitelist (owner only)").option("--vault <address>", "Vault address (default: from config)").requiredOption("--depositor <address>", "Address to remove").action(async (opts) => {
10487
10584
  resolveVault(opts);
10488
- const spinner = ora9("Removing depositor...").start();
10585
+ const spinner = ora10("Removing depositor...").start();
10489
10586
  try {
10490
10587
  const depositor = validateAddress(opts.depositor, "depositor");
10491
10588
  const hash = await removeDepositor(depositor);
10492
10589
  spinner.succeed(`Depositor removed: ${hash}`);
10493
- console.log(chalk16.dim(` ${getExplorerUrl(hash)}`));
10590
+ console.log(chalk18.dim(` ${getExplorerUrl(hash)}`));
10494
10591
  } catch (err) {
10495
10592
  spinner.fail("Removal failed");
10496
- console.error(chalk16.red(formatContractError(err)));
10593
+ console.error(chalk18.red(formatContractError(err)));
10497
10594
  process.exit(1);
10498
10595
  }
10499
10596
  });
@@ -10502,17 +10599,17 @@ fund.command("set-agent-fee").description("Set the vault's agent performance fee
10502
10599
  `Agent fee in bps (e.g. 1000 = 10%; max ${MAX_AGENT_FEE_BPS} = ${MAX_AGENT_FEE_BPS / 100}%). The governor clamps the realized fee to its configured maxPerformanceFeeBps, which may be lower.`
10503
10600
  ).action(async (opts) => {
10504
10601
  resolveVault(opts);
10505
- const spinner = ora9("Setting agent fee...").start();
10602
+ const spinner = ora10("Setting agent fee...").start();
10506
10603
  try {
10507
10604
  const bps = parseBigIntArg(opts.bps, "bps");
10508
10605
  const hash = await setAgentFeeBps(bps);
10509
10606
  spinner.succeed(
10510
10607
  `Agent fee set to ${Number(bps) / 100}% (realized fee is clamped to the governor's maxPerformanceFeeBps): ${hash}`
10511
10608
  );
10512
- console.log(chalk16.dim(` ${getExplorerUrl(hash)}`));
10609
+ console.log(chalk18.dim(` ${getExplorerUrl(hash)}`));
10513
10610
  } catch (err) {
10514
10611
  spinner.fail("Failed to set agent fee");
10515
- console.error(chalk16.red(formatContractError(err)));
10612
+ console.error(chalk18.red(formatContractError(err)));
10516
10613
  process.exit(1);
10517
10614
  }
10518
10615
  });
@@ -10522,7 +10619,7 @@ fund.command("add").description("Register an agent on a fund vault (creator only
10522
10619
  const agentWallet = validateAddress(opts.wallet, "wallet");
10523
10620
  if (!opts.agentId) {
10524
10621
  console.error(
10525
- chalk16.red(
10622
+ chalk18.red(
10526
10623
  "--calldata-only requires --agent-id (auto-lookup from wallet is skipped in calldata mode)"
10527
10624
  )
10528
10625
  );
@@ -10540,7 +10637,7 @@ fund.command("add").description("Register an agent on a fund vault (creator only
10540
10637
  );
10541
10638
  return;
10542
10639
  }
10543
- const spinner = ora9("Verifying creator...").start();
10640
+ const spinner = ora10("Verifying creator...").start();
10544
10641
  try {
10545
10642
  resolveVault(opts);
10546
10643
  const vaultAddress = getVaultAddress();
@@ -10555,7 +10652,7 @@ fund.command("add").description("Register an agent on a fund vault (creator only
10555
10652
  if (opts.agentId) {
10556
10653
  agentId = BigInt(opts.agentId);
10557
10654
  } else {
10558
- const { AGENT_REGISTRY: AGENT_REGISTRY2 } = await import("./addresses-FGJ4I4IG.js");
10655
+ const { AGENT_REGISTRY: AGENT_REGISTRY2 } = await import("./addresses-MS6BB7AB.js");
10559
10656
  const registry = AGENT_REGISTRY2().IDENTITY_REGISTRY;
10560
10657
  if (registry === "0x0000000000000000000000000000000000000000") {
10561
10658
  agentId = 0n;
@@ -10576,7 +10673,7 @@ fund.command("add").description("Register an agent on a fund vault (creator only
10576
10673
  });
10577
10674
  if (balance === 0n) {
10578
10675
  spinner.fail("Agent wallet does not own an ERC-8004 identity NFT");
10579
- console.error(chalk16.dim(" Mint one first: sherwood identity mint --name <name>"));
10676
+ console.error(chalk18.dim(" Mint one first: sherwood identity mint --name <name>"));
10580
10677
  process.exit(1);
10581
10678
  }
10582
10679
  const tokenId = await client.readContract({
@@ -10592,13 +10689,13 @@ fund.command("add").description("Register an agent on a fund vault (creator only
10592
10689
  args: [agentWallet, 0n]
10593
10690
  });
10594
10691
  agentId = tokenId;
10595
- console.log(chalk16.dim(` Resolved agent ID: #${agentId}`));
10692
+ console.log(chalk18.dim(` Resolved agent ID: #${agentId}`));
10596
10693
  }
10597
10694
  }
10598
10695
  spinner.text = "Registering agent...";
10599
10696
  const hash = await registerAgent(agentId, agentWallet);
10600
10697
  spinner.succeed(`Agent registered: ${hash}`);
10601
- console.log(chalk16.dim(` ${getExplorerUrl(hash)}`));
10698
+ console.log(chalk18.dim(` ${getExplorerUrl(hash)}`));
10602
10699
  try {
10603
10700
  const xmtp = await loadXmtp();
10604
10701
  const xmtpClient = await xmtp.getXmtpClient();
@@ -10610,14 +10707,14 @@ fund.command("add").description("Register an agent on a fund vault (creator only
10610
10707
  fund: subdomain,
10611
10708
  timestamp: Math.floor(Date.now() / 1e3)
10612
10709
  });
10613
- console.log(chalk16.dim(` Added to chat: ${subdomain}`));
10710
+ console.log(chalk18.dim(` Added to chat: ${subdomain}`));
10614
10711
  } catch {
10615
- console.warn(chalk16.yellow(" \u26A0 Could not add agent to chat group"));
10616
- console.warn(chalk16.dim(` If no group exists, run: sherwood chat ${subdomain} init`));
10712
+ console.warn(chalk18.yellow(" \u26A0 Could not add agent to chat group"));
10713
+ console.warn(chalk18.dim(` If no group exists, run: sherwood chat ${subdomain} init`));
10617
10714
  }
10618
10715
  } catch (err) {
10619
10716
  spinner.fail("Registration failed");
10620
- console.error(chalk16.red(formatContractError(err)));
10717
+ console.error(chalk18.red(formatContractError(err)));
10621
10718
  process.exit(1);
10622
10719
  }
10623
10720
  });
@@ -10625,7 +10722,7 @@ fund.command("share").description("Print the shareable dashboard URL for your fu
10625
10722
  try {
10626
10723
  const subdomain = opts.subdomain || getPrimaryFund(getChain().id)?.subdomain;
10627
10724
  if (!subdomain) {
10628
- console.error(chalk16.red(" No fund configured. Pass --subdomain <name> or run 'fund create/join' first."));
10725
+ console.error(chalk18.red(" No fund configured. Pass --subdomain <name> or run 'fund create/join' first."));
10629
10726
  process.exit(1);
10630
10727
  }
10631
10728
  const fundInfo = await resolveFund(subdomain);
@@ -10652,12 +10749,12 @@ fund.command("share").description("Print the shareable dashboard URL for your fu
10652
10749
  }
10653
10750
  console.log();
10654
10751
  } catch (err) {
10655
- console.error(chalk16.red(` \u2716 ${formatContractError(err)}`));
10752
+ console.error(chalk18.red(` \u2716 ${formatContractError(err)}`));
10656
10753
  process.exit(1);
10657
10754
  }
10658
10755
  });
10659
10756
  fund.command("join").description("Request to join a fund (creates an EAS attestation)").option("--subdomain <name>", "Fund subdomain to join").option("--ref <agentId>", "Referrer agent ID (from invite link)").option("--message <text>", "Message to the creator", "Requesting to join your fund").action(async (opts) => {
10660
- const spinner = ora9("Resolving fund...").start();
10757
+ const spinner = ora10("Resolving fund...").start();
10661
10758
  try {
10662
10759
  const subdomain = opts.subdomain || getPrimaryFund(getChain().id)?.subdomain;
10663
10760
  if (!subdomain) {
@@ -10677,14 +10774,14 @@ fund.command("join").description("Request to join a fund (creates an EAS attesta
10677
10774
  const hits = await searchFundAcrossChains(subdomain);
10678
10775
  spinner.fail(`Fund "${subdomain}" not found on ${getNetwork()}`);
10679
10776
  if (hits.length === 0) {
10680
- console.error(chalk16.red(` Not found on any supported chain.`));
10777
+ console.error(chalk18.red(` Not found on any supported chain.`));
10681
10778
  } else if (hits.length === 1) {
10682
- console.error(chalk16.yellow(` Found on chain: ${chalk16.bold(hits[0].network)}`));
10683
- console.error(chalk16.dim(` Re-run: sherwood --chain ${hits[0].network} fund join --subdomain ${subdomain}`));
10779
+ console.error(chalk18.yellow(` Found on chain: ${chalk18.bold(hits[0].network)}`));
10780
+ console.error(chalk18.dim(` Re-run: sherwood --chain ${hits[0].network} fund join --subdomain ${subdomain}`));
10684
10781
  } else {
10685
10782
  const chains = hits.map((h) => h.network).join(", ");
10686
- console.error(chalk16.yellow(` Found on chains: ${chalk16.bold(chains)}`));
10687
- console.error(chalk16.dim(` Specify which chain to join with --chain <network>.`));
10783
+ console.error(chalk18.yellow(` Found on chains: ${chalk18.bold(chains)}`));
10784
+ console.error(chalk18.dim(` Specify which chain to join with --chain <network>.`));
10688
10785
  }
10689
10786
  process.exit(1);
10690
10787
  }
@@ -10725,17 +10822,17 @@ fund.command("join").description("Request to join a fund (creates an EAS attesta
10725
10822
  try {
10726
10823
  const xmtp = await loadXmtp();
10727
10824
  await xmtp.getXmtpClient();
10728
- console.log(chalk16.dim(" XMTP identity ready"));
10825
+ console.log(chalk18.dim(" XMTP identity ready"));
10729
10826
  } catch {
10730
- console.warn(chalk16.yellow(" \u26A0 Could not initialize XMTP identity"));
10827
+ console.warn(chalk18.yellow(" \u26A0 Could not initialize XMTP identity"));
10731
10828
  }
10732
10829
  try {
10733
10830
  const cron = await loadCron();
10734
10831
  const cronResult = cron.registerFundCrons(subdomain, isTestnet(), getNotifyTo());
10735
10832
  if (cronResult.isOpenClaw && cronResult.registered) {
10736
- console.log(chalk16.green(" \u2713 Participation crons registered"));
10833
+ console.log(chalk18.green(" \u2713 Participation crons registered"));
10737
10834
  } else if (!cronResult.isOpenClaw) {
10738
- console.log(chalk16.dim(" Tip: Set up a scheduled process to run `sherwood session check " + subdomain + "` periodically"));
10835
+ console.log(chalk18.dim(" Tip: Set up a scheduled process to run `sherwood session check " + subdomain + "` periodically"));
10739
10836
  }
10740
10837
  } catch {
10741
10838
  }
@@ -10748,14 +10845,14 @@ fund.command("join").description("Request to join a fund (creates an EAS attesta
10748
10845
  );
10749
10846
  if (existingRequest) {
10750
10847
  spinner.succeed("You already have a pending join request for this fund");
10751
- console.log(chalk16.dim(` Attestation: ${existingRequest.uid}`));
10752
- console.log(chalk16.dim(` Submitted: ${new Date(existingRequest.time * 1e3).toLocaleString()}`));
10848
+ console.log(chalk18.dim(` Attestation: ${existingRequest.uid}`));
10849
+ console.log(chalk18.dim(` Submitted: ${new Date(existingRequest.time * 1e3).toLocaleString()}`));
10753
10850
  try {
10754
10851
  const xmtp = await loadXmtp();
10755
10852
  await xmtp.getXmtpClient();
10756
- console.log(chalk16.dim(" XMTP identity ready"));
10853
+ console.log(chalk18.dim(" XMTP identity ready"));
10757
10854
  } catch {
10758
- console.warn(chalk16.yellow(" \u26A0 Could not initialize XMTP identity"));
10855
+ console.warn(chalk18.yellow(" \u26A0 Could not initialize XMTP identity"));
10759
10856
  }
10760
10857
  return;
10761
10858
  }
@@ -10776,7 +10873,7 @@ fund.command("join").description("Request to join a fund (creates an EAS attesta
10776
10873
  spinner.succeed("Join request created (XMTP identity ready)");
10777
10874
  } catch {
10778
10875
  spinner.succeed("Join request created");
10779
- console.warn(chalk16.yellow(" \u26A0 Could not initialize XMTP identity \u2014 creator may not be able to auto-add you to chat"));
10876
+ console.warn(chalk18.yellow(" \u26A0 Could not initialize XMTP identity \u2014 creator may not be able to auto-add you to chat"));
10780
10877
  }
10781
10878
  addFund(getChain().id, { subdomain, vault: fund2.vault, role: "agent" });
10782
10879
  setPrimaryFund(getChain().id, subdomain);
@@ -10806,12 +10903,12 @@ fund.command("join").description("Request to join a fund (creates an EAS attesta
10806
10903
  console.log();
10807
10904
  } catch (err) {
10808
10905
  spinner.fail("Join request failed");
10809
- console.error(chalk16.red(formatContractError(err)));
10906
+ console.error(chalk18.red(formatContractError(err)));
10810
10907
  process.exit(1);
10811
10908
  }
10812
10909
  });
10813
10910
  fund.command("requests").description("View pending join requests for a fund (creator only)").option("--subdomain <name>", "Fund subdomain").option("--vault <address>", "Vault address (default: from config)").action(async (opts) => {
10814
- const spinner = ora9("Loading join requests...").start();
10911
+ const spinner = ora10("Loading join requests...").start();
10815
10912
  try {
10816
10913
  let creatorAddress;
10817
10914
  let subdomain;
@@ -10868,11 +10965,11 @@ fund.command("requests").description("View pending join requests for a fund (cre
10868
10965
  if (vid) {
10869
10966
  const v = await verifyVidTag(vid, req.attester, ownerOfCached);
10870
10967
  const verified = v.bindingOk && v.ownerOk;
10871
- const badge = verified ? G6("\u2714 verified") : chalk16.red("\u2718 FAILED");
10968
+ const badge = verified ? G6("\u2714 verified") : chalk18.red("\u2718 FAILED");
10872
10969
  const detail = v.walletOnly ? `(wallet-only \u2014 no ERC-8004, wallet ${vid.wallet})` : `(agent #${vid.tokenId} on chain ${vid.issuingChainId}, wallet ${vid.wallet})`;
10873
10970
  console.log(W6(` Virtuals: ${badge} ${DIM6(detail)}`));
10874
- if (!v.bindingOk) console.log(chalk16.red(` binding signature invalid \u2014 do not approve based on this identity`));
10875
- else if (!v.ownerOk) console.log(chalk16.red(` NFT ownership check failed${v.owner ? ` (owner is ${v.owner})` : v.error ? ` (${v.error})` : ""}`));
10971
+ if (!v.bindingOk) console.log(chalk18.red(` binding signature invalid \u2014 do not approve based on this identity`));
10972
+ else if (!v.ownerOk) console.log(chalk18.red(` NFT ownership check failed${v.owner ? ` (owner is ${v.owner})` : v.error ? ` (${v.error})` : ""}`));
10876
10973
  }
10877
10974
  console.log(DIM6(` Requested: ${date}`));
10878
10975
  console.log(DIM6(` Attestation: ${req.uid}`));
@@ -10885,12 +10982,12 @@ fund.command("requests").description("View pending join requests for a fund (cre
10885
10982
  console.log();
10886
10983
  } catch (err) {
10887
10984
  spinner.fail("Failed to load requests");
10888
- console.error(chalk16.red(formatContractError(err)));
10985
+ console.error(chalk18.red(formatContractError(err)));
10889
10986
  process.exit(1);
10890
10987
  }
10891
10988
  });
10892
10989
  fund.command("approve").description("Approve an agent join request (registers agent + creates EAS approval)").option("--vault <address>", "Vault address (default: from config)").option("--subdomain <name>", "Fund subdomain (alternative to --vault)").requiredOption("--agent-id <id>", "Agent's ERC-8004 identity token ID").requiredOption("--wallet <address>", "Agent wallet address").action(async (opts) => {
10893
- const spinner = ora9("Verifying creator...").start();
10990
+ const spinner = ora10("Verifying creator...").start();
10894
10991
  try {
10895
10992
  const approveSubdomain = opts.subdomain || getPrimaryFund(getChain().id)?.subdomain;
10896
10993
  if (approveSubdomain && !opts.vault) {
@@ -10975,8 +11072,8 @@ fund.command("approve").description("Approve an agent join request (registers ag
10975
11072
  });
10976
11073
  console.log(DIM6(` Added to chat: ${subdomain}`));
10977
11074
  } catch {
10978
- console.warn(chalk16.yellow(" \u26A0 Could not add agent to chat group"));
10979
- console.warn(chalk16.dim(` If no group exists, run: sherwood chat ${subdomain} init`));
11075
+ console.warn(chalk18.yellow(" \u26A0 Could not add agent to chat group"));
11076
+ console.warn(chalk18.dim(` If no group exists, run: sherwood chat ${subdomain} init`));
10980
11077
  }
10981
11078
  spinner.succeed("Agent approved and registered");
10982
11079
  console.log();
@@ -10989,29 +11086,29 @@ fund.command("approve").description("Approve an agent join request (registers ag
10989
11086
  SEP6();
10990
11087
  } catch (err) {
10991
11088
  spinner.fail("Approval failed");
10992
- console.error(chalk16.red(formatContractError(err)));
11089
+ console.error(chalk18.red(formatContractError(err)));
10993
11090
  process.exit(1);
10994
11091
  }
10995
11092
  });
10996
11093
  fund.command("reject").description("Reject a join request by revoking its attestation").requiredOption("--attestation <uid>", "Join request attestation UID to revoke").action(async (opts) => {
10997
- const spinner = ora9("Revoking attestation...").start();
11094
+ const spinner = ora10("Revoking attestation...").start();
10998
11095
  try {
10999
11096
  const hash = await revokeJoinRequest(opts.attestation);
11000
11097
  spinner.succeed("Join request rejected");
11001
11098
  console.log(DIM6(` ${getEasExplorerUrl(hash)}`));
11002
11099
  } catch (err) {
11003
11100
  spinner.fail("Rejection failed");
11004
- console.error(chalk16.red(formatContractError(err)));
11101
+ console.error(chalk18.red(formatContractError(err)));
11005
11102
  process.exit(1);
11006
11103
  }
11007
11104
  });
11008
11105
  fund.command("leave").description("Leave a fund \u2014 removes participation crons and session state").option("--subdomain <name>", "Fund subdomain to leave").action(async (opts) => {
11009
11106
  const subdomain = opts.subdomain || getPrimaryFund(getChain().id)?.subdomain;
11010
11107
  if (!subdomain) {
11011
- console.error(chalk16.red(" No fund configured. Pass --subdomain <name>."));
11108
+ console.error(chalk18.red(" No fund configured. Pass --subdomain <name>."));
11012
11109
  process.exit(1);
11013
11110
  }
11014
- const spinner = ora9("Cleaning up...").start();
11111
+ const spinner = ora10("Cleaning up...").start();
11015
11112
  try {
11016
11113
  let cronsRemoved = false;
11017
11114
  try {
@@ -11028,13 +11125,13 @@ fund.command("leave").description("Leave a fund \u2014 removes participation cro
11028
11125
  }
11029
11126
  console.log(G6(" \u2713 Session state cleared"));
11030
11127
  console.log();
11031
- console.log(chalk16.dim(" Note: This does not remove you on-chain. To exit your position:"));
11032
- console.log(chalk16.dim(" sherwood vault balance \u2014 check your LP share balance"));
11033
- console.log(chalk16.dim(" Redeem shares via the vault contract or dashboard"));
11128
+ console.log(chalk18.dim(" Note: This does not remove you on-chain. To exit your position:"));
11129
+ console.log(chalk18.dim(" sherwood vault balance \u2014 check your LP share balance"));
11130
+ console.log(chalk18.dim(" Redeem shares via the vault contract or dashboard"));
11034
11131
  console.log();
11035
11132
  } catch (err) {
11036
11133
  spinner.fail("Leave failed");
11037
- console.error(chalk16.red(err instanceof Error ? err.message : String(err)));
11134
+ console.error(chalk18.red(err instanceof Error ? err.message : String(err)));
11038
11135
  process.exit(1);
11039
11136
  }
11040
11137
  });
@@ -11085,7 +11182,7 @@ fund.command("set-primary").description("Set the active fund for CLI commands (a
11085
11182
  }
11086
11183
  }
11087
11184
  if (!target) {
11088
- console.error(chalk16.red(" Could not resolve fund. Pass --subdomain or --vault."));
11185
+ console.error(chalk18.red(" Could not resolve fund. Pass --subdomain or --vault."));
11089
11186
  process.exit(1);
11090
11187
  }
11091
11188
  setPrimaryFund(chainId, target);
@@ -11093,7 +11190,7 @@ fund.command("set-primary").description("Set the active fund for CLI commands (a
11093
11190
  \u2713 Primary fund set to ${target}.sherwoodagent.eth
11094
11191
  `));
11095
11192
  } catch (err) {
11096
- console.error(chalk16.red(formatContractError(err)));
11193
+ console.error(chalk18.red(formatContractError(err)));
11097
11194
  process.exit(1);
11098
11195
  }
11099
11196
  });
@@ -11101,11 +11198,11 @@ var vaultCmd = program.command("vault");
11101
11198
  vaultCmd.command("deposit").description("Deposit into a vault").option("--vault <address>", "Vault address (default: from config)").requiredOption("--amount <amount>", "Amount to deposit (in asset units)").option("--use-eth", "Auto-wrap ETH \u2192 WETH before depositing (for WETH vaults)").option("--receiver <address>", "Depositor / share receiver (required with --calldata-only)").action(async (opts) => {
11102
11199
  resolveVault(opts);
11103
11200
  const decimals = await getAssetDecimals();
11104
- const amount = parseUnits9(opts.amount, decimals);
11201
+ const amount = parseUnits11(opts.amount, decimals);
11105
11202
  if (isCalldataOnly()) {
11106
11203
  if (!opts.receiver) {
11107
11204
  console.error(
11108
- chalk16.red(
11205
+ chalk18.red(
11109
11206
  "--calldata-only requires --receiver <address> (the depositor / share receiver)"
11110
11207
  )
11111
11208
  );
@@ -11144,7 +11241,7 @@ vaultCmd.command("deposit").description("Deposit into a vault").option("--vault
11144
11241
  )
11145
11242
  );
11146
11243
  } catch (err) {
11147
- console.error(chalk16.red(err instanceof Error ? err.message : String(err)));
11244
+ console.error(chalk18.red(err instanceof Error ? err.message : String(err)));
11148
11245
  process.exit(1);
11149
11246
  }
11150
11247
  return;
@@ -11154,12 +11251,12 @@ vaultCmd.command("deposit").description("Deposit into a vault").option("--vault
11154
11251
  await preflightDeposit(amount);
11155
11252
  }
11156
11253
  } catch (err) {
11157
- console.error(chalk16.red(`
11254
+ console.error(chalk18.red(`
11158
11255
  \u2716 ${err instanceof Error ? err.message : String(err)}
11159
11256
  `));
11160
11257
  process.exit(1);
11161
11258
  }
11162
- const spinner = ora9(`Depositing ${opts.amount}...`).start();
11259
+ const spinner = ora10(`Depositing ${opts.amount}...`).start();
11163
11260
  try {
11164
11261
  let hash;
11165
11262
  if (opts.useEth) {
@@ -11169,22 +11266,22 @@ vaultCmd.command("deposit").description("Deposit into a vault").option("--vault
11169
11266
  hash = await deposit(amount);
11170
11267
  }
11171
11268
  spinner.succeed(`Deposited: ${hash}`);
11172
- console.log(chalk16.dim(` ${getExplorerUrl(hash)}`));
11269
+ console.log(chalk18.dim(` ${getExplorerUrl(hash)}`));
11173
11270
  } catch (err) {
11174
11271
  spinner.fail("Deposit failed");
11175
- console.error(chalk16.red(formatContractError(err)));
11272
+ console.error(chalk18.red(formatContractError(err)));
11176
11273
  process.exit(1);
11177
11274
  }
11178
11275
  });
11179
11276
  vaultCmd.command("info").description("Display vault state").option("--vault <address>", "Vault address (default: from config)").action(async (opts) => {
11180
11277
  resolveVault(opts);
11181
- const spinner = ora9("Loading vault info...").start();
11278
+ const spinner = ora10("Loading vault info...").start();
11182
11279
  try {
11183
11280
  const info = await getVaultInfo();
11184
11281
  spinner.stop();
11185
11282
  console.log();
11186
- console.log(chalk16.bold("Vault Info"));
11187
- console.log(chalk16.dim("\u2500".repeat(40)));
11283
+ console.log(chalk18.bold("Vault Info"));
11284
+ console.log(chalk18.dim("\u2500".repeat(40)));
11188
11285
  console.log(` Address: ${info.address}`);
11189
11286
  console.log(` Total Assets: ${info.totalAssets}`);
11190
11287
  console.log(` Agent Count: ${info.agentCount}`);
@@ -11193,26 +11290,26 @@ vaultCmd.command("info").description("Display vault state").option("--vault <add
11193
11290
  console.log();
11194
11291
  } catch (err) {
11195
11292
  spinner.fail("Failed to load vault info");
11196
- console.error(chalk16.red(formatContractError(err)));
11293
+ console.error(chalk18.red(formatContractError(err)));
11197
11294
  process.exit(1);
11198
11295
  }
11199
11296
  });
11200
11297
  vaultCmd.command("balance").description("Show LP share balance and asset value").option("--vault <address>", "Vault address (default: from config)").option("--address <address>", "Address to check (default: your wallet)").action(async (opts) => {
11201
11298
  resolveVault(opts);
11202
- const spinner = ora9("Loading balance...").start();
11299
+ const spinner = ora10("Loading balance...").start();
11203
11300
  try {
11204
11301
  const balance = await getBalance(opts.address);
11205
11302
  spinner.stop();
11206
11303
  console.log();
11207
- console.log(chalk16.bold("LP Position"));
11208
- console.log(chalk16.dim("\u2500".repeat(40)));
11304
+ console.log(chalk18.bold("LP Position"));
11305
+ console.log(chalk18.dim("\u2500".repeat(40)));
11209
11306
  console.log(` Shares: ${balance.shares.toString()}`);
11210
11307
  console.log(` Asset Value: ${balance.assetsValue}`);
11211
11308
  console.log(` % of Vault: ${balance.percentOfVault}`);
11212
11309
  console.log();
11213
11310
  } catch (err) {
11214
11311
  spinner.fail("Failed to load balance");
11215
- console.error(chalk16.red(formatContractError(err)));
11312
+ console.error(chalk18.red(formatContractError(err)));
11216
11313
  process.exit(1);
11217
11314
  }
11218
11315
  });
@@ -11223,7 +11320,7 @@ vaultCmd.command("redeem").description("Redeem vault shares for the underlying a
11223
11320
  if (isCalldataOnly()) {
11224
11321
  if (!opts.shares) {
11225
11322
  console.error(
11226
- chalk16.red(
11323
+ chalk18.red(
11227
11324
  "--calldata-only requires --shares (auto-'all' needs your on-chain share balance)"
11228
11325
  )
11229
11326
  );
@@ -11231,7 +11328,7 @@ vaultCmd.command("redeem").description("Redeem vault shares for the underlying a
11231
11328
  }
11232
11329
  if (!opts.owner) {
11233
11330
  console.error(
11234
- chalk16.red(
11331
+ chalk18.red(
11235
11332
  "--calldata-only requires --owner <address> (the share holder whose shares burn)"
11236
11333
  )
11237
11334
  );
@@ -11245,7 +11342,7 @@ vaultCmd.command("redeem").description("Redeem vault shares for the underlying a
11245
11342
  vault: getVaultAddress(),
11246
11343
  receiver,
11247
11344
  owner,
11248
- shares: parseUnits9(opts.shares, shareDecimals)
11345
+ shares: parseUnits11(opts.shares, shareDecimals)
11249
11346
  },
11250
11347
  getChain().id
11251
11348
  )
@@ -11255,22 +11352,22 @@ vaultCmd.command("redeem").description("Redeem vault shares for the underlying a
11255
11352
  let shares;
11256
11353
  try {
11257
11354
  if (opts.shares) {
11258
- shares = parseUnits9(opts.shares, shareDecimals);
11355
+ shares = parseUnits11(opts.shares, shareDecimals);
11259
11356
  } else {
11260
11357
  shares = await getShareBalance();
11261
11358
  if (shares === 0n) {
11262
- console.error(chalk16.red("\n \u2716 No shares to redeem.\n"));
11359
+ console.error(chalk18.red("\n \u2716 No shares to redeem.\n"));
11263
11360
  process.exit(1);
11264
11361
  }
11265
11362
  }
11266
11363
  } catch (err) {
11267
- console.error(chalk16.red(`
11364
+ console.error(chalk18.red(`
11268
11365
  \u2716 ${err instanceof Error ? err.message : String(err)}
11269
11366
  `));
11270
11367
  process.exit(1);
11271
11368
  }
11272
- if (opts.receiver && !isAddress10(opts.receiver)) {
11273
- console.error(chalk16.red(`
11369
+ if (opts.receiver && !isAddress12(opts.receiver)) {
11370
+ console.error(chalk18.red(`
11274
11371
  \u2716 Invalid receiver address: ${opts.receiver}
11275
11372
  `));
11276
11373
  process.exit(1);
@@ -11278,31 +11375,31 @@ vaultCmd.command("redeem").description("Redeem vault shares for the underlying a
11278
11375
  try {
11279
11376
  await preflightRedeem(shares);
11280
11377
  } catch (err) {
11281
- console.error(chalk16.red(`
11378
+ console.error(chalk18.red(`
11282
11379
  \u2716 ${err instanceof Error ? err.message : String(err)}
11283
11380
  `));
11284
11381
  process.exit(1);
11285
11382
  }
11286
- const sharesDisplay = formatUnits7(shares, shareDecimals);
11287
- const spinner = ora9(`Redeeming ${sharesDisplay} shares...`).start();
11383
+ const sharesDisplay = formatUnits10(shares, shareDecimals);
11384
+ const spinner = ora10(`Redeeming ${sharesDisplay} shares...`).start();
11288
11385
  try {
11289
11386
  const { hash, assetsOut } = await redeem(
11290
11387
  shares,
11291
11388
  opts.receiver
11292
11389
  );
11293
11390
  spinner.succeed(`Redeemed: ${hash}`);
11294
- console.log(chalk16.dim(` ${getExplorerUrl(hash)}`));
11295
- console.log(` Assets received: ${formatUnits7(assetsOut, assetDecimals)}`);
11391
+ console.log(chalk18.dim(` ${getExplorerUrl(hash)}`));
11392
+ console.log(` Assets received: ${formatUnits10(assetsOut, assetDecimals)}`);
11296
11393
  } catch (err) {
11297
11394
  spinner.fail("Redeem failed");
11298
- console.error(chalk16.red(formatContractError(err)));
11395
+ console.error(chalk18.red(formatContractError(err)));
11299
11396
  process.exit(1);
11300
11397
  }
11301
11398
  });
11302
11399
  var strategy = program.command("strategy").description("Strategy templates \u2014 list, clone, propose");
11303
11400
  registerStrategyTemplateCommands(strategy);
11304
11401
  program.command("providers").description("List available providers (research + swap routing)").action(async () => {
11305
- const { listProviders } = await import("./providers-F6MNPMR4.js");
11402
+ const { listProviders } = await import("./providers-4HQHB7V5.js");
11306
11403
  for (const info of listProviders()) {
11307
11404
  console.log(`
11308
11405
  ${info.name} (${info.type})`);
@@ -11312,17 +11409,17 @@ ${info.name} (${info.type})`);
11312
11409
  }
11313
11410
  });
11314
11411
  try {
11315
- const { registerChatCommands } = await import("./chat-5TUHBSIA.js");
11412
+ const { registerChatCommands } = await import("./chat-FGTYCJ4B.js");
11316
11413
  registerChatCommands(program);
11317
11414
  } catch {
11318
11415
  program.command("chat <name> [action] [actionArgs...]").description("Fund chat (XMTP) \u2014 requires @xmtp/cli").action(() => {
11319
- console.error(chalk16.red("XMTP CLI not available."));
11320
- console.error(chalk16.dim("Install with: npm install -g @xmtp/cli"));
11321
- console.error(chalk16.dim("Or reinstall: npm i -g @sherwoodagent/cli"));
11416
+ console.error(chalk18.red("XMTP CLI not available."));
11417
+ console.error(chalk18.dim("Install with: npm install -g @xmtp/cli"));
11418
+ console.error(chalk18.dim("Or reinstall: npm i -g @sherwoodagent/cli"));
11322
11419
  process.exit(1);
11323
11420
  });
11324
11421
  }
11325
- var { registerSessionCommands } = await import("./session-AXLPYJHX.js");
11422
+ var { registerSessionCommands } = await import("./session-SIOJZO6P.js");
11326
11423
  registerSessionCommands(program);
11327
11424
  registerVeniceCommands(program);
11328
11425
  registerAllowanceCommands(program);
@@ -11331,11 +11428,11 @@ registerProposalCommands(program);
11331
11428
  registerQueueCommands(program);
11332
11429
  registerGovernorCommands(program);
11333
11430
  registerGuardianCommands(program);
11334
- var { registerResearchCommands } = await import("./research-5ZJTRILJ.js");
11431
+ var { registerResearchCommands } = await import("./research-2RWAMWWH.js");
11335
11432
  registerResearchCommands(program);
11336
- var { registerAgentCommands } = await import("./agent-QUINV725.js");
11433
+ var { registerAgentCommands } = await import("./agent-C5XZSK7Z.js");
11337
11434
  registerAgentCommands(program);
11338
- var { registerTradeCommands } = await import("./trade-BZM7K2F4.js");
11435
+ var { registerTradeCommands } = await import("./trade-ZEIY3MCL.js");
11339
11436
  registerTradeCommands(program);
11340
11437
  registerGridCommand(program);
11341
11438
  var configCmd = program.command("config");
@@ -11344,58 +11441,58 @@ configCmd.command("set").description("Save settings to ~/.sherwood/config.json (
11344
11441
  if (opts.privateKey) {
11345
11442
  setPrivateKey(opts.privateKey);
11346
11443
  const account = getAccount();
11347
- console.log(chalk16.green("Private key saved to ~/.sherwood/config.json"));
11348
- console.log(chalk16.dim(` Wallet: ${account.address}`));
11444
+ console.log(chalk18.green("Private key saved to ~/.sherwood/config.json"));
11445
+ console.log(chalk18.dim(` Wallet: ${account.address}`));
11349
11446
  saved = true;
11350
11447
  }
11351
11448
  if (opts.vault) {
11352
11449
  const chainId = getChain().id;
11353
11450
  setChainContract(chainId, "vault", opts.vault);
11354
- console.log(chalk16.green(`Vault saved to ~/.sherwood/config.json (chain ${chainId})`));
11355
- console.log(chalk16.dim(` Vault: ${opts.vault}`));
11451
+ console.log(chalk18.green(`Vault saved to ~/.sherwood/config.json (chain ${chainId})`));
11452
+ console.log(chalk18.dim(` Vault: ${opts.vault}`));
11356
11453
  saved = true;
11357
11454
  }
11358
11455
  if (opts.rpc) {
11359
11456
  const network = getNetwork();
11360
11457
  setConfigRpcUrl(network, opts.rpc);
11361
- console.log(chalk16.green(`RPC URL saved for ${network}`));
11362
- console.log(chalk16.dim(` RPC: ${opts.rpc}`));
11458
+ console.log(chalk18.green(`RPC URL saved for ${network}`));
11459
+ console.log(chalk18.dim(` RPC: ${opts.rpc}`));
11363
11460
  saved = true;
11364
11461
  }
11365
11462
  if (opts.notifyTo) {
11366
11463
  setNotifyTo(opts.notifyTo);
11367
- console.log(chalk16.green("Notify destination saved to ~/.sherwood/config.json"));
11368
- console.log(chalk16.dim(` Notify to: ${opts.notifyTo}`));
11464
+ console.log(chalk18.green("Notify destination saved to ~/.sherwood/config.json"));
11465
+ console.log(chalk18.dim(` Notify to: ${opts.notifyTo}`));
11369
11466
  saved = true;
11370
11467
  }
11371
11468
  if (opts.uniswapApiKey) {
11372
11469
  setUniswapApiKey(opts.uniswapApiKey);
11373
- console.log(chalk16.green("Uniswap API key saved to ~/.sherwood/config.json"));
11470
+ console.log(chalk18.green("Uniswap API key saved to ~/.sherwood/config.json"));
11374
11471
  saved = true;
11375
11472
  }
11376
11473
  if (opts.veniceApiKey) {
11377
11474
  setVeniceApiKey(opts.veniceApiKey);
11378
- console.log(chalk16.green("Venice API key saved to ~/.sherwood/config.json"));
11475
+ console.log(chalk18.green("Venice API key saved to ~/.sherwood/config.json"));
11379
11476
  saved = true;
11380
11477
  }
11381
11478
  if (opts.anthropicApiKey) {
11382
11479
  setAnthropicApiKey(opts.anthropicApiKey);
11383
- console.log(chalk16.green("Anthropic API key saved to ~/.sherwood/config.json"));
11480
+ console.log(chalk18.green("Anthropic API key saved to ~/.sherwood/config.json"));
11384
11481
  saved = true;
11385
11482
  }
11386
11483
  if (opts.xmtpGroup) {
11387
11484
  const parts = opts.xmtpGroup.split(":");
11388
11485
  if (parts.length !== 2 || !parts[0] || !parts[1]) {
11389
- console.log(chalk16.red("Format: --xmtp-group <subdomain>:<groupId>"));
11486
+ console.log(chalk18.red("Format: --xmtp-group <subdomain>:<groupId>"));
11390
11487
  process.exit(1);
11391
11488
  }
11392
11489
  cacheGroupId(parts[0], parts[1]);
11393
- console.log(chalk16.green(`XMTP group ID cached for ${parts[0]}`));
11394
- console.log(chalk16.dim(` Group ID: ${parts[1]}`));
11490
+ console.log(chalk18.green(`XMTP group ID cached for ${parts[0]}`));
11491
+ console.log(chalk18.dim(` Group ID: ${parts[1]}`));
11395
11492
  saved = true;
11396
11493
  }
11397
11494
  if (!saved) {
11398
- console.log(chalk16.red("Provide at least one of: --private-key, --vault, --rpc, --notify-to, --uniswap-api-key, --venice-api-key, --anthropic-api-key, --xmtp-group"));
11495
+ console.log(chalk18.red("Provide at least one of: --private-key, --vault, --rpc, --notify-to, --uniswap-api-key, --venice-api-key, --anthropic-api-key, --xmtp-group"));
11399
11496
  process.exit(1);
11400
11497
  }
11401
11498
  });
@@ -11406,25 +11503,25 @@ configCmd.command("show").description("Display current config for the active net
11406
11503
  const config = loadConfig();
11407
11504
  const customRpc = config.rpc?.[network];
11408
11505
  console.log();
11409
- console.log(chalk16.bold(`Sherwood Config`));
11410
- console.log(chalk16.dim("\u2500".repeat(50)));
11411
- console.log(` Network: ${chalk16.cyan(network)} (chain ${chainId})`);
11412
- console.log(` RPC: ${customRpc ? chalk16.green(customRpc) : chalk16.dim("default")}`);
11413
- console.log(` Wallet: ${config.privateKey ? chalk16.green("configured") : chalk16.dim("not set")}`);
11414
- console.log(` Agent ID: ${config.agentId ?? chalk16.dim("not set")}`);
11415
- console.log(` Vault: ${contracts.vault ?? chalk16.dim("not set")}`);
11416
- console.log(` Uniswap: ${getUniswapApiKey() ? chalk16.green("API key configured") : chalk16.dim("not set")}`);
11417
- console.log(` Venice: ${getVeniceApiKey() ? chalk16.green("API key configured") : chalk16.dim("not set")}`);
11506
+ console.log(chalk18.bold(`Sherwood Config`));
11507
+ console.log(chalk18.dim("\u2500".repeat(50)));
11508
+ console.log(` Network: ${chalk18.cyan(network)} (chain ${chainId})`);
11509
+ console.log(` RPC: ${customRpc ? chalk18.green(customRpc) : chalk18.dim("default")}`);
11510
+ console.log(` Wallet: ${config.privateKey ? chalk18.green("configured") : chalk18.dim("not set")}`);
11511
+ console.log(` Agent ID: ${config.agentId ?? chalk18.dim("not set")}`);
11512
+ console.log(` Vault: ${contracts.vault ?? chalk18.dim("not set")}`);
11513
+ console.log(` Uniswap: ${getUniswapApiKey() ? chalk18.green("API key configured") : chalk18.dim("not set")}`);
11514
+ console.log(` Venice: ${getVeniceApiKey() ? chalk18.green("API key configured") : chalk18.dim("not set")}`);
11418
11515
  const groupEntries = Object.entries(config.groupCache || {}).filter(([, v]) => v);
11419
11516
  if (groupEntries.length > 0) {
11420
11517
  console.log();
11421
- console.log(chalk16.bold(" XMTP Groups"));
11518
+ console.log(chalk18.bold(" XMTP Groups"));
11422
11519
  for (const [sub, gid] of groupEntries) {
11423
- console.log(` ${sub}: ${chalk16.cyan(gid)}`);
11520
+ console.log(` ${sub}: ${chalk18.cyan(gid)}`);
11424
11521
  }
11425
11522
  }
11426
11523
  console.log();
11427
- console.log(chalk16.dim(" Config file: ~/.sherwood/config.json"));
11524
+ console.log(chalk18.dim(" Config file: ~/.sherwood/config.json"));
11428
11525
  console.log();
11429
11526
  });
11430
11527
  program.parse();