@sherwoodagent/cli 0.86.1 → 0.87.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 (71) hide show
  1. package/dist/{abis-WVW2EBI3.js → abis-WJQ6IVYV.js} +2 -2
  2. package/dist/{agent-TBLC3WNJ.js → agent-A2JEYGQS.js} +7 -7
  3. package/dist/{chat-ETZSKQDI.js → chat-OZAAN5LT.js} +8 -8
  4. package/dist/{chunk-ZN2MHIB7.js → chunk-37GT3TJX.js} +5 -5
  5. package/dist/{chunk-45FELUWY.js → chunk-3UYGXGMF.js} +2 -2
  6. package/dist/{chunk-YAS52NEF.js → chunk-CU42ZD4K.js} +5 -5
  7. package/dist/chunk-CU42ZD4K.js.map +1 -0
  8. package/dist/{chunk-PVTZMRC6.js → chunk-G3FUEM5N.js} +2 -2
  9. package/dist/chunk-G3FUEM5N.js.map +1 -0
  10. package/dist/{chunk-XPVXNG2K.js → chunk-GR3GSU3I.js} +6 -6
  11. package/dist/{chunk-KVB5P2OE.js → chunk-IINWI3LD.js} +2 -2
  12. package/dist/{chunk-F3MDCUGO.js → chunk-J2IZWAEW.js} +75 -227
  13. package/dist/chunk-J2IZWAEW.js.map +1 -0
  14. package/dist/{chunk-3IAZQMAW.js → chunk-JGD6A2Q4.js} +29 -82
  15. package/dist/chunk-JGD6A2Q4.js.map +1 -0
  16. package/dist/{chunk-QRMZRAMG.js → chunk-MIAMGVZ4.js} +8 -8
  17. package/dist/chunk-MIAMGVZ4.js.map +1 -0
  18. package/dist/{chunk-EA65CDQH.js → chunk-R6F57QQF.js} +14 -23
  19. package/dist/chunk-R6F57QQF.js.map +1 -0
  20. package/dist/{chunk-EVUKJ7CJ.js → chunk-TTF5TDRV.js} +5 -5
  21. package/dist/{chunk-IAM4VIU2.js → chunk-UOIAY6ZG.js} +6 -39
  22. package/dist/chunk-UOIAY6ZG.js.map +1 -0
  23. package/dist/{chunk-6QBGTX2Q.js → chunk-V7TNYHIK.js} +257 -484
  24. package/dist/chunk-V7TNYHIK.js.map +1 -0
  25. package/dist/{chunk-OUYMZ5ZC.js → chunk-W3XWRWML.js} +5 -5
  26. package/dist/{client-3SE632Q2.js → client-C6N2ASTH.js} +3 -3
  27. package/dist/{eas-KMDAMLXW.js → eas-VFTWEI4K.js} +6 -6
  28. package/dist/{governor-JNSWPJVQ.js → governor-HVBSI6Z2.js} +6 -6
  29. package/dist/identity-OLD25QEP.js +18 -0
  30. package/dist/index.js +91 -305
  31. package/dist/index.js.map +1 -1
  32. package/dist/{network-FEHRFDPJ.js → network-7445KSCF.js} +2 -2
  33. package/dist/{price-YNPYE2EO.js → price-O3THX2HL.js} +6 -6
  34. package/dist/{providers-BMOHHVUN.js → providers-KZNCCUKT.js} +4 -4
  35. package/dist/{research-W74PNYPO.js → research-ARFBFXIT.js} +7 -7
  36. package/dist/{session-HVRZ6AJM.js → session-A7CYZSSA.js} +14 -12
  37. package/dist/session-A7CYZSSA.js.map +1 -0
  38. package/dist/{trade-EOQY72L7.js → trade-ZCK332E4.js} +15 -15
  39. package/dist/{vault-HWJQJW5U.js → vault-CDI7BELZ.js} +8 -8
  40. package/dist/{xmtp-KW73BGVO.js → xmtp-7LAWDKJT.js} +6 -6
  41. package/package.json +1 -1
  42. package/dist/chunk-3IAZQMAW.js.map +0 -1
  43. package/dist/chunk-6QBGTX2Q.js.map +0 -1
  44. package/dist/chunk-EA65CDQH.js.map +0 -1
  45. package/dist/chunk-F3MDCUGO.js.map +0 -1
  46. package/dist/chunk-IAM4VIU2.js.map +0 -1
  47. package/dist/chunk-PVTZMRC6.js.map +0 -1
  48. package/dist/chunk-QRMZRAMG.js.map +0 -1
  49. package/dist/chunk-YAS52NEF.js.map +0 -1
  50. package/dist/identity-ATWV2O7Y.js +0 -15
  51. package/dist/session-HVRZ6AJM.js.map +0 -1
  52. /package/dist/{abis-WVW2EBI3.js.map → abis-WJQ6IVYV.js.map} +0 -0
  53. /package/dist/{agent-TBLC3WNJ.js.map → agent-A2JEYGQS.js.map} +0 -0
  54. /package/dist/{chat-ETZSKQDI.js.map → chat-OZAAN5LT.js.map} +0 -0
  55. /package/dist/{chunk-ZN2MHIB7.js.map → chunk-37GT3TJX.js.map} +0 -0
  56. /package/dist/{chunk-45FELUWY.js.map → chunk-3UYGXGMF.js.map} +0 -0
  57. /package/dist/{chunk-XPVXNG2K.js.map → chunk-GR3GSU3I.js.map} +0 -0
  58. /package/dist/{chunk-KVB5P2OE.js.map → chunk-IINWI3LD.js.map} +0 -0
  59. /package/dist/{chunk-EVUKJ7CJ.js.map → chunk-TTF5TDRV.js.map} +0 -0
  60. /package/dist/{chunk-OUYMZ5ZC.js.map → chunk-W3XWRWML.js.map} +0 -0
  61. /package/dist/{client-3SE632Q2.js.map → client-C6N2ASTH.js.map} +0 -0
  62. /package/dist/{eas-KMDAMLXW.js.map → eas-VFTWEI4K.js.map} +0 -0
  63. /package/dist/{governor-JNSWPJVQ.js.map → governor-HVBSI6Z2.js.map} +0 -0
  64. /package/dist/{identity-ATWV2O7Y.js.map → identity-OLD25QEP.js.map} +0 -0
  65. /package/dist/{network-FEHRFDPJ.js.map → network-7445KSCF.js.map} +0 -0
  66. /package/dist/{price-YNPYE2EO.js.map → price-O3THX2HL.js.map} +0 -0
  67. /package/dist/{providers-BMOHHVUN.js.map → providers-KZNCCUKT.js.map} +0 -0
  68. /package/dist/{research-W74PNYPO.js.map → research-ARFBFXIT.js.map} +0 -0
  69. /package/dist/{trade-EOQY72L7.js.map → trade-ZCK332E4.js.map} +0 -0
  70. /package/dist/{vault-HWJQJW5U.js.map → vault-CDI7BELZ.js.map} +0 -0
  71. /package/dist/{xmtp-KW73BGVO.js.map → xmtp-7LAWDKJT.js.map} +0 -0
