@sherwoodagent/cli 0.89.3 → 0.90.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 (70) hide show
  1. package/dist/{agent-QU2OSWS4.js → agent-DLLONQ76.js} +9 -9
  2. package/dist/agent-DLLONQ76.js.map +1 -0
  3. package/dist/{chat-EVRY5BV3.js → chat-FSAHNEIY.js} +12 -12
  4. package/dist/{chunk-WIUPOQNS.js → chunk-25VV4W6X.js} +2 -2
  5. package/dist/{chunk-DQZJULNP.js → chunk-43TG4FOX.js} +4 -4
  6. package/dist/{chunk-KPTKX226.js → chunk-DCQELFSU.js} +4 -4
  7. package/dist/{chunk-LIW6K4OJ.js → chunk-JDTTJDGP.js} +2 -2
  8. package/dist/{chunk-3R57ETXQ.js → chunk-LSY4GYJ2.js} +2 -2
  9. package/dist/{chunk-WAF3JU5J.js → chunk-OFGBQAUM.js} +6 -6
  10. package/dist/{chunk-UCULHATO.js → chunk-PTWYREL2.js} +52 -13
  11. package/dist/chunk-PTWYREL2.js.map +1 -0
  12. package/dist/{chunk-5XMQQ4LX.js → chunk-QBOBGQQV.js} +4 -4
  13. package/dist/{chunk-NJNK6GTJ.js → chunk-QQJAM24N.js} +6 -6
  14. package/dist/{chunk-2SIUEMPV.js → chunk-RITIB5RY.js} +4 -4
  15. package/dist/{chunk-KXUA5BEH.js → chunk-UKWKI4UC.js} +4 -4
  16. package/dist/{chunk-6KXITNND.js → chunk-WKOTF5H6.js} +12 -12
  17. package/dist/{chunk-74QYNLJE.js → chunk-WTPIXSGL.js} +3 -3
  18. package/dist/{chunk-QUAVAJWE.js → chunk-XJR2YQK3.js} +1 -15
  19. package/dist/chunk-XJR2YQK3.js.map +1 -0
  20. package/dist/{chunk-I7NYU4JB.js → chunk-YJEBZJ7Y.js} +3 -3
  21. package/dist/{client-3BFK7TNL.js → client-IFQ2TMCY.js} +4 -4
  22. package/dist/{config-UZ2GIXAO.js → config-WIHIVOGZ.js} +2 -6
  23. package/dist/{eas-YTAAJSLU.js → eas-KVH644YY.js} +6 -6
  24. package/dist/{governor-53PNPDCZ.js → governor-L7FTXIAC.js} +6 -6
  25. package/dist/{identity-462SMK5H.js → identity-ZMHBCTOK.js} +8 -8
  26. package/dist/index.js +316 -228
  27. package/dist/index.js.map +1 -1
  28. package/dist/{launchpad-LHMBN4TV.js → launchpad-CEUSWTXH.js} +6 -6
  29. package/dist/{lighter-preflight-TSLSSYWI.js → lighter-preflight-YOVDIULH.js} +8 -8
  30. package/dist/{network-EZ5X2BF7.js → network-XQLQ4MSH.js} +3 -3
  31. package/dist/{price-QKOARHS4.js → price-GZEQNKAF.js} +7 -7
  32. package/dist/{providers-22A42FKP.js → providers-3PSOZI6R.js} +5 -5
  33. package/dist/{research-3L3BTHWY.js → research-C4W7C5S6.js} +9 -9
  34. package/dist/{session-27X337LQ.js → session-LIMD5AG5.js} +12 -12
  35. package/dist/{trade-6Q7VCDEA.js → trade-U5TZIZHF.js} +18 -18
  36. package/dist/{vault-TQWUWBSG.js → vault-SV7UAREO.js} +9 -9
  37. package/dist/{xmtp-EOMKXRTB.js → xmtp-TOPGDWX3.js} +6 -6
  38. package/package.json +1 -2
  39. package/dist/agent-QU2OSWS4.js.map +0 -1
  40. package/dist/chunk-QUAVAJWE.js.map +0 -1
  41. package/dist/chunk-UCULHATO.js.map +0 -1
  42. /package/dist/{chat-EVRY5BV3.js.map → chat-FSAHNEIY.js.map} +0 -0
  43. /package/dist/{chunk-WIUPOQNS.js.map → chunk-25VV4W6X.js.map} +0 -0
  44. /package/dist/{chunk-DQZJULNP.js.map → chunk-43TG4FOX.js.map} +0 -0
  45. /package/dist/{chunk-KPTKX226.js.map → chunk-DCQELFSU.js.map} +0 -0
  46. /package/dist/{chunk-LIW6K4OJ.js.map → chunk-JDTTJDGP.js.map} +0 -0
  47. /package/dist/{chunk-3R57ETXQ.js.map → chunk-LSY4GYJ2.js.map} +0 -0
  48. /package/dist/{chunk-WAF3JU5J.js.map → chunk-OFGBQAUM.js.map} +0 -0
  49. /package/dist/{chunk-5XMQQ4LX.js.map → chunk-QBOBGQQV.js.map} +0 -0
  50. /package/dist/{chunk-NJNK6GTJ.js.map → chunk-QQJAM24N.js.map} +0 -0
  51. /package/dist/{chunk-2SIUEMPV.js.map → chunk-RITIB5RY.js.map} +0 -0
  52. /package/dist/{chunk-KXUA5BEH.js.map → chunk-UKWKI4UC.js.map} +0 -0
  53. /package/dist/{chunk-6KXITNND.js.map → chunk-WKOTF5H6.js.map} +0 -0
  54. /package/dist/{chunk-74QYNLJE.js.map → chunk-WTPIXSGL.js.map} +0 -0
  55. /package/dist/{chunk-I7NYU4JB.js.map → chunk-YJEBZJ7Y.js.map} +0 -0
  56. /package/dist/{client-3BFK7TNL.js.map → client-IFQ2TMCY.js.map} +0 -0
  57. /package/dist/{config-UZ2GIXAO.js.map → config-WIHIVOGZ.js.map} +0 -0
  58. /package/dist/{eas-YTAAJSLU.js.map → eas-KVH644YY.js.map} +0 -0
  59. /package/dist/{governor-53PNPDCZ.js.map → governor-L7FTXIAC.js.map} +0 -0
  60. /package/dist/{identity-462SMK5H.js.map → identity-ZMHBCTOK.js.map} +0 -0
  61. /package/dist/{launchpad-LHMBN4TV.js.map → launchpad-CEUSWTXH.js.map} +0 -0
  62. /package/dist/{lighter-preflight-TSLSSYWI.js.map → lighter-preflight-YOVDIULH.js.map} +0 -0
  63. /package/dist/{network-EZ5X2BF7.js.map → network-XQLQ4MSH.js.map} +0 -0
  64. /package/dist/{price-QKOARHS4.js.map → price-GZEQNKAF.js.map} +0 -0
  65. /package/dist/{providers-22A42FKP.js.map → providers-3PSOZI6R.js.map} +0 -0
  66. /package/dist/{research-3L3BTHWY.js.map → research-C4W7C5S6.js.map} +0 -0
  67. /package/dist/{session-27X337LQ.js.map → session-LIMD5AG5.js.map} +0 -0
  68. /package/dist/{trade-6Q7VCDEA.js.map → trade-U5TZIZHF.js.map} +0 -0
  69. /package/dist/{vault-TQWUWBSG.js.map → vault-SV7UAREO.js.map} +0 -0
  70. /package/dist/{xmtp-EOMKXRTB.js.map → xmtp-TOPGDWX3.js.map} +0 -0
