@sherwoodagent/cli 0.25.3 → 0.29.0

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 (57) hide show
  1. package/dist/addresses-CQLJSZGN.js +35 -0
  2. package/dist/agent-QIQABFLV.js +7087 -0
  3. package/dist/agent-QIQABFLV.js.map +1 -0
  4. package/dist/{chat-DRKUZCOY.js → chat-N6LSZUSC.js} +45 -12
  5. package/dist/chat-N6LSZUSC.js.map +1 -0
  6. package/dist/{chunk-KEUEO4UE.js → chunk-2H6IGGKN.js} +1 -1
  7. package/dist/chunk-2H6IGGKN.js.map +1 -0
  8. package/dist/{chunk-H55III3L.js → chunk-3EMDYEAD.js} +7 -5
  9. package/dist/{chunk-H55III3L.js.map → chunk-3EMDYEAD.js.map} +1 -1
  10. package/dist/{chunk-6DWQIKGN.js → chunk-I3UVF2GD.js} +7 -5
  11. package/dist/{chunk-6DWQIKGN.js.map → chunk-I3UVF2GD.js.map} +1 -1
  12. package/dist/{chunk-4WG64CRK.js → chunk-IIBOFECO.js} +7 -5
  13. package/dist/{chunk-4WG64CRK.js.map → chunk-IIBOFECO.js.map} +1 -1
  14. package/dist/{chunk-ICUQY7TY.js → chunk-PQ5ZX6ZT.js} +39 -343
  15. package/dist/chunk-PQ5ZX6ZT.js.map +1 -0
  16. package/dist/{chunk-66VFSLPS.js → chunk-QGEIK4H5.js} +2 -2
  17. package/dist/chunk-T5BRUFWV.js +142 -0
  18. package/dist/chunk-T5BRUFWV.js.map +1 -0
  19. package/dist/chunk-WQOTLKVP.js +456 -0
  20. package/dist/chunk-WQOTLKVP.js.map +1 -0
  21. package/dist/{chunk-SBVHGUQJ.js → chunk-WRG7GAIA.js} +2 -2
  22. package/dist/{chunk-Y7LUFGIS.js → chunk-YRYPGJ66.js} +9 -7
  23. package/dist/{chunk-Y7LUFGIS.js.map → chunk-YRYPGJ66.js.map} +1 -1
  24. package/dist/{chunk-GWIW6DDG.js → chunk-ZPYN5ZAI.js} +53 -1
  25. package/dist/chunk-ZPYN5ZAI.js.map +1 -0
  26. package/dist/{client-CWQFYZ5Z.js → client-HBMSTSKK.js} +3 -3
  27. package/dist/{eas-652I6ULB.js → eas-D3KSAGWT.js} +6 -5
  28. package/dist/{governor-CY3GXU44.js → governor-3MYMDBRF.js} +6 -5
  29. package/dist/index.js +267 -220
  30. package/dist/index.js.map +1 -1
  31. package/dist/{ipfs-22YLNQ2C.js → ipfs-IGXLLJCF.js} +2 -2
  32. package/dist/{network-QEMP3DSP.js → network-X6GM7ROG.js} +6 -2
  33. package/dist/{price-FOCSYKGJ.js → price-DXNFNTV6.js} +8 -6
  34. package/dist/{price-FOCSYKGJ.js.map → price-DXNFNTV6.js.map} +1 -1
  35. package/dist/{research-LJKYDBCL.js → research-H3I4LALI.js} +8 -8
  36. package/dist/{research-ZX7T2ZIJ.js → research-NCESMYXK.js} +4 -4
  37. package/dist/research-NCESMYXK.js.map +1 -0
  38. package/dist/{session-7HKFQ7JZ.js → session-5JUUZYIL.js} +12 -10
  39. package/dist/{session-7HKFQ7JZ.js.map → session-5JUUZYIL.js.map} +1 -1
  40. package/dist/{trade-4SOHHD5R.js → trade-XDE6YCNY.js} +16 -14
  41. package/dist/{trade-4SOHHD5R.js.map → trade-XDE6YCNY.js.map} +1 -1
  42. package/dist/{xmtp-K555NJPU.js → xmtp-XTJ7HDVG.js} +6 -5
  43. package/dist/{xmtp-K555NJPU.js.map → xmtp-XTJ7HDVG.js.map} +1 -1
  44. package/package.json +1 -1
  45. package/dist/chat-DRKUZCOY.js.map +0 -1
  46. package/dist/chunk-GWIW6DDG.js.map +0 -1
  47. package/dist/chunk-ICUQY7TY.js.map +0 -1
  48. package/dist/chunk-KEUEO4UE.js.map +0 -1
  49. /package/dist/{client-CWQFYZ5Z.js.map → addresses-CQLJSZGN.js.map} +0 -0
  50. /package/dist/{chunk-66VFSLPS.js.map → chunk-QGEIK4H5.js.map} +0 -0
  51. /package/dist/{chunk-SBVHGUQJ.js.map → chunk-WRG7GAIA.js.map} +0 -0
  52. /package/dist/{eas-652I6ULB.js.map → client-HBMSTSKK.js.map} +0 -0
  53. /package/dist/{governor-CY3GXU44.js.map → eas-D3KSAGWT.js.map} +0 -0
  54. /package/dist/{ipfs-22YLNQ2C.js.map → governor-3MYMDBRF.js.map} +0 -0
  55. /package/dist/{network-QEMP3DSP.js.map → ipfs-IGXLLJCF.js.map} +0 -0
  56. /package/dist/{research-ZX7T2ZIJ.js.map → network-X6GM7ROG.js.map} +0 -0
  57. /package/dist/{research-LJKYDBCL.js.map → research-H3I4LALI.js.map} +0 -0