@@ -15,7 +15,7 @@ import {
15
15
  SYNTHRA_QUOTER_ABI,
16
16
  UNISWAP_QUOTER_V2_ABI,
17
17
  VENICE_STAKING_ABI
18
- } from "./chunk-F3MDCUGO.js";
18
+ } from "./chunk-J2IZWAEW.js";
19
19
  export {
20
20
  BASE_STRATEGY_ABI,
21
21
  EAS_ABI,
@@ -34,4 +34,4 @@ export {
34
34
  UNISWAP_QUOTER_V2_ABI,
35
35
  VENICE_STAKING_ABI
36
36
  };
37
- //# sourceMappingURL=abis-WVW2EBI3.js.map
37
+ //# sourceMappingURL=abis-WJQ6IVYV.js.map
@@ -12,7 +12,7 @@ import {
12
12
  import {
13
13
  getResearchProvider,
14
14
  isX402WalletFunded
15
- } from "./chunk-45FELUWY.js";
15
+ } from "./chunk-3UYGXGMF.js";
16
16
  import {
17
17
  HyperliquidProvider,
18
18
  calculateATR,
@@ -29,9 +29,9 @@ import {
29
29
  } from "./chunk-DBOINZYU.js";
30
30
  import {
31
31
  chatCompletion
32
- } from "./chunk-KVB5P2OE.js";
33
- import "./chunk-QRMZRAMG.js";
34
- import "./chunk-PVTZMRC6.js";
32
+ } from "./chunk-IINWI3LD.js";
33
+ import "./chunk-MIAMGVZ4.js";
34
+ import "./chunk-G3FUEM5N.js";
35
35
  import {
36
36
  getVeniceApiKey
37
37
  } from "./chunk-3TZIOAPH.js";
@@ -5573,8 +5573,8 @@ var PortfolioTracker = class {
5573
5573
  }
5574
5574
  try {
5575
5575
  const { createPublicClient, http } = await import("viem");
5576
- const { getChain } = await import("./network-FEHRFDPJ.js");
5577
- const { BASE_STRATEGY_ABI, SYNDICATE_VAULT_ABI } = await import("./abis-WVW2EBI3.js");
5576
+ const { getChain } = await import("./network-7445KSCF.js");
5577
+ const { BASE_STRATEGY_ABI, SYNDICATE_VAULT_ABI } = await import("./abis-WJQ6IVYV.js");
5578
5578
  void chain;
5579
5579
  const client = createPublicClient({
5580
5580
  chain: getChain(),
@@ -9550,4 +9550,4 @@ function formatFearGreed(value) {
9550
9550
  export {
9551
9551
  registerAgentCommands
9552
9552
  };
9553
- //# sourceMappingURL=agent-TBLC3WNJ.js.map
9553
+ //# sourceMappingURL=agent-A2JEYGQS.js.map
@@ -1,25 +1,25 @@
1
1
  import {
2
2
  getFund,
3
3
  updateMetadata
4
- } from "./chunk-EVUKJ7CJ.js";
4
+ } from "./chunk-TTF5TDRV.js";
5
5
  import {
6
6
  getTextRecord,
7
7
  resolveFund,
8
8
  setTextRecord
9
- } from "./chunk-ZN2MHIB7.js";
9
+ } from "./chunk-37GT3TJX.js";
10
10
  import {
11
11
  ENS
12
- } from "./chunk-IAM4VIU2.js";
12
+ } from "./chunk-UOIAY6ZG.js";
13
13
  import {
14
14
  formatContractError,
15
15
  getAccount
16
- } from "./chunk-QRMZRAMG.js";
17
- import "./chunk-PVTZMRC6.js";
16
+ } from "./chunk-MIAMGVZ4.js";
17
+ import "./chunk-G3FUEM5N.js";
18
18
  import {
19
19
  cacheGroupId,
20
20
  getCachedGroupId
21
21
  } from "./chunk-3TZIOAPH.js";
22
- import "./chunk-F3MDCUGO.js";
22
+ import "./chunk-J2IZWAEW.js";
23
23
  import {
24
24
  fetchMetadata,
25
25
  uploadMetadata
@@ -29,7 +29,7 @@ import {
29
29
  import chalk from "chalk";
30
30
  import ora from "ora";
31
31
  async function loadXmtp() {
32
- return import("./xmtp-KW73BGVO.js");
32
+ return import("./xmtp-7LAWDKJT.js");
33
33
  }
34
34
  function formatTimestamp(date) {
35
35
  return `${date.getHours().toString().padStart(2, "0")}:${date.getMinutes().toString().padStart(2, "0")}`;
@@ -563,4 +563,4 @@ function registerChatCommands(program) {
563
563
  export {
564
564
  registerChatCommands
565
565
  };
566
- //# sourceMappingURL=chat-ETZSKQDI.js.map
566
+ //# sourceMappingURL=chat-OZAAN5LT.js.map
@@ -1,18 +1,18 @@
1
1
  import {
2
2
  ENS,
3
3
  SHERWOOD
4
- } from "./chunk-IAM4VIU2.js";
4
+ } from "./chunk-UOIAY6ZG.js";
5
5
  import {
6
6
  getPublicClient
7
- } from "./chunk-QRMZRAMG.js";
7
+ } from "./chunk-MIAMGVZ4.js";
8
8
  import {
9
9
  VALID_NETWORKS,
10
10
  withNetwork
11
- } from "./chunk-PVTZMRC6.js";
11
+ } from "./chunk-G3FUEM5N.js";
12
12
  import {
13
13
  L2_REGISTRY_ABI,
14
14
  SYNDICATE_FACTORY_ABI
15
- } from "./chunk-F3MDCUGO.js";
15
+ } from "./chunk-J2IZWAEW.js";
16
16
 
17
17
  // src/lib/ens.ts
18
18
  import { namehash } from "viem/ens";
@@ -111,4 +111,4 @@ export {
111
111
  setTextRecord,
112
112
  getTextRecord
113
113
  };
114
- //# sourceMappingURL=chunk-ZN2MHIB7.js.map
114
+ //# sourceMappingURL=chunk-37GT3TJX.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  getAccount
3
- } from "./chunk-QRMZRAMG.js";
3
+ } from "./chunk-MIAMGVZ4.js";
4
4
 
5
5
  // src/lib/x402.ts
6
6
  var _x402Fetch = null;
@@ -635,4 +635,4 @@ export {
635
635
  NansenProvider,
636
636
  getResearchProvider
637
637
  };
638
- //# sourceMappingURL=chunk-45FELUWY.js.map
638
+ //# sourceMappingURL=chunk-3UYGXGMF.js.map
@@ -1,20 +1,20 @@
1
1
  import {
2
2
  SHERWOOD
3
- } from "./chunk-IAM4VIU2.js";
3
+ } from "./chunk-UOIAY6ZG.js";
4
4
  import {
5
5
  getAccount,
6
6
  getPublicClient,
7
7
  waitForReceipt,
8
8
  writeContractWithRetry
9
- } from "./chunk-QRMZRAMG.js";
9
+ } from "./chunk-MIAMGVZ4.js";
10
10
  import {
11
11
  getChain
12
- } from "./chunk-PVTZMRC6.js";
12
+ } from "./chunk-G3FUEM5N.js";
13
13
  import {
14
14
  PROTOCOL_CONFIG_ABI,
15
15
  SYNDICATE_FACTORY_ABI,
16
16
  SYNDICATE_GOVERNOR_ABI
17
- } from "./chunk-F3MDCUGO.js";
17
+ } from "./chunk-J2IZWAEW.js";
18
18
 
19
19
  // src/lib/governor.ts
20
20
  import { parseEventLogs } from "viem";
@@ -494,4 +494,4 @@ export {
494
494
  setMgmtSplit,
495
495
  setPerfSplit
496
496
  };
