@sherwoodagent/cli 0.25.1 → 0.25.3

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 (31) hide show
  1. package/dist/{chat-52PWNH7Y.js → chat-DRKUZCOY.js} +4 -4
  2. package/dist/{chunk-VQIFAXUY.js → chunk-4WG64CRK.js} +2 -2
  3. package/dist/{chunk-JEVBC7DV.js → chunk-6DWQIKGN.js} +2 -2
  4. package/dist/{chunk-7PCI3WHQ.js → chunk-H55III3L.js} +2 -2
  5. package/dist/{chunk-ZPLUJT4V.js → chunk-ICUQY7TY.js} +34 -1
  6. package/dist/chunk-ICUQY7TY.js.map +1 -0
  7. package/dist/{chunk-QBNWBWD3.js → chunk-Y7LUFGIS.js} +91 -2
  8. package/dist/chunk-Y7LUFGIS.js.map +1 -0
  9. package/dist/{eas-YZIHYQAI.js → eas-652I6ULB.js} +3 -3
  10. package/dist/{governor-YPDAOT3S.js → governor-CY3GXU44.js} +3 -3
  11. package/dist/index.js +199 -18
  12. package/dist/index.js.map +1 -1
  13. package/dist/{price-SWNEGWO4.js → price-FOCSYKGJ.js} +2 -2
  14. package/dist/{research-PH77VSE4.js → research-LJKYDBCL.js} +3 -3
  15. package/dist/{session-NMA4RLKC.js → session-7HKFQ7JZ.js} +5 -5
  16. package/dist/{trade-N2A74UPX.js → trade-4SOHHD5R.js} +6 -6
  17. package/dist/{xmtp-YNOGIZ4G.js → xmtp-K555NJPU.js} +3 -3
  18. package/package.json +1 -1
  19. package/dist/chunk-QBNWBWD3.js.map +0 -1
  20. package/dist/chunk-ZPLUJT4V.js.map +0 -1
  21. /package/dist/{chat-52PWNH7Y.js.map → chat-DRKUZCOY.js.map} +0 -0
  22. /package/dist/{chunk-VQIFAXUY.js.map → chunk-4WG64CRK.js.map} +0 -0
  23. /package/dist/{chunk-JEVBC7DV.js.map → chunk-6DWQIKGN.js.map} +0 -0
  24. /package/dist/{chunk-7PCI3WHQ.js.map → chunk-H55III3L.js.map} +0 -0
  25. /package/dist/{eas-YZIHYQAI.js.map → eas-652I6ULB.js.map} +0 -0
  26. /package/dist/{governor-YPDAOT3S.js.map → governor-CY3GXU44.js.map} +0 -0
  27. /package/dist/{price-SWNEGWO4.js.map → price-FOCSYKGJ.js.map} +0 -0
  28. /package/dist/{research-PH77VSE4.js.map → research-LJKYDBCL.js.map} +0 -0
  29. /package/dist/{session-NMA4RLKC.js.map → session-7HKFQ7JZ.js.map} +0 -0
  30. /package/dist/{trade-N2A74UPX.js.map → trade-4SOHHD5R.js.map} +0 -0
  31. /package/dist/{xmtp-YNOGIZ4G.js.map → xmtp-K555NJPU.js.map} +0 -0
package/dist/index.js CHANGED
@@ -4,19 +4,24 @@ import {
4
4
  deposit,
5
5
  depositWithEthWrap,
6
6
  executeBatch,
7
+ getAssetAddress,
7
8
  getAssetDecimals,
8
9
  getBalance,
10
+ getShareBalance,
9
11
  getVaultAddress,
10
12
  getVaultInfo,
13
+ getVaultOwner,
11
14
  isAgent,
12
15
  preflightDeposit,
16
+ preflightRedeem,
17
+ redeem,
13
18
  registerAgent,
14
19
  removeDepositor,
15
20
  resolveSyndicate,
16
21
  resolveVaultSyndicate,
17
22
  setTextRecord,
18
23
  setVaultAddress
19
- } from "./chunk-QBNWBWD3.js";
24
+ } from "./chunk-Y7LUFGIS.js";
20
25
  import {
21
26
  UniswapProvider,
22
27
  applySlippage,
@@ -27,7 +32,7 @@ import {
27
32
  getQuote,
28
33
  listModels,
29
34
  provisionApiKey
30
- } from "./chunk-VQIFAXUY.js";
35
+ } from "./chunk-4WG64CRK.js";
31
36
  import {
32
37
  PROPOSAL_STATE,
33
38
  PROPOSAL_STATES,
@@ -36,6 +41,7 @@ import {
36
41
  emergencyCancel,
37
42
  emergencySettle,
38
43
  executeProposal,
44
+ getActiveProposal,
39
45
  getCapitalSnapshot,
40
46
  getExecuteCalls,
41
47
  getGovernorAddress,
@@ -58,7 +64,7 @@ import {
58
64
  setVotingPeriod,
59
65
  settleProposal,
60
66
  vote
61
- } from "./chunk-7PCI3WHQ.js";
67
+ } from "./chunk-H55III3L.js";
62
68
  import {
63
69
  fetchMetadata,
64
70
  uploadMetadata
@@ -72,7 +78,7 @@ import {
72
78
  queryJoinRequests,
73
79
  revokeAttestation,
74
80
  stripReferrerPrefix
75
- } from "./chunk-JEVBC7DV.js";
81
+ } from "./chunk-6DWQIKGN.js";
76
82
  import {
77
83
  AERODROME,
78
84
  AGENT_REGISTRY,
@@ -93,7 +99,7 @@ import {
93
99
  UNISWAP,
94
100
  VENICE,
95
101
  VENICE_STAKING_ABI
96
- } from "./chunk-ZPLUJT4V.js";
102
+ } from "./chunk-ICUQY7TY.js";
97
103
  import {
98
104
  formatContractError,
99
105
  getAccount,
@@ -139,7 +145,7 @@ import {
139
145
  import { config as loadDotenv } from "dotenv";
140
146
  import { createRequire } from "module";
141
147
  import { Command, Option } from "commander";
142
- import { parseUnits as parseUnits5, isAddress as isAddress5 } from "viem";
148
+ import { parseUnits as parseUnits5, formatUnits as formatUnits5, isAddress as isAddress5 } from "viem";
143
149
  import chalk8 from "chalk";
144
150
  import ora7 from "ora";
145
151
  import { input, confirm, select } from "@inquirer/prompts";
@@ -1293,9 +1299,9 @@ function registerStrategyTemplateCommands(strategy2) {
1293
1299
  console.error(chalk.red("Missing --name, --performance-fee, or --duration. Use --write-calls to skip proposal submission."));
1294
1300
  process.exit(1);
1295
1301
  }
1296
- const { propose: propose2 } = await import("./governor-YPDAOT3S.js");
1302
+ const { propose: propose2 } = await import("./governor-CY3GXU44.js");
1297
1303
  const { pinJSON } = await import("./ipfs-22YLNQ2C.js");
1298
- const { parseDuration: parseDuration2 } = await import("./governor-YPDAOT3S.js");
1304
+ const { parseDuration: parseDuration2 } = await import("./governor-CY3GXU44.js");
1299
1305
  const performanceFeeBps = BigInt(opts.performanceFee);
1300
1306
  if (performanceFeeBps < 0n || performanceFeeBps > 10000n) {
1301
1307
  console.error(chalk.red("--performance-fee must be 0-10000 (basis points)"));
@@ -1403,7 +1409,7 @@ function registerStrategyTemplateCommands(strategy2) {
1403
1409
  let prices = [];
1404
1410
  let priceSource = null;
1405
1411
  try {
1406
- const { getTokenPricesInAsset } = await import("./price-SWNEGWO4.js");
1412
+ const { getTokenPricesInAsset } = await import("./price-FOCSYKGJ.js");
1407
1413
  prices = await getTokenPricesInAsset({
1408
1414
  tokens: allocations.map((a, i) => ({
1409
1415
  token: a.token,
@@ -1950,7 +1956,7 @@ function registerVeniceCommands(program2) {
1950
1956
  console.log(chalk2.dim(` Key: ${apiKey.slice(0, 8)}...${apiKey.slice(-4)}`));
1951
1957
  console.log(chalk2.dim(" Saved to ~/.sherwood/config.json"));
1952
1958
  try {
1953
- const { createVeniceProvisionAttestation, getEasScanUrl: getEasScanUrl2 } = await import("./eas-YZIHYQAI.js");
1959
+ const { createVeniceProvisionAttestation, getEasScanUrl: getEasScanUrl2 } = await import("./eas-652I6ULB.js");
1954
1960
  const { uid } = await createVeniceProvisionAttestation(account.address);
1955
1961
  if (uid !== "0x0000000000000000000000000000000000000000000000000000000000000000") {
1956
1962
  console.log(chalk2.dim(` Attested: ${getEasScanUrl2(uid)}`));
@@ -2101,7 +2107,7 @@ ${opts.prompt}`;
2101
2107
  console.log(chalk2.dim(`Model: ${result.model} | Tokens: ${result.usage.promptTokens} in, ${result.usage.completionTokens} out, ${result.usage.totalTokens} total`));
2102
2108
  }
2103
2109
  try {
2104
- const { createVeniceInferenceAttestation, getEasScanUrl: getEasScanUrl2 } = await import("./eas-YZIHYQAI.js");
2110
+ const { createVeniceInferenceAttestation, getEasScanUrl: getEasScanUrl2 } = await import("./eas-652I6ULB.js");
2105
2111
  const { keccak256, toHex, isAddress: isAddr } = await import("viem");
2106
2112
  const { getChainContracts: getChainContracts2 } = await import("./config-YXZKPSZB.js");
2107
2113
  const { getChain: getActiveChain } = await import("./network-QEMP3DSP.js");
@@ -2555,7 +2561,7 @@ function registerIdentityCommands(program2) {
2555
2561
  }
2556
2562
 
2557
2563
  // src/commands/proposal.ts
2558
- import { isAddress as isAddress4 } from "viem";
2564
+ import { isAddress as isAddress4, encodeFunctionData as encodeFunctionData9 } from "viem";
2559
2565
  import chalk6 from "chalk";
2560
2566
  import ora5 from "ora";
2561
2567
  import { readFileSync as readFileSync2 } from "fs";
@@ -3233,7 +3239,7 @@ function printSimulationResult(result, callType) {
3233
3239
  }
3234
3240
  async function sendSimulationAlert(subdomain, proposalId, vault, execResult, settleResult) {
3235
3241
  try {
3236
- const xmtp = await import("./xmtp-YNOGIZ4G.js");
3242
+ const xmtp = await import("./xmtp-K555NJPU.js");
3237
3243
  const { getAccount: getAccount2 } = await import("./client-CWQFYZ5Z.js");
3238
3244
  const group = await xmtp.getGroup("", subdomain);
3239
3245
  const allRisks = [...execResult.risks, ...settleResult?.risks ?? []];
@@ -3685,6 +3691,130 @@ function registerProposalCommands(program2) {
3685
3691
  process.exit(1);
3686
3692
  }
3687
3693
  });
3694
+ proposal.command("unstick", { hidden: true }).description(
3695
+ "Guardian-only: unstick a vault whose Executed proposal cannot settle (no funds moved)"
3696
+ ).requiredOption("--id <proposalId>", "Proposal ID to unstick").option("--yes", "Skip the interactive confirmation").option(
3697
+ "--dry-run",
3698
+ "Check preconditions and print the fallback call without broadcasting"
3699
+ ).action(async (opts) => {
3700
+ try {
3701
+ const proposalId = parseBigIntArg(opts.id, "proposal ID");
3702
+ const account = getAccount();
3703
+ const spinner = ora5("Loading proposal...").start();
3704
+ const p = await getProposal(proposalId);
3705
+ const state = await getProposalState(proposalId);
3706
+ if (state !== PROPOSAL_STATE.Executed) {
3707
+ spinner.fail(
3708
+ `Proposal ${proposalId} is ${PROPOSAL_STATES[state] || "Unknown"} \u2014 unstick only applies to Executed proposals.`
3709
+ );
3710
+ console.error(
3711
+ DIM2(
3712
+ "\n Other states have their own recovery path:\n Draft/Pending \u2192 sherwood proposal cancel --id <id>\n Approved \u2192 sherwood proposal veto <id>\n Expired \u2192 vault is not locked, nothing to do\n Settled \u2192 already settled\n Cancelled \u2192 governor upgrade required (issue #177)\n"
3713
+ )
3714
+ );
3715
+ process.exit(1);
3716
+ }
3717
+ const now = BigInt(Math.floor(Date.now() / 1e3));
3718
+ const expiresAt = p.executedAt + p.strategyDuration;
3719
+ if (p.executedAt === 0n || now < expiresAt) {
3720
+ spinner.fail("Strategy duration has not elapsed yet.");
3721
+ const remaining = expiresAt - now;
3722
+ console.error(
3723
+ DIM2(
3724
+ `
3725
+ Can unstick after: ${new Date(Number(expiresAt) * 1e3).toLocaleString()} (in ~${formatDurationShort(remaining)})
3726
+ `
3727
+ )
3728
+ );
3729
+ process.exit(1);
3730
+ }
3731
+ const vault = p.vault;
3732
+ const active = await getActiveProposal(vault);
3733
+ if (active !== proposalId) {
3734
+ spinner.fail(
3735
+ `Vault ${vault} active proposal is ${active}, not ${proposalId} \u2014 nothing to unstick for this proposal.`
3736
+ );
3737
+ process.exit(1);
3738
+ }
3739
+ const vaultOwner = await getVaultOwner(vault);
3740
+ if (account.address.toLowerCase() !== vaultOwner.toLowerCase()) {
3741
+ spinner.fail("Only the vault owner can unstick a proposal.");
3742
+ console.error(
3743
+ DIM2(`
3744
+ Vault owner: ${vaultOwner}
3745
+ Your wallet: ${account.address}
3746
+ `)
3747
+ );
3748
+ process.exit(1);
3749
+ }
3750
+ const asset = await getAssetAddress();
3751
+ const noopCalldata = encodeFunctionData9({
3752
+ abi: ERC20_ABI,
3753
+ functionName: "balanceOf",
3754
+ args: [vault]
3755
+ });
3756
+ const fallbackCalls = [
3757
+ { target: asset, data: noopCalldata, value: 0n }
3758
+ ];
3759
+ spinner.stop();
3760
+ console.log();
3761
+ console.log(BOLD2("Unstick plan"));
3762
+ SEP2();
3763
+ console.log(` Proposal: ${proposalId}`);
3764
+ console.log(` Vault: ${vault}`);
3765
+ console.log(` Asset: ${asset}`);
3766
+ console.log(` State: ${PROPOSAL_STATES[state]} (duration elapsed)`);
3767
+ console.log(` Caller: ${account.address} (vault owner \u2713)`);
3768
+ console.log();
3769
+ console.log(LABEL2(" Fallback call (no-op, cannot revert):"));
3770
+ console.log(DIM2(` target: ${asset}`));
3771
+ console.log(DIM2(` data: ${noopCalldata} // balanceOf(${vault})`));
3772
+ console.log(DIM2(" value: 0"));
3773
+ console.log();
3774
+ console.log(
3775
+ DIM2(
3776
+ " This calls emergencySettle(id, [noop]). The governor catches any revert\n from the pre-committed settlement calls and runs the no-op instead. No\n funds move. The proposal transitions to Settled and the vault unlocks.\n LPs can then redeem via `sherwood vault redeem`."
3777
+ )
3778
+ );
3779
+ console.log();
3780
+ if (opts.dryRun) {
3781
+ console.log(G2(" (dry-run) Preconditions OK \u2014 not broadcasting.\n"));
3782
+ return;
3783
+ }
3784
+ if (!opts.yes) {
3785
+ process.stdout.write(chalk6.yellow(" Proceed? [y/N] "));
3786
+ const answer = await new Promise((resolve2) => {
3787
+ process.stdin.resume();
3788
+ process.stdin.setEncoding("utf-8");
3789
+ process.stdin.once("data", (d) => resolve2(String(d).trim().toLowerCase()));
3790
+ });
3791
+ process.stdin.pause();
3792
+ if (answer !== "y" && answer !== "yes") {
3793
+ console.log(DIM2(" Cancelled.\n"));
3794
+ return;
3795
+ }
3796
+ }
3797
+ const send = ora5("Broadcasting emergencySettle...").start();
3798
+ const hash = await emergencySettle(proposalId, fallbackCalls);
3799
+ send.succeed(G2("Vault unstuck \u2014 proposal Settled"));
3800
+ console.log(DIM2(` ${getExplorerUrl(hash)}`));
3801
+ const stillActive = await getActiveProposal(vault);
3802
+ if (stillActive === 0n) {
3803
+ console.log(G2(" redemptionsLocked cleared \u2713"));
3804
+ } else {
3805
+ console.log(
3806
+ chalk6.yellow(
3807
+ ` \u26A0 getActiveProposal(vault) still returns ${stillActive} \u2014 check manually.`
3808
+ )
3809
+ );
3810
+ }
3811
+ console.log();
3812
+ } catch (err) {
3813
+ console.error(chalk6.red(`
3814
+ \u2716 ${formatContractError(err)}`));
3815
+ process.exit(1);
3816
+ }
3817
+ });
3688
3818
  proposal.command("cancel").description("Cancel a proposal (proposer or vault owner)").requiredOption("--id <proposalId>", "Proposal ID").option("--emergency", "Emergency cancel (vault owner only, any non-settled state)").action(async (opts) => {
3689
3819
  try {
3690
3820
  const proposalId = parseBigIntArg(opts.id, "proposal ID");
@@ -3926,7 +4056,7 @@ try {
3926
4056
  var require2 = createRequire(import.meta.url);
3927
4057
  var { version: CLI_VERSION } = require2("../package.json");
3928
4058
  async function loadXmtp() {
3929
- return import("./xmtp-YNOGIZ4G.js");
4059
+ return import("./xmtp-K555NJPU.js");
3930
4060
  }
3931
4061
  async function loadCron() {
3932
4062
  return import("./cron-EOULYO3R.js");
@@ -4886,6 +5016,57 @@ vaultCmd.command("balance").description("Show LP share balance and asset value")
4886
5016
  process.exit(1);
4887
5017
  }
4888
5018
  });
5019
+ vaultCmd.command("redeem").description("Redeem vault shares for the underlying asset (ERC-4626)").option("--vault <address>", "Vault address (default: from config)").option("--shares <amount>", "Shares to redeem in whole-share units (default: all)").option("--receiver <address>", "Receiver of the underlying asset (default: your wallet)").action(async (opts) => {
5020
+ resolveVault(opts);
5021
+ const assetDecimals = await getAssetDecimals();
5022
+ const shareDecimals = assetDecimals * 2;
5023
+ let shares;
5024
+ try {
5025
+ if (opts.shares) {
5026
+ shares = parseUnits5(opts.shares, shareDecimals);
5027
+ } else {
5028
+ shares = await getShareBalance();
5029
+ if (shares === 0n) {
5030
+ console.error(chalk8.red("\n \u2716 No shares to redeem.\n"));
5031
+ process.exit(1);
5032
+ }
5033
+ }
5034
+ } catch (err) {
5035
+ console.error(chalk8.red(`
5036
+ \u2716 ${err instanceof Error ? err.message : String(err)}
5037
+ `));
5038
+ process.exit(1);
5039
+ }
5040
+ if (opts.receiver && !isAddress5(opts.receiver)) {
5041
+ console.error(chalk8.red(`
5042
+ \u2716 Invalid receiver address: ${opts.receiver}
5043
+ `));
5044
+ process.exit(1);
5045
+ }
5046
+ try {
5047
+ await preflightRedeem(shares);
5048
+ } catch (err) {
5049
+ console.error(chalk8.red(`
5050
+ \u2716 ${err instanceof Error ? err.message : String(err)}
5051
+ `));
5052
+ process.exit(1);
5053
+ }
5054
+ const sharesDisplay = formatUnits5(shares, shareDecimals);
5055
+ const spinner = ora7(`Redeeming ${sharesDisplay} shares...`).start();
5056
+ try {
5057
+ const { hash, assetsOut } = await redeem(
5058
+ shares,
5059
+ opts.receiver
5060
+ );
5061
+ spinner.succeed(`Redeemed: ${hash}`);
5062
+ console.log(chalk8.dim(` ${getExplorerUrl(hash)}`));
5063
+ console.log(` Assets received: ${formatUnits5(assetsOut, assetDecimals)}`);
5064
+ } catch (err) {
5065
+ spinner.fail("Redeem failed");
5066
+ console.error(chalk8.red(formatContractError(err)));
5067
+ process.exit(1);
5068
+ }
5069
+ });
4889
5070
  var strategy = program.command("strategy").description("Strategy templates \u2014 list, clone, propose");
4890
5071
  registerStrategyTemplateCommands(strategy);
4891
5072
  program.command("providers").description("List available DeFi providers").action(async () => {
@@ -4900,7 +5081,7 @@ ${info.name} (${info.type})`);
4900
5081
  }
4901
5082
  });
4902
5083
  try {
4903
- const { registerChatCommands } = await import("./chat-52PWNH7Y.js");
5084
+ const { registerChatCommands } = await import("./chat-DRKUZCOY.js");
4904
5085
  registerChatCommands(program);
4905
5086
  } catch {
4906
5087
  program.command("chat <name> [action] [actionArgs...]").description("Syndicate chat (XMTP) \u2014 requires @xmtp/cli").action(() => {
@@ -4910,16 +5091,16 @@ try {
4910
5091
  process.exit(1);
4911
5092
  });
4912
5093
  }
4913
- var { registerSessionCommands } = await import("./session-NMA4RLKC.js");
5094
+ var { registerSessionCommands } = await import("./session-7HKFQ7JZ.js");
4914
5095
  registerSessionCommands(program);
4915
5096
  registerVeniceCommands(program);
4916
5097
  registerAllowanceCommands(program);
4917
5098
  registerIdentityCommands(program);
4918
5099
  registerProposalCommands(program);
4919
5100
  registerGovernorCommands(program);
4920
- var { registerResearchCommands } = await import("./research-PH77VSE4.js");
5101
+ var { registerResearchCommands } = await import("./research-LJKYDBCL.js");
4921
5102
  registerResearchCommands(program);
4922
- var { registerTradeCommands } = await import("./trade-N2A74UPX.js");
5103
+ var { registerTradeCommands } = await import("./trade-4SOHHD5R.js");
4923
5104
  registerTradeCommands(program);
4924
5105
  var configCmd = program.command("config");
4925
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) => {