@sherwoodagent/cli 0.74.2 → 0.75.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 (65) hide show
  1. package/dist/{abis-D7EDCKVZ.js → abis-OLIDCWDS.js} +2 -2
  2. package/dist/{addresses-OFFTM6NG.js → addresses-JJPQTF6S.js} +4 -4
  3. package/dist/{agent-IJOOONON.js → agent-FYRYTKYM.js} +8 -8
  4. package/dist/{chat-3PM3GP3C.js → chat-CO244AHH.js} +9 -9
  5. package/dist/{chunk-6MV4ESXM.js → chunk-3TZIOAPH.js} +25 -1
  6. package/dist/chunk-3TZIOAPH.js.map +1 -0
  7. package/dist/{chunk-RE3PPAXZ.js → chunk-EVTDWMXQ.js} +5 -5
  8. package/dist/{chunk-RE3PPAXZ.js.map → chunk-EVTDWMXQ.js.map} +1 -1
  9. package/dist/{chunk-2OHX3O55.js → chunk-FP5DZCOM.js} +3 -3
  10. package/dist/{chunk-UINMHN6S.js → chunk-I6X6NL65.js} +2 -2
  11. package/dist/{chunk-LHVSS27T.js → chunk-LSVCF24W.js} +2 -2
  12. package/dist/{chunk-RAP6MUMB.js → chunk-M7CGUYUX.js} +7 -7
  13. package/dist/{chunk-7BMCLMSE.js → chunk-MEMYGZWQ.js} +3 -3
  14. package/dist/{chunk-BD4ZV7FQ.js → chunk-RGFA732Z.js} +3 -3
  15. package/dist/{chunk-DGLLSZ2D.js → chunk-T2HVR3O6.js} +2 -2
  16. package/dist/{chunk-WBQMGZ5X.js → chunk-TI64P5R4.js} +5 -5
  17. package/dist/{chunk-JF7KAVOM.js → chunk-TN7J5LXW.js} +5 -5
  18. package/dist/{chunk-I2PC6TBZ.js → chunk-TU655ZTV.js} +1 -22
  19. package/dist/chunk-TU655ZTV.js.map +1 -0
  20. package/dist/{chunk-N3NVFSDQ.js → chunk-WCX7DKLQ.js} +5 -5
  21. package/dist/{chunk-MUINMYCE.js → chunk-WGXZ623D.js} +5 -5
  22. package/dist/{client-C3C6IXAH.js → client-GRPJRISD.js} +4 -4
  23. package/dist/{config-7HU4X7EK.js → config-ZGFS4I7K.js} +12 -4
  24. package/dist/{eas-G4TPLJ6S.js → eas-4RIW3IS4.js} +7 -7
  25. package/dist/{governor-PYQQ7QRG.js → governor-7KETSN47.js} +7 -7
  26. package/dist/index.js +411 -62
  27. package/dist/index.js.map +1 -1
  28. package/dist/{network-WU2QC3L4.js → network-UP2X5XDW.js} +3 -3
  29. package/dist/{price-DGGB6W2G.js → price-LAQSXN7M.js} +7 -7
  30. package/dist/{providers-YOOQFBN2.js → providers-2J6LL67W.js} +5 -5
  31. package/dist/{research-KX3LCAOQ.js → research-FHQCSLTZ.js} +9 -9
  32. package/dist/{session-GUVSID3Z.js → session-JQ3IF3IV.js} +12 -12
  33. package/dist/{trade-WDPMFFYB.js → trade-5EYPZN7M.js} +18 -18
  34. package/dist/{vault-WDRLJLJ6.js → vault-5YYTHS5W.js} +9 -9
  35. package/dist/{xmtp-Q4ZSQV2Q.js → xmtp-OZ5PJFCT.js} +7 -7
  36. package/package.json +1 -1
  37. package/dist/chunk-6MV4ESXM.js.map +0 -1
  38. package/dist/chunk-I2PC6TBZ.js.map +0 -1
  39. /package/dist/{abis-D7EDCKVZ.js.map → abis-OLIDCWDS.js.map} +0 -0
  40. /package/dist/{addresses-OFFTM6NG.js.map → addresses-JJPQTF6S.js.map} +0 -0
  41. /package/dist/{agent-IJOOONON.js.map → agent-FYRYTKYM.js.map} +0 -0
  42. /package/dist/{chat-3PM3GP3C.js.map → chat-CO244AHH.js.map} +0 -0
  43. /package/dist/{chunk-2OHX3O55.js.map → chunk-FP5DZCOM.js.map} +0 -0
  44. /package/dist/{chunk-UINMHN6S.js.map → chunk-I6X6NL65.js.map} +0 -0
  45. /package/dist/{chunk-LHVSS27T.js.map → chunk-LSVCF24W.js.map} +0 -0
  46. /package/dist/{chunk-RAP6MUMB.js.map → chunk-M7CGUYUX.js.map} +0 -0
  47. /package/dist/{chunk-7BMCLMSE.js.map → chunk-MEMYGZWQ.js.map} +0 -0
  48. /package/dist/{chunk-BD4ZV7FQ.js.map → chunk-RGFA732Z.js.map} +0 -0
  49. /package/dist/{chunk-DGLLSZ2D.js.map → chunk-T2HVR3O6.js.map} +0 -0
  50. /package/dist/{chunk-WBQMGZ5X.js.map → chunk-TI64P5R4.js.map} +0 -0
  51. /package/dist/{chunk-JF7KAVOM.js.map → chunk-TN7J5LXW.js.map} +0 -0
  52. /package/dist/{chunk-N3NVFSDQ.js.map → chunk-WCX7DKLQ.js.map} +0 -0
  53. /package/dist/{chunk-MUINMYCE.js.map → chunk-WGXZ623D.js.map} +0 -0
  54. /package/dist/{client-C3C6IXAH.js.map → client-GRPJRISD.js.map} +0 -0
  55. /package/dist/{config-7HU4X7EK.js.map → config-ZGFS4I7K.js.map} +0 -0
  56. /package/dist/{eas-G4TPLJ6S.js.map → eas-4RIW3IS4.js.map} +0 -0
  57. /package/dist/{governor-PYQQ7QRG.js.map → governor-7KETSN47.js.map} +0 -0
  58. /package/dist/{network-WU2QC3L4.js.map → network-UP2X5XDW.js.map} +0 -0
  59. /package/dist/{price-DGGB6W2G.js.map → price-LAQSXN7M.js.map} +0 -0
  60. /package/dist/{providers-YOOQFBN2.js.map → providers-2J6LL67W.js.map} +0 -0
  61. /package/dist/{research-KX3LCAOQ.js.map → research-FHQCSLTZ.js.map} +0 -0
  62. /package/dist/{session-GUVSID3Z.js.map → session-JQ3IF3IV.js.map} +0 -0
  63. /package/dist/{trade-WDPMFFYB.js.map → trade-5EYPZN7M.js.map} +0 -0
  64. /package/dist/{vault-WDRLJLJ6.js.map → vault-5YYTHS5W.js.map} +0 -0
  65. /package/dist/{xmtp-Q4ZSQV2Q.js.map → xmtp-OZ5PJFCT.js.map} +0 -0
package/dist/index.js CHANGED
@@ -15,7 +15,7 @@ import {
15
15
  checkApiKeyValid,
16
16
  listModels,
17
17
  provisionApiKey
18
- } from "./chunk-BD4ZV7FQ.js";
18
+ } from "./chunk-RGFA732Z.js";
19
19
  import {
20
20
  approveDepositor,
21
21
  deposit,
@@ -38,8 +38,8 @@ import {
38
38
  removeDepositor,
39
39
  setAgentFeeBps,
40
40
  setVaultAddress
41
- } from "./chunk-RAP6MUMB.js";
42
- import "./chunk-7BMCLMSE.js";
41
+ } from "./chunk-M7CGUYUX.js";
42
+ import "./chunk-MEMYGZWQ.js";
43
43
  import {
44
44
  applySlippage,
45
45
  assetDecimalsForSymbol,
@@ -50,7 +50,7 @@ import {
50
50
  getMultiHopQuote,
51
51
  getQuote,
52
52
  resolveToken
53
- } from "./chunk-WBQMGZ5X.js";
53
+ } from "./chunk-TI64P5R4.js";
54
54
  import {
55
55
  createApproval,
56
56
  createJoinRequest,
@@ -61,20 +61,20 @@ import {
61
61
  queryJoinRequests,
62
62
  revokeJoinRequest,
63
63
  stripReferrerPrefix
64
- } from "./chunk-N3NVFSDQ.js";
64
+ } from "./chunk-WCX7DKLQ.js";
65
65
  import {
66
66
  createFund,
67
67
  getActiveFunds,
68
68
  getFund,
69
69
  subdomainExists,
70
70
  updateMetadata
71
- } from "./chunk-MUINMYCE.js";
71
+ } from "./chunk-WGXZ623D.js";
72
72
  import {
73
73
  resolveFund,
74
74
  resolveVaultFund,
75
75
  searchFundAcrossChains,
76
76
  setTextRecord
77
- } from "./chunk-JF7KAVOM.js";
77
+ } from "./chunk-TN7J5LXW.js";
78
78
  import {
79
79
  PROPOSAL_STATE,
80
80
  PROPOSAL_STATES,
@@ -108,7 +108,7 @@ import {
108
108
  setVotingPeriod,
109
109
  settleProposal,
110
110
  vote
111
- } from "./chunk-RE3PPAXZ.js";
111
+ } from "./chunk-EVTDWMXQ.js";
112
112
  import {
113
113
  AERODROME,
114
114
  AGENT_REGISTRY,
@@ -118,7 +118,7 @@ import {
118
118
  TOKENS,
119
119
  UNISWAP,
120
120
  VENICE
121
- } from "./chunk-UINMHN6S.js";
121
+ } from "./chunk-I6X6NL65.js";
122
122
  import {
123
123
  GAS_UNITS,
124
124
  estimateGasCushion,
@@ -129,7 +129,7 @@ import {
129
129
  sendTxWithRetry,
130
130
  waitForReceipt,
131
131
  writeContractWithRetry
132
- } from "./chunk-2OHX3O55.js";
132
+ } from "./chunk-FP5DZCOM.js";
133
133
  import {
134
134
  DEFAULT_NETWORK,
135
135
  VALID_NETWORKS,
@@ -141,7 +141,7 @@ import {
141
141
  isTestnet,
142
142
  setNetwork,
143
143
  withNetwork
144
- } from "./chunk-LHVSS27T.js";
144
+ } from "./chunk-LSVCF24W.js";
145
145
  import {
146
146
  addFund,
147
147
  cacheGroupId,
@@ -149,10 +149,13 @@ import {
149
149
  getCachedGroupId,
150
150
  getChainContracts,
151
151
  getFunds,
152
+ getIdentityChainId,
153
+ getIdentityProvider,
152
154
  getNotifyTo,
153
155
  getPrimaryFund,
154
156
  getUniswapApiKey,
155
157
  getVeniceApiKey,
158
+ getVirtualsIdentity,
156
159
  loadConfig,
157
160
  requirePrivateKey,
158
161
  setAgentId,
@@ -163,8 +166,9 @@ import {
163
166
  setPrimaryFund,
164
167
  setPrivateKey,
165
168
  setUniswapApiKey,
166
- setVeniceApiKey
167
- } from "./chunk-6MV4ESXM.js";
169
+ setVeniceApiKey,
170
+ setVirtualsIdentity
171
+ } from "./chunk-3TZIOAPH.js";
168
172
  import {
169
173
  BASE_STRATEGY_ABI,
170
174
  ERC20_ABI,
@@ -174,7 +178,7 @@ import {
174
178
  SWAP_ROUTER_EXACT_INPUT_SINGLE_ABI,
175
179
  SYNDICATE_VAULT_ABI,
176
180
  VENICE_STAKING_ABI
177
- } from "./chunk-I2PC6TBZ.js";
181
+ } from "./chunk-TU655ZTV.js";
178
182
  import {
179
183
  fetchMetadata,
180
184
  mergeFundMetadata,
@@ -185,7 +189,7 @@ import {
185
189
  import { config as loadDotenv } from "dotenv";
186
190
  import { createRequire } from "module";
187
191
  import { Command, Option } from "commander";
188
- import { parseUnits as parseUnits8, formatUnits as formatUnits7, isAddress as isAddress9 } from "viem";
192
+ import { parseUnits as parseUnits8, formatUnits as formatUnits7, isAddress as isAddress10 } from "viem";
189
193
  import chalk16 from "chalk";
190
194
  import ora9 from "ora";
191
195
  import { input, confirm, select } from "@inquirer/prompts";
@@ -2432,7 +2436,7 @@ function registerStrategyTemplateCommands(strategy2) {
2432
2436
  process.exit(1);
2433
2437
  }
2434
2438
  if (!opts.agent) opts.agent = proposer;
2435
- const { parseDuration: parseDuration3, getGovernorOf: getGovernorOf2 } = await import("./governor-PYQQ7QRG.js");
2439
+ const { parseDuration: parseDuration3, getGovernorOf: getGovernorOf2 } = await import("./governor-7KETSN47.js");
2436
2440
  const strategyDuration2 = parseDuration3(opts.duration);
2437
2441
  const chainId = getChain().id;
2438
2442
  try {
@@ -2658,9 +2662,9 @@ function registerStrategyTemplateCommands(strategy2) {
2658
2662
  console.error(chalk.red("Missing --name or --duration. Use --write-calls to skip proposal submission."));
2659
2663
  process.exit(1);
2660
2664
  }
2661
- const { propose: propose2 } = await import("./governor-PYQQ7QRG.js");
2665
+ const { propose: propose2 } = await import("./governor-7KETSN47.js");
2662
2666
  const { pinJSON } = await import("./ipfs-RWSTXTZM.js");
2663
- const { parseDuration: parseDuration2 } = await import("./governor-PYQQ7QRG.js");
2667
+ const { parseDuration: parseDuration2 } = await import("./governor-7KETSN47.js");
2664
2668
  const strategyDuration = parseDuration2(opts.duration);
2665
2669
  const metaSpinner = ora("Pinning metadata to IPFS...").start();
2666
2670
  let metadataURI;
@@ -2683,7 +2687,7 @@ function registerStrategyTemplateCommands(strategy2) {
2683
2687
  process.exit(1);
2684
2688
  }
2685
2689
  try {
2686
- const { getAgentFeeBps: getAgentFeeBps2 } = await import("./vault-WDRLJLJ6.js");
2690
+ const { getAgentFeeBps: getAgentFeeBps2 } = await import("./vault-5YYTHS5W.js");
2687
2691
  const feeBps = await getAgentFeeBps2(vault);
2688
2692
  console.log(
2689
2693
  chalk.yellow(
@@ -2771,7 +2775,7 @@ function registerStrategyTemplateCommands(strategy2) {
2771
2775
  let prices = [];
2772
2776
  let priceSource = null;
2773
2777
  try {
2774
- const { getTokenPricesInAsset } = await import("./price-DGGB6W2G.js");
2778
+ const { getTokenPricesInAsset } = await import("./price-LAQSXN7M.js");
2775
2779
  prices = await getTokenPricesInAsset({
2776
2780
  tokens: allocations.map((a, i) => ({
2777
2781
  token: a.token,
@@ -3201,7 +3205,7 @@ function registerVeniceCommands(program2) {
3201
3205
  console.log(chalk2.dim(` Key: ${apiKey.slice(0, 8)}...${apiKey.slice(-4)}`));
3202
3206
  console.log(chalk2.dim(" Saved to ~/.sherwood/config.json"));
3203
3207
  try {
3204
- const { createVeniceProvisionAttestation, getEasScanUrl: getEasScanUrl2 } = await import("./eas-G4TPLJ6S.js");
3208
+ const { createVeniceProvisionAttestation, getEasScanUrl: getEasScanUrl2 } = await import("./eas-4RIW3IS4.js");
3205
3209
  const { uid } = await createVeniceProvisionAttestation(account.address);
3206
3210
  if (uid !== "0x0000000000000000000000000000000000000000000000000000000000000000") {
3207
3211
  console.log(chalk2.dim(` Attested: ${getEasScanUrl2(uid)}`));
@@ -3557,10 +3561,10 @@ ${opts.prompt}`;
3557
3561
  console.log(chalk2.dim(`Model: ${result.model} | Tokens: ${result.usage.promptTokens} in, ${result.usage.completionTokens} out, ${result.usage.totalTokens} total`));
3558
3562
  }
3559
3563
  try {
3560
- const { createVeniceInferenceAttestation, getEasScanUrl: getEasScanUrl2 } = await import("./eas-G4TPLJ6S.js");
3564
+ const { createVeniceInferenceAttestation, getEasScanUrl: getEasScanUrl2 } = await import("./eas-4RIW3IS4.js");
3561
3565
  const { keccak256: keccak2563, toHex, isAddress: isAddr } = await import("viem");
3562
- const { getChainContracts: getChainContracts2 } = await import("./config-7HU4X7EK.js");
3563
- const { getChain: getActiveChain } = await import("./network-WU2QC3L4.js");
3566
+ const { getChainContracts: getChainContracts2 } = await import("./config-ZGFS4I7K.js");
3567
+ const { getChain: getActiveChain } = await import("./network-UP2X5XDW.js");
3564
3568
  const vaultRecipient = opts.vault && isAddr(opts.vault) ? opts.vault : getChainContracts2(getActiveChain().id).vault;
3565
3569
  const promptHash = keccak2563(toHex(userContent)).slice(0, 18);
3566
3570
  const { uid } = await createVeniceInferenceAttestation(
@@ -3858,9 +3862,176 @@ function registerAllowanceCommands(program2) {
3858
3862
  }
3859
3863
 
3860
3864
  // src/commands/identity.ts
3865
+ import { generatePrivateKey } from "viem/accounts";
3861
3866
  import chalk4 from "chalk";
3862
3867
  import ora4 from "ora";
3863
3868
  import { SDK } from "agent0-sdk";
3869
+
3870
+ // src/lib/virtuals.ts
3871
+ import { execFile } from "child_process";
3872
+ import { promisify } from "util";
3873
+ import { createPublicClient, http, recoverMessageAddress, isAddress as isAddress5 } from "viem";
3874
+ import { base, baseSepolia } from "viem/chains";
3875
+ var execFileAsync = promisify(execFile);
3876
+ var BINDING_VERSION = "v1";
3877
+ function buildBindingMessage(sherwoodEoa, issuingChainId, tokenId) {
3878
+ return `sherwood-identity-link:${BINDING_VERSION}:${sherwoodEoa.toLowerCase()}:${issuingChainId}:${tokenId}`;
3879
+ }
3880
+ async function verifyBinding(params) {
3881
+ try {
3882
+ const recovered = await recoverMessageAddress({
3883
+ message: buildBindingMessage(params.sherwoodEoa, params.issuingChainId, params.tokenId),
3884
+ signature: params.signature
3885
+ });
3886
+ return recovered.toLowerCase() === params.virtualsWallet.toLowerCase();
3887
+ } catch {
3888
+ return false;
3889
+ }
3890
+ }
3891
+ var ISSUING_CHAINS = {
3892
+ [base.id]: {
3893
+ chain: base,
3894
+ identityRegistry: "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432"
3895
+ },
3896
+ [baseSepolia.id]: {
3897
+ chain: baseSepolia,
3898
+ identityRegistry: "0x8004A818BFB912233c491871b3d84c89A494BD9e"
3899
+ }
3900
+ };
3901
+ var OWNER_OF_ABI = [
3902
+ {
3903
+ name: "ownerOf",
3904
+ type: "function",
3905
+ stateMutability: "view",
3906
+ inputs: [{ name: "tokenId", type: "uint256" }],
3907
+ outputs: [{ name: "", type: "address" }]
3908
+ }
3909
+ ];
3910
+ var ISSUING_RPC_ENV = {
3911
+ [base.id]: "BASE_RPC_URL",
3912
+ [baseSepolia.id]: "BASE_SEPOLIA_RPC_URL"
3913
+ };
3914
+ async function ownerOfOnIssuingChain(issuingChainId, tokenId) {
3915
+ const issuing = ISSUING_CHAINS[issuingChainId];
3916
+ if (!issuing) {
3917
+ throw new Error(
3918
+ `Unsupported issuing chain ${issuingChainId}. Supported: ${Object.keys(ISSUING_CHAINS).join(", ")}`
3919
+ );
3920
+ }
3921
+ const rpcOverride = process.env[ISSUING_RPC_ENV[issuingChainId]];
3922
+ const client = createPublicClient({ chain: issuing.chain, transport: http(rpcOverride) });
3923
+ return client.readContract({
3924
+ address: issuing.identityRegistry,
3925
+ abi: OWNER_OF_ABI,
3926
+ functionName: "ownerOf",
3927
+ args: [tokenId]
3928
+ });
3929
+ }
3930
+ var VID_TAG_RE = /\s*\[vid:(v\d+):(\d+):(\d+):(0x[0-9a-fA-F]{40}):(self|0x[0-9a-fA-F]{130})\]\s*$/;
3931
+ function formatVidTag(tag) {
3932
+ return `[vid:${BINDING_VERSION}:${tag.issuingChainId}:${tag.tokenId}:${tag.wallet.toLowerCase()}:${tag.signature}]`;
3933
+ }
3934
+ function appendVidTag(message, tag) {
3935
+ return `${message} ${formatVidTag(tag)}`;
3936
+ }
3937
+ function parseVidTag(message) {
3938
+ if (message.indexOf("[vid:") !== message.lastIndexOf("[vid:")) return null;
3939
+ const match = message.match(VID_TAG_RE);
3940
+ if (!match) return null;
3941
+ if (!isAddress5(match[4])) return null;
3942
+ return {
3943
+ version: match[1],
3944
+ issuingChainId: parseInt(match[2], 10),
3945
+ tokenId: BigInt(match[3]),
3946
+ wallet: match[4],
3947
+ signature: match[5] === "self" ? "self" : match[5]
3948
+ };
3949
+ }
3950
+ function stripVidTag(message) {
3951
+ return message.replace(VID_TAG_RE, "");
3952
+ }
3953
+ async function verifyVidTag(tag, attester, ownerOf = ownerOfOnIssuingChain) {
3954
+ let bindingOk;
3955
+ if (tag.signature === "self") {
3956
+ bindingOk = attester.toLowerCase() === tag.wallet.toLowerCase();
3957
+ } else {
3958
+ bindingOk = await verifyBinding({
3959
+ sherwoodEoa: attester,
3960
+ issuingChainId: tag.issuingChainId,
3961
+ tokenId: tag.tokenId,
3962
+ virtualsWallet: tag.wallet,
3963
+ signature: tag.signature
3964
+ });
3965
+ }
3966
+ if (!bindingOk) {
3967
+ return { bindingOk: false, ownerOk: false, error: "binding failed \u2014 ownership check skipped" };
3968
+ }
3969
+ try {
3970
+ const owner = await ownerOf(tag.issuingChainId, tag.tokenId);
3971
+ return {
3972
+ bindingOk,
3973
+ ownerOk: owner.toLowerCase() === tag.wallet.toLowerCase(),
3974
+ owner
3975
+ };
3976
+ } catch (err) {
3977
+ return { bindingOk, ownerOk: false, error: err.message };
3978
+ }
3979
+ }
3980
+ function makeOwnerOfCache() {
3981
+ const cache = /* @__PURE__ */ new Map();
3982
+ return (chainId, tokenId) => {
3983
+ const key = `${chainId}:${tokenId}`;
3984
+ let p = cache.get(key);
3985
+ if (!p) {
3986
+ p = ownerOfOnIssuingChain(chainId, tokenId);
3987
+ p.catch(() => {
3988
+ });
3989
+ cache.set(key, p);
3990
+ }
3991
+ return p;
3992
+ };
3993
+ }
3994
+ async function acpJson(args) {
3995
+ try {
3996
+ const { stdout } = await execFileAsync("acp", [...args, "--json"], {
3997
+ timeout: 15e3
3998
+ });
3999
+ const start = stdout.indexOf("{");
4000
+ if (start < 0) return null;
4001
+ return JSON.parse(stdout.slice(start));
4002
+ } catch {
4003
+ return null;
4004
+ }
4005
+ }
4006
+ async function detectAcp() {
4007
+ try {
4008
+ await execFileAsync("acp", ["--version"], { timeout: 1e4 });
4009
+ return true;
4010
+ } catch {
4011
+ return false;
4012
+ }
4013
+ }
4014
+ async function acpWhoami() {
4015
+ const json = await acpJson(["agent", "whoami"]);
4016
+ if (!json) return null;
4017
+ const agentId = json.agentId ?? json.id ?? json.agent?.id;
4018
+ const name = json.name ?? json.agent?.name;
4019
+ return {
4020
+ agentId: agentId != null ? String(agentId) : void 0,
4021
+ name: name != null ? String(name) : void 0
4022
+ };
4023
+ }
4024
+ async function acpWalletAddress() {
4025
+ const json = await acpJson(["wallet", "address"]);
4026
+ if (!json) return null;
4027
+ for (const key of ["address", "evmAddress", "evm", "wallet"]) {
4028
+ const value = json[key];
4029
+ if (typeof value === "string" && isAddress5(value)) return value;
4030
+ }
4031
+ return null;
4032
+ }
4033
+
4034
+ // src/commands/identity.ts
3864
4035
  var IDENTITY_REGISTRY_ABI2 = [
3865
4036
  {
3866
4037
  name: "balanceOf",
@@ -3976,6 +4147,123 @@ function registerIdentityCommands(program2) {
3976
4147
  process.exit(1);
3977
4148
  }
3978
4149
  });
4150
+ 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 (8453 = Base, 84532 = Base Sepolia)", "8453").option("--binding-sig <hex>", "EIP-191 signature of the binding message by the economyOS wallet").action(async (opts) => {
4151
+ const account = getAccount();
4152
+ const issuingChainId = parseInt(opts.chainId, 10);
4153
+ if (!ISSUING_CHAINS[issuingChainId]) {
4154
+ console.error(chalk4.red(`Unsupported issuing chain ${opts.chainId}. Supported: ${Object.keys(ISSUING_CHAINS).join(", ")}`));
4155
+ process.exit(1);
4156
+ }
4157
+ const spinner = ora4("Resolving economyOS agent...").start();
4158
+ try {
4159
+ let virtualsWallet = opts.wallet;
4160
+ let virtualsAgentId;
4161
+ if (await detectAcp()) {
4162
+ const who = await acpWhoami();
4163
+ virtualsAgentId = who?.agentId;
4164
+ if (!virtualsWallet) {
4165
+ virtualsWallet = await acpWalletAddress() ?? void 0;
4166
+ }
4167
+ }
4168
+ if (!virtualsWallet) {
4169
+ spinner.fail("Could not resolve the economyOS agent wallet");
4170
+ console.error(chalk4.dim(" Install + authenticate the acp CLI (npm i -g @virtuals-protocol/acp-cli; acp configure)"));
4171
+ console.error(chalk4.dim(" or pass --wallet <address> explicitly."));
4172
+ process.exit(1);
4173
+ }
4174
+ let tokenId;
4175
+ if (opts.agentId) {
4176
+ tokenId = BigInt(opts.agentId);
4177
+ } else {
4178
+ spinner.text = `Searching ERC-8004 registry on chain ${issuingChainId} for ${virtualsWallet}...`;
4179
+ const sdk = new SDK({
4180
+ chainId: issuingChainId,
4181
+ rpcUrl: ISSUING_CHAINS[issuingChainId].chain.rpcUrls.default.http[0],
4182
+ privateKey: generatePrivateKey()
4183
+ });
4184
+ const results = await sdk.searchAgents({
4185
+ walletAddress: virtualsWallet,
4186
+ chains: [issuingChainId]
4187
+ });
4188
+ if (results.length === 0) {
4189
+ spinner.fail(`No ERC-8004 registration found for ${virtualsWallet} on chain ${issuingChainId}`);
4190
+ console.error(chalk4.dim(" Register first via the Virtuals CLI:"));
4191
+ console.error(chalk4.dim(` acp agent register-erc8004 --agent-id ${virtualsAgentId ?? "<id>"} --chain-id ${issuingChainId}`));
4192
+ console.error(chalk4.dim(" Then re-run this command (or pass --agent-id <tokenId> directly)."));
4193
+ process.exit(1);
4194
+ }
4195
+ if (results.length > 1) {
4196
+ spinner.fail(`Wallet ${virtualsWallet} has ${results.length} ERC-8004 registrations on chain ${issuingChainId} \u2014 pick one explicitly`);
4197
+ for (const a of results) {
4198
+ const idStr2 = String(a.agentId);
4199
+ const tid = idStr2.includes(":") ? idStr2.split(":")[1] : idStr2;
4200
+ console.error(chalk4.dim(` #${tid} ${a.name || "(no name)"}`));
4201
+ }
4202
+ console.error(chalk4.green(" Re-run with: sherwood identity link-virtuals --agent-id <tokenId>"));
4203
+ process.exit(1);
4204
+ }
4205
+ const idStr = String(results[0].agentId);
4206
+ tokenId = BigInt(idStr.includes(":") ? idStr.split(":")[1] : idStr);
4207
+ }
4208
+ if (tokenId > BigInt(Number.MAX_SAFE_INTEGER)) {
4209
+ spinner.fail(`Token ID ${tokenId} exceeds Number.MAX_SAFE_INTEGER \u2014 cannot be stored in config`);
4210
+ process.exit(1);
4211
+ }
4212
+ spinner.text = `Verifying ownerOf(#${tokenId}) on chain ${issuingChainId}...`;
4213
+ const owner = await ownerOfOnIssuingChain(issuingChainId, tokenId);
4214
+ if (owner.toLowerCase() !== virtualsWallet.toLowerCase()) {
4215
+ spinner.fail(`Agent #${tokenId} on chain ${issuingChainId} is owned by ${owner}, not ${virtualsWallet}`);
4216
+ process.exit(1);
4217
+ }
4218
+ const self = virtualsWallet.toLowerCase() === account.address.toLowerCase();
4219
+ const bindingMessage = buildBindingMessage(account.address, issuingChainId, tokenId);
4220
+ let binding;
4221
+ if (!self) {
4222
+ if (!opts.bindingSig) {
4223
+ spinner.fail("Binding signature required (economyOS wallet differs from your Sherwood wallet)");
4224
+ console.error();
4225
+ console.error(chalk4.bold(" Sign this exact message with the economyOS agent wallet:"));
4226
+ console.error(chalk4.green(` ${bindingMessage}`));
4227
+ console.error();
4228
+ console.error(chalk4.dim(" (e.g. via the acp CLI / app.virtuals.io wallet signing, EIP-191 personal_sign)"));
4229
+ console.error(chalk4.dim(" Then re-run with --binding-sig <signature>."));
4230
+ process.exit(1);
4231
+ }
4232
+ spinner.text = "Verifying binding signature...";
4233
+ const ok = await verifyBinding({
4234
+ sherwoodEoa: account.address,
4235
+ issuingChainId,
4236
+ tokenId,
4237
+ virtualsWallet,
4238
+ signature: opts.bindingSig
4239
+ });
4240
+ if (!ok) {
4241
+ spinner.fail("Binding signature does not recover to the economyOS wallet");
4242
+ console.error(chalk4.dim(` Expected signer: ${virtualsWallet}`));
4243
+ console.error(chalk4.dim(` Signed message must be exactly: ${bindingMessage}`));
4244
+ process.exit(1);
4245
+ }
4246
+ binding = { sig: opts.bindingSig, message: bindingMessage };
4247
+ }
4248
+ setVirtualsIdentity(Number(tokenId), issuingChainId, {
4249
+ agentId: virtualsAgentId,
4250
+ wallet: virtualsWallet,
4251
+ binding
4252
+ });
4253
+ spinner.succeed(`Virtuals identity linked: agent #${tokenId} (chain ${issuingChainId})`);
4254
+ console.log(chalk4.dim(` economyOS wallet: ${virtualsWallet}`));
4255
+ if (virtualsAgentId) console.log(chalk4.dim(` Virtuals agent: ${virtualsAgentId}`));
4256
+ console.log(chalk4.dim(` Sherwood wallet: ${account.address}${self ? " (same as economyOS wallet \u2014 no binding needed)" : " (bound via signature)"}`));
4257
+ console.log(chalk4.dim(` Saved to ~/.sherwood/config.json`));
4258
+ console.log();
4259
+ console.log(chalk4.green("You can now create or join funds with this identity:"));
4260
+ console.log(chalk4.dim(` sherwood fund create --agent-id ${tokenId} --subdomain <name> --name <name>`));
4261
+ } catch (err) {
4262
+ spinner.fail("Failed to link Virtuals identity");
4263
+ console.error(chalk4.red(formatContractError(err)));
4264
+ process.exit(1);
4265
+ }
4266
+ });
3979
4267
  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) => {
3980
4268
  if (!opts.wallet && !opts.name) {
3981
4269
  console.error(chalk4.red("Pass --wallet <address> or --name <text> (or both)."));
@@ -4022,6 +4310,47 @@ function registerIdentityCommands(program2) {
4022
4310
  });
4023
4311
  identity.command("status").description("Show your agent identity status").action(async () => {
4024
4312
  const account = getAccount();
4313
+ if (getIdentityProvider() === "virtuals") {
4314
+ const virtuals = getVirtualsIdentity();
4315
+ const savedId = getAgentId();
4316
+ const issuingChainId = getIdentityChainId();
4317
+ console.log();
4318
+ console.log(chalk4.bold("Agent Identity (ERC-8004 via Virtuals economyOS)"));
4319
+ console.log(chalk4.dim("\u2500".repeat(40)));
4320
+ console.log(` Sherwood wallet: ${account.address}`);
4321
+ console.log(` economyOS wallet: ${virtuals?.wallet ?? chalk4.red("(missing)")}`);
4322
+ if (virtuals?.agentId) console.log(` Virtuals agent: ${virtuals.agentId}`);
4323
+ console.log(` Issuing chain: ${issuingChainId ?? chalk4.red("(missing)")}`);
4324
+ console.log(` Saved ID: ${savedId != null ? `#${savedId}` : chalk4.red("(missing)")}`);
4325
+ if (virtuals?.wallet && savedId != null && issuingChainId != null) {
4326
+ const spinner2 = ora4("Re-verifying link...").start();
4327
+ try {
4328
+ const owner = await ownerOfOnIssuingChain(issuingChainId, BigInt(savedId));
4329
+ const ownerOk = owner.toLowerCase() === virtuals.wallet.toLowerCase();
4330
+ let bindingOk = virtuals.wallet.toLowerCase() === account.address.toLowerCase();
4331
+ if (!bindingOk && virtuals.binding?.sig) {
4332
+ bindingOk = await verifyBinding({
4333
+ sherwoodEoa: account.address,
4334
+ issuingChainId,
4335
+ tokenId: BigInt(savedId),
4336
+ virtualsWallet: virtuals.wallet,
4337
+ signature: virtuals.binding.sig
4338
+ });
4339
+ }
4340
+ spinner2.stop();
4341
+ console.log(` NFT ownership: ${ownerOk ? chalk4.green("verified") : chalk4.red(`FAILED (owner is ${owner})`)}`);
4342
+ console.log(` Binding: ${bindingOk ? chalk4.green("verified") : chalk4.red("FAILED")}`);
4343
+ if (!ownerOk) {
4344
+ console.log(chalk4.yellow(" The NFT moved since linking \u2014 re-run 'sherwood identity link-virtuals'."));
4345
+ }
4346
+ } catch (err) {
4347
+ spinner2.warn("Could not re-verify against the issuing chain");
4348
+ console.log(chalk4.dim(` ${err.message}`));
4349
+ }
4350
+ }
4351
+ console.log();
4352
+ return;
4353
+ }
4025
4354
  const registry = AGENT_REGISTRY().IDENTITY_REGISTRY;
4026
4355
  const client = getPublicClient();
4027
4356
  const spinner = ora4("Checking identity...").start();
@@ -4115,7 +4444,7 @@ function registerIdentityCommands(program2) {
4115
4444
  }
4116
4445
 
4117
4446
  // src/commands/proposal.ts
4118
- import { isAddress as isAddress5, encodeFunctionData as encodeFunctionData10 } from "viem";
4447
+ import { isAddress as isAddress6, encodeFunctionData as encodeFunctionData10 } from "viem";
4119
4448
  import chalk6 from "chalk";
4120
4449
  import ora5 from "ora";
4121
4450
  import { readFileSync as readFileSync2 } from "fs";
@@ -4808,8 +5137,8 @@ function printSimulationResult(result, callType) {
4808
5137
  }
4809
5138
  async function sendSimulationAlert(subdomain, proposalId, vault, execResult, settleResult) {
4810
5139
  try {
4811
- const xmtp = await import("./xmtp-Q4ZSQV2Q.js");
4812
- const { getAccount: getAccount2 } = await import("./client-C3C6IXAH.js");
5140
+ const xmtp = await import("./xmtp-OZ5PJFCT.js");
5141
+ const { getAccount: getAccount2 } = await import("./client-GRPJRISD.js");
4813
5142
  const group = await xmtp.getGroup("", subdomain);
4814
5143
  const allRisks = [...execResult.risks, ...settleResult?.risks ?? []];
4815
5144
  const criticals = allRisks.filter((r) => r.level === "critical");
@@ -4902,7 +5231,7 @@ function formatTimestamp(ts) {
4902
5231
  }
4903
5232
  function parseVaultOption(raw, spinner) {
4904
5233
  const vault = String(raw);
4905
- if (!isAddress5(vault)) {
5234
+ if (!isAddress6(vault)) {
4906
5235
  if (spinner) spinner.fail(`Invalid vault address: ${vault}`);
4907
5236
  else console.error(chalk6.red(`Invalid vault address: ${vault}`));
4908
5237
  process.exit(1);
@@ -4956,7 +5285,7 @@ function registerProposalCommands(program2) {
4956
5285
  proposal.command("create").description("Submit a strategy proposal").requiredOption("--vault <address>", "Vault address the proposal targets").requiredOption("--name <name>", "Strategy name").requiredOption("--description <text>", "Strategy rationale and risk summary").requiredOption("--duration <duration>", "Strategy duration (e.g. 7d, 24h, 3600)").requiredOption("--execute-calls <path>", "Path to JSON file with execute Call[] array").requiredOption("--settle-calls <path>", "Path to JSON file with settlement Call[] array").option("--strategy <address>", "Live-NAV strategy clone address (default: none \u2014 queue-only)").option("--metadata-uri <uri>", "Override \u2014 skip IPFS upload and use this URI directly").option("--simulate", "Simulate calls via Tenderly before submitting").option("--force", "Submit even if simulation fails (requires --simulate)").action(async (opts) => {
4957
5286
  try {
4958
5287
  const vault = opts.vault;
4959
- if (!isAddress5(vault)) {
5288
+ if (!isAddress6(vault)) {
4960
5289
  console.error(chalk6.red(`Invalid vault address: ${opts.vault}`));
4961
5290
  process.exit(1);
4962
5291
  }
@@ -4966,7 +5295,7 @@ function registerProposalCommands(program2) {
4966
5295
  const ZERO_STRATEGY = "0x0000000000000000000000000000000000000000";
4967
5296
  let strategy2 = ZERO_STRATEGY;
4968
5297
  if (opts.strategy) {
4969
- if (!isAddress5(opts.strategy)) {
5298
+ if (!isAddress6(opts.strategy)) {
4970
5299
  console.error(chalk6.red(`Invalid strategy address: ${opts.strategy}`));
4971
5300
  process.exit(1);
4972
5301
  }
@@ -5748,7 +6077,7 @@ function registerProposalCommands(program2) {
5748
6077
  let riskContext = {};
5749
6078
  let proposalId;
5750
6079
  if (opts.id) {
5751
- if (!opts.vault || !isAddress5(opts.vault)) {
6080
+ if (!opts.vault || !isAddress6(opts.vault)) {
5752
6081
  console.error(chalk6.red("\n \u2716 --vault is required when using --id (proposal IDs are per-vault)"));
5753
6082
  process.exit(1);
5754
6083
  }
@@ -5772,7 +6101,7 @@ function registerProposalCommands(program2) {
5772
6101
  console.log(DIM2(`
5773
6102
  Simulating proposal #${proposalId} on vault ${vault.slice(0, 10)}...`));
5774
6103
  } else if (opts.executeCalls) {
5775
- if (!opts.vault || !isAddress5(opts.vault)) {
6104
+ if (!opts.vault || !isAddress6(opts.vault)) {
5776
6105
  console.error(chalk6.red("\n \u2716 --vault is required when using --execute-calls"));
5777
6106
  process.exit(1);
5778
6107
  }
@@ -5815,7 +6144,7 @@ function registerProposalCommands(program2) {
5815
6144
  }
5816
6145
 
5817
6146
  // src/commands/queue.ts
5818
- import { parseUnits as parseUnits5, formatUnits as formatUnits5, isAddress as isAddress6, parseEventLogs } from "viem";
6147
+ import { parseUnits as parseUnits5, formatUnits as formatUnits5, isAddress as isAddress7, parseEventLogs } from "viem";
5819
6148
  import chalk7 from "chalk";
5820
6149
  import ora6 from "ora";
5821
6150
  var WETH_ABI2 = [
@@ -5951,7 +6280,7 @@ var QUEUE_ABI = [
5951
6280
  ];
5952
6281
  var KIND_LABELS = ["Redeem", "Deposit"];
5953
6282
  function resolveVaultAddress(opt) {
5954
- if (!opt || !isAddress6(opt)) {
6283
+ if (!opt || !isAddress7(opt)) {
5955
6284
  console.error(chalk7.red(`Invalid or missing --vault address: ${opt ?? "(none)"}`));
5956
6285
  process.exit(1);
5957
6286
  }
@@ -6204,7 +6533,7 @@ function registerQueueCommands(program2) {
6204
6533
  // src/commands/governor.ts
6205
6534
  import chalk8 from "chalk";
6206
6535
  import ora7 from "ora";
6207
- import { isAddress as isAddress7 } from "viem";
6536
+ import { isAddress as isAddress8 } from "viem";
6208
6537
  var G3 = chalk8.green;
6209
6538
  var W3 = chalk8.white;
6210
6539
  var DIM3 = chalk8.gray;
@@ -6213,7 +6542,7 @@ var LABEL3 = chalk8.green.bold;
6213
6542
  var SEP3 = () => console.log(DIM3("\u2500".repeat(60)));
6214
6543
  function parseVaultArg(raw) {
6215
6544
  const vault = String(raw);
6216
- if (!isAddress7(vault)) {
6545
+ if (!isAddress8(vault)) {
6217
6546
  console.error(chalk8.red(`Invalid vault address: ${vault}`));
6218
6547
  process.exit(1);
6219
6548
  }
@@ -6388,7 +6717,7 @@ function registerGovernorCommands(program2) {
6388
6717
  // src/commands/guardian-delegate.ts
6389
6718
  import chalk9 from "chalk";
6390
6719
  import ora8 from "ora";
6391
- import { formatUnits as formatUnits6, isAddress as isAddress8, parseUnits as parseUnits6 } from "viem";
6720
+ import { formatUnits as formatUnits6, isAddress as isAddress9, parseUnits as parseUnits6 } from "viem";
6392
6721
  var G4 = chalk9.green;
6393
6722
  var W4 = chalk9.white;
6394
6723
  var DIM4 = chalk9.gray;
@@ -6470,7 +6799,7 @@ function registerGuardianCommands(program2) {
6470
6799
  const pc = getPublicClient();
6471
6800
  let target;
6472
6801
  if (addressArg) {
6473
- if (!isAddress8(addressArg)) {
6802
+ if (!isAddress9(addressArg)) {
6474
6803
  console.error(chalk9.red("Invalid address"));
6475
6804
  process.exit(1);
6476
6805
  }
@@ -6588,7 +6917,7 @@ function registerGuardianCommands(program2) {
6588
6917
  }
6589
6918
  });
6590
6919
  guardian.command("delegate <delegate> <amount>").description("Delegate WOOD stake to a guardian. Amount in WOOD.").action(async (delegate, amountStr) => {
6591
- if (!isAddress8(delegate)) {
6920
+ if (!isAddress9(delegate)) {
6592
6921
  console.error(chalk9.red("Invalid delegate address"));
6593
6922
  process.exit(1);
6594
6923
  }
@@ -6612,7 +6941,7 @@ function registerGuardianCommands(program2) {
6612
6941
  }
6613
6942
  });
6614
6943
  guardian.command("undelegate <delegate> <action>").description("Unstake-delegation flow: 'request' | 'cancel' | 'claim'").action(async (delegate, action) => {
6615
- if (!isAddress8(delegate)) {
6944
+ if (!isAddress9(delegate)) {
6616
6945
  console.error(chalk9.red("Invalid delegate address"));
6617
6946
  process.exit(1);
6618
6947
  }
@@ -8646,13 +8975,13 @@ import { join as join4 } from "path";
8646
8975
  import { homedir as homedir4 } from "os";
8647
8976
  import { createHash as createHash2 } from "crypto";
8648
8977
  var DEFAULT_SWEEP_DIR = join4(homedir4(), ".sherwood", "grid", "sweeps");
8649
- function expandSweep(sweep, base) {
8978
+ function expandSweep(sweep, base2) {
8650
8979
  const fields = ["leverage", "levelsPerSide", "atrMultiplier", "rebalanceDriftPct"];
8651
8980
  const valueLists = {
8652
- leverage: sweep.leverage && sweep.leverage.length > 0 ? sweep.leverage : [base.leverage],
8653
- levelsPerSide: sweep.levelsPerSide && sweep.levelsPerSide.length > 0 ? sweep.levelsPerSide : [base.levelsPerSide],
8654
- atrMultiplier: sweep.atrMultiplier && sweep.atrMultiplier.length > 0 ? sweep.atrMultiplier : [base.atrMultiplier],
8655
- rebalanceDriftPct: sweep.rebalanceDriftPct && sweep.rebalanceDriftPct.length > 0 ? sweep.rebalanceDriftPct : [base.rebalanceDriftPct]
8981
+ leverage: sweep.leverage && sweep.leverage.length > 0 ? sweep.leverage : [base2.leverage],
8982
+ levelsPerSide: sweep.levelsPerSide && sweep.levelsPerSide.length > 0 ? sweep.levelsPerSide : [base2.levelsPerSide],
8983
+ atrMultiplier: sweep.atrMultiplier && sweep.atrMultiplier.length > 0 ? sweep.atrMultiplier : [base2.atrMultiplier],
8984
+ rebalanceDriftPct: sweep.rebalanceDriftPct && sweep.rebalanceDriftPct.length > 0 ? sweep.rebalanceDriftPct : [base2.rebalanceDriftPct]
8656
8985
  };
8657
8986
  let combos = [{}];
8658
8987
  for (const field of fields) {
@@ -8691,13 +9020,13 @@ async function runSweep(opts) {
8691
9020
  tokenSplit = {};
8692
9021
  for (const t of opts.tokens) tokenSplit[t] = weight;
8693
9022
  }
8694
- const base = {
9023
+ const base2 = {
8695
9024
  ...DEFAULT_GRID_CONFIG,
8696
9025
  ...opts.baseConfig,
8697
9026
  tokens: opts.tokens,
8698
9027
  tokenSplit
8699
9028
  };
8700
- const combos = expandSweep(opts.sweep, base);
9029
+ const combos = expandSweep(opts.sweep, base2);
8701
9030
  if (combos.length === 0) throw new Error("sweep produced no combinations");
8702
9031
  const loader = new HistoricalDataLoader({ noCache: opts.noCache });
8703
9032
  if (opts.verbose !== false) {
@@ -8708,7 +9037,7 @@ async function runSweep(opts) {
8708
9037
  const runs = [];
8709
9038
  for (let i = 0; i < combos.length; i++) {
8710
9039
  const combo = combos[i];
8711
- const config = { ...base, ...combo };
9040
+ const config = { ...base2, ...combo };
8712
9041
  const runOutPath = join4(sweepDir, `run-${i.toString().padStart(3, "0")}.json`);
8713
9042
  if (opts.verbose !== false) {
8714
9043
  process.stderr.write(` [sweep] [${i + 1}/${combos.length}] ${JSON.stringify(combo)}
@@ -9246,9 +9575,9 @@ try {
9246
9575
  } catch {
9247
9576
  }
9248
9577
  var require2 = createRequire(import.meta.url);
9249
- var CLI_VERSION = "0.74.2";
9578
+ var CLI_VERSION = "0.75.0";
9250
9579
  async function loadXmtp() {
9251
- return import("./xmtp-Q4ZSQV2Q.js");
9580
+ return import("./xmtp-OZ5PJFCT.js");
9252
9581
  }
9253
9582
  async function loadCron() {
9254
9583
  return import("./cron-QMLRWDJG.js");
@@ -9260,7 +9589,7 @@ var BOLD6 = chalk16.white.bold;
9260
9589
  var LABEL5 = chalk16.green.bold;
9261
9590
  var SEP6 = () => console.log(DIM6("\u2500".repeat(60)));
9262
9591
  function validateAddress(value, name) {
9263
- if (!isAddress9(value)) {
9592
+ if (!isAddress10(value)) {
9264
9593
  console.error(chalk16.red(`Invalid ${name} address: ${value}`));
9265
9594
  process.exit(1);
9266
9595
  }
@@ -9849,7 +10178,7 @@ fund.command("add").description("Register an agent on a fund vault (creator only
9849
10178
  if (opts.agentId) {
9850
10179
  agentId = BigInt(opts.agentId);
9851
10180
  } else {
9852
- const { AGENT_REGISTRY: AGENT_REGISTRY2 } = await import("./addresses-OFFTM6NG.js");
10181
+ const { AGENT_REGISTRY: AGENT_REGISTRY2 } = await import("./addresses-JJPQTF6S.js");
9853
10182
  const registry = AGENT_REGISTRY2().IDENTITY_REGISTRY;
9854
10183
  if (registry === "0x0000000000000000000000000000000000000000") {
9855
10184
  agentId = 0n;
@@ -9982,6 +10311,16 @@ fund.command("join").description("Request to join a fund (creates an EAS attesta
9982
10311
  }
9983
10312
  process.exit(1);
9984
10313
  }
10314
+ let joinMessage = opts.message;
10315
+ const virtualsIdentity = getVirtualsIdentity();
10316
+ if (getIdentityProvider() === "virtuals" && virtualsIdentity) {
10317
+ joinMessage = appendVidTag(joinMessage, {
10318
+ issuingChainId: getIdentityChainId() ?? 8453,
10319
+ tokenId: BigInt(agentId),
10320
+ wallet: virtualsIdentity.wallet,
10321
+ signature: virtualsIdentity.binding?.sig ?? "self"
10322
+ });
10323
+ }
9985
10324
  if (isCalldataOnly()) {
9986
10325
  const referrerAgentId2 = opts.ref ? parseInt(opts.ref, 10) : void 0;
9987
10326
  spinner.stop();
@@ -9992,7 +10331,7 @@ fund.command("join").description("Request to join a fund (creates an EAS attesta
9992
10331
  agentId: BigInt(agentId),
9993
10332
  vault: fund2.vault,
9994
10333
  creator: fund2.creator,
9995
- message: opts.message,
10334
+ message: joinMessage,
9996
10335
  referrerAgentId: referrerAgentId2
9997
10336
  },
9998
10337
  getChain().id
@@ -10050,7 +10389,7 @@ fund.command("join").description("Request to join a fund (creates an EAS attesta
10050
10389
  BigInt(agentId),
10051
10390
  fund2.vault,
10052
10391
  fund2.creator,
10053
- opts.message,
10392
+ joinMessage,
10054
10393
  referrerAgentId
10055
10394
  );
10056
10395
  try {
@@ -10137,16 +10476,26 @@ fund.command("requests").description("View pending join requests for a fund (cre
10137
10476
  console.log();
10138
10477
  console.log(LABEL5(` \u25C6 Pending Join Requests (${requests.length})`));
10139
10478
  SEP6();
10479
+ const ownerOfCached = makeOwnerOfCache();
10140
10480
  for (let i = 0; i < requests.length; i++) {
10141
10481
  const req = requests[i];
10142
10482
  const date = new Date(req.time * 1e3).toLocaleString();
10143
10483
  const referrer = parseReferrer(req.decoded.message);
10144
- const cleanMessage = stripReferrerPrefix(req.decoded.message);
10484
+ const vid = parseVidTag(req.decoded.message);
10485
+ const cleanMessage = stripReferrerPrefix(stripVidTag(req.decoded.message));
10145
10486
  console.log(W6(` ${i + 1}. Agent #${req.decoded.agentId} ${DIM6(`(${req.attester})`)}`));
10146
10487
  console.log(DIM6(` Message: "${cleanMessage}"`));
10147
10488
  if (referrer !== null) {
10148
10489
  console.log(G6(` Referred by: Agent #${referrer}`));
10149
10490
  }
10491
+ if (vid) {
10492
+ const v = await verifyVidTag(vid, req.attester, ownerOfCached);
10493
+ const verified = v.bindingOk && v.ownerOk;
10494
+ const badge = verified ? G6("\u2714 verified") : chalk16.red("\u2718 FAILED");
10495
+ console.log(W6(` Virtuals: ${badge} ${DIM6(`(agent #${vid.tokenId} on chain ${vid.issuingChainId}, wallet ${vid.wallet})`)}`));
10496
+ if (!v.bindingOk) console.log(chalk16.red(` binding signature invalid \u2014 do not approve based on this identity`));
10497
+ else if (!v.ownerOk) console.log(chalk16.red(` NFT ownership check failed${v.owner ? ` (owner is ${v.owner})` : v.error ? ` (${v.error})` : ""}`));
10498
+ }
10150
10499
  console.log(DIM6(` Requested: ${date}`));
10151
10500
  console.log(DIM6(` Attestation: ${req.uid}`));
10152
10501
  console.log();
@@ -10542,7 +10891,7 @@ vaultCmd.command("redeem").description("Redeem vault shares for the underlying a
10542
10891
  `));
10543
10892
  process.exit(1);
10544
10893
  }
10545
- if (opts.receiver && !isAddress9(opts.receiver)) {
10894
+ if (opts.receiver && !isAddress10(opts.receiver)) {
10546
10895
  console.error(chalk16.red(`
10547
10896
  \u2716 Invalid receiver address: ${opts.receiver}
10548
10897
  `));
@@ -10575,7 +10924,7 @@ vaultCmd.command("redeem").description("Redeem vault shares for the underlying a
10575
10924
  var strategy = program.command("strategy").description("Strategy templates \u2014 list, clone, propose");
10576
10925
  registerStrategyTemplateCommands(strategy);
10577
10926
  program.command("providers").description("List available providers (research + swap routing)").action(async () => {
10578
- const { listProviders } = await import("./providers-YOOQFBN2.js");
10927
+ const { listProviders } = await import("./providers-2J6LL67W.js");
10579
10928
  for (const info of listProviders()) {
10580
10929
  console.log(`
10581
10930
  ${info.name} (${info.type})`);
@@ -10585,7 +10934,7 @@ ${info.name} (${info.type})`);
10585
10934
  }
10586
10935
  });
10587
10936
  try {
10588
- const { registerChatCommands } = await import("./chat-3PM3GP3C.js");
10937
+ const { registerChatCommands } = await import("./chat-CO244AHH.js");
10589
10938
  registerChatCommands(program);
10590
10939
  } catch {
10591
10940
  program.command("chat <name> [action] [actionArgs...]").description("Fund chat (XMTP) \u2014 requires @xmtp/cli").action(() => {
@@ -10595,7 +10944,7 @@ try {
10595
10944
  process.exit(1);
10596
10945
  });
10597
10946
  }
10598
- var { registerSessionCommands } = await import("./session-GUVSID3Z.js");
10947
+ var { registerSessionCommands } = await import("./session-JQ3IF3IV.js");
10599
10948
  registerSessionCommands(program);
10600
10949
  registerVeniceCommands(program);
10601
10950
  registerAllowanceCommands(program);
@@ -10604,11 +10953,11 @@ registerProposalCommands(program);
10604
10953
  registerQueueCommands(program);
10605
10954
  registerGovernorCommands(program);
10606
10955
  registerGuardianCommands(program);
10607
- var { registerResearchCommands } = await import("./research-KX3LCAOQ.js");
10956
+ var { registerResearchCommands } = await import("./research-FHQCSLTZ.js");
10608
10957
  registerResearchCommands(program);
10609
- var { registerAgentCommands } = await import("./agent-IJOOONON.js");
10958
+ var { registerAgentCommands } = await import("./agent-FYRYTKYM.js");
10610
10959
  registerAgentCommands(program);
10611
- var { registerTradeCommands } = await import("./trade-WDPMFFYB.js");
10960
+ var { registerTradeCommands } = await import("./trade-5EYPZN7M.js");
10612
10961
  registerTradeCommands(program);
10613
10962
  registerGridCommand(program);
10614
10963
  var configCmd = program.command("config");