@sherwoodagent/cli 0.86.1 → 0.87.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 (71) hide show
  1. package/dist/{abis-WVW2EBI3.js → abis-WJQ6IVYV.js} +2 -2
  2. package/dist/{agent-TBLC3WNJ.js → agent-FCGZL4GF.js} +7 -7
  3. package/dist/{chat-ETZSKQDI.js → chat-AKLYUJZV.js} +8 -8
  4. package/dist/{chunk-ZN2MHIB7.js → chunk-4ITTHKRX.js} +5 -5
  5. package/dist/{chunk-EVUKJ7CJ.js → chunk-6D3FNU75.js} +5 -5
  6. package/dist/{chunk-45FELUWY.js → chunk-6SAE2VDK.js} +2 -2
  7. package/dist/{chunk-EA65CDQH.js → chunk-BH3VTJ4F.js} +14 -23
  8. package/dist/chunk-BH3VTJ4F.js.map +1 -0
  9. package/dist/{chunk-QRMZRAMG.js → chunk-D4BSBW3Q.js} +221 -10
  10. package/dist/chunk-D4BSBW3Q.js.map +1 -0
  11. package/dist/{chunk-KVB5P2OE.js → chunk-EEI6FRTE.js} +2 -2
  12. package/dist/{chunk-IAM4VIU2.js → chunk-FWQESFFM.js} +18 -41
  13. package/dist/chunk-FWQESFFM.js.map +1 -0
  14. package/dist/{chunk-PVTZMRC6.js → chunk-G3FUEM5N.js} +2 -2
  15. package/dist/chunk-G3FUEM5N.js.map +1 -0
  16. package/dist/{chunk-YAS52NEF.js → chunk-G5MXVAFC.js} +18 -5
  17. package/dist/chunk-G5MXVAFC.js.map +1 -0
  18. package/dist/{chunk-F3MDCUGO.js → chunk-J2IZWAEW.js} +75 -227
  19. package/dist/chunk-J2IZWAEW.js.map +1 -0
  20. package/dist/{chunk-XPVXNG2K.js → chunk-N2E2Q5GL.js} +6 -6
  21. package/dist/{chunk-3IAZQMAW.js → chunk-QFGZQYZA.js} +29 -82
  22. package/dist/chunk-QFGZQYZA.js.map +1 -0
  23. package/dist/{chunk-OUYMZ5ZC.js → chunk-SI65QHTY.js} +5 -5
  24. package/dist/{chunk-6QBGTX2Q.js → chunk-VYCLG5DE.js} +264 -487
  25. package/dist/chunk-VYCLG5DE.js.map +1 -0
  26. package/dist/{client-3SE632Q2.js → client-PYFE6YQR.js} +3 -3
  27. package/dist/{eas-KMDAMLXW.js → eas-DV3Z7AT3.js} +6 -6
  28. package/dist/{governor-JNSWPJVQ.js → governor-QFBN6RYS.js} +8 -6
  29. package/dist/identity-M4TXM7EX.js +18 -0
  30. package/dist/index.js +352 -355
  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-EXZDYVDD.js} +6 -6
  34. package/dist/{providers-BMOHHVUN.js → providers-6UZKDFQD.js} +4 -4
  35. package/dist/{research-W74PNYPO.js → research-44GHYE4H.js} +7 -7
  36. package/dist/{session-HVRZ6AJM.js → session-45NQAHFI.js} +14 -12
  37. package/dist/session-45NQAHFI.js.map +1 -0
  38. package/dist/{trade-EOQY72L7.js → trade-FO52SP62.js} +15 -15
  39. package/dist/{vault-HWJQJW5U.js → vault-WWGSRNRP.js} +8 -8
  40. package/dist/{xmtp-KW73BGVO.js → xmtp-72IRK7JL.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-FCGZL4GF.js.map} +0 -0
  54. /package/dist/{chat-ETZSKQDI.js.map → chat-AKLYUJZV.js.map} +0 -0
  55. /package/dist/{chunk-ZN2MHIB7.js.map → chunk-4ITTHKRX.js.map} +0 -0
  56. /package/dist/{chunk-EVUKJ7CJ.js.map → chunk-6D3FNU75.js.map} +0 -0
  57. /package/dist/{chunk-45FELUWY.js.map → chunk-6SAE2VDK.js.map} +0 -0
  58. /package/dist/{chunk-KVB5P2OE.js.map → chunk-EEI6FRTE.js.map} +0 -0
  59. /package/dist/{chunk-XPVXNG2K.js.map → chunk-N2E2Q5GL.js.map} +0 -0
  60. /package/dist/{chunk-OUYMZ5ZC.js.map → chunk-SI65QHTY.js.map} +0 -0
  61. /package/dist/{client-3SE632Q2.js.map → client-PYFE6YQR.js.map} +0 -0
  62. /package/dist/{eas-KMDAMLXW.js.map → eas-DV3Z7AT3.js.map} +0 -0
  63. /package/dist/{governor-JNSWPJVQ.js.map → governor-QFBN6RYS.js.map} +0 -0
  64. /package/dist/{identity-ATWV2O7Y.js.map → identity-M4TXM7EX.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-EXZDYVDD.js.map} +0 -0
  67. /package/dist/{providers-BMOHHVUN.js.map → providers-6UZKDFQD.js.map} +0 -0
  68. /package/dist/{research-W74PNYPO.js.map → research-44GHYE4H.js.map} +0 -0
  69. /package/dist/{trade-EOQY72L7.js.map → trade-FO52SP62.js.map} +0 -0
  70. /package/dist/{vault-HWJQJW5U.js.map → vault-WWGSRNRP.js.map} +0 -0
  71. /package/dist/{xmtp-KW73BGVO.js.map → xmtp-72IRK7JL.js.map} +0 -0
@@ -1,33 +1,34 @@
1
1
  import {
2
2
  COORDINATION_NETWORK
3
- } from "./chunk-OUYMZ5ZC.js";
3
+ } from "./chunk-SI65QHTY.js";
4
4
  import {
5
5
  AGENT_REGISTRY
6
- } from "./chunk-IAM4VIU2.js";
6
+ } from "./chunk-FWQESFFM.js";
7
7
  import {
8
8
  formatContractError,
9
9
  getAccount,
10
10
  getPublicClient,
11
11
  sendTxWithRetry,
12
12
  waitForReceipt
13
- } from "./chunk-QRMZRAMG.js";
13
+ } from "./chunk-D4BSBW3Q.js";
14
14
  import {
15
15
  getChain,
16
- getChainConfig,
17
- getRpcUrl,
18
16
  withNetwork
19
- } from "./chunk-PVTZMRC6.js";
17
+ } from "./chunk-G3FUEM5N.js";
20
18
  import {
21
19
  getAgentId,
22
20
  getIdentityChainId,
23
21
  getIdentityProvider,
24
22
  getVirtualsIdentity,
25
- requirePrivateKey,
26
23
  setAgentId,
27
24
  setVirtualsIdentity
28
25
  } from "./chunk-3TZIOAPH.js";
26
+ import {
27
+ resolveMetadataSummary
28
+ } from "./chunk-YMB4RJOR.js";
29
29
 
30
30
  // src/commands/identity.ts
31
+ import { getAddress as getAddress9, isAddress as isAddress3 } from "viem";
31
32
  import { generatePrivateKey } from "viem/accounts";
32
33
  import chalk from "chalk";
33
34
  import ora from "ora";
@@ -471,27 +472,6 @@ var SYNDICATE_VAULT_ABI = [
471
472
  { name: "agentAddress", type: "address" }
472
473
  ],
473
474
  outputs: []
474
- },
475
- // Governor-only: mint + fund + run a single-use CallSandbox.
476
- // ICallSandbox.Call is TWO fields (address,bytes). There is NO `value`.
477
- {
478
- name: "runSandbox",
479
- type: "function",
480
- stateMutability: "nonpayable",
481
- inputs: [
482
- { name: "pid", type: "uint256" },
483
- {
484
- name: "calls",
485
- type: "tuple[]",
486
- components: [
487
- { name: "target", type: "address" },
488
- { name: "data", type: "bytes" }
489
- ]
490
- },
491
- { name: "declaredTokens", type: "address[]" },
492
- { name: "funding", type: "uint256" }
493
- ],
494
- outputs: [{ name: "sandbox", type: "address" }]
495
475
  }
496
476
  ];
497
477
  var SYNDICATE_GOVERNOR_ABI = [
@@ -553,74 +533,6 @@ var SYNDICATE_GOVERNOR_ABI = [
553
533
  ],
554
534
  outputs: [{ name: "proposalId", type: "uint256" }]
555
535
  },
556
- // proposeWithSandbox — same 10 args as propose, prefixed with SandboxPayload.
557
- // ICallSandbox.Call is TWO fields (address,bytes). There is NO `value`:
558
- // native value would open a transfer channel with no metering story
559
- // (ICallSandbox.sol:44-51). Aliasing BatchExecutorLib.Call would reintroduce it.
560
- {
561
- name: "proposeWithSandbox",
562
- type: "function",
563
- stateMutability: "nonpayable",
564
- inputs: [
565
- {
566
- name: "sandbox",
567
- type: "tuple",
568
- components: [
569
- { name: "funding", type: "uint256" },
570
- {
571
- name: "calls",
572
- type: "tuple[]",
573
- components: [
574
- { name: "target", type: "address" },
575
- { name: "data", type: "bytes" }
576
- ]
577
- },
578
- { name: "declaredTokens", type: "address[]" }
579
- ]
580
- },
581
- { name: "vault", type: "address" },
582
- { name: "strategy", type: "address" },
583
- { name: "metadataURI", type: "string" },
584
- { name: "strategyDuration", type: "uint256" },
585
- {
586
- name: "envelope",
587
- type: "tuple",
588
- components: [
589
- { name: "maxCapital", type: "uint256" },
590
- { name: "maxDrawdownBps", type: "uint16" }
591
- ]
592
- },
593
- {
594
- name: "executeCalls",
595
- type: "tuple[]",
596
- components: [
597
- { name: "target", type: "address" },
598
- { name: "data", type: "bytes" },
599
- { name: "value", type: "uint256" }
600
- ]
601
- },
602
- { name: "executeCallCaps", type: "uint256[]" },
603
- {
604
- name: "settlementCalls",
605
- type: "tuple[]",
606
- components: [
607
- { name: "target", type: "address" },
608
- { name: "data", type: "bytes" },
609
- { name: "value", type: "uint256" }
610
- ]
611
- },
612
- { name: "settlementCallCaps", type: "uint256[]" },
613
- {
614
- name: "coProposers",
615
- type: "tuple[]",
616
- components: [
617
- { name: "agent", type: "address" },
618
- { name: "splitBps", type: "uint256" }
619
- ]
620
- }
621
- ],
622
- outputs: [{ name: "proposalId", type: "uint256" }]
623
- },
624
536
  // Lifecycle writes
625
537
  {
626
538
  name: "vote",
@@ -714,9 +626,10 @@ var SYNDICATE_GOVERNOR_ABI = [
714
626
  { name: "metadataURI", type: "string" },
715
627
  { name: "performanceFeeBps", type: "uint256" },
716
628
  { name: "strategyDuration", type: "uint256" },
717
- { name: "votesFor", type: "uint256" },
629
+ // Optimistic governance tallies only AGAINST weight; the For /
630
+ // Abstain counters were dropped at v1 and `votableSupply` (the
631
+ // veto denominator) is appended at the tail instead.
718
632
  { name: "votesAgainst", type: "uint256" },
719
- { name: "votesAbstain", type: "uint256" },
720
633
  { name: "snapshotTimestamp", type: "uint256" },
721
634
  { name: "voteEnd", type: "uint256" },
722
635
  { name: "reviewEnd", type: "uint256" },
@@ -756,36 +669,8 @@ var SYNDICATE_GOVERNOR_ABI = [
756
669
  ]
757
670
  },
758
671
  { name: "proposerBondLedger", type: "address" },
759
- { name: "effectiveMaxCapital", type: "uint256" }
760
- ]
761
- }
762
- ]
763
- },
764
- // sandboxPayload — ISyndicateGovernor.sol ~730 / SyndicateGovernor.sol:506.
765
- // Returns SandboxPayload {funding, calls, declaredTokens}. Calls are
766
- // ICallSandbox.Call = (address target, bytes data) ONLY — no `value`.
767
- // Non-sandbox (and unknown) pids return the mapping default: zero funding,
768
- // empty calls, empty declaredTokens. The contract does not revert.
769
- {
770
- name: "sandboxPayload",
771
- type: "function",
772
- stateMutability: "view",
773
- inputs: [{ name: "proposalId", type: "uint256" }],
774
- outputs: [
775
- {
776
- name: "payload",
777
- type: "tuple",
778
- components: [
779
- { name: "funding", type: "uint256" },
780
- {
781
- name: "calls",
782
- type: "tuple[]",
783
- components: [
784
- { name: "target", type: "address" },
785
- { name: "data", type: "bytes" }
786
- ]
787
- },
788
- { name: "declaredTokens", type: "address[]" }
672
+ { name: "effectiveMaxCapital", type: "uint256" },
673
+ { name: "votableSupply", type: "uint256" }
789
674
  ]
790
675
  }
791
676
  ]
@@ -944,19 +829,43 @@ var SYNDICATE_FACTORY_ABI = [
944
829
  }
945
830
  ];
946
831
  var PROTOCOL_CONFIG_ABI = [
832
+ // The two-number fee model exposes the SPLITS, not flat rates. The
833
+ // `protocolFeeBps` / `guardianFeeBps` scalars this ABI used to declare are
834
+ // on no deployed ProtocolConfig — every read through them reverted.
947
835
  {
948
- name: "protocolFeeBps",
836
+ name: "mgmtSplit",
949
837
  type: "function",
950
838
  stateMutability: "view",
951
839
  inputs: [],
952
- outputs: [{ name: "", type: "uint256" }]
840
+ outputs: [
841
+ {
842
+ name: "",
843
+ type: "tuple",
844
+ components: [
845
+ { name: "agentBps", type: "uint16" },
846
+ { name: "protocolBps", type: "uint16" },
847
+ { name: "guardianBps", type: "uint16" }
848
+ ]
849
+ }
850
+ ]
953
851
  },
954
852
  {
955
- name: "guardianFeeBps",
853
+ name: "perfSplit",
956
854
  type: "function",
957
855
  stateMutability: "view",
958
856
  inputs: [],
959
- outputs: [{ name: "", type: "uint256" }]
857
+ outputs: [
858
+ {
859
+ name: "",
860
+ type: "tuple",
861
+ components: [
862
+ { name: "agentBps", type: "uint16" },
863
+ { name: "protocolBps", type: "uint16" },
864
+ { name: "guardianBps", type: "uint16" },
865
+ { name: "ownerBps", type: "uint16" }
866
+ ]
867
+ }
868
+ ]
960
869
  },
961
870
  {
962
871
  name: "protocolFeeRecipient",
@@ -965,10 +874,7 @@ var PROTOCOL_CONFIG_ABI = [
965
874
  inputs: [],
966
875
  outputs: [{ name: "", type: "address" }]
967
876
  },
968
- // Protocol-owner setters — post-audit ProtocolConfig has no per-rate
969
- // protocol fee; the two-number model exposes the SPLITS instead. (The old
970
- // `setProtocolFeeBps` entry described a function the contract no longer
971
- // has; every call through it reverted.)
877
+ // Protocol-owner setters.
972
878
  {
973
879
  name: "setMgmtSplit",
974
880
  type: "function",
@@ -1012,8 +918,11 @@ var GUARDIAN_REGISTRY_ABI = [
1012
918
  // requestUnstakeGuardian / cancelUnstakeGuardian / claimUnstakeGuardian /
1013
919
  // guardianStake / isActiveGuardian to the registry reverts with empty
1014
920
  // returndata. Use STAKED_WOOD_ABI against `sherwood.stakedWood`.
1015
- // Guardian review vote — 3 args, no slashBps. Selector 0x3ad95b6d.
1016
- // GuardianVoteType: None=0, Approve=1, Block=2 (uint8).
921
+ // Guardian review vote — 4 args. Selector 0x4915ace5. The 3-arg form
922
+ // (0x3ad95b6d) is on no deployed registry.
923
+ // GuardianVoteType: None=0, Approve=1, Block=2 (uint8). `lockWood` is the
924
+ // approver's declared WOOD lock, clamped to its free budget by the
925
+ // ExposureLedger and ignored on a Block vote.
1017
926
  {
1018
927
  name: "voteOnProposal",
1019
928
  type: "function",
@@ -1021,7 +930,8 @@ var GUARDIAN_REGISTRY_ABI = [
1021
930
  inputs: [
1022
931
  { name: "governor", type: "address" },
1023
932
  { name: "proposalId", type: "uint256" },
1024
- { name: "support", type: "uint8" }
933
+ { name: "support", type: "uint8" },
934
+ { name: "lockWood", type: "uint256" }
1025
935
  ],
1026
936
  outputs: []
1027
937
  },
@@ -1225,30 +1135,15 @@ var PROTOCOL_SELECTORS = {
1225
1135
  signature: "propose(address,address,string,uint256,(uint256,uint16),(address,bytes,uint256)[],uint256[],(address,bytes,uint256)[],uint256[],(address,uint256)[])",
1226
1136
  selector: "0x784ea274"
1227
1137
  },
1228
- proposeWithSandbox: {
1229
- iface: "ISyndicateGovernor",
1230
- signature: "proposeWithSandbox((uint256,(address,bytes)[],address[]),address,address,string,uint256,(uint256,uint16),(address,bytes,uint256)[],uint256[],(address,bytes,uint256)[],uint256[],(address,uint256)[])",
1231
- selector: "0x16c0fa9c"
1232
- },
1233
1138
  voteOnProposal: {
1234
1139
  iface: "IGuardianRegistry",
1235
- signature: "voteOnProposal(address,uint256,uint8)",
1236
- selector: "0x3ad95b6d"
1140
+ signature: "voteOnProposal(address,uint256,uint8,uint256)",
1141
+ selector: "0x4915ace5"
1237
1142
  },
1238
1143
  getReviewState: {
1239
1144
  iface: "IGuardianRegistry",
1240
1145
  signature: "getReviewState(address,uint256)",
1241
1146
  selector: "0x043bd8b9"
1242
- },
1243
- runSandbox: {
1244
- iface: "ISyndicateVault",
1245
- signature: "runSandbox(uint256,(address,bytes)[],address[],uint256)",
1246
- selector: "0xb0f4c59d"
1247
- },
1248
- sweep: {
1249
- iface: "ICallSandbox",
1250
- signature: "sweep()",
1251
- selector: "0x35faa416"
1252
1147
  }
1253
1148
  };
1254
1149
  var API_CALLDATA_SELECTORS = {
@@ -1278,14 +1173,11 @@ var API_CALLDATA_SELECTORS = {
1278
1173
  propose: [
1279
1174
  { target: "governor", selector: "0x784ea274", signature: PROTOCOL_SELECTORS.propose.signature }
1280
1175
  ],
1281
- "propose-with-sandbox": [
1282
- { target: "governor", selector: "0x16c0fa9c", signature: PROTOCOL_SELECTORS.proposeWithSandbox.signature }
1283
- ],
1284
1176
  vote: [
1285
1177
  { target: "governor", selector: "0x943e8216", signature: "vote(uint256,uint8)" }
1286
1178
  ],
1287
1179
  "vote-on-proposal": [
1288
- { target: "guardianRegistry", selector: "0x3ad95b6d", signature: PROTOCOL_SELECTORS.voteOnProposal.signature }
1180
+ { target: "guardianRegistry", selector: "0x4915ace5", signature: PROTOCOL_SELECTORS.voteOnProposal.signature }
1289
1181
  ],
1290
1182
  execute: [
1291
1183
  { target: "governor", selector: "0x0d61b519", signature: "executeProposal(uint256)" }
@@ -1346,7 +1238,6 @@ var NO_GUARDIAN_ERA = {
1346
1238
  protocolConfig: ZERO_ADDRESS,
1347
1239
  priceRouter: ZERO_ADDRESS,
1348
1240
  tierRegistry: ZERO_ADDRESS,
1349
- callSandboxImpl: ZERO_ADDRESS,
1350
1241
  exposureLedger: ZERO_ADDRESS,
1351
1242
  proposerBondEscrow: ZERO_ADDRESS,
1352
1243
  challengeGame: ZERO_ADDRESS,
@@ -1489,7 +1380,6 @@ var ROBINHOOD_L2 = {
1489
1380
  protocolConfig: "0xC104Eb6a522d6718cA28F344B2373B29d57FF2E0",
1490
1381
  priceRouter: "0xDd302ffcfA08071780eC1A2f12BccFB9ba6b6731",
1491
1382
  tierRegistry: "0x99b8068Dc0F6093466964D581f72d947e3e380DB",
1492
- callSandboxImpl: "0xf09f6AF7DeBB964eD731376C9Af389F2Ce3d872A",
1493
1383
  // Not in chains/46630.json (econ-security stack not deployed there yet).
1494
1384
  exposureLedger: ZERO_ADDRESS,
1495
1385
  proposerBondEscrow: ZERO_ADDRESS,
@@ -1516,23 +1406,22 @@ var ROBINHOOD_FORK = {
1516
1406
  name: "Robinhood Chain (fork)",
1517
1407
  slug: "robinhood-fork",
1518
1408
  sherwood: {
1519
- factory: "0x02bc9B9C1A4322D5A5df86DadA0a2a02e45108B9",
1520
- guardianRegistry: "0xdfEe38C4D7595c9c04AdBcaFE01E4Fd6FD6117f4",
1521
- stakedWood: "0xD3037D28693cc7BB3DbF1E17B6e01C4ce628f6DF",
1522
- vaultImpl: "0x9BF51da59B13746e6cCeb1b35c398EDA9776a4Dc",
1523
- batchExecutorLib: "0xdBdBce2af4222Abe0cCDAc05f84364a50577B5a2",
1524
- strategyFactory: "0xb3C009aECAeDd5ccC62Ec12eDAAA55F19C4A1eFb",
1409
+ factory: "0x619af1488F32B4797f6faDa3C3a8De72a5B693E0",
1410
+ guardianRegistry: "0xD8F9E7446E6d6c02198AAaF674A0C5e3d5D1BF72",
1411
+ stakedWood: "0xdDf2B4C52B9575e0e6D03a3A57D75D06a4a9e203",
1412
+ vaultImpl: "0xdaB4707c9997a84e931FE98F4688adaFc70b6B95",
1413
+ batchExecutorLib: "0x899FC2Cac572F64A233344115b488E71E0044f34",
1414
+ strategyFactory: "0xb06788F027268a9A06c3AD41a88559530D2E54b1",
1525
1415
  // Guardian-era contracts from sherwood-protocol/chains/9994663.json (SHE-93).
1526
- governorBeacon: "0x2e8aB422Db9127F1a70d8C38A15903f22B51DA97",
1527
- protocolConfig: "0x36C45dC52FbC267d8536E8456ADe5255eC83A5ab",
1528
- // Not in chains/9994663.json (no PriceRouter / CallSandbox on the fork).
1416
+ governorBeacon: "0x3CF45eFE9fBDdd6cB749384Bf5c1bA5Ec96af05d",
1417
+ protocolConfig: "0x8aDb5810B5bF8B9149BE3Ca45Cb441818a9679bB",
1418
+ // Not in chains/9994663.json (no PriceRouter on the fork).
1529
1419
  priceRouter: ZERO_ADDRESS,
1530
- tierRegistry: "0x42B089B816F994d792481fAa308199E9CF63be9f",
1531
- callSandboxImpl: ZERO_ADDRESS,
1532
- exposureLedger: "0x223e2Fd41aD6487333146fc3998d000E74CB1549",
1533
- proposerBondEscrow: "0xef2D6994faCad11e6CfAF3DaBf7b0B2091009B05",
1534
- challengeGame: "0x202c1F133006D6706e872433CCAfD729c7A8AE56",
1535
- tokenCourt: "0x5DC603881f5d77f41bbd4202F1d518263Dfd497f"
1420
+ tierRegistry: "0x4614f058920941A0a9a852e62485fbDE692D75E1",
1421
+ exposureLedger: "0x99D789E7C8E65dB5597dCa692F082B47BE30AB33",
1422
+ proposerBondEscrow: "0x7d25058c891d3AC5C8bc8Da6aA937DFeE648B5cF",
1423
+ challengeGame: "0x7046FececcA6c0f5E66Cc998099593ae71A1bbee",
1424
+ tokenCourt: "0xC30bA62727be65fd867385Ce27Ff7C78bd66A897"
1536
1425
  },
1537
1426
  // The fork is ephemeral, so attestation WRITES are disabled there (CLI
1538
1427
  // enforces it). Reads still resolve against the 4663 coordination chain, so
@@ -1554,10 +1443,12 @@ var ROBINHOOD_FORK = {
1554
1443
  // A Tenderly vnet scopes its blocks under /explorer/vnet/<id> — the bare
1555
1444
  // dashboard host resolves to the caller's own dashboard, not this fork.
1556
1445
  explorer: "https://dashboard.tenderly.co/explorer/vnet/6ad5961e-fbca-452f-939f-ca9a8c020933",
1557
- // PUBLIC endpoint of vnet a3fb16: reads + tx broadcast, no state-cheat
1558
- // surface. Admin/cheat RPCs stay private (Tenderly dashboard).
1446
+ // PUBLIC endpoint of the vnet carrying the v1 redeploy: reads + tx
1447
+ // broadcast, no state-cheat surface. Admin/cheat RPCs stay private
1448
+ // (Tenderly dashboard). Retired vnets answer `not_found` rather than a
1449
+ // transport error, so the address book is the tell for which one is live.
1559
1450
  rpcs: [
1560
- "https://virtual.robinhood-chain.eu.rpc.tenderly.co/moonwell/wormhole-bridge/231af1"
1451
+ "https://virtual.robinhood-chain.eu.rpc.tenderly.co/moonwell/wormhole-bridge/f509bc-4fdefe"
1561
1452
  ]
1562
1453
  };
1563
1454
  var REGISTRY = {
@@ -1976,155 +1867,6 @@ function encodePropose(args, chainId) {
1976
1867
  note: "Reverts if the vault has an active proposal (cooldown not elapsed). The strategy address is immutable post-propose; pass address(0) to opt out of live NAV. `coProposers[].splitBps` total must satisfy contract-side constraints."
1977
1868
  };
1978
1869
  }
1979
- var MAX_SANDBOX_CALLS = 32;
1980
- var MAX_SANDBOX_TOKENS = 16;
1981
- function validateSandboxCall(call, idx) {
1982
- if (!call || typeof call !== "object") {
1983
- throw usage(`\`sandbox.calls[${idx}]\` must be an object of {target, data}`);
1984
- }
1985
- const c = call;
1986
- if ("value" in c && c.value !== void 0 && c.value !== null) {
1987
- throw usage(`\`sandbox.calls[${idx}]\` must be (address,bytes) only \u2014 ICallSandbox.Call has no \`value\` field (native value would open an unmetered transfer channel). Do not alias BatchExecutorLib.Call.`);
1988
- }
1989
- if (typeof c.target !== "string" || !isAddress2(c.target)) {
1990
- throw usage(`\`sandbox.calls[${idx}].target\` must be a 0x-prefixed address`);
1991
- }
1992
- if (getAddress2(c.target) === ZERO_ADDRESS2) {
1993
- throw usage(`\`sandbox.calls[${idx}].target\` must not be the zero address (the governor reverts ZeroSandboxTarget)`);
1994
- }
1995
- if (typeof c.data !== "string" || !/^0x[0-9a-fA-F]*$/.test(c.data)) {
1996
- throw usage(`\`sandbox.calls[${idx}].data\` must be a 0x-prefixed hex string`);
1997
- }
1998
- return { target: getAddress2(c.target), data: c.data };
1999
- }
2000
- function validateSandboxPayload(sandbox, maxCapital) {
2001
- if (!sandbox || typeof sandbox !== "object") {
2002
- throw usage("`sandbox` must be an object of {funding, calls, declaredTokens}");
2003
- }
2004
- const s = sandbox;
2005
- const funding = toBigInt(s.funding, "sandbox.funding");
2006
- if (funding === 0n) {
2007
- throw usage("`sandbox.funding` must be > 0 (the governor rejects zero as ZeroSandboxFunding)");
2008
- }
2009
- if (funding > maxCapital) {
2010
- throw usage(`\`sandbox.funding\` (${funding}) exceeds \`envelope.maxCapital\` (${maxCapital}) \u2014 the sandbox is funded out of the declared envelope, not beside it`);
2011
- }
2012
- if (!Array.isArray(s.calls)) {
2013
- throw usage("`sandbox.calls` must be an array of {target, data} objects (no value)");
2014
- }
2015
- if (s.calls.length === 0) {
2016
- throw usage("`sandbox.calls` must be non-empty (the governor rejects empty as EmptySandboxCalls)");
2017
- }
2018
- if (s.calls.length > MAX_SANDBOX_CALLS) {
2019
- throw usage(`\`sandbox.calls\` has ${s.calls.length} entries; max is ${MAX_SANDBOX_CALLS}`);
2020
- }
2021
- const calls = s.calls.map((c, i) => validateSandboxCall(c, i));
2022
- const rawTokens = s.declaredTokens ?? [];
2023
- if (!Array.isArray(rawTokens)) {
2024
- throw usage("`sandbox.declaredTokens` must be an array of addresses");
2025
- }
2026
- if (rawTokens.length > MAX_SANDBOX_TOKENS) {
2027
- throw usage(`\`sandbox.declaredTokens\` has ${rawTokens.length} entries; max is ${MAX_SANDBOX_TOKENS}`);
2028
- }
2029
- const declaredTokens = [];
2030
- const seen = /* @__PURE__ */ new Set();
2031
- for (let i = 0; i < rawTokens.length; i++) {
2032
- const t = rawTokens[i];
2033
- if (typeof t !== "string" || !isAddress2(t)) {
2034
- throw usage(`\`sandbox.declaredTokens[${i}]\` must be a 0x-prefixed address`);
2035
- }
2036
- const addr = getAddress2(t);
2037
- if (seen.has(addr.toLowerCase())) {
2038
- throw usage(`\`sandbox.declaredTokens[${i}]\` duplicates ${addr} (the governor reverts DuplicateSandboxToken)`);
2039
- }
2040
- seen.add(addr.toLowerCase());
2041
- declaredTokens.push(addr);
2042
- }
2043
- return { funding, calls, declaredTokens };
2044
- }
2045
- function encodeProposeWithSandbox(args, chainId) {
2046
- const vault = getAddress2(args.vault);
2047
- const governor = parseGovernor(args.governor);
2048
- const strategy = args.strategy === ZERO_ADDRESS2 ? ZERO_ADDRESS2 : getAddress2(args.strategy);
2049
- if (typeof args.metadataURI !== "string" || args.metadataURI.length === 0) {
2050
- throw usage("`metadataURI` must be a non-empty string (e.g. ipfs://...)");
2051
- }
2052
- const strategyDuration = typeof args.strategyDuration === "bigint" ? args.strategyDuration : BigInt(args.strategyDuration);
2053
- if (strategyDuration <= 0n) {
2054
- throw usage("`strategyDuration` must be > 0 (seconds)");
2055
- }
2056
- if (!Array.isArray(args.executeCalls)) {
2057
- throw usage("`executeCalls` must be an array of {target, data, value} objects");
2058
- }
2059
- if (!Array.isArray(args.settlementCalls)) {
2060
- throw usage("`settlementCalls` must be an array of {target, data, value} objects");
2061
- }
2062
- const executeCalls = args.executeCalls.map((c, i) => validateBatchCall(c, "executeCalls", i));
2063
- const settlementCalls = args.settlementCalls.map((c, i) => validateBatchCall(c, "settlementCalls", i));
2064
- const coProposers = (args.coProposers ?? []).map((cp, i) => {
2065
- if (!cp || typeof cp !== "object") {
2066
- throw usage(`\`coProposers[${i}]\` must be an object`);
2067
- }
2068
- const agent = cp.agent;
2069
- const splitBps = cp.splitBps;
2070
- if (typeof agent !== "string" || !isAddress2(agent)) {
2071
- throw usage(`\`coProposers[${i}].agent\` must be a 0x-prefixed address`);
2072
- }
2073
- let bps;
2074
- if (typeof splitBps === "string" && /^\d+$/.test(splitBps)) {
2075
- bps = BigInt(splitBps);
2076
- } else if (typeof splitBps === "bigint") {
2077
- bps = splitBps;
2078
- } else if (typeof splitBps === "number" && Number.isInteger(splitBps) && splitBps >= 0) {
2079
- bps = BigInt(splitBps);
2080
- } else {
2081
- throw usage(`\`coProposers[${i}].splitBps\` must be a non-negative integer (string, number, or bigint)`);
2082
- }
2083
- if (bps < 0n || bps > 10000n) {
2084
- throw usage(`\`coProposers[${i}].splitBps\` must be in [0, 10000]`);
2085
- }
2086
- return { agent: getAddress2(agent), splitBps: bps };
2087
- });
2088
- if (!args.envelope || typeof args.envelope !== "object") {
2089
- throw usage("`envelope` must be an object of {maxCapital, maxDrawdownBps}");
2090
- }
2091
- const maxCapital = toBigInt(args.envelope.maxCapital, "envelope.maxCapital");
2092
- if (maxCapital === 0n) {
2093
- throw usage("`envelope.maxCapital` must be > 0 (the governor rejects zero as ZeroMaxCapital)");
2094
- }
2095
- const maxDrawdownBps = args.envelope.maxDrawdownBps;
2096
- if (!Number.isInteger(maxDrawdownBps) || maxDrawdownBps < 0 || maxDrawdownBps > 1e4) {
2097
- throw usage("`envelope.maxDrawdownBps` must be an integer in [0, 10000]");
2098
- }
2099
- const executeCallCaps = validateCaps(args.executeCallCaps, executeCalls, maxCapital, "executeCallCaps");
2100
- const settlementCallCaps = validateCaps(args.settlementCallCaps, settlementCalls, maxCapital, "settlementCallCaps");
2101
- const sandbox = validateSandboxPayload(args.sandbox, maxCapital);
2102
- const data = encodeFunctionData2({
2103
- abi: SYNDICATE_GOVERNOR_ABI,
2104
- functionName: "proposeWithSandbox",
2105
- args: [
2106
- sandbox,
2107
- vault,
2108
- strategy,
2109
- args.metadataURI,
2110
- strategyDuration,
2111
- { maxCapital, maxDrawdownBps },
2112
- executeCalls,
2113
- executeCallCaps,
2114
- settlementCalls,
2115
- settlementCallCaps,
2116
- coProposers
2117
- ]
2118
- });
2119
- return {
2120
- txs: [governorTx(governor, chainId, data)],
2121
- preconditions: [
2122
- { type: "vault-not-locked", vault }
2123
- ],
2124
- description: `Propose a sandbox strategy on ${vault} (funding ${sandbox.funding.toString()}, ${sandbox.calls.length} sandbox call(s), duration ${strategyDuration.toString()}s).`,
2125
- note: "Reverts if the vault has an active proposal, has no CallSandbox implementation bound, or the payload fails propose-time sandbox gates (empty calls, zero funding, funding > maxCapital, zero target, duplicate declared tokens). ICallSandbox.Call is (address,bytes) only \u2014 no native value."
2126
- };
2127
- }
2128
1870
  function encodeUnstick(args, chainId) {
2129
1871
  const governor = parseGovernor(args.governor);
2130
1872
  const id = parseProposalId(args.proposalId);
@@ -2632,17 +2374,21 @@ function encodeVoteOnProposal(args, chainId) {
2632
2374
  throw usage("`vote` must be one of: Approve, Block");
2633
2375
  }
2634
2376
  const proposalId = parseUint(args.proposalId, "proposalId");
2377
+ if (typeof args.lockWood !== "bigint" || args.lockWood < 0n) {
2378
+ throw usage("`lockWood` must be a non-negative bigint of WOOD base units");
2379
+ }
2380
+ const lockWood = args.lockWood;
2635
2381
  const data = encodeFunctionData7({
2636
2382
  abi: GUARDIAN_REGISTRY_ABI,
2637
2383
  functionName: "voteOnProposal",
2638
- args: [governor, proposalId, support]
2384
+ args: [governor, proposalId, support, lockWood]
2639
2385
  });
2640
- const underwriting = args.vote === "Approve" ? " APPROVE books coverage against the CALLER'S OWN slashable guardian bond (ExposureLedger.recordApproval). If this proposal is later challenged or slashed, your WOOD stake is at risk \u2014 not another guardian's. An over-exposed guardian books nothing rather than reverting; the vote still lands." : " Block votes do not book coverage. Slash severity is computed at resolveReview from block-side decisiveness.";
2386
+ const underwriting = args.vote === "Approve" ? ` APPROVE books coverage against the CALLER'S OWN slashable guardian bond (ExposureLedger.recordApproval): you declare ${lockWood.toString()} WOOD, the ledger locks that clamped to your free budget. If this proposal is later challenged or slashed, your WOOD stake is at risk \u2014 not another guardian's. An over-exposed guardian books nothing rather than reverting; the vote still lands.` : " Block votes do not book coverage, and `lockWood` is ignored. Slash severity is computed at resolveReview from block-side decisiveness.";
2641
2387
  return {
2642
2388
  txs: [registryTx(chainId, data)],
2643
2389
  preconditions: [],
2644
2390
  description: `Guardian review vote ${args.vote} on proposal ${proposalId.toString()} (governor ${governor}).`,
2645
- note: `voteOnProposal(governor, proposalId, vote) \u2014 3 args, selector 0x3ad95b6d, no slashBps.${underwriting}`
2391
+ note: `voteOnProposal(governor, proposalId, vote, lockWood) \u2014 4 args, selector 0x4915ace5.${underwriting}`
2646
2392
  };
2647
2393
  }
2648
2394
 
@@ -2650,6 +2396,7 @@ function encodeVoteOnProposal(args, chainId) {
2650
2396
  import { getAddress as getAddress8 } from "viem";
2651
2397
 
2652
2398
  // src/commands/identity.ts
2399
+ var COORDINATION_CHAIN_ID = 4663;
2653
2400
  var IDENTITY_REGISTRY_ABI2 = [
2654
2401
  {
2655
2402
  name: "balanceOf",
@@ -2664,63 +2411,77 @@ var IDENTITY_REGISTRY_ABI2 = [
2664
2411
  stateMutability: "view",
2665
2412
  inputs: [{ name: "tokenId", type: "uint256" }],
2666
2413
  outputs: [{ name: "", type: "address" }]
2414
+ },
2415
+ {
2416
+ name: "tokenURI",
2417
+ type: "function",
2418
+ stateMutability: "view",
2419
+ inputs: [{ name: "tokenId", type: "uint256" }],
2420
+ outputs: [{ name: "", type: "string" }]
2667
2421
  }
2668
2422
  ];
2669
- function getAgent0SDK() {
2670
- const key = requirePrivateKey();
2671
- const chain = getChain();
2672
- const sdkConfig = {
2673
- chainId: chain.id,
2674
- rpcUrl: getRpcUrl(),
2675
- privateKey: key
2676
- };
2677
- if (chain.id !== getChainConfig().chain.id) {
2678
- sdkConfig.registryOverrides = {
2679
- [chain.id]: {
2680
- IDENTITY: AGENT_REGISTRY().IDENTITY_REGISTRY,
2681
- REPUTATION: AGENT_REGISTRY().REPUTATION_REGISTRY
2682
- }
2683
- };
2423
+ async function ownedAgentIds(wallet) {
2424
+ const client = getPublicClient();
2425
+ const registry = AGENT_REGISTRY().IDENTITY_REGISTRY;
2426
+ const balance = await client.readContract({
2427
+ address: registry,
2428
+ abi: IDENTITY_REGISTRY_ABI2,
2429
+ functionName: "balanceOf",
2430
+ args: [wallet]
2431
+ });
2432
+ if (balance === 0n) return [];
2433
+ const logs = await client.getLogs({
2434
+ address: registry,
2435
+ event: {
2436
+ type: "event",
2437
+ name: "Transfer",
2438
+ inputs: [
2439
+ { indexed: true, name: "from", type: "address" },
2440
+ { indexed: true, name: "to", type: "address" },
2441
+ { indexed: true, name: "tokenId", type: "uint256" }
2442
+ ]
2443
+ },
2444
+ args: { from: "0x0000000000000000000000000000000000000000", to: wallet },
2445
+ fromBlock: 0n
2446
+ });
2447
+ const minted = [...new Set(logs.map((l) => l.args?.tokenId).filter((id) => id != null))];
2448
+ const owned = [];
2449
+ for (const id of minted) {
2450
+ try {
2451
+ const owner = await client.readContract({
2452
+ address: registry,
2453
+ abi: IDENTITY_REGISTRY_ABI2,
2454
+ functionName: "ownerOf",
2455
+ args: [id]
2456
+ });
2457
+ if (owner.toLowerCase() === wallet.toLowerCase()) owned.push(id);
2458
+ } catch {
2459
+ }
2684
2460
  }
2685
- return new SDK(sdkConfig);
2461
+ return owned;
2462
+ }
2463
+ async function lookupAgentIdsByWallet(wallet) {
2464
+ return withNetwork(COORDINATION_NETWORK, () => ownedAgentIds(wallet));
2686
2465
  }
2687
2466
  async function lookupAgentIdByWallet(wallet) {
2688
- return withNetwork(COORDINATION_NETWORK, async () => {
2689
- const client = getPublicClient();
2690
- const registry = AGENT_REGISTRY().IDENTITY_REGISTRY;
2691
- const balance = await client.readContract({
2692
- address: registry,
2693
- abi: [{
2694
- name: "balanceOf",
2695
- type: "function",
2696
- stateMutability: "view",
2697
- inputs: [{ name: "owner", type: "address" }],
2698
- outputs: [{ name: "", type: "uint256" }]
2699
- }],
2700
- functionName: "balanceOf",
2701
- args: [wallet]
2702
- });
2703
- if (balance === 0n) return null;
2704
- const logs = await client.getLogs({
2705
- address: registry,
2706
- event: {
2707
- type: "event",
2708
- name: "Transfer",
2709
- inputs: [
2710
- { indexed: true, name: "from", type: "address" },
2711
- { indexed: true, name: "to", type: "address" },
2712
- { indexed: true, name: "tokenId", type: "uint256" }
2713
- ]
2714
- },
2715
- args: { from: "0x0000000000000000000000000000000000000000", to: wallet },
2716
- fromBlock: 0n
2467
+ const ids = await lookupAgentIdsByWallet(wallet);
2468
+ return ids[ids.length - 1] ?? null;
2469
+ }
2470
+ async function readIdentityMetadata(tokenId) {
2471
+ try {
2472
+ const uri = await getPublicClient().readContract({
2473
+ address: AGENT_REGISTRY().IDENTITY_REGISTRY,
2474
+ abi: IDENTITY_REGISTRY_ABI2,
2475
+ functionName: "tokenURI",
2476
+ args: [tokenId]
2717
2477
  });
2718
- const last = logs[logs.length - 1];
2719
- return last?.args?.tokenId ?? null;
2720
- });
2478
+ return await resolveMetadataSummary(uri);
2479
+ } catch {
2480
+ return null;
2481
+ }
2721
2482
  }
2722
2483
  function registerIdentityCommands(program) {
2723
- const identity = program.command("identity").description("Manage ERC-8004 agent identity (via Agent0 SDK)");
2484
+ const identity = program.command("identity").description("Manage ERC-8004 agent identity (on Robinhood mainnet, chain 4663)");
2724
2485
  identity.command("mint").description("Register a new ERC-8004 agent identity (required before creating/joining vaults)").requiredOption("--name <name>", "Agent name (e.g. 'Alpha Seeker Agent')").option("--description <desc>", "Agent description", "Sherwood vault agent").option("--image <uri>", "Agent image URI (IPFS recommended)").action(async (opts) => {
2725
2486
  if (isCalldataOnly()) {
2726
2487
  emitCalldata(
@@ -2730,7 +2491,7 @@ function registerIdentityCommands(program) {
2730
2491
  description: opts.description,
2731
2492
  image: opts.image
2732
2493
  },
2733
- 4663
2494
+ COORDINATION_CHAIN_ID
2734
2495
  )
2735
2496
  );
2736
2497
  return;
@@ -2754,7 +2515,7 @@ function registerIdentityCommands(program) {
2754
2515
  }
2755
2516
  const action = encodeIdentityMint(
2756
2517
  { name: opts.name, description: opts.description, image: opts.image },
2757
- 4663
2518
+ COORDINATION_CHAIN_ID
2758
2519
  );
2759
2520
  const tx = action.txs[0];
2760
2521
  const hash = await sendTxWithRetry({
@@ -2815,7 +2576,7 @@ function registerIdentityCommands(program) {
2815
2576
  process.exit(1);
2816
2577
  }
2817
2578
  });
2818
- identity.command("link-virtuals").description("Link a Virtuals economyOS agent identity (ERC-8004 on Base) to this Sherwood install").option("--wallet <address>", "economyOS agent wallet (default: auto-detect via `acp wallet address`)").option("--agent-id <tokenId>", "ERC-8004 token ID on the issuing chain (default: resolve via Agent0 SDK)").option("--chain-id <id>", "Issuing chain ID (4663 = Robinhood Chain, 8453 = Base, 84532 = Base Sepolia)", String(DEFAULT_ISSUING_CHAIN_ID)).option("--binding-sig <hex>", "EIP-191 signature of the binding message by the economyOS wallet").option("--wallet-only", "Link without an ERC-8004 registration \u2014 the economyOS wallet + binding signature are the identity (agentId 0)").action(async (opts) => {
2579
+ identity.command("link-virtuals").description("Link a Virtuals economyOS agent identity (ERC-8004 on Robinhood Chain or Base) to this Sherwood install").option("--wallet <address>", "economyOS agent wallet (default: auto-detect via `acp wallet address`)").option("--agent-id <tokenId>", "ERC-8004 token ID on the issuing chain (default: resolve from that chain's registry)").option("--chain-id <id>", "Issuing chain ID (4663 = Robinhood Chain, 8453 = Base, 84532 = Base Sepolia)", String(DEFAULT_ISSUING_CHAIN_ID)).option("--binding-sig <hex>", "EIP-191 signature of the binding message by the economyOS wallet").option("--wallet-only", "Link without an ERC-8004 registration \u2014 the economyOS wallet + binding signature are the identity (agentId 0)").action(async (opts) => {
2819
2580
  const account = getAccount();
2820
2581
  const issuingChainId = opts.walletOnly ? WALLET_ONLY_CHAIN_ID : parseInt(opts.chainId, 10);
2821
2582
  if (!opts.walletOnly && !ISSUING_CHAINS[issuingChainId]) {
@@ -2844,6 +2605,24 @@ function registerIdentityCommands(program) {
2844
2605
  tokenId = 0n;
2845
2606
  } else if (opts.agentId) {
2846
2607
  tokenId = BigInt(opts.agentId);
2608
+ } else if (issuingChainId === COORDINATION_CHAIN_ID) {
2609
+ spinner.text = `Searching the ERC-8004 registry on Robinhood mainnet (${COORDINATION_CHAIN_ID}) for ${virtualsWallet}...`;
2610
+ const ids = await lookupAgentIdsByWallet(virtualsWallet);
2611
+ if (ids.length === 0) {
2612
+ spinner.fail(`No ERC-8004 registration found for ${virtualsWallet} on chain ${issuingChainId}`);
2613
+ console.error(chalk.dim(" Register first via the Virtuals CLI:"));
2614
+ console.error(chalk.dim(` acp agent register-erc8004 --agent-id ${virtualsAgentId ?? "<id>"} --chain-id ${issuingChainId}`));
2615
+ console.error(chalk.dim(" Then re-run this command (or pass --agent-id <tokenId> directly)."));
2616
+ console.error(chalk.dim(" No registration possible yet? Link without one: --wallet-only"));
2617
+ process.exit(1);
2618
+ }
2619
+ if (ids.length > 1) {
2620
+ spinner.fail(`Wallet ${virtualsWallet} has ${ids.length} ERC-8004 registrations on chain ${issuingChainId} \u2014 pick one explicitly`);
2621
+ for (const id of ids) console.error(chalk.dim(` #${id}`));
2622
+ console.error(chalk.green(" Re-run with: sherwood identity link-virtuals --agent-id <tokenId>"));
2623
+ process.exit(1);
2624
+ }
2625
+ tokenId = ids[0];
2847
2626
  } else {
2848
2627
  spinner.text = `Searching ERC-8004 registry on chain ${issuingChainId} for ${virtualsWallet}...`;
2849
2628
  const sdk = new SDK({
@@ -2947,40 +2726,41 @@ function registerIdentityCommands(program) {
2947
2726
  process.exit(1);
2948
2727
  }
2949
2728
  });
2950
- identity.command("find").description("Search ERC-8004 agents by wallet address or name (recover a lost agent ID)").option("--wallet <address>", "Filter by owner / wallet address").option("--name <text>", "Filter by agent name (exact or substring match, depending on registry)").option("--all-chains", "Search across all chains, not just the active one").action(async (opts) => {
2951
- if (!opts.wallet && !opts.name) {
2952
- console.error(chalk.red("Pass --wallet <address> or --name <text> (or both)."));
2729
+ identity.command("find").description("Find ERC-8004 agent identities held by a wallet (recover a lost agent ID)").option("--wallet <address>", "Owner / wallet address").option("--name <text>", "(unsupported \u2014 name search needs an indexer; see the error it prints)").action(async (opts) => {
2730
+ if (opts.name) {
2731
+ console.error(chalk.red("Name search is not available."));
2732
+ console.error(chalk.dim(" Identity lives on Robinhood mainnet (4663) and no indexer covers that chain,"));
2733
+ console.error(chalk.dim(" so there is nothing to query by name. Search by owner instead:"));
2734
+ console.error(chalk.dim(" sherwood identity find --wallet <address>"));
2953
2735
  process.exit(1);
2954
2736
  }
2955
- const spinner = ora("Searching ERC-8004 registry...").start();
2737
+ if (!opts.wallet || !isAddress3(opts.wallet)) {
2738
+ console.error(chalk.red("Pass --wallet <address> (a 0x-prefixed address)."));
2739
+ process.exit(1);
2740
+ }
2741
+ const wallet = getAddress9(opts.wallet);
2742
+ const spinner = ora(`Searching the ERC-8004 registry on Robinhood mainnet (${COORDINATION_CHAIN_ID})...`).start();
2956
2743
  try {
2957
- const sdk = getAgent0SDK();
2958
- const filters = {};
2959
- if (opts.wallet) filters.walletAddress = opts.wallet;
2960
- if (opts.name) filters.name = opts.name;
2961
- filters.chains = opts.allChains ? "all" : [getChain().id];
2962
- const results = await sdk.searchAgents(filters);
2744
+ const found = await withNetwork(COORDINATION_NETWORK, async () => {
2745
+ const ids = await ownedAgentIds(wallet);
2746
+ return Promise.all(ids.map(async (id) => ({ id, meta: await readIdentityMetadata(id) })));
2747
+ });
2963
2748
  spinner.stop();
2964
- if (results.length === 0) {
2965
- console.log(chalk.dim("No agents found matching those filters."));
2966
- console.log(chalk.dim("If you minted on a different chain, retry with --all-chains."));
2749
+ if (found.length === 0) {
2750
+ console.log(chalk.dim(`No identity minted to ${wallet} on Robinhood mainnet (${COORDINATION_CHAIN_ID}).`));
2751
+ console.log(chalk.dim(" Mint one: sherwood identity mint --name <name>"));
2752
+ console.log(chalk.dim(" Already have one you received by transfer? Bind it directly:"));
2753
+ console.log(chalk.dim(" sherwood identity load --id <tokenId>"));
2967
2754
  return;
2968
2755
  }
2969
2756
  console.log();
2970
- console.log(chalk.bold(`Found ${results.length} agent${results.length === 1 ? "" : "s"}`));
2757
+ console.log(chalk.bold(`Found ${found.length} agent${found.length === 1 ? "" : "s"}`));
2971
2758
  console.log(chalk.dim("\u2500".repeat(50)));
2972
- for (const a of results) {
2973
- const idStr = String(a.agentId);
2974
- const tokenId = idStr.includes(":") ? idStr.split(":")[1] : idStr;
2975
- console.log(` ${chalk.bold(`#${tokenId}`)} ${a.name || chalk.dim("(no name)")}`);
2976
- console.log(chalk.dim(` Chain: ${a.chainId}`));
2977
- console.log(chalk.dim(` Full: ${idStr}`));
2978
- if (a.owners?.length) {
2979
- console.log(chalk.dim(` Owner: ${a.owners[0]}`));
2980
- }
2981
- if (a.walletAddress) {
2982
- console.log(chalk.dim(` Wallet: ${a.walletAddress}`));
2983
- }
2759
+ for (const { id, meta } of found) {
2760
+ console.log(` ${chalk.bold(`#${id}`)} ${meta?.name || chalk.dim("(no name)")}`);
2761
+ console.log(chalk.dim(` Chain: Robinhood mainnet (${COORDINATION_CHAIN_ID})`));
2762
+ console.log(chalk.dim(` Owner: ${wallet}`));
2763
+ if (meta?.description) console.log(chalk.dim(` Desc: ${meta.description}`));
2984
2764
  }
2985
2765
  console.log();
2986
2766
  console.log(chalk.green("To bind one of these to this machine:"));
@@ -2995,7 +2775,7 @@ function registerIdentityCommands(program) {
2995
2775
  const account = getAccount();
2996
2776
  if (getIdentityProvider() === "virtuals") {
2997
2777
  const virtuals = getVirtualsIdentity();
2998
- const savedId = getAgentId();
2778
+ const savedId2 = getAgentId();
2999
2779
  const issuingChainId = getIdentityChainId();
3000
2780
  console.log();
3001
2781
  console.log(chalk.bold("Agent Identity (ERC-8004 via Virtuals economyOS)"));
@@ -3005,14 +2785,14 @@ function registerIdentityCommands(program) {
3005
2785
  if (virtuals?.agentId) console.log(` Virtuals agent: ${virtuals.agentId}`);
3006
2786
  const walletOnly = issuingChainId === WALLET_ONLY_CHAIN_ID;
3007
2787
  console.log(` Issuing chain: ${walletOnly ? chalk.yellow("wallet-only (no ERC-8004)") : issuingChainId ?? chalk.red("(missing)")}`);
3008
- console.log(` Saved ID: ${savedId != null ? walletOnly ? chalk.dim("0 (wallet-only)") : `#${savedId}` : chalk.red("(missing)")}`);
3009
- if (virtuals?.wallet && savedId != null && issuingChainId != null) {
2788
+ console.log(` Saved ID: ${savedId2 != null ? walletOnly ? chalk.dim("0 (wallet-only)") : `#${savedId2}` : chalk.red("(missing)")}`);
2789
+ if (virtuals?.wallet && savedId2 != null && issuingChainId != null) {
3010
2790
  const spinner2 = ora("Re-verifying link...").start();
3011
2791
  try {
3012
2792
  let ownerOk = true;
3013
2793
  let owner;
3014
2794
  if (!walletOnly) {
3015
- owner = await ownerOfOnIssuingChain(issuingChainId, BigInt(savedId));
2795
+ owner = await ownerOfOnIssuingChain(issuingChainId, BigInt(savedId2));
3016
2796
  ownerOk = owner.toLowerCase() === virtuals.wallet.toLowerCase();
3017
2797
  }
3018
2798
  let bindingOk = virtuals.wallet.toLowerCase() === account.address.toLowerCase();
@@ -3020,7 +2800,7 @@ function registerIdentityCommands(program) {
3020
2800
  bindingOk = await verifyBinding({
3021
2801
  sherwoodEoa: account.address,
3022
2802
  issuingChainId,
3023
- tokenId: BigInt(savedId),
2803
+ tokenId: BigInt(savedId2),
3024
2804
  virtualsWallet: virtuals.wallet,
3025
2805
  signature: virtuals.binding.sig
3026
2806
  });
@@ -3047,86 +2827,79 @@ function registerIdentityCommands(program) {
3047
2827
  console.log();
3048
2828
  return;
3049
2829
  }
3050
- const registry = AGENT_REGISTRY().IDENTITY_REGISTRY;
3051
- const client = getPublicClient();
3052
- const spinner = ora("Checking identity...").start();
2830
+ const savedId = getAgentId();
2831
+ const hasSavedId = savedId != null && savedId !== 0;
2832
+ const spinner = ora(`Checking identity on Robinhood mainnet (${COORDINATION_CHAIN_ID})...`).start();
3053
2833
  try {
3054
- const balance = await client.readContract({
3055
- address: registry,
3056
- abi: IDENTITY_REGISTRY_ABI2,
3057
- functionName: "balanceOf",
3058
- args: [account.address]
2834
+ const state = await withNetwork(COORDINATION_NETWORK, async () => {
2835
+ const registry = AGENT_REGISTRY().IDENTITY_REGISTRY;
2836
+ const client = getPublicClient();
2837
+ const balance = await client.readContract({
2838
+ address: registry,
2839
+ abi: IDENTITY_REGISTRY_ABI2,
2840
+ functionName: "balanceOf",
2841
+ args: [account.address]
2842
+ });
2843
+ let owner = null;
2844
+ let meta = null;
2845
+ if (hasSavedId) {
2846
+ try {
2847
+ owner = await client.readContract({
2848
+ address: registry,
2849
+ abi: IDENTITY_REGISTRY_ABI2,
2850
+ functionName: "ownerOf",
2851
+ args: [BigInt(savedId)]
2852
+ });
2853
+ } catch {
2854
+ owner = null;
2855
+ }
2856
+ if (owner?.toLowerCase() === account.address.toLowerCase()) {
2857
+ meta = await readIdentityMetadata(BigInt(savedId));
2858
+ }
2859
+ }
2860
+ const owned = !hasSavedId && balance > 0n ? await ownedAgentIds(account.address) : [];
2861
+ return { registry, balance, owner, meta, owned };
3059
2862
  });
3060
2863
  spinner.stop();
3061
- const savedId = getAgentId();
3062
2864
  console.log();
3063
2865
  console.log(chalk.bold("Agent Identity (ERC-8004)"));
3064
2866
  console.log(chalk.dim("\u2500".repeat(40)));
3065
2867
  console.log(` Wallet: ${account.address}`);
3066
- console.log(` Registry: ${registry}`);
3067
- console.log(` NFTs owned: ${balance.toString()}`);
3068
- if (savedId) {
3069
- try {
3070
- const owner = await client.readContract({
3071
- address: registry,
3072
- abi: IDENTITY_REGISTRY_ABI2,
3073
- functionName: "ownerOf",
3074
- args: [BigInt(savedId)]
3075
- });
3076
- const isOwner = owner.toLowerCase() === account.address.toLowerCase();
3077
- console.log(` Saved ID: #${savedId} ${isOwner ? chalk.green("(verified)") : chalk.red("(owned by " + owner + ")")}`);
3078
- if (isOwner) {
3079
- try {
3080
- const sdk = getAgent0SDK();
3081
- const agent = await sdk.loadAgent(`${getChain().id}:${savedId}`);
3082
- if (agent.name) console.log(` Name: ${agent.name}`);
3083
- if (agent.description) console.log(` Desc: ${chalk.dim(agent.description)}`);
3084
- if (agent.walletAddress) console.log(` Wallet: ${agent.walletAddress}`);
3085
- } catch {
3086
- }
3087
- }
3088
- } catch {
2868
+ console.log(` Chain: Robinhood mainnet (${COORDINATION_CHAIN_ID}) \u2014 the coordination chain`);
2869
+ console.log(` Registry: ${state.registry}`);
2870
+ console.log(` NFTs owned: ${state.balance.toString()}`);
2871
+ if (hasSavedId) {
2872
+ if (state.owner == null) {
3089
2873
  console.log(` Saved ID: #${savedId} ${chalk.red("(token not found)")}`);
2874
+ } else {
2875
+ const isOwner = state.owner.toLowerCase() === account.address.toLowerCase();
2876
+ console.log(` Saved ID: #${savedId} ${isOwner ? chalk.green("(verified)") : chalk.red("(owned by " + state.owner + ")")}`);
2877
+ console.log(` Owner: ${state.owner}`);
2878
+ if (state.meta?.name) console.log(` Name: ${state.meta.name}`);
2879
+ if (state.meta?.description) console.log(` Desc: ${chalk.dim(state.meta.description)}`);
3090
2880
  }
3091
2881
  console.log();
3092
- } else if (balance > 0n) {
3093
- console.log(` Saved ID: ${chalk.yellow("none (but this wallet owns NFTs \u2014 listing below)")}`);
2882
+ } else if (state.owned.length > 0) {
2883
+ console.log(` Saved ID: ${chalk.yellow("none (but this wallet owns identities \u2014 listing below)")}`);
3094
2884
  console.log();
3095
- const lookupSpinner = ora("Resolving owned token IDs via Agent0 SDK...").start();
3096
- try {
3097
- const sdk = getAgent0SDK();
3098
- const results = await sdk.searchAgents({
3099
- walletAddress: account.address,
3100
- chains: [getChain().id]
3101
- });
3102
- lookupSpinner.stop();
3103
- if (results.length === 0) {
3104
- console.log(chalk.dim(" No agents resolved for this wallet on the active chain."));
3105
- console.log(chalk.dim(" If you minted on a different chain, try:"));
3106
- console.log(chalk.dim(" sherwood identity find --wallet " + account.address + " --all-chains"));
3107
- } else {
3108
- console.log(chalk.bold(` Owned identities on this chain (${results.length}):`));
3109
- for (const a of results) {
3110
- const idStr = String(a.agentId);
3111
- const tokenId = idStr.includes(":") ? idStr.split(":")[1] : idStr;
3112
- console.log(` ${chalk.bold(`#${tokenId}`)} ${a.name || chalk.dim("(no name)")}`);
3113
- }
3114
- console.log();
3115
- console.log(chalk.green(" Bind one to this machine:"));
3116
- if (results.length === 1) {
3117
- const idStr = String(results[0].agentId);
3118
- const tokenId = idStr.includes(":") ? idStr.split(":")[1] : idStr;
3119
- console.log(chalk.dim(` sherwood identity load --id ${tokenId}`));
3120
- } else {
3121
- console.log(chalk.dim(" sherwood identity load --id <tokenId>"));
3122
- }
3123
- }
3124
- } catch (err) {
3125
- lookupSpinner.warn("Could not resolve owned token IDs via Agent0 SDK");
3126
- console.log(chalk.dim(` ${err.message}`));
3127
- console.log(chalk.dim(" Try: sherwood identity find --wallet " + account.address));
2885
+ console.log(chalk.bold(` Identities held by this wallet (${state.owned.length}):`));
2886
+ for (const id of state.owned) {
2887
+ console.log(` ${chalk.bold(`#${id}`)}`);
3128
2888
  }
3129
2889
  console.log();
2890
+ console.log(chalk.green(" Bind one to this machine:"));
2891
+ console.log(
2892
+ chalk.dim(
2893
+ state.owned.length === 1 ? ` sherwood identity load --id ${state.owned[0]}` : " sherwood identity load --id <tokenId>"
2894
+ )
2895
+ );
2896
+ console.log();
2897
+ } else if (state.balance > 0n) {
2898
+ console.log(` Saved ID: ${chalk.yellow("none")}`);
2899
+ console.log(chalk.dim(" This wallet holds identities that were not minted to it, and the"));
2900
+ console.log(chalk.dim(" registry is not enumerable \u2014 bind yours by id:"));
2901
+ console.log(chalk.dim(" sherwood identity load --id <tokenId>"));
2902
+ console.log();
3130
2903
  } else {
3131
2904
  console.log(` Saved ID: ${chalk.dim("none \u2014 run 'sherwood identity mint --name <name>'")}`);
3132
2905
  console.log();
@@ -3140,9 +2913,7 @@ function registerIdentityCommands(program) {
3140
2913
  }
3141
2914
 
3142
2915
  export {
3143
- setCalldataOnly,
3144
- isCalldataOnly,
3145
- emitCalldata,
2916
+ STRATEGY_FACTORY_ABI,
3146
2917
  encodeDeposit,
3147
2918
  encodeRedeem,
3148
2919
  encodeApproveDepositor,
@@ -3152,26 +2923,32 @@ export {
3152
2923
  encodeSettle,
3153
2924
  encodeCancel,
3154
2925
  encodePropose,
3155
- encodeProposeWithSandbox,
3156
2926
  encodeUnstick,
3157
2927
  encodeEmergencySettle,
3158
2928
  encodeGovernorParam,
3159
2929
  encodeMgmtSplit,
3160
2930
  encodePerfSplit,
3161
2931
  encodeCreateFund,
2932
+ predictStrategyCloneAddress,
2933
+ deriveStrategySalt,
2934
+ effectiveStrategySalt,
3162
2935
  encodeStrategyDeploy,
3163
2936
  encodeJoinRequest,
3164
2937
  encodeApproveAgent,
3165
2938
  encodeGuardianStake,
3166
2939
  encodeGuardianUnstake,
3167
2940
  encodeVoteOnProposal,
2941
+ setCalldataOnly,
2942
+ isCalldataOnly,
2943
+ emitCalldata,
3168
2944
  DEFAULT_ISSUING_CHAIN_ID,
3169
2945
  appendVidTag,
3170
2946
  parseVidTag,
3171
2947
  stripVidTag,
3172
2948
  verifyVidTag,
3173
2949
  makeOwnerOfCache,
2950
+ lookupAgentIdsByWallet,
3174
2951
  lookupAgentIdByWallet,
3175
2952
  registerIdentityCommands
3176
2953
  };
3177
- //# sourceMappingURL=chunk-6QBGTX2Q.js.map
2954
+ //# sourceMappingURL=chunk-VYCLG5DE.js.map