@sherwoodagent/cli 0.47.1 → 0.51.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 (39) hide show
  1. package/dist/{abis-RGCO5GHC.js → abis-Z6M6SRPX.js} +2 -2
  2. package/dist/{agent-4HKHLQEJ.js → agent-E5GHURKJ.js} +49 -155
  3. package/dist/agent-E5GHURKJ.js.map +1 -0
  4. package/dist/{chat-MRTPUZ3X.js → chat-TD6V5LFD.js} +5 -5
  5. package/dist/{chunk-WMZEOR5W.js → chunk-2HNUJ7XH.js} +2 -2
  6. package/dist/{chunk-R7X33D2S.js → chunk-4OF4IZ6M.js} +2 -2
  7. package/dist/{chunk-D77JGXIV.js → chunk-J2FOCXF2.js} +1 -8
  8. package/dist/{chunk-D77JGXIV.js.map → chunk-J2FOCXF2.js.map} +1 -1
  9. package/dist/{chunk-E6LH2FJ6.js → chunk-ME6MUKGZ.js} +2 -2
  10. package/dist/{chunk-R2P4C2I7.js → chunk-OMW47WOO.js} +142 -2
  11. package/dist/chunk-OMW47WOO.js.map +1 -0
  12. package/dist/{chunk-KJ35EF7N.js → chunk-T464VNRC.js} +2 -2
  13. package/dist/{chunk-IS2CLLUT.js → chunk-UYL6Q7BS.js} +2 -2
  14. package/dist/{eas-PEEWGSAO.js → eas-LHJF2UCG.js} +3 -3
  15. package/dist/{governor-MG5VVSU4.js → governor-JD4KZXDA.js} +3 -3
  16. package/dist/index.js +593 -194
  17. package/dist/index.js.map +1 -1
  18. package/dist/{price-WCCXWPDM.js → price-2PNKWY4D.js} +2 -2
  19. package/dist/{research-QBKISW2M.js → research-WBZU4QNU.js} +3 -3
  20. package/dist/{session-FPCPCVQX.js → session-IYT3N7MG.js} +5 -5
  21. package/dist/{trade-NO6CNWCA.js → trade-PTYLNJBU.js} +6 -6
  22. package/dist/{xmtp-ACB2W573.js → xmtp-ZACWHUI5.js} +3 -3
  23. package/package.json +1 -1
  24. package/dist/agent-4HKHLQEJ.js.map +0 -1
  25. package/dist/chunk-R2P4C2I7.js.map +0 -1
  26. /package/dist/{abis-RGCO5GHC.js.map → abis-Z6M6SRPX.js.map} +0 -0
  27. /package/dist/{chat-MRTPUZ3X.js.map → chat-TD6V5LFD.js.map} +0 -0
  28. /package/dist/{chunk-WMZEOR5W.js.map → chunk-2HNUJ7XH.js.map} +0 -0
  29. /package/dist/{chunk-R7X33D2S.js.map → chunk-4OF4IZ6M.js.map} +0 -0
  30. /package/dist/{chunk-E6LH2FJ6.js.map → chunk-ME6MUKGZ.js.map} +0 -0
  31. /package/dist/{chunk-KJ35EF7N.js.map → chunk-T464VNRC.js.map} +0 -0
  32. /package/dist/{chunk-IS2CLLUT.js.map → chunk-UYL6Q7BS.js.map} +0 -0
  33. /package/dist/{eas-PEEWGSAO.js.map → eas-LHJF2UCG.js.map} +0 -0
  34. /package/dist/{governor-MG5VVSU4.js.map → governor-JD4KZXDA.js.map} +0 -0
  35. /package/dist/{price-WCCXWPDM.js.map → price-2PNKWY4D.js.map} +0 -0
  36. /package/dist/{research-QBKISW2M.js.map → research-WBZU4QNU.js.map} +0 -0
  37. /package/dist/{session-FPCPCVQX.js.map → session-IYT3N7MG.js.map} +0 -0
  38. /package/dist/{trade-NO6CNWCA.js.map → trade-PTYLNJBU.js.map} +0 -0
  39. /package/dist/{xmtp-ACB2W573.js.map → xmtp-ZACWHUI5.js.map} +0 -0