497
- //# sourceMappingURL=chunk-YAS52NEF.js.map
497
+ //# sourceMappingURL=chunk-CU42ZD4K.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/governor.ts","../src/lib/generated/proposal-state.ts"],"sourcesContent":["/**\n * Governor contract wrapper — reads/writes to SyndicateGovernor.\n *\n * Per-vault governor design: the factory deploys ONE governor per vault\n * (BeaconProxy). Every helper takes the vault address and resolves its\n * governor via `factory.governorOf(vault)` (memoized per chain+vault —\n * the binding is set once at createSyndicate and never changes).\n *\n * Protocol-wide fee parameters (protocol/guardian fee bps + recipients)\n * live on the separate ProtocolConfig contract, resolved via\n * `factory.protocolConfig()`.\n */\n\nimport type { Address, Hex, Log } from \"viem\";\nimport { parseEventLogs } from \"viem\";\nimport { getPublicClient, getAccount, writeContractWithRetry, waitForReceipt } from \"./client.js\";\nimport { getChain } from \"./network.js\";\nimport { SHERWOOD } from \"./addresses.js\";\nimport { SYNDICATE_GOVERNOR_ABI, SYNDICATE_FACTORY_ABI, PROTOCOL_CONFIG_ABI } from \"./abis.js\";\nimport { PROPOSAL_STATE, PROPOSAL_STATES } from \"./generated/proposal-state.js\";\n\n// ── Types ──\n\nexport interface GovernorParams {\n votingPeriod: bigint;\n executionWindow: bigint;\n vetoThresholdBps: bigint;\n maxPerformanceFeeBps: bigint;\n cooldownPeriod: bigint;\n collaborationWindow: bigint;\n maxCoProposers: bigint;\n minStrategyDuration: bigint;\n maxStrategyDuration: bigint;\n}\n\nexport interface StrategyProposal {\n id: bigint;\n proposer: Address;\n vault: Address;\n /** Strategy contract address whose `positionValue()` the vault polls\n * for live NAV. Set at propose time, immutable thereafter. address(0)\n * for queue-only proposals (no live NAV). */\n strategy: Address;\n metadataURI: string;\n /** Agent fee (bps) snapshotted from the vault's `agentFeeBps` at propose. */\n performanceFeeBps: bigint;\n strategyDuration: bigint;\n /** AGAINST weight only. The FOR/ABSTAIN tallies are gone: optimistic\n * governance never needed them, so the turnout denominator is the\n * `votableSupply` snapshot at the bottom of this tuple. */\n votesAgainst: bigint;\n snapshotTimestamp: bigint;\n voteEnd: bigint;\n reviewEnd: bigint;\n executeBy: bigint;\n executedAt: bigint;\n state: number;\n vetoThresholdBps: bigint;\n /** Fee-recipient snapshot taken from ProtocolConfig at propose time.\n *\n * THE FLAT `snapshot*FeeBps` SCALARS AND `selfManagesFees` ARE GONE: the\n * splits became structs (`snapshotMgmtSplit`/`snapshotPerfSplit` below) and\n * self-managed fees were removed outright. Every field below is positional\n * in the on-chain tuple — omitting or reordering one corrupts the decode of\n * everything after it. */\n snapshotProtocolFeeRecipient: Address;\n snapshotGuardiansFeeRecipient: Address;\n /** Risk envelope declared at propose: the net-outflow ceiling the execute\n * batch is metered against. */\n maxCapital: bigint;\n /** Declared drawdown bound, bps of `effectiveMaxCapital`. */\n maxDrawdownBps: number;\n /** Tier the envelope resolved to; drives how much coverage is required. */\n envelopeTier: number;\n requiredCoverage: bigint;\n /** WOOD bond pulled from the proposer at propose, held by the escrow. */\n proposerBondWood: bigint;\n proposerBondEscrow: Address;\n /** Management-fee split snapshotted from ProtocolConfig at propose. */\n snapshotMgmtSplit: { agentBps: number; protocolBps: number; guardianBps: number };\n /** Performance-fee split snapshotted from ProtocolConfig at propose. */\n snapshotPerfSplit: { agentBps: number; protocolBps: number; guardianBps: number; ownerBps: number };\n /** The ledger the bond's reclaim gates read — bound alongside the escrow so\n * re-pointing either slot later cannot strand the bond. */\n proposerBondLedger: Address;\n /** `maxCapital` after any scaling applied at execute. */\n effectiveMaxCapital: bigint;\n /** Total vote weight eligible at `snapshotTimestamp` — the denominator the\n * veto threshold is measured against. */\n votableSupply: bigint;\n}\n\nexport interface CoProposer {\n agent: Address;\n splitBps: bigint;\n}\n\nexport interface BatchCall {\n target: Address;\n data: Hex;\n value: bigint;\n}\n\n// ProposalState ordering is code-generated from the Solidity enum\n// (contracts/src/interfaces/ISyndicateGovernor.sol) — `npm run codegen`.\n// History: PR #229 inserted GuardianReview at index 2 and this hand-kept\n// mirror drifted for ~2 months, mislabeling Approved (3) as Rejected and\n// making `proposal execute` reject valid approved proposals. The generated\n// module (checked by codegen-drift.test.ts + CI) makes that impossible.\nexport { PROPOSAL_STATE, PROPOSAL_STATES };\n\nexport const VOTE_TYPE = {\n For: 0,\n Against: 1,\n Abstain: 2,\n} as const;\n\n// ── Client-side action gates (mirror SyndicateGovernor) ──\n//\n// The governor's mutating entrypoints resolve state INLINE and can act on a\n// state the read-only `getProposalState` view is still reporting as\n// GuardianReview. The client gates below reproduce that divergence so the CLI\n// stops refusing txs the contract would accept (issue #452).\n\n/** Result of the `proposal execute` client gate. */\nexport type ExecuteGate =\n | { kind: \"send\" } // state == Approved — straightforward execute.\n | { kind: \"send-self-resolve\" } // GuardianReview, window elapsed, still within\n // the execution window — executeProposal\n // self-resolves the (cold-start) review inline.\n | { kind: \"refuse-review-open\" } // GuardianReview, review window still open — the\n // tx WOULD revert (ProposalNotApproved).\n | { kind: \"refuse-expired\" } // GuardianReview past executeBy — the inline\n // self-resolve maps to Expired, tx WOULD revert.\n | { kind: \"refuse-state\" }; // any other non-executable state.\n\n/**\n * Decide whether `executeProposal(id)` should be broadcast.\n *\n * Mirrors `SyndicateGovernor.executeProposal` (contracts/src/SyndicateGovernor.sol:342)\n * vs. the `getProposalState` view:\n * - The view (`_resolveStateView` @824 / `_resolveAfterVote` @865) keeps\n * reporting `GuardianReview` once the review window elapses but the registry\n * has not cached a resolution — a zero-guardian / never-opened cold-start\n * review NEVER auto-opens, so the view is stuck there indefinitely.\n * - `executeProposal` runs the MUTATING `_resolveState` (@789) which, when the\n * window elapsed (`now > reviewEnd`), calls `registry.resolveReview` inline\n * (cold-start ⇒ blocked=false) and maps to Approved when `now <= executeBy`\n * (else Expired) — then executes in the same tx.\n * Invariant `voteEnd < reviewEnd < executeBy` (@528-530) holds for any past-vote\n * proposal, so `reviewEnd`/`executeBy` are always populated in the GuardianReview\n * branch.\n *\n * `now` MUST be chain time (latest block timestamp), not wall-clock — on a\n * time-warped vnet the two diverge and the contract compares against chain time.\n */\nexport function evaluateExecuteGate(args: {\n state: number;\n reviewEnd: bigint;\n executeBy: bigint;\n now: bigint;\n}): ExecuteGate {\n const { state, reviewEnd, executeBy, now } = args;\n if (state === PROPOSAL_STATE.Approved) return { kind: \"send\" };\n if (state === PROPOSAL_STATE.GuardianReview) {\n if (now <= reviewEnd) return { kind: \"refuse-review-open\" };\n if (now > executeBy) return { kind: \"refuse-expired\" };\n return { kind: \"send-self-resolve\" };\n }\n return { kind: \"refuse-state\" };\n}\n\n/**\n * Classification for the `resolve-reviews` keeper.\n * - `resolvable`: an OPENED, unresolved review past its window — needs a real\n * `resolveReview` tx (computes block quorum, may slash approvers).\n * - `cold-start`: an UNOPENED, unresolved review past its window — the\n * zero-guardian case. `resolveReview` would only mark it resolved/not-blocked\n * (GuardianRegistry.resolveReview @639-643), which `executeProposal`\n * already does inline, so the keeper should report it (pointing at\n * `proposal execute`) rather than spend a redundant tx.\n * - `none`: not past window yet, or already resolved.\n */\nexport type ReviewResolveClass = \"resolvable\" | \"cold-start\" | \"none\";\n\nexport function classifyReview(args: {\n opened: boolean;\n resolved: boolean;\n reviewEnd: bigint;\n now: bigint;\n}): ReviewResolveClass {\n const { opened, resolved, reviewEnd, now } = args;\n const pastWindow = reviewEnd > 0n && now >= reviewEnd;\n if (!pastWindow || resolved) return \"none\";\n return opened ? \"resolvable\" : \"cold-start\";\n}\n\n/**\n * Classification for the `open-reviews` keeper (SHE-162), the other leg of\n * `classifyReview`: `GuardianRegistry.openReview(governor, proposalId)` is\n * permissionless, and an unopened review clears by default (`outcomeOf`:\n * `if (!r.opened) return ReviewOutcome.Cleared;`) — nobody opening it means\n * proposals execute unreviewed.\n * - `openable`: a registered, unopened, unresolved review inside the open\n * window `[voteEnd, reviewEnd)` — needs an `openReview` keeper tx.\n * - `none`: never registered (collapsed window, `reviewEnd <= voteEnd`),\n * already opened or resolved, or outside the window. Past `reviewEnd`\n * opening is pointless — that is `classifyReview`'s territory.\n */\nexport type ReviewOpenClass = \"openable\" | \"none\";\n\nexport function classifyReviewOpen(args: {\n opened: boolean;\n resolved: boolean;\n voteEnd: bigint;\n reviewEnd: bigint;\n now: bigint;\n}): ReviewOpenClass {\n const { opened, resolved, voteEnd, reviewEnd, now } = args;\n // Collapsed window ⇒ the review was never registered with the registry;\n // openReview would revert ReviewNotOpen (r.voteEnd == 0).\n const registered = voteEnd > 0n && reviewEnd > voteEnd;\n // Contract gate is `now >= voteEnd` (inclusive); past reviewEnd the open\n // is moot — the review resolves/clears without it.\n const inWindow = now >= voteEnd && now < reviewEnd;\n if (!registered || !inWindow || opened || resolved) return \"none\";\n return \"openable\";\n}\n\n/**\n * Per-proposal scan step shared by the `open-reviews` / `resolve-reviews`\n * keepers. Runs `load` for every id concurrently; an id whose load throws is\n * RECORDED in `failures` (id + error), never silently swallowed — a systemic\n * failure (e.g. an ABI mismatch, the SHE-88/SHE-49 class) must surface as\n * \"N of M failed to load\", not as a clean \"nothing to do\". The loadable ids\n * are still returned so the keeper can process every candidate it CAN see.\n */\nexport interface ReviewScanFailure {\n id: bigint;\n error: unknown;\n}\n\nexport async function scanReviewCandidates<T>(\n ids: readonly bigint[],\n load: (id: bigint) => Promise<T>,\n): Promise<{ candidates: T[]; failures: ReviewScanFailure[] }> {\n const failures: ReviewScanFailure[] = [];\n const settled = await Promise.all(\n ids.map(async (id): Promise<{ ok: true; value: T } | { ok: false }> => {\n try {\n return { ok: true, value: await load(id) };\n } catch (error) {\n failures.push({ id, error });\n return { ok: false };\n }\n }),\n );\n const candidates: T[] = [];\n for (const s of settled) if (s.ok) candidates.push(s.value);\n return { candidates, failures };\n}\n\n/**\n * A mined-but-REVERTED tx still yields a receipt — `waitForReceipt` resolves\n * with `status: \"reverted\"` and does not throw. A keeper counting that as a\n * success would report \"opened/resolved\" for a tx that changed nothing. Call\n * this on every keeper receipt: it throws (like a send failure) unless the\n * tx actually succeeded, so the caller's catch path drives the exit code.\n */\nexport function assertReceiptSuccess(receipt: { status: string }): void {\n if (receipt.status !== \"success\") {\n throw new Error(`transaction mined but reverted on-chain (status=${receipt.status})`);\n }\n}\n\n// ── Duration parser ──\n\nexport function parseDuration(input: string): bigint {\n const match = input.match(/^(\\d+)(d|h|m|s)?$/);\n if (!match) throw new Error(`Invalid duration: ${input}`);\n const value = BigInt(match[1]);\n switch (match[2]) {\n case \"d\":\n return value * 86400n;\n case \"h\":\n return value * 3600n;\n case \"m\":\n return value * 60n;\n case \"s\":\n case undefined:\n return value;\n default:\n throw new Error(`Unknown duration unit: ${match[2]}`);\n }\n}\n\n// ── Address helpers ──\n\n// governorOf(vault) is set once at createSyndicate and never rebinds, so\n// it is safe to memoize per chain+vault for the lifetime of the process.\nconst governorCache = new Map<string, Address>();\n\n/** Resolve the per-vault governor via `factory.governorOf(vault)`. */\nexport async function getGovernorOf(vault: Address): Promise<Address> {\n const key = `${getChain().id}:${vault.toLowerCase()}`;\n const cached = governorCache.get(key);\n if (cached) return cached;\n\n const client = getPublicClient();\n const governor = await client.readContract({\n address: SHERWOOD().FACTORY,\n abi: SYNDICATE_FACTORY_ABI,\n functionName: \"governorOf\",\n args: [vault],\n }) as Address;\n\n if (governor === \"0x0000000000000000000000000000000000000000\") {\n throw new Error(`No governor registered for vault ${vault} — is it a factory-created vault?`);\n }\n\n governorCache.set(key, governor);\n return governor;\n}\n\n// ProtocolConfig is a protocol-wide singleton behind the factory — same\n// set-once semantics as governorOf, memoized per chain.\nconst protocolConfigCache = new Map<number, Address>();\n\n/** Resolve the ProtocolConfig address via `factory.protocolConfig()`. */\nexport async function getProtocolConfigAddress(): Promise<Address> {\n const chainId = getChain().id;\n const cached = protocolConfigCache.get(chainId);\n if (cached) return cached;\n\n const client = getPublicClient();\n const config = await client.readContract({\n address: SHERWOOD().FACTORY,\n abi: SYNDICATE_FACTORY_ABI,\n functionName: \"protocolConfig\",\n }) as Address;\n\n protocolConfigCache.set(chainId, config);\n return config;\n}\n\n// ── Read helpers ──\n\nexport async function getGovernorParams(vault: Address): Promise<GovernorParams> {\n const client = getPublicClient();\n const result = await client.readContract({\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"getGovernorParams\",\n }) as {\n votingPeriod: bigint;\n executionWindow: bigint;\n vetoThresholdBps: bigint;\n maxPerformanceFeeBps: bigint;\n cooldownPeriod: bigint;\n collaborationWindow: bigint;\n maxCoProposers: bigint;\n minStrategyDuration: bigint;\n maxStrategyDuration: bigint;\n };\n return result;\n}\n\nexport async function getProposal(vault: Address, id: bigint): Promise<StrategyProposal> {\n const client = getPublicClient();\n const result = await client.readContract({\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"getProposal\",\n args: [id],\n }) as StrategyProposal;\n return result;\n}\n\nexport async function getProposalState(vault: Address, id: bigint): Promise<number> {\n const client = getPublicClient();\n return client.readContract({\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"getProposalState\",\n args: [id],\n }) as Promise<number>;\n}\n\nexport async function proposalCount(vault: Address): Promise<bigint> {\n const client = getPublicClient();\n return client.readContract({\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"proposalCount\",\n }) as Promise<bigint>;\n}\n\nexport async function getVoteWeight(vault: Address, proposalId: bigint, voter: Address): Promise<bigint> {\n const client = getPublicClient();\n return client.readContract({\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"getVoteWeight\",\n args: [proposalId, voter],\n }) as Promise<bigint>;\n}\n\nexport async function hasVoted(vault: Address, proposalId: bigint, voter: Address): Promise<boolean> {\n const client = getPublicClient();\n return client.readContract({\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"hasVoted\",\n args: [proposalId, voter],\n }) as Promise<boolean>;\n}\n\n// `getProposalCalls` (concat of execute + settle) was dropped in V1.5\n// to reclaim governor bytecode under EIP-170. Use `getExecuteCalls`\n// + `getSettlementCalls` instead — same data, no on-chain copy loop.\n\nexport async function getExecuteCalls(vault: Address, proposalId: bigint): Promise<BatchCall[]> {\n const client = getPublicClient();\n const result = await client.readContract({\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"getExecuteCalls\",\n args: [proposalId],\n }) as { target: Address; data: Hex; value: bigint }[];\n return result.map((c) => ({ target: c.target, data: c.data, value: c.value }));\n}\n\nexport async function getSettlementCalls(vault: Address, proposalId: bigint): Promise<BatchCall[]> {\n const client = getPublicClient();\n const result = await client.readContract({\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"getSettlementCalls\",\n args: [proposalId],\n }) as { target: Address; data: Hex; value: bigint }[];\n return result.map((c) => ({ target: c.target, data: c.data, value: c.value }));\n}\n\n// Per-vault governor: `getRegisteredVaults` / `isRegisteredVault` were\n// removed on-chain — a governor serves exactly one vault (`governor.vault()`).\n// Enumerate vaults via the factory (`getAllActiveSyndicates`) instead.\n\nexport async function getActiveProposal(vault: Address): Promise<bigint> {\n const client = getPublicClient();\n return client.readContract({\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"getActiveProposal\",\n }) as Promise<bigint>;\n}\n\nexport async function getCooldownEnd(vault: Address): Promise<bigint> {\n const client = getPublicClient();\n return client.readContract({\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"getCooldownEnd\",\n }) as Promise<bigint>;\n}\n\nexport async function openProposalCount(vault: Address): Promise<bigint> {\n const client = getPublicClient();\n return client.readContract({\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"openProposalCount\",\n }) as Promise<bigint>;\n}\n\nexport async function getCapitalSnapshot(vault: Address, proposalId: bigint): Promise<bigint> {\n const client = getPublicClient();\n return client.readContract({\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"getCapitalSnapshot\",\n args: [proposalId],\n }) as Promise<bigint>;\n}\n\n/**\n * Extract proposalId from ProposalCreated event logs.\n * Returns undefined if the event is not found or parsing fails.\n */\nexport function parseProposalIdFromLogs(logs: Log[]): bigint | undefined {\n try {\n const parsed = parseEventLogs({\n abi: SYNDICATE_GOVERNOR_ABI,\n logs,\n eventName: \"ProposalCreated\",\n });\n return parsed[0]?.args.proposalId;\n } catch {\n return undefined;\n }\n}\n\n// ── Write helpers ──\n\n/**\n * The risk envelope a proposal commits to.\n *\n * `maxCapital` is in ASSET UNITS (the vault's own asset, at its decimals), not\n * a share. `maxDrawdownBps` is the declared loss allowance in basis points,\n * 0..10_000, and is what the settle-price guard sizes its tolerance from — so\n * it is a real declaration to voters and guardians, not a formality.\n */\nexport interface RiskEnvelope {\n maxCapital: bigint;\n maxDrawdownBps: number;\n}\n\n/**\n * @param executeCallCaps one entry per execute call, in ASSET UNITS: the\n * maximum GROSS OUTFLOW of the vault asset measured around that call. A call\n * that moves nothing out (an `approve`, or a settlement that only returns\n * assets) takes 0. Summed per batch and required to be <= `maxCapital`;\n * the execute and settlement batches are bounded independently because they\n * run in separate transactions.\n */\nexport async function propose(\n vault: Address,\n strategy: Address,\n metadataURI: string,\n strategyDuration: bigint,\n envelope: RiskEnvelope,\n executeCalls: BatchCall[],\n executeCallCaps: bigint[],\n settlementCalls: BatchCall[],\n settlementCallCaps: bigint[],\n coProposers: CoProposer[] = [],\n): Promise<{ hash: Hex; proposalId: bigint }> {\n // Fail here rather than as an on-chain `CallCapsLengthMismatch` — the\n // governor's revert names the mismatch but not which batch, and a caller that\n // built the arrays in different places will not know.\n if (executeCallCaps.length !== executeCalls.length) {\n throw new Error(\n `executeCallCaps has ${executeCallCaps.length} entries for ${executeCalls.length} execute calls — every call must declare exactly one cap`,\n );\n }\n if (settlementCallCaps.length !== settlementCalls.length) {\n throw new Error(\n `settlementCallCaps has ${settlementCallCaps.length} entries for ${settlementCalls.length} settlement calls — every call must declare exactly one cap`,\n );\n }\n\n const hash = await writeContractWithRetry({\n account: getAccount(),\n chain: getChain(),\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"propose\",\n args: [\n vault,\n strategy,\n metadataURI,\n strategyDuration,\n { maxCapital: envelope.maxCapital, maxDrawdownBps: envelope.maxDrawdownBps },\n executeCalls,\n executeCallCaps,\n settlementCalls,\n settlementCallCaps,\n coProposers,\n ],\n });\n\n const receipt = await waitForReceipt(hash);\n\n // Parse proposalId from the ProposalCreated event in the receipt logs.\n // Falls back to proposalCount() if event parsing fails.\n let proposalId = parseProposalIdFromLogs(receipt.logs);\n if (proposalId === undefined) {\n try {\n proposalId = await proposalCount(vault);\n } catch {\n proposalId = 0n;\n }\n }\n\n return { hash: receipt.transactionHash, proposalId };\n}\n\nexport async function vote(vault: Address, proposalId: bigint, support: number): Promise<Hex> {\n const hash = await writeContractWithRetry({\n account: getAccount(),\n chain: getChain(),\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"vote\",\n args: [proposalId, support],\n });\n const receipt = await waitForReceipt(hash);\n return receipt.transactionHash;\n}\n\nexport async function executeProposal(vault: Address, proposalId: bigint): Promise<Hex> {\n const hash = await writeContractWithRetry({\n account: getAccount(),\n chain: getChain(),\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"executeProposal\",\n args: [proposalId],\n });\n const receipt = await waitForReceipt(hash);\n return receipt.transactionHash;\n}\n\n/**\n * Walk a proposal's executeCalls and pick the strategy clone — the\n * target of the call whose selector matches `BaseStrategy.execute()`\n * (0x61461954). This is the canonical entry point that every Sherwood\n * strategy template inherits from BaseStrategy, so it's a reliable\n * marker even across template families (Moonwell / Aerodrome /\n * Hyperliquid / Mamo / Venice / Portfolio).\n *\n * Returns null when no execute() call is present (e.g. proposals that\n * only do approves and direct ERC-20 transfers without a strategy).\n */\nexport function detectStrategyAdapter(\n calls: { target: Address; data: Hex; value: bigint }[],\n): Address | null {\n const STRATEGY_EXECUTE_SELECTOR = \"0x61461954\";\n for (const call of calls) {\n if (call.data.slice(0, 10).toLowerCase() === STRATEGY_EXECUTE_SELECTOR) {\n return call.target;\n }\n }\n return null;\n}\n\nexport async function settleProposal(vault: Address, proposalId: bigint): Promise<Hex> {\n const hash = await writeContractWithRetry({\n account: getAccount(),\n chain: getChain(),\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"settleProposal\",\n args: [proposalId],\n });\n const receipt = await waitForReceipt(hash);\n return receipt.transactionHash;\n}\n\nexport async function emergencySettle(vault: Address, proposalId: bigint, calls: BatchCall[]): Promise<Hex> {\n const hash = await writeContractWithRetry({\n account: getAccount(),\n chain: getChain(),\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"emergencySettleWithCalls\",\n args: [proposalId, calls],\n });\n const receipt = await waitForReceipt(hash);\n return receipt.transactionHash;\n}\n\nexport async function cancelProposal(vault: Address, proposalId: bigint): Promise<Hex> {\n const hash = await writeContractWithRetry({\n account: getAccount(),\n chain: getChain(),\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"cancelProposal\",\n args: [proposalId],\n });\n const receipt = await waitForReceipt(hash);\n return receipt.transactionHash;\n}\n\nexport async function emergencyCancel(vault: Address, proposalId: bigint): Promise<Hex> {\n const hash = await writeContractWithRetry({\n account: getAccount(),\n chain: getChain(),\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"emergencyCancel\",\n args: [proposalId],\n });\n const receipt = await waitForReceipt(hash);\n return receipt.transactionHash;\n}\n\n// ── Parameter setters ──\n//\n// Per-vault governor: governance parameters are per-vault now, set by the\n// VAULT OWNER on that vault's governor. Setters revert with\n// `ParamsFrozenDuringProposal` while any proposal is open on the vault.\n\ntype GovernorParamSetter =\n | \"setVotingPeriod\"\n | \"setExecutionWindow\"\n | \"setVetoThresholdBps\"\n | \"setMaxPerformanceFeeBps\"\n | \"setMaxStrategyDuration\"\n | \"setCooldownPeriod\";\n\nasync function setGovernorParam(\n vault: Address,\n functionName: GovernorParamSetter,\n value: bigint,\n): Promise<Hex> {\n const hash = await writeContractWithRetry({\n account: getAccount(),\n chain: getChain(),\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName,\n args: [value],\n });\n const receipt = await waitForReceipt(hash);\n return receipt.transactionHash;\n}\n\nexport async function setVotingPeriod(vault: Address, seconds: bigint): Promise<Hex> {\n return setGovernorParam(vault, \"setVotingPeriod\", seconds);\n}\n\nexport async function setExecutionWindow(vault: Address, seconds: bigint): Promise<Hex> {\n return setGovernorParam(vault, \"setExecutionWindow\", seconds);\n}\n\nexport async function setVetoThresholdBps(vault: Address, bps: bigint): Promise<Hex> {\n return setGovernorParam(vault, \"setVetoThresholdBps\", bps);\n}\n\nexport async function setMaxPerformanceFeeBps(vault: Address, bps: bigint): Promise<Hex> {\n return setGovernorParam(vault, \"setMaxPerformanceFeeBps\", bps);\n}\n\nexport async function setMaxStrategyDuration(vault: Address, seconds: bigint): Promise<Hex> {\n return setGovernorParam(vault, \"setMaxStrategyDuration\", seconds);\n}\n\nexport async function setCooldownPeriod(vault: Address, seconds: bigint): Promise<Hex> {\n return setGovernorParam(vault, \"setCooldownPeriod\", seconds);\n}\n\nexport async function vetoProposal(vault: Address, proposalId: bigint): Promise<Hex> {\n const hash = await writeContractWithRetry({\n account: getAccount(),\n chain: getChain(),\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"vetoProposal\",\n args: [proposalId],\n });\n const receipt = await waitForReceipt(hash);\n return receipt.transactionHash;\n}\n\n// ── ProtocolConfig fee-split setters (protocol-owner only) ──\n//\n// Post-audit ProtocolConfig holds no per-rate protocol fee — the two-number\n// model exposes the SPLITS of the management and performance fees instead,\n// on the protocol-wide config (resolved via `factory.protocolConfig()`).\n\nexport interface MgmtSplit {\n agentBps: number;\n protocolBps: number;\n guardianBps: number;\n}\n\nexport interface PerfSplit extends MgmtSplit {\n ownerBps: number;\n}\n\nexport async function setMgmtSplit(s: MgmtSplit): Promise<Hex> {\n const hash = await writeContractWithRetry({\n account: getAccount(),\n chain: getChain(),\n address: await getProtocolConfigAddress(),\n abi: PROTOCOL_CONFIG_ABI,\n functionName: \"setMgmtSplit\",\n args: [s],\n });\n const receipt = await waitForReceipt(hash);\n return receipt.transactionHash;\n}\n\nexport async function setPerfSplit(s: PerfSplit): Promise<Hex> {\n const hash = await writeContractWithRetry({\n account: getAccount(),\n chain: getChain(),\n address: await getProtocolConfigAddress(),\n abi: PROTOCOL_CONFIG_ABI,\n functionName: \"setPerfSplit\",\n args: [s],\n });\n const receipt = await waitForReceipt(hash);\n return receipt.transactionHash;\n}\n","/**\n * AUTO-GENERATED by cli/scripts/codegen-contracts.ts — do not edit.\n * Regenerate: npm run codegen (in cli/)\n *\n * Source of truth: sherwood-protocol src/interfaces/ISyndicateGovernor.sol (enum ProposalState)\n */\n\n/** On-chain `ProposalState` member names, index === Solidity enum value. */\nexport const PROPOSAL_STATES = [\n \"Draft\",\n \"Pending\",\n \"GuardianReview\",\n \"Approved\",\n \"Rejected\",\n \"Expired\",\n \"Executed\",\n \"Settled\",\n \"Cancelled\",\n] as const;\n\nexport type ProposalStateName = (typeof PROPOSAL_STATES)[number];\n\n/** Name → Solidity enum value. */\nexport const PROPOSAL_STATE = {\n Draft: 0,\n Pending: 1,\n GuardianReview: 2,\n Approved: 3,\n Rejected: 4,\n Expired: 5,\n Executed: 6,\n Settled: 7,\n Cancelled: 8,\n} as const;\n"],"mappings":"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","names":[]}
@@ -19,7 +19,7 @@ var robinhoodTestnet = defineChain({
19
19
  },
20
20
  testnet: true
21
21
  });