package/dist/index.js CHANGED
@@ -1,4 +1,32 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ UniswapProvider,
4
+ applySlippage,
5
+ chatCompletion,
6
+ checkApiKeyValid,
7
+ encodeSwapPath,
8
+ getMultiHopQuote,
9
+ getQuote,
10
+ listModels,
11
+ provisionApiKey
12
+ } from "./chunk-IIBOFECO.js";
13
+ import {
14
+ createApproval,
15
+ createJoinRequest,
16
+ getEasScanUrl,
17
+ parseReferrer,
18
+ queryApprovals,
19
+ queryJoinRequests,
20
+ revokeAttestation,
21
+ stripReferrerPrefix
22
+ } from "./chunk-I3UVF2GD.js";
23
+ import {
24
+ createSyndicate,
25
+ getActiveSyndicates,
26
+ getSyndicate,
27
+ subdomainExists,
28
+ updateMetadata
29
+ } from "./chunk-T5BRUFWV.js";
2
30
  import {
3
31
  approveDepositor,
4
32
  deposit,
@@ -21,18 +49,7 @@ import {
21
49
  resolveVaultSyndicate,
22
50
  setTextRecord,
23
51
  setVaultAddress
24
- } from "./chunk-Y7LUFGIS.js";
25
- import {
26
- UniswapProvider,
27
- applySlippage,
28
- chatCompletion,
29
- checkApiKeyValid,
30
- encodeSwapPath,
31
- getMultiHopQuote,
32
- getQuote,
33
- listModels,
34
- provisionApiKey
35
- } from "./chunk-4WG64CRK.js";
52
+ } from "./chunk-YRYPGJ66.js";
36
53
  import {
37
54
  PROPOSAL_STATE,
38
55
  PROPOSAL_STATES,
@@ -64,42 +81,33 @@ import {
64
81
  setVotingPeriod,
65
82
  settleProposal,
66
83
  vote
67
- } from "./chunk-H55III3L.js";
84
+ } from "./chunk-3EMDYEAD.js";
68
85
  import {
69
86
  fetchMetadata,
70
87
  uploadMetadata
71
- } from "./chunk-KEUEO4UE.js";
88
+ } from "./chunk-2H6IGGKN.js";
72
89
  import {
73
- createApproval,
74
- createJoinRequest,
75
- getEasScanUrl,
76
- parseReferrer,
77
- queryApprovals,
78
- queryJoinRequests,
79
- revokeAttestation,
80
- stripReferrerPrefix
81
- } from "./chunk-6DWQIKGN.js";
90
+ BASE_STRATEGY_ABI,
91
+ ERC20_ABI,
92
+ PORTFOLIO_STRATEGY_ABI,
93
+ SWAP_ROUTER_ABI,
94
+ SWAP_ROUTER_EXACT_INPUT_SINGLE_ABI,
95
+ SYNDICATE_VAULT_ABI,
96
+ VENICE_STAKING_ABI
97
+ } from "./chunk-PQ5ZX6ZT.js";
82
98
  import {
83
99
  AERODROME,
84
100
  AGENT_REGISTRY,
85
- BASE_STRATEGY_ABI,
86
101
  CHAINLINK,
87
102
  EAS_SCHEMAS,
88
- ERC20_ABI,
89
103
  MOONWELL,
90
- PORTFOLIO_STRATEGY_ABI,
91
104
  SHERWOOD,
92
105
  STRATEGY_TEMPLATES,
93
- SWAP_ROUTER_ABI,
94
- SWAP_ROUTER_EXACT_INPUT_SINGLE_ABI,
95
- SYNDICATE_FACTORY_ABI,
96
- SYNDICATE_VAULT_ABI,
97
106
  SYNTHRA,
98
107
  TOKENS,
99
108
  UNISWAP,
100
- VENICE,
101
- VENICE_STAKING_ABI
102
- } from "./chunk-ICUQY7TY.js";
109
+ VENICE
110
+ } from "./chunk-WQOTLKVP.js";
103
111
  import {
104
112
  formatContractError,
105
113
  getAccount,
@@ -107,7 +115,7 @@ import {
107
115
  sendTxWithRetry,
108
116
  waitForReceipt,
109
117
  writeContractWithRetry
110
- } from "./chunk-SBVHGUQJ.js";
118
+ } from "./chunk-WRG7GAIA.js";
111
119
  import {
112
120
  CHAIN_REGISTRY,
113
121
  VALID_NETWORKS,
@@ -117,12 +125,13 @@ import {
117
125
  getRpcUrl,
118
126
  isTestnet,
119
127
  setNetwork
120
- } from "./chunk-GWIW6DDG.js";
128
+ } from "./chunk-ZPYN5ZAI.js";
121
129
  import {
122
130
  addSyndicate,
123
131
  cacheGroupId,
124
132
  cacheSwapRoute,
125
133
  getAgentId,
134
+ getCachedGroupId,
126
135
  getCachedSwapRoute,
127
136
  getChainContracts,
128
137
  getNotifyTo,
@@ -145,7 +154,7 @@ import {
145
154
  import { config as loadDotenv } from "dotenv";
146
155
  import { createRequire } from "module";
147
156
  import { Command, Option } from "commander";
148
- import { parseUnits as parseUnits5, formatUnits as formatUnits5, isAddress as isAddress5 } from "viem";
157
+ import { parseUnits as parseUnits4, formatUnits as formatUnits4, isAddress as isAddress5 } from "viem";
149
158
  import chalk8 from "chalk";
150
159
  import ora7 from "ora";
151
160
  import { input, confirm, select } from "@inquirer/prompts";
@@ -185,7 +194,7 @@ var MoonwellProvider = class {
185
194
  };
186
195
 
187
196
  // src/commands/strategy-template.ts
188
- import { parseUnits, formatUnits, isAddress, erc20Abi, encodeAbiParameters as encodeAbiParameters7, decodeAbiParameters } from "viem";
197
+ import { parseUnits, formatUnits, isAddress, erc20Abi, encodeAbiParameters as encodeAbiParameters8, decodeAbiParameters } from "viem";
189
198
  import chalk from "chalk";
190
199
  import ora from "ora";
191
200
  import { writeFileSync, mkdirSync } from "fs";
@@ -558,6 +567,56 @@ function buildSettleCalls6(clone) {
558
567
  ];
559
568
  }
560
569
 
570
+ // src/strategies/hyperliquid-perp-template.ts
571
+ import { encodeAbiParameters as encodeAbiParameters7, encodeFunctionData as encodeFunctionData7 } from "viem";
572
+ function buildInitData7(asset, depositAmount, minReturnAmount, perpAssetIndex, leverage, maxPositionSize, maxTradesPerDay) {
573
+ return encodeAbiParameters7(
574
+ [
575
+ { type: "address" },
576
+ { type: "uint256" },
577
+ { type: "uint256" },
578
+ { type: "uint32" },
579
+ { type: "uint32" },
580
+ { type: "uint256" },
581
+ { type: "uint32" }
582
+ ],
583
+ [asset, depositAmount, minReturnAmount, perpAssetIndex, leverage, maxPositionSize, maxTradesPerDay]
584
+ );
585
+ }
586
+ function buildExecuteCalls7(clone, asset, amount) {
587
+ return [
588
+ {
589
+ target: asset,
590
+ data: encodeFunctionData7({
591
+ abi: ERC20_ABI,
592
+ functionName: "approve",
593
+ args: [clone, amount]
594
+ }),
595
+ value: 0n
596
+ },
597
+ {
598
+ target: clone,
599
+ data: encodeFunctionData7({
600
+ abi: BASE_STRATEGY_ABI,
601
+ functionName: "execute"
602
+ }),
603
+ value: 0n
604
+ }
605
+ ];
606
+ }
607
+ function buildSettleCalls7(clone) {
608
+ return [
609
+ {
610
+ target: clone,
611
+ data: encodeFunctionData7({
612
+ abi: BASE_STRATEGY_ABI,
613
+ functionName: "settle"
614
+ }),
615
+ value: 0n
616
+ }
617
+ ];
618
+ }
619
+
561
620
  // src/commands/strategy-template.ts
562
621
  import { concat as concat2, numberToHex } from "viem";
563
622
  var ZERO = "0x0000000000000000000000000000000000000000";
@@ -574,14 +633,14 @@ function encodeV3Path(tokens, fees) {
574
633
  }
575
634
  function buildSwapExtraData(network, tokenIn, tokenOut, feeTier, hop) {
576
635
  if (network === "robinhood-testnet") {
577
- return encodeAbiParameters7([{ type: "uint24" }], [feeTier]);
636
+ return encodeAbiParameters8([{ type: "uint24" }], [feeTier]);
578
637
  }
579
638
  if (hop) {
580
639
  const path = encodeV3Path([tokenIn, hop.via, tokenOut], [hop.feeIn, hop.feeOut]);
581
- const encoded2 = encodeAbiParameters7([{ type: "bytes" }], [path]);
640
+ const encoded2 = encodeAbiParameters8([{ type: "bytes" }], [path]);
582
641
  return `0x01${encoded2.slice(2)}`;
583
642
  }
584
- const encoded = encodeAbiParameters7([{ type: "uint24" }], [feeTier]);
643
+ const encoded = encodeAbiParameters8([{ type: "uint24" }], [feeTier]);
585
644
  return `0x00${encoded.slice(2)}`;
586
645
  }
587
646
  async function detectSwapRoute(asset, token, preferredFeeTier) {
@@ -714,6 +773,12 @@ var TEMPLATES = [
714
773
  key: "portfolio",
715
774
  description: "Weighted portfolio of tokens (stock tokens, crypto) with rebalancing",
716
775
  addressKey: "PORTFOLIO"
776
+ },
777
+ {
778
+ name: "Hyperliquid Perp",
779
+ key: "hyperliquid-perp",
780
+ description: "Leveraged perp trading on Hyperliquid via HyperEVM precompiles",
781
+ addressKey: "HYPERLIQUID_PERP"
717
782
  }
718
783
  ];
719
784
  function resolveTemplate(key) {
@@ -969,6 +1034,26 @@ async function buildInitDataForTemplate(templateKey, opts, vault) {
969
1034
  assetAmount: totalAmount
970
1035
  };
971
1036
  }
1037
+ if (templateKey === "hyperliquid-perp") {
1038
+ if (!opts.amount) {
1039
+ console.error(chalk.red("--amount is required for hyperliquid-perp template"));
1040
+ process.exit(1);
1041
+ }
1042
+ const token = opts.token || "USDC";
1043
+ const asset = resolveToken(token);
1044
+ const decimals = token.toUpperCase() === "USDC" ? 6 : 18;
1045
+ const depositAmount = parseUnits(opts.amount, decimals);
1046
+ const minReturn = parseUnits(opts.minReturn || opts.amount, decimals);
1047
+ const leverage = Number(opts.leverage || "10");
1048
+ const assetIndex = Number(opts.assetIndex || "0");
1049
+ const maxPosition = parseUnits(opts.maxPosition || "100000", decimals);
1050
+ const maxTradesDay = Number(opts.maxTradesPerDay || "50");
1051
+ return {
1052
+ initData: buildInitData7(asset, depositAmount, minReturn, assetIndex, leverage, maxPosition, maxTradesDay),
1053
+ asset,
1054
+ assetAmount: depositAmount
1055
+ };
1056
+ }
972
1057
  throw new Error(`No init builder for template: ${templateKey}`);
973
1058
  }
