@sherwoodagent/cli 0.87.1 → 0.88.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.
@@ -24,6 +24,16 @@ import {
24
24
  import { encodeAbiParameters, parseAbiParameters, decodeAbiParameters } from "viem";
25
25
  var ZERO_BYTES32 = "0x0000000000000000000000000000000000000000000000000000000000000000";
26
26
  var ATTESTED_TOPIC = "0x8bf46bf4cfd674fa735a3d63ec1c9ad4153f033c290341f3a588b75685141b35";
27
+ var ATTESTED_EVENT = {
28
+ type: "event",
29
+ name: "Attested",
30
+ inputs: [
31
+ { name: "recipient", type: "address", indexed: true },
32
+ { name: "attester", type: "address", indexed: true },
33
+ { name: "uid", type: "bytes32", indexed: false },
34
+ { name: "schemaUID", type: "bytes32", indexed: true }
35
+ ]
36
+ };
27
37
  var JOIN_REQUEST_PARAMS = parseAbiParameters("uint256, uint256, address, string");
28
38
  var AGENT_APPROVED_PARAMS = parseAbiParameters("uint256, uint256, address");
29
39
  var X402_RESEARCH_PARAMS = parseAbiParameters("string, string, string, string, string");
@@ -40,25 +50,41 @@ function assertSchemasRegistered() {
40
50
  }
41
51
  }
42
52
  function getEasNetwork() {
53
+ if (forkAttestationsEnabled()) return "robinhood-fork";
43
54
  return EAS_NETWORK;
44
55
  }
56
+ function forkAttestationsEnabled() {
57
+ return forkAttestationsEnabledFor(getNetwork());
58
+ }
59
+ function forkAttestationsEnabledFor(network) {
60
+ if (network !== "robinhood-fork") return false;
61
+ const raw = process.env.SHERWOOD_EAS_ON_FORK;
62
+ return raw === "1" || raw === "true";
63
+ }
45
64
  var COORDINATION_NETWORK = "robinhood-mainnet";
46
65
  var EAS_NETWORK = COORDINATION_NETWORK;
47
66
  function attestationWritesEnabled() {
48
- return getNetwork() !== "robinhood-fork";
67
+ return getNetwork() !== "robinhood-fork" || forkAttestationsEnabled();
49
68
  }
50
69
  function skipWriteOnFork(kind) {
51
70
  if (attestationWritesEnabled()) return false;
52
71
  console.log(
53
- ` ${kind} attestation skipped: writes are disabled on robinhood-fork (ephemeral chain; attestations live on Robinhood mainnet).`
72
+ ` ${kind} attestation skipped: writes are disabled on robinhood-fork (ephemeral chain; attestations live on Robinhood mainnet). Set SHERWOOD_EAS_ON_FORK=1 to record it on the fork's own EAS instead.`
54
73
  );
55
74
  return true;
56
75
  }
57
76
  async function assertCanPayForAttestation() {
58
- await withNetwork(EAS_NETWORK, async () => {
77
+ const easNetwork = getEasNetwork();
78
+ await withNetwork(easNetwork, async () => {
59
79
  const account = getAccount();
60
80
  const balance = await getPublicClient().getBalance({ address: account.address });
61
81
  if (balance === 0n) {
82
+ if (easNetwork === "robinhood-fork") {
83
+ throw new Error(
84
+ `No ETH on the fork (chain 9994663) for ${account.address}.
85
+ SHERWOOD_EAS_ON_FORK=1 records attestations on the fork's own EAS, so this wallet needs a small vnet balance (top up with tenderly_setBalance).`
86
+ );
87
+ }
62
88
  throw new Error(
63
89
  `No ETH on Robinhood mainnet (chain 4663) for ${account.address}.
64
90
  Attestations are recorded on Robinhood mainnet regardless of which chain your fund is on, so this wallet needs a small mainnet balance (a single attestation costs well under 0.0001 ETH).`
@@ -75,11 +101,54 @@ function getEasGraphqlUrl() {
75
101
  }
76
102
  return url;
77
103
  }
104
+ function hasEasIndexer() {
105
+ return CHAIN_REGISTRY[getEasNetwork()].easGraphqlUrl !== null;
106
+ }
107
+ var FORK_EAS_FROM_BLOCK = 67079663n;
108
+ function easScanFromBlock() {
109
+ const raw = process.env.SHERWOOD_EAS_FORK_FROM_BLOCK;
110
+ if (raw) {
111
+ try {
112
+ const n = BigInt(raw);
113
+ if (n >= 0n) return n;
114
+ } catch {
115
+ }
116
+ }
117
+ return FORK_EAS_FROM_BLOCK;
118
+ }
119
+ async function queryAttestationsOnChain(schemaUid, filter) {
120
+ const client = getPublicClient();
121
+ const logs = await client.getLogs({
122
+ address: EAS_CONTRACTS().EAS,
123
+ event: ATTESTED_EVENT,
124
+ args: { recipient: filter.recipient, attester: filter.attester, schemaUID: schemaUid },
125
+ fromBlock: easScanFromBlock(),
126
+ toBlock: "latest"
127
+ });
128
+ const out = [];
129
+ for (const log of logs) {
130
+ const uid = log.args.uid;
131
+ if (!uid) continue;
132
+ const a = await client.readContract({
133
+ address: EAS_CONTRACTS().EAS,
134
+ abi: EAS_ABI,
135
+ functionName: "getAttestation",
136
+ args: [uid]
137
+ });
138
+ if (a.revocationTime !== 0n) continue;
139
+ out.push({
140
+ id: a.uid,
141
+ attester: a.attester,
142
+ recipient: a.recipient,
143
+ time: Number(a.time),
144
+ data: a.data
145
+ });
146
+ }
147
+ return out.sort((x, y) => y.time - x.time);
148
+ }
78
149
  function getEasScanUrl(uid) {
79
150
  const host = CHAIN_REGISTRY[getEasNetwork()].easScanHost;
80
- if (!host) {
81
- throw new Error(`EAS scan host is not configured on ${getEasNetwork()}.`);
82
- }
151
+ if (!host) return `uid ${uid}`;
83
152
  return `https://${host}/attestation/view/${uid}`;
84
153
  }
85
154
  function getEasExplorerUrl(txHash) {
@@ -362,6 +431,10 @@ async function queryApprovals(attester) {
362
431
  async function queryApprovalsImpl(attester) {
363
432
  assertSchemasRegistered();
364
433
  const schemaUid = EAS_SCHEMAS().AGENT_APPROVED;
434
+ if (!hasEasIndexer()) {
435
+ const rows = await queryAttestationsOnChain(schemaUid, { attester });
436
+ return rows.map(decodeApprovalRow);
437
+ }
365
438
  const url = getEasGraphqlUrl();
366
439
  const query = `
367
440
  query Approvals($schemaId: String!, $attester: String!) {
@@ -394,20 +467,21 @@ async function queryApprovalsImpl(attester) {
394
467
  }
395
468
  const json = await response.json();
396
469
  if (!json.data?.attestations) return [];
397
- return json.data.attestations.map((a) => {
398
- const decoded = decodeAbiParameters(AGENT_APPROVED_PARAMS, a.data);
399
- return {
400
- uid: a.id,
401
- attester: a.attester,
402
- recipient: a.recipient,
403
- time: a.time,
404
- decoded: {
405
- syndicateId: decoded[0],
406
- agentId: decoded[1],
407
- vault: decoded[2]
408
- }
409
- };
410
- });
470
+ return json.data.attestations.map(decodeApprovalRow);
471
+ }
472
+ function decodeApprovalRow(a) {
473
+ const decoded = decodeAbiParameters(AGENT_APPROVED_PARAMS, a.data);
474
+ return {
475
+ uid: a.id,
476
+ attester: a.attester,
477
+ recipient: a.recipient,
478
+ time: a.time,
479
+ decoded: {
480
+ syndicateId: decoded[0],
481
+ agentId: decoded[1],
482
+ vault: decoded[2]
483
+ }
484
+ };
411
485
  }
412
486
  async function queryJoinRequests(recipient) {
413
487
  return withNetwork(getEasNetwork(), () => queryJoinRequestsImpl(recipient));
@@ -415,6 +489,10 @@ async function queryJoinRequests(recipient) {
415
489
  async function queryJoinRequestsImpl(recipient) {
416
490
  assertSchemasRegistered();
417
491
  const schemaUid = EAS_SCHEMAS().SYNDICATE_JOIN_REQUEST;
492
+ if (!hasEasIndexer()) {
493
+ const rows = await queryAttestationsOnChain(schemaUid, { recipient });
494
+ return rows.map(decodeJoinRequestRow);
495
+ }
418
496
  const url = getEasGraphqlUrl();
419
497
  const query = `
420
498
  query JoinRequests($schemaId: String!, $recipient: String!) {
@@ -447,25 +525,28 @@ async function queryJoinRequestsImpl(recipient) {
447
525
  }
448
526
  const json = await response.json();
449
527
  if (!json.data?.attestations) return [];
450
- return json.data.attestations.map((a) => {
451
- const decoded = decodeAbiParameters(JOIN_REQUEST_PARAMS, a.data);
452
- return {
453
- uid: a.id,
454
- attester: a.attester,
455
- recipient: a.recipient,
456
- time: a.time,
457
- decoded: {
458
- syndicateId: decoded[0],
459
- agentId: decoded[1],
460
- vault: decoded[2],
461
- message: decoded[3]
462
- }
463
- };
464
- });
528
+ return json.data.attestations.map(decodeJoinRequestRow);
529
+ }
530
+ function decodeJoinRequestRow(a) {
531
+ const decoded = decodeAbiParameters(JOIN_REQUEST_PARAMS, a.data);
532
+ return {
533
+ uid: a.id,
534
+ attester: a.attester,
535
+ recipient: a.recipient,
536
+ time: a.time,
537
+ decoded: {
538
+ syndicateId: decoded[0],
539
+ agentId: decoded[1],
540
+ vault: decoded[2],
541
+ message: decoded[3]
542
+ }
543
+ };
465
544
  }
466
545
 
467
546
  export {
468
547
  getEasNetwork,
548
+ forkAttestationsEnabled,
549
+ forkAttestationsEnabledFor,
469
550
  COORDINATION_NETWORK,
470
551
  EAS_NETWORK,
471
552
  attestationWritesEnabled,
@@ -488,4 +569,4 @@ export {
488
569
  queryApprovals,
489
570
  queryJoinRequests
490
571
  };
491
- //# sourceMappingURL=chunk-SI65QHTY.js.map
572
+ //# sourceMappingURL=chunk-SCQAKMMI.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/eas.ts"],"sourcesContent":["/**\n * EAS (Ethereum Attestation Service) wrapper for fund join requests and approvals.\n *\n * Uses viem for on-chain writes and the EAS GraphQL API for queries.\n * No ethers dependency — attestation data is encoded with viem's encodeAbiParameters.\n */\n\nimport type { Address, Hex } from \"viem\";\nimport { encodeAbiParameters, parseAbiParameters, decodeAbiParameters } from \"viem\";\nimport { getPublicClient, getAccount, writeContractWithRetry, waitForReceipt } from \"./client.js\";\nimport { getChain, getNetwork, getChainConfig, withNetwork, isTestnet, CHAIN_REGISTRY, type Network } from \"./network.js\";\nimport { EAS_CONTRACTS, EAS_SCHEMAS } from \"./addresses.js\";\nimport { EAS_ABI } from \"./abis.js\";\n\n// ── Schema definitions ──\n\nconst ZERO_BYTES32 = \"0x0000000000000000000000000000000000000000000000000000000000000000\" as Hex;\n\n// keccak256(\"Attested(address,address,bytes32,bytes32)\")\nconst ATTESTED_TOPIC = \"0x8bf46bf4cfd674fa735a3d63ec1c9ad4153f033c290341f3a588b75685141b35\" as Hex;\n\n/**\n * The same event, as an ABI item, for the indexer-free log reader. recipient,\n * attester and schemaUID are indexed, so a query can filter on all three; the\n * uid rides in the data.\n */\nconst ATTESTED_EVENT = {\n type: \"event\",\n name: \"Attested\",\n inputs: [\n { name: \"recipient\", type: \"address\", indexed: true },\n { name: \"attester\", type: \"address\", indexed: true },\n { name: \"uid\", type: \"bytes32\", indexed: false },\n { name: \"schemaUID\", type: \"bytes32\", indexed: true },\n ],\n} as const;\n\nconst JOIN_REQUEST_PARAMS = parseAbiParameters(\"uint256, uint256, address, string\");\nconst AGENT_APPROVED_PARAMS = parseAbiParameters(\"uint256, uint256, address\");\nconst X402_RESEARCH_PARAMS = parseAbiParameters(\"string, string, string, string, string\");\nconst VENICE_PROVISION_PARAMS = parseAbiParameters(\"address, string\");\nconst VENICE_INFERENCE_PARAMS = parseAbiParameters(\"string, uint256, uint256, string\");\nconst TRADE_EXECUTED_PARAMS = parseAbiParameters(\"address, address, uint256, string, string, string\");\n\nfunction assertSchemasRegistered() {\n const schemas = EAS_SCHEMAS();\n if (schemas.SYNDICATE_JOIN_REQUEST === ZERO_BYTES32 || schemas.AGENT_APPROVED === ZERO_BYTES32) {\n const flag = isTestnet() ? \" --testnet\" : \"\";\n throw new Error(\n `EAS schemas not registered on ${getNetwork()}. Run: cd cli && npx tsx scripts/register-eas-schemas.ts${flag}`,\n );\n }\n}\n\n/**\n * The chain where fund-coordination attestations live: Robinhood mainnet\n * (4663), which is where Sherwood deployed EAS and registered its schemas.\n *\n * Under SHERWOOD_EAS_ON_FORK this returns the fork instead. The vnet is a fork\n * of 4663 taken after registration, so the same EAS contract and the same\n * schema UIDs are live on it — nothing else in the write path changes, the\n * attestation simply lands on the ephemeral chain and costs vnet ETH.\n */\nexport function getEasNetwork(): Network {\n if (forkAttestationsEnabled()) return \"robinhood-fork\";\n return EAS_NETWORK;\n}\n\n/**\n * `SHERWOOD_EAS_ON_FORK=1` — opt in to recording attestations on the Tenderly\n * fork's OWN EAS instead of skipping them.\n *\n * The vnet is a fork of Robinhood mainnet taken after Sherwood registered its\n * schemas, so the same EAS (0x7d70441B…) and the same schema UIDs exist on it\n * — writes land on the fork, cost only vnet ETH, and never touch 4663's\n * permanent record. Off by default: the fork is the DEFAULT network, so\n * attesting must be a deliberate choice (simulations, e2e coverage runs).\n *\n * Only meaningful on `robinhood-fork`; returns false on every other chain, so\n * a stray export in a shell profile cannot redirect a real attestation.\n */\nexport function forkAttestationsEnabled(): boolean {\n return forkAttestationsEnabledFor(getNetwork());\n}\n\n/**\n * Same question, asked by network name instead of via the singleton — the\n * simulation builds its config before any CLI subprocess has selected a chain.\n */\nexport function forkAttestationsEnabledFor(network: Network): boolean {\n if (network !== \"robinhood-fork\") return false;\n const raw = process.env.SHERWOOD_EAS_ON_FORK;\n return raw === \"1\" || raw === \"true\";\n}\n\n/**\n * The coordination chain: attestations AND ERC-8004 identity live on Robinhood\n * mainnet regardless of which chain a fund runs on — a join request for a\n * 46630 fund is recorded on 4663, and its agent's identity NFT is minted there.\n */\nexport const COORDINATION_NETWORK: Network = \"robinhood-mainnet\";\nexport const EAS_NETWORK: Network = COORDINATION_NETWORK;\n\n/**\n * Attestation WRITES are a no-op on the Tenderly fork.\n *\n * The fork is ephemeral and is the default network, so routing its writes to\n * mainnet would burn real ETH recording vnet activity into a permanent public\n * record. Reads are unaffected — a fork session still displays 4663\n * attestations. See spec §10.3.\n */\nexport function attestationWritesEnabled(): boolean {\n return getNetwork() !== \"robinhood-fork\" || forkAttestationsEnabled();\n}\n\n/** Thrown-free guard used by every write path; returns true when it skipped. */\nfunction skipWriteOnFork(kind: string): boolean {\n if (attestationWritesEnabled()) return false;\n console.log(\n ` ${kind} attestation skipped: writes are disabled on robinhood-fork ` +\n `(ephemeral chain; attestations live on Robinhood mainnet). ` +\n `Set SHERWOOD_EAS_ON_FORK=1 to record it on the fork's own EAS instead.`,\n );\n return true;\n}\n\n/**\n * Fails before an attestation write when the signer cannot pay for it on the\n * EAS chain. Attestations cost real mainnet ETH even when the fund is on a\n * testnet, which is surprising enough that a bare out-of-gas revert would be\n * the worst possible way to discover it.\n */\nexport async function assertCanPayForAttestation(): Promise<void> {\n // Check the chain the attestation will ACTUALLY land on: mainnet normally,\n // the fork itself under SHERWOOD_EAS_ON_FORK. Checking 4663 while writing to\n // the fork would be the wrong balance on the wrong chain.\n const easNetwork = getEasNetwork();\n await withNetwork(easNetwork, async () => {\n const account = getAccount();\n const balance = await getPublicClient().getBalance({ address: account.address });\n if (balance === 0n) {\n if (easNetwork === \"robinhood-fork\") {\n throw new Error(\n `No ETH on the fork (chain 9994663) for ${account.address}.\\n` +\n `SHERWOOD_EAS_ON_FORK=1 records attestations on the fork's own EAS, ` +\n `so this wallet needs a small vnet balance (top up with tenderly_setBalance).`,\n );\n }\n throw new Error(\n `No ETH on Robinhood mainnet (chain 4663) for ${account.address}.\\n` +\n `Attestations are recorded on Robinhood mainnet regardless of which ` +\n `chain your fund is on, so this wallet needs a small mainnet balance ` +\n `(a single attestation costs well under 0.0001 ETH).`,\n );\n }\n });\n}\n\n// ── GraphQL ──\n\nfunction getEasGraphqlUrl(): string {\n const url = getChainConfig().easGraphqlUrl;\n if (!url) {\n throw new Error(\n `EAS is not available on ${getNetwork()}. Attestation operations require a chain with EAS (e.g. base, base-sepolia).`,\n );\n }\n return url;\n}\n\n/**\n * Whether attestation READS have an indexer on the EAS chain. The fork has\n * none (no one indexes an ephemeral vnet), so under SHERWOOD_EAS_ON_FORK the\n * query paths read the EAS contract's own `Attested` logs instead.\n */\nfunction hasEasIndexer(): boolean {\n return CHAIN_REGISTRY[getEasNetwork()].easGraphqlUrl !== null;\n}\n\n/**\n * First block worth scanning for `Attested` logs on the fork.\n *\n * A vnet inherits its parent's whole history, so scanning from 0 would ask the\n * node for 67M blocks of mainnet logs. Everything the fork itself attested is\n * at or after the fork point, which is where the v1 stack was deployed.\n * Override with SHERWOOD_EAS_FORK_FROM_BLOCK when a new vnet is minted.\n */\nconst FORK_EAS_FROM_BLOCK = 67079663n;\n\nfunction easScanFromBlock(): bigint {\n const raw = process.env.SHERWOOD_EAS_FORK_FROM_BLOCK;\n if (raw) {\n try {\n const n = BigInt(raw);\n if (n >= 0n) return n;\n } catch {\n // fall through to the default\n }\n }\n return FORK_EAS_FROM_BLOCK;\n}\n\n/** One attestation as the GraphQL indexer would have returned it. */\ninterface RawAttestation {\n id: string;\n attester: string;\n recipient: string;\n time: number;\n data: string;\n}\n\n/**\n * Indexer-free replacement for a GraphQL `attestations(where: …)` query: read\n * the EAS contract's own `Attested` logs, then `getAttestation` each uid for\n * the payload. Revoked attestations are dropped, matching the GraphQL\n * `revoked: { equals: false }` filter every caller uses.\n *\n * `recipient` and `attester` are INDEXED on the event, so both filters are\n * pushed into the log query rather than applied client-side.\n */\nasync function queryAttestationsOnChain(\n schemaUid: Hex,\n filter: { attester?: Address; recipient?: Address },\n): Promise<RawAttestation[]> {\n const client = getPublicClient();\n const logs = await client.getLogs({\n address: EAS_CONTRACTS().EAS,\n event: ATTESTED_EVENT,\n args: { recipient: filter.recipient, attester: filter.attester, schemaUID: schemaUid },\n fromBlock: easScanFromBlock(),\n toBlock: \"latest\",\n });\n\n const out: RawAttestation[] = [];\n for (const log of logs) {\n const uid = log.args.uid;\n if (!uid) continue;\n const a = await client.readContract({\n address: EAS_CONTRACTS().EAS,\n abi: EAS_ABI,\n functionName: \"getAttestation\",\n args: [uid],\n }) as {\n uid: Hex; schema: Hex; time: bigint; expirationTime: bigint;\n revocationTime: bigint; refUID: Hex; recipient: Address;\n attester: Address; revocable: boolean; data: Hex;\n };\n if (a.revocationTime !== 0n) continue; // revoked\n out.push({\n id: a.uid,\n attester: a.attester,\n recipient: a.recipient,\n time: Number(a.time),\n data: a.data,\n });\n }\n // GraphQL callers order newest-first; keep that contract.\n return out.sort((x, y) => y.time - x.time);\n}\n\n\n\nexport function getEasScanUrl(uid: Hex): string {\n // Always use the EAS chain's scan host — attestations live on Base, even\n // for HyperEVM funds. Read the registry directly rather than mutating\n // the singleton, since this is a pure URL build.\n const host = CHAIN_REGISTRY[getEasNetwork()].easScanHost;\n // Neither Robinhood chain has an easscan-equivalent UI. Throwing here used\n // to blank the \"Attested:\" line at every best-effort call site (they all\n // swallow it), hiding a write that DID land — show the uid instead.\n if (!host) return `uid ${uid}`;\n return `https://${host}/attestation/view/${uid}`;\n}\n\n/**\n * The block-explorer URL for a tx that ran on the EAS chain. Use this for\n * attestation create/revoke txs so the link points to base(-sepolia) scan\n * even when the active --chain is HyperEVM / Robinhood.\n */\nexport function getEasExplorerUrl(txHash: string): string {\n const host = CHAIN_REGISTRY[getEasNetwork()].explorerHost;\n return `https://${host}/tx/${txHash}`;\n}\n\n// ── Attestation Creation ──\n\n/**\n * Extract the attestation UID from a transaction receipt.\n * The EAS contract emits: event Attested(address indexed recipient, address indexed attester, bytes32 uid, bytes32 indexed schemaUID)\n * uid is a non-indexed parameter in the event data.\n */\nfunction extractAttestationUid(receipt: { logs: readonly { topics: readonly Hex[]; data: Hex }[] }): Hex {\n for (const log of receipt.logs) {\n // Match the Attested event signature to avoid false positives from other events\n if (log.topics[0] !== ATTESTED_TOPIC) continue;\n // Attested event has 4 topics (sig + 3 indexed) and data contains the uid (bytes32)\n if (log.topics.length === 4 && log.data.length >= 66) {\n return (\"0x\" + log.data.slice(2, 66)) as Hex;\n }\n }\n throw new Error(\"Could not extract attestation UID from transaction receipt\");\n}\n\n// ── Message Prefix Helpers ──\n//\n// Join-request messages can carry CLI metadata as bracketed prefixes. Order\n// is `[chain:<network>] [ref:<id>] body` — chain outer because the chain\n// disambiguates the fund, ref inner because it's optional and per-user.\n// Both prefixes are stripped before display.\n\nconst CHAIN_PREFIX_RE = /^\\[chain:([a-z0-9-]+)\\]\\s*/;\n// Tolerate an optional leading [chain:...] prefix so parseReferrer keeps\n// working when both metadata fields are encoded.\nconst REF_PREFIX_RE = /^(?:\\[chain:[a-z0-9-]+\\]\\s*)?\\[ref:(\\d+)\\]\\s*/;\n\n/**\n * Format a message with an optional referrer prefix.\n * e.g. formatMessageWithRef(\"Hello\", 42) → \"[ref:42] Hello\"\n */\nexport function formatMessageWithRef(message: string, referrerAgentId?: number): string {\n if (referrerAgentId == null) return message;\n return `[ref:${referrerAgentId}] ${message}`;\n}\n\n/**\n * Parse a referrer agentId from a message, if present.\n * e.g. parseReferrer(\"[ref:42] Hello\") → 42\n * parseReferrer(\"[chain:hyperevm] [ref:42] Hello\") → 42\n */\nexport function parseReferrer(message: string): number | null {\n const match = message.match(REF_PREFIX_RE);\n return match ? parseInt(match[1], 10) : null;\n}\n\n/**\n * Format a message with a `[chain:<network>]` prefix when the fund\n * lives on a chain other than the EAS chain (Base / Base-Sepolia). Skipped\n * when source matches the EAS chain to avoid noise on the common case.\n */\nexport function formatMessageWithChain(\n message: string,\n sourceNetwork: Network,\n easNetwork: Network,\n): string {\n if (sourceNetwork === easNetwork) return message;\n return `[chain:${sourceNetwork}] ${message}`;\n}\n\n/**\n * Parse the source-chain prefix from a message, if present.\n * Returns null when no `[chain:<network>]` prefix is found, which means the\n * attestation was created from the EAS chain itself (e.g. base attestation\n * for a base fund).\n */\nexport function parseChain(message: string): string | null {\n const match = message.match(CHAIN_PREFIX_RE);\n return match ? match[1] : null;\n}\n\n/**\n * Strip both `[chain:...]` and `[ref:...]` prefixes from a message,\n * returning the clean human-facing body. Name kept for backward compat.\n */\nexport function stripReferrerPrefix(message: string): string {\n // REF_PREFIX_RE already swallows an optional leading chain prefix when ref\n // is present; the second replace handles a chain prefix without ref.\n return message.replace(REF_PREFIX_RE, \"\").replace(CHAIN_PREFIX_RE, \"\");\n}\n\n/**\n * Create a SYNDICATE_JOIN_REQUEST attestation.\n * Attester: the calling agent. Recipient: the fund creator.\n * If referrerAgentId is provided, it's embedded in the message as a [ref:N] prefix.\n */\nexport async function createJoinRequest(\n syndicateId: bigint,\n agentId: bigint,\n vault: Address,\n creatorAddress: Address,\n message: string,\n referrerAgentId?: number,\n): Promise<{ uid: Hex; hash: Hex } | null> {\n if (skipWriteOnFork(\"join request\")) return null;\n // Capture the fund's source chain BEFORE switching to the EAS chain\n // so we can encode it in the message prefix.\n const sourceNetwork = getNetwork();\n const easNetwork = getEasNetwork();\n const messageWithRef = formatMessageWithRef(message, referrerAgentId);\n const encodedMessage = formatMessageWithChain(messageWithRef, sourceNetwork, easNetwork);\n\n return withNetwork(easNetwork, async () => {\n assertSchemasRegistered();\n\n const data = encodeAbiParameters(JOIN_REQUEST_PARAMS, [\n syndicateId, agentId, vault, encodedMessage,\n ]);\n\n const hash = await writeContractWithRetry({\n account: getAccount(),\n chain: getChain(),\n address: EAS_CONTRACTS().EAS,\n abi: EAS_ABI,\n functionName: \"attest\",\n args: [{\n schema: EAS_SCHEMAS().SYNDICATE_JOIN_REQUEST,\n data: {\n recipient: creatorAddress,\n expirationTime: 0n,\n revocable: true,\n refUID: ZERO_BYTES32,\n data,\n value: 0n,\n },\n }],\n value: 0n,\n });\n\n const receipt = await waitForReceipt(hash);\n const uid = extractAttestationUid(receipt);\n\n return { uid, hash };\n });\n}\n\n/**\n * Create an AGENT_APPROVED attestation.\n * Attester: the fund creator. Recipient: the agent wallet.\n */\nexport async function createApproval(\n syndicateId: bigint,\n agentId: bigint,\n vault: Address,\n agentAddress: Address,\n): Promise<{ uid: Hex; hash: Hex } | null> {\n if (skipWriteOnFork(\"approval\")) return null;\n return withNetwork(getEasNetwork(), async () => {\n assertSchemasRegistered();\n\n const data = encodeAbiParameters(AGENT_APPROVED_PARAMS, [\n syndicateId, agentId, vault,\n ]);\n\n const hash = await writeContractWithRetry({\n account: getAccount(),\n chain: getChain(),\n address: EAS_CONTRACTS().EAS,\n abi: EAS_ABI,\n functionName: \"attest\",\n args: [{\n schema: EAS_SCHEMAS().AGENT_APPROVED,\n data: {\n recipient: agentAddress,\n expirationTime: 0n,\n revocable: true,\n refUID: ZERO_BYTES32,\n data,\n value: 0n,\n },\n }],\n value: 0n,\n });\n\n const receipt = await waitForReceipt(hash);\n const uid = extractAttestationUid(receipt);\n\n return { uid, hash };\n });\n}\n\n/**\n * Revoke an attestation. Only the original attester can revoke. Uses the\n * active chain's EAS — call sites that revoke fund-coordination\n * attestations (join requests, approvals) should go through\n * `revokeJoinRequest` / `revokeApproval` so the revoke lands on the same\n * chain as the original attestation (Base / Base-Sepolia).\n */\nexport async function revokeAttestation(\n schemaUid: Hex,\n attestationUid: Hex,\n): Promise<Hex> {\n return writeContractWithRetry({\n account: getAccount(),\n chain: getChain(),\n address: EAS_CONTRACTS().EAS,\n abi: EAS_ABI,\n functionName: \"revoke\",\n args: [{\n schema: schemaUid,\n data: {\n uid: attestationUid,\n value: 0n,\n },\n }],\n value: 0n,\n });\n}\n\n/** Revoke a SYNDICATE_JOIN_REQUEST on the EAS chain (Base / Base-Sepolia). */\nexport async function revokeJoinRequest(attestationUid: Hex): Promise<Hex | null> {\n if (skipWriteOnFork(\"revoke\")) return null;\n return withNetwork(getEasNetwork(), () =>\n revokeAttestation(EAS_SCHEMAS().SYNDICATE_JOIN_REQUEST, attestationUid),\n );\n}\n\n/**\n * Create an X402_RESEARCH attestation — records a research query on-chain.\n * Attester: the agent. Recipient: vault address (links to fund) or agent itself.\n * Schema: \"string provider, string queryType, string prompt, string costUsdc, string resultUri\"\n */\nexport async function createResearchAttestation(\n provider: string,\n queryType: string,\n prompt: string,\n costUsdc: string,\n resultUri: string,\n recipient?: Address,\n): Promise<{ uid: Hex; hash: Hex } | null> {\n if (skipWriteOnFork(\"research\")) return null;\n const schemas = EAS_SCHEMAS();\n if (schemas.X402_RESEARCH === ZERO_BYTES32) {\n throw new Error(\n \"X402_RESEARCH schema not registered. Run: npx tsx scripts/register-eas-schemas.ts --testnet\",\n );\n }\n\n const client = getPublicClient();\n const account = getAccount();\n\n const data = encodeAbiParameters(X402_RESEARCH_PARAMS, [\n provider, queryType, prompt, costUsdc, resultUri,\n ]);\n\n const hash = await writeContractWithRetry({\n account,\n chain: getChain(),\n address: EAS_CONTRACTS().EAS,\n abi: EAS_ABI,\n functionName: \"attest\",\n args: [{\n schema: schemas.X402_RESEARCH,\n data: {\n recipient: recipient ?? account.address,\n expirationTime: 0n,\n revocable: false,\n refUID: ZERO_BYTES32,\n data,\n value: 0n,\n },\n }],\n value: 0n,\n });\n\n const receipt = await waitForReceipt(hash);\n const uid = extractAttestationUid(receipt);\n\n return { uid, hash };\n}\n\n/**\n * Create a VENICE_PROVISION attestation — records that an agent provisioned a Venice API key.\n * Schema: \"address agent, string status\"\n */\nexport async function createVeniceProvisionAttestation(\n agent: Address,\n): Promise<{ uid: Hex; hash: Hex } | null> {\n if (skipWriteOnFork(\"venice provision\")) return null;\n const schemas = EAS_SCHEMAS();\n if (schemas.VENICE_PROVISION === ZERO_BYTES32) return skipAttestation(\"VENICE_PROVISION\");\n\n const client = getPublicClient();\n const account = getAccount();\n\n const data = encodeAbiParameters(VENICE_PROVISION_PARAMS, [agent, \"provisioned\"]);\n\n const hash = await writeContractWithRetry({\n account,\n chain: getChain(),\n address: EAS_CONTRACTS().EAS,\n abi: EAS_ABI,\n functionName: \"attest\",\n args: [{\n schema: schemas.VENICE_PROVISION,\n data: {\n recipient: agent,\n expirationTime: 0n,\n revocable: false,\n refUID: ZERO_BYTES32,\n data,\n value: 0n,\n },\n }],\n value: 0n,\n });\n\n const receipt = await waitForReceipt(hash);\n const uid = extractAttestationUid(receipt);\n return { uid, hash };\n}\n\n/**\n * Create a VENICE_INFERENCE attestation — records an inference call.\n * Attester: the agent. Recipient: vault address (links to fund) or agent itself.\n * Schema: \"string model, uint256 promptTokens, uint256 completionTokens, string promptHash\"\n */\nexport async function createVeniceInferenceAttestation(\n model: string,\n promptTokens: number,\n completionTokens: number,\n promptHash: string,\n recipient?: Address,\n): Promise<{ uid: Hex; hash: Hex } | null> {\n if (skipWriteOnFork(\"venice inference\")) return null;\n const schemas = EAS_SCHEMAS();\n if (schemas.VENICE_INFERENCE === ZERO_BYTES32) return skipAttestation(\"VENICE_INFERENCE\");\n\n const client = getPublicClient();\n const account = getAccount();\n\n const data = encodeAbiParameters(VENICE_INFERENCE_PARAMS, [\n model,\n BigInt(promptTokens),\n BigInt(completionTokens),\n promptHash,\n ]);\n\n const hash = await writeContractWithRetry({\n account,\n chain: getChain(),\n address: EAS_CONTRACTS().EAS,\n abi: EAS_ABI,\n functionName: \"attest\",\n args: [{\n schema: schemas.VENICE_INFERENCE,\n data: {\n recipient: recipient ?? account.address,\n expirationTime: 0n,\n revocable: false,\n refUID: ZERO_BYTES32,\n data,\n value: 0n,\n },\n }],\n value: 0n,\n });\n\n const receipt = await waitForReceipt(hash);\n const uid = extractAttestationUid(receipt);\n return { uid, hash };\n}\n\n/**\n * Create a TRADE_EXECUTED attestation — records a swap on-chain.\n * Attester: the agent. Recipient: vault address (links to fund) or agent itself.\n * Schema: \"address tokenIn, address tokenOut, uint256 amountIn, string amountOut, string txHash, string routing\"\n */\nexport async function createTradeAttestation(\n tokenIn: Address,\n tokenOut: Address,\n amountIn: bigint,\n amountOut: string,\n txHash: string,\n routing: string,\n recipient?: Address,\n): Promise<{ uid: Hex; hash: Hex } | null> {\n if (skipWriteOnFork(\"trade\")) return null;\n const schemas = EAS_SCHEMAS();\n if (schemas.TRADE_EXECUTED === ZERO_BYTES32) return skipAttestation(\"TRADE_EXECUTED\");\n\n const client = getPublicClient();\n const account = getAccount();\n\n const data = encodeAbiParameters(TRADE_EXECUTED_PARAMS, [\n tokenIn, tokenOut, amountIn, amountOut, txHash, routing,\n ]);\n\n const hash = await writeContractWithRetry({\n account,\n chain: getChain(),\n address: EAS_CONTRACTS().EAS,\n abi: EAS_ABI,\n functionName: \"attest\",\n args: [{\n schema: schemas.TRADE_EXECUTED,\n data: {\n recipient: recipient ?? account.address,\n expirationTime: 0n,\n revocable: false,\n refUID: ZERO_BYTES32,\n data,\n value: 0n,\n },\n }],\n value: 0n,\n });\n\n const receipt = await waitForReceipt(hash);\n const uid = extractAttestationUid(receipt);\n return { uid, hash };\n}\n\n/** Skip attestation gracefully when schema isn't registered on this chain. */\nfunction skipAttestation(name: string): { uid: Hex; hash: Hex } {\n return { uid: ZERO_BYTES32, hash: ZERO_BYTES32 };\n}\n\n// ── Attestation Queries ──\n\nexport interface JoinRequestAttestation {\n uid: Hex;\n attester: Address;\n recipient: Address;\n time: number;\n decoded: {\n syndicateId: bigint;\n agentId: bigint;\n vault: Address;\n message: string;\n };\n}\n\n/**\n * Query pending (non-revoked) join requests for a given recipient (creator address).\n * Uses the EAS GraphQL API.\n */\nexport interface ApprovalAttestation {\n uid: Hex;\n attester: Address;\n recipient: Address;\n time: number;\n decoded: {\n syndicateId: bigint;\n agentId: bigint;\n vault: Address;\n };\n}\n\n/**\n * Query existing (non-revoked) AGENT_APPROVED attestations created by a given attester (creator).\n * Used to check for duplicates before creating a new approval and to filter already-approved agents from requests.\n */\nexport async function queryApprovals(\n attester: Address,\n): Promise<ApprovalAttestation[]> {\n return withNetwork(getEasNetwork(), () => queryApprovalsImpl(attester));\n}\n\nasync function queryApprovalsImpl(attester: Address): Promise<ApprovalAttestation[]> {\n assertSchemasRegistered();\n const schemaUid = EAS_SCHEMAS().AGENT_APPROVED;\n if (!hasEasIndexer()) {\n const rows = await queryAttestationsOnChain(schemaUid, { attester });\n return rows.map(decodeApprovalRow);\n }\n const url = getEasGraphqlUrl();\n\n const query = `\n query Approvals($schemaId: String!, $attester: String!) {\n attestations(\n where: {\n schemaId: { equals: $schemaId }\n attester: { equals: $attester }\n revoked: { equals: false }\n }\n orderBy: [{ time: desc }]\n ) {\n id\n attester\n recipient\n time\n data\n }\n }\n `;\n\n const response = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n query,\n variables: { schemaId: schemaUid, attester },\n }),\n });\n\n if (!response.ok) {\n throw new Error(`EAS GraphQL query failed: ${response.statusText}`);\n }\n\n const json = await response.json() as {\n data?: {\n attestations: Array<{\n id: string;\n attester: string;\n recipient: string;\n time: number;\n data: string;\n }>;\n };\n };\n\n if (!json.data?.attestations) return [];\n\n return json.data.attestations.map(decodeApprovalRow);\n}\n\n/** Decode one AGENT_APPROVED row — same shape from GraphQL or from a log read. */\nfunction decodeApprovalRow(a: RawAttestation): ApprovalAttestation {\n const decoded = decodeAbiParameters(AGENT_APPROVED_PARAMS, a.data as Hex);\n return {\n uid: a.id as Hex,\n attester: a.attester as Address,\n recipient: a.recipient as Address,\n time: a.time,\n decoded: {\n syndicateId: decoded[0],\n agentId: decoded[1],\n vault: decoded[2],\n },\n };\n}\n\nexport async function queryJoinRequests(\n recipient: Address,\n): Promise<JoinRequestAttestation[]> {\n return withNetwork(getEasNetwork(), () => queryJoinRequestsImpl(recipient));\n}\n\nasync function queryJoinRequestsImpl(recipient: Address): Promise<JoinRequestAttestation[]> {\n assertSchemasRegistered();\n const schemaUid = EAS_SCHEMAS().SYNDICATE_JOIN_REQUEST;\n if (!hasEasIndexer()) {\n const rows = await queryAttestationsOnChain(schemaUid, { recipient });\n return rows.map(decodeJoinRequestRow);\n }\n const url = getEasGraphqlUrl();\n\n const query = `\n query JoinRequests($schemaId: String!, $recipient: String!) {\n attestations(\n where: {\n schemaId: { equals: $schemaId }\n recipient: { equals: $recipient }\n revoked: { equals: false }\n }\n orderBy: [{ time: desc }]\n ) {\n id\n attester\n recipient\n time\n data\n }\n }\n `;\n\n const response = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n query,\n variables: { schemaId: schemaUid, recipient },\n }),\n });\n\n if (!response.ok) {\n throw new Error(`EAS GraphQL query failed: ${response.statusText}`);\n }\n\n const json = await response.json() as {\n data?: {\n attestations: Array<{\n id: string;\n attester: string;\n recipient: string;\n time: number;\n data: string;\n }>;\n };\n };\n\n if (!json.data?.attestations) return [];\n\n return json.data.attestations.map(decodeJoinRequestRow);\n}\n\n/** Decode one SYNDICATE_JOIN_REQUEST row — GraphQL or log read. */\nfunction decodeJoinRequestRow(a: RawAttestation): JoinRequestAttestation {\n const decoded = decodeAbiParameters(JOIN_REQUEST_PARAMS, a.data as Hex);\n return {\n uid: a.id as Hex,\n attester: a.attester as Address,\n recipient: a.recipient as Address,\n time: a.time,\n decoded: {\n syndicateId: decoded[0],\n agentId: decoded[1],\n vault: decoded[2],\n message: decoded[3],\n },\n };\n}\n"],"mappings":"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","names":[]}
@@ -9,6 +9,8 @@ import {
9
9
  createTradeAttestation,
10
10
  createVeniceInferenceAttestation,
11
11
  createVeniceProvisionAttestation,
12
+ forkAttestationsEnabled,
13
+ forkAttestationsEnabledFor,
12
14
  formatMessageWithChain,
13
15
  formatMessageWithRef,
14
16
  getEasExplorerUrl,
@@ -21,7 +23,7 @@ import {
21
23
  revokeAttestation,
22
24
  revokeJoinRequest,
23
25
  stripReferrerPrefix
24
- } from "./chunk-SI65QHTY.js";
26
+ } from "./chunk-SCQAKMMI.js";
25
27
  import "./chunk-FWQESFFM.js";
26
28
  import "./chunk-D4BSBW3Q.js";
27
29
  import "./chunk-G3FUEM5N.js";
@@ -38,6 +40,8 @@ export {
38
40
  createTradeAttestation,
39
41
  createVeniceInferenceAttestation,
40
42
  createVeniceProvisionAttestation,
43
+ forkAttestationsEnabled,
44
+ forkAttestationsEnabledFor,
41
45
  formatMessageWithChain,
42
46
  formatMessageWithRef,
43
47
  getEasExplorerUrl,
@@ -51,4 +55,4 @@ export {
51
55
  revokeJoinRequest,
52
56
  stripReferrerPrefix
53
57
  };
54
- //# sourceMappingURL=eas-DV3Z7AT3.js.map
58
+ //# sourceMappingURL=eas-B4HR2HXX.js.map
@@ -2,8 +2,8 @@ import {
2
2
  lookupAgentIdByWallet,
3
3
  lookupAgentIdsByWallet,
4
4
  registerIdentityCommands
5
- } from "./chunk-VYCLG5DE.js";
6
- import "./chunk-SI65QHTY.js";
5
+ } from "./chunk-HMFPP2PE.js";
6
+ import "./chunk-SCQAKMMI.js";
7
7
  import "./chunk-FWQESFFM.js";
8
8
  import "./chunk-D4BSBW3Q.js";
9
9
  import "./chunk-G3FUEM5N.js";
@@ -15,4 +15,4 @@ export {
15
15
  lookupAgentIdsByWallet,
16
16
  registerIdentityCommands
17
17
  };
18
- //# sourceMappingURL=identity-M4TXM7EX.js.map
18
+ //# sourceMappingURL=identity-I2BG4IGT.js.map
package/dist/index.js CHANGED
@@ -68,7 +68,7 @@ import {
68
68
  setCalldataOnly,
69
69
  stripVidTag,
70
70
  verifyVidTag
71
- } from "./chunk-VYCLG5DE.js";
71
+ } from "./chunk-HMFPP2PE.js";
72
72
  import {
73
73
  createApproval,
74
74
  createJoinRequest,
@@ -78,7 +78,7 @@ import {
78
78
  queryJoinRequests,
79
79
  revokeJoinRequest,
80
80
  stripReferrerPrefix
81
- } from "./chunk-SI65QHTY.js";
81
+ } from "./chunk-SCQAKMMI.js";
82
82
  import {
83
83
  createFund,
84
84
  getActiveFunds,
@@ -114,7 +114,7 @@ import {
114
114
  removeDepositor,
115
115
  setAgentFeeBps,
116
116
  setVaultAddress
117
- } from "./chunk-N2E2Q5GL.js";
117
+ } from "./chunk-CWGP4VXZ.js";
118
118
  import "./chunk-BH3VTJ4F.js";
119
119
  import {
120
120
  PROPOSAL_STATE,
@@ -1393,7 +1393,7 @@ function registerStrategyProposeCommands(strategy2) {
1393
1393
  metadataURI = `data:application/json;base64,${Buffer.from(inline).toString("base64")}`;
1394
1394
  }
1395
1395
  try {
1396
- const { getAgentFeeBps: getAgentFeeBps2 } = await import("./vault-WWGSRNRP.js");
1396
+ const { getAgentFeeBps: getAgentFeeBps2 } = await import("./vault-E7XD6DLD.js");
1397
1397
  const feeBps = await getAgentFeeBps2(vault);
1398
1398
  console.log(
1399
1399
  chalk3.yellow(
@@ -2074,7 +2074,7 @@ function registerVeniceCommands(program2) {
2074
2074
  console.log(chalk5.dim(` Key: ${apiKey.slice(0, 8)}...${apiKey.slice(-4)}`));
2075
2075
  console.log(chalk5.dim(" Saved to ~/.sherwood/config.json"));
2076
2076
  try {
2077
- const { createVeniceProvisionAttestation, getEasScanUrl } = await import("./eas-DV3Z7AT3.js");
2077
+ const { createVeniceProvisionAttestation, getEasScanUrl } = await import("./eas-B4HR2HXX.js");
2078
2078
  const attestation = await createVeniceProvisionAttestation(account.address);
2079
2079
  if (attestation) {
2080
2080
  console.log(chalk5.dim(` Attested: ${getEasScanUrl(attestation.uid)}`));
@@ -2430,7 +2430,7 @@ ${opts.prompt}`;
2430
2430
  console.log(chalk5.dim(`Model: ${result.model} | Tokens: ${result.usage.promptTokens} in, ${result.usage.completionTokens} out, ${result.usage.totalTokens} total`));
2431
2431
  }
2432
2432
  try {
2433
- const { createVeniceInferenceAttestation, getEasScanUrl } = await import("./eas-DV3Z7AT3.js");
2433
+ const { createVeniceInferenceAttestation, getEasScanUrl } = await import("./eas-B4HR2HXX.js");
2434
2434
  const { keccak256: keccak2562, toHex, isAddress: isAddr } = await import("viem");
2435
2435
  const { getChainContracts: getChainContracts2 } = await import("./config-ZGFS4I7K.js");
2436
2436
  const { getChain: getActiveChain } = await import("./network-7445KSCF.js");
@@ -3619,7 +3619,7 @@ async function resolveRiskEnvelope(opts, vault) {
3619
3619
  console.error(chalk8.red(" --max-capital is required (the ceiling this proposal may deploy, in asset units)."));
3620
3620
  process.exit(1);
3621
3621
  }
3622
- const asset = await getAssetAddress();
3622
+ const asset = await getAssetAddress(vault);
3623
3623
  const decimals = await getPublicClient().readContract({
3624
3624
  address: asset,
3625
3625
  abi: ERC20_ABI,
@@ -3818,6 +3818,15 @@ function registerProposalCommands(program2) {
3818
3818
  0n,
3819
3819
  "--settle-caps"
3820
3820
  );
3821
+ try {
3822
+ await ensureProposerBondAllowance(vault, envelope.maxCapital, await getAssetAddress(vault));
3823
+ } catch (err) {
3824
+ if (err instanceof InsufficientProposerBondWood) {
3825
+ spinner.fail(err.message);
3826
+ process.exit(1);
3827
+ }
3828
+ throw err;
3829
+ }
3821
3830
  const result = await propose(
3822
3831
  vault,
3823
3832
  strategy2,
@@ -4345,7 +4354,7 @@ function registerProposalCommands(program2) {
4345
4354
  );
4346
4355
  process.exit(1);
4347
4356
  }
4348
- const asset = await getAssetAddress();
4357
+ const asset = await getAssetAddress(vault);
4349
4358
  const noopCalldata = encodeFunctionData3({
4350
4359
  abi: ERC20_ABI,
4351
4360
  functionName: "balanceOf",
@@ -8048,7 +8057,7 @@ try {
8048
8057
  } catch {
8049
8058
  }
8050
8059
  var require2 = createRequire(import.meta.url);
8051
- var CLI_VERSION = "0.87.1";
8060
+ var CLI_VERSION = "0.88.1";
8052
8061
  async function loadXmtp() {
8053
8062
  return import("./xmtp-72IRK7JL.js");
8054
8063
  }
@@ -8721,7 +8730,7 @@ vaultCmd.command("add").description("Register an agent on a vault (creator only)
8721
8730
  agentId = BigInt(opts.agentId);
8722
8731
  } else {
8723
8732
  spinner.text = "Looking up ERC-8004 identity from wallet...";
8724
- const { lookupAgentIdByWallet } = await import("./identity-M4TXM7EX.js");
8733
+ const { lookupAgentIdByWallet } = await import("./identity-I2BG4IGT.js");
8725
8734
  const resolved = await lookupAgentIdByWallet(agentWallet);
8726
8735
  if (resolved === null) {
8727
8736
  spinner.fail("Agent wallet does not own an ERC-8004 identity NFT");
@@ -9453,11 +9462,11 @@ registerProposalCommands(program);
9453
9462
  registerQueueCommands(program);
9454
9463
  registerGovernorCommands(program);
9455
9464
  registerGuardianCommands(program);
9456
- var { registerResearchCommands } = await import("./research-44GHYE4H.js");
9465
+ var { registerResearchCommands } = await import("./research-T7A27OMB.js");
9457
9466
  registerResearchCommands(program);
9458
9467
  var { registerAgentCommands } = await import("./agent-FCGZL4GF.js");
9459
9468
  registerAgentCommands(program);
9460
- var { registerTradeCommands } = await import("./trade-FO52SP62.js");
9469
+ var { registerTradeCommands } = await import("./trade-ZOVM433K.js");
9461
9470
  registerTradeCommands(program);
9462
9471
  registerGridCommand(program);
9463
9472
  var configCmd = program.command("config");