package/dist/index.js CHANGED
@@ -15,14 +15,17 @@ import {
15
15
  checkApiKeyValid,
16
16
  listModels,
17
17
  provisionApiKey
18
- } from "./chunk-74QYNLJE.js";
18
+ } from "./chunk-WTPIXSGL.js";
19
19
  import {
20
20
  createFund,
21
21
  getActiveFunds,
22
22
  getFund,
23
23
  subdomainExists,
24
24
  updateMetadata
25
- } from "./chunk-DQZJULNP.js";
25
+ } from "./chunk-43TG4FOX.js";
26
+ import {
27
+ addLaunchpadTemplateOptions
28
+ } from "./chunk-UKWKI4UC.js";
26
29
  import {
27
30
  FORK_UNOBSERVABLE_REASON,
28
31
  LIGHTER_API_PROFILES,
@@ -54,8 +57,8 @@ import {
54
57
  removeDepositor,
55
58
  setAgentFeeBps,
56
59
  setVaultAddress
57
- } from "./chunk-WAF3JU5J.js";
58
- import "./chunk-NJNK6GTJ.js";
60
+ } from "./chunk-OFGBQAUM.js";
61
+ import "./chunk-QQJAM24N.js";
59
62
  import {
60
63
  CL_DEFAULTS,
61
64
  DEFAULT_FEE_TIER,
@@ -89,7 +92,22 @@ import {
89
92
  selectBestFeeTier,
90
93
  twapTickFromCumulatives,
91
94
  v3SingleHopExtraData
92
- } from "./chunk-6KXITNND.js";
95
+ } from "./chunk-WKOTF5H6.js";
96
+ import {
97
+ CLAIM_SETTLE_BUFFER_SECONDS,
98
+ DEFAULT_DEADLINE_MARGIN_SECONDS,
99
+ LaunchpadInputError,
100
+ buildLaunchpadInitParams,
101
+ decideLaunchDrawdown,
102
+ defaultMaxFeeIn,
103
+ liveFeeCost,
104
+ parseAmountFlag,
105
+ parseDeadline,
106
+ parseDurationSeconds,
107
+ parseSettleSlippageBps,
108
+ parseVenue,
109
+ sameAddr
110
+ } from "./chunk-T5NA6KOF.js";
93
111
  import {
94
112
  DEFAULT_ISSUING_CHAIN_ID,
95
113
  STRATEGY_FACTORY_ABI,
@@ -109,6 +127,7 @@ import {
109
127
  encodeJoinRequest,
110
128
  encodeMgmtSplit,
111
129
  encodePerfSplit,
130
+ encodePrepareOwnerStake,
112
131
  encodePropose,
113
132
  encodeRedeem,
114
133
  encodeRegisterAgent,
@@ -123,12 +142,12 @@ import {
123
142
  registerIdentityCommands,
124
143
  stripVidTag,
125
144
  verifyVidTag
126
- } from "./chunk-UCULHATO.js";
145
+ } from "./chunk-PTWYREL2.js";
127
146
  import {
128
- fetchMetadata,
129
- mergeFundMetadata,
130
- uploadMetadata
131
- } from "./chunk-YMB4RJOR.js";
147
+ emitCalldata,
148
+ isCalldataOnly,
149
+ setCalldataOnly
150
+ } from "./chunk-GAQMHH44.js";
132
151
  import {
133
152
  createApproval,
134
153
  createJoinRequest,
@@ -138,13 +157,13 @@ import {
138
157
  queryJoinRequests,
139
158
  revokeJoinRequest,
140
159
  stripReferrerPrefix
141
- } from "./chunk-2SIUEMPV.js";
160
+ } from "./chunk-RITIB5RY.js";
142
161
  import {
143
162
  resolveFund,
144
163
  resolveVaultFund,
145
164
  searchFundAcrossChains,
146
165
  setTextRecord
147
- } from "./chunk-KPTKX226.js";
166
+ } from "./chunk-DCQELFSU.js";
148
167
  import {
149
168
  PROPOSAL_STATE,
150
169
  PROPOSAL_STATES,
@@ -183,50 +202,7 @@ import {
183
202
  setVotingPeriod,
184
203
  settleProposal,
185
204
  vote
186
- } from "./chunk-5XMQQ4LX.js";
187
- import {
188
- LIGHTER_DEFAULT_API_KEY_INDEX,
189
- LIGHTER_MAX_DEPOSIT,
190
- acknowledgeShortfallCalldata,
191
- buildPostSettleRecoveryCalls,
192
- deriveBurnPubKey,
193
- encodeCancelAll,
194
- encodeClosePosition,
195
- encodeRotateKey,
196
- guardrailActionCalldata,
197
- initiateReturnCalldata,
198
- isLighterPubKeyOnCurve,
199
- queueWithdrawCalldata,
200
- recoverResidualsCalldata,
201
- registerAgentKeyCalldata,
202
- usdgToTicksFloor,
203
- validateLighterKeyIndex,
204
- validateLighterMarket,
205
- validateLighterPubKey
206
- } from "./chunk-TCUSM4V7.js";
207
- import {
208
- addLaunchpadTemplateOptions
209
- } from "./chunk-KXUA5BEH.js";
210
- import {
211
- CLAIM_SETTLE_BUFFER_SECONDS,
212
- DEFAULT_DEADLINE_MARGIN_SECONDS,
213
- LaunchpadInputError,
214
- buildLaunchpadInitParams,
215
- decideLaunchDrawdown,
216
- defaultMaxFeeIn,
217
- liveFeeCost,
218
- parseAmountFlag,
219
- parseDeadline,
220
- parseDurationSeconds,
221
- parseSettleSlippageBps,
222
- parseVenue,
223
- sameAddr
224
- } from "./chunk-T5NA6KOF.js";
225
- import {
226
- emitCalldata,
227
- isCalldataOnly,
228
- setCalldataOnly
229
- } from "./chunk-GAQMHH44.js";
205
+ } from "./chunk-QBOBGQQV.js";
230
206
  import {
231
207
  AERODROME,
232
208
  LAUNCH_ADAPTERS,
@@ -236,7 +212,7 @@ import {
236
212
  TOKENS,
237
213
  UNISWAP,
238
214
  VENICE
239
- } from "./chunk-3R57ETXQ.js";
215
+ } from "./chunk-LSY4GYJ2.js";
240
216
  import {
241
217
  GAS_UNITS,
242
218
  estimateGasCushion,
@@ -247,7 +223,7 @@ import {
247
223
  sendTxWithRetry,
248
224
  waitForReceipt,
249
225
  writeContractWithRetry
250
- } from "./chunk-I7NYU4JB.js";
226
+ } from "./chunk-YJEBZJ7Y.js";
251
227
  import {
252
228
  DEFAULT_NETWORK,
253
229
  VALID_NETWORKS,
@@ -257,7 +233,7 @@ import {
257
233
  isTestnet,
258
234
  setNetwork,
259
235
  withNetwork
260
- } from "./chunk-LIW6K4OJ.js";
236
+ } from "./chunk-JDTTJDGP.js";
261
237
  import {
262
238
  addFund,
263
239
  cacheGroupId,
@@ -274,7 +250,6 @@ import {
274
250
  getVeniceApiKey,
275
251
  getVirtualsIdentity,
276
252
  loadConfig,
277
- setAnthropicApiKey,
278
253
  setChainContract,
279
254
  setConfigRpcUrl,
280
255
  setLighterKeyConfig,
@@ -283,7 +258,27 @@ import {
283
258
  setPrivateKey,
284
259
  setUniswapApiKey,
285
260
  setVeniceApiKey
286
- } from "./chunk-QUAVAJWE.js";
261
+ } from "./chunk-XJR2YQK3.js";
262
+ import {
263
+ LIGHTER_DEFAULT_API_KEY_INDEX,
264
+ LIGHTER_MAX_DEPOSIT,
265
+ acknowledgeShortfallCalldata,
266
+ buildPostSettleRecoveryCalls,
267
+ deriveBurnPubKey,
268
+ encodeCancelAll,
269
+ encodeClosePosition,
270
+ encodeRotateKey,
271
+ guardrailActionCalldata,
272
+ initiateReturnCalldata,
273
+ isLighterPubKeyOnCurve,
274
+ queueWithdrawCalldata,
275
+ recoverResidualsCalldata,
276
+ registerAgentKeyCalldata,
277
+ usdgToTicksFloor,
278
+ validateLighterKeyIndex,
279
+ validateLighterMarket,
280
+ validateLighterPubKey
281
+ } from "./chunk-TCUSM4V7.js";
287
282
  import {
288
283
  BASE_STRATEGY_ABI,
289
284
  ERC20_ABI,
@@ -297,6 +292,11 @@ import {
297
292
  SYNDICATE_VAULT_ABI,
298
293
  VENICE_STAKING_ABI
299
294
  } from "./chunk-SCWNKVNW.js";
295
+ import {
296
+ fetchMetadata,
297
+ mergeFundMetadata,
298
+ uploadMetadata
299
+ } from "./chunk-YMB4RJOR.js";
300
300
 
301
301
  // src/index.ts
302
302
  import { config as loadDotenv } from "dotenv";
@@ -522,7 +522,7 @@ var HYPERLIQUID_GRID_STRATEGY_ABI = [
522
522
  ];
523
523
 
524
524
  // src/commands/strategy-template-lib.ts
525
- import { parseUnits as parseUnits3, formatUnits as formatUnits4, isAddress as isAddress4, erc20Abi as erc20Abi3 } from "viem";
525
+ import { parseUnits as parseUnits3, formatUnits as formatUnits4, isAddress as isAddress4, erc20Abi as erc20Abi3, encodeFunctionData, maxUint256 } from "viem";
526
526
  import chalk3 from "chalk";
527
527
 
528
528
  // src/lib/proposer-bond-error.ts
@@ -560,7 +560,8 @@ var STAKED_WOOD_ABI = [
560
560
  { type: "function", name: "claimUnstakeGuardian", inputs: [], outputs: [], stateMutability: "nonpayable" },
561
561
  // Views
562
562
  { type: "function", name: "guardianStake", inputs: [{ type: "address" }], outputs: [{ type: "uint256" }], stateMutability: "view" },
563
- { type: "function", name: "isActiveGuardian", inputs: [{ type: "address" }], outputs: [{ type: "bool" }], stateMutability: "view" }
563
+ { type: "function", name: "isActiveGuardian", inputs: [{ type: "address" }], outputs: [{ type: "bool" }], stateMutability: "view" },
564
+ { type: "function", name: "minOwnerStake", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" }
564
565
  ];
565
566
  var ERC20_ABI2 = [
566
567
  { type: "function", name: "approve", inputs: [{ type: "address" }, { type: "uint256" }], outputs: [{ type: "bool" }], stateMutability: "nonpayable" },
@@ -692,6 +693,19 @@ function registerGuardianCommands(program2) {
692
693
  "Bond WOOD as a prospective vault owner \u2014 required before `vault create`. Amount in WOOD (min = swood.minOwnerStake, default 10000)."
693
694
  ).action(async (amountStr) => {
694
695
  const amount = parseUnits(amountStr, 18);
696
+ if (isCalldataOnly()) {
697
+ const min = await getPublicClient().readContract({
698
+ address: swood(),
699
+ abi: STAKED_WOOD_ABI,
700
+ functionName: "minOwnerStake"
701
+ });
702
+ if (amount < min) {
703
+ console.error(chalk.red(`Owner stake must be at least ${formatUnits2(min, 18)} WOOD (StakedWood.minOwnerStake).`));
704
+ process.exit(1);
705
+ }
706
+ emitCalldata(encodePrepareOwnerStake({ amount }, getChain().id));
707
+ return;
708
+ }
695
709
  await ensureWoodAllowance(amount);
696
710
  const wallet = getWalletClient();
697
711
  const pc = getPublicClient();
@@ -1761,7 +1775,7 @@ async function resolveChainInputsForTemplate(templateKey, opts, deps = {}) {
1761
1775
  }
1762
1776
  if (templateKey === "lighter-perp") {
1763
1777
  if (opts.pubkey) return {};
1764
- const { getLighterKeyConfig: getLighterKeyConfig2 } = await import("./config-UZ2GIXAO.js");
1778
+ const { getLighterKeyConfig: getLighterKeyConfig2 } = await import("./config-WIHIVOGZ.js");
1765
1779
  const saved = getLighterKeyConfig2();
1766
1780
  return saved ? { lighterSavedKey: { pubKey: saved.pubKey, apiKeyIndex: saved.apiKeyIndex } } : {};
1767
1781
  }
@@ -1805,84 +1819,120 @@ function capsForCalls(calls, strategy2, maxCapital) {
1805
1819
  return seen === 1 ? share + remainder : share;
1806
1820
  });
1807
1821
  }
1808
- async function ensureProposerBondAllowance(vault, requiredCoverage, asset) {
1822
+ async function pinProposalMetadata(meta) {
1823
+ const { pinJSON } = await import("./ipfs-M56BLMCW.js");
1809
1824
  try {
1810
- const publicClient = getPublicClient();
1811
- const governor = await getGovernorOf(vault);
1812
- const govViews = [
1813
- {
1814
- type: "function",
1815
- name: "bondEscrow",
1816
- inputs: [],
1817
- outputs: [{ type: "address" }],
1818
- stateMutability: "view"
1819
- },
1820
- {
1821
- type: "function",
1822
- name: "exposureLedger",
1823
- inputs: [],
1824
- outputs: [{ type: "address" }],
1825
- stateMutability: "view"
1826
- }
1827
- ];
1828
- const escrow = await publicClient.readContract({
1825
+ const uri = await pinJSON(meta, meta.name);
1826
+ console.error(chalk3.dim(` Metadata pinned: ${uri}`));
1827
+ return uri;
1828
+ } catch {
1829
+ console.error(
1830
+ chalk3.yellow(" IPFS pin failed \u2014 using inline metadata. The app renders only ipfs:// metadata; pass --metadata-uri to override.")
1831
+ );
1832
+ const inline = JSON.stringify({ ...meta, createdBy: "@sherwoodagent/cli" });
1833
+ return `data:application/json;base64,${Buffer.from(inline).toString("base64")}`;
1834
+ }
1835
+ }
1836
+ var BOND_GOVERNOR_VIEWS = [
1837
+ { type: "function", name: "bondEscrow", inputs: [], outputs: [{ type: "address" }], stateMutability: "view" },
1838
+ { type: "function", name: "exposureLedger", inputs: [], outputs: [{ type: "address" }], stateMutability: "view" }
1839
+ ];
1840
+ var PROPOSER_BOND_WOOD_ABI = [
1841
+ {
1842
+ type: "function",
1843
+ name: "proposerBondWood",
1844
+ inputs: [
1845
+ { name: "asset", type: "address" },
1846
+ { name: "requiredCoverage", type: "uint256" }
1847
+ ],
1848
+ outputs: [{ type: "uint256" }],
1849
+ stateMutability: "view"
1850
+ }
1851
+ ];
1852
+ async function quoteProposerBond(vault, requiredCoverage, asset) {
1853
+ const publicClient = getPublicClient();
1854
+ const governor = await getGovernorOf(vault);
1855
+ const escrow = await publicClient.readContract({
1856
+ address: governor,
1857
+ abi: BOND_GOVERNOR_VIEWS,
1858
+ functionName: "bondEscrow"
1859
+ });
1860
+ if (!escrow || escrow === ZERO2) return null;
1861
+ let quotedBond = 0n;
1862
+ try {
1863
+ const ledger = await publicClient.readContract({
1829
1864
  address: governor,
1830
- abi: govViews,
1831
- functionName: "bondEscrow"
1865
+ abi: BOND_GOVERNOR_VIEWS,
1866
+ functionName: "exposureLedger"
1832
1867
  });
1833
- if (!escrow || escrow === ZERO2) return;
1834
- let quotedBond = 0n;
1835
- try {
1836
- const ledger = await publicClient.readContract({
1837
- address: governor,
1838
- abi: govViews,
1839
- functionName: "exposureLedger"
1868
+ if (ledger && ledger !== ZERO2 && requiredCoverage > 0n) {
1869
+ quotedBond = await publicClient.readContract({
1870
+ address: ledger,
1871
+ abi: PROPOSER_BOND_WOOD_ABI,
1872
+ functionName: "proposerBondWood",
1873
+ args: [asset, requiredCoverage]
1840
1874
  });
1841
- if (ledger && ledger !== ZERO2 && requiredCoverage > 0n) {
1842
- quotedBond = await publicClient.readContract({
1843
- address: ledger,
1844
- abi: [
1845
- {
1846
- type: "function",
1847
- name: "proposerBondWood",
1848
- inputs: [
1849
- { name: "asset", type: "address" },
1850
- { name: "requiredCoverage", type: "uint256" }
1851
- ],
1852
- outputs: [{ type: "uint256" }],
1853
- stateMutability: "view"
1854
- }
1855
- ],
1856
- functionName: "proposerBondWood",
1857
- args: [asset, requiredCoverage]
1858
- });
1859
- }
1860
- } catch {
1861
1875
  }
1862
- console.log(
1863
- chalk3.dim(
1864
- ` Quoted proposer bond: ${formatUnits4(quotedBond, 18)} WOOD (via ExposureLedger.proposerBondWood; ~1% of extractable value at default proposerBondBps, WOOD-denominated and price-dependent \u2014 not a fixed WOOD amount)`
1865
- )
1866
- );
1867
- console.log(chalk3.dim(` Proposer bond escrow: ${escrow} \u2014 ensuring WOOD allowance`));
1868
- if (quotedBond > 0n) {
1869
- const wood2 = SHERWOOD().WOOD_TOKEN;
1870
- const holder = getAccount().address;
1871
- const balance = await publicClient.readContract({
1872
- address: wood2,
1873
- abi: erc20Abi3,
1874
- functionName: "balanceOf",
1875
- args: [holder]
1876
- });
1877
- if (balance < quotedBond) {
1878
- throw new InsufficientProposerBondWood(quotedBond, balance);
1879
- }
1880
- }
1881
- await ensureWoodAllowance(2n ** 255n, escrow, "WOOD (proposer bond)");
1876
+ } catch {
1877
+ }
1878
+ return { escrow, quotedBond };
1879
+ }
1880
+ function bondQuoteLines(quote) {
1881
+ return [
1882
+ ` Quoted proposer bond: ${formatUnits4(quote.quotedBond, 18)} WOOD (via ExposureLedger.proposerBondWood; ~1% of extractable value at default proposerBondBps, WOOD-denominated and price-dependent \u2014 not a fixed WOOD amount)`,
1883
+ ` Proposer bond escrow: ${quote.escrow}`
1884
+ ];
1885
+ }
1886
+ async function requireBondWood(holder, quotedBond) {
1887
+ if (quotedBond === 0n) return;
1888
+ const balance = await getPublicClient().readContract({
1889
+ address: SHERWOOD().WOOD_TOKEN,
1890
+ abi: erc20Abi3,
1891
+ functionName: "balanceOf",
1892
+ args: [holder]
1893
+ });
1894
+ if (balance < quotedBond) throw new InsufficientProposerBondWood(quotedBond, balance);
1895
+ }
1896
+ async function ensureProposerBondAllowance(vault, requiredCoverage, asset) {
1897
+ try {
1898
+ const quote = await quoteProposerBond(vault, requiredCoverage, asset);
1899
+ if (!quote) return;
1900
+ for (const line of bondQuoteLines(quote)) console.log(chalk3.dim(line));
1901
+ await requireBondWood(getAccount().address, quote.quotedBond);
1902
+ await ensureWoodAllowance(2n ** 255n, quote.escrow, "WOOD (proposer bond)");
1882
1903
  } catch (err) {
1883
1904
  if (err instanceof InsufficientProposerBondWood) throw err;
1884
1905
  }
1885
1906
  }
1907
+ async function proposerBondApprovalTxs(vault, requiredCoverage, asset, proposer, chainId) {
1908
+ let quote;
1909
+ try {
1910
+ quote = await quoteProposerBond(vault, requiredCoverage, asset);
1911
+ } catch {
1912
+ return [];
1913
+ }
1914
+ if (!quote) return [];
1915
+ for (const line of bondQuoteLines(quote)) console.error(chalk3.dim(line));
1916
+ const wood2 = SHERWOOD().WOOD_TOKEN;
1917
+ if (proposer) {
1918
+ await requireBondWood(proposer, quote.quotedBond);
1919
+ const allowance = await getPublicClient().readContract({
1920
+ address: wood2,
1921
+ abi: erc20Abi3,
1922
+ functionName: "allowance",
1923
+ args: [proposer, quote.escrow]
1924
+ });
1925
+ if (allowance >= 2n ** 255n) return [];
1926
+ }
1927
+ return [
1928
+ {
1929
+ to: wood2,
1930
+ data: encodeFunctionData({ abi: erc20Abi3, functionName: "approve", args: [quote.escrow, maxUint256] }),
1931
+ value: "0x0",
1932
+ chainId
1933
+ }
1934
+ ];
1935
+ }
1886
1936
 
1887
1937
  // src/commands/strategy-propose.ts
1888
1938
  import { formatUnits as formatUnits5, isAddress as isAddress5, erc20Abi as erc20Abi4 } from "viem";
@@ -1919,7 +1969,7 @@ function registerStrategyProposeCommands(strategy2) {
1919
1969
  if (isCalldataOnly()) {
1920
1970
  const missing = [];
1921
1971
  if (!opts.proposer) missing.push("--proposer <address> (the external signer)");
1922
- if (!opts.metadataUri) missing.push("--metadata-uri <uri> (IPFS pin needs a signer)");
1972
+ if (!opts.metadataUri && !opts.name) missing.push("--name <name> (or --metadata-uri <uri>)");
1923
1973
  if (!opts.duration) missing.push("--duration <d>");
1924
1974
  if (missing.length > 0) {
1925
1975
  console.error(chalk4.red(`--calldata-only requires: ${missing.join(", ")}`));
@@ -1984,7 +2034,7 @@ function registerStrategyProposeCommands(strategy2) {
1984
2034
  }
1985
2035
  }
1986
2036
  if (templateKey === "lighter-perp") {
1987
- const { runLighterProposePreflight } = await import("./lighter-preflight-TSLSSYWI.js");
2037
+ const { runLighterProposePreflight } = await import("./lighter-preflight-YOVDIULH.js");
1988
2038
  await runLighterProposePreflight(vault, opts, maxDrawdownBps);
1989
2039
  }
1990
2040
  } catch (err) {
@@ -1992,7 +2042,7 @@ function registerStrategyProposeCommands(strategy2) {
1992
2042
  process.exit(1);
1993
2043
  }
1994
2044
  if (!opts.agent) opts.agent = proposer;
1995
- const { parseDuration: parseDuration3, getGovernorOf: getGovernorOf2 } = await import("./governor-53PNPDCZ.js");
2045
+ const { parseDuration: parseDuration3, getGovernorOf: getGovernorOf2 } = await import("./governor-L7FTXIAC.js");
1996
2046
  const strategyDuration2 = parseDuration3(opts.duration);
1997
2047
  const chainId = getChain().id;
1998
2048
  try {
@@ -2015,12 +2065,23 @@ function registerStrategyProposeCommands(strategy2) {
2015
2065
  built.assetAmount,
2016
2066
  built.extraApprovals
2017
2067
  );
2068
+ const metadataURI2 = opts.metadataUri || await pinProposalMetadata({
2069
+ name: opts.name,
2070
+ description: opts.description || "",
2071
+ proposer,
2072
+ vault,
2073
+ strategyClone: deploy.clone,
2074
+ template: def.key,
2075
+ strategyDuration: Number(strategyDuration2),
2076
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
2077
+ });
2078
+ const bondTxs = await proposerBondApprovalTxs(vault, built.assetAmount, built.asset, proposer, chainId);
2018
2079
  const proposeAction = encodePropose(
2019
2080
  {
2020
2081
  vault,
2021
2082
  governor,
2022
2083
  strategy: deploy.clone,
2023
- metadataURI: opts.metadataUri,
2084
+ metadataURI: metadataURI2,
2024
2085
  strategyDuration: strategyDuration2,
2025
2086
  // Same envelope + cap shape the broadcasting path uses, so the
2026
2087
  // emitted calldata is the transaction that path would send.
@@ -2033,14 +2094,14 @@ function registerStrategyProposeCommands(strategy2) {
2033
2094
  chainId
2034
2095
  );
2035
2096
  emitCalldata({
2036
- txs: [...deploy.txs, ...proposeAction.txs],
2097
+ txs: [...bondTxs, ...deploy.txs, ...proposeAction.txs],
2037
2098
  preconditions: [...deploy.preconditions, ...proposeAction.preconditions],
2038
2099
  // Surface the deterministic clone + salt as structured fields (also
2039
2100
  // baked into tx 2's `strategy` arg + the execute/settle calls).
2040
2101
  clone: deploy.clone,
2041
2102
  salt: deploy.salt,
2042
- description: `Keyless ${def.name} proposal on ${vault}: (1) deploy clone at ${deploy.clone} (deterministic CREATE2, salt ${deploy.salt}); (2) governor.propose referencing it.`,
2043
- note: "Broadcast SEQUENTIALLY: send tx 1 (cloneAndInitDeterministic) and WAIT for it to confirm, then send tx 2 (propose). If tx 1 reverts \u2014 proposer not a registered agent, proposer != tx-1 signer, template not allowlisted, or vault unregistered \u2014 do NOT send tx 2: it would create a proposal referencing an undeployed strategy. Send tx 1 from the --proposer wallet (the factory requires proposer == msg.sender, and msg.sender must be a vault owner/agent). The clone address is pinned by (factory, template, vault, salt) and is already baked into tx 2 + the execute/settle calls. The factory binds the salt to the vault and only the vault's owner/agents may deploy there, so the predicted address can't be front-run."
2103
+ description: `Keyless ${def.name} proposal on ${vault}: ` + (bondTxs.length ? "WOOD.approve(proposer-bond escrow); " : "") + `deploy clone at ${deploy.clone} (deterministic CREATE2, salt ${deploy.salt}); governor.propose referencing it.`,
2104
+ note: "Broadcast SEQUENTIALLY from the --proposer wallet, waiting for each tx to confirm before the next. " + (bondTxs.length ? "The first tx approves WOOD to the proposer-bond escrow \u2014 propose pulls the bond from the proposer and reverts without it. " : "") + "If cloneAndInitDeterministic reverts \u2014 proposer not a registered agent, proposer != signer, template not allowlisted, or vault unregistered \u2014 do NOT send propose: it would create a proposal referencing an undeployed strategy. The factory requires proposer == msg.sender, and msg.sender must be a vault owner/agent. The clone address is pinned by (factory, template, vault, salt) and is already baked into the propose tx + the execute/settle calls. The factory binds the salt to the vault and only the vault's owner/agents may deploy there, so the predicted address can't be front-run."
2044
2105
  });
2045
2106
  } catch (err) {
2046
2107
  console.error(chalk4.red(err instanceof Error ? err.message : String(err)));
@@ -2110,7 +2171,7 @@ function registerStrategyProposeCommands(strategy2) {
2110
2171
  }
2111
2172
  }
2112
2173
  if (templateKey === "lighter-perp") {
2113
- const { runLighterProposePreflight } = await import("./lighter-preflight-TSLSSYWI.js");
2174
+ const { runLighterProposePreflight } = await import("./lighter-preflight-YOVDIULH.js");
2114
2175
  await runLighterProposePreflight(vault, opts, maxDrawdownBps);
2115
2176
  }
2116
2177
  preflightSpinner.succeed("Preflight OK");
@@ -2227,9 +2288,9 @@ function registerStrategyProposeCommands(strategy2) {
2227
2288
  console.error(chalk4.red("Missing --name or --duration. Use --write-calls to skip proposal submission."));
2228
2289
  process.exit(1);
2229
2290
  }
2230
- const { propose: propose2 } = await import("./governor-53PNPDCZ.js");
2291
+ const { propose: propose2 } = await import("./governor-L7FTXIAC.js");
2231
2292
  const { pinJSON } = await import("./ipfs-M56BLMCW.js");
2232
- const { parseDuration: parseDuration2 } = await import("./governor-53PNPDCZ.js");
2293
+ const { parseDuration: parseDuration2 } = await import("./governor-L7FTXIAC.js");
2233
2294
  const strategyDuration = parseDuration2(opts.duration);
2234
2295
  const metaSpinner = ora2("Pinning metadata to IPFS...").start();
2235
2296
  let metadataURI;
@@ -2261,7 +2322,7 @@ function registerStrategyProposeCommands(strategy2) {
2261
2322
  metadataURI = `data:application/json;base64,${Buffer.from(inline).toString("base64")}`;
2262
2323
  }
2263
2324
  try {
2264
- const { getAgentFeeBps: getAgentFeeBps2 } = await import("./vault-TQWUWBSG.js");
2325
+ const { getAgentFeeBps: getAgentFeeBps2 } = await import("./vault-SV7UAREO.js");
2265
2326
  const feeBps = await getAgentFeeBps2(vault);
2266
2327
  console.log(
2267
2328
  chalk4.yellow(
@@ -2312,7 +2373,7 @@ function registerStrategyProposeCommands(strategy2) {
2312
2373
  console.log(chalk4.yellow(` asset.approve(${clone}, <repaymentAmount>)`));
2313
2374
  }
2314
2375
  if (templateKey === "lighter-perp") {
2315
- const { lighterNextSteps } = await import("./lighter-preflight-TSLSSYWI.js");
2376
+ const { lighterNextSteps } = await import("./lighter-preflight-YOVDIULH.js");
2316
2377
  console.log();
2317
2378
  for (const line of lighterNextSteps(clone)) console.log(chalk4.yellow(line));
2318
2379
  }
@@ -2584,7 +2645,7 @@ function registerStrategyTemplateCommands(strategy2) {
2584
2645
  let prices = [];
2585
2646
  let priceSource = null;
2586
2647
  try {
2587
- const { getTokenPricesInAsset } = await import("./price-QKOARHS4.js");
2648
+ const { getTokenPricesInAsset } = await import("./price-GZEQNKAF.js");
2588
2649
  prices = await getTokenPricesInAsset({
2589
2650
  tokens: allocations.map((a, i) => ({
2590
2651
  token: a.token,
@@ -3001,7 +3062,7 @@ function registerVeniceCommands(program2) {
3001
3062
  console.log(chalk6.dim(` Key: ${apiKey.slice(0, 8)}...${apiKey.slice(-4)}`));
3002
3063
  console.log(chalk6.dim(" Saved to ~/.sherwood/config.json"));
3003
3064
  try {
3004
- const { createVeniceProvisionAttestation, getEasScanUrl } = await import("./eas-YTAAJSLU.js");
3065
+ const { createVeniceProvisionAttestation, getEasScanUrl } = await import("./eas-KVH644YY.js");
3005
3066
  const attestation = await createVeniceProvisionAttestation(account.address);
3006
3067
  if (attestation) {
3007
3068
  console.log(chalk6.dim(` Attested: ${getEasScanUrl(attestation.uid)}`));
@@ -3357,10 +3418,10 @@ ${opts.prompt}`;
3357
3418
  console.log(chalk6.dim(`Model: ${result.model} | Tokens: ${result.usage.promptTokens} in, ${result.usage.completionTokens} out, ${result.usage.totalTokens} total`));
3358
3419
  }
3359
3420
  try {
3360
- const { createVeniceInferenceAttestation, getEasScanUrl } = await import("./eas-YTAAJSLU.js");
3421
+ const { createVeniceInferenceAttestation, getEasScanUrl } = await import("./eas-KVH644YY.js");
3361
3422
  const { keccak256: keccak2562, toHex, isAddress: isAddr } = await import("viem");
3362
- const { getChainContracts: getChainContracts2 } = await import("./config-UZ2GIXAO.js");
3363
- const { getChain: getActiveChain } = await import("./network-EZ5X2BF7.js");
3423
+ const { getChainContracts: getChainContracts2 } = await import("./config-WIHIVOGZ.js");
3424
+ const { getChain: getActiveChain } = await import("./network-XQLQ4MSH.js");
3364
3425
  const vaultRecipient = opts.vault && isAddr(opts.vault) ? opts.vault : getChainContracts2(getActiveChain().id).vault;
3365
3426
  const promptHash = keccak2562(toHex(userContent)).slice(0, 18);
3366
3427
  const attestation = await createVeniceInferenceAttestation(
@@ -3389,7 +3450,7 @@ import chalk7 from "chalk";
3389
3450
  import ora5 from "ora";
3390
3451
 
3391
3452
  // src/strategies/allowance-disburse.ts
3392
- import { encodeFunctionData, parseUnits as parseUnits7 } from "viem";
3453
+ import { encodeFunctionData as encodeFunctionData2, parseUnits as parseUnits7 } from "viem";
3393
3454
  function buildDisburseBatch(config, vaultAddress, agents, assetAddress, assetDecimals2, minUsdc, swapPath) {
3394
3455
  const assetAmount = parseUnits7(config.amount, assetDecimals2);
3395
3456
  const isUsdc = assetAddress.toLowerCase() === TOKENS().USDC.toLowerCase();
@@ -3398,7 +3459,7 @@ function buildDisburseBatch(config, vaultAddress, agents, assetAddress, assetDec
3398
3459
  if (!isUsdc) {
3399
3460
  calls.push({
3400
3461
  target: assetAddress,
3401
- data: encodeFunctionData({
3462
+ data: encodeFunctionData2({
3402
3463
  abi: ERC20_ABI,
3403
3464
  functionName: "approve",
3404
3465
  args: [UNISWAP().SWAP_ROUTER, assetAmount]
@@ -3408,7 +3469,7 @@ function buildDisburseBatch(config, vaultAddress, agents, assetAddress, assetDec
3408
3469
  if (isWeth) {
3409
3470
  calls.push({
3410
3471
  target: UNISWAP().SWAP_ROUTER,
3411
- data: encodeFunctionData({
3472
+ data: encodeFunctionData2({
3412
3473
  abi: SWAP_ROUTER_EXACT_INPUT_SINGLE_ABI,
3413
3474
  functionName: "exactInputSingle",
3414
3475
  args: [
@@ -3428,7 +3489,7 @@ function buildDisburseBatch(config, vaultAddress, agents, assetAddress, assetDec
3428
3489
  } else {
3429
3490
  calls.push({
3430
3491
  target: UNISWAP().SWAP_ROUTER,
3431
- data: encodeFunctionData({
3492
+ data: encodeFunctionData2({
3432
3493
  abi: SWAP_ROUTER_ABI,
3433
3494
  functionName: "exactInput",
3434
3495
  args: [
@@ -3448,7 +3509,7 @@ function buildDisburseBatch(config, vaultAddress, agents, assetAddress, assetDec
3448
3509
  for (const agent of agents) {
3449
3510
  calls.push({
3450
3511
  target: TOKENS().USDC,
3451
- data: encodeFunctionData({
3512
+ data: encodeFunctionData2({
3452
3513
  abi: ERC20_ABI,
3453
3514
  functionName: "transfer",
3454
3515
  args: [agent, perAgent]
@@ -3658,13 +3719,13 @@ function registerAllowanceCommands(program2) {
3658
3719
  }
3659
3720
 
3660
3721
  // src/commands/proposal.ts
3661
- import { isAddress as isAddress9, encodeFunctionData as encodeFunctionData3, formatUnits as formatUnits9, parseUnits as parseUnits9 } from "viem";
3722
+ import { isAddress as isAddress9, encodeFunctionData as encodeFunctionData4, formatUnits as formatUnits9, parseUnits as parseUnits9 } from "viem";
3662
3723
  import chalk9 from "chalk";
3663
3724
  import ora6 from "ora";
3664
3725
  import { readFileSync as readFileSync2 } from "fs";
3665
3726
 
3666
3727
  // src/lib/simulate.ts
3667
- import { decodeFunctionData as decodeFunctionData2, encodeFunctionData as encodeFunctionData2 } from "viem";
3728
+ import { decodeFunctionData as decodeFunctionData2, encodeFunctionData as encodeFunctionData3 } from "viem";
3668
3729
  import chalk8 from "chalk";
3669
3730
 
3670
3731
  // src/lib/risk.ts
@@ -4224,7 +4285,7 @@ async function simulateViaEthCall(vault, calls) {
4224
4285
  const governor = await getGovernorOf(vault);
4225
4286
  const client = getPublicClient();
4226
4287
  const uncapped = calls.map(() => MAX_UINT256);
4227
- const input2 = encodeFunctionData2({
4288
+ const input2 = encodeFunctionData3({
4228
4289
  abi: SYNDICATE_VAULT_ABI,
4229
4290
  functionName: "executeGovernorBatch",
4230
4291
  args: [
@@ -4356,8 +4417,8 @@ function printSimulationResult(result, callType) {
4356
4417
  }
4357
4418
  async function sendSimulationAlert(subdomain, proposalId, vault, execResult, settleResult) {
4358
4419
  try {
4359
- const xmtp = await import("./xmtp-EOMKXRTB.js");
4360
- const { getAccount: getAccount2 } = await import("./client-3BFK7TNL.js");
4420
+ const xmtp = await import("./xmtp-TOPGDWX3.js");
4421
+ const { getAccount: getAccount2 } = await import("./client-IFQ2TMCY.js");
4361
4422
  const group = await xmtp.getGroup("", subdomain);
4362
4423
  const allRisks = [...execResult.risks, ...settleResult?.risks ?? []];
4363
4424
  const criticals = allRisks.filter((r) => r.level === "critical");
@@ -4605,7 +4666,7 @@ function registerProposalCommands(program2) {
4605
4666
  ).option(
4606
4667
  "--settle-caps <list>",
4607
4668
  "Comma-separated per-settlement-call outflow caps in asset units. Default: 0 for every call, because a settlement returns assets to the vault rather than sending them."
4608
- ).option("--metadata-uri <uri>", "Override \u2014 skip IPFS upload and use this URI directly").option("--simulate", "Simulate calls via Tenderly before submitting").option("--force", "Submit even if simulation fails (requires --simulate)").action(async (opts) => {
4669
+ ).option("--metadata-uri <uri>", "Override \u2014 skip IPFS upload and use this URI directly").option("--proposer <address>", "With --calldata-only: the wallet that will send propose (recorded in metadata; enables the proposer-bond balance/allowance preflight)").option("--simulate", "Simulate calls via Tenderly before submitting").option("--force", "Submit even if simulation fails (requires --simulate)").action(async (opts) => {
4609
4670
  try {
4610
4671
  const vault = opts.vault;
4611
4672
  if (!isAddress9(vault)) {
@@ -4625,46 +4686,72 @@ function registerProposalCommands(program2) {
4625
4686
  strategy2 = opts.strategy;
4626
4687
  }
4627
4688
  if (isCalldataOnly()) {
4628
- if (!opts.metadataUri) {
4629
- console.error(
4630
- chalk9.red(
4631
- "--calldata-only requires --metadata-uri (IPFS metadata upload needs a signing wallet)"
4632
- )
4633
- );
4634
- process.exit(1);
4689
+ let proposer;
4690
+ if (opts.proposer) {
4691
+ if (!isAddress9(opts.proposer)) {
4692
+ console.error(chalk9.red(`Invalid --proposer address: ${opts.proposer}`));
4693
+ process.exit(1);
4694
+ }
4695
+ proposer = opts.proposer;
4635
4696
  }
4636
4697
  const calldataEnvelope = await resolveRiskEnvelope(opts, vault);
4637
4698
  const capDecimals2 = await assetDecimals(vault);
4699
+ const chainId = getChain().id;
4638
4700
  try {
4639
- emitCalldata(
4640
- encodePropose(
4641
- {
4642
- vault,
4643
- governor: await getGovernorOf(vault),
4644
- strategy: strategy2,
4645
- metadataURI: opts.metadataUri,
4646
- strategyDuration,
4647
- envelope: calldataEnvelope,
4648
- executeCalls,
4649
- executeCallCaps: resolveCaps(
4650
- opts.executeCaps,
4651
- executeCalls.length,
4652
- calldataEnvelope.maxCapital,
4653
- "--execute-caps",
4654
- capDecimals2
4655
- ),
4656
- settlementCalls: settleCalls,
4657
- settlementCallCaps: resolveCaps(
4658
- opts.settleCaps,
4659
- settleCalls.length,
4660
- 0n,
4661
- "--settle-caps",
4662
- capDecimals2
4663
- )
4664
- },
4665
- getChain().id
4666
- )
4701
+ const metadataURI2 = opts.metadataUri || await pinProposalMetadata({
4702
+ schema: "sherwood/proposal/v1",
4703
+ name: opts.name,
4704
+ description: opts.description,
4705
+ chain: getNetwork(),
4706
+ strategies: [],
4707
+ terms: {},
4708
+ links: {},
4709
+ ...proposer ? { proposer } : {},
4710
+ vault,
4711
+ strategyDuration: Number(strategyDuration),
4712
+ createdAt: Math.floor(Date.now() / 1e3)
4713
+ });
4714
+ const bondTxs = await proposerBondApprovalTxs(
4715
+ vault,
4716
+ calldataEnvelope.maxCapital,
4717
+ await getAssetAddress(vault),
4718
+ proposer,
4719
+ chainId
4667
4720
  );
4721
+ const proposeAction = encodePropose(
4722
+ {
4723
+ vault,
4724
+ governor: await getGovernorOf(vault),
4725
+ strategy: strategy2,
4726
+ metadataURI: metadataURI2,
4727
+ strategyDuration,
4728
+ envelope: calldataEnvelope,
4729
+ executeCalls,
4730
+ executeCallCaps: resolveCaps(
4731
+ opts.executeCaps,
4732
+ executeCalls.length,
4733
+ calldataEnvelope.maxCapital,
4734
+ "--execute-caps",
4735
+ capDecimals2
4736
+ ),
4737
+ settlementCalls: settleCalls,
4738
+ settlementCallCaps: resolveCaps(
4739
+ opts.settleCaps,
4740
+ settleCalls.length,
4741
+ 0n,
4742
+ "--settle-caps",
4743
+ capDecimals2
4744
+ )
4745
+ },
4746
+ chainId
4747
+ );
4748
+ emitCalldata({
4749
+ ...proposeAction,
4750
+ txs: [...bondTxs, ...proposeAction.txs],
4751
+ ...bondTxs.length ? {
4752
+ note: "Send in order from the proposing agent's wallet: the WOOD approval to the proposer-bond escrow first \u2014 propose pulls the bond and reverts without it." + (proposeAction.note ? ` ${proposeAction.note}` : "")
4753
+ } : {}
4754
+ });
4668
4755
  } catch (err) {
4669
4756
  console.error(chalk9.red(err instanceof Error ? err.message : String(err)));
4670
4757
  process.exit(1);
@@ -5301,7 +5388,7 @@ function registerProposalCommands(program2) {
5301
5388
  process.exit(1);
5302
5389
  }
5303
5390
  const asset = await getAssetAddress(vault);
5304
- const noopCalldata = encodeFunctionData3({
5391
+ const noopCalldata = encodeFunctionData4({
5305
5392
  abi: ERC20_ABI,
5306
5393
  functionName: "balanceOf",
5307
5394
  args: [vault]
@@ -5679,7 +5766,7 @@ function registerProposalCommands(program2) {
5679
5766
  txs: [
5680
5767
  {
5681
5768
  to: governor,
5682
- data: encodeFunctionData3({
5769
+ data: encodeFunctionData4({
5683
5770
  abi: SYNDICATE_GOVERNOR_ABI,
5684
5771
  functionName: "reclaimProposerBond",
5685
5772
  args: [proposalId]
@@ -10089,9 +10176,9 @@ try {
10089
10176
  } catch {
10090
10177
  }
10091
10178
  var require2 = createRequire(import.meta.url);
10092
- var CLI_VERSION = "0.89.3";
10179
+ var CLI_VERSION = "0.90.1";
10093
10180
  async function loadXmtp() {
10094
- return import("./xmtp-EOMKXRTB.js");
10181
+ return import("./xmtp-TOPGDWX3.js");
10095
10182
  }
10096
10183
  async function loadCron() {
10097
10184
  return import("./cron-E3UAZF5B.js");
@@ -10146,6 +10233,10 @@ program.name("sherwood").description("CLI for agent-managed onchain vaults").ver
10146
10233
  ).hook("preAction", (thisCommand) => {
10147
10234
  const opts = thisCommand.optsWithGlobals();
10148
10235
  setCalldataOnly(Boolean(opts.calldataOnly));
10236
+ if (opts.calldataOnly) {
10237
+ console.log = console.error;
10238
+ console.info = console.error;
10239
+ }
10149
10240
  setNetwork(opts.chain);
10150
10241
  });
10151
10242
  var LEGACY_GROUP_ALIASES = ["fund", "syndicate"];
@@ -10287,20 +10378,22 @@ vaultCmd.command("create").description("Launch a new vault via the factory (inte
10287
10378
  }
10288
10379
  }
10289
10380
  if (isCalldataOnly()) {
10290
- emitCalldata(
10291
- encodeCreateFund(
10292
- {
10293
- creatorAgentId: agentIdStr,
10294
- metadataURI,
10295
- asset,
10296
- name,
10297
- symbol,
10298
- openDeposits,
10299
- subdomain
10300
- },
10301
- getChain().id
10302
- )
10381
+ const action = encodeCreateFund(
10382
+ {
10383
+ creatorAgentId: agentIdStr,
10384
+ metadataURI,
10385
+ asset,
10386
+ name,
10387
+ symbol,
10388
+ openDeposits,
10389
+ subdomain
10390
+ },
10391
+ getChain().id
10303
10392
  );
10393
+ emitCalldata({
10394
+ ...action,
10395
+ note: `${action.note} Bond first with \`sherwood --calldata-only guardian prepare-owner-stake <amount>\`. After this tx confirms, register the creator as an agent (the factory does not, and proposing requires it): read the vault with \`sherwood vault info ${subdomain}\`, then send \`sherwood --calldata-only vault add --vault <vault> --wallet <creator> --agent-id ${agentIdStr}\`.`
10396
+ });
10304
10397
  return;
10305
10398
  }
10306
10399
  const existingId = await subdomainExists(subdomain);
@@ -10762,7 +10855,7 @@ vaultCmd.command("add").description("Register an agent on a vault (creator only)
10762
10855
  agentId = BigInt(opts.agentId);
10763
10856
  } else {
10764
10857
  spinner.text = "Looking up ERC-8004 identity from wallet...";
10765
- const { lookupAgentIdByWallet } = await import("./identity-462SMK5H.js");
10858
+ const { lookupAgentIdByWallet } = await import("./identity-ZMHBCTOK.js");
10766
10859
  const resolved = await lookupAgentIdByWallet(agentWallet);
10767
10860
  if (resolved === null) {
10768
10861
  spinner.fail("Agent wallet does not own an ERC-8004 identity NFT");
@@ -11465,7 +11558,7 @@ vaultCmd.command("redeem").description("Redeem vault shares for the underlying a
11465
11558
  var strategy = program.command("strategy").description("Strategy templates \u2014 list, clone, propose");
11466
11559
  registerStrategyTemplateCommands(strategy);
11467
11560
  program.command("providers").description("List available providers (research + swap routing)").action(async () => {
11468
- const { listProviders } = await import("./providers-22A42FKP.js");
11561
+ const { listProviders } = await import("./providers-3PSOZI6R.js");
11469
11562
  for (const info2 of listProviders()) {
11470
11563
  console.log(`
11471
11564
  ${info2.name} (${info2.type})`);
@@ -11475,7 +11568,7 @@ ${info2.name} (${info2.type})`);
11475
11568
  }
11476
11569
  });
11477
11570
  try {
11478
- const { registerChatCommands } = await import("./chat-EVRY5BV3.js");
11571
+ const { registerChatCommands } = await import("./chat-FSAHNEIY.js");
11479
11572
  registerChatCommands(program);
11480
11573
  } catch {
11481
11574
  program.command("chat <name> [action] [actionArgs...]").description("Vault chat (XMTP) \u2014 requires @xmtp/cli").action(() => {
@@ -11485,7 +11578,7 @@ try {
11485
11578
  process.exit(1);
11486
11579
  });
11487
11580
  }
11488
- var { registerSessionCommands } = await import("./session-27X337LQ.js");
11581
+ var { registerSessionCommands } = await import("./session-LIMD5AG5.js");
11489
11582
  registerSessionCommands(program);
11490
11583
  registerVeniceCommands(program);
11491
11584
  registerAllowanceCommands(program);
@@ -11494,18 +11587,18 @@ registerProposalCommands(program);
11494
11587
  registerQueueCommands(program);
11495
11588
  registerGovernorCommands(program);
11496
11589
  registerGuardianCommands(program);
11497
- var { registerResearchCommands } = await import("./research-3L3BTHWY.js");
11590
+ var { registerResearchCommands } = await import("./research-C4W7C5S6.js");
11498
11591
  registerResearchCommands(program);
11499
- var { registerAgentCommands } = await import("./agent-QU2OSWS4.js");
11592
+ var { registerAgentCommands } = await import("./agent-DLLONQ76.js");
11500
11593
  registerAgentCommands(program);
11501
- var { registerTradeCommands } = await import("./trade-6Q7VCDEA.js");
11594
+ var { registerTradeCommands } = await import("./trade-U5TZIZHF.js");
11502
11595
  registerTradeCommands(program);
11503
11596
  registerGridCommand(program);
11504
11597
  registerLighterCommands(program);
11505
- var { registerLaunchpadCommands } = await import("./launchpad-LHMBN4TV.js");
11598
+ var { registerLaunchpadCommands } = await import("./launchpad-CEUSWTXH.js");
11506
11599
  registerLaunchpadCommands(program);
11507
11600
  var configCmd = program.command("config");
11508
- 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 vault 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("--anthropic-api-key <key>", "Anthropic Claude API key (for LLM judge)").option("--xmtp-group <subdomain:groupId>", "Cache an XMTP group ID for a vault (e.g. my-vault:abc123)").action((opts) => {
11601
+ 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 vault 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 vault (e.g. my-vault:abc123)").action((opts) => {
11509
11602
  let saved = false;
11510
11603
  if (opts.privateKey) {
11511
11604
  setPrivateKey(opts.privateKey);
@@ -11544,11 +11637,6 @@ configCmd.command("set").description("Save settings to ~/.sherwood/config.json (
11544
11637
  console.log(chalk19.green("Venice API key saved to ~/.sherwood/config.json"));
11545
11638
  saved = true;
11546
11639
  }
11547
- if (opts.anthropicApiKey) {
11548
- setAnthropicApiKey(opts.anthropicApiKey);
11549
- console.log(chalk19.green("Anthropic API key saved to ~/.sherwood/config.json"));
11550
- saved = true;
11551
- }
11552
11640
  if (opts.xmtpGroup) {
11553
11641
  const parts = opts.xmtpGroup.split(":");
11554
11642
  if (parts.length !== 2 || !parts[0] || !parts[1]) {
@@ -11561,7 +11649,7 @@ configCmd.command("set").description("Save settings to ~/.sherwood/config.json (
11561
11649
  saved = true;
11562
11650
  }
11563
11651
  if (!saved) {
11564
- console.log(chalk19.red("Provide at least one of: --private-key, --vault, --rpc, --notify-to, --uniswap-api-key, --venice-api-key, --anthropic-api-key, --xmtp-group"));
11652
+ console.log(chalk19.red("Provide at least one of: --private-key, --vault, --rpc, --notify-to, --uniswap-api-key, --venice-api-key, --xmtp-group"));
11565
11653
  process.exit(1);
11566
11654
  }
11567
11655
  });