@sherwoodagent/cli 0.80.0 → 0.81.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.
@@ -23,7 +23,7 @@ import "./chunk-TU655ZTV.js";
23
23
  import {
24
24
  fetchMetadata,
25
25
  uploadMetadata
26
- } from "./chunk-XDGCHURW.js";
26
+ } from "./chunk-VR4VHX4D.js";
27
27
 
28
28
  // src/commands/chat.ts
29
29
  import chalk from "chalk";
@@ -563,4 +563,4 @@ function registerChatCommands(program) {
563
563
  export {
564
564
  registerChatCommands
565
565
  };
566
- //# sourceMappingURL=chat-56DDAGA2.js.map
566
+ //# sourceMappingURL=chat-ANE3SNHH.js.map
@@ -1,8 +1,8 @@
1
1
  // src/lib/ipfs.ts
2
2
  var DEFAULT_PINATA_GATEWAY = "https://sherwood.mypinata.cloud";
3
- var DEFAULT_UPLOAD_API = "https://www.sherwood.sh/api/ipfs/upload";
3
+ var DEFAULT_API_BASE = "https://api.sherwood.sh";
4
4
  function getUploadApiUrl() {
5
- return process.env.SHERWOOD_API_URL ? `${process.env.SHERWOOD_API_URL}/api/ipfs/upload` : DEFAULT_UPLOAD_API;
5
+ return `${process.env.SHERWOOD_API_URL ?? DEFAULT_API_BASE}/ipfs/upload`;
6
6
  }
7
7
  function getPinataGateway() {
8
8
  return process.env.PINATA_GATEWAY || DEFAULT_PINATA_GATEWAY;
@@ -94,4 +94,4 @@ export {
94
94
  mergeFundMetadata,
95
95
  resolveMetadataSummary
96
96
  };
97
- //# sourceMappingURL=chunk-XDGCHURW.js.map
97
+ //# sourceMappingURL=chunk-VR4VHX4D.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/ipfs.ts"],"sourcesContent":["/**\n * IPFS metadata upload/fetch via Sherwood API.\n *\n * Uploads go through the server-side API at api.sherwood.sh/ipfs/upload\n * which holds the Pinata JWT. CLI and app only need the gateway URL for reads.\n */\n\nexport interface FundMetadata {\n schema: string;\n name: string;\n description: string;\n logo?: string;\n chain: string;\n xmtpGroupId?: string;\n strategies: {\n id: string;\n name: string;\n description: string;\n protocols: string[];\n riskLevel: string;\n }[];\n terms: {\n minDeposit?: string;\n minDepositFormatted?: string;\n feeModel?: string;\n lockPeriod?: number;\n };\n links: {\n moltbook?: string;\n dashboard?: string;\n github?: string;\n };\n}\n\nconst DEFAULT_PINATA_GATEWAY = \"https://sherwood.mypinata.cloud\";\n// SHERWOOD_API_URL overrides the BASE — an origin serving the flat v1 tree,\n// e.g. https://api.sherwood.sh, http://localhost:3000/api/v1,\n// https://<deployment>.vercel.app/api/v1.\nconst DEFAULT_API_BASE = \"https://api.sherwood.sh\";\n\nfunction getUploadApiUrl(): string {\n return `${process.env.SHERWOOD_API_URL ?? DEFAULT_API_BASE}/ipfs/upload`;\n}\n\nfunction getPinataGateway(): string {\n return process.env.PINATA_GATEWAY || DEFAULT_PINATA_GATEWAY;\n}\n\n/**\n * Upload JSON to IPFS via the Sherwood API (server-side Pinata).\n * Returns the IPFS URI (ipfs://Qm...).\n */\nasync function uploadToIPFS(content: Record<string, unknown>, name: string): Promise<string> {\n const url = getUploadApiUrl();\n\n // Transient \"fetch failed\" / cold-start 5xx from the pin API shouldn't kill\n // a propose flow — retry briefly before surfacing (vnet e2e finding).\n const attempts = 3;\n let lastErr: unknown;\n for (let i = 0; i < attempts; i++) {\n try {\n const response = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ content, name }),\n });\n\n if (!response.ok) {\n const text = await response.text();\n // 4xx won't improve on retry; 5xx might.\n if (response.status < 500) throw new Error(`IPFS upload failed (${response.status}): ${text}`);\n lastErr = new Error(`IPFS upload failed (${response.status}): ${text}`);\n } else {\n const result = (await response.json()) as { ipfsHash: string };\n return `ipfs://${result.ipfsHash}`;\n }\n } catch (err) {\n if (err instanceof Error && err.message.startsWith(\"IPFS upload failed (4\")) throw err;\n lastErr = err;\n }\n if (i < attempts - 1) await new Promise((r) => setTimeout(r, 2000 * (i + 1)));\n }\n throw lastErr instanceof Error ? lastErr : new Error(`IPFS upload failed: ${String(lastErr)}`);\n}\n\n/**\n * Pin arbitrary JSON to IPFS.\n * Used for research results and other generic JSON payloads.\n * Returns the IPFS URI (ipfs://Qm...).\n */\nexport async function pinJSON(content: Record<string, unknown>, name: string): Promise<string> {\n return uploadToIPFS(content, name);\n}\n\n/**\n * Upload fund metadata to IPFS.\n * Returns the IPFS URI (ipfs://Qm...).\n */\nexport async function uploadMetadata(metadata: FundMetadata): Promise<string> {\n const name = `sherwood-fund-${metadata.name.toLowerCase().replace(/\\s+/g, \"-\")}`;\n return uploadToIPFS(metadata as unknown as Record<string, unknown>, name);\n}\n\n/**\n * Fetch and parse metadata from an IPFS URI.\n * Supports ipfs:// protocol URIs and raw CIDs.\n */\nexport async function fetchMetadata(ipfsURI: string): Promise<FundMetadata> {\n const gateway = getPinataGateway();\n let cid: string;\n\n if (ipfsURI.startsWith(\"ipfs://\")) {\n cid = ipfsURI.slice(7);\n } else if (ipfsURI.startsWith(\"Qm\") || ipfsURI.startsWith(\"bafy\")) {\n cid = ipfsURI;\n } else {\n throw new Error(`Invalid IPFS URI: ${ipfsURI}`);\n }\n\n const url = `${gateway}/ipfs/${cid}`;\n const response = await fetch(url);\n\n if (!response.ok) {\n throw new Error(`Failed to fetch metadata from ${url} (${response.status})`);\n }\n\n return (await response.json()) as FundMetadata;\n}\n\n/**\n * Merge flag-driven overrides onto the fund's CURRENT metadata.\n *\n * `update-metadata` used to rebuild the JSON from scratch, silently dropping\n * any field not re-supplied by a flag — notably `xmtpGroupId`, which is the\n * ONLY group-discovery path for the dashboard on ENS-less chains (issue #458).\n *\n * Semantics: flags (`name`/`description`) win; everything else on `current`\n * (`xmtpGroupId`, `terms`, `links`, `strategies`, and any unknown keys) is\n * preserved. Unknown keys survive because the spread of `current` is a runtime\n * copy of every own-enumerable property, not just the ones in `FundMetadata`.\n * Pass `current = null` (e.g. when the fetch failed) to fall back to the old\n * build-from-scratch behavior.\n */\nexport function mergeFundMetadata(\n current: Partial<FundMetadata> | null | undefined,\n overrides: {\n name?: string;\n description?: string;\n subdomain: string;\n defaultChain: string;\n },\n): FundMetadata {\n const base = { ...(current ?? {}) } as Partial<FundMetadata> & Record<string, unknown>;\n const name = overrides.name || base.name || overrides.subdomain;\n const description =\n overrides.description ||\n base.description ||\n `${name} — a Sherwood fund on ${overrides.subdomain}.sherwoodagent.eth`;\n return {\n ...base,\n schema: base.schema || \"sherwood/fund/v1\",\n name,\n description,\n chain: base.chain || overrides.defaultChain,\n strategies: base.strategies ?? [],\n terms: base.terms ?? {},\n links: base.links ?? {},\n };\n}\n\n/**\n * Resolve a metadata URI (ipfs:// or data: base64) to name + description.\n * Returns null on any error — callers should treat enrichment as best-effort.\n */\nexport async function resolveMetadataSummary(\n uri: string,\n): Promise<{ name: string; description: string } | null> {\n try {\n if (uri.startsWith(\"data:application/json;base64,\")) {\n const b64 = uri.slice(\"data:application/json;base64,\".length);\n const json = JSON.parse(Buffer.from(b64, \"base64\").toString(\"utf-8\"));\n return { name: json.name || \"\", description: json.description || \"\" };\n }\n const meta = await fetchMetadata(uri);\n return { name: meta.name, description: meta.description };\n } catch {\n return null;\n }\n}\n"],"mappings":"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","names":[]}
@@ -7,7 +7,7 @@ import {
7
7
  } from "./chunk-BJ4G3TPP.js";
8
8
  import {
9
9
  resolveMetadataSummary
10
- } from "./chunk-XDGCHURW.js";
10
+ } from "./chunk-VR4VHX4D.js";
11
11
 
12
12
  // src/lib/events.ts
13
13
  import { parseAbiItem } from "viem";
@@ -170,4 +170,4 @@ export {
170
170
  getCurrentBlock,
171
171
  enrichProposalEvents
172
172
  };
173
- //# sourceMappingURL=chunk-MAG63U53.js.map
173
+ //# sourceMappingURL=chunk-WUYJ7AS6.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  getLogsChunked
3
- } from "./chunk-MAG63U53.js";
3
+ } from "./chunk-WUYJ7AS6.js";
4
4
  import {
5
5
  TOKENS
6
6
  } from "./chunk-XW6NDXBA.js";