22
- var ROBINHOOD_FORK_PUBLIC_RPC = "https://virtual.robinhood-chain.eu.rpc.tenderly.co/moonwell/wormhole-bridge/231af1";
22
+ var ROBINHOOD_FORK_PUBLIC_RPC = "https://virtual.robinhood-chain.eu.rpc.tenderly.co/moonwell/wormhole-bridge/f509bc-4fdefe";
23
23
  var ROBINHOOD_FORK_EXPLORER = "https://dashboard.tenderly.co/explorer/vnet/6ad5961e-fbca-452f-939f-ca9a8c020933";
24
24
  var robinhoodFork = defineChain({
25
25
  id: 9994663,
@@ -186,4 +186,4 @@ export {
186
186
  getExplorerUrl,
187
187
  isTestnet
188
188
  };
189
- //# sourceMappingURL=chunk-PVTZMRC6.js.map
189
+ //# sourceMappingURL=chunk-G3FUEM5N.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/network.ts"],"sourcesContent":["/**\n * Network state singleton.\n *\n * Called once at CLI startup via the --chain flag's preAction hook.\n * Every other module reads from here — never hardcodes a chain.\n *\n * Deployment targets: the Robinhood Chain mainnet fork (chain 9994663) — the\n * DEFAULT, and what the product ships against (app.sherwood.sh and the docs\n * both point there) — plus the Robinhood L2 testnet (chain 46630), still\n * reachable via `--chain robinhood-testnet`. Sherwood launches on Robinhood\n * first; other chains may be added back later, at which point they re-enter\n * the Network union + CHAIN_REGISTRY below.\n */\n\nimport { type Chain, defineChain, parseEther } from \"viem\";\nimport { getConfigRpcUrl } from \"./config.js\";\n\n// ── Robinhood L2 Testnet (Arbitrum Orbit, chain ID 46630) ──\n\nexport const robinhoodTestnet = defineChain({\n id: 46630,\n name: \"Robinhood Chain Testnet\",\n nativeCurrency: { name: \"Ethereum\", symbol: \"ETH\", decimals: 18 },\n rpcUrls: {\n default: { http: [\"https://rpc.testnet.chain.robinhood.com\"] },\n },\n blockExplorers: {\n default: {\n name: \"Blockscout\",\n url: \"https://explorer.testnet.chain.robinhood.com\",\n },\n },\n testnet: true,\n});\n\n// ── Robinhood Chain mainnet fork (Tenderly Virtual TestNet, chain ID 9994663) ──\n//\n// A fork of Robinhood Chain *mainnet* (USDG stablecoin, official Uniswap v3+v4,\n// Chainlink push feeds, tokenized-stock liquidity). Used for mainnet-faithful\n// e2e + guardian-network simulations. Ephemeral: Tenderly vnets expire — the RPC\n// is overridable via ROBINHOOD_FORK_RPC_URL when a new vnet is minted.\n\n/**\n * The PUBLIC RPC endpoint of the vnet carrying the v1 redeploy — safe to\n * bundle and to hand to users: it serves reads and accepts broadcast txs, but\n * exposes no state-cheat surface.\n *\n * Admin/cheat calls (`tenderly_setBalance`, `tenderly_setStorageAt`,\n * `evm_increaseTime`, …) need that vnet's *admin* RPC, which is private —\n * pull it from the Tenderly dashboard and pass it via ROBINHOOD_FORK_RPC_URL.\n *\n * Several vnets have answered to chain id 9994663 over time and the retired\n * ones return `not_found` rather than an RPC error, which reads as a network\n * hiccup. The address book is the tell: this endpoint is the one the\n * SyndicateFactory in chains/9994663.json (0x619af148…, deployed at block\n * 67,079,667) actually has code at.\n */\nconst ROBINHOOD_FORK_PUBLIC_RPC =\n \"https://virtual.robinhood-chain.eu.rpc.tenderly.co/moonwell/wormhole-bridge/f509bc-4fdefe\";\n\n/**\n * Tenderly scopes a vnet explorer under its vnet id — the bare\n * `dashboard.tenderly.co` host resolves to the user's own dashboard, not to\n * this fork's blocks, so tx/address links must carry the full prefix.\n */\nconst ROBINHOOD_FORK_EXPLORER =\n \"https://dashboard.tenderly.co/explorer/vnet/6ad5961e-fbca-452f-939f-ca9a8c020933\";\n\nexport const robinhoodFork = defineChain({\n id: 9994663,\n name: \"Robinhood Chain (fork)\",\n nativeCurrency: { name: \"Ethereum\", symbol: \"ETH\", decimals: 18 },\n rpcUrls: {\n default: {\n http: [ROBINHOOD_FORK_PUBLIC_RPC],\n },\n },\n blockExplorers: {\n default: {\n name: \"Tenderly\",\n url: ROBINHOOD_FORK_EXPLORER,\n },\n },\n testnet: true,\n});\n\n// ── Types ──\n\nexport type Network = \"robinhood-testnet\" | \"robinhood-fork\" | \"robinhood-mainnet\";\n\nexport interface ChainConfig {\n chain: Chain;\n /**\n * Ordered list of public RPC URLs tried in sequence when no user RPC is set.\n * First entry is the primary; the rest are fallbacks used transparently via\n * viem's `fallback` transport on rate-limit / network errors.\n */\n rpcFallbacks: string[];\n /** Legacy env var for backwards compat (optional per chain) */\n rpcEnvVar?: string;\n explorerHost: string;\n /**\n * Full URL prefix for explorer links, when the explorer is not rooted at\n * `https://${explorerHost}` — a Tenderly vnet scopes its blocks under\n * `/explorer/vnet/<id>`. Defaults to `https://${explorerHost}`.\n */\n explorerBaseUrl?: string;\n /** EAS GraphQL endpoint — null if EAS is not available on this chain */\n easGraphqlUrl: string | null;\n /** EAS scan host — null if unavailable */\n easScanHost: string | null;\n xmtpEnv: \"production\" | \"dev\";\n isTestnet: boolean;\n /**\n * ETH held back for gas in the native-ETH-wrap deposit path — the floor and\n * fallback for the live per-tx cushion estimate (`estimateGasCushion` in\n * client.ts), NOT a fixed requirement. High-fee chains (Base) want a\n * Base-scale reserve; near-zero-fee chains (Robinhood testnet, ~14-wei base\n * fee) want a tiny one so a valid deposit isn't rejected client-side. Unset →\n * `DEFAULT_MIN_GAS_RESERVE`.\n */\n minGasReserve?: bigint;\n}\n\n/**\n * Base-scale default reserve, used when a chain omits `minGasReserve`. Matches\n * the old hardcoded 0.0005-ETH cushion so higher-fee chains keep prior behavior.\n */\nexport const DEFAULT_MIN_GAS_RESERVE = parseEther(\"0.0005\");\n\n/**\n * Robinhood Chain mainnet (4663) — the EAS **coordination chain**.\n *\n * Sherwood core is NOT deployed here. This entry exists so attestations have a\n * single permanent home regardless of which chain a fund lives on, and it is\n * deliberately excluded from VALID_NETWORKS so it can never be picked as one.\n *\n * See docs/superpowers/specs/2026-08-26-eas-robinhood-mainnet-design.md §5.1.\n */\nexport const robinhoodMainnet = defineChain({\n id: 4663,\n name: \"Robinhood Chain\",\n nativeCurrency: {name: \"Ethereum\", symbol: \"ETH\", decimals: 18},\n rpcUrls: {default: {http: [\"https://rpc.mainnet.chain.robinhood.com\"]}},\n blockExplorers: {\n default: {name: \"Blockscout\", url: \"https://robinhoodchain.blockscout.com\"},\n },\n});\n\n// ── Chain Registry ──\n\nexport const CHAIN_REGISTRY: Record<Network, ChainConfig> = {\n \"robinhood-testnet\": {\n chain: robinhoodTestnet,\n rpcFallbacks: [\"https://rpc.testnet.chain.robinhood.com\"],\n rpcEnvVar: \"ROBINHOOD_TESTNET_RPC_URL\",\n explorerHost: \"explorer.testnet.chain.robinhood.com\",\n easGraphqlUrl: null,\n easScanHost: null,\n xmtpEnv: \"production\",\n isTestnet: true,\n // ~14-wei base fee: a full wrap+approve+deposit sequence costs a few\n // million wei (~1e-11 ETH). 0.00002 ETH is a generous floor that still\n // leaves a 0.00058-ETH wallet room to wrap 0.0005 and deposit.\n minGasReserve: parseEther(\"0.00002\"),\n },\n \"robinhood-fork\": {\n chain: robinhoodFork,\n rpcFallbacks: [ROBINHOOD_FORK_PUBLIC_RPC],\n rpcEnvVar: \"ROBINHOOD_FORK_RPC_URL\",\n explorerHost: \"dashboard.tenderly.co\",\n explorerBaseUrl: ROBINHOOD_FORK_EXPLORER,\n easGraphqlUrl: null,\n easScanHost: null,\n xmtpEnv: \"production\",\n isTestnet: true,\n // Robinhood-mainnet-fork gas (~0.17 gwei) is higher than testnet's ~14 wei —\n // keep a modest reserve so the ETH-wrap deposit path isn't rejected.\n minGasReserve: parseEther(\"0.0005\"),\n },\n \"robinhood-mainnet\": {\n chain: robinhoodMainnet,\n // Public endpoint kept only as a last-resort fallback: it sits behind\n // Cloudflare and challenges non-browser clients under load, and Robinhood's\n // own docs call it unsuitable for production. ROBINHOOD_RPC_URL (Alchemy)\n // is what actually gets used.\n rpcFallbacks: [\"https://rpc.mainnet.chain.robinhood.com\"],\n rpcEnvVar: \"ROBINHOOD_RPC_URL\",\n explorerHost: \"robinhoodchain.blockscout.com\",\n // Self-hosted EAS indexer — easscan does not index 4663. Serves GraphQL at\n // the root, so no /graphql suffix.\n easGraphqlUrl: \"https://sherwood-indexer-production.up.railway.app\",\n // No easscan-equivalent UI for this chain yet; attestation permalinks are\n // pending the app's own /attestation route (spec §10.2).\n easScanHost: null,\n xmtpEnv: \"production\",\n isTestnet: false,\n },\n};\n\n/**\n * Networks a user may select with `--chain`.\n *\n * NOT simply the CHAIN_REGISTRY keys: `robinhood-mainnet` is a coordination\n * chain for attestations only (no Sherwood contracts deployed there), so\n * selecting it as a fund's home chain would resolve every address to zero.\n */\nexport const COORDINATION_ONLY_NETWORKS: readonly Network[] = [\"robinhood-mainnet\"];\n\nexport const VALID_NETWORKS = (Object.keys(CHAIN_REGISTRY) as Network[]).filter(\n (n) => !COORDINATION_ONLY_NETWORKS.includes(n),\n);\n\n/**\n * The network a bare CLI invocation (no `--chain`) targets.\n *\n * The fork is where the product actually lives: app.sherwood.sh defaults to\n * chain 9994663, the docs banner declares it, and the redeployed 46630 factory\n * holds zero syndicates — so a default of `robinhood-testnet` landed a fresh\n * agent on an empty chain. `--chain robinhood-testnet` still selects 46630.\n *\n * 46630 was NOT redeployed for v1: it still runs the pre-v1 contracts, so\n * this CLI's ABIs do not match what is deployed there. Selecting it is a\n * broken path until that chain is redeployed off `v1-deploy`.\n */\nexport const DEFAULT_NETWORK: Network = \"robinhood-fork\";\n\n// ── Singleton state ──\n\nlet _network: Network = DEFAULT_NETWORK;\n\nexport function setNetwork(n: Network) {\n const config = CHAIN_REGISTRY[n];\n if (!config) {\n throw new Error(\n `Unknown network: ${n}. Valid: ${VALID_NETWORKS.join(\", \")}`,\n );\n }\n _network = n;\n}\n\nexport function getNetwork(): Network {\n return _network;\n}\n\n/**\n * Run `fn` with the network singleton temporarily switched to `network`,\n * restoring the previous network in `finally`.\n *\n * The viem clients (`getPublicClient`, `getWalletClient`) auto-invalidate on\n * chain change, so callers get fresh per-chain RPC + chain context inside the\n * block. Used for cross-chain fund resolution.\n */\nexport async function withNetwork<T>(\n network: Network,\n fn: () => Promise<T>,\n): Promise<T> {\n const previous = _network;\n _network = network;\n try {\n return await fn();\n } finally {\n _network = previous;\n }\n}\n\nexport function getChainConfig(): ChainConfig {\n return CHAIN_REGISTRY[_network];\n}\n\n/**\n * Per-chain ETH gas reserve floor/fallback for the ETH-wrap deposit path.\n * Falls back to the Base-scale default when the active chain doesn't set one.\n */\nexport function getMinGasReserve(): bigint {\n return CHAIN_REGISTRY[_network].minGasReserve ?? DEFAULT_MIN_GAS_RESERVE;\n}\n\n/**\n * Dev/CI-only chain-id override (`SIM_CHAIN_ID`) for custom-chainId vnet forks.\n * viem asserts the node's chainId matches the chain definition on every write,\n * so signing for such a fork requires the id to be swapped at the source.\n *\n * Interlock: honored ONLY while `SIM_ADDRESSES_FILE` is also set (the vnet\n * e2e harness's address override). A bare SIM_CHAIN_ID does nothing, so this\n * can never redirect signing on a real network run.\n */\nexport function applyChainIdOverride(chain: Chain): Chain {\n const raw = process.env.SIM_CHAIN_ID;\n if (!raw || !process.env.SIM_ADDRESSES_FILE) return chain;\n const id = Number(raw);\n if (!Number.isInteger(id) || id <= 0) return chain;\n return { ...chain, id };\n}\n\nexport function getChain(): Chain {\n return applyChainIdOverride(CHAIN_REGISTRY[_network].chain);\n}\n\n/**\n * Ordered list of RPC URLs to try, deduped:\n * 1. User config (~/.sherwood/config.json) — honored first\n * 2. The active chain's legacy env var (`rpcEnvVar` — ROBINHOOD_FORK_RPC_URL\n * on the default fork, ROBINHOOD_TESTNET_RPC_URL on 46630)\n * 3. Public fallback list from CHAIN_REGISTRY\n *\n * Fed to viem's `fallback()` transport so rate-limited RPCs transparently\n * advance to the next entry. See issue #182.\n */\nexport function getRpcUrls(): string[] {\n const cfg = CHAIN_REGISTRY[_network];\n const urls: string[] = [];\n\n const fromConfig = getConfigRpcUrl(_network);\n if (fromConfig) urls.push(fromConfig);\n\n if (cfg.rpcEnvVar && process.env[cfg.rpcEnvVar]) {\n urls.push(process.env[cfg.rpcEnvVar]!);\n }\n\n // Vnet harness (SIM_CHAIN_ID + SIM_ADDRESSES_FILE interlock): the fork RPC\n // is the ONLY valid endpoint — the public fallbacks point at the real\n // network. viem's fallback() otherwise rotates there on a vnet hiccup and\n // silently estimates gas/fees against MAINNET state (live finding: an\n // approve estimated at 21.9k gas on mainnet — no code at that address —\n // reverted out-of-gas on the vnet where it needs ~46k). A vnet call must\n // fail loudly, never retarget the real chain.\n if (process.env.SIM_CHAIN_ID && process.env.SIM_ADDRESSES_FILE && urls.length > 0) {\n return Array.from(new Set(urls));\n }\n\n urls.push(...cfg.rpcFallbacks);\n\n return Array.from(new Set(urls));\n}\n\nexport function getRpcUrl(): string {\n return getRpcUrls()[0];\n}\n\nexport function getExplorerUrl(txHash: string): string {\n const cfg = CHAIN_REGISTRY[_network];\n const base = cfg.explorerBaseUrl ?? `https://${cfg.explorerHost}`;\n return `${base}/tx/${txHash}`;\n}\n\nexport function isTestnet(): boolean {\n return CHAIN_REGISTRY[_network].isTestnet;\n}\n"],"mappings":"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","names":[]}
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  getLogsChunked
3
- } from "./chunk-EA65CDQH.js";
3
+ } from "./chunk-R6F57QQF.js";
4
4
  import {
5
5
  TOKENS
6
- } from "./chunk-IAM4VIU2.js";
6
+ } from "./chunk-UOIAY6ZG.js";
7
7
  import {
8
8
  GAS_UNITS,
9
9
  estimateGasCushion,
@@ -12,17 +12,17 @@ import {
12
12
  getWalletClient,
13
13
  waitForReceipt,
14
14
  writeContractWithRetry
15
- } from "./chunk-QRMZRAMG.js";
15
+ } from "./chunk-MIAMGVZ4.js";
16
16
  import {
17
17
  getChain
18
- } from "./chunk-PVTZMRC6.js";
18
+ } from "./chunk-G3FUEM5N.js";
19
19
  import {
20
20
  getChainContracts
21
21
  } from "./chunk-3TZIOAPH.js";
22
22
  import {
23
23
  ERC20_ABI,
24
24
  SYNDICATE_VAULT_ABI
25
- } from "./chunk-F3MDCUGO.js";
25
+ } from "./chunk-J2IZWAEW.js";
26
26
 
27
27
  // src/lib/vault.ts
28
28
  import { formatUnits, parseAbiItem } from "viem";
@@ -557,4 +557,4 @@ export {
557
557
  registerAgent,
558
558
  getVaultInfo
559
559
  };
560
- //# sourceMappingURL=chunk-XPVXNG2K.js.map
560
+ //# sourceMappingURL=chunk-GR3GSU3I.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  getAccount
3
- } from "./chunk-QRMZRAMG.js";
3
+ } from "./chunk-MIAMGVZ4.js";
4
4
  import {
5
5
  getVeniceApiKey,
6
6
  setVeniceApiKey
@@ -186,4 +186,4 @@ export {
186
186
  chatCompletion,
187
187
  listModels
188
188
  };
189
- //# sourceMappingURL=chunk-KVB5P2OE.js.map
189
+ //# sourceMappingURL=chunk-IINWI3LD.js.map