@sherwoodagent/cli 0.7.3 → 0.8.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.
- package/dist/{chat-BSLMAYM5.js → chat-O34BTHII.js} +5 -5
- package/dist/{chunk-EDR5AHSC.js → chunk-4MTHXGTK.js} +2 -2
- package/dist/{chunk-QMWMT6EH.js → chunk-5ADWTXNT.js} +115 -31
- package/dist/chunk-5ADWTXNT.js.map +1 -0
- package/dist/{chunk-B7XDUFI3.js → chunk-ARZIQ7YZ.js} +3 -3
- package/dist/{chunk-6MEYSN2W.js → chunk-BXUNWV52.js} +480 -36
- package/dist/chunk-BXUNWV52.js.map +1 -0
- package/dist/{chunk-P3GYAMGZ.js → chunk-VQP4XR67.js} +15 -5
- package/dist/chunk-VQP4XR67.js.map +1 -0
- package/dist/{eas-TMHFTX43.js → eas-TI4XI5VU.js} +4 -4
- package/dist/index.js +1064 -210
- package/dist/index.js.map +1 -1
- package/dist/{research-ILKLSHVP.js → research-GX32VMP7.js} +5 -5
- package/dist/{research-5QALNYVS.js → research-ZR7HXITG.js} +3 -3
- package/dist/{session-XUOMZWOT.js → session-QEIVURQO.js} +5 -5
- package/dist/{xmtp-4XTQQ7RE.js → xmtp-A6F63GZH.js} +6 -6
- package/dist/xmtp-A6F63GZH.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-6MEYSN2W.js.map +0 -1
- package/dist/chunk-P3GYAMGZ.js.map +0 -1
- package/dist/chunk-QMWMT6EH.js.map +0 -1
- package/dist/xmtp-4XTQQ7RE.js.map +0 -1
- /package/dist/{chat-BSLMAYM5.js.map → chat-O34BTHII.js.map} +0 -0
- /package/dist/{chunk-EDR5AHSC.js.map → chunk-4MTHXGTK.js.map} +0 -0
- /package/dist/{chunk-B7XDUFI3.js.map → chunk-ARZIQ7YZ.js.map} +0 -0
- /package/dist/{eas-TMHFTX43.js.map → eas-TI4XI5VU.js.map} +0 -0
- /package/dist/{research-ILKLSHVP.js.map → research-GX32VMP7.js.map} +0 -0
- /package/dist/{research-5QALNYVS.js.map → research-ZR7HXITG.js.map} +0 -0
- /package/dist/{session-XUOMZWOT.js.map → session-QEIVURQO.js.map} +0 -0
|
@@ -2,10 +2,10 @@ import {
|
|
|
2
2
|
MESSARI_COST_ESTIMATE,
|
|
3
3
|
NANSEN_COST_ESTIMATE,
|
|
4
4
|
getResearchProvider
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-4MTHXGTK.js";
|
|
6
6
|
import {
|
|
7
7
|
getAccount
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-5ADWTXNT.js";
|
|
9
9
|
|
|
10
10
|
// src/commands/research.ts
|
|
11
11
|
import chalk from "chalk";
|
|
@@ -13,7 +13,7 @@ import ora from "ora";
|
|
|
13
13
|
import { confirm } from "@inquirer/prompts";
|
|
14
14
|
import { isAddress } from "viem";
|
|
15
15
|
async function loadXmtp() {
|
|
16
|
-
return import("./xmtp-
|
|
16
|
+
return import("./xmtp-A6F63GZH.js");
|
|
17
17
|
}
|
|
18
18
|
var COST_ESTIMATES = {
|
|
19
19
|
messari: MESSARI_COST_ESTIMATE,
|
|
@@ -80,7 +80,7 @@ function formatValue(value) {
|
|
|
80
80
|
}
|
|
81
81
|
async function postResearch(syndicateName, result, prompt) {
|
|
82
82
|
const { pinJSON } = await import("./ipfs-P3NVJQCF.js");
|
|
83
|
-
const { createResearchAttestation, getEasScanUrl } = await import("./eas-
|
|
83
|
+
const { createResearchAttestation, getEasScanUrl } = await import("./eas-TI4XI5VU.js");
|
|
84
84
|
const xmtp = await loadXmtp();
|
|
85
85
|
const pinSpinner = ora("Pinning research result to IPFS...").start();
|
|
86
86
|
let resultUri;
|
|
@@ -305,4 +305,4 @@ function registerResearchCommands(program) {
|
|
|
305
305
|
export {
|
|
306
306
|
registerResearchCommands
|
|
307
307
|
};
|
|
308
|
-
//# sourceMappingURL=research-
|
|
308
|
+
//# sourceMappingURL=research-GX32VMP7.js.map
|
|
@@ -2,11 +2,11 @@ import {
|
|
|
2
2
|
MessariProvider,
|
|
3
3
|
NansenProvider,
|
|
4
4
|
getResearchProvider
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-4MTHXGTK.js";
|
|
6
|
+
import "./chunk-5ADWTXNT.js";
|
|
7
7
|
export {
|
|
8
8
|
MessariProvider,
|
|
9
9
|
NansenProvider,
|
|
10
10
|
getResearchProvider
|
|
11
11
|
};
|
|
12
|
-
//# sourceMappingURL=research-
|
|
12
|
+
//# sourceMappingURL=research-ZR7HXITG.js.map
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
resolveSyndicate
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-ARZIQ7YZ.js";
|
|
4
4
|
import {
|
|
5
5
|
SHERWOOD,
|
|
6
6
|
SYNDICATE_VAULT_ABI
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-BXUNWV52.js";
|
|
8
8
|
import {
|
|
9
9
|
getPublicClient
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-5ADWTXNT.js";
|
|
11
11
|
|
|
12
12
|
// src/commands/session.ts
|
|
13
13
|
import chalk from "chalk";
|
|
@@ -160,7 +160,7 @@ async function getCurrentBlock() {
|
|
|
160
160
|
|
|
161
161
|
// src/commands/session.ts
|
|
162
162
|
async function loadXmtp() {
|
|
163
|
-
return import("./xmtp-
|
|
163
|
+
return import("./xmtp-A6F63GZH.js");
|
|
164
164
|
}
|
|
165
165
|
async function resolveGovernor(vaultAddress) {
|
|
166
166
|
const client = getPublicClient();
|
|
@@ -387,4 +387,4 @@ function registerSessionCommands(program) {
|
|
|
387
387
|
export {
|
|
388
388
|
registerSessionCommands
|
|
389
389
|
};
|
|
390
|
-
//# sourceMappingURL=session-
|
|
390
|
+
//# sourceMappingURL=session-QEIVURQO.js.map
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getTextRecord
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import "./chunk-
|
|
3
|
+
} from "./chunk-ARZIQ7YZ.js";
|
|
4
|
+
import "./chunk-BXUNWV52.js";
|
|
5
5
|
import {
|
|
6
6
|
cacheGroupId,
|
|
7
7
|
getAccount,
|
|
8
8
|
getCachedGroupId,
|
|
9
|
-
|
|
9
|
+
getChainConfig,
|
|
10
10
|
loadConfig,
|
|
11
11
|
saveConfig
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-5ADWTXNT.js";
|
|
13
13
|
|
|
14
14
|
// src/lib/xmtp.ts
|
|
15
15
|
import { execFileSync, spawn, execSync } from "child_process";
|
|
@@ -46,7 +46,7 @@ function getXmtpBinaryPath() {
|
|
|
46
46
|
);
|
|
47
47
|
}
|
|
48
48
|
function getXmtpEnv() {
|
|
49
|
-
return
|
|
49
|
+
return getChainConfig().xmtpEnv;
|
|
50
50
|
}
|
|
51
51
|
function getXmtpEnvFile() {
|
|
52
52
|
return path.join(homedir(), ".xmtp", ".env");
|
|
@@ -360,4 +360,4 @@ export {
|
|
|
360
360
|
sendReaction,
|
|
361
361
|
streamMessages
|
|
362
362
|
};
|
|
363
|
-
//# sourceMappingURL=xmtp-
|
|
363
|
+
//# sourceMappingURL=xmtp-A6F63GZH.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/xmtp.ts"],"sourcesContent":["/**\n * XMTP client and group operations for syndicate chat.\n *\n * Shells out to the @xmtp/cli binary instead of using @xmtp/node-sdk directly.\n * This avoids native binding (GLIBC) issues on Linux.\n *\n * Credentials: the sherwood private key is passed to each subprocess via the\n * XMTP_WALLET_KEY env var. We never write to ~/.xmtp/.env — the XMTP CLI\n * manages its own DB encryption key and env file. This avoids destroying\n * existing XMTP setups when agents already have the CLI configured.\n */\n\nimport { execFileSync, spawn, execSync } from \"node:child_process\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { homedir } from \"node:os\";\nimport {\n loadConfig,\n saveConfig,\n cacheGroupId,\n getCachedGroupId,\n} from \"./config.js\";\nimport { getTextRecord } from \"./ens.js\";\nimport { getChainConfig } from \"./network.js\";\nimport type { ChatEnvelope } from \"./types.js\";\nimport { getAccount } from \"./client.js\";\n\n// ── Types ──\n\nexport interface XmtpMessage {\n id: string;\n conversationId: string;\n senderInboxId: string;\n contentType: string;\n content: string;\n sentAt: Date;\n}\n\nexport interface XmtpMember {\n inboxId: string;\n permissionLevel: string;\n}\n\n// ── Binary resolution ──\n\nlet _binaryPath: string | null = null;\n\nfunction getXmtpBinaryPath(): string {\n if (_binaryPath) return _binaryPath;\n\n // Try local node_modules/@xmtp/cli/bin/run.js relative to this file\n const searchPaths = [\n // From dist/ after build\n path.resolve(import.meta.dirname, \"..\", \"node_modules\", \"@xmtp\", \"cli\", \"bin\", \"run.js\"),\n // From src/ during dev\n path.resolve(import.meta.dirname, \"..\", \"..\", \"node_modules\", \"@xmtp\", \"cli\", \"bin\", \"run.js\"),\n // From cwd\n path.resolve(process.cwd(), \"node_modules\", \"@xmtp\", \"cli\", \"bin\", \"run.js\"),\n ];\n\n for (const p of searchPaths) {\n if (fs.existsSync(p)) {\n _binaryPath = p;\n return _binaryPath;\n }\n }\n\n // Fall back to system PATH\n try {\n const which = execSync(\"which xmtp\", { encoding: \"utf8\" }).trim();\n if (which) {\n _binaryPath = which;\n return _binaryPath;\n }\n } catch {\n // Not on PATH\n }\n\n throw new Error(\n \"XMTP CLI not found. Install with: npm install -g @xmtp/cli\",\n );\n}\n\n// ── Environment ──\n\nfunction getXmtpEnv(): string {\n return getChainConfig().xmtpEnv;\n}\n\nfunction getXmtpEnvFile(): string {\n return path.join(homedir(), \".xmtp\", \".env\");\n}\n\n/**\n * Ensure ~/.xmtp/.env exists with at least the wallet key and a DB encryption key.\n * If the file already exists, only update the wallet key line — preserve everything\n * else (especially XMTP_DB_ENCRYPTION_KEY). If no file exists, run `xmtp init` to\n * let the CLI generate its own keys, then patch in our wallet key.\n */\nlet _envReady = false;\n\nfunction ensureXmtpEnv(): void {\n if (_envReady) return;\n\n const config = loadConfig();\n if (!config.privateKey) {\n throw new Error(\n 'No private key configured. Run \"sherwood config set --private-key 0x...\"',\n );\n }\n\n const envFile = getXmtpEnvFile();\n const walletKey = config.privateKey.replace(/^0x/, \"\");\n\n if (fs.existsSync(envFile)) {\n const existing = fs.readFileSync(envFile, \"utf8\");\n if (existing.includes(`XMTP_WALLET_KEY=${walletKey}`)) {\n _envReady = true;\n return;\n }\n\n // Update wallet key while preserving all other vars (DB encryption key, etc.)\n const lines = existing.split(\"\\n\").filter((l) => !l.startsWith(\"XMTP_WALLET_KEY=\"));\n lines.push(`XMTP_WALLET_KEY=${walletKey}`);\n fs.writeFileSync(envFile, lines.filter(Boolean).join(\"\\n\") + \"\\n\", { mode: 0o600 });\n } else {\n // No env file — let XMTP CLI generate keys via `init`, then patch wallet key\n const xmtpDir = path.join(homedir(), \".xmtp\");\n fs.mkdirSync(xmtpDir, { recursive: true });\n\n const bin = getXmtpBinaryPath();\n const initArgs = [\"init\", \"--env\", getXmtpEnv()];\n if (bin.endsWith(\".js\")) {\n execFileSync(\"node\", [bin, ...initArgs], {\n encoding: \"utf8\",\n timeout: 30_000,\n env: { ...process.env, XMTP_WALLET_KEY: walletKey },\n });\n } else {\n execFileSync(bin, initArgs, {\n encoding: \"utf8\",\n timeout: 30_000,\n env: { ...process.env, XMTP_WALLET_KEY: walletKey },\n });\n }\n\n // Patch in our wallet key (init may have generated a different one)\n if (fs.existsSync(envFile)) {\n const content = fs.readFileSync(envFile, \"utf8\");\n const lines = content.split(\"\\n\").filter((l) => !l.startsWith(\"XMTP_WALLET_KEY=\"));\n lines.push(`XMTP_WALLET_KEY=${walletKey}`);\n fs.writeFileSync(envFile, lines.filter(Boolean).join(\"\\n\") + \"\\n\", { mode: 0o600 });\n } else {\n // init didn't create the file — write a minimal one\n fs.writeFileSync(envFile, `XMTP_WALLET_KEY=${walletKey}\\n`, { mode: 0o600 });\n }\n }\n\n _envReady = true;\n}\n\n// ── Subprocess runners ──\n\nfunction execXmtp(args: string[]): string {\n ensureXmtpEnv();\n const bin = getXmtpBinaryPath();\n const fullArgs = [...args, \"--env\", getXmtpEnv(), \"--env-file\", getXmtpEnvFile()];\n\n if (bin.endsWith(\".js\")) {\n return execFileSync(\"node\", [bin, ...fullArgs], {\n encoding: \"utf8\",\n timeout: 30_000,\n }).trim();\n }\n\n return execFileSync(bin, fullArgs, {\n encoding: \"utf8\",\n timeout: 30_000,\n }).trim();\n}\n\nfunction execXmtpJson<T>(args: string[]): T {\n const stdout = execXmtp([...args, \"--json\", \"--log-level\", \"off\"]);\n return JSON.parse(stdout) as T;\n}\n\n// ── Conversation sync ──\n\nlet _conversationsSynced = false;\n\n/**\n * Sync conversations from the network into the local XMTP DB.\n * One-shot commands (send, messages, members) spawn a fresh process\n * that may not have the group locally — this ensures it's available.\n *\n * Uses `sync-all` instead of `sync` because `sync` only refreshes\n * already-known conversations. `sync-all` also processes MLS welcome\n * messages, which is required for agents that were added to a group\n * by someone else. Only runs once per process.\n */\nfunction syncConversations(): void {\n if (_conversationsSynced) return;\n execXmtp([\"conversations\", \"sync-all\"]);\n _conversationsSynced = true;\n}\n\n// ── Stale installation cleanup ──\n\n/**\n * Revoke stale XMTP installations for the current wallet.\n *\n * When an agent wipes ~/.xmtp/ and re-initializes, a new MLS installation is\n * created but old ones remain registered on the network. When add-members runs,\n * the MLS welcome may target a stale installation's KeyPackage — the current\n * installation can never sync that group.\n *\n * This function detects and revokes all installations except the current one,\n * ensuring add-members targets the right installation.\n */\nfunction revokeStaleInstallations(inboxId: string, currentInstallationId: string): void {\n try {\n // Get all installations for this inbox from the network\n const inboxStates = execXmtpJson<Array<{\n inboxId: string;\n installations: Array<{ id: string }>;\n }>>([\"inbox-states\", inboxId]);\n\n const state = inboxStates?.[0];\n if (!state?.installations || state.installations.length <= 1) return;\n\n const staleIds = state.installations\n .map((i) => i.id)\n .filter((id) => id !== currentInstallationId);\n\n if (staleIds.length === 0) return;\n\n // Revoke stale installations — only the wallet owner can do this\n execXmtp([\n \"revoke-installations\",\n inboxId,\n \"-i\",\n staleIds.join(\",\"),\n \"--force\",\n ]);\n } catch {\n // Non-fatal — stale installations are a UX issue, not a blocker\n }\n}\n\n// ── Client ──\n\nexport async function getXmtpClient(): Promise<string> {\n // client info returns { properties: { inboxId, installationId, ... }, options: { ... } }\n const result = execXmtpJson<{\n properties: {\n inboxId: string;\n installationId: string;\n };\n }>([\"client\", \"info\"]);\n\n const { inboxId, installationId } = result.properties;\n\n // Cache inbox ID\n const config = loadConfig();\n if (!config.xmtpInboxId && inboxId) {\n config.xmtpInboxId = inboxId;\n saveConfig(config);\n }\n\n // Clean up stale installations so add-members targets the current one\n if (inboxId && installationId) {\n revokeStaleInstallations(inboxId, installationId);\n }\n\n return inboxId;\n}\n\n// ── Group Creation ──\n\nexport async function createSyndicateGroup(\n _client: string,\n subdomain: string,\n isPublic: boolean = false,\n): Promise<string> {\n // CLI requires at least one member address; use creator's own address\n // (creator is auto-added as super admin regardless)\n const creatorAddress = getAccount().address;\n const result = execXmtpJson<{ id?: string; conversationId?: string; groupId?: string }>(\n [\n \"conversations\",\n \"create-group\",\n creatorAddress,\n \"--name\",\n subdomain,\n \"--description\",\n `Sherwood syndicate: ${subdomain}.sherwoodagent.eth`,\n \"--permissions\",\n \"admin-only\",\n ],\n );\n\n const groupId = result.id || result.conversationId || result.groupId;\n if (!groupId) {\n throw new Error(\"Failed to parse group ID from xmtp CLI output\");\n }\n\n // Add spectator if requested — enables dashboard live feed\n const SPECTATOR_ADDRESS = process.env.DASHBOARD_SPECTATOR_ADDRESS || \"0xec00089b73fbd0733cc11ee39f81404cbc9c9786\";\n if (isPublic) {\n await addMember(groupId, SPECTATOR_ADDRESS);\n }\n\n // Cache locally\n cacheGroupId(subdomain, groupId);\n\n return groupId;\n}\n\n// ── Group Lookup ──\n\n/**\n * Check if a conversation exists in the local XMTP DB.\n * Returns true if `conversations get <id>` succeeds.\n */\nfunction conversationExists(groupId: string): boolean {\n try {\n execXmtp([\"conversations\", \"get\", groupId]);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Search synced conversations for a group matching the syndicate name.\n * Falls back to this when the cached/ENS group ID is stale.\n */\nfunction findGroupByName(subdomain: string): string | null {\n try {\n const conversations = execXmtpJson<Array<{ id?: string; name?: string; description?: string }>>(\n [\"conversations\", \"list\", \"--type\", \"group\"],\n );\n if (!Array.isArray(conversations)) return null;\n\n const match = conversations.find(\n (c) => c.name === subdomain || c.description?.includes(`${subdomain}.sherwoodagent.eth`),\n );\n return match?.id || null;\n } catch {\n return null;\n }\n}\n\nexport async function getGroup(\n _client: string,\n subdomain: string,\n): Promise<string> {\n // Sync first so we have the latest conversations locally\n syncConversations();\n\n // Try local cache\n let groupId: string | undefined = getCachedGroupId(subdomain);\n\n // Validate cached ID actually exists in the local DB\n if (groupId && !conversationExists(groupId)) {\n cacheGroupId(subdomain, \"\"); // invalidate stale entry\n groupId = undefined;\n }\n\n // Fall back to on-chain ENS text record\n if (!groupId) {\n const ensId = await getTextRecord(subdomain, \"xmtpGroupId\");\n if (ensId && conversationExists(ensId)) {\n groupId = ensId;\n cacheGroupId(subdomain, groupId);\n }\n }\n\n // Last resort: search synced conversations by name\n if (!groupId) {\n const found = findGroupByName(subdomain);\n if (found) {\n groupId = found;\n cacheGroupId(subdomain, groupId);\n }\n }\n\n if (!groupId) {\n throw new Error(\n `No XMTP group found for syndicate \"${subdomain}\". Run \"sherwood chat ${subdomain} init\" to create one.`,\n );\n }\n\n return groupId;\n}\n\n// ── Member Management ──\n\nexport async function addMember(\n groupId: string,\n address: string,\n): Promise<void> {\n // Verify the target has an active XMTP identity before adding\n const reachable = execXmtpJson<Array<{ identifier: string; reachable: boolean }>>(\n [\"can-message\", address],\n );\n if (!reachable?.[0]?.reachable) {\n throw new Error(\n `${address} is not reachable on XMTP. They need to initialize their client first (run: xmtp client info --env ${getXmtpEnv()}).`,\n );\n }\n\n syncConversations();\n execXmtp([\"conversation\", \"add-members\", groupId, address]);\n\n // Set consent to \"allowed\" on the adder's side so subsequent operations\n // (send, messages) don't skip this conversation due to unknown consent state\n try {\n execXmtp([\"conversation\", \"update-consent\", groupId, \"--state\", \"allowed\"]);\n } catch {\n // Non-fatal — consent state is a filtering concern, not a blocker\n }\n}\n\nexport async function removeMember(\n groupId: string,\n address: string,\n): Promise<void> {\n syncConversations();\n execXmtp([\"conversation\", \"remove-members\", groupId, address]);\n}\n\n// ── Messaging ──\n\nexport async function sendEnvelope(\n groupId: string,\n envelope: ChatEnvelope,\n): Promise<void> {\n const text = JSON.stringify(envelope);\n execXmtp([\"conversation\", \"send-text\", groupId, text]);\n}\n\nexport async function sendMarkdown(\n groupId: string,\n markdown: string,\n): Promise<void> {\n const envelope: ChatEnvelope = {\n type: \"MESSAGE\",\n from: getAccount().address,\n text: markdown,\n data: { format: \"markdown\" },\n timestamp: Math.floor(Date.now() / 1000),\n };\n await sendEnvelope(groupId, envelope);\n}\n\nexport async function sendReaction(\n groupId: string,\n messageId: string,\n emoji: string,\n): Promise<void> {\n const envelope: ChatEnvelope = {\n type: \"REACTION\",\n from: getAccount().address,\n data: { reference: messageId, emoji },\n timestamp: Math.floor(Date.now() / 1000),\n };\n await sendEnvelope(groupId, envelope);\n}\n\n// ── Streaming ──\n\nexport async function streamMessages(\n groupId: string,\n onMessage: (msg: XmtpMessage) => void,\n): Promise<() => void> {\n ensureXmtpEnv();\n const bin = getXmtpBinaryPath();\n\n const args = [\n \"conversations\",\n \"stream-all-messages\",\n \"--json\",\n \"--log-level\",\n \"off\",\n \"--env\",\n getXmtpEnv(),\n \"--env-file\",\n getXmtpEnvFile(),\n ];\n\n const proc = bin.endsWith(\".js\")\n ? spawn(\"node\", [bin, ...args])\n : spawn(bin, args);\n\n let buffer = \"\";\n proc.stdout.on(\"data\", (chunk: Buffer) => {\n buffer += chunk.toString();\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() || \"\";\n for (const line of lines) {\n if (!line.trim()) continue;\n try {\n const msg = JSON.parse(line);\n // Filter to our group\n if (msg.conversationId === groupId) {\n onMessage({\n id: msg.id || \"\",\n conversationId: msg.conversationId || \"\",\n senderInboxId: msg.senderInboxId || \"\",\n contentType: msg.contentType?.typeId || \"text\",\n content: typeof msg.content === \"string\" ? msg.content : JSON.stringify(msg.content),\n sentAt: new Date(msg.sentAt || Date.now()),\n });\n }\n } catch {\n // Skip unparseable lines\n }\n }\n });\n\n // Return cleanup function\n return () => {\n proc.kill(\"SIGTERM\");\n };\n}\n\n// ── Message History ──\n\nexport async function getRecentMessages(\n groupId: string,\n limit: number = 20,\n): Promise<XmtpMessage[]> {\n const raw = execXmtpJson<Array<Record<string, unknown>>>([\n \"conversation\",\n \"messages\",\n groupId,\n ]);\n\n const messages: XmtpMessage[] = (Array.isArray(raw) ? raw : []).map((m) => ({\n id: String(m.id || \"\"),\n conversationId: String(m.conversationId || \"\"),\n senderInboxId: String(m.senderInboxId || \"\"),\n contentType: String(\n (m.contentType as Record<string, unknown>)?.typeId || \"text\",\n ),\n content:\n typeof m.content === \"string\" ? m.content : JSON.stringify(m.content),\n sentAt: new Date((m.sentAt as string) || Date.now()),\n }));\n\n return messages.slice(-limit);\n}\n\n// ── Members ──\n\nexport async function getMembers(\n groupId: string,\n): Promise<XmtpMember[]> {\n const raw = execXmtpJson<Array<Record<string, unknown>>>([\n \"conversation\",\n \"members\",\n groupId,\n ]);\n\n // permissionLevel from CLI: 0 = member, 1 = admin, 2 = super_admin\n const levelMap: Record<number, string> = { 0: \"member\", 1: \"admin\", 2: \"super_admin\" };\n return (Array.isArray(raw) ? raw : []).map((m) => ({\n inboxId: String(m.inboxId || \"\"),\n permissionLevel: levelMap[Number(m.permissionLevel)] || \"member\",\n }));\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/addresses.ts","../src/lib/abis.ts"],"sourcesContent":["/**\n * Contract addresses by network.\n *\n * All exports are functions — they resolve at call time based on the\n * current network set via setNetwork(). This ensures --testnet works\n * even when modules are imported before the flag is parsed.\n */\n\nimport type { Address } from \"viem\";\nimport { getNetwork } from \"./network.js\";\n\n// ── Base Mainnet ──\n\nconst BASE_TOKENS = {\n USDC: \"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\" as Address,\n WETH: \"0x4200000000000000000000000000000000000006\" as Address,\n cbETH: \"0x2Ae3F1Ec7F1F5012CFEab0185bfc7aa3cf0DEc22\" as Address,\n wstETH: \"0xc1CBa3fCea344f92D9239c08C0568f6F2F0ee452\" as Address,\n cbBTC: \"0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf\" as Address,\n DAI: \"0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb\" as Address,\n AERO: \"0x940181a94A35A4569E4529A3CDfB74e38FD98631\" as Address,\n} as const;\n\nconst BASE_MOONWELL = {\n COMPTROLLER: \"0xfBb21d0380beE3312B33c4353c8936a0F13EF26C\" as Address,\n mUSDC: \"0xEdc817A28E8B93B03976FBd4a3dDBc9f7D176c22\" as Address,\n mWETH: \"0x628ff693426583D9a7FB391E54366292F509D457\" as Address,\n mCbETH: \"0x3bf93770f2d4a794c3d9EBEfBAeBAE2a8f09A5E5\" as Address,\n mWstETH: \"0x627Fe393Bc6EdDA28e99AE648fD6fF362514304b\" as Address,\n mCbBTC: \"0xF877ACaFA28c19b96727966690b2f44d35aD5976\" as Address,\n mDAI: \"0x73b06D8d18De422E269645eaCe15400DE7462417\" as Address,\n mAERO: \"0x73902f619CEB9B31FD8EFecf435CbDf89E369Ba6\" as Address,\n} as const;\n\nconst BASE_UNISWAP = {\n SWAP_ROUTER: \"0x2626664c2603336E57B271c5C0b26F421741e481\" as Address,\n QUOTER_V2: \"0x3d4e44Eb1374240CE5F1B871ab261CD16335B76a\" as Address,\n} as const;\n\nconst BASE_INFRA = {\n MULTICALL3: \"0xcA11bde05977b3631167028862bE2a173976CA11\" as Address,\n} as const;\n\n// ── Base Sepolia ──\n// Zero addresses = protocol not deployed on testnet. Strategies that need them\n// (e.g. levered-swap) will fail at execution time with a clear allowlist error.\n\nconst BASE_SEPOLIA_TOKENS = {\n USDC: \"0x036CbD53842c5426634e7929541eC2318f3dCF7e\" as Address, // Circle test USDC\n WETH: \"0x4200000000000000000000000000000000000006\" as Address, // Canonical bridged WETH\n cbETH: \"0x0000000000000000000000000000000000000000\" as Address,\n wstETH: \"0x0000000000000000000000000000000000000000\" as Address,\n cbBTC: \"0x0000000000000000000000000000000000000000\" as Address,\n DAI: \"0x0000000000000000000000000000000000000000\" as Address,\n AERO: \"0x0000000000000000000000000000000000000000\" as Address,\n} as const;\n\nconst BASE_SEPOLIA_MOONWELL = {\n COMPTROLLER: \"0x0000000000000000000000000000000000000000\" as Address,\n mUSDC: \"0x0000000000000000000000000000000000000000\" as Address,\n mWETH: \"0x0000000000000000000000000000000000000000\" as Address,\n mCbETH: \"0x0000000000000000000000000000000000000000\" as Address,\n mWstETH: \"0x0000000000000000000000000000000000000000\" as Address,\n mCbBTC: \"0x0000000000000000000000000000000000000000\" as Address,\n mDAI: \"0x0000000000000000000000000000000000000000\" as Address,\n mAERO: \"0x0000000000000000000000000000000000000000\" as Address,\n} as const;\n\nconst BASE_SEPOLIA_UNISWAP = {\n SWAP_ROUTER: \"0x94cC0AaC535CCDB3C01d6787D6413C739ae12bc4\" as Address, // Uniswap V3 SwapRouter02\n QUOTER_V2: \"0xC5290058841028F1614F3A6F0F5816cAd0df5E27\" as Address, // Uniswap V3 QuoterV2\n} as const;\n\nconst BASE_SEPOLIA_INFRA = {\n MULTICALL3: \"0xcA11bde05977b3631167028862bE2a173976CA11\" as Address, // Deterministic, same everywhere\n} as const;\n\n// ── ENS / Durin ──\n\nconst BASE_ENS = {\n L2_REGISTRAR: \"0x0000000000000000000000000000000000000000\" as Address, // TODO: set after mainnet deploy\n L2_REGISTRY: \"0x0000000000000000000000000000000000000000\" as Address, // TODO: set after mainnet deploy\n} as const;\n\nconst BASE_SEPOLIA_ENS = {\n L2_REGISTRAR: \"0x1fCbe9dFC25e3fa3F7C55b26c7992684A4758b47\" as Address,\n L2_REGISTRY: \"0x06eb7b85b59bc3e50fe4837be776cdd26de602cf\" as Address,\n} as const;\n\n// ── ERC-8004 Agent Identity ──\n\nconst BASE_AGENT_REGISTRY = {\n IDENTITY_REGISTRY: \"0x8004A169FB4a3325136EB29fA0ceB6D2e539a432\" as Address,\n REPUTATION_REGISTRY: \"0x8004BAa17C55a88189AE136b182e5fdA19dE9b63\" as Address,\n} as const;\n\nconst BASE_SEPOLIA_AGENT_REGISTRY = {\n IDENTITY_REGISTRY: \"0x8004A818BFB912233c491871b3d84c89A494BD9e\" as Address,\n REPUTATION_REGISTRY: \"0x8004B663056A597Dffe9eCcC1965A193B7388713\" as Address,\n} as const;\n\n// ── Sherwood Protocol (our deployed contracts) ──\n\nconst BASE_SHERWOOD = {\n FACTORY: \"0x0000000000000000000000000000000000000000\" as Address, // TODO: set after mainnet deploy\n STRATEGY_REGISTRY: \"0x0000000000000000000000000000000000000000\" as Address, // TODO: set after mainnet deploy\n GOVERNOR: \"0x0000000000000000000000000000000000000000\" as Address, // TODO: set after mainnet deploy\n} as const;\n\nconst BASE_SEPOLIA_SHERWOOD = {\n FACTORY: \"0x60bf54dDce61ece85BE5e66CBaA17cC312DEa6C8\" as Address,\n STRATEGY_REGISTRY: \"0xf1e6E9bd1a735B54F383b18ad6603Ddd566C71cE\" as Address,\n GOVERNOR: \"0xB478cdb99260F46191C9e5Da405F7E70eEA23dE4\" as Address,\n} as const;\n\n// ── Venice (VVV governance + sVVV staking + DIEM compute) ──\n\nconst BASE_VENICE = {\n VVV: \"0xacfe6019ed1a7dc6f7b508c02d1b04ec88cc21bf\" as Address,\n STAKING: \"0x321b7ff75154472b18edb199033ff4d116f340ff\" as Address, // also the sVVV ERC-20\n DIEM: \"0xF4d97F2da56e8c3098f3a8D538DB630A2606a024\" as Address,\n} as const;\n\nconst BASE_SEPOLIA_VENICE = {\n VVV: \"0x0000000000000000000000000000000000000000\" as Address,\n STAKING: \"0x0000000000000000000000000000000000000000\" as Address,\n DIEM: \"0x0000000000000000000000000000000000000000\" as Address,\n} as const;\n\n// ── EAS (Ethereum Attestation Service) — Base predeploys ──\n\nconst BASE_EAS = {\n EAS: \"0x4200000000000000000000000000000000000021\" as Address,\n SCHEMA_REGISTRY: \"0x4200000000000000000000000000000000000020\" as Address,\n} as const;\n\nconst BASE_SEPOLIA_EAS = {\n EAS: \"0x4200000000000000000000000000000000000021\" as Address,\n SCHEMA_REGISTRY: \"0x4200000000000000000000000000000000000020\" as Address,\n} as const;\n\n// ── EAS Schema UIDs (populated after running scripts/register-eas-schemas.ts) ──\n\nconst BASE_EAS_SCHEMAS = {\n SYNDICATE_JOIN_REQUEST: \"0x0000000000000000000000000000000000000000000000000000000000000000\" as `0x${string}`,\n AGENT_APPROVED: \"0x0000000000000000000000000000000000000000000000000000000000000000\" as `0x${string}`,\n X402_RESEARCH: \"0x0000000000000000000000000000000000000000000000000000000000000000\" as `0x${string}`,\n} as const;\n\nconst BASE_SEPOLIA_EAS_SCHEMAS = {\n SYNDICATE_JOIN_REQUEST: \"0x1e7ce17b16233977ba913b156033e98f52029f4bee273a4abefe6c15ce11d5ef\" as `0x${string}`,\n AGENT_APPROVED: \"0x1013f7b38f433b2a93fc5ac162482813081c64edd67cea9b5a90698531ddb607\" as `0x${string}`,\n X402_RESEARCH: \"0x86c67f0a59acb3093ecbeb6c4d1d4352e4a48143672e92ef9dd2fdfc8a9ca708\" as `0x${string}`,\n} as const;\n\n// ── Exports (functions, resolved at call time) ──\n\nexport function TOKENS() {\n return getNetwork() === \"base\" ? BASE_TOKENS : BASE_SEPOLIA_TOKENS;\n}\n\nexport function MOONWELL() {\n return getNetwork() === \"base\" ? BASE_MOONWELL : BASE_SEPOLIA_MOONWELL;\n}\n\nexport function UNISWAP() {\n return getNetwork() === \"base\" ? BASE_UNISWAP : BASE_SEPOLIA_UNISWAP;\n}\n\nexport function INFRA() {\n return getNetwork() === \"base\" ? BASE_INFRA : BASE_SEPOLIA_INFRA;\n}\n\nexport function ENS() {\n return getNetwork() === \"base\" ? BASE_ENS : BASE_SEPOLIA_ENS;\n}\n\nexport function AGENT_REGISTRY() {\n return getNetwork() === \"base\" ? BASE_AGENT_REGISTRY : BASE_SEPOLIA_AGENT_REGISTRY;\n}\n\nexport function VENICE() {\n return getNetwork() === \"base\" ? BASE_VENICE : BASE_SEPOLIA_VENICE;\n}\n\nexport function SHERWOOD() {\n return getNetwork() === \"base\" ? BASE_SHERWOOD : BASE_SEPOLIA_SHERWOOD;\n}\n\nexport function EAS_CONTRACTS() {\n return getNetwork() === \"base\" ? BASE_EAS : BASE_SEPOLIA_EAS;\n}\n\nexport function EAS_SCHEMAS() {\n return getNetwork() === \"base\" ? BASE_EAS_SCHEMAS : BASE_SEPOLIA_EAS_SCHEMAS;\n}\n","/**\n * Minimal contract ABIs for viem type inference.\n * Extracted from contracts/src/ — keep in sync if contracts change.\n */\n\n// ── SyndicateVault (ERC-4626 + ERC20Votes + governor integration) ──\n\nexport const SYNDICATE_VAULT_ABI = [\n // ERC-4626\n {\n name: \"deposit\",\n type: \"function\",\n stateMutability: \"nonpayable\",\n inputs: [\n { name: \"assets\", type: \"uint256\" },\n { name: \"receiver\", type: \"address\" },\n ],\n outputs: [{ name: \"shares\", type: \"uint256\" }],\n },\n {\n name: \"totalAssets\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [],\n outputs: [{ name: \"\", type: \"uint256\" }],\n },\n {\n name: \"asset\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [],\n outputs: [{ name: \"\", type: \"address\" }],\n },\n // ERC-20\n {\n name: \"balanceOf\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [{ name: \"account\", type: \"address\" }],\n outputs: [{ name: \"\", type: \"uint256\" }],\n },\n // LP\n {\n name: \"ragequit\",\n type: \"function\",\n stateMutability: \"nonpayable\",\n inputs: [{ name: \"receiver\", type: \"address\" }],\n outputs: [{ name: \"assets\", type: \"uint256\" }],\n },\n // Batch execution (owner-only, via delegatecall to shared executor lib)\n {\n name: \"executeBatch\",\n type: \"function\",\n stateMutability: \"nonpayable\",\n inputs: [\n {\n name: \"calls\",\n type: \"tuple[]\",\n components: [\n { name: \"target\", type: \"address\" },\n { name: \"data\", type: \"bytes\" },\n { name: \"value\", type: \"uint256\" },\n ],\n },\n ],\n outputs: [],\n },\n {\n name: \"simulateBatch\",\n type: \"function\",\n stateMutability: \"nonpayable\",\n inputs: [\n {\n name: \"calls\",\n type: \"tuple[]\",\n components: [\n { name: \"target\", type: \"address\" },\n { name: \"data\", type: \"bytes\" },\n { name: \"value\", type: \"uint256\" },\n ],\n },\n ],\n outputs: [\n {\n name: \"results\",\n type: \"tuple[]\",\n components: [\n { name: \"success\", type: \"bool\" },\n { name: \"returnData\", type: \"bytes\" },\n ],\n },\n ],\n },\n // Agent management\n {\n name: \"registerAgent\",\n type: \"function\",\n stateMutability: \"nonpayable\",\n inputs: [\n { name: \"agentId\", type: \"uint256\" },\n { name: \"pkpAddress\", type: \"address\" },\n { name: \"operatorEOA\", type: \"address\" },\n ],\n outputs: [],\n },\n {\n name: \"removeAgent\",\n type: \"function\",\n stateMutability: \"nonpayable\",\n inputs: [{ name: \"pkpAddress\", type: \"address\" }],\n outputs: [],\n },\n // Views\n {\n name: \"getAgentConfig\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [{ name: \"pkpAddress\", type: \"address\" }],\n outputs: [\n {\n name: \"\",\n type: \"tuple\",\n components: [\n { name: \"agentId\", type: \"uint256\" },\n { name: \"pkpAddress\", type: \"address\" },\n { name: \"operatorEOA\", type: \"address\" },\n { name: \"active\", type: \"bool\" },\n ],\n },\n ],\n },\n {\n name: \"getAgentCount\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [],\n outputs: [{ name: \"\", type: \"uint256\" }],\n },\n {\n name: \"isAgent\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [{ name: \"pkpAddress\", type: \"address\" }],\n outputs: [{ name: \"\", type: \"bool\" }],\n },\n {\n name: \"getExecutorImpl\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [],\n outputs: [{ name: \"\", type: \"address\" }],\n },\n {\n name: \"totalDeposited\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [],\n outputs: [{ name: \"\", type: \"uint256\" }],\n },\n {\n name: \"getAgentOperators\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [],\n outputs: [{ name: \"\", type: \"address[]\" }],\n },\n {\n name: \"pause\",\n type: \"function\",\n stateMutability: \"nonpayable\",\n inputs: [],\n outputs: [],\n },\n {\n name: \"unpause\",\n type: \"function\",\n stateMutability: \"nonpayable\",\n inputs: [],\n outputs: [],\n },\n // Depositor whitelist\n {\n name: \"approveDepositor\",\n type: \"function\",\n stateMutability: \"nonpayable\",\n inputs: [{ name: \"depositor\", type: \"address\" }],\n outputs: [],\n },\n {\n name: \"removeDepositor\",\n type: \"function\",\n stateMutability: \"nonpayable\",\n inputs: [{ name: \"depositor\", type: \"address\" }],\n outputs: [],\n },\n {\n name: \"approveDepositors\",\n type: \"function\",\n stateMutability: \"nonpayable\",\n inputs: [{ name: \"depositors\", type: \"address[]\" }],\n outputs: [],\n },\n {\n name: \"isApprovedDepositor\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [{ name: \"depositor\", type: \"address\" }],\n outputs: [{ name: \"\", type: \"bool\" }],\n },\n {\n name: \"getApprovedDepositors\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [],\n outputs: [{ name: \"\", type: \"address[]\" }],\n },\n {\n name: \"setOpenDeposits\",\n type: \"function\",\n stateMutability: \"nonpayable\",\n inputs: [{ name: \"open\", type: \"bool\" }],\n outputs: [],\n },\n {\n name: \"openDeposits\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [],\n outputs: [{ name: \"\", type: \"bool\" }],\n },\n // ERC-4626 views for LP balance\n {\n name: \"convertToAssets\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [{ name: \"shares\", type: \"uint256\" }],\n outputs: [{ name: \"assets\", type: \"uint256\" }],\n },\n {\n name: \"totalSupply\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [],\n outputs: [{ name: \"\", type: \"uint256\" }],\n },\n // ── Events ──\n {\n name: \"AgentRegistered\",\n type: \"event\",\n inputs: [\n { name: \"agentId\", type: \"uint256\", indexed: true },\n { name: \"pkpAddress\", type: \"address\", indexed: true },\n { name: \"operatorEOA\", type: \"address\", indexed: true },\n ],\n },\n {\n name: \"AgentRemoved\",\n type: \"event\",\n inputs: [{ name: \"pkpAddress\", type: \"address\", indexed: true }],\n },\n {\n name: \"Ragequit\",\n type: \"event\",\n inputs: [\n { name: \"lp\", type: \"address\", indexed: true },\n { name: \"shares\", type: \"uint256\", indexed: false },\n { name: \"assets\", type: \"uint256\", indexed: false },\n ],\n },\n {\n name: \"DepositorApproved\",\n type: \"event\",\n inputs: [{ name: \"depositor\", type: \"address\", indexed: true }],\n },\n {\n name: \"DepositorRemoved\",\n type: \"event\",\n inputs: [{ name: \"depositor\", type: \"address\", indexed: true }],\n },\n {\n name: \"RedemptionsLockedEvent\",\n type: \"event\",\n inputs: [],\n },\n {\n name: \"RedemptionsUnlockedEvent\",\n type: \"event\",\n inputs: [],\n },\n // Governor integration\n {\n name: \"governor\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [],\n outputs: [{ name: \"\", type: \"address\" }],\n },\n {\n name: \"redemptionsLocked\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [],\n outputs: [{ name: \"\", type: \"bool\" }],\n },\n {\n name: \"managementFeeBps\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [],\n outputs: [{ name: \"\", type: \"uint256\" }],\n },\n {\n name: \"setGovernor\",\n type: \"function\",\n stateMutability: \"nonpayable\",\n inputs: [{ name: \"governor_\", type: \"address\" }],\n outputs: [],\n },\n] as const;\n\n// ── Uniswap Quoter V2 ──\n\nexport const UNISWAP_QUOTER_V2_ABI = [\n {\n name: \"quoteExactInputSingle\",\n type: \"function\",\n stateMutability: \"nonpayable\",\n inputs: [\n {\n name: \"params\",\n type: \"tuple\",\n components: [\n { name: \"tokenIn\", type: \"address\" },\n { name: \"tokenOut\", type: \"address\" },\n { name: \"amountIn\", type: \"uint256\" },\n { name: \"fee\", type: \"uint24\" },\n { name: \"sqrtPriceLimitX96\", type: \"uint160\" },\n ],\n },\n ],\n outputs: [\n { name: \"amountOut\", type: \"uint256\" },\n { name: \"sqrtPriceX96After\", type: \"uint160\" },\n { name: \"initializedTicksCrossed\", type: \"uint32\" },\n { name: \"gasEstimate\", type: \"uint256\" },\n ],\n },\n {\n name: \"quoteExactInput\",\n type: \"function\",\n stateMutability: \"nonpayable\",\n inputs: [\n { name: \"path\", type: \"bytes\" },\n { name: \"amountIn\", type: \"uint256\" },\n ],\n outputs: [\n { name: \"amountOut\", type: \"uint256\" },\n { name: \"sqrtPriceX96AfterList\", type: \"uint160[]\" },\n { name: \"initializedTicksCrossedList\", type: \"uint32[]\" },\n { name: \"gasEstimate\", type: \"uint256\" },\n ],\n },\n] as const;\n\n// ── Uniswap SwapRouter (multi-hop) ──\n\nexport const SWAP_ROUTER_ABI = [\n {\n name: \"exactInput\",\n type: \"function\",\n stateMutability: \"nonpayable\",\n inputs: [\n {\n name: \"params\",\n type: \"tuple\",\n components: [\n { name: \"path\", type: \"bytes\" },\n { name: \"recipient\", type: \"address\" },\n { name: \"amountIn\", type: \"uint256\" },\n { name: \"amountOutMinimum\", type: \"uint256\" },\n ],\n },\n ],\n outputs: [{ name: \"amountOut\", type: \"uint256\" }],\n },\n] as const;\n\n// ── ERC20 ──\n\nexport const ERC20_ABI = [\n {\n name: \"approve\",\n type: \"function\",\n stateMutability: \"nonpayable\",\n inputs: [\n { name: \"spender\", type: \"address\" },\n { name: \"amount\", type: \"uint256\" },\n ],\n outputs: [{ name: \"\", type: \"bool\" }],\n },\n {\n name: \"balanceOf\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [{ name: \"account\", type: \"address\" }],\n outputs: [{ name: \"\", type: \"uint256\" }],\n },\n {\n name: \"allowance\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [\n { name: \"owner\", type: \"address\" },\n { name: \"spender\", type: \"address\" },\n ],\n outputs: [{ name: \"\", type: \"uint256\" }],\n },\n {\n name: \"decimals\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [],\n outputs: [{ name: \"\", type: \"uint8\" }],\n },\n {\n name: \"symbol\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [],\n outputs: [{ name: \"\", type: \"string\" }],\n },\n {\n name: \"transfer\",\n type: \"function\",\n stateMutability: \"nonpayable\",\n inputs: [\n { name: \"to\", type: \"address\" },\n { name: \"amount\", type: \"uint256\" },\n ],\n outputs: [{ name: \"\", type: \"bool\" }],\n },\n] as const;\n\n// ── SyndicateFactory ──\n\nexport const SYNDICATE_FACTORY_ABI = [\n {\n name: \"createSyndicate\",\n type: \"function\",\n stateMutability: \"nonpayable\",\n inputs: [\n { name: \"creatorAgentId\", type: \"uint256\" },\n {\n name: \"config\",\n type: \"tuple\",\n components: [\n { name: \"metadataURI\", type: \"string\" },\n { name: \"asset\", type: \"address\" },\n { name: \"name\", type: \"string\" },\n { name: \"symbol\", type: \"string\" },\n { name: \"openDeposits\", type: \"bool\" },\n { name: \"subdomain\", type: \"string\" },\n ],\n },\n ],\n outputs: [\n { name: \"syndicateId\", type: \"uint256\" },\n { name: \"vault\", type: \"address\" },\n ],\n },\n {\n name: \"syndicates\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [{ name: \"\", type: \"uint256\" }],\n outputs: [\n { name: \"id\", type: \"uint256\" },\n { name: \"vault\", type: \"address\" },\n { name: \"creator\", type: \"address\" },\n { name: \"metadataURI\", type: \"string\" },\n { name: \"createdAt\", type: \"uint256\" },\n { name: \"active\", type: \"bool\" },\n { name: \"subdomain\", type: \"string\" },\n ],\n },\n {\n name: \"getActiveSyndicates\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [],\n outputs: [\n {\n name: \"\",\n type: \"tuple[]\",\n components: [\n { name: \"id\", type: \"uint256\" },\n { name: \"vault\", type: \"address\" },\n { name: \"creator\", type: \"address\" },\n { name: \"metadataURI\", type: \"string\" },\n { name: \"createdAt\", type: \"uint256\" },\n { name: \"active\", type: \"bool\" },\n { name: \"subdomain\", type: \"string\" },\n ],\n },\n ],\n },\n {\n name: \"syndicateCount\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [],\n outputs: [{ name: \"\", type: \"uint256\" }],\n },\n {\n name: \"vaultToSyndicate\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [{ name: \"\", type: \"address\" }],\n outputs: [{ name: \"\", type: \"uint256\" }],\n },\n {\n name: \"updateMetadata\",\n type: \"function\",\n stateMutability: \"nonpayable\",\n inputs: [\n { name: \"syndicateId\", type: \"uint256\" },\n { name: \"metadataURI\", type: \"string\" },\n ],\n outputs: [],\n },\n {\n name: \"deactivate\",\n type: \"function\",\n stateMutability: \"nonpayable\",\n inputs: [{ name: \"syndicateId\", type: \"uint256\" }],\n outputs: [],\n },\n {\n name: \"executorImpl\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [],\n outputs: [{ name: \"\", type: \"address\" }],\n },\n {\n name: \"vaultImpl\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [],\n outputs: [{ name: \"\", type: \"address\" }],\n },\n {\n name: \"subdomainToSyndicate\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [{ name: \"subdomain\", type: \"string\" }],\n outputs: [{ name: \"\", type: \"uint256\" }],\n },\n {\n name: \"isSubdomainAvailable\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [{ name: \"subdomain\", type: \"string\" }],\n outputs: [{ name: \"\", type: \"bool\" }],\n },\n {\n name: \"SyndicateCreated\",\n type: \"event\",\n inputs: [\n { name: \"id\", type: \"uint256\", indexed: true },\n { name: \"vault\", type: \"address\", indexed: true },\n { name: \"creator\", type: \"address\", indexed: true },\n { name: \"metadataURI\", type: \"string\", indexed: false },\n { name: \"subdomain\", type: \"string\", indexed: false },\n ],\n },\n] as const;\n\n// ── L2 Registry (Durin ENS — text records) ──\n\nexport const L2_REGISTRY_ABI = [\n {\n name: \"setText\",\n type: \"function\",\n stateMutability: \"nonpayable\",\n inputs: [\n { name: \"node\", type: \"bytes32\" },\n { name: \"key\", type: \"string\" },\n { name: \"value\", type: \"string\" },\n ],\n outputs: [],\n },\n {\n name: \"text\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [\n { name: \"node\", type: \"bytes32\" },\n { name: \"key\", type: \"string\" },\n ],\n outputs: [{ name: \"\", type: \"string\" }],\n },\n] as const;\n\n// ── StrategyRegistry ──\n\nexport const STRATEGY_REGISTRY_ABI = [\n {\n name: \"registerStrategy\",\n type: \"function\",\n stateMutability: \"nonpayable\",\n inputs: [\n { name: \"implementation\", type: \"address\" },\n { name: \"strategyTypeId\", type: \"uint256\" },\n { name: \"name\", type: \"string\" },\n { name: \"metadataURI\", type: \"string\" },\n ],\n outputs: [{ name: \"strategyId\", type: \"uint256\" }],\n },\n {\n name: \"getStrategy\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [{ name: \"strategyId\", type: \"uint256\" }],\n outputs: [\n {\n name: \"\",\n type: \"tuple\",\n components: [\n { name: \"implementation\", type: \"address\" },\n { name: \"creator\", type: \"address\" },\n { name: \"strategyTypeId\", type: \"uint256\" },\n { name: \"active\", type: \"bool\" },\n { name: \"name\", type: \"string\" },\n { name: \"metadataURI\", type: \"string\" },\n ],\n },\n ],\n },\n {\n name: \"getStrategiesByType\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [{ name: \"strategyTypeId\", type: \"uint256\" }],\n outputs: [{ name: \"\", type: \"uint256[]\" }],\n },\n {\n name: \"getStrategiesByCreator\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [{ name: \"creator\", type: \"address\" }],\n outputs: [{ name: \"\", type: \"uint256[]\" }],\n },\n {\n name: \"strategyCount\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [],\n outputs: [{ name: \"\", type: \"uint256\" }],\n },\n {\n name: \"isStrategyActive\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [{ name: \"strategyId\", type: \"uint256\" }],\n outputs: [{ name: \"\", type: \"bool\" }],\n },\n {\n name: \"deactivateStrategy\",\n type: \"function\",\n stateMutability: \"nonpayable\",\n inputs: [{ name: \"strategyId\", type: \"uint256\" }],\n outputs: [],\n },\n] as const;\n\n// ── Venice Staking (sVVV = staking contract ERC-20) ──\n\nexport const VENICE_STAKING_ABI = [\n {\n name: \"stake\",\n type: \"function\",\n stateMutability: \"nonpayable\",\n inputs: [\n { name: \"recipient\", type: \"address\" },\n { name: \"amount\", type: \"uint256\" },\n ],\n outputs: [],\n },\n {\n name: \"initiateUnstake\",\n type: \"function\",\n stateMutability: \"nonpayable\",\n inputs: [{ name: \"amount\", type: \"uint256\" }],\n outputs: [],\n },\n {\n name: \"finalizeUnstake\",\n type: \"function\",\n stateMutability: \"nonpayable\",\n inputs: [],\n outputs: [],\n },\n {\n name: \"mintDiem\",\n type: \"function\",\n stateMutability: \"nonpayable\",\n inputs: [\n { name: \"sVVVAmountToLock\", type: \"uint256\" },\n { name: \"minDiemAmountOut\", type: \"uint256\" },\n ],\n outputs: [],\n },\n {\n name: \"balanceOf\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [{ name: \"account\", type: \"address\" }],\n outputs: [{ name: \"\", type: \"uint256\" }],\n },\n {\n name: \"pendingRewards\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [{ name: \"_user\", type: \"address\" }],\n outputs: [{ name: \"\", type: \"uint256\" }],\n },\n {\n name: \"cooldownDuration\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [],\n outputs: [{ name: \"\", type: \"uint256\" }],\n },\n {\n name: \"getDiemAmountOut\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [{ name: \"sVVVAmountToLock\", type: \"uint256\" }],\n outputs: [{ name: \"\", type: \"uint256\" }],\n },\n {\n name: \"claim\",\n type: \"function\",\n stateMutability: \"nonpayable\",\n inputs: [],\n outputs: [],\n },\n] as const;\n\n// ── EAS (Ethereum Attestation Service) ──\n\nexport const EAS_ABI = [\n {\n name: \"attest\",\n type: \"function\",\n stateMutability: \"payable\",\n inputs: [\n {\n name: \"request\",\n type: \"tuple\",\n components: [\n { name: \"schema\", type: \"bytes32\" },\n {\n name: \"data\",\n type: \"tuple\",\n components: [\n { name: \"recipient\", type: \"address\" },\n { name: \"expirationTime\", type: \"uint64\" },\n { name: \"revocable\", type: \"bool\" },\n { name: \"refUID\", type: \"bytes32\" },\n { name: \"data\", type: \"bytes\" },\n { name: \"value\", type: \"uint256\" },\n ],\n },\n ],\n },\n ],\n outputs: [{ name: \"\", type: \"bytes32\" }],\n },\n {\n name: \"revoke\",\n type: \"function\",\n stateMutability: \"payable\",\n inputs: [\n {\n name: \"request\",\n type: \"tuple\",\n components: [\n { name: \"schema\", type: \"bytes32\" },\n {\n name: \"data\",\n type: \"tuple\",\n components: [\n { name: \"uid\", type: \"bytes32\" },\n { name: \"value\", type: \"uint256\" },\n ],\n },\n ],\n },\n ],\n outputs: [],\n },\n {\n name: \"getAttestation\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [{ name: \"uid\", type: \"bytes32\" }],\n outputs: [\n {\n name: \"\",\n type: \"tuple\",\n components: [\n { name: \"uid\", type: \"bytes32\" },\n { name: \"schema\", type: \"bytes32\" },\n { name: \"time\", type: \"uint64\" },\n { name: \"expirationTime\", type: \"uint64\" },\n { name: \"revocationTime\", type: \"uint64\" },\n { name: \"refUID\", type: \"bytes32\" },\n { name: \"recipient\", type: \"address\" },\n { name: \"attester\", type: \"address\" },\n { name: \"revocable\", type: \"bool\" },\n { name: \"data\", type: \"bytes\" },\n ],\n },\n ],\n },\n] as const;\n\n// ── SyndicateGovernor ──\n\nexport const SYNDICATE_GOVERNOR_ABI = [\n // Proposal lifecycle\n {\n name: \"propose\",\n type: \"function\",\n stateMutability: \"nonpayable\",\n inputs: [\n { name: \"vault\", type: \"address\" },\n { name: \"metadataURI\", type: \"string\" },\n { name: \"performanceFeeBps\", type: \"uint256\" },\n { name: \"strategyDuration\", type: \"uint256\" },\n {\n name: \"calls\",\n type: \"tuple[]\",\n components: [\n { name: \"target\", type: \"address\" },\n { name: \"data\", type: \"bytes\" },\n { name: \"value\", type: \"uint256\" },\n ],\n },\n { name: \"splitIndex\", type: \"uint256\" },\n ],\n outputs: [{ name: \"proposalId\", type: \"uint256\" }],\n },\n {\n name: \"vote\",\n type: \"function\",\n stateMutability: \"nonpayable\",\n inputs: [\n { name: \"proposalId\", type: \"uint256\" },\n { name: \"support\", type: \"bool\" },\n ],\n outputs: [],\n },\n {\n name: \"executeProposal\",\n type: \"function\",\n stateMutability: \"nonpayable\",\n inputs: [{ name: \"proposalId\", type: \"uint256\" }],\n outputs: [],\n },\n {\n name: \"settleProposal\",\n type: \"function\",\n stateMutability: \"nonpayable\",\n inputs: [{ name: \"proposalId\", type: \"uint256\" }],\n outputs: [],\n },\n {\n name: \"settleByAgent\",\n type: \"function\",\n stateMutability: \"nonpayable\",\n inputs: [\n { name: \"proposalId\", type: \"uint256\" },\n {\n name: \"calls\",\n type: \"tuple[]\",\n components: [\n { name: \"target\", type: \"address\" },\n { name: \"data\", type: \"bytes\" },\n { name: \"value\", type: \"uint256\" },\n ],\n },\n ],\n outputs: [],\n },\n {\n name: \"emergencySettle\",\n type: \"function\",\n stateMutability: \"nonpayable\",\n inputs: [\n { name: \"proposalId\", type: \"uint256\" },\n {\n name: \"calls\",\n type: \"tuple[]\",\n components: [\n { name: \"target\", type: \"address\" },\n { name: \"data\", type: \"bytes\" },\n { name: \"value\", type: \"uint256\" },\n ],\n },\n ],\n outputs: [],\n },\n {\n name: \"cancelProposal\",\n type: \"function\",\n stateMutability: \"nonpayable\",\n inputs: [{ name: \"proposalId\", type: \"uint256\" }],\n outputs: [],\n },\n {\n name: \"emergencyCancel\",\n type: \"function\",\n stateMutability: \"nonpayable\",\n inputs: [{ name: \"proposalId\", type: \"uint256\" }],\n outputs: [],\n },\n // Views\n {\n name: \"getProposal\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [{ name: \"proposalId\", type: \"uint256\" }],\n outputs: [\n {\n name: \"\",\n type: \"tuple\",\n components: [\n { name: \"id\", type: \"uint256\" },\n { name: \"proposer\", type: \"address\" },\n { name: \"vault\", type: \"address\" },\n { name: \"metadataURI\", type: \"string\" },\n { name: \"performanceFeeBps\", type: \"uint256\" },\n { name: \"splitIndex\", type: \"uint256\" },\n { name: \"strategyDuration\", type: \"uint256\" },\n { name: \"votesFor\", type: \"uint256\" },\n { name: \"votesAgainst\", type: \"uint256\" },\n { name: \"snapshotTimestamp\", type: \"uint256\" },\n { name: \"voteEnd\", type: \"uint256\" },\n { name: \"executeBy\", type: \"uint256\" },\n { name: \"executedAt\", type: \"uint256\" },\n { name: \"state\", type: \"uint8\" },\n ],\n },\n ],\n },\n {\n name: \"getProposalState\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [{ name: \"proposalId\", type: \"uint256\" }],\n outputs: [{ name: \"\", type: \"uint8\" }],\n },\n {\n name: \"getProposalCalls\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [{ name: \"proposalId\", type: \"uint256\" }],\n outputs: [\n {\n name: \"\",\n type: \"tuple[]\",\n components: [\n { name: \"target\", type: \"address\" },\n { name: \"data\", type: \"bytes\" },\n { name: \"value\", type: \"uint256\" },\n ],\n },\n ],\n },\n {\n name: \"getVoteWeight\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [\n { name: \"proposalId\", type: \"uint256\" },\n { name: \"voter\", type: \"address\" },\n ],\n outputs: [{ name: \"\", type: \"uint256\" }],\n },\n {\n name: \"hasVoted\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [\n { name: \"proposalId\", type: \"uint256\" },\n { name: \"voter\", type: \"address\" },\n ],\n outputs: [{ name: \"\", type: \"bool\" }],\n },\n {\n name: \"proposalCount\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [],\n outputs: [{ name: \"\", type: \"uint256\" }],\n },\n {\n name: \"getGovernorParams\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [],\n outputs: [\n {\n name: \"\",\n type: \"tuple\",\n components: [\n { name: \"votingPeriod\", type: \"uint256\" },\n { name: \"executionWindow\", type: \"uint256\" },\n { name: \"quorumBps\", type: \"uint256\" },\n { name: \"maxPerformanceFeeBps\", type: \"uint256\" },\n { name: \"maxStrategyDuration\", type: \"uint256\" },\n { name: \"cooldownPeriod\", type: \"uint256\" },\n ],\n },\n ],\n },\n {\n name: \"getRegisteredVaults\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [],\n outputs: [{ name: \"\", type: \"address[]\" }],\n },\n {\n name: \"getActiveProposal\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [{ name: \"vault\", type: \"address\" }],\n outputs: [{ name: \"\", type: \"uint256\" }],\n },\n {\n name: \"getCooldownEnd\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [{ name: \"vault\", type: \"address\" }],\n outputs: [{ name: \"\", type: \"uint256\" }],\n },\n {\n name: \"getCapitalSnapshot\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [{ name: \"proposalId\", type: \"uint256\" }],\n outputs: [{ name: \"\", type: \"uint256\" }],\n },\n {\n name: \"isRegisteredVault\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [{ name: \"vault\", type: \"address\" }],\n outputs: [{ name: \"\", type: \"bool\" }],\n },\n // Vault management\n {\n name: \"addVault\",\n type: \"function\",\n stateMutability: \"nonpayable\",\n inputs: [{ name: \"vault\", type: \"address\" }],\n outputs: [],\n },\n {\n name: \"removeVault\",\n type: \"function\",\n stateMutability: \"nonpayable\",\n inputs: [{ name: \"vault\", type: \"address\" }],\n outputs: [],\n },\n // ── Events ──\n {\n name: \"ProposalCreated\",\n type: \"event\",\n inputs: [\n { name: \"proposalId\", type: \"uint256\", indexed: true },\n { name: \"proposer\", type: \"address\", indexed: true },\n { name: \"vault\", type: \"address\", indexed: true },\n { name: \"performanceFeeBps\", type: \"uint256\", indexed: false },\n { name: \"strategyDuration\", type: \"uint256\", indexed: false },\n { name: \"splitIndex\", type: \"uint256\", indexed: false },\n { name: \"callCount\", type: \"uint256\", indexed: false },\n { name: \"metadataURI\", type: \"string\", indexed: false },\n ],\n },\n {\n name: \"VoteCast\",\n type: \"event\",\n inputs: [\n { name: \"proposalId\", type: \"uint256\", indexed: true },\n { name: \"voter\", type: \"address\", indexed: true },\n { name: \"support\", type: \"bool\", indexed: false },\n { name: \"weight\", type: \"uint256\", indexed: false },\n ],\n },\n {\n name: \"ProposalExecuted\",\n type: \"event\",\n inputs: [\n { name: \"proposalId\", type: \"uint256\", indexed: true },\n { name: \"vault\", type: \"address\", indexed: true },\n { name: \"capitalSnapshot\", type: \"uint256\", indexed: false },\n ],\n },\n {\n name: \"ProposalSettled\",\n type: \"event\",\n inputs: [\n { name: \"proposalId\", type: \"uint256\", indexed: true },\n { name: \"vault\", type: \"address\", indexed: true },\n { name: \"pnl\", type: \"int256\", indexed: false },\n { name: \"performanceFee\", type: \"uint256\", indexed: false },\n { name: \"duration\", type: \"uint256\", indexed: false },\n ],\n },\n {\n name: \"ProposalCancelled\",\n type: \"event\",\n inputs: [\n { name: \"proposalId\", type: \"uint256\", indexed: true },\n { name: \"cancelledBy\", type: \"address\", indexed: true },\n ],\n },\n // Parameter setters (owner-only)\n {\n name: \"setVotingPeriod\",\n type: \"function\",\n stateMutability: \"nonpayable\",\n inputs: [{ name: \"newVotingPeriod\", type: \"uint256\" }],\n outputs: [],\n },\n {\n name: \"setExecutionWindow\",\n type: \"function\",\n stateMutability: \"nonpayable\",\n inputs: [{ name: \"newExecutionWindow\", type: \"uint256\" }],\n outputs: [],\n },\n {\n name: \"setQuorumBps\",\n type: \"function\",\n stateMutability: \"nonpayable\",\n inputs: [{ name: \"newQuorumBps\", type: \"uint256\" }],\n outputs: [],\n },\n {\n name: \"setMaxPerformanceFeeBps\",\n type: \"function\",\n stateMutability: \"nonpayable\",\n inputs: [{ name: \"newMaxPerformanceFeeBps\", type: \"uint256\" }],\n outputs: [],\n },\n {\n name: \"setMaxStrategyDuration\",\n type: \"function\",\n stateMutability: \"nonpayable\",\n inputs: [{ name: \"newMaxStrategyDuration\", type: \"uint256\" }],\n outputs: [],\n },\n {\n name: \"setCooldownPeriod\",\n type: \"function\",\n stateMutability: \"nonpayable\",\n inputs: [{ name: \"newCooldownPeriod\", type: \"uint256\" }],\n outputs: [],\n },\n] as const;\n\n// ── EAS Schema Registry ──\n\nexport const SCHEMA_REGISTRY_ABI = [\n {\n name: \"register\",\n type: \"function\",\n stateMutability: \"nonpayable\",\n inputs: [\n { name: \"schema\", type: \"string\" },\n { name: \"resolver\", type: \"address\" },\n { name: \"revocable\", type: \"bool\" },\n ],\n outputs: [{ name: \"\", type: \"bytes32\" }],\n },\n {\n name: \"Registered\",\n type: \"event\",\n inputs: [\n { name: \"uid\", type: \"bytes32\", indexed: true },\n { name: \"registerer\", type: \"address\", indexed: true },\n ],\n },\n] as const;\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/eas.ts"],"sourcesContent":["/**\n * EAS (Ethereum Attestation Service) wrapper for syndicate 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, getWalletClient, getAccount } from \"./client.js\";\nimport { getChain, getNetwork } 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\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\");\n\nfunction assertSchemasRegistered() {\n const schemas = EAS_SCHEMAS();\n if (schemas.SYNDICATE_JOIN_REQUEST === ZERO_BYTES32 || schemas.AGENT_APPROVED === ZERO_BYTES32) {\n throw new Error(\n \"EAS schemas not registered. Run: npx tsx scripts/register-eas-schemas.ts --testnet\",\n );\n }\n}\n\n// ── GraphQL ──\n\nfunction getEasGraphqlUrl(): string {\n return getNetwork() === \"base\"\n ? \"https://base.easscan.org/graphql\"\n : \"https://base-sepolia.easscan.org/graphql\";\n}\n\nexport function getEasScanUrl(uid: Hex): string {\n const host = getNetwork() === \"base\" ? \"base.easscan.org\" : \"base-sepolia.easscan.org\";\n return `https://${host}/attestation/view/${uid}`;\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 // 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/**\n * Create a SYNDICATE_JOIN_REQUEST attestation.\n * Attester: the calling agent. Recipient: the syndicate creator.\n */\nexport async function createJoinRequest(\n syndicateId: bigint,\n agentId: bigint,\n vault: Address,\n creatorAddress: Address,\n message: string,\n): Promise<{ uid: Hex; hash: Hex }> {\n assertSchemasRegistered();\n const wallet = getWalletClient();\n const client = getPublicClient();\n\n const data = encodeAbiParameters(JOIN_REQUEST_PARAMS, [\n syndicateId, agentId, vault, message,\n ]);\n\n const hash = await wallet.writeContract({\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 client.waitForTransactionReceipt({ hash });\n const uid = extractAttestationUid(receipt);\n\n return { uid, hash };\n}\n\n/**\n * Create an AGENT_APPROVED attestation.\n * Attester: the syndicate creator. Recipient: the agent's operator EOA.\n */\nexport async function createApproval(\n syndicateId: bigint,\n agentId: bigint,\n vault: Address,\n agentAddress: Address,\n): Promise<{ uid: Hex; hash: Hex }> {\n assertSchemasRegistered();\n const wallet = getWalletClient();\n const client = getPublicClient();\n\n const data = encodeAbiParameters(AGENT_APPROVED_PARAMS, [\n syndicateId, agentId, vault,\n ]);\n\n const hash = await wallet.writeContract({\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 client.waitForTransactionReceipt({ hash });\n const uid = extractAttestationUid(receipt);\n\n return { uid, hash };\n}\n\n/**\n * Revoke an attestation. Only the original attester can revoke.\n */\nexport async function revokeAttestation(\n schemaUid: Hex,\n attestationUid: Hex,\n): Promise<Hex> {\n const wallet = getWalletClient();\n\n return wallet.writeContract({\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/**\n * Create an X402_RESEARCH attestation — records a research query on-chain.\n * Attester: the agent. Recipient: the agent itself (self-attestation for audit trail).\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): Promise<{ uid: Hex; hash: Hex }> {\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 wallet = getWalletClient();\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 wallet.writeContract({\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: 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 client.waitForTransactionReceipt({ hash });\n const uid = extractAttestationUid(receipt);\n\n return { uid, hash };\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 assertSchemasRegistered();\n const schemaUid = EAS_SCHEMAS().AGENT_APPROVED;\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((a) => {\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}\n\nexport async function queryJoinRequests(\n recipient: Address,\n): Promise<JoinRequestAttestation[]> {\n assertSchemasRegistered();\n const schemaUid = EAS_SCHEMAS().SYNDICATE_JOIN_REQUEST;\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((a) => {\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}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/network.ts","../src/lib/config.ts","../src/lib/client.ts"],"sourcesContent":["/**\n * Network state singleton.\n *\n * Called once at CLI startup via the --testnet flag's preAction hook.\n * Every other module reads from here — never hardcodes a chain.\n */\n\nimport { base, baseSepolia } from \"viem/chains\";\n\nexport type Network = \"base\" | \"base-sepolia\";\n\nlet _network: Network = \"base\";\n\nexport function setNetwork(n: Network) {\n _network = n;\n}\n\nexport function getNetwork(): Network {\n return _network;\n}\n\nexport function getChain() {\n return _network === \"base\" ? base : baseSepolia;\n}\n\nexport function getRpcUrl(): string {\n if (_network === \"base-sepolia\") {\n return process.env.BASE_SEPOLIA_RPC_URL || \"https://sepolia.base.org\";\n }\n return process.env.BASE_RPC_URL || \"https://mainnet.base.org\";\n}\n\nexport function getExplorerUrl(txHash: string): string {\n const host = _network === \"base\" ? \"basescan.org\" : \"sepolia.basescan.org\";\n return `https://${host}/tx/${txHash}`;\n}\n\nexport function isTestnet(): boolean {\n return _network === \"base-sepolia\";\n}\n","/**\n * Local config management — ~/.sherwood/config.json\n *\n * Stores group ID cache, per-chain contract addresses, and wallet config.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nconst CONFIG_DIR = path.join(process.env.HOME || \"~\", \".sherwood\");\nconst CONFIG_PATH = path.join(CONFIG_DIR, \"config.json\");\n\n/** Per-chain user-specific addresses (stored by chainId). */\nexport interface ChainContracts {\n vault?: string; // user's default vault address\n}\n\nexport interface SherwoodConfig {\n dbEncryptionKey?: string; // legacy — no longer used, XMTP CLI manages its own DB\n privateKey?: string; // wallet private key (0x-prefixed)\n xmtpInboxId?: string;\n groupCache: Record<string, string>; // subdomain → XMTP group ID\n veniceApiKey?: string; // Venice AI inference API key\n agentId?: number; // ERC-8004 identity token ID\n contracts?: Record<string, ChainContracts>; // chainId → user addresses\n}\n\nexport function loadConfig(): SherwoodConfig {\n if (fs.existsSync(CONFIG_PATH)) {\n return JSON.parse(fs.readFileSync(CONFIG_PATH, \"utf-8\"));\n }\n\n const config: SherwoodConfig = { groupCache: {} };\n fs.mkdirSync(CONFIG_DIR, { recursive: true });\n fs.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2));\n return config;\n}\n\nexport function saveConfig(config: SherwoodConfig): void {\n fs.mkdirSync(CONFIG_DIR, { recursive: true });\n fs.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2));\n}\n\nexport function cacheGroupId(subdomain: string, groupId: string): void {\n const config = loadConfig();\n config.groupCache[subdomain] = groupId;\n saveConfig(config);\n}\n\nexport function getCachedGroupId(subdomain: string): string | undefined {\n const config = loadConfig();\n return config.groupCache[subdomain];\n}\n\nexport function setVeniceApiKey(apiKey: string): void {\n const config = loadConfig();\n config.veniceApiKey = apiKey;\n saveConfig(config);\n}\n\nexport function getVeniceApiKey(): string | undefined {\n return loadConfig().veniceApiKey;\n}\n\nexport function setAgentId(agentId: number): void {\n const config = loadConfig();\n config.agentId = agentId;\n saveConfig(config);\n}\n\nexport function getAgentId(): number | undefined {\n return loadConfig().agentId;\n}\n\nexport function setPrivateKey(key: string): void {\n const config = loadConfig();\n config.privateKey = key.startsWith(\"0x\") ? key : `0x${key}`;\n saveConfig(config);\n}\n\nexport function getPrivateKey(): string | undefined {\n return loadConfig().privateKey;\n}\n\n// ── Per-chain contract addresses ──\n\nexport function getChainContracts(chainId: number): ChainContracts {\n const config = loadConfig();\n return config.contracts?.[String(chainId)] ?? {};\n}\n\nexport function setChainContract(\n chainId: number,\n key: keyof ChainContracts,\n value: string,\n): void {\n const config = loadConfig();\n if (!config.contracts) config.contracts = {};\n const cid = String(chainId);\n if (!config.contracts[cid]) config.contracts[cid] = {};\n config.contracts[cid][key] = value;\n saveConfig(config);\n}\n","/**\n * viem client factory — resolves chain and RPC from the network module.\n * Private key is read from ~/.sherwood/config.json (set via `sherwood config set --private-key`),\n * with PRIVATE_KEY env var as fallback.\n */\n\n// dotenv loaded at entrypoint\nimport { createPublicClient, createWalletClient, http } from \"viem\";\nimport { privateKeyToAccount } from \"viem/accounts\";\nimport { getChain, getRpcUrl } from \"./network.js\";\nimport { loadConfig } from \"./config.js\";\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nlet _publicClient: any = null;\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nlet _walletClient: any = null;\n\n/**\n * Resolve the private key: config → env → error.\n */\nfunction getPrivateKey(): `0x${string}` {\n // 1. Config (~/.sherwood/config.json)\n const config = loadConfig();\n if (config.privateKey) {\n const k = config.privateKey;\n return (k.startsWith(\"0x\") ? k : `0x${k}`) as `0x${string}`;\n }\n\n // 2. Env var fallback\n const env = process.env.PRIVATE_KEY;\n if (env) {\n return (env.startsWith(\"0x\") ? env : `0x${env}`) as `0x${string}`;\n }\n\n throw new Error(\n \"Private key not found. Run 'sherwood config set --private-key <key>' or set PRIVATE_KEY env var.\",\n );\n}\n\nexport function getPublicClient() {\n if (!_publicClient) {\n _publicClient = createPublicClient({\n chain: getChain(),\n transport: http(getRpcUrl()),\n });\n }\n return _publicClient as ReturnType<typeof createPublicClient>;\n}\n\nexport function getWalletClient() {\n if (!_walletClient) {\n const account = privateKeyToAccount(getPrivateKey());\n _walletClient = createWalletClient({\n account,\n chain: getChain(),\n transport: http(getRpcUrl()),\n });\n }\n return _walletClient as ReturnType<typeof createWalletClient>;\n}\n\n/**\n * Reset cached clients. Required for tests that call setNetwork()\n * after a client was already created.\n */\nexport function resetClients() {\n _publicClient = null;\n _walletClient = null;\n}\n\nexport function getAccount() {\n return privateKeyToAccount(getPrivateKey());\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/xmtp.ts"],"sourcesContent":["/**\n * XMTP client and group operations for syndicate chat.\n *\n * Shells out to the @xmtp/cli binary instead of using @xmtp/node-sdk directly.\n * This avoids native binding (GLIBC) issues on Linux.\n *\n * Credentials: the sherwood private key is passed to each subprocess via the\n * XMTP_WALLET_KEY env var. We never write to ~/.xmtp/.env — the XMTP CLI\n * manages its own DB encryption key and env file. This avoids destroying\n * existing XMTP setups when agents already have the CLI configured.\n */\n\nimport { execFileSync, spawn, execSync } from \"node:child_process\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { homedir } from \"node:os\";\nimport {\n loadConfig,\n saveConfig,\n cacheGroupId,\n getCachedGroupId,\n} from \"./config.js\";\nimport { getTextRecord } from \"./ens.js\";\nimport { getNetwork } from \"./network.js\";\nimport type { ChatEnvelope } from \"./types.js\";\nimport { getAccount } from \"./client.js\";\n\n// ── Types ──\n\nexport interface XmtpMessage {\n id: string;\n conversationId: string;\n senderInboxId: string;\n contentType: string;\n content: string;\n sentAt: Date;\n}\n\nexport interface XmtpMember {\n inboxId: string;\n permissionLevel: string;\n}\n\n// ── Binary resolution ──\n\nlet _binaryPath: string | null = null;\n\nfunction getXmtpBinaryPath(): string {\n if (_binaryPath) return _binaryPath;\n\n // Try local node_modules/@xmtp/cli/bin/run.js relative to this file\n const searchPaths = [\n // From dist/ after build\n path.resolve(import.meta.dirname, \"..\", \"node_modules\", \"@xmtp\", \"cli\", \"bin\", \"run.js\"),\n // From src/ during dev\n path.resolve(import.meta.dirname, \"..\", \"..\", \"node_modules\", \"@xmtp\", \"cli\", \"bin\", \"run.js\"),\n // From cwd\n path.resolve(process.cwd(), \"node_modules\", \"@xmtp\", \"cli\", \"bin\", \"run.js\"),\n ];\n\n for (const p of searchPaths) {\n if (fs.existsSync(p)) {\n _binaryPath = p;\n return _binaryPath;\n }\n }\n\n // Fall back to system PATH\n try {\n const which = execSync(\"which xmtp\", { encoding: \"utf8\" }).trim();\n if (which) {\n _binaryPath = which;\n return _binaryPath;\n }\n } catch {\n // Not on PATH\n }\n\n throw new Error(\n \"XMTP CLI not found. Install with: npm install -g @xmtp/cli\",\n );\n}\n\n// ── Environment ──\n\nfunction getXmtpEnv(): string {\n return getNetwork() === \"base\" ? \"production\" : \"dev\";\n}\n\nfunction getXmtpEnvFile(): string {\n return path.join(homedir(), \".xmtp\", \".env\");\n}\n\n/**\n * Ensure ~/.xmtp/.env exists with at least the wallet key and a DB encryption key.\n * If the file already exists, only update the wallet key line — preserve everything\n * else (especially XMTP_DB_ENCRYPTION_KEY). If no file exists, run `xmtp init` to\n * let the CLI generate its own keys, then patch in our wallet key.\n */\nlet _envReady = false;\n\nfunction ensureXmtpEnv(): void {\n if (_envReady) return;\n\n const config = loadConfig();\n if (!config.privateKey) {\n throw new Error(\n 'No private key configured. Run \"sherwood config set --private-key 0x...\"',\n );\n }\n\n const envFile = getXmtpEnvFile();\n const walletKey = config.privateKey.replace(/^0x/, \"\");\n\n if (fs.existsSync(envFile)) {\n const existing = fs.readFileSync(envFile, \"utf8\");\n if (existing.includes(`XMTP_WALLET_KEY=${walletKey}`)) {\n _envReady = true;\n return;\n }\n\n // Update wallet key while preserving all other vars (DB encryption key, etc.)\n const lines = existing.split(\"\\n\").filter((l) => !l.startsWith(\"XMTP_WALLET_KEY=\"));\n lines.push(`XMTP_WALLET_KEY=${walletKey}`);\n fs.writeFileSync(envFile, lines.filter(Boolean).join(\"\\n\") + \"\\n\", { mode: 0o600 });\n } else {\n // No env file — let XMTP CLI generate keys via `init`, then patch wallet key\n const xmtpDir = path.join(homedir(), \".xmtp\");\n fs.mkdirSync(xmtpDir, { recursive: true });\n\n const bin = getXmtpBinaryPath();\n const initArgs = [\"init\", \"--env\", getXmtpEnv()];\n if (bin.endsWith(\".js\")) {\n execFileSync(\"node\", [bin, ...initArgs], {\n encoding: \"utf8\",\n timeout: 30_000,\n env: { ...process.env, XMTP_WALLET_KEY: walletKey },\n });\n } else {\n execFileSync(bin, initArgs, {\n encoding: \"utf8\",\n timeout: 30_000,\n env: { ...process.env, XMTP_WALLET_KEY: walletKey },\n });\n }\n\n // Patch in our wallet key (init may have generated a different one)\n if (fs.existsSync(envFile)) {\n const content = fs.readFileSync(envFile, \"utf8\");\n const lines = content.split(\"\\n\").filter((l) => !l.startsWith(\"XMTP_WALLET_KEY=\"));\n lines.push(`XMTP_WALLET_KEY=${walletKey}`);\n fs.writeFileSync(envFile, lines.filter(Boolean).join(\"\\n\") + \"\\n\", { mode: 0o600 });\n } else {\n // init didn't create the file — write a minimal one\n fs.writeFileSync(envFile, `XMTP_WALLET_KEY=${walletKey}\\n`, { mode: 0o600 });\n }\n }\n\n _envReady = true;\n}\n\n// ── Subprocess runners ──\n\nfunction execXmtp(args: string[]): string {\n ensureXmtpEnv();\n const bin = getXmtpBinaryPath();\n const fullArgs = [...args, \"--env\", getXmtpEnv(), \"--env-file\", getXmtpEnvFile()];\n\n if (bin.endsWith(\".js\")) {\n return execFileSync(\"node\", [bin, ...fullArgs], {\n encoding: \"utf8\",\n timeout: 30_000,\n }).trim();\n }\n\n return execFileSync(bin, fullArgs, {\n encoding: \"utf8\",\n timeout: 30_000,\n }).trim();\n}\n\nfunction execXmtpJson<T>(args: string[]): T {\n const stdout = execXmtp([...args, \"--json\", \"--log-level\", \"off\"]);\n return JSON.parse(stdout) as T;\n}\n\n// ── Conversation sync ──\n\nlet _conversationsSynced = false;\n\n/**\n * Sync conversations from the network into the local XMTP DB.\n * One-shot commands (send, messages, members) spawn a fresh process\n * that may not have the group locally — this ensures it's available.\n *\n * Uses `sync-all` instead of `sync` because `sync` only refreshes\n * already-known conversations. `sync-all` also processes MLS welcome\n * messages, which is required for agents that were added to a group\n * by someone else. Only runs once per process.\n */\nfunction syncConversations(): void {\n if (_conversationsSynced) return;\n execXmtp([\"conversations\", \"sync-all\"]);\n _conversationsSynced = true;\n}\n\n// ── Stale installation cleanup ──\n\n/**\n * Revoke stale XMTP installations for the current wallet.\n *\n * When an agent wipes ~/.xmtp/ and re-initializes, a new MLS installation is\n * created but old ones remain registered on the network. When add-members runs,\n * the MLS welcome may target a stale installation's KeyPackage — the current\n * installation can never sync that group.\n *\n * This function detects and revokes all installations except the current one,\n * ensuring add-members targets the right installation.\n */\nfunction revokeStaleInstallations(inboxId: string, currentInstallationId: string): void {\n try {\n // Get all installations for this inbox from the network\n const inboxStates = execXmtpJson<Array<{\n inboxId: string;\n installations: Array<{ id: string }>;\n }>>([\"inbox-states\", inboxId]);\n\n const state = inboxStates?.[0];\n if (!state?.installations || state.installations.length <= 1) return;\n\n const staleIds = state.installations\n .map((i) => i.id)\n .filter((id) => id !== currentInstallationId);\n\n if (staleIds.length === 0) return;\n\n // Revoke stale installations — only the wallet owner can do this\n execXmtp([\n \"revoke-installations\",\n inboxId,\n \"-i\",\n staleIds.join(\",\"),\n \"--force\",\n ]);\n } catch {\n // Non-fatal — stale installations are a UX issue, not a blocker\n }\n}\n\n// ── Client ──\n\nexport async function getXmtpClient(): Promise<string> {\n // client info returns { properties: { inboxId, installationId, ... }, options: { ... } }\n const result = execXmtpJson<{\n properties: {\n inboxId: string;\n installationId: string;\n };\n }>([\"client\", \"info\"]);\n\n const { inboxId, installationId } = result.properties;\n\n // Cache inbox ID\n const config = loadConfig();\n if (!config.xmtpInboxId && inboxId) {\n config.xmtpInboxId = inboxId;\n saveConfig(config);\n }\n\n // Clean up stale installations so add-members targets the current one\n if (inboxId && installationId) {\n revokeStaleInstallations(inboxId, installationId);\n }\n\n return inboxId;\n}\n\n// ── Group Creation ──\n\nexport async function createSyndicateGroup(\n _client: string,\n subdomain: string,\n isPublic: boolean = false,\n): Promise<string> {\n // CLI requires at least one member address; use creator's own address\n // (creator is auto-added as super admin regardless)\n const creatorAddress = getAccount().address;\n const result = execXmtpJson<{ id?: string; conversationId?: string; groupId?: string }>(\n [\n \"conversations\",\n \"create-group\",\n creatorAddress,\n \"--name\",\n subdomain,\n \"--description\",\n `Sherwood syndicate: ${subdomain}.sherwoodagent.eth`,\n \"--permissions\",\n \"admin-only\",\n ],\n );\n\n const groupId = result.id || result.conversationId || result.groupId;\n if (!groupId) {\n throw new Error(\"Failed to parse group ID from xmtp CLI output\");\n }\n\n // Add spectator if requested — enables dashboard live feed\n const SPECTATOR_ADDRESS = process.env.DASHBOARD_SPECTATOR_ADDRESS || \"0xec00089b73fbd0733cc11ee39f81404cbc9c9786\";\n if (isPublic) {\n await addMember(groupId, SPECTATOR_ADDRESS);\n }\n\n // Cache locally\n cacheGroupId(subdomain, groupId);\n\n return groupId;\n}\n\n// ── Group Lookup ──\n\n/**\n * Check if a conversation exists in the local XMTP DB.\n * Returns true if `conversations get <id>` succeeds.\n */\nfunction conversationExists(groupId: string): boolean {\n try {\n execXmtp([\"conversations\", \"get\", groupId]);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Search synced conversations for a group matching the syndicate name.\n * Falls back to this when the cached/ENS group ID is stale.\n */\nfunction findGroupByName(subdomain: string): string | null {\n try {\n const conversations = execXmtpJson<Array<{ id?: string; name?: string; description?: string }>>(\n [\"conversations\", \"list\", \"--type\", \"group\"],\n );\n if (!Array.isArray(conversations)) return null;\n\n const match = conversations.find(\n (c) => c.name === subdomain || c.description?.includes(`${subdomain}.sherwoodagent.eth`),\n );\n return match?.id || null;\n } catch {\n return null;\n }\n}\n\nexport async function getGroup(\n _client: string,\n subdomain: string,\n): Promise<string> {\n // Sync first so we have the latest conversations locally\n syncConversations();\n\n // Try local cache\n let groupId: string | undefined = getCachedGroupId(subdomain);\n\n // Validate cached ID actually exists in the local DB\n if (groupId && !conversationExists(groupId)) {\n cacheGroupId(subdomain, \"\"); // invalidate stale entry\n groupId = undefined;\n }\n\n // Fall back to on-chain ENS text record\n if (!groupId) {\n const ensId = await getTextRecord(subdomain, \"xmtpGroupId\");\n if (ensId && conversationExists(ensId)) {\n groupId = ensId;\n cacheGroupId(subdomain, groupId);\n }\n }\n\n // Last resort: search synced conversations by name\n if (!groupId) {\n const found = findGroupByName(subdomain);\n if (found) {\n groupId = found;\n cacheGroupId(subdomain, groupId);\n }\n }\n\n if (!groupId) {\n throw new Error(\n `No XMTP group found for syndicate \"${subdomain}\". Run \"sherwood chat ${subdomain} init\" to create one.`,\n );\n }\n\n return groupId;\n}\n\n// ── Member Management ──\n\nexport async function addMember(\n groupId: string,\n address: string,\n): Promise<void> {\n // Verify the target has an active XMTP identity before adding\n const reachable = execXmtpJson<Array<{ identifier: string; reachable: boolean }>>(\n [\"can-message\", address],\n );\n if (!reachable?.[0]?.reachable) {\n throw new Error(\n `${address} is not reachable on XMTP. They need to initialize their client first (run: xmtp client info --env ${getXmtpEnv()}).`,\n );\n }\n\n syncConversations();\n execXmtp([\"conversation\", \"add-members\", groupId, address]);\n\n // Set consent to \"allowed\" on the adder's side so subsequent operations\n // (send, messages) don't skip this conversation due to unknown consent state\n try {\n execXmtp([\"conversation\", \"update-consent\", groupId, \"--state\", \"allowed\"]);\n } catch {\n // Non-fatal — consent state is a filtering concern, not a blocker\n }\n}\n\nexport async function removeMember(\n groupId: string,\n address: string,\n): Promise<void> {\n syncConversations();\n execXmtp([\"conversation\", \"remove-members\", groupId, address]);\n}\n\n// ── Messaging ──\n\nexport async function sendEnvelope(\n groupId: string,\n envelope: ChatEnvelope,\n): Promise<void> {\n const text = JSON.stringify(envelope);\n execXmtp([\"conversation\", \"send-text\", groupId, text]);\n}\n\nexport async function sendMarkdown(\n groupId: string,\n markdown: string,\n): Promise<void> {\n const envelope: ChatEnvelope = {\n type: \"MESSAGE\",\n from: getAccount().address,\n text: markdown,\n data: { format: \"markdown\" },\n timestamp: Math.floor(Date.now() / 1000),\n };\n await sendEnvelope(groupId, envelope);\n}\n\nexport async function sendReaction(\n groupId: string,\n messageId: string,\n emoji: string,\n): Promise<void> {\n const envelope: ChatEnvelope = {\n type: \"REACTION\",\n from: getAccount().address,\n data: { reference: messageId, emoji },\n timestamp: Math.floor(Date.now() / 1000),\n };\n await sendEnvelope(groupId, envelope);\n}\n\n// ── Streaming ──\n\nexport async function streamMessages(\n groupId: string,\n onMessage: (msg: XmtpMessage) => void,\n): Promise<() => void> {\n ensureXmtpEnv();\n const bin = getXmtpBinaryPath();\n\n const args = [\n \"conversations\",\n \"stream-all-messages\",\n \"--json\",\n \"--log-level\",\n \"off\",\n \"--env\",\n getXmtpEnv(),\n \"--env-file\",\n getXmtpEnvFile(),\n ];\n\n const proc = bin.endsWith(\".js\")\n ? spawn(\"node\", [bin, ...args])\n : spawn(bin, args);\n\n let buffer = \"\";\n proc.stdout.on(\"data\", (chunk: Buffer) => {\n buffer += chunk.toString();\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() || \"\";\n for (const line of lines) {\n if (!line.trim()) continue;\n try {\n const msg = JSON.parse(line);\n // Filter to our group\n if (msg.conversationId === groupId) {\n onMessage({\n id: msg.id || \"\",\n conversationId: msg.conversationId || \"\",\n senderInboxId: msg.senderInboxId || \"\",\n contentType: msg.contentType?.typeId || \"text\",\n content: typeof msg.content === \"string\" ? msg.content : JSON.stringify(msg.content),\n sentAt: new Date(msg.sentAt || Date.now()),\n });\n }\n } catch {\n // Skip unparseable lines\n }\n }\n });\n\n // Return cleanup function\n return () => {\n proc.kill(\"SIGTERM\");\n };\n}\n\n// ── Message History ──\n\nexport async function getRecentMessages(\n groupId: string,\n limit: number = 20,\n): Promise<XmtpMessage[]> {\n const raw = execXmtpJson<Array<Record<string, unknown>>>([\n \"conversation\",\n \"messages\",\n groupId,\n ]);\n\n const messages: XmtpMessage[] = (Array.isArray(raw) ? raw : []).map((m) => ({\n id: String(m.id || \"\"),\n conversationId: String(m.conversationId || \"\"),\n senderInboxId: String(m.senderInboxId || \"\"),\n contentType: String(\n (m.contentType as Record<string, unknown>)?.typeId || \"text\",\n ),\n content:\n typeof m.content === \"string\" ? m.content : JSON.stringify(m.content),\n sentAt: new Date((m.sentAt as string) || Date.now()),\n }));\n\n return messages.slice(-limit);\n}\n\n// ── Members ──\n\nexport async function getMembers(\n groupId: string,\n): Promise<XmtpMember[]> {\n const raw = execXmtpJson<Array<Record<string, unknown>>>([\n \"conversation\",\n \"members\",\n groupId,\n ]);\n\n // permissionLevel from CLI: 0 = member, 1 = admin, 2 = super_admin\n const levelMap: Record<number, string> = { 0: \"member\", 1: \"admin\", 2: \"super_admin\" };\n return (Array.isArray(raw) ? raw : []).map((m) => ({\n inboxId: String(m.inboxId || \"\"),\n permissionLevel: levelMap[Number(m.permissionLevel)] || \"member\",\n }));\n}\n"],"mappings":"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","names":[]}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|