974
1059
  function buildCallsForTemplate(templateKey, clone, asset, assetAmount, extraApprovals) {
@@ -1010,6 +1095,12 @@ function buildCallsForTemplate(templateKey, clone, asset, assetAmount, extraAppr
1010
1095
  settleCalls: buildSettleCalls6(clone)
1011
1096
  };
1012
1097
  }
1098
+ if (templateKey === "hyperliquid-perp") {
1099
+ return {
1100
+ executeCalls: buildExecuteCalls7(clone, asset, assetAmount),
1101
+ settleCalls: buildSettleCalls7(clone)
1102
+ };
1103
+ }
1013
1104
  throw new Error(`No call builder for template: ${templateKey}`);
1014
1105
  }
1015
1106
  function resolveSwapAdapter() {
@@ -1104,7 +1195,7 @@ function registerStrategyTemplateCommands(strategy2) {
1104
1195
  console.log(chalk.dim("Full proposal: sherwood strategy propose <template> --vault <addr> ..."));
1105
1196
  console.log();
1106
1197
  });
1107
- 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").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)").action(async (templateKey, opts) => {
1198
+ 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) => {
1108
1199
  const vault = opts.vault;
1109
1200
  if (!isAddress(vault)) {
1110
1201
  console.error(chalk.red("Invalid vault address"));
@@ -1152,7 +1243,7 @@ function registerStrategyTemplateCommands(strategy2) {
1152
1243
  console.log(chalk.dim("Use this address in your proposal batch calls."));
1153
1244
  console.log();
1154
1245
  });
1155
- 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").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)").action(async (templateKey, opts) => {
1246
+ 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) => {
1156
1247
  const clone = opts.clone;
1157
1248
  const vault = opts.vault;
1158
1249
  if (!isAddress(clone)) {
@@ -1208,7 +1299,7 @@ function registerStrategyTemplateCommands(strategy2) {
1208
1299
  console.log(` Proposer: ${chalk.green(getAccount().address)}`);
1209
1300
  console.log();
1210
1301
  });
1211
- 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").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)").action(async (templateKey, opts) => {
1302
+ 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) => {
1212
1303
  const vault = opts.vault;
1213
1304
  if (!isAddress(vault)) {
1214
1305
  console.error(chalk.red("Invalid vault address"));
@@ -1299,9 +1390,9 @@ function registerStrategyTemplateCommands(strategy2) {
1299
1390
  console.error(chalk.red("Missing --name, --performance-fee, or --duration. Use --write-calls to skip proposal submission."));
1300
1391
  process.exit(1);
1301
1392
  }
1302
- const { propose: propose2 } = await import("./governor-CY3GXU44.js");
1303
- const { pinJSON } = await import("./ipfs-22YLNQ2C.js");
1304
- const { parseDuration: parseDuration2 } = await import("./governor-CY3GXU44.js");
1393
+ const { propose: propose2 } = await import("./governor-3MYMDBRF.js");
1394
+ const { pinJSON } = await import("./ipfs-IGXLLJCF.js");
1395
+ const { parseDuration: parseDuration2 } = await import("./governor-3MYMDBRF.js");
1305
1396
  const performanceFeeBps = BigInt(opts.performanceFee);
1306
1397
  if (performanceFeeBps < 0n || performanceFeeBps > 10000n) {
1307
1398
  console.error(chalk.red("--performance-fee must be 0-10000 (basis points)"));
@@ -1409,7 +1500,7 @@ function registerStrategyTemplateCommands(strategy2) {
1409
1500
  let prices = [];
1410
1501
  let priceSource = null;
1411
1502
  try {
1412
- const { getTokenPricesInAsset } = await import("./price-FOCSYKGJ.js");
1503
+ const { getTokenPricesInAsset } = await import("./price-DXNFNTV6.js");
1413
1504
  prices = await getTokenPricesInAsset({
1414
1505
  tokens: allocations.map((a, i) => ({
1415
1506
  token: a.token,
@@ -1658,7 +1749,7 @@ function registerStrategyTemplateCommands(strategy2) {
1658
1749
  });
1659
1750
  const updateSpinner = ora("Updating target weights...").start();
1660
1751
  try {
1661
- const innerData = encodeAbiParameters7(
1752
+ const innerData = encodeAbiParameters8(
1662
1753
  [{ type: "uint256[]" }, { type: "uint256" }, { type: "bytes[]" }],
1663
1754
  [newWeightsBps.map((w) => BigInt(w)), BigInt(maxSlip), swapData]
1664
1755
  );
@@ -1735,124 +1826,6 @@ function registerStrategyTemplateCommands(strategy2) {
1735
1826
  });
1736
1827
  }
1737
1828
 
1738
- // src/lib/factory.ts
1739
- import { decodeEventLog } from "viem";
1740
- function getFactoryAddress() {
1741
- return SHERWOOD().FACTORY;
1742
- }
1743
- async function createSyndicate(params) {
1744
- const client = getPublicClient();
1745
- const hash = await writeContractWithRetry({
1746
- account: getAccount(),
1747
- chain: getChain(),
1748
- address: getFactoryAddress(),
1749
- abi: SYNDICATE_FACTORY_ABI,
1750
- functionName: "createSyndicate",
1751
- args: [
1752
- params.creatorAgentId,
1753
- {
1754
- metadataURI: params.metadataURI,
1755
- asset: params.asset,
1756
- name: params.name,
1757
- symbol: params.symbol,
1758
- openDeposits: params.openDeposits,
1759
- subdomain: params.subdomain
1760
- }
1761
- ]
1762
- });
1763
- const receipt = await waitForReceipt(hash);
1764
- for (const log of receipt.logs) {
1765
- try {
1766
- const event = decodeEventLog({
1767
- abi: SYNDICATE_FACTORY_ABI,
1768
- data: log.data,
1769
- topics: log.topics
1770
- });
1771
- if (event.eventName === "SyndicateCreated") {
1772
- const args = event.args;
1773
- return {
1774
- hash,
1775
- syndicateId: args.id,
1776
- vault: args.vault
1777
- };
1778
- }
1779
- } catch {
1780
- }
1781
- }
1782
- const count = await getSyndicateCount();
1783
- const info = await getSyndicate(count);
1784
- return {
1785
- hash,
1786
- syndicateId: count,
1787
- vault: info.vault
1788
- };
1789
- }
1790
- async function subdomainExists(subdomain) {
1791
- const client = getPublicClient();
1792
- const id = await client.readContract({
1793
- address: getFactoryAddress(),
1794
- abi: SYNDICATE_FACTORY_ABI,
1795
- functionName: "subdomainToSyndicate",
1796
- args: [subdomain]
1797
- });
1798
- return id > 0n ? id : null;
1799
- }
1800
- async function getSyndicate(id) {
1801
- const client = getPublicClient();
1802
- const result = await client.readContract({
1803
- address: getFactoryAddress(),
1804
- abi: SYNDICATE_FACTORY_ABI,
1805
- functionName: "syndicates",
1806
- args: [id]
1807
- });
1808
- return {
1809
- id: result[0],
1810
- vault: result[1],
1811
- creator: result[2],
1812
- metadataURI: result[3],
1813
- createdAt: result[4],
1814
- active: result[5],
1815
- subdomain: result[6]
1816
- };
1817
- }
1818
- async function getSyndicateCount() {
1819
- const client = getPublicClient();
1820
- return client.readContract({
1821
- address: getFactoryAddress(),
1822
- abi: SYNDICATE_FACTORY_ABI,
1823
- functionName: "syndicateCount"
1824
- });
1825
- }
1826
- async function getActiveSyndicates() {
1827
- const client = getPublicClient();
1828
- const result = await client.readContract({
1829
- address: getFactoryAddress(),
1830
- abi: SYNDICATE_FACTORY_ABI,
1831
- functionName: "getAllActiveSyndicates"
1832
- });
1833
- return result.map((s) => ({
1834
- id: s.id,
1835
- vault: s.vault,
1836
- creator: s.creator,
1837
- metadataURI: s.metadataURI,
1838
- createdAt: s.createdAt,
1839
- active: s.active,
1840
- subdomain: s.subdomain
1841
- }));
1842
- }
1843
- async function updateMetadata(syndicateId, metadataURI) {
1844
- const hash = await writeContractWithRetry({
1845
- account: getAccount(),
1846
- chain: getChain(),
1847
- address: getFactoryAddress(),
1848
- abi: SYNDICATE_FACTORY_ABI,
1849
- functionName: "updateMetadata",
1850
- args: [syndicateId, metadataURI]
1851
- });
1852
- await waitForReceipt(hash);
1853
- return hash;
1854
- }
1855
-
1856
1829
  // src/lib/subgraph.ts
1857
1830
  function getSubgraphUrl() {
1858
1831
  const url = process.env.SUBGRAPH_URL;
@@ -1920,7 +1893,7 @@ async function getActiveSyndicates2(creator) {
1920
1893
  }
1921
1894
 
1922
1895
  // src/commands/venice.ts
1923
- import { formatUnits as formatUnits3, isAddress as isAddress2 } from "viem";
1896
+ import { formatUnits as formatUnits2, isAddress as isAddress2 } from "viem";
1924
1897
  import chalk2 from "chalk";
1925
1898
  import ora2 from "ora";
1926
1899
  import { readFileSync } from "fs";
@@ -1943,7 +1916,7 @@ function registerVeniceCommands(program2) {
1943
1916
  console.log(chalk2.yellow(" Use the VeniceInferenceStrategy via a proposal to distribute sVVV to agents."));
1944
1917
  process.exit(1);
1945
1918
  }
1946
- checkSpinner.succeed(`sVVV balance: ${formatUnits3(sVvvBalance, 18)}`);
1919
+ checkSpinner.succeed(`sVVV balance: ${formatUnits2(sVvvBalance, 18)}`);
1947
1920
  } catch (err) {
1948
1921
  checkSpinner.fail("Failed to check sVVV balance");
1949
1922
  console.error(chalk2.red(formatContractError(err)));
@@ -1956,7 +1929,7 @@ function registerVeniceCommands(program2) {
1956
1929
  console.log(chalk2.dim(` Key: ${apiKey.slice(0, 8)}...${apiKey.slice(-4)}`));
1957
1930
  console.log(chalk2.dim(" Saved to ~/.sherwood/config.json"));
1958
1931
  try {
1959
- const { createVeniceProvisionAttestation, getEasScanUrl: getEasScanUrl2 } = await import("./eas-652I6ULB.js");
1932
+ const { createVeniceProvisionAttestation, getEasScanUrl: getEasScanUrl2 } = await import("./eas-D3KSAGWT.js");
1960
1933
  const { uid } = await createVeniceProvisionAttestation(account.address);
1961
1934
  if (uid !== "0x0000000000000000000000000000000000000000000000000000000000000000") {
1962
1935
  console.log(chalk2.dim(` Attested: ${getEasScanUrl2(uid)}`));
@@ -2028,17 +2001,17 @@ function registerVeniceCommands(program2) {
2028
2001
  console.log(chalk2.bold("Venice Inference Status"));
2029
2002
  console.log(chalk2.dim("\u2500".repeat(50)));
2030
2003
  console.log(chalk2.bold("\n Vault"));
2031
- console.log(` Profit available: ${formatUnits3(profit, assetDecimals)} ${assetSymbol}`);
2032
- console.log(` VVV (unstaked): ${formatUnits3(vaultVvvBalance, 18)}`);
2004
+ console.log(` Profit available: ${formatUnits2(profit, assetDecimals)} ${assetSymbol}`);
2005
+ console.log(` VVV (unstaked): ${formatUnits2(vaultVvvBalance, 18)}`);
2033
2006
  console.log(chalk2.bold("\n Agent sVVV Balances"));
2034
2007
  for (const { agent, balance } of agentBalances) {
2035
2008
  const isMe = agent.toLowerCase() === account.address.toLowerCase();
2036
2009
  const label = isMe ? chalk2.green(`${agent} (you)`) : agent;
2037
- console.log(` ${label}: ${formatUnits3(balance, 18)} sVVV`);
2010
+ console.log(` ${label}: ${formatUnits2(balance, 18)} sVVV`);
2038
2011
  }
2039
2012
  console.log(chalk2.bold("\n Your Wallet"));
2040
- console.log(` sVVV: ${formatUnits3(mySvvv, 18)}`);
2041
- console.log(` Pending rewards: ${formatUnits3(myPending, 18)} VVV`);
2013
+ console.log(` sVVV: ${formatUnits2(mySvvv, 18)}`);
2014
+ console.log(` Pending rewards: ${formatUnits2(myPending, 18)} VVV`);
2042
2015
  console.log(chalk2.bold("\n Venice API"));
2043
2016
  console.log(` Key: ${apiKey ? `${apiKey.slice(0, 8)}...${apiKey.slice(-4)}` : chalk2.dim("not provisioned")}`);
2044
2017
  console.log(` Status: ${apiKeyValid ? chalk2.green("valid") : chalk2.red("invalid/missing")}`);
@@ -2107,10 +2080,10 @@ ${opts.prompt}`;
2107
2080
  console.log(chalk2.dim(`Model: ${result.model} | Tokens: ${result.usage.promptTokens} in, ${result.usage.completionTokens} out, ${result.usage.totalTokens} total`));
2108
2081
  }
2109
2082
  try {
2110
- const { createVeniceInferenceAttestation, getEasScanUrl: getEasScanUrl2 } = await import("./eas-652I6ULB.js");
2083
+ const { createVeniceInferenceAttestation, getEasScanUrl: getEasScanUrl2 } = await import("./eas-D3KSAGWT.js");
2111
2084
  const { keccak256, toHex, isAddress: isAddr } = await import("viem");
2112
2085
  const { getChainContracts: getChainContracts2 } = await import("./config-YXZKPSZB.js");
2113
- const { getChain: getActiveChain } = await import("./network-QEMP3DSP.js");
2086
+ const { getChain: getActiveChain } = await import("./network-X6GM7ROG.js");
2114
2087
  const vaultRecipient = opts.vault && isAddr(opts.vault) ? opts.vault : getChainContracts2(getActiveChain().id).vault;
2115
2088
  const promptHash = keccak256(toHex(userContent)).slice(0, 18);
2116
2089
  const { uid } = await createVeniceInferenceAttestation(
@@ -2134,21 +2107,21 @@ ${opts.prompt}`;
2134
2107
  }
2135
2108
 
2136
2109
  // src/commands/allowance.ts
2137
- import { parseUnits as parseUnits4, formatUnits as formatUnits4, isAddress as isAddress3 } from "viem";
2110
+ import { parseUnits as parseUnits3, formatUnits as formatUnits3, isAddress as isAddress3 } from "viem";
2138
2111
  import chalk3 from "chalk";
2139
2112
  import ora3 from "ora";
2140
2113
 
2141
2114
  // src/strategies/allowance-disburse.ts
2142
- import { encodeFunctionData as encodeFunctionData7, parseUnits as parseUnits3 } from "viem";
2115
+ import { encodeFunctionData as encodeFunctionData8, parseUnits as parseUnits2 } from "viem";
2143
2116
  function buildDisburseBatch(config, vaultAddress, agents, assetAddress, assetDecimals, minUsdc, swapPath) {
2144
- const assetAmount = parseUnits3(config.amount, assetDecimals);
2117
+ const assetAmount = parseUnits2(config.amount, assetDecimals);
2145
2118
  const isUsdc = assetAddress.toLowerCase() === TOKENS().USDC.toLowerCase();
2146
2119
  const isWeth = assetAddress.toLowerCase() === TOKENS().WETH.toLowerCase();
2147
2120
  const calls = [];
2148
2121
  if (!isUsdc) {
2149
2122
  calls.push({
2150
2123
  target: assetAddress,
2151
- data: encodeFunctionData7({
2124
+ data: encodeFunctionData8({
2152
2125
  abi: ERC20_ABI,
2153
2126
  functionName: "approve",
2154
2127
  args: [UNISWAP().SWAP_ROUTER, assetAmount]
@@ -2158,7 +2131,7 @@ function buildDisburseBatch(config, vaultAddress, agents, assetAddress, assetDec
2158
2131
  if (isWeth) {
2159
2132
  calls.push({
2160
2133
  target: UNISWAP().SWAP_ROUTER,
2161
- data: encodeFunctionData7({
2134
+ data: encodeFunctionData8({
2162
2135
  abi: SWAP_ROUTER_EXACT_INPUT_SINGLE_ABI,
2163
2136
  functionName: "exactInputSingle",
2164
2137
  args: [
@@ -2178,7 +2151,7 @@ function buildDisburseBatch(config, vaultAddress, agents, assetAddress, assetDec
2178
2151
  } else {
2179
2152
  calls.push({
2180
2153
  target: UNISWAP().SWAP_ROUTER,
2181
- data: encodeFunctionData7({
2154
+ data: encodeFunctionData8({
2182
2155
  abi: SWAP_ROUTER_ABI,
2183
2156
  functionName: "exactInput",
2184
2157
  args: [
@@ -2198,7 +2171,7 @@ function buildDisburseBatch(config, vaultAddress, agents, assetAddress, assetDec
2198
2171
  for (const agent of agents) {
2199
2172
  calls.push({
2200
2173
  target: TOKENS().USDC,
2201
- data: encodeFunctionData7({
2174
+ data: encodeFunctionData8({
2202
2175
  abi: ERC20_ABI,
2203
2176
  functionName: "transfer",
2204
2177
  args: [agent, perAgent]
@@ -2254,7 +2227,7 @@ function registerAllowanceCommands(program2) {
2254
2227
  console.error(chalk3.red("No agents registered in vault. Register agents first."));
2255
2228
  process.exit(1);
2256
2229
  }
2257
- const requestedAmount = parseUnits4(opts.amount, assetDecimals);
2230
+ const requestedAmount = parseUnits3(opts.amount, assetDecimals);
2258
2231
  const profit = assetBalance > totalDeposited ? assetBalance - totalDeposited : 0n;
2259
2232
  const isUsdc = assetAddress.toLowerCase() === TOKENS().USDC.toLowerCase();
2260
2233
  const isWeth = assetAddress.toLowerCase() === TOKENS().WETH.toLowerCase();
@@ -2263,9 +2236,9 @@ function registerAllowanceCommands(program2) {
2263
2236
  console.log(chalk3.dim("\u2500".repeat(40)));
2264
2237
  console.log(` Asset: ${assetSymbol} (${assetDecimals} decimals)`);
2265
2238
  console.log(` Amount: ${opts.amount} ${assetSymbol}`);
2266
- console.log(` Vault balance: ${formatUnits4(assetBalance, assetDecimals)} ${assetSymbol}`);
2267
- console.log(` Deposited: ${formatUnits4(totalDeposited, assetDecimals)} ${assetSymbol}`);
2268
- console.log(` Profit: ${formatUnits4(profit, assetDecimals)} ${assetSymbol}`);
2239
+ console.log(` Vault balance: ${formatUnits3(assetBalance, assetDecimals)} ${assetSymbol}`);
2240
+ console.log(` Deposited: ${formatUnits3(totalDeposited, assetDecimals)} ${assetSymbol}`);
2241
+ console.log(` Profit: ${formatUnits3(profit, assetDecimals)} ${assetSymbol}`);
2269
2242
  console.log(` Agents: ${agents.length} (USDC will be split equally)`);
2270
2243
  if (!isUsdc) {
2271
2244
  console.log(` Routing: ${isWeth ? `WETH \u2192 USDC (fee ${fee})` : `${assetSymbol} \u2192 WETH \u2192 USDC (fee ${fee})`}`);
@@ -2274,7 +2247,7 @@ function registerAllowanceCommands(program2) {
2274
2247
  console.log(` Vault: ${vaultAddress}`);
2275
2248
  console.log();
2276
2249
  if (requestedAmount > profit) {
2277
- console.warn(chalk3.yellow(` Warning: amount (${opts.amount}) exceeds available profit (${formatUnits4(profit, assetDecimals)})`));
2250
+ console.warn(chalk3.yellow(` Warning: amount (${opts.amount}) exceeds available profit (${formatUnits3(profit, assetDecimals)})`));
2278
2251
  console.warn(chalk3.yellow(" This will use deposited capital, not just profits."));
2279
2252
  console.log();
2280
2253
  }
@@ -2308,7 +2281,7 @@ function registerAllowanceCommands(program2) {
2308
2281
  }
2309
2282
  minUsdc = applySlippage(amountOut, slippageBps);
2310
2283
  quoteSpinner.succeed(
2311
- `Quote: ${formatUnits4(amountOut, 6)} USDC (min: ${formatUnits4(minUsdc, 6)}, per agent: ${formatUnits4(minUsdc / BigInt(agents.length), 6)})`
2284
+ `Quote: ${formatUnits3(amountOut, 6)} USDC (min: ${formatUnits3(minUsdc, 6)}, per agent: ${formatUnits3(minUsdc / BigInt(agents.length), 6)})`
2312
2285
  );
2313
2286
  } catch (err) {
2314
2287
  quoteSpinner.fail("Failed to fetch quote");
@@ -2318,7 +2291,7 @@ function registerAllowanceCommands(program2) {
2318
2291
  }
2319
2292
  const perAgent = minUsdc / BigInt(agents.length);
2320
2293
  if (isUsdc) {
2321
- console.log(chalk3.dim(` Per agent: ${formatUnits4(perAgent, 6)} USDC`));
2294
+ console.log(chalk3.dim(` Per agent: ${formatUnits3(perAgent, 6)} USDC`));
2322
2295
  console.log();
2323
2296
  }
2324
2297
  const config = {
@@ -2385,14 +2358,14 @@ function registerAllowanceCommands(program2) {
2385
2358
  console.log(chalk3.dim("\u2500".repeat(50)));
2386
2359
  console.log(chalk3.bold("\n Vault"));
2387
2360
  console.log(` Asset: ${assetSymbol}`);
2388
- console.log(` Balance: ${formatUnits4(assetBalance, assetDecimals)} ${assetSymbol}`);
2389
- console.log(` Deposited: ${formatUnits4(totalDeposited, assetDecimals)} ${assetSymbol}`);
2390
- console.log(` Profit: ${formatUnits4(profit, assetDecimals)} ${assetSymbol}`);
2361
+ console.log(` Balance: ${formatUnits3(assetBalance, assetDecimals)} ${assetSymbol}`);
2362
+ console.log(` Deposited: ${formatUnits3(totalDeposited, assetDecimals)} ${assetSymbol}`);
2363
+ console.log(` Profit: ${formatUnits3(profit, assetDecimals)} ${assetSymbol}`);
2391
2364
  console.log(chalk3.bold("\n Agent USDC Balances"));
2392
2365
  for (const { agent, balance } of agentBalances) {
2393
2366
  const isMe = agent.toLowerCase() === account.address.toLowerCase();
2394
2367
  const label = isMe ? chalk3.green(`${agent} (you)`) : agent;
2395
- console.log(` ${label}: ${formatUnits4(balance, 6)} USDC`);
2368
+ console.log(` ${label}: ${formatUnits3(balance, 6)} USDC`);
2396
2369
  }
2397
2370
  console.log();
2398
2371
  } catch (err) {
@@ -2561,7 +2534,7 @@ function registerIdentityCommands(program2) {
2561
2534
  }
2562
2535
 
2563
2536
  // src/commands/proposal.ts
2564
- import { isAddress as isAddress4, encodeFunctionData as encodeFunctionData9 } from "viem";
2537
+ import { isAddress as isAddress4, encodeFunctionData as encodeFunctionData10 } from "viem";
2565
2538
  import chalk6 from "chalk";
2566
2539
  import ora5 from "ora";
2567
2540
  import { readFileSync as readFileSync2 } from "fs";
@@ -2597,7 +2570,7 @@ function parseBigIntArg(value, name) {
2597
2570
  }
2598
2571
 
2599
2572
  // src/lib/simulate.ts
2600
- import { decodeFunctionData, encodeFunctionData as encodeFunctionData8 } from "viem";
2573
+ import { decodeFunctionData, encodeFunctionData as encodeFunctionData9 } from "viem";
2601
2574
  import chalk5 from "chalk";
2602
2575
  var G = chalk5.green;
2603
2576
  var W = chalk5.white;
@@ -3116,7 +3089,7 @@ async function simulateViaApi(vault, calls) {
3116
3089
  async function simulateViaEthCall(vault, calls) {
3117
3090
  const governor = getGovernorAddress();
3118
3091
  const client = getPublicClient();
3119
- const input2 = encodeFunctionData8({
3092
+ const input2 = encodeFunctionData9({
3120
3093
  abi: SYNDICATE_VAULT_ABI,
3121
3094
  functionName: "executeGovernorBatch",
3122
3095
  args: [calls.map((c) => ({ target: c.target, data: c.data, value: c.value }))]
@@ -3239,8 +3212,8 @@ function printSimulationResult(result, callType) {
3239
3212
  }
3240
3213
  async function sendSimulationAlert(subdomain, proposalId, vault, execResult, settleResult) {
3241
3214
  try {
3242
- const xmtp = await import("./xmtp-K555NJPU.js");
3243
- const { getAccount: getAccount2 } = await import("./client-CWQFYZ5Z.js");
3215
+ const xmtp = await import("./xmtp-XTJ7HDVG.js");
3216
+ const { getAccount: getAccount2 } = await import("./client-HBMSTSKK.js");
3244
3217
  const group = await xmtp.getGroup("", subdomain);
3245
3218
  const allRisks = [...execResult.risks, ...settleResult?.risks ?? []];
3246
3219
  const criticals = allRisks.filter((r) => r.level === "critical");
@@ -3748,7 +3721,7 @@ function registerProposalCommands(program2) {
3748
3721
  process.exit(1);
3749
3722
  }
3750
3723
  const asset = await getAssetAddress();
3751
- const noopCalldata = encodeFunctionData9({
3724
+ const noopCalldata = encodeFunctionData10({
3752
3725
  abi: ERC20_ABI,
3753
3726
  functionName: "balanceOf",
3754
3727
  args: [vault]
@@ -4056,7 +4029,7 @@ try {
4056
4029
  var require2 = createRequire(import.meta.url);
4057
4030
  var { version: CLI_VERSION } = require2("../package.json");
4058
4031
  async function loadXmtp() {
4059
- return import("./xmtp-K555NJPU.js");
4032
+ return import("./xmtp-XTJ7HDVG.js");
4060
4033
  }
4061
4034
  async function loadCron() {
4062
4035
  return import("./cron-EOULYO3R.js");
@@ -4393,10 +4366,16 @@ syndicate.command("list").description("List active syndicates (queries subgraph,
4393
4366
  process.exit(1);
4394
4367
  }
4395
4368
  });
4396
- syndicate.command("info").description("Display syndicate details by ID").argument("<id>", "Syndicate ID").action(async (idStr) => {
4369
+ syndicate.command("info").description("Display syndicate details by ID or subdomain").argument("<id>", "Syndicate ID or subdomain name").action(async (idStr) => {
4397
4370
  const spinner = ora7("Loading syndicate info...").start();
4398
4371
  try {
4399
- const id = BigInt(idStr);
4372
+ let id;
4373
+ if (/^\d+$/.test(idStr)) {
4374
+ id = BigInt(idStr);
4375
+ } else {
4376
+ const resolved = await resolveSyndicate(idStr);
4377
+ id = resolved.id;
4378
+ }
4400
4379
  const info = await getSyndicate(id);
4401
4380
  spinner.stop();
4402
4381
  if (!info.vault || info.vault === "0x0000000000000000000000000000000000000000") {
@@ -4417,6 +4396,12 @@ syndicate.command("info").description("Display syndicate details by ID").argumen
4417
4396
  if (info.metadataURI) {
4418
4397
  console.log(` Metadata: ${chalk8.dim(info.metadataURI)}`);
4419
4398
  }
4399
+ if (info.subdomain) {
4400
+ const xmtpGroupId = getCachedGroupId(info.subdomain);
4401
+ if (xmtpGroupId) {
4402
+ console.log(` XMTP Group: ${chalk8.cyan(xmtpGroupId)}`);
4403
+ }
4404
+ }
4420
4405
  setVaultAddress(info.vault);
4421
4406
  const vaultInfo = await getVaultInfo();
4422
4407
  console.log();
@@ -4496,7 +4481,7 @@ syndicate.command("remove-depositor").description("Remove an address from the de
4496
4481
  process.exit(1);
4497
4482
  }
4498
4483
  });
4499
- syndicate.command("add").description("Register an agent on a syndicate vault (creator only)").option("--vault <address>", "Vault address (default: from config)").requiredOption("--agent-id <id>", "Agent's ERC-8004 identity token ID").requiredOption("--wallet <address>", "Agent wallet address").action(async (opts) => {
4484
+ syndicate.command("add").description("Register an agent on a syndicate vault (creator only)").option("--vault <address>", "Vault address (default: from config)").option("--agent-id <id>", "Agent's ERC-8004 identity token ID (resolved from wallet if omitted)").requiredOption("--wallet <address>", "Agent wallet address").action(async (opts) => {
4500
4485
  const spinner = ora7("Verifying creator...").start();
4501
4486
  try {
4502
4487
  resolveVault(opts);
@@ -4508,11 +4493,52 @@ syndicate.command("add").description("Register an agent on a syndicate vault (cr
4508
4493
  process.exit(1);
4509
4494
  }
4510
4495
  const agentWallet = validateAddress(opts.wallet, "wallet");
4496
+ let agentId;
4497
+ if (opts.agentId) {
4498
+ agentId = BigInt(opts.agentId);
4499
+ } else {
4500
+ const { AGENT_REGISTRY: AGENT_REGISTRY2 } = await import("./addresses-CQLJSZGN.js");
4501
+ const registry = AGENT_REGISTRY2().IDENTITY_REGISTRY;
4502
+ if (registry === "0x0000000000000000000000000000000000000000") {
4503
+ agentId = 0n;
4504
+ } else {
4505
+ spinner.text = "Looking up ERC-8004 identity from wallet...";
4506
+ const client = getPublicClient();
4507
+ const balance = await client.readContract({
4508
+ address: registry,
4509
+ abi: [{
4510
+ name: "balanceOf",
4511
+ type: "function",
4512
+ stateMutability: "view",
4513
+ inputs: [{ name: "owner", type: "address" }],
4514
+ outputs: [{ name: "", type: "uint256" }]
4515
+ }],
4516
+ functionName: "balanceOf",
4517
+ args: [agentWallet]
4518
+ });
4519
+ if (balance === 0n) {
4520
+ spinner.fail("Agent wallet does not own an ERC-8004 identity NFT");
4521
+ console.error(chalk8.dim(" Mint one first: sherwood identity mint --name <name>"));
4522
+ process.exit(1);
4523
+ }
4524
+ const tokenId = await client.readContract({
4525
+ address: registry,
4526
+ abi: [{
4527
+ name: "tokenOfOwnerByIndex",
4528
+ type: "function",
4529
+ stateMutability: "view",
4530
+ inputs: [{ name: "owner", type: "address" }, { name: "index", type: "uint256" }],
4531
+ outputs: [{ name: "", type: "uint256" }]
4532
+ }],
4533
+ functionName: "tokenOfOwnerByIndex",
4534
+ args: [agentWallet, 0n]
4535
+ });
4536
+ agentId = tokenId;
4537
+ console.log(chalk8.dim(` Resolved agent ID: #${agentId}`));
4538
+ }
4539
+ }
4511
4540
  spinner.text = "Registering agent...";
4512
- const hash = await registerAgent(
4513
- BigInt(opts.agentId),
4514
- agentWallet
4515
- );
4541
+ const hash = await registerAgent(agentId, agentWallet);
4516
4542
  spinner.succeed(`Agent registered: ${hash}`);
4517
4543
  console.log(chalk8.dim(` ${getExplorerUrl(hash)}`));
4518
4544
  try {
@@ -4522,7 +4548,7 @@ syndicate.command("add").description("Register an agent on a syndicate vault (cr
4522
4548
  await xmtp.addMember(group, opts.wallet);
4523
4549
  await xmtp.sendEnvelope(group, {
4524
4550
  type: "AGENT_REGISTERED",
4525
- agent: { erc8004Id: Number(opts.agentId), address: opts.wallet },
4551
+ agent: { erc8004Id: Number(agentId), address: opts.wallet },
4526
4552
  syndicate: subdomain,
4527
4553
  timestamp: Math.floor(Date.now() / 1e3)
4528
4554
  });
@@ -4948,7 +4974,7 @@ var vaultCmd = program.command("vault");
4948
4974
  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) => {
4949
4975
  resolveVault(opts);
4950
4976
  const decimals = await getAssetDecimals();
4951
- const amount = parseUnits5(opts.amount, decimals);
4977
+ const amount = parseUnits4(opts.amount, decimals);
4952
4978
  try {
4953
4979
  if (!opts.useEth) {
4954
4980
  await preflightDeposit(amount);
@@ -5023,7 +5049,7 @@ vaultCmd.command("redeem").description("Redeem vault shares for the underlying a
5023
5049
  let shares;
5024
5050
  try {
5025
5051
  if (opts.shares) {
5026
- shares = parseUnits5(opts.shares, shareDecimals);
5052
+ shares = parseUnits4(opts.shares, shareDecimals);
5027
5053
  } else {
5028
5054
  shares = await getShareBalance();
5029
5055
  if (shares === 0n) {
@@ -5051,7 +5077,7 @@ vaultCmd.command("redeem").description("Redeem vault shares for the underlying a
5051
5077
  `));
5052
5078
  process.exit(1);
5053
5079
  }
5054
- const sharesDisplay = formatUnits5(shares, shareDecimals);
5080
+ const sharesDisplay = formatUnits4(shares, shareDecimals);
5055
5081
  const spinner = ora7(`Redeeming ${sharesDisplay} shares...`).start();
5056
5082
  try {
5057
5083
  const { hash, assetsOut } = await redeem(
@@ -5060,7 +5086,7 @@ vaultCmd.command("redeem").description("Redeem vault shares for the underlying a
5060
5086
  );
5061
5087
  spinner.succeed(`Redeemed: ${hash}`);
5062
5088
  console.log(chalk8.dim(` ${getExplorerUrl(hash)}`));
5063
- console.log(` Assets received: ${formatUnits5(assetsOut, assetDecimals)}`);
5089
+ console.log(` Assets received: ${formatUnits4(assetsOut, assetDecimals)}`);
5064
5090
  } catch (err) {
5065
5091
  spinner.fail("Redeem failed");
5066
5092
  console.error(chalk8.red(formatContractError(err)));
@@ -5070,7 +5096,7 @@ vaultCmd.command("redeem").description("Redeem vault shares for the underlying a
5070
5096
  var strategy = program.command("strategy").description("Strategy templates \u2014 list, clone, propose");
5071
5097
  registerStrategyTemplateCommands(strategy);
5072
5098
  program.command("providers").description("List available DeFi providers").action(async () => {
5073
- const { MessariProvider, NansenProvider } = await import("./research-ZX7T2ZIJ.js");
5099
+ const { MessariProvider, NansenProvider } = await import("./research-NCESMYXK.js");
5074
5100
  const providers = [new MoonwellProvider(), new UniswapProvider(), new MessariProvider(), new NansenProvider()];
5075
5101
  for (const p of providers) {
5076
5102
  const info = p.info();
@@ -5081,7 +5107,7 @@ ${info.name} (${info.type})`);
5081
5107
  }
5082
5108
  });
5083
5109
  try {
5084
- const { registerChatCommands } = await import("./chat-DRKUZCOY.js");
5110
+ const { registerChatCommands } = await import("./chat-N6LSZUSC.js");
5085
5111
  registerChatCommands(program);
5086
5112
  } catch {
5087
5113
  program.command("chat <name> [action] [actionArgs...]").description("Syndicate chat (XMTP) \u2014 requires @xmtp/cli").action(() => {
@@ -5091,19 +5117,21 @@ try {
5091
5117
  process.exit(1);
5092
5118
  });
5093
5119
  }
5094
- var { registerSessionCommands } = await import("./session-7HKFQ7JZ.js");
5120
+ var { registerSessionCommands } = await import("./session-5JUUZYIL.js");
5095
5121
  registerSessionCommands(program);
5096
5122
  registerVeniceCommands(program);
5097
5123
  registerAllowanceCommands(program);
5098
5124
  registerIdentityCommands(program);
5099
5125
  registerProposalCommands(program);
5100
5126
  registerGovernorCommands(program);
5101
- var { registerResearchCommands } = await import("./research-LJKYDBCL.js");
5127
+ var { registerResearchCommands } = await import("./research-H3I4LALI.js");
5102
5128
  registerResearchCommands(program);
5103
- var { registerTradeCommands } = await import("./trade-4SOHHD5R.js");
5129
+ var { registerAgentCommands } = await import("./agent-QIQABFLV.js");
5130
+ registerAgentCommands(program);
5131
+ var { registerTradeCommands } = await import("./trade-XDE6YCNY.js");
5104
5132
  registerTradeCommands(program);
5105
5133
  var configCmd = program.command("config");
5106
- configCmd.command("set").description("Save settings to ~/.sherwood/config.json (persists across sessions)").option("--private-key <key>", "Wallet private key (0x-prefixed)").option("--vault <address>", "Default SyndicateVault address").option("--rpc <url>", "Custom RPC URL for the active --chain network").option("--notify-to <id>", "Destination for cron summaries (Telegram chat ID, phone, etc.)").option("--uniswap-api-key <key>", "Uniswap Trading API key (from developers.uniswap.org)").option("--venice-api-key <key>", "Venice AI inference API key").action((opts) => {
5134
+ configCmd.command("set").description("Save settings to ~/.sherwood/config.json (persists across sessions)").option("--private-key <key>", "Wallet private key (0x-prefixed)").option("--vault <address>", "Default SyndicateVault address").option("--rpc <url>", "Custom RPC URL for the active --chain network").option("--notify-to <id>", "Destination for cron summaries (Telegram chat ID, phone, etc.)").option("--uniswap-api-key <key>", "Uniswap Trading API key (from developers.uniswap.org)").option("--venice-api-key <key>", "Venice AI inference API key").option("--xmtp-group <subdomain:groupId>", "Cache an XMTP group ID for a syndicate (e.g. my-fund:abc123)").action((opts) => {
5107
5135
  let saved = false;
5108
5136
  if (opts.privateKey) {
5109
5137
  setPrivateKey(opts.privateKey);
@@ -5142,8 +5170,19 @@ configCmd.command("set").description("Save settings to ~/.sherwood/config.json (
5142
5170
  console.log(chalk8.green("Venice API key saved to ~/.sherwood/config.json"));
5143
5171
  saved = true;
5144
5172
  }
5173
+ if (opts.xmtpGroup) {
5174
+ const parts = opts.xmtpGroup.split(":");
5175
+ if (parts.length !== 2 || !parts[0] || !parts[1]) {
5176
+ console.log(chalk8.red("Format: --xmtp-group <subdomain>:<groupId>"));
5177
+ process.exit(1);
5178
+ }
5179
+ cacheGroupId(parts[0], parts[1]);
5180
+ console.log(chalk8.green(`XMTP group ID cached for ${parts[0]}`));
5181
+ console.log(chalk8.dim(` Group ID: ${parts[1]}`));
5182
+ saved = true;
5183
+ }
5145
5184
  if (!saved) {
5146
- console.log(chalk8.red("Provide at least one of: --private-key, --vault, --rpc, --notify-to, --uniswap-api-key, --venice-api-key"));
5185
+ console.log(chalk8.red("Provide at least one of: --private-key, --vault, --rpc, --notify-to, --uniswap-api-key, --venice-api-key, --xmtp-group"));
5147
5186
  process.exit(1);
5148
5187
  }
5149
5188
  });
@@ -5163,6 +5202,14 @@ configCmd.command("show").description("Display current config for the active net
5163
5202
  console.log(` Vault: ${contracts.vault ?? chalk8.dim("not set")}`);
5164
5203
  console.log(` Uniswap: ${getUniswapApiKey() ? chalk8.green("API key configured") : chalk8.dim("not set")}`);
5165
5204
  console.log(` Venice: ${getVeniceApiKey() ? chalk8.green("API key configured") : chalk8.dim("not set")}`);
5205
+ const groupEntries = Object.entries(config.groupCache || {}).filter(([, v]) => v);
5206
+ if (groupEntries.length > 0) {
5207
+ console.log();
5208
+ console.log(chalk8.bold(" XMTP Groups"));
5209
+ for (const [sub, gid] of groupEntries) {
5210
+ console.log(` ${sub}: ${chalk8.cyan(gid)}`);
5211
+ }
5212
+ }
5166
5213
  console.log();
5167
5214
  console.log(chalk8.dim(" Config file: ~/.sherwood/config.json"));
5168
5215
  console.log();