package/dist/index.js CHANGED
@@ -1,15 +1,19 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  HyperliquidProvider,
4
- getLatestSignals
5
- } from "./chunk-R2P4C2I7.js";
4
+ getLatestSignals,
5
+ hlCancelAllOrders,
6
+ hlGetMeta,
7
+ hlPlaceLimitOrder,
8
+ resolveHLCoin
9
+ } from "./chunk-OMW47WOO.js";
6
10
  import {
7
11
  UniswapProvider,
8
12
  applySlippage,
9
13
  encodeSwapPath,
10
14
  getMultiHopQuote,
11
15
  getQuote
12
- } from "./chunk-WMZEOR5W.js";
16
+ } from "./chunk-2HNUJ7XH.js";
13
17
  import {
14
18
  chatCompletion,
15
19
  checkApiKeyValid,
@@ -26,14 +30,14 @@ import {
26
30
  queryJoinRequests,
27
31
  revokeJoinRequest,
28
32
  stripReferrerPrefix
29
- } from "./chunk-E6LH2FJ6.js";
33
+ } from "./chunk-ME6MUKGZ.js";
30
34
  import {
31
35
  createSyndicate,
32
36
  getActiveSyndicates,
33
37
  getSyndicate,
34
38
  subdomainExists,
35
39
  updateMetadata
36
- } from "./chunk-IS2CLLUT.js";
40
+ } from "./chunk-UYL6Q7BS.js";
37
41
  import {
38
42
  approveDepositor,
39
43
  deposit,
@@ -57,7 +61,7 @@ import {
57
61
  searchSyndicateAcrossChains,
58
62
  setTextRecord,
59
63
  setVaultAddress
60
- } from "./chunk-R7X33D2S.js";
64
+ } from "./chunk-4OF4IZ6M.js";
61
65
  import {
62
66
  PROPOSAL_STATE,
63
67
  PROPOSAL_STATES,
@@ -89,7 +93,7 @@ import {
89
93
  setVotingPeriod,
90
94
  settleProposal,
91
95
  vote
92
- } from "./chunk-KJ35EF7N.js";
96
+ } from "./chunk-T464VNRC.js";
93
97
  import {
94
98
  AERODROME,
95
99
  AGENT_REGISTRY,
@@ -154,7 +158,7 @@ import {
154
158
  SWAP_ROUTER_EXACT_INPUT_SINGLE_ABI,
155
159
  SYNDICATE_VAULT_ABI,
156
160
  VENICE_STAKING_ABI
157
- } from "./chunk-D77JGXIV.js";
161
+ } from "./chunk-J2FOCXF2.js";
158
162
  import {
159
163
  fetchMetadata,
160
164
  uploadMetadata
@@ -164,8 +168,8 @@ import {
164
168
  import { config as loadDotenv } from "dotenv";
165
169
  import { createRequire } from "module";
166
170
  import { Command, Option } from "commander";
167
- import { parseUnits as parseUnits6, formatUnits as formatUnits5, isAddress as isAddress6 } from "viem";
168
- import chalk13 from "chalk";
171
+ import { parseUnits as parseUnits7, formatUnits as formatUnits5, isAddress as isAddress6 } from "viem";
172
+ import chalk15 from "chalk";
169
173
  import ora8 from "ora";
170
174
  import { input, confirm, select } from "@inquirer/prompts";
171
175
 
@@ -589,18 +593,17 @@ function buildSettleCalls6(clone) {
589
593
 
590
594
  // src/strategies/hyperliquid-perp-template.ts
591
595
  import { encodeAbiParameters as encodeAbiParameters7, encodeFunctionData as encodeFunctionData7, maxUint256 as maxUint2562 } from "viem";
592
- function buildInitData7(asset, depositAmount, minReturnAmount, perpAssetIndex, leverage, maxPositionSize, maxTradesPerDay) {
596
+ function buildInitData7(asset, depositAmount, perpAssetIndex, leverage, maxPositionSize, maxTradesPerDay) {
593
597
  return encodeAbiParameters7(
594
598
  [
595
599
  { type: "address" },
596
600
  { type: "uint256" },
597
- { type: "uint256" },
598
601
  { type: "uint32" },
599
602
  { type: "uint32" },
600
603
  { type: "uint256" },
601
604
  { type: "uint32" }
602
605
  ],
603
- [asset, depositAmount, minReturnAmount, perpAssetIndex, leverage, maxPositionSize, maxTradesPerDay]
606
+ [asset, depositAmount, perpAssetIndex, leverage, maxPositionSize, maxTradesPerDay]
604
607
  );
605
608
  }
606
609
  function buildExecuteCalls7(clone, asset, amount) {
@@ -1066,19 +1069,12 @@ async function buildInitDataForTemplate(templateKey, opts, vault) {
1066
1069
  const asset = resolveToken(token);
1067
1070
  const decimals = token.toUpperCase() === "USDC" ? 6 : 18;
1068
1071
  const depositAmount = opts.amount ? parseUnits(opts.amount, decimals) : 0n;
1069
- if (depositAmount === 0n && !opts.minReturn) {
1070
- console.error(chalk.red(
1071
- "--min-return is required when --amount is omitted (dynamic-all mode).\n The settlement floor can't be derived without a reference deposit \u2014 set it explicitly to the minimum USDC you'll accept back from HyperCore."
1072
- ));
1073
- process.exit(1);
1074
- }
1075
- const minReturn = opts.minReturn ? parseUnits(opts.minReturn, decimals) : opts.amount ? parseUnits(opts.amount, decimals) : 0n;
1076
1072
  const leverage = Number(opts.leverage || "10");
1077
1073
  const assetIndex = Number(opts.assetIndex || "0");
1078
1074
  const maxPosition = parseUnits(opts.maxPosition || "100000", decimals);
1079
1075
  const maxTradesDay = Number(opts.maxTradesPerDay || "50");
1080
1076
  return {
1081
- initData: buildInitData7(asset, depositAmount, minReturn, assetIndex, leverage, maxPosition, maxTradesDay),
1077
+ initData: buildInitData7(asset, depositAmount, assetIndex, leverage, maxPosition, maxTradesDay),
1082
1078
  asset,
1083
1079
  assetAmount: depositAmount
1084
1080
  };
@@ -1224,7 +1220,7 @@ function registerStrategyTemplateCommands(strategy2) {
1224
1220
  console.log(chalk.dim("Full proposal: sherwood strategy propose <template> --vault <addr> ..."));
1225
1221
  console.log();
1226
1222
  });
1227
- 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").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("--leverage <number>", "Leverage multiplier (Hyperliquid Perp, default: 10)").option("--asset-index <number>", "Perp asset index (Hyperliquid Perp, default: 0 for BTC)").option("--min-return <n>", "Min return amount on settlement (Hyperliquid Perp)").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)").action(async (templateKey, opts) => {
1223
+ 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").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("--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)").action(async (templateKey, opts) => {
1228
1224
  const vault = opts.vault;
1229
1225
  if (!isAddress(vault)) {
1230
1226
  console.error(chalk.red("Invalid vault address"));
@@ -1272,7 +1268,7 @@ function registerStrategyTemplateCommands(strategy2) {
1272
1268
  console.log(chalk.dim("Use this address in your proposal batch calls."));
1273
1269
  console.log();
1274
1270
  });
1275
- 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").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("--leverage <number>", "Leverage multiplier (Hyperliquid Perp, default: 10)").option("--asset-index <number>", "Perp asset index (Hyperliquid Perp, default: 0 for BTC)").option("--min-return <n>", "Min return amount on settlement (Hyperliquid Perp)").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)").action(async (templateKey, opts) => {
1271
+ 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").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("--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)").action(async (templateKey, opts) => {
1276
1272
  const clone = opts.clone;
1277
1273
  const vault = opts.vault;
1278
1274
  if (!isAddress(clone)) {
@@ -1328,7 +1324,7 @@ function registerStrategyTemplateCommands(strategy2) {
1328
1324
  console.log(` Proposer: ${chalk.green(getAccount().address)}`);
1329
1325
  console.log();
1330
1326
  });
1331
- 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").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("--performance-fee <bps>", "Agent fee in bps").option("--duration <duration>", "Strategy duration (7d, 24h, etc.)").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("--leverage <number>", "Leverage multiplier (Hyperliquid Perp, default: 10)").option("--asset-index <number>", "Perp asset index (Hyperliquid Perp, default: 0 for BTC)").option("--min-return <n>", "Min return amount on settlement (Hyperliquid Perp)").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)").action(async (templateKey, opts) => {
1327
+ 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").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("--performance-fee <bps>", "Agent fee in bps").option("--duration <duration>", "Strategy duration (7d, 24h, etc.)").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("--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)").action(async (templateKey, opts) => {
1332
1328
  const vault = opts.vault;
1333
1329
  if (!isAddress(vault)) {
1334
1330
  console.error(chalk.red("Invalid vault address"));
@@ -1454,9 +1450,9 @@ function registerStrategyTemplateCommands(strategy2) {
1454
1450
  console.error(chalk.red("Missing --name, --performance-fee, or --duration. Use --write-calls to skip proposal submission."));
1455
1451
  process.exit(1);
1456
1452
  }
1457
- const { propose: propose2 } = await import("./governor-MG5VVSU4.js");
1453
+ const { propose: propose2 } = await import("./governor-JD4KZXDA.js");
1458
1454
  const { pinJSON } = await import("./ipfs-IGXLLJCF.js");
1459
- const { parseDuration: parseDuration2 } = await import("./governor-MG5VVSU4.js");
1455
+ const { parseDuration: parseDuration2 } = await import("./governor-JD4KZXDA.js");
1460
1456
  const performanceFeeBps = BigInt(opts.performanceFee);
1461
1457
  if (performanceFeeBps < 0n || performanceFeeBps > 10000n) {
1462
1458
  console.error(chalk.red("--performance-fee must be 0-10000 (basis points)"));
@@ -1563,7 +1559,7 @@ function registerStrategyTemplateCommands(strategy2) {
1563
1559
  let prices = [];
1564
1560
  let priceSource = null;
1565
1561
  try {
1566
- const { getTokenPricesInAsset } = await import("./price-WCCXWPDM.js");
1562
+ const { getTokenPricesInAsset } = await import("./price-2PNKWY4D.js");
1567
1563
  prices = await getTokenPricesInAsset({
1568
1564
  tokens: allocations.map((a, i) => ({
1569
1565
  token: a.token,
@@ -1993,7 +1989,7 @@ function registerVeniceCommands(program2) {
1993
1989
  console.log(chalk2.dim(` Key: ${apiKey.slice(0, 8)}...${apiKey.slice(-4)}`));
1994
1990
  console.log(chalk2.dim(" Saved to ~/.sherwood/config.json"));
1995
1991
  try {
1996
- const { createVeniceProvisionAttestation, getEasScanUrl: getEasScanUrl2 } = await import("./eas-PEEWGSAO.js");
1992
+ const { createVeniceProvisionAttestation, getEasScanUrl: getEasScanUrl2 } = await import("./eas-LHJF2UCG.js");
1997
1993
  const { uid } = await createVeniceProvisionAttestation(account.address);
1998
1994
  if (uid !== "0x0000000000000000000000000000000000000000000000000000000000000000") {
1999
1995
  console.log(chalk2.dim(` Attested: ${getEasScanUrl2(uid)}`));
@@ -2349,12 +2345,12 @@ ${opts.prompt}`;
2349
2345
  console.log(chalk2.dim(`Model: ${result.model} | Tokens: ${result.usage.promptTokens} in, ${result.usage.completionTokens} out, ${result.usage.totalTokens} total`));
2350
2346
  }
2351
2347
  try {
2352
- const { createVeniceInferenceAttestation, getEasScanUrl: getEasScanUrl2 } = await import("./eas-PEEWGSAO.js");
2353
- const { keccak256, toHex, isAddress: isAddr } = await import("viem");
2348
+ const { createVeniceInferenceAttestation, getEasScanUrl: getEasScanUrl2 } = await import("./eas-LHJF2UCG.js");
2349
+ const { keccak256: keccak2562, toHex, isAddress: isAddr } = await import("viem");
2354
2350
  const { getChainContracts: getChainContracts2 } = await import("./config-REASKDIK.js");
2355
2351
  const { getChain: getActiveChain } = await import("./network-3ZU7UBDU.js");
2356
2352
  const vaultRecipient = opts.vault && isAddr(opts.vault) ? opts.vault : getChainContracts2(getActiveChain().id).vault;
2357
- const promptHash = keccak256(toHex(userContent)).slice(0, 18);
2353
+ const promptHash = keccak2562(toHex(userContent)).slice(0, 18);
2358
2354
  const { uid } = await createVeniceInferenceAttestation(
2359
2355
  result.model,
2360
2356
  result.usage.promptTokens,
@@ -3525,7 +3521,7 @@ function printSimulationResult(result, callType) {
3525
3521
  }
3526
3522
  async function sendSimulationAlert(subdomain, proposalId, vault, execResult, settleResult) {
3527
3523
  try {
3528
- const xmtp = await import("./xmtp-ACB2W573.js");
3524
+ const xmtp = await import("./xmtp-ZACWHUI5.js");
3529
3525
  const { getAccount: getAccount2 } = await import("./client-UHHCB6EZ.js");
3530
3526
  const group = await xmtp.getGroup("", subdomain);
3531
3527
  const allRisks = [...execResult.risks, ...settleResult?.risks ?? []];
@@ -4618,13 +4614,13 @@ function registerGuardianCommands(program2) {
4618
4614
  }
4619
4615
 
4620
4616
  // src/commands/grid.ts
4621
- import chalk12 from "chalk";
4617
+ import chalk14 from "chalk";
4622
4618
 
4623
4619
  // src/grid/loop.ts
4624
- import chalk11 from "chalk";
4625
- import { appendFile, mkdir as mkdir3 } from "fs/promises";
4626
- import { join as join3 } from "path";
4627
- import { homedir as homedir3 } from "os";
4620
+ import chalk13 from "chalk";
4621
+ import { appendFile, mkdir as mkdir4 } from "fs/promises";
4622
+ import { join as join4 } from "path";
4623
+ import { homedir as homedir4 } from "os";
4628
4624
 
4629
4625
  // src/grid/manager.ts
4630
4626
  import chalk9 from "chalk";
@@ -4964,6 +4960,45 @@ var GridManager = class {
4964
4960
  };
4965
4961
  }).filter((e) => e.fillCount > 0);
4966
4962
  }
4963
+ /**
4964
+ * Compute the orders that should be placed for the current grid state,
4965
+ * without simulating fills. Used by the live executor.
4966
+ *
4967
+ * Returns:
4968
+ * - ordersToPlace: all current grid levels that haven't been filled
4969
+ * - assetsToCancel: tokens whose grid was rebalanced (need cancel-and-place)
4970
+ * - needsRebalance: whether any grid was rebuilt this tick
4971
+ */
4972
+ computeOrders(prices) {
4973
+ const state = this.portfolio.getState();
4974
+ if (!state || state.paused || !this.config.enabled) {
4975
+ return { ordersToPlace: [], assetsToCancel: [], needsRebalance: false };
4976
+ }
4977
+ const ordersToPlace = [];
4978
+ const assetsToCancel = [];
4979
+ let needsRebalance = false;
4980
+ for (const grid of state.grids) {
4981
+ const price = prices[grid.token];
4982
+ if (!price || price <= 0) continue;
4983
+ const wasEmpty = grid.levels.length === 0;
4984
+ const fullRebuild = wasEmpty || this.needsFullRebuild(grid);
4985
+ const shift = !fullRebuild && grid.centerPrice > 0 && this.needsShift(grid, price);
4986
+ if (fullRebuild || shift) {
4987
+ needsRebalance = true;
4988
+ if (!wasEmpty) assetsToCancel.push(grid.token);
4989
+ }
4990
+ for (const level of grid.levels) {
4991
+ if (level.filled) continue;
4992
+ ordersToPlace.push({
4993
+ token: grid.token,
4994
+ isBuy: level.side === "buy",
4995
+ price: level.price,
4996
+ quantity: level.quantity
4997
+ });
4998
+ }
4999
+ }
5000
+ return { ordersToPlace, assetsToCancel, needsRebalance };
5001
+ }
4967
5002
  /** Get aggregate stats for display. */
4968
5003
  getStats() {
4969
5004
  const state = this.portfolio.getState();
@@ -5033,8 +5068,8 @@ var GridHedgeManager = class {
5033
5068
  await mkdir2(dirname2(HEDGE_STATE_PATH), { recursive: true });
5034
5069
  const tmp = `${HEDGE_STATE_PATH}.tmp.${process.pid}`;
5035
5070
  await writeFile2(tmp, JSON.stringify(this.state, null, 2), "utf-8");
5036
- const { rename: rename2 } = await import("fs/promises");
5037
- await rename2(tmp, HEDGE_STATE_PATH);
5071
+ const { rename: rename3 } = await import("fs/promises");
5072
+ await rename3(tmp, HEDGE_STATE_PATH);
5038
5073
  }
5039
5074
  /**
5040
5075
  * Run one hedge tick. Call after grid tick with current prices and open fill data.
@@ -5152,14 +5187,330 @@ var GridHedgeManager = class {
5152
5187
  }
5153
5188
  };
5154
5189
 
5190
+ // src/grid/executor.ts
5191
+ import chalk11 from "chalk";
5192
+ var GridExecutor = class {
5193
+ cfg;
5194
+ constructor(cfg) {
5195
+ this.cfg = cfg;
5196
+ }
5197
+ /**
5198
+ * Execute the order plan against Hyperliquid.
5199
+ * Cancels stale orders for rebalanced tokens, then places new orders.
5200
+ */
5201
+ async execute(plan) {
5202
+ const errors = [];
5203
+ let cancelled = 0;
5204
+ let placed = 0;
5205
+ for (const token of plan.assetsToCancel) {
5206
+ const coin = resolveHLCoin(token);
5207
+ if (!coin) {
5208
+ errors.push(`No HL ticker for ${token}`);
5209
+ continue;
5210
+ }
5211
+ try {
5212
+ await hlCancelAllOrders(coin);
5213
+ cancelled++;
5214
+ console.error(chalk11.dim(` [grid-exec] Cancelled all orders for ${coin}`));
5215
+ } catch (e) {
5216
+ errors.push(`Cancel ${coin} failed: ${e.message}`);
5217
+ }
5218
+ }
5219
+ for (const order of plan.ordersToPlace) {
5220
+ const coin = resolveHLCoin(order.token);
5221
+ if (!coin) {
5222
+ errors.push(`No HL ticker for ${order.token}`);
5223
+ continue;
5224
+ }
5225
+ try {
5226
+ const res = await hlPlaceLimitOrder(coin, order.isBuy, order.quantity, order.price);
5227
+ if (res.success) {
5228
+ placed++;
5229
+ } else {
5230
+ errors.push(`Place ${coin} ${order.isBuy ? "buy" : "sell"} @${order.price}: ${res.error}`);
5231
+ }
5232
+ } catch (e) {
5233
+ errors.push(`Place ${coin} threw: ${e.message}`);
5234
+ }
5235
+ }
5236
+ return { placed, cancelled, errors };
5237
+ }
5238
+ };
5239
+
5240
+ // src/grid/onchain-executor.ts
5241
+ import chalk12 from "chalk";
5242
+ import { mkdir as mkdir3, readFile as readFile3, rename as rename2, writeFile as writeFile3 } from "fs/promises";
5243
+ import { dirname as dirname3, join as join3 } from "path";
5244
+ import { homedir as homedir3 } from "os";
5245
+ import { encodeAbiParameters as encodeAbiParameters10, parseUnits as parseUnits6 } from "viem";
5246
+
5247
+ // src/grid/cloid.ts
5248
+ import { keccak256, encodeAbiParameters as encodeAbiParameters9 } from "viem";
5249
+ function gridCloid(strategy2, assetIndex, isBuy, levelIndex, nonce) {
5250
+ const hash = keccak256(
5251
+ encodeAbiParameters9(
5252
+ [
5253
+ { type: "address" },
5254
+ { type: "uint32" },
5255
+ { type: "bool" },
5256
+ { type: "uint32" },
5257
+ { type: "uint32" }
5258
+ ],
5259
+ [strategy2, assetIndex, isBuy, levelIndex, nonce]
5260
+ )
5261
+ );
5262
+ const top16 = hash.slice(0, 2 + 32);
5263
+ return BigInt(top16);
5264
+ }
5265
+
5266
+ // src/grid/strategy-abi.ts
5267
+ var HYPERLIQUID_GRID_STRATEGY_ABI = [
5268
+ {
5269
+ type: "function",
5270
+ name: "updateParams",
5271
+ inputs: [{ name: "data", type: "bytes" }],
5272
+ outputs: [],
5273
+ stateMutability: "nonpayable"
5274
+ }
5275
+ ];
5276
+
5277
+ // src/grid/onchain-executor.ts
5278
+ var ONCHAIN_STATE_PATH = join3(homedir3(), ".sherwood", "grid", "onchain-state.json");
5279
+ var UINT64_MAX = 18446744073709551615n;
5280
+ var ACTION_PLACE_GRID = 1;
5281
+ var ACTION_CANCEL_ALL = 2;
5282
+ var ACTION_CANCEL_AND_PLACE = 3;
5283
+ var GRID_ORDER_COMPONENTS = [
5284
+ { name: "assetIndex", type: "uint32" },
5285
+ { name: "isBuy", type: "bool" },
5286
+ { name: "limitPx", type: "uint64" },
5287
+ { name: "sz", type: "uint64" },
5288
+ { name: "cloid", type: "uint128" }
5289
+ ];
5290
+ var OnchainGridExecutor = class {
5291
+ cfg;
5292
+ nonces = /* @__PURE__ */ new Map();
5293
+ placedCloids = /* @__PURE__ */ new Map();
5294
+ meta = null;
5295
+ busy = false;
5296
+ constructor(cfg) {
5297
+ this.cfg = cfg;
5298
+ }
5299
+ /** Load persisted state. Call once before the first execute(). */
5300
+ async load() {
5301
+ try {
5302
+ const raw = await readFile3(ONCHAIN_STATE_PATH, "utf-8");
5303
+ const state = JSON.parse(raw);
5304
+ for (const [tok, n] of Object.entries(state.nonces)) this.nonces.set(tok, n);
5305
+ for (const [tok, cloids] of Object.entries(state.placedCloids)) {
5306
+ this.placedCloids.set(tok, cloids.map((s) => BigInt(s)));
5307
+ }
5308
+ console.error(chalk12.dim(` [grid-onchain] Loaded state: ${this.nonces.size} tokens`));
5309
+ } catch (e) {
5310
+ const code = e.code;
5311
+ if (code === "ENOENT") {
5312
+ } else {
5313
+ console.error(
5314
+ chalk12.yellow(
5315
+ ` [grid-onchain] Failed to load state (${e.message}) \u2014 starting fresh. Existing on-chain orders may be orphaned.`
5316
+ )
5317
+ );
5318
+ }
5319
+ }
5320
+ if (!this.meta) this.meta = await hlGetMeta();
5321
+ }
5322
+ /**
5323
+ * Atomic save: write to .tmp, then POSIX-rename. A crash mid-write leaves
5324
+ * either the old file intact or the new file fully written — never a
5325
+ * partial JSON that would crash load() on restart.
5326
+ */
5327
+ async save() {
5328
+ const state = {
5329
+ nonces: Object.fromEntries(this.nonces),
5330
+ placedCloids: Object.fromEntries(
5331
+ [...this.placedCloids].map(([tok, cloids]) => [tok, cloids.map((c) => c.toString())])
5332
+ )
5333
+ };
5334
+ await mkdir3(dirname3(ONCHAIN_STATE_PATH), { recursive: true });
5335
+ const tmp = ONCHAIN_STATE_PATH + ".tmp";
5336
+ await writeFile3(tmp, JSON.stringify(state, null, 2));
5337
+ await rename2(tmp, ONCHAIN_STATE_PATH);
5338
+ }
5339
+ /**
5340
+ * Execute the order plan: cancel stale orders for rebalanced tokens, then
5341
+ * place new orders. Each (token) is one tx. Persists state after each tx
5342
+ * so a crash mid-execution still leaves a recoverable on-disk record.
5343
+ *
5344
+ * Concurrency-guarded: a second concurrent call returns immediately rather
5345
+ * than racing tx submission against another in-flight execute().
5346
+ */
5347
+ async execute(plan) {
5348
+ if (this.busy) {
5349
+ return { placed: 0, cancelled: 0, txs: [], errors: ["execute() already in flight \u2014 skipping"] };
5350
+ }
5351
+ this.busy = true;
5352
+ try {
5353
+ if (!this.meta) await this.load();
5354
+ const errors = [];
5355
+ const txs = [];
5356
+ let placed = 0;
5357
+ let cancelled = 0;
5358
+ const ordersByToken = /* @__PURE__ */ new Map();
5359
+ for (const o of plan.ordersToPlace) {
5360
+ if (!ordersByToken.has(o.token)) ordersByToken.set(o.token, []);
5361
+ ordersByToken.get(o.token).push(o);
5362
+ }
5363
+ const cancelSet = new Set(plan.assetsToCancel);
5364
+ const allTokens = /* @__PURE__ */ new Set([...ordersByToken.keys(), ...cancelSet]);
5365
+ for (const token of allTokens) {
5366
+ const assetIndex = this.cfg.assetIndices[token];
5367
+ if (assetIndex === void 0) {
5368
+ errors.push(`No asset index for ${token}`);
5369
+ continue;
5370
+ }
5371
+ const coin = resolveHLCoin(token);
5372
+ if (!coin) {
5373
+ errors.push(`No HL ticker for ${token}`);
5374
+ continue;
5375
+ }
5376
+ const meta = this.meta.get(coin);
5377
+ if (!meta) {
5378
+ errors.push(`No HL meta for ${coin} (run \`sherwood grid status\` to refresh)`);
5379
+ continue;
5380
+ }
5381
+ const wantCancel = cancelSet.has(token);
5382
+ const orders = ordersByToken.get(token) ?? [];
5383
+ const wantPlace = orders.length > 0;
5384
+ try {
5385
+ if (wantCancel && wantPlace) {
5386
+ const tx = await this.cancelAndPlace(token, assetIndex, orders, meta);
5387
+ txs.push(tx);
5388
+ cancelled += 1;
5389
+ placed += orders.length;
5390
+ } else if (wantCancel) {
5391
+ const tx = await this.cancelAll(token, assetIndex);
5392
+ txs.push(tx);
5393
+ cancelled += 1;
5394
+ } else if (wantPlace) {
5395
+ const tx = await this.placeGrid(token, assetIndex, orders, meta);
5396
+ txs.push(tx);
5397
+ placed += orders.length;
5398
+ }
5399
+ await this.save();
5400
+ } catch (e) {
5401
+ errors.push(`${token}: ${e.message}`);
5402
+ }
5403
+ }
5404
+ return { placed, cancelled, txs, errors };
5405
+ } finally {
5406
+ this.busy = false;
5407
+ }
5408
+ }
5409
+ currentNonce(token) {
5410
+ return this.nonces.get(token) ?? 0;
5411
+ }
5412
+ bumpNonce(token) {
5413
+ const next = this.currentNonce(token) + 1;
5414
+ this.nonces.set(token, next);
5415
+ return next;
5416
+ }
5417
+ /**
5418
+ * Pure encoding — does NOT mutate placedCloids. Caller commits CLOIDs
5419
+ * only after the on-chain tx confirms successfully.
5420
+ *
5421
+ * Uses viem's `parseUnits` for decimal scaling instead of float math so
5422
+ * high-szDecimals tokens (BTC=5, ETH=4) keep full precision on small sizes.
5423
+ */
5424
+ encodeOrders(assetIndex, orders, meta, nonce) {
5425
+ const cloids = [];
5426
+ const encoded = orders.map((o, i) => {
5427
+ const cloid = gridCloid(this.cfg.strategyAddress, assetIndex, o.isBuy, i, nonce);
5428
+ cloids.push(cloid);
5429
+ const limitPx = parseUnits6(o.price.toFixed(meta.pxDecimals), meta.pxDecimals);
5430
+ const sz = parseUnits6(o.quantity.toFixed(meta.szDecimals), meta.szDecimals);
5431
+ if (limitPx > UINT64_MAX || sz > UINT64_MAX) {
5432
+ throw new Error(
5433
+ `Order exceeds uint64: token=${o.token} px=${limitPx} sz=${sz}`
5434
+ );
5435
+ }
5436
+ return { assetIndex, isBuy: o.isBuy, limitPx, sz, cloid };
5437
+ });
5438
+ return { encoded, cloids };
5439
+ }
5440
+ async placeGrid(token, assetIndex, orders, meta) {
5441
+ const nonce = this.bumpNonce(token);
5442
+ const { encoded, cloids } = this.encodeOrders(assetIndex, orders, meta, nonce);
5443
+ const data = encodeAbiParameters10(
5444
+ [{ type: "uint8" }, { type: "tuple[]", components: [...GRID_ORDER_COMPONENTS] }],
5445
+ [ACTION_PLACE_GRID, encoded]
5446
+ );
5447
+ const tx = await this.send(data);
5448
+ this.placedCloids.set(token, cloids);
5449
+ return tx;
5450
+ }
5451
+ async cancelAll(token, assetIndex) {
5452
+ const cloids = this.placedCloids.get(token) ?? [];
5453
+ if (cloids.length === 0) {
5454
+ this.bumpNonce(token);
5455
+ return "0x";
5456
+ }
5457
+ const data = encodeAbiParameters10(
5458
+ [{ type: "uint8" }, { type: "uint32" }, { type: "uint128[]" }],
5459
+ [ACTION_CANCEL_ALL, assetIndex, cloids]
5460
+ );
5461
+ const tx = await this.send(data);
5462
+ this.placedCloids.set(token, []);
5463
+ this.bumpNonce(token);
5464
+ return tx;
5465
+ }
5466
+ async cancelAndPlace(token, assetIndex, orders, meta) {
5467
+ const oldCloids = this.placedCloids.get(token) ?? [];
5468
+ const newNonce = this.bumpNonce(token);
5469
+ const { encoded, cloids: newCloids } = this.encodeOrders(assetIndex, orders, meta, newNonce);
5470
+ const data = encodeAbiParameters10(
5471
+ [
5472
+ { type: "uint8" },
5473
+ { type: "uint32" },
5474
+ { type: "uint128[]" },
5475
+ { type: "tuple[]", components: [...GRID_ORDER_COMPONENTS] }
5476
+ ],
5477
+ [ACTION_CANCEL_AND_PLACE, assetIndex, oldCloids, encoded]
5478
+ );
5479
+ const tx = await this.send(data);
5480
+ this.placedCloids.set(token, newCloids);
5481
+ return tx;
5482
+ }
5483
+ /**
5484
+ * Submit and wait for receipt. Throwing here surfaces to the per-token
5485
+ * try/catch in execute(), recording the error and skipping the save() so
5486
+ * placedCloids never reflects orders that didn't land.
5487
+ */
5488
+ async send(data) {
5489
+ const tx = await writeContractWithRetry({
5490
+ address: this.cfg.strategyAddress,
5491
+ abi: HYPERLIQUID_GRID_STRATEGY_ABI,
5492
+ functionName: "updateParams",
5493
+ args: [data]
5494
+ });
5495
+ const pub = getPublicClient();
5496
+ const receipt = await pub.waitForTransactionReceipt({ hash: tx, timeout: 3e4 });
5497
+ if (receipt.status !== "success") {
5498
+ throw new Error(`Tx ${tx} reverted on-chain`);
5499
+ }
5500
+ console.error(chalk12.dim(` [grid-onchain] tx ${tx.slice(0, 10)}... confirmed`));
5501
+ return tx;
5502
+ }
5503
+ };
5504
+
5155
5505
  // src/grid/loop.ts
5156
- var GRID_CYCLES_PATH = join3(homedir3(), ".sherwood", "grid", "cycles.jsonl");
5506
+ var GRID_CYCLES_PATH = join4(homedir4(), ".sherwood", "grid", "cycles.jsonl");
5157
5507
  var GridLoop = class {
5158
5508
  cfg;
5159
5509
  gridConfig;
5160
5510
  manager;
5161
5511
  hedge;
5162
5512
  hl;
5513
+ executor = null;
5163
5514
  running = false;
5164
5515
  cycleCount = 0;
5165
5516
  timer = null;
@@ -5169,12 +5520,25 @@ var GridLoop = class {
5169
5520
  this.manager = new GridManager(this.gridConfig);
5170
5521
  this.hedge = new GridHedgeManager();
5171
5522
  this.hl = new HyperliquidProvider();
5523
+ if (cfg.live) {
5524
+ if (!cfg.assetIndices) {
5525
+ throw new Error("assetIndices required when live=true");
5526
+ }
5527
+ if (cfg.strategyAddress) {
5528
+ this.executor = new OnchainGridExecutor({
5529
+ strategyAddress: cfg.strategyAddress,
5530
+ assetIndices: cfg.assetIndices
5531
+ });
5532
+ } else {
5533
+ this.executor = new GridExecutor({ assetIndices: cfg.assetIndices });
5534
+ }
5535
+ }
5172
5536
  }
5173
5537
  /** Start the grid loop. Resolves when shut down via SIGINT/SIGTERM. */
5174
5538
  async start() {
5175
5539
  this.running = true;
5176
5540
  const shutdown = () => {
5177
- console.error(chalk11.yellow("\n [grid-loop] Shutting down\u2026"));
5541
+ console.error(chalk13.yellow("\n [grid-loop] Shutting down\u2026"));
5178
5542
  this.running = false;
5179
5543
  if (this.timer) {
5180
5544
  clearTimeout(this.timer);
@@ -5184,7 +5548,10 @@ var GridLoop = class {
5184
5548
  process.on("SIGINT", shutdown);
5185
5549
  process.on("SIGTERM", shutdown);
5186
5550
  await this.manager.init(this.cfg.capital);
5187
- console.error(chalk11.cyan(
5551
+ if (this.executor instanceof OnchainGridExecutor) {
5552
+ await this.executor.load();
5553
+ }
5554
+ console.error(chalk13.cyan(
5188
5555
  `
5189
5556
  [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
5190
5557
  `
@@ -5193,7 +5560,7 @@ var GridLoop = class {
5193
5560
  try {
5194
5561
  await this.tick();
5195
5562
  } catch (err) {
5196
- console.error(chalk11.red(` [grid-loop] Tick error: ${err.message}`));
5563
+ console.error(chalk13.red(` [grid-loop] Tick error: ${err.message}`));
5197
5564
  }
5198
5565
  if (this.running) {
5199
5566
  await new Promise((resolve2) => {
@@ -5203,7 +5570,7 @@ var GridLoop = class {
5203
5570
  }
5204
5571
  process.off("SIGINT", shutdown);
5205
5572
  process.off("SIGTERM", shutdown);
5206
- console.error(chalk11.yellow(" [grid-loop] Stopped."));
5573
+ console.error(chalk13.yellow(" [grid-loop] Stopped."));
5207
5574
  }
5208
5575
  /** Execute one grid cycle. */
5209
5576
  async tick() {
@@ -5217,25 +5584,37 @@ var GridLoop = class {
5217
5584
  }
5218
5585
  }
5219
5586
  if (Object.keys(prices).length === 0) {
5220
- console.error(chalk11.dim(` [grid-loop] #${this.cycleCount} \u2014 no prices, skipping`));
5587
+ console.error(chalk13.dim(` [grid-loop] #${this.cycleCount} \u2014 no prices, skipping`));
5221
5588
  return;
5222
5589
  }
5223
5590
  const result = await this.manager.tick(prices);
5224
5591
  const elapsed = Date.now() - start;
5592
+ if (this.executor) {
5593
+ const plan = this.manager.computeOrders(prices);
5594
+ if (plan.ordersToPlace.length > 0 || plan.assetsToCancel.length > 0) {
5595
+ const res = await this.executor.execute(plan);
5596
+ if (res.errors.length > 0) {
5597
+ console.error(chalk13.yellow(` [grid-loop] Executor errors: ${res.errors.join("; ")}`));
5598
+ }
5599
+ if (res.placed > 0 || res.cancelled > 0) {
5600
+ console.error(chalk13.cyan(` [grid-loop] Live: placed=${res.placed} cancelled=${res.cancelled}`));
5601
+ }
5602
+ }
5603
+ }
5225
5604
  if (result.roundTrips > 0) {
5226
- console.error(chalk11.green(
5605
+ console.error(chalk13.green(
5227
5606
  ` [grid-loop] #${this.cycleCount} \u2014 ${result.roundTrips} RT(s), +$${result.pnlUsd.toFixed(2)} PnL, ${result.fills} fill(s) [${elapsed}ms]`
5228
5607
  ));
5229
5608
  }
5230
5609
  if (result.fills > 0 && result.roundTrips === 0) {
5231
- console.error(chalk11.dim(
5610
+ console.error(chalk13.dim(
5232
5611
  ` [grid-loop] #${this.cycleCount} \u2014 ${result.fills} fill(s), 0 RTs [${elapsed}ms]`
5233
5612
  ));
5234
5613
  }
5235
5614
  const openExposure = this.manager.getOpenFillExposure();
5236
5615
  const hedgeResult = await this.hedge.tick(openExposure, prices);
5237
5616
  if (hedgeResult.adjustments > 0) {
5238
- console.error(chalk11.magenta(
5617
+ console.error(chalk13.magenta(
5239
5618
  ` [hedge] ${hedgeResult.adjustments} adjustment(s), unrealized: $${hedgeResult.unrealizedPnl.toFixed(2)}, total realized: $${hedgeResult.totalRealizedPnl.toFixed(2)}`
5240
5619
  ));
5241
5620
  }
@@ -5255,7 +5634,7 @@ var GridLoop = class {
5255
5634
  hedgeTotalRealizedPnl: hedgeResult.totalRealizedPnl
5256
5635
  };
5257
5636
  try {
5258
- await mkdir3(join3(homedir3(), ".sherwood", "grid"), { recursive: true });
5637
+ await mkdir4(join4(homedir4(), ".sherwood", "grid"), { recursive: true });
5259
5638
  await appendFile(GRID_CYCLES_PATH, JSON.stringify(cycleEntry) + "\n");
5260
5639
  } catch {
5261
5640
  }
@@ -5264,7 +5643,7 @@ var GridLoop = class {
5264
5643
  if (stats2) {
5265
5644
  const hedgeStatus = this.hedge.getStatus();
5266
5645
  const hedgeInfo = hedgeStatus && hedgeStatus.positions.length > 0 ? ` hedge=$${hedgeResult.unrealizedPnl.toFixed(2)}unr/$${hedgeStatus.totalRealizedPnl.toFixed(2)}real` : "";
5267
- console.error(chalk11.cyan(
5646
+ console.error(chalk13.cyan(
5268
5647
  ` [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)" : ""}`
5269
5648
  ));
5270
5649
  }
@@ -5273,19 +5652,36 @@ var GridLoop = class {
5273
5652
  };
5274
5653
 
5275
5654
  // src/commands/grid.ts
5276
- var DIM5 = chalk12.gray;
5277
- var G5 = chalk12.green;
5278
- var BOLD5 = chalk12.white.bold;
5279
- var W5 = chalk12.white;
5655
+ var DIM5 = chalk14.gray;
5656
+ var G5 = chalk14.green;
5657
+ var BOLD5 = chalk14.white.bold;
5658
+ var W5 = chalk14.white;
5280
5659
  var SEP5 = () => console.log(DIM5("\u2500".repeat(60)));
5281
5660
  function registerGridCommand(program2) {
5282
5661
  const grid = program2.command("grid").description("Grid trading strategy \u2014 ATR-based grid on BTC/ETH/SOL");
5283
- grid.command("start").description("Start the grid trading loop").option("--capital <usd>", "Starting capital in USD", "5000").option("--cycle <seconds>", "Cycle interval in seconds", "60").option("--tokens <list>", "Comma-separated token list", "bitcoin,ethereum,solana").option("--leverage <n>", "Leverage multiplier", "5").option("--levels <n>", "Grid levels per side", "15").action(async (opts) => {
5662
+ grid.command("start").description("Start the grid trading loop").option("--capital <usd>", "Starting capital in USD", "5000").option("--cycle <seconds>", "Cycle interval in seconds", "60").option("--tokens <list>", "Comma-separated token list", "bitcoin,ethereum,solana").option("--leverage <n>", "Leverage multiplier", "5").option("--levels <n>", "Grid levels per side", "15").option("--live", "enable live execution (places real orders on Hyperliquid)").option("--asset-indices <pairs>", "comma-separated token=index pairs (e.g. bitcoin=3,ethereum=4,solana=5)").option("--strategy <address>", "on-chain strategy contract address (enables on-chain executor)").action(async (opts) => {
5284
5663
  const capital = parseFloat(opts.capital);
5285
5664
  const cycleMs = parseInt(opts.cycle, 10) * 1e3;
5286
5665
  const tokens = opts.tokens.split(",").map((t) => t.trim());
5287
5666
  const leverage = parseFloat(opts.leverage);
5288
5667
  const levels = parseInt(opts.levels, 10);
5668
+ const live = !!opts.live;
5669
+ let assetIndices;
5670
+ if (live) {
5671
+ if (!opts.assetIndices) {
5672
+ throw new Error("--asset-indices required when --live (e.g. --asset-indices bitcoin=3,ethereum=4,solana=5)");
5673
+ }
5674
+ assetIndices = {};
5675
+ for (const pair of opts.assetIndices.split(",")) {
5676
+ const [tok, idx] = pair.split("=");
5677
+ if (!tok || !idx) throw new Error(`Bad asset-indices pair: ${pair}`);
5678
+ assetIndices[tok.trim()] = Number(idx);
5679
+ }
5680
+ }
5681
+ const strategyAddress = opts.strategy;
5682
+ if (strategyAddress && !live) {
5683
+ throw new Error("--strategy requires --live");
5684
+ }
5289
5685
  const weight = 1 / tokens.length;
5290
5686
  const tokenSplit = {};
5291
5687
  for (const t of tokens) {
@@ -5303,6 +5699,9 @@ function registerGridCommand(program2) {
5303
5699
  const loop = new GridLoop({
5304
5700
  capital,
5305
5701
  cycle: cycleMs,
5702
+ live,
5703
+ assetIndices,
5704
+ strategyAddress,
5306
5705
  config: {
5307
5706
  ...DEFAULT_GRID_CONFIG,
5308
5707
  tokens,
@@ -5326,7 +5725,7 @@ function registerGridCommand(program2) {
5326
5725
  console.log(G5.bold(" Grid Portfolio"));
5327
5726
  SEP5();
5328
5727
  console.log(W5(` Allocation: $${state.totalAllocation.toLocaleString()}`));
5329
- console.log(W5(` Status: ${state.paused ? chalk12.red("PAUSED \u2014 " + state.pauseReason) : G5("Active")}`));
5728
+ console.log(W5(` Status: ${state.paused ? chalk14.red("PAUSED \u2014 " + state.pauseReason) : G5("Active")}`));
5330
5729
  console.log(W5(` Initialized: ${new Date(state.initializedAt).toLocaleString()}`));
5331
5730
  SEP5();
5332
5731
  console.log();
@@ -5339,13 +5738,13 @@ function registerGridCommand(program2) {
5339
5738
  const pnl = `$${g.stats.totalPnlUsd.toFixed(2)}`.padStart(10);
5340
5739
  const todayPnl = `$${g.stats.todayPnlUsd.toFixed(2)}`.padStart(10);
5341
5740
  const fills = String(g.stats.totalFills).padStart(6);
5342
- const pnlColor = g.stats.totalPnlUsd >= 0 ? G5 : chalk12.red;
5343
- const todayColor = g.stats.todayPnlUsd >= 0 ? G5 : chalk12.red;
5741
+ const pnlColor = g.stats.totalPnlUsd >= 0 ? G5 : chalk14.red;
5742
+ const todayColor = g.stats.todayPnlUsd >= 0 ? G5 : chalk14.red;
5344
5743
  console.log(` ${W5(name)} ${alloc} ${rts} ${pnlColor(pnl)} ${todayColor(todayPnl)} ${fills}`);
5345
5744
  }
5346
5745
  console.log(DIM5(" " + "\u2500".repeat(72)));
5347
- const totalPnlColor = agg.totalPnlUsd >= 0 ? G5 : chalk12.red;
5348
- const todayTotalColor = agg.todayPnlUsd >= 0 ? G5 : chalk12.red;
5746
+ const totalPnlColor = agg.totalPnlUsd >= 0 ? G5 : chalk14.red;
5747
+ const todayTotalColor = agg.todayPnlUsd >= 0 ? G5 : chalk14.red;
5349
5748
  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)}`);
5350
5749
  console.log();
5351
5750
  });
@@ -5359,20 +5758,20 @@ try {
5359
5758
  var require2 = createRequire(import.meta.url);
5360
5759
  var { version: CLI_VERSION } = require2("../package.json");
5361
5760
  async function loadXmtp() {
5362
- return import("./xmtp-ACB2W573.js");
5761
+ return import("./xmtp-ZACWHUI5.js");
5363
5762
  }
5364
5763
  async function loadCron() {
5365
5764
  return import("./cron-EOULYO3R.js");
5366
5765
  }
5367
- var G6 = chalk13.green;
5368
- var W6 = chalk13.white;
5369
- var DIM6 = chalk13.gray;
5370
- var BOLD6 = chalk13.white.bold;
5371
- var LABEL5 = chalk13.green.bold;
5766
+ var G6 = chalk15.green;
5767
+ var W6 = chalk15.white;
5768
+ var DIM6 = chalk15.gray;
5769
+ var BOLD6 = chalk15.white.bold;
5770
+ var LABEL5 = chalk15.green.bold;
5372
5771
  var SEP6 = () => console.log(DIM6("\u2500".repeat(60)));
5373
5772
  function validateAddress(value, name) {
5374
5773
  if (!isAddress6(value)) {
5375
- console.error(chalk13.red(`Invalid ${name} address: ${value}`));
5774
+ console.error(chalk15.red(`Invalid ${name} address: ${value}`));
5376
5775
  process.exit(1);
5377
5776
  }
5378
5777
  return value;
@@ -5392,7 +5791,7 @@ program.name("sherwood").description("CLI for agent-managed investment syndicate
5392
5791
  process.env.ENABLE_TESTNET = "true";
5393
5792
  if (network !== "base") {
5394
5793
  console.warn(
5395
- chalk13.yellow("[warn] --testnet ignored, --chain takes precedence")
5794
+ chalk15.yellow("[warn] --testnet ignored, --chain takes precedence")
5396
5795
  );
5397
5796
  } else {
5398
5797
  network = "base-sepolia";
@@ -5400,7 +5799,7 @@ program.name("sherwood").description("CLI for agent-managed investment syndicate
5400
5799
  }
5401
5800
  setNetwork(network);
5402
5801
  if (getNetwork() !== "base") {
5403
- console.log(chalk13.yellow(`[${getNetwork()}]`));
5802
+ console.log(chalk15.yellow(`[${getNetwork()}]`));
5404
5803
  }
5405
5804
  });
5406
5805
  var syndicate = program.command("syndicate");
@@ -5448,7 +5847,7 @@ syndicate.command("create").description("Create a new syndicate via the factory
5448
5847
  asset = opts.asset;
5449
5848
  } else {
5450
5849
  const supported = Object.keys(ASSET_SYMBOLS).join(", ");
5451
- console.error(chalk13.red(` Unknown asset "${opts.asset}". Use a symbol (${supported}) or a 0x address.`));
5850
+ console.error(chalk15.red(` Unknown asset "${opts.asset}". Use a symbol (${supported}) or a 0x address.`));
5452
5851
  process.exit(1);
5453
5852
  }
5454
5853
  } else if (nonInteractive) {
@@ -5478,7 +5877,7 @@ syndicate.command("create").description("Create a new syndicate via the factory
5478
5877
  console.log(W6(` Agent ID: #${agentIdStr}`));
5479
5878
  console.log(W6(` Asset: ${assetSymbol} (${asset.slice(0, 10)}...)`));
5480
5879
  console.log(W6(` Share token: ${symbol}`));
5481
- console.log(W6(` Open deposits: ${openDeposits ? G6("yes") : chalk13.red("no (whitelist)")}`));
5880
+ console.log(W6(` Open deposits: ${openDeposits ? G6("yes") : chalk15.red("no (whitelist)")}`));
5482
5881
  SEP6();
5483
5882
  if (!nonInteractive) {
5484
5883
  const go = await confirm({ message: G6("Deploy syndicate?"), default: true });
@@ -5505,7 +5904,7 @@ syndicate.command("create").description("Create a new syndicate via the factory
5505
5904
  metadataURI = await uploadMetadata(metadata);
5506
5905
  spinner2.succeed(G6(`Metadata pinned: ${DIM6(metadataURI)}`));
5507
5906
  } catch (err) {
5508
- spinner2.warn(chalk13.yellow(`IPFS upload failed \u2014 using inline metadata`));
5907
+ spinner2.warn(chalk15.yellow(`IPFS upload failed \u2014 using inline metadata`));
5509
5908
  const json = JSON.stringify({ name, description, subdomain, asset: assetSymbol, openDeposits, createdBy: "@sherwoodagent/cli" });
5510
5909
  metadataURI = `data:application/json;base64,${Buffer.from(json).toString("base64")}`;
5511
5910
  }
@@ -5515,12 +5914,12 @@ syndicate.command("create").description("Create a new syndicate via the factory
5515
5914
  const existingInfo = await getSyndicate(existingId);
5516
5915
  const callerAddress = getAccount().address.toLowerCase();
5517
5916
  if (existingInfo.creator.toLowerCase() !== callerAddress) {
5518
- console.error(chalk13.red(`
5917
+ console.error(chalk15.red(`
5519
5918
  \u2716 Subdomain '${subdomain}' is already taken by another syndicate.
5520
5919
  `));
5521
5920
  process.exit(1);
5522
5921
  }
5523
- console.log(chalk13.yellow(`
5922
+ console.log(chalk15.yellow(`
5524
5923
  \u26A0 Syndicate '${subdomain}' already exists \u2014 resuming setup...
5525
5924
  `));
5526
5925
  const spinner2 = ora8({ text: W6("Resuming setup..."), color: "green" }).start();
@@ -5551,7 +5950,7 @@ syndicate.command("create").description("Create a new syndicate via the factory
5551
5950
  cacheGroupId(subdomain, groupId);
5552
5951
  }
5553
5952
  } catch {
5554
- console.warn(chalk13.yellow("\n \u26A0 Could not set up XMTP chat group"));
5953
+ console.warn(chalk15.yellow("\n \u26A0 Could not set up XMTP chat group"));
5555
5954
  }
5556
5955
  try {
5557
5956
  const cron = await loadCron();
@@ -5598,7 +5997,7 @@ syndicate.command("create").description("Create a new syndicate via the factory
5598
5997
  // agentAddress = creator EOA (direct execution)
5599
5998
  );
5600
5999
  } catch (regErr) {
5601
- console.warn(chalk13.yellow("\n \u26A0 Could not auto-register creator as agent \u2014 register manually with `syndicate add`"));
6000
+ console.warn(chalk15.yellow("\n \u26A0 Could not auto-register creator as agent \u2014 register manually with `syndicate add`"));
5602
6001
  }
5603
6002
  spinner.text = W6("Setting up chat...");
5604
6003
  try {
@@ -5611,8 +6010,8 @@ syndicate.command("create").description("Create a new syndicate via the factory
5611
6010
  } catch {
5612
6011
  }
5613
6012
  } catch {
5614
- console.warn(chalk13.yellow("\n \u26A0 Could not create XMTP chat group"));
5615
- console.warn(chalk13.dim(` Recover later with: sherwood chat ${subdomain} init`));
6013
+ console.warn(chalk15.yellow("\n \u26A0 Could not create XMTP chat group"));
6014
+ console.warn(chalk15.dim(` Recover later with: sherwood chat ${subdomain} init`));
5616
6015
  }
5617
6016
  try {
5618
6017
  const cron = await loadCron();
@@ -5640,7 +6039,7 @@ syndicate.command("create").description("Create a new syndicate via the factory
5640
6039
  console.log(G6(" \u2713 Syndicate saved to ~/.sherwood/config.json (set as primary)"));
5641
6040
  console.log();
5642
6041
  } catch (err) {
5643
- console.error(chalk13.red(`
6042
+ console.error(chalk15.red(`
5644
6043
  \u2716 ${formatContractError(err)}`));
5645
6044
  process.exit(1);
5646
6045
  }
@@ -5690,38 +6089,38 @@ syndicate.command("list").description("List active syndicates (queries subgraph,
5690
6089
  }
5691
6090
  spinner.stop();
5692
6091
  if (syndicates.length === 0) {
5693
- console.log(chalk13.dim("No active syndicates found."));
6092
+ console.log(chalk15.dim("No active syndicates found."));
5694
6093
  return;
5695
6094
  }
5696
6095
  console.log();
5697
- console.log(chalk13.bold(`Active Syndicates (${syndicates.length})`));
6096
+ console.log(chalk15.bold(`Active Syndicates (${syndicates.length})`));
5698
6097
  if (!process.env.SUBGRAPH_URL && !opts.allChains) {
5699
- console.log(chalk13.dim(" (Set SUBGRAPH_URL for faster indexed queries)"));
6098
+ console.log(chalk15.dim(" (Set SUBGRAPH_URL for faster indexed queries)"));
5700
6099
  }
5701
6100
  if (opts.allChains) {
5702
- console.log(chalk13.dim(" (Aggregated across chains via on-chain factory calls; SUBGRAPH_URL is single-chain only)"));
6101
+ console.log(chalk15.dim(" (Aggregated across chains via on-chain factory calls; SUBGRAPH_URL is single-chain only)"));
5703
6102
  }
5704
- console.log(chalk13.dim("\u2500".repeat(70)));
6103
+ console.log(chalk15.dim("\u2500".repeat(70)));
5705
6104
  for (const s of syndicates) {
5706
6105
  const ts = typeof s.createdAt === "string" ? Number(s.createdAt) : Number(s.createdAt);
5707
6106
  const date = new Date(ts * 1e3).toLocaleDateString();
5708
6107
  const ensName = s.subdomain ? `${s.subdomain}.sherwoodagent.eth` : "";
5709
- const chainTag = s.chain ? chalk13.dim(`[${s.chain}] `) : "";
5710
- console.log(` ${chainTag}#${s.id} ${chalk13.bold(ensName || String(s.vault))}`);
5711
- if (ensName) console.log(` Vault: ${chalk13.cyan(String(s.vault))}`);
6108
+ const chainTag = s.chain ? chalk15.dim(`[${s.chain}] `) : "";
6109
+ console.log(` ${chainTag}#${s.id} ${chalk15.bold(ensName || String(s.vault))}`);
6110
+ if (ensName) console.log(` Vault: ${chalk15.cyan(String(s.vault))}`);
5712
6111
  console.log(` Creator: ${s.creator}`);
5713
6112
  console.log(` Created: ${date}`);
5714
6113
  if (s.totalDeposits) {
5715
6114
  console.log(` Deposits: ${s.totalDeposits} USDC`);
5716
6115
  }
5717
6116
  if (s.metadataURI) {
5718
- console.log(` Metadata: ${chalk13.dim(s.metadataURI)}`);
6117
+ console.log(` Metadata: ${chalk15.dim(s.metadataURI)}`);
5719
6118
  }
5720
6119
  console.log();
5721
6120
  }
5722
6121
  } catch (err) {
5723
6122
  spinner.fail("Failed to load syndicates");
5724
- console.error(chalk13.red(formatContractError(err)));
6123
+ console.error(chalk15.red(formatContractError(err)));
5725
6124
  process.exit(1);
5726
6125
  }
5727
6126
  });
@@ -5761,38 +6160,38 @@ syndicate.command("info").description("Display syndicate details by ID or subdom
5761
6160
  spinner.stop();
5762
6161
  if (crossChainHint) {
5763
6162
  const others = crossChainHint.others.length > 0 ? ` (also on: ${crossChainHint.others.join(", ")})` : "";
5764
- console.log(chalk13.yellow(` Found on chain: ${chalk13.bold(crossChainHint.network)}${others}`));
5765
- console.log(chalk13.dim(` Re-run with --chain ${crossChainHint.network} to interact with this syndicate.`));
6163
+ console.log(chalk15.yellow(` Found on chain: ${chalk15.bold(crossChainHint.network)}${others}`));
6164
+ console.log(chalk15.dim(` Re-run with --chain ${crossChainHint.network} to interact with this syndicate.`));
5766
6165
  console.log();
5767
6166
  }
5768
6167
  if (!info.vault || info.vault === "0x0000000000000000000000000000000000000000") {
5769
- console.log(chalk13.red(`Syndicate #${id} not found.`));
6168
+ console.log(chalk15.red(`Syndicate #${id} not found.`));
5770
6169
  process.exit(1);
5771
6170
  }
5772
6171
  const date = new Date(Number(info.createdAt) * 1e3).toLocaleDateString();
5773
6172
  console.log();
5774
- console.log(chalk13.bold(`Syndicate #${info.id}`));
5775
- console.log(chalk13.dim("\u2500".repeat(40)));
6173
+ console.log(chalk15.bold(`Syndicate #${info.id}`));
6174
+ console.log(chalk15.dim("\u2500".repeat(40)));
5776
6175
  if (info.subdomain) {
5777
- console.log(` ENS: ${chalk13.bold(`${info.subdomain}.sherwoodagent.eth`)}`);
6176
+ console.log(` ENS: ${chalk15.bold(`${info.subdomain}.sherwoodagent.eth`)}`);
5778
6177
  }
5779
- console.log(` Vault: ${chalk13.cyan(info.vault)}`);
6178
+ console.log(` Vault: ${chalk15.cyan(info.vault)}`);
5780
6179
  console.log(` Creator: ${info.creator}`);
5781
6180
  console.log(` Created: ${date}`);
5782
- console.log(` Active: ${info.active ? chalk13.green("yes") : chalk13.red("no")}`);
6181
+ console.log(` Active: ${info.active ? chalk15.green("yes") : chalk15.red("no")}`);
5783
6182
  if (info.metadataURI) {
5784
- console.log(` Metadata: ${chalk13.dim(info.metadataURI)}`);
6183
+ console.log(` Metadata: ${chalk15.dim(info.metadataURI)}`);
5785
6184
  }
5786
6185
  if (info.subdomain) {
5787
6186
  const xmtpGroupId = getCachedGroupId(info.subdomain);
5788
6187
  if (xmtpGroupId) {
5789
- console.log(` XMTP Group: ${chalk13.cyan(xmtpGroupId)}`);
6188
+ console.log(` XMTP Group: ${chalk15.cyan(xmtpGroupId)}`);
5790
6189
  }
5791
6190
  }
5792
6191
  setVaultAddress(info.vault);
5793
6192
  const vaultInfo = crossChainHint ? await withNetwork(crossChainHint.network, () => getVaultInfo()) : await getVaultInfo();
5794
6193
  console.log();
5795
- console.log(chalk13.bold(" Vault Stats"));
6194
+ console.log(chalk15.bold(" Vault Stats"));
5796
6195
  console.log(` Total Assets: ${vaultInfo.totalAssets}`);
5797
6196
  console.log(` Agent Count: ${vaultInfo.agentCount}`);
5798
6197
  console.log(` Redemptions Locked: ${vaultInfo.redemptionsLocked}`);
@@ -5800,7 +6199,7 @@ syndicate.command("info").description("Display syndicate details by ID or subdom
5800
6199
  console.log();
5801
6200
  } catch (err) {
5802
6201
  spinner.fail("Failed to load syndicate info");
5803
- console.error(chalk13.red(formatContractError(err)));
6202
+ console.error(chalk15.red(formatContractError(err)));
5804
6203
  process.exit(1);
5805
6204
  }
5806
6205
  });
@@ -5836,7 +6235,7 @@ syndicate.command("update-metadata").description("Update syndicate metadata (cre
5836
6235
  console.log(DIM6(` ${getExplorerUrl(hash)}`));
5837
6236
  } catch (err) {
5838
6237
  spinner.fail("Metadata update failed");
5839
- console.error(chalk13.red(formatContractError(err)));
6238
+ console.error(chalk15.red(formatContractError(err)));
5840
6239
  process.exit(1);
5841
6240
  }
5842
6241
  });
@@ -5847,10 +6246,10 @@ syndicate.command("approve-depositor").description("Approve an address to deposi
5847
6246
  const depositor = validateAddress(opts.depositor, "depositor");
5848
6247
  const hash = await approveDepositor(depositor);
5849
6248
  spinner.succeed(`Depositor approved: ${hash}`);
5850
- console.log(chalk13.dim(` ${getExplorerUrl(hash)}`));
6249
+ console.log(chalk15.dim(` ${getExplorerUrl(hash)}`));
5851
6250
  } catch (err) {
5852
6251
  spinner.fail("Approval failed");
5853
- console.error(chalk13.red(formatContractError(err)));
6252
+ console.error(chalk15.red(formatContractError(err)));
5854
6253
  process.exit(1);
5855
6254
  }
5856
6255
  });
@@ -5861,10 +6260,10 @@ syndicate.command("remove-depositor").description("Remove an address from the de
5861
6260
  const depositor = validateAddress(opts.depositor, "depositor");
5862
6261
  const hash = await removeDepositor(depositor);
5863
6262
  spinner.succeed(`Depositor removed: ${hash}`);
5864
- console.log(chalk13.dim(` ${getExplorerUrl(hash)}`));
6263
+ console.log(chalk15.dim(` ${getExplorerUrl(hash)}`));
5865
6264
  } catch (err) {
5866
6265
  spinner.fail("Removal failed");
5867
- console.error(chalk13.red(formatContractError(err)));
6266
+ console.error(chalk15.red(formatContractError(err)));
5868
6267
  process.exit(1);
5869
6268
  }
5870
6269
  });
@@ -5905,7 +6304,7 @@ syndicate.command("add").description("Register an agent on a syndicate vault (cr
5905
6304
  });
5906
6305
  if (balance === 0n) {
5907
6306
  spinner.fail("Agent wallet does not own an ERC-8004 identity NFT");
5908
- console.error(chalk13.dim(" Mint one first: sherwood identity mint --name <name>"));
6307
+ console.error(chalk15.dim(" Mint one first: sherwood identity mint --name <name>"));
5909
6308
  process.exit(1);
5910
6309
  }
5911
6310
  const tokenId = await client.readContract({
@@ -5921,13 +6320,13 @@ syndicate.command("add").description("Register an agent on a syndicate vault (cr
5921
6320
  args: [agentWallet, 0n]
5922
6321
  });
5923
6322
  agentId = tokenId;
5924
- console.log(chalk13.dim(` Resolved agent ID: #${agentId}`));
6323
+ console.log(chalk15.dim(` Resolved agent ID: #${agentId}`));
5925
6324
  }
5926
6325
  }
5927
6326
  spinner.text = "Registering agent...";
5928
6327
  const hash = await registerAgent(agentId, agentWallet);
5929
6328
  spinner.succeed(`Agent registered: ${hash}`);
5930
- console.log(chalk13.dim(` ${getExplorerUrl(hash)}`));
6329
+ console.log(chalk15.dim(` ${getExplorerUrl(hash)}`));
5931
6330
  try {
5932
6331
  const xmtp = await loadXmtp();
5933
6332
  const xmtpClient = await xmtp.getXmtpClient();
@@ -5939,14 +6338,14 @@ syndicate.command("add").description("Register an agent on a syndicate vault (cr
5939
6338
  syndicate: subdomain,
5940
6339
  timestamp: Math.floor(Date.now() / 1e3)
5941
6340
  });
5942
- console.log(chalk13.dim(` Added to chat: ${subdomain}`));
6341
+ console.log(chalk15.dim(` Added to chat: ${subdomain}`));
5943
6342
  } catch {
5944
- console.warn(chalk13.yellow(" \u26A0 Could not add agent to chat group"));
5945
- console.warn(chalk13.dim(` If no group exists, run: sherwood chat ${subdomain} init`));
6343
+ console.warn(chalk15.yellow(" \u26A0 Could not add agent to chat group"));
6344
+ console.warn(chalk15.dim(` If no group exists, run: sherwood chat ${subdomain} init`));
5946
6345
  }
5947
6346
  } catch (err) {
5948
6347
  spinner.fail("Registration failed");
5949
- console.error(chalk13.red(formatContractError(err)));
6348
+ console.error(chalk15.red(formatContractError(err)));
5950
6349
  process.exit(1);
5951
6350
  }
5952
6351
  });
@@ -5954,7 +6353,7 @@ syndicate.command("share").description("Print the shareable dashboard URL for yo
5954
6353
  try {
5955
6354
  const subdomain = opts.subdomain || getPrimarySyndicate(getChain().id)?.subdomain;
5956
6355
  if (!subdomain) {
5957
- console.error(chalk13.red(" No syndicate configured. Pass --subdomain <name> or run 'syndicate create/join' first."));
6356
+ console.error(chalk15.red(" No syndicate configured. Pass --subdomain <name> or run 'syndicate create/join' first."));
5958
6357
  process.exit(1);
5959
6358
  }
5960
6359
  const syndicateInfo = await resolveSyndicate(subdomain);
@@ -5981,7 +6380,7 @@ syndicate.command("share").description("Print the shareable dashboard URL for yo
5981
6380
  }
5982
6381
  console.log();
5983
6382
  } catch (err) {
5984
- console.error(chalk13.red(` \u2716 ${formatContractError(err)}`));
6383
+ console.error(chalk15.red(` \u2716 ${formatContractError(err)}`));
5985
6384
  process.exit(1);
5986
6385
  }
5987
6386
  });
@@ -6006,14 +6405,14 @@ syndicate.command("join").description("Request to join a syndicate (creates an E
6006
6405
  const hits = await searchSyndicateAcrossChains(subdomain);
6007
6406
  spinner.fail(`Syndicate "${subdomain}" not found on ${getNetwork()}`);
6008
6407
  if (hits.length === 0) {
6009
- console.error(chalk13.red(` Not found on any supported chain.`));
6408
+ console.error(chalk15.red(` Not found on any supported chain.`));
6010
6409
  } else if (hits.length === 1) {
6011
- console.error(chalk13.yellow(` Found on chain: ${chalk13.bold(hits[0].network)}`));
6012
- console.error(chalk13.dim(` Re-run: sherwood --chain ${hits[0].network} syndicate join --subdomain ${subdomain}`));
6410
+ console.error(chalk15.yellow(` Found on chain: ${chalk15.bold(hits[0].network)}`));
6411
+ console.error(chalk15.dim(` Re-run: sherwood --chain ${hits[0].network} syndicate join --subdomain ${subdomain}`));
6013
6412
  } else {
6014
6413
  const chains = hits.map((h) => h.network).join(", ");
6015
- console.error(chalk13.yellow(` Found on chains: ${chalk13.bold(chains)}`));
6016
- console.error(chalk13.dim(` Specify which chain to join with --chain <network>.`));
6414
+ console.error(chalk15.yellow(` Found on chains: ${chalk15.bold(chains)}`));
6415
+ console.error(chalk15.dim(` Specify which chain to join with --chain <network>.`));
6017
6416
  }
6018
6417
  process.exit(1);
6019
6418
  }
@@ -6026,17 +6425,17 @@ syndicate.command("join").description("Request to join a syndicate (creates an E
6026
6425
  try {
6027
6426
  const xmtp = await loadXmtp();
6028
6427
  await xmtp.getXmtpClient();
6029
- console.log(chalk13.dim(" XMTP identity ready"));
6428
+ console.log(chalk15.dim(" XMTP identity ready"));
6030
6429
  } catch {
6031
- console.warn(chalk13.yellow(" \u26A0 Could not initialize XMTP identity"));
6430
+ console.warn(chalk15.yellow(" \u26A0 Could not initialize XMTP identity"));
6032
6431
  }
6033
6432
  try {
6034
6433
  const cron = await loadCron();
6035
6434
  const cronResult = cron.registerSyndicateCrons(subdomain, isTestnet(), getNotifyTo());
6036
6435
  if (cronResult.isOpenClaw && cronResult.registered) {
6037
- console.log(chalk13.green(" \u2713 Participation crons registered"));
6436
+ console.log(chalk15.green(" \u2713 Participation crons registered"));
6038
6437
  } else if (!cronResult.isOpenClaw) {
6039
- console.log(chalk13.dim(" Tip: Set up a scheduled process to run `sherwood session check " + subdomain + "` periodically"));
6438
+ console.log(chalk15.dim(" Tip: Set up a scheduled process to run `sherwood session check " + subdomain + "` periodically"));
6040
6439
  }
6041
6440
  } catch {
6042
6441
  }
@@ -6049,14 +6448,14 @@ syndicate.command("join").description("Request to join a syndicate (creates an E
6049
6448
  );
6050
6449
  if (existingRequest) {
6051
6450
  spinner.succeed("You already have a pending join request for this syndicate");
6052
- console.log(chalk13.dim(` Attestation: ${existingRequest.uid}`));
6053
- console.log(chalk13.dim(` Submitted: ${new Date(existingRequest.time * 1e3).toLocaleString()}`));
6451
+ console.log(chalk15.dim(` Attestation: ${existingRequest.uid}`));
6452
+ console.log(chalk15.dim(` Submitted: ${new Date(existingRequest.time * 1e3).toLocaleString()}`));
6054
6453
  try {
6055
6454
  const xmtp = await loadXmtp();
6056
6455
  await xmtp.getXmtpClient();
6057
- console.log(chalk13.dim(" XMTP identity ready"));
6456
+ console.log(chalk15.dim(" XMTP identity ready"));
6058
6457
  } catch {
6059
- console.warn(chalk13.yellow(" \u26A0 Could not initialize XMTP identity"));
6458
+ console.warn(chalk15.yellow(" \u26A0 Could not initialize XMTP identity"));
6060
6459
  }
6061
6460
  return;
6062
6461
  }
@@ -6077,7 +6476,7 @@ syndicate.command("join").description("Request to join a syndicate (creates an E
6077
6476
  spinner.succeed("Join request created (XMTP identity ready)");
6078
6477
  } catch {
6079
6478
  spinner.succeed("Join request created");
6080
- console.warn(chalk13.yellow(" \u26A0 Could not initialize XMTP identity \u2014 creator may not be able to auto-add you to chat"));
6479
+ console.warn(chalk15.yellow(" \u26A0 Could not initialize XMTP identity \u2014 creator may not be able to auto-add you to chat"));
6081
6480
  }
6082
6481
  addSyndicate(getChain().id, { subdomain, vault: syndicate2.vault, role: "agent" });
6083
6482
  setPrimarySyndicate(getChain().id, subdomain);
@@ -6107,7 +6506,7 @@ syndicate.command("join").description("Request to join a syndicate (creates an E
6107
6506
  console.log();
6108
6507
  } catch (err) {
6109
6508
  spinner.fail("Join request failed");
6110
- console.error(chalk13.red(formatContractError(err)));
6509
+ console.error(chalk15.red(formatContractError(err)));
6111
6510
  process.exit(1);
6112
6511
  }
6113
6512
  });
@@ -6175,7 +6574,7 @@ syndicate.command("requests").description("View pending join requests for a synd
6175
6574
  console.log();
6176
6575
  } catch (err) {
6177
6576
  spinner.fail("Failed to load requests");
6178
- console.error(chalk13.red(formatContractError(err)));
6577
+ console.error(chalk15.red(formatContractError(err)));
6179
6578
  process.exit(1);
6180
6579
  }
6181
6580
  });
@@ -6250,8 +6649,8 @@ syndicate.command("approve").description("Approve an agent join request (registe
6250
6649
  });
6251
6650
  console.log(DIM6(` Added to chat: ${subdomain}`));
6252
6651
  } catch {
6253
- console.warn(chalk13.yellow(" \u26A0 Could not add agent to chat group"));
6254
- console.warn(chalk13.dim(` If no group exists, run: sherwood chat ${subdomain} init`));
6652
+ console.warn(chalk15.yellow(" \u26A0 Could not add agent to chat group"));
6653
+ console.warn(chalk15.dim(` If no group exists, run: sherwood chat ${subdomain} init`));
6255
6654
  }
6256
6655
  spinner.succeed("Agent approved and registered");
6257
6656
  console.log();
@@ -6264,7 +6663,7 @@ syndicate.command("approve").description("Approve an agent join request (registe
6264
6663
  SEP6();
6265
6664
  } catch (err) {
6266
6665
  spinner.fail("Approval failed");
6267
- console.error(chalk13.red(formatContractError(err)));
6666
+ console.error(chalk15.red(formatContractError(err)));
6268
6667
  process.exit(1);
6269
6668
  }
6270
6669
  });
@@ -6276,14 +6675,14 @@ syndicate.command("reject").description("Reject a join request by revoking its a
6276
6675
  console.log(DIM6(` ${getEasExplorerUrl(hash)}`));
6277
6676
  } catch (err) {
6278
6677
  spinner.fail("Rejection failed");
6279
- console.error(chalk13.red(formatContractError(err)));
6678
+ console.error(chalk15.red(formatContractError(err)));
6280
6679
  process.exit(1);
6281
6680
  }
6282
6681
  });
6283
6682
  syndicate.command("leave").description("Leave a syndicate \u2014 removes participation crons and session state").option("--subdomain <name>", "Syndicate subdomain to leave").action(async (opts) => {
6284
6683
  const subdomain = opts.subdomain || getPrimarySyndicate(getChain().id)?.subdomain;
6285
6684
  if (!subdomain) {
6286
- console.error(chalk13.red(" No syndicate configured. Pass --subdomain <name>."));
6685
+ console.error(chalk15.red(" No syndicate configured. Pass --subdomain <name>."));
6287
6686
  process.exit(1);
6288
6687
  }
6289
6688
  const spinner = ora8("Cleaning up...").start();
@@ -6303,13 +6702,13 @@ syndicate.command("leave").description("Leave a syndicate \u2014 removes partici
6303
6702
  }
6304
6703
  console.log(G6(" \u2713 Session state cleared"));
6305
6704
  console.log();
6306
- console.log(chalk13.dim(" Note: This does not remove you on-chain. To exit your position:"));
6307
- console.log(chalk13.dim(" sherwood vault balance \u2014 check your LP share balance"));
6308
- console.log(chalk13.dim(" Redeem shares via the vault contract or dashboard"));
6705
+ console.log(chalk15.dim(" Note: This does not remove you on-chain. To exit your position:"));
6706
+ console.log(chalk15.dim(" sherwood vault balance \u2014 check your LP share balance"));
6707
+ console.log(chalk15.dim(" Redeem shares via the vault contract or dashboard"));
6309
6708
  console.log();
6310
6709
  } catch (err) {
6311
6710
  spinner.fail("Leave failed");
6312
- console.error(chalk13.red(err instanceof Error ? err.message : String(err)));
6711
+ console.error(chalk15.red(err instanceof Error ? err.message : String(err)));
6313
6712
  process.exit(1);
6314
6713
  }
6315
6714
  });
@@ -6360,7 +6759,7 @@ syndicate.command("set-primary").description("Set the active syndicate for CLI c
6360
6759
  }
6361
6760
  }
6362
6761
  if (!target) {
6363
- console.error(chalk13.red(" Could not resolve syndicate. Pass --subdomain or --vault."));
6762
+ console.error(chalk15.red(" Could not resolve syndicate. Pass --subdomain or --vault."));
6364
6763
  process.exit(1);
6365
6764
  }
6366
6765
  setPrimarySyndicate(chainId, target);
@@ -6368,7 +6767,7 @@ syndicate.command("set-primary").description("Set the active syndicate for CLI c
6368
6767
  \u2713 Primary syndicate set to ${target}.sherwoodagent.eth
6369
6768
  `));
6370
6769
  } catch (err) {
6371
- console.error(chalk13.red(formatContractError(err)));
6770
+ console.error(chalk15.red(formatContractError(err)));
6372
6771
  process.exit(1);
6373
6772
  }
6374
6773
  });
@@ -6376,13 +6775,13 @@ var vaultCmd = program.command("vault");
6376
6775
  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)").action(async (opts) => {
6377
6776
  resolveVault(opts);
6378
6777
  const decimals = await getAssetDecimals();
6379
- const amount = parseUnits6(opts.amount, decimals);
6778
+ const amount = parseUnits7(opts.amount, decimals);
6380
6779
  try {
6381
6780
  if (!opts.useEth) {
6382
6781
  await preflightDeposit(amount);
6383
6782
  }
6384
6783
  } catch (err) {
6385
- console.error(chalk13.red(`
6784
+ console.error(chalk15.red(`
6386
6785
  \u2716 ${err instanceof Error ? err.message : String(err)}
6387
6786
  `));
6388
6787
  process.exit(1);
@@ -6397,10 +6796,10 @@ vaultCmd.command("deposit").description("Deposit into a vault").option("--vault
6397
6796
  hash = await deposit(amount);
6398
6797
  }
6399
6798
  spinner.succeed(`Deposited: ${hash}`);
6400
- console.log(chalk13.dim(` ${getExplorerUrl(hash)}`));
6799
+ console.log(chalk15.dim(` ${getExplorerUrl(hash)}`));
6401
6800
  } catch (err) {
6402
6801
  spinner.fail("Deposit failed");
6403
- console.error(chalk13.red(formatContractError(err)));
6802
+ console.error(chalk15.red(formatContractError(err)));
6404
6803
  process.exit(1);
6405
6804
  }
6406
6805
  });
@@ -6411,8 +6810,8 @@ vaultCmd.command("info").description("Display vault state").option("--vault <add
6411
6810
  const info = await getVaultInfo();
6412
6811
  spinner.stop();
6413
6812
  console.log();
6414
- console.log(chalk13.bold("Vault Info"));
6415
- console.log(chalk13.dim("\u2500".repeat(40)));
6813
+ console.log(chalk15.bold("Vault Info"));
6814
+ console.log(chalk15.dim("\u2500".repeat(40)));
6416
6815
  console.log(` Address: ${info.address}`);
6417
6816
  console.log(` Total Assets: ${info.totalAssets}`);
6418
6817
  console.log(` Agent Count: ${info.agentCount}`);
@@ -6421,7 +6820,7 @@ vaultCmd.command("info").description("Display vault state").option("--vault <add
6421
6820
  console.log();
6422
6821
  } catch (err) {
6423
6822
  spinner.fail("Failed to load vault info");
6424
- console.error(chalk13.red(formatContractError(err)));
6823
+ console.error(chalk15.red(formatContractError(err)));
6425
6824
  process.exit(1);
6426
6825
  }
6427
6826
  });
@@ -6432,15 +6831,15 @@ vaultCmd.command("balance").description("Show LP share balance and asset value")
6432
6831
  const balance = await getBalance(opts.address);
6433
6832
  spinner.stop();
6434
6833
  console.log();
6435
- console.log(chalk13.bold("LP Position"));
6436
- console.log(chalk13.dim("\u2500".repeat(40)));
6834
+ console.log(chalk15.bold("LP Position"));
6835
+ console.log(chalk15.dim("\u2500".repeat(40)));
6437
6836
  console.log(` Shares: ${balance.shares.toString()}`);
6438
6837
  console.log(` Asset Value: ${balance.assetsValue}`);
6439
6838
  console.log(` % of Vault: ${balance.percentOfVault}`);
6440
6839
  console.log();
6441
6840
  } catch (err) {
6442
6841
  spinner.fail("Failed to load balance");
6443
- console.error(chalk13.red(formatContractError(err)));
6842
+ console.error(chalk15.red(formatContractError(err)));
6444
6843
  process.exit(1);
6445
6844
  }
6446
6845
  });
@@ -6451,22 +6850,22 @@ vaultCmd.command("redeem").description("Redeem vault shares for the underlying a
6451
6850
  let shares;
6452
6851
  try {
6453
6852
  if (opts.shares) {
6454
- shares = parseUnits6(opts.shares, shareDecimals);
6853
+ shares = parseUnits7(opts.shares, shareDecimals);
6455
6854
  } else {
6456
6855
  shares = await getShareBalance();
6457
6856
  if (shares === 0n) {
6458
- console.error(chalk13.red("\n \u2716 No shares to redeem.\n"));
6857
+ console.error(chalk15.red("\n \u2716 No shares to redeem.\n"));
6459
6858
  process.exit(1);
6460
6859
  }
6461
6860
  }
6462
6861
  } catch (err) {
6463
- console.error(chalk13.red(`
6862
+ console.error(chalk15.red(`
6464
6863
  \u2716 ${err instanceof Error ? err.message : String(err)}
6465
6864
  `));
6466
6865
  process.exit(1);
6467
6866
  }
6468
6867
  if (opts.receiver && !isAddress6(opts.receiver)) {
6469
- console.error(chalk13.red(`
6868
+ console.error(chalk15.red(`
6470
6869
  \u2716 Invalid receiver address: ${opts.receiver}
6471
6870
  `));
6472
6871
  process.exit(1);
@@ -6474,7 +6873,7 @@ vaultCmd.command("redeem").description("Redeem vault shares for the underlying a
6474
6873
  try {
6475
6874
  await preflightRedeem(shares);
6476
6875
  } catch (err) {
6477
- console.error(chalk13.red(`
6876
+ console.error(chalk15.red(`
6478
6877
  \u2716 ${err instanceof Error ? err.message : String(err)}
6479
6878
  `));
6480
6879
  process.exit(1);
@@ -6487,11 +6886,11 @@ vaultCmd.command("redeem").description("Redeem vault shares for the underlying a
6487
6886
  opts.receiver
6488
6887
  );
6489
6888
  spinner.succeed(`Redeemed: ${hash}`);
6490
- console.log(chalk13.dim(` ${getExplorerUrl(hash)}`));
6889
+ console.log(chalk15.dim(` ${getExplorerUrl(hash)}`));
6491
6890
  console.log(` Assets received: ${formatUnits5(assetsOut, assetDecimals)}`);
6492
6891
  } catch (err) {
6493
6892
  spinner.fail("Redeem failed");
6494
- console.error(chalk13.red(formatContractError(err)));
6893
+ console.error(chalk15.red(formatContractError(err)));
6495
6894
  process.exit(1);
6496
6895
  }
6497
6896
  });
@@ -6509,17 +6908,17 @@ ${info.name} (${info.type})`);
6509
6908
  }
6510
6909
  });
6511
6910
  try {
6512
- const { registerChatCommands } = await import("./chat-MRTPUZ3X.js");
6911
+ const { registerChatCommands } = await import("./chat-TD6V5LFD.js");
6513
6912
  registerChatCommands(program);
6514
6913
  } catch {
6515
6914
  program.command("chat <name> [action] [actionArgs...]").description("Syndicate chat (XMTP) \u2014 requires @xmtp/cli").action(() => {
6516
- console.error(chalk13.red("XMTP CLI not available."));
6517
- console.error(chalk13.dim("Install with: npm install -g @xmtp/cli"));
6518
- console.error(chalk13.dim("Or reinstall: npm i -g @sherwoodagent/cli"));
6915
+ console.error(chalk15.red("XMTP CLI not available."));
6916
+ console.error(chalk15.dim("Install with: npm install -g @xmtp/cli"));
6917
+ console.error(chalk15.dim("Or reinstall: npm i -g @sherwoodagent/cli"));
6519
6918
  process.exit(1);
6520
6919
  });
6521
6920
  }
6522
- var { registerSessionCommands } = await import("./session-FPCPCVQX.js");
6921
+ var { registerSessionCommands } = await import("./session-IYT3N7MG.js");
6523
6922
  registerSessionCommands(program);
6524
6923
  registerVeniceCommands(program);
6525
6924
  registerAllowanceCommands(program);
@@ -6527,11 +6926,11 @@ registerIdentityCommands(program);
6527
6926
  registerProposalCommands(program);
6528
6927
  registerGovernorCommands(program);
6529
6928
  registerGuardianCommands(program);
6530
- var { registerResearchCommands } = await import("./research-QBKISW2M.js");
6929
+ var { registerResearchCommands } = await import("./research-WBZU4QNU.js");
6531
6930
  registerResearchCommands(program);
6532
- var { registerAgentCommands } = await import("./agent-4HKHLQEJ.js");
6931
+ var { registerAgentCommands } = await import("./agent-E5GHURKJ.js");
6533
6932
  registerAgentCommands(program);
6534
- var { registerTradeCommands } = await import("./trade-NO6CNWCA.js");
6933
+ var { registerTradeCommands } = await import("./trade-PTYLNJBU.js");
6535
6934
  registerTradeCommands(program);
6536
6935
  registerGridCommand(program);
6537
6936
  var configCmd = program.command("config");
@@ -6540,58 +6939,58 @@ configCmd.command("set").description("Save settings to ~/.sherwood/config.json (
6540
6939
  if (opts.privateKey) {
6541
6940
  setPrivateKey(opts.privateKey);
6542
6941
  const account = getAccount();
6543
- console.log(chalk13.green("Private key saved to ~/.sherwood/config.json"));
6544
- console.log(chalk13.dim(` Wallet: ${account.address}`));
6942
+ console.log(chalk15.green("Private key saved to ~/.sherwood/config.json"));
6943
+ console.log(chalk15.dim(` Wallet: ${account.address}`));
6545
6944
  saved = true;
6546
6945
  }
6547
6946
  if (opts.vault) {
6548
6947
  const chainId = getChain().id;
6549
6948
  setChainContract(chainId, "vault", opts.vault);
6550
- console.log(chalk13.green(`Vault saved to ~/.sherwood/config.json (chain ${chainId})`));
6551
- console.log(chalk13.dim(` Vault: ${opts.vault}`));
6949
+ console.log(chalk15.green(`Vault saved to ~/.sherwood/config.json (chain ${chainId})`));
6950
+ console.log(chalk15.dim(` Vault: ${opts.vault}`));
6552
6951
  saved = true;
6553
6952
  }
6554
6953
  if (opts.rpc) {
6555
6954
  const network = getNetwork();
6556
6955
  setConfigRpcUrl(network, opts.rpc);
6557
- console.log(chalk13.green(`RPC URL saved for ${network}`));
6558
- console.log(chalk13.dim(` RPC: ${opts.rpc}`));
6956
+ console.log(chalk15.green(`RPC URL saved for ${network}`));
6957
+ console.log(chalk15.dim(` RPC: ${opts.rpc}`));
6559
6958
  saved = true;
6560
6959
  }
6561
6960
  if (opts.notifyTo) {
6562
6961
  setNotifyTo(opts.notifyTo);
6563
- console.log(chalk13.green("Notify destination saved to ~/.sherwood/config.json"));
6564
- console.log(chalk13.dim(` Notify to: ${opts.notifyTo}`));
6962
+ console.log(chalk15.green("Notify destination saved to ~/.sherwood/config.json"));
6963
+ console.log(chalk15.dim(` Notify to: ${opts.notifyTo}`));
6565
6964
  saved = true;
6566
6965
  }
6567
6966
  if (opts.uniswapApiKey) {
6568
6967
  setUniswapApiKey(opts.uniswapApiKey);
6569
- console.log(chalk13.green("Uniswap API key saved to ~/.sherwood/config.json"));
6968
+ console.log(chalk15.green("Uniswap API key saved to ~/.sherwood/config.json"));
6570
6969
  saved = true;
6571
6970
  }
6572
6971
  if (opts.veniceApiKey) {
6573
6972
  setVeniceApiKey(opts.veniceApiKey);
6574
- console.log(chalk13.green("Venice API key saved to ~/.sherwood/config.json"));
6973
+ console.log(chalk15.green("Venice API key saved to ~/.sherwood/config.json"));
6575
6974
  saved = true;
6576
6975
  }
6577
6976
  if (opts.anthropicApiKey) {
6578
6977
  setAnthropicApiKey(opts.anthropicApiKey);
6579
- console.log(chalk13.green("Anthropic API key saved to ~/.sherwood/config.json"));
6978
+ console.log(chalk15.green("Anthropic API key saved to ~/.sherwood/config.json"));
6580
6979
  saved = true;
6581
6980
  }
6582
6981
  if (opts.xmtpGroup) {
6583
6982
  const parts = opts.xmtpGroup.split(":");
6584
6983
  if (parts.length !== 2 || !parts[0] || !parts[1]) {
6585
- console.log(chalk13.red("Format: --xmtp-group <subdomain>:<groupId>"));
6984
+ console.log(chalk15.red("Format: --xmtp-group <subdomain>:<groupId>"));
6586
6985
  process.exit(1);
6587
6986
  }
6588
6987
  cacheGroupId(parts[0], parts[1]);
6589
- console.log(chalk13.green(`XMTP group ID cached for ${parts[0]}`));
6590
- console.log(chalk13.dim(` Group ID: ${parts[1]}`));
6988
+ console.log(chalk15.green(`XMTP group ID cached for ${parts[0]}`));
6989
+ console.log(chalk15.dim(` Group ID: ${parts[1]}`));
6591
6990
  saved = true;
6592
6991
  }
6593
6992
  if (!saved) {
6594
- console.log(chalk13.red("Provide at least one of: --private-key, --vault, --rpc, --notify-to, --uniswap-api-key, --venice-api-key, --anthropic-api-key, --xmtp-group"));
6993
+ console.log(chalk15.red("Provide at least one of: --private-key, --vault, --rpc, --notify-to, --uniswap-api-key, --venice-api-key, --anthropic-api-key, --xmtp-group"));
6595
6994
  process.exit(1);
6596
6995
  }
6597
6996
  });
@@ -6602,25 +7001,25 @@ configCmd.command("show").description("Display current config for the active net
6602
7001
  const config = loadConfig();
6603
7002
  const customRpc = config.rpc?.[network];
6604
7003
  console.log();
6605
- console.log(chalk13.bold(`Sherwood Config`));
6606
- console.log(chalk13.dim("\u2500".repeat(50)));
6607
- console.log(` Network: ${chalk13.cyan(network)} (chain ${chainId})`);
6608
- console.log(` RPC: ${customRpc ? chalk13.green(customRpc) : chalk13.dim("default")}`);
6609
- console.log(` Wallet: ${config.privateKey ? chalk13.green("configured") : chalk13.dim("not set")}`);
6610
- console.log(` Agent ID: ${config.agentId ?? chalk13.dim("not set")}`);
6611
- console.log(` Vault: ${contracts.vault ?? chalk13.dim("not set")}`);
6612
- console.log(` Uniswap: ${getUniswapApiKey() ? chalk13.green("API key configured") : chalk13.dim("not set")}`);
6613
- console.log(` Venice: ${getVeniceApiKey() ? chalk13.green("API key configured") : chalk13.dim("not set")}`);
7004
+ console.log(chalk15.bold(`Sherwood Config`));
7005
+ console.log(chalk15.dim("\u2500".repeat(50)));
7006
+ console.log(` Network: ${chalk15.cyan(network)} (chain ${chainId})`);
7007
+ console.log(` RPC: ${customRpc ? chalk15.green(customRpc) : chalk15.dim("default")}`);
7008
+ console.log(` Wallet: ${config.privateKey ? chalk15.green("configured") : chalk15.dim("not set")}`);
7009
+ console.log(` Agent ID: ${config.agentId ?? chalk15.dim("not set")}`);
7010
+ console.log(` Vault: ${contracts.vault ?? chalk15.dim("not set")}`);
7011
+ console.log(` Uniswap: ${getUniswapApiKey() ? chalk15.green("API key configured") : chalk15.dim("not set")}`);
7012
+ console.log(` Venice: ${getVeniceApiKey() ? chalk15.green("API key configured") : chalk15.dim("not set")}`);
6614
7013
  const groupEntries = Object.entries(config.groupCache || {}).filter(([, v]) => v);
6615
7014
  if (groupEntries.length > 0) {
6616
7015
  console.log();
6617
- console.log(chalk13.bold(" XMTP Groups"));
7016
+ console.log(chalk15.bold(" XMTP Groups"));
6618
7017
  for (const [sub, gid] of groupEntries) {
6619
- console.log(` ${sub}: ${chalk13.cyan(gid)}`);
7018
+ console.log(` ${sub}: ${chalk15.cyan(gid)}`);
6620
7019
  }
6621
7020
  }
6622
7021
  console.log();
6623
- console.log(chalk13.dim(" Config file: ~/.sherwood/config.json"));
7022
+ console.log(chalk15.dim(" Config file: ~/.sherwood/config.json"));
6624
7023
  console.log();
6625
7024
  });
6626
7025
  program.parse();