@@ -557,4 +557,4 @@ export {
557
557
  registerAgent,
558
558
  getVaultInfo
559
559
  };
560
- //# sourceMappingURL=chunk-2LUTKS24.js.map
560
+ //# sourceMappingURL=chunk-Z7GRB3OQ.js.map
package/dist/index.js CHANGED
@@ -38,8 +38,8 @@ import {
38
38
  removeDepositor,
39
39
  setAgentFeeBps,
40
40
  setVaultAddress
41
- } from "./chunk-2LUTKS24.js";
42
- import "./chunk-MAG63U53.js";
41
+ } from "./chunk-Z7GRB3OQ.js";
42
+ import "./chunk-WUYJ7AS6.js";
43
43
  import {
44
44
  applySlippage,
45
45
  assetDecimalsForSymbol,
@@ -183,7 +183,7 @@ import {
183
183
  fetchMetadata,
184
184
  mergeFundMetadata,
185
185
  uploadMetadata
186
- } from "./chunk-XDGCHURW.js";
186
+ } from "./chunk-VR4VHX4D.js";
187
187
 
188
188
  // src/index.ts
189
189
  import { config as loadDotenv } from "dotenv";
@@ -315,13 +315,17 @@ var CHAIN_IDS = {
315
315
  BASE: 8453,
316
316
  HYPEREVM: 999,
317
317
  ROBINHOOD: 4663,
318
- ROBINHOOD_L2: 46630
318
+ ROBINHOOD_L2: 46630,
319
+ // Tenderly fork of Robinhood mainnet (USDG + Uniswap v3+v4) — mainnet-faithful
320
+ // e2e + guardian-sim environment. Ephemeral vnet; addresses in addresses.ts.
321
+ ROBINHOOD_FORK: 9994663
319
322
  };
320
323
  var SUPPORTED_CHAIN_IDS = [
321
324
  CHAIN_IDS.BASE,
322
325
  CHAIN_IDS.HYPEREVM,
323
326
  CHAIN_IDS.ROBINHOOD,
324
- CHAIN_IDS.ROBINHOOD_L2
327
+ CHAIN_IDS.ROBINHOOD_L2,
328
+ CHAIN_IDS.ROBINHOOD_FORK
325
329
  ];
326
330
 
327
331
  // ../sdk/dist/errors.js
@@ -1179,11 +1183,38 @@ var ROBINHOOD_L2 = {
1179
1183
  explorer: "https://explorer.testnet.chain.robinhood.com",
1180
1184
  rpcs: ["https://rpc.testnet.chain.robinhood.com"]
1181
1185
  };
1186
+ var ROBINHOOD_FORK = {
1187
+ chainId: CHAIN_IDS.ROBINHOOD_FORK,
1188
+ name: "Robinhood Chain (fork)",
1189
+ slug: "robinhood-fork",
1190
+ sherwood: {
1191
+ factory: "0xD9E2F732cc30bC87303E2b9E9fD2f19966D9eDc2",
1192
+ guardianRegistry: "0x8Cc7E69708B551221B831e1C2BAc473860DffA1A",
1193
+ vaultImpl: "0xdfe3176c09163043157D2741b9ed1C66F249D62B",
1194
+ batchExecutorLib: "0x6B57335d93A2cDCcB14C25Bf7497834ac53A0Ab2",
1195
+ strategyFactory: "0x8599ECDdEC4C969ec9E1f3AEE894afd70365AaC2"
1196
+ },
1197
+ // No ERC-8004 registry and no EAS path on the Robinhood fork.
1198
+ identityRegistry: ZERO_ADDRESS,
1199
+ eas: NO_EAS,
1200
+ tokens: {
1201
+ weth: {
1202
+ address: "0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73",
1203
+ symbol: "WETH",
1204
+ decimals: 18
1205
+ }
1206
+ },
1207
+ explorer: "https://dashboard.tenderly.co",
1208
+ rpcs: [
1209
+ "https://virtual.robinhood-chain.eu.rpc.tenderly.co/moonwell/wormhole-bridge/f4e186"
1210
+ ]
1211
+ };
1182
1212
  var REGISTRY = {
1183
1213
  [CHAIN_IDS.BASE]: BASE,
1184
1214
  [CHAIN_IDS.HYPEREVM]: HYPEREVM,
1185
1215
  [CHAIN_IDS.ROBINHOOD]: ROBINHOOD,
1186
- [CHAIN_IDS.ROBINHOOD_L2]: ROBINHOOD_L2
1216
+ [CHAIN_IDS.ROBINHOOD_L2]: ROBINHOOD_L2,
1217
+ [CHAIN_IDS.ROBINHOOD_FORK]: ROBINHOOD_FORK
1187
1218
  };
1188
1219
  function getDeployment(chainId) {
1189
1220
  const entry = REGISTRY[chainId];
@@ -2663,7 +2694,7 @@ function registerStrategyTemplateCommands(strategy2) {
2663
2694
  process.exit(1);
2664
2695
  }
2665
2696
  const { propose: propose2 } = await import("./governor-AL2XUGBE.js");
2666
- const { pinJSON } = await import("./ipfs-RWSTXTZM.js");
2697
+ const { pinJSON } = await import("./ipfs-EJ7IHXCU.js");
2667
2698
  const { parseDuration: parseDuration2 } = await import("./governor-AL2XUGBE.js");
2668
2699
  const strategyDuration = parseDuration2(opts.duration);
2669
2700
  const metaSpinner = ora("Pinning metadata to IPFS...").start();
@@ -2696,7 +2727,7 @@ function registerStrategyTemplateCommands(strategy2) {
2696
2727
  metadataURI = `data:application/json;base64,${Buffer.from(inline).toString("base64")}`;
2697
2728
  }
2698
2729
  try {
2699
- const { getAgentFeeBps: getAgentFeeBps2 } = await import("./vault-QKURBBSL.js");
2730
+ const { getAgentFeeBps: getAgentFeeBps2 } = await import("./vault-KE5TKCSY.js");
2700
2731
  const feeBps = await getAgentFeeBps2(vault);
2701
2732
  console.log(
2702
2733
  chalk.yellow(
@@ -5025,13 +5056,12 @@ function safeCall(fn) {
5025
5056
  }
5026
5057
  }
5027
5058
  function getApiBaseUrl() {
5028
- if (process.env.SHERWOOD_API_URL) return process.env.SHERWOOD_API_URL;
5029
- return getChain().testnet ? "https://testnet.sherwood.sh" : "https://www.sherwood.sh";
5059
+ return process.env.SHERWOOD_API_URL ?? "https://api.sherwood.sh";
5030
5060
  }
5031
5061
  async function simulateViaApi(vault, calls) {
5032
5062
  const baseUrl = getApiBaseUrl();
5033
5063
  const chainId = getChain().id;
5034
- const response = await fetch(`${baseUrl}/api/simulate`, {
5064
+ const response = await fetch(`${baseUrl}/simulate`, {
5035
5065
  method: "POST",
5036
5066
  headers: { "Content-Type": "application/json" },
5037
5067
  body: JSON.stringify({
@@ -9664,7 +9694,7 @@ try {
9664
9694
  } catch {
9665
9695
  }
9666
9696
  var require2 = createRequire(import.meta.url);
9667
- var CLI_VERSION = "0.80.0";
9697
+ var CLI_VERSION = "0.81.0";
9668
9698
  async function loadXmtp() {
9669
9699
  return import("./xmtp-M2OBCCNR.js");
9670
9700
  }
@@ -11024,7 +11054,7 @@ ${info.name} (${info.type})`);
11024
11054
  }
11025
11055
  });
11026
11056
  try {
11027
- const { registerChatCommands } = await import("./chat-56DDAGA2.js");
11057
+ const { registerChatCommands } = await import("./chat-ANE3SNHH.js");
11028
11058
  registerChatCommands(program);
11029
11059
  } catch {
11030
11060
  program.command("chat <name> [action] [actionArgs...]").description("Fund chat (XMTP) \u2014 requires @xmtp/cli").action(() => {
@@ -11034,7 +11064,7 @@ try {
11034
11064
  process.exit(1);
11035
11065
  });
11036
11066
  }
11037
- var { registerSessionCommands } = await import("./session-RSWSCMM5.js");
11067
+ var { registerSessionCommands } = await import("./session-BE52OSEV.js");
11038
11068
  registerSessionCommands(program);
11039
11069
  registerVeniceCommands(program);
11040
11070
  registerAllowanceCommands(program);
@@ -11043,7 +11073,7 @@ registerProposalCommands(program);
11043
11073
  registerQueueCommands(program);
11044
11074
  registerGovernorCommands(program);
11045
11075
  registerGuardianCommands(program);
11046
- var { registerResearchCommands } = await import("./research-ICDDAAGV.js");
11076
+ var { registerResearchCommands } = await import("./research-IFMAQWCH.js");
11047
11077
  registerResearchCommands(program);
11048
11078
  var { registerAgentCommands } = await import("./agent-VLYILEUP.js");
11049
11079
  registerAgentCommands(program);