@sherwoodagent/cli 0.83.1 → 0.85.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/{abis-ZQ6I3S6L.js → abis-WVW2EBI3.js} +2 -2
- package/dist/{agent-C5XZSK7Z.js → agent-TBLC3WNJ.js} +7 -7
- package/dist/{chat-FGTYCJ4B.js → chat-DNWTI4CZ.js} +8 -8
- package/dist/{chunk-G34TNE53.js → chunk-45FELUWY.js} +2 -2
- package/dist/{chunk-4WAEM2TC.js → chunk-53W6CYYV.js} +5 -5
- package/dist/{chunk-NKRMMFQG.js → chunk-65G5BFYR.js} +56 -5
- package/dist/chunk-65G5BFYR.js.map +1 -0
- package/dist/{chunk-4GO7I33U.js → chunk-6N7EVSAZ.js} +36 -5
- package/dist/chunk-6N7EVSAZ.js.map +1 -0
- package/dist/{chunk-I7TMY7AS.js → chunk-AM6MI2JF.js} +88 -38
- package/dist/chunk-AM6MI2JF.js.map +1 -0
- package/dist/{chunk-AJ46XIGY.js → chunk-ARSQ5UQA.js} +41 -5
- package/dist/chunk-ARSQ5UQA.js.map +1 -0
- package/dist/{chunk-XSP64L7L.js → chunk-F3MDCUGO.js} +4 -368
- package/dist/chunk-F3MDCUGO.js.map +1 -0
- package/dist/{chunk-MBWFTXF5.js → chunk-I2BBOJNC.js} +5 -5
- package/dist/chunk-ILHOW6IA.js +2971 -0
- package/dist/chunk-ILHOW6IA.js.map +1 -0
- package/dist/{chunk-CCNOXDZ7.js → chunk-KVB5P2OE.js} +2 -2
- package/dist/{chunk-M34JVPJO.js → chunk-M4GX5PL2.js} +41 -6
- package/dist/chunk-M4GX5PL2.js.map +1 -0
- package/dist/{chunk-ZW2VKCFZ.js → chunk-PVTZMRC6.js} +34 -2
- package/dist/chunk-PVTZMRC6.js.map +1 -0
- package/dist/{chunk-AQPTBVEA.js → chunk-QRMZRAMG.js} +2 -2
- package/dist/{chunk-AOL2DJTK.js → chunk-TWT56FTL.js} +6 -6
- package/dist/{client-OPZ2ORWW.js → client-3SE632Q2.js} +3 -3
- package/dist/{eas-32PEJETG.js → eas-D3BVHBJH.js} +14 -6
- package/dist/{governor-GSCXEZWI.js → governor-35IXAEDJ.js} +12 -6
- package/dist/identity-RMEPBFOL.js +15 -0
- package/dist/index.js +1326 -3389
- package/dist/index.js.map +1 -1
- package/dist/{network-HCFCNZUI.js → network-FEHRFDPJ.js} +6 -2
- package/dist/{price-OUL7WIXQ.js → price-I5T77X7Y.js} +6 -6
- package/dist/{providers-4HQHB7V5.js → providers-BMOHHVUN.js} +4 -4
- package/dist/{research-2RWAMWWH.js → research-GZNVG3SP.js} +15 -12
- package/dist/research-GZNVG3SP.js.map +1 -0
- package/dist/{session-SIOJZO6P.js → session-M5QB25PK.js} +46 -15
- package/dist/session-M5QB25PK.js.map +1 -0
- package/dist/{trade-ZEIY3MCL.js → trade-TCQ5NUNA.js} +21 -21
- package/dist/trade-TCQ5NUNA.js.map +1 -0
- package/dist/{vault-VDADZFSV.js → vault-K2R4VHVI.js} +8 -8
- package/dist/{xmtp-2U7CSBXM.js → xmtp-R25Q5GWY.js} +6 -6
- package/package.json +2 -2
- package/dist/addresses-MS6BB7AB.js +0 -45
- package/dist/chunk-4GO7I33U.js.map +0 -1
- package/dist/chunk-AJ46XIGY.js.map +0 -1
- package/dist/chunk-I7TMY7AS.js.map +0 -1
- package/dist/chunk-M34JVPJO.js.map +0 -1
- package/dist/chunk-NKRMMFQG.js.map +0 -1
- package/dist/chunk-XSP64L7L.js.map +0 -1
- package/dist/chunk-ZW2VKCFZ.js.map +0 -1
- package/dist/research-2RWAMWWH.js.map +0 -1
- package/dist/session-SIOJZO6P.js.map +0 -1
- package/dist/trade-ZEIY3MCL.js.map +0 -1
- /package/dist/{abis-ZQ6I3S6L.js.map → abis-WVW2EBI3.js.map} +0 -0
- /package/dist/{agent-C5XZSK7Z.js.map → agent-TBLC3WNJ.js.map} +0 -0
- /package/dist/{chat-FGTYCJ4B.js.map → chat-DNWTI4CZ.js.map} +0 -0
- /package/dist/{chunk-G34TNE53.js.map → chunk-45FELUWY.js.map} +0 -0
- /package/dist/{chunk-4WAEM2TC.js.map → chunk-53W6CYYV.js.map} +0 -0
- /package/dist/{chunk-MBWFTXF5.js.map → chunk-I2BBOJNC.js.map} +0 -0
- /package/dist/{chunk-CCNOXDZ7.js.map → chunk-KVB5P2OE.js.map} +0 -0
- /package/dist/{chunk-AQPTBVEA.js.map → chunk-QRMZRAMG.js.map} +0 -0
- /package/dist/{chunk-AOL2DJTK.js.map → chunk-TWT56FTL.js.map} +0 -0
- /package/dist/{addresses-MS6BB7AB.js.map → client-3SE632Q2.js.map} +0 -0
- /package/dist/{client-OPZ2ORWW.js.map → eas-D3BVHBJH.js.map} +0 -0
- /package/dist/{eas-32PEJETG.js.map → governor-35IXAEDJ.js.map} +0 -0
- /package/dist/{governor-GSCXEZWI.js.map → identity-RMEPBFOL.js.map} +0 -0
- /package/dist/{network-HCFCNZUI.js.map → network-FEHRFDPJ.js.map} +0 -0
- /package/dist/{price-OUL7WIXQ.js.map → price-I5T77X7Y.js.map} +0 -0
- /package/dist/{providers-4HQHB7V5.js.map → providers-BMOHHVUN.js.map} +0 -0
- /package/dist/{vault-VDADZFSV.js.map → vault-K2R4VHVI.js.map} +0 -0
- /package/dist/{xmtp-2U7CSBXM.js.map → xmtp-R25Q5GWY.js.map} +0 -0
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
EAS_CONTRACTS,
|
|
3
3
|
EAS_SCHEMAS
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-AM6MI2JF.js";
|
|
5
5
|
import {
|
|
6
6
|
getAccount,
|
|
7
7
|
getPublicClient,
|
|
8
8
|
waitForReceipt,
|
|
9
9
|
writeContractWithRetry
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-QRMZRAMG.js";
|
|
11
11
|
import {
|
|
12
12
|
CHAIN_REGISTRY,
|
|
13
13
|
getChain,
|
|
@@ -15,10 +15,10 @@ import {
|
|
|
15
15
|
getNetwork,
|
|
16
16
|
isTestnet,
|
|
17
17
|
withNetwork
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-PVTZMRC6.js";
|
|
19
19
|
import {
|
|
20
20
|
EAS_ABI
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-F3MDCUGO.js";
|
|
22
22
|
|
|
23
23
|
// src/lib/eas.ts
|
|
24
24
|
import { encodeAbiParameters, parseAbiParameters, decodeAbiParameters } from "viem";
|
|
@@ -40,7 +40,31 @@ function assertSchemasRegistered() {
|
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
function getEasNetwork() {
|
|
43
|
-
return
|
|
43
|
+
return EAS_NETWORK;
|
|
44
|
+
}
|
|
45
|
+
var COORDINATION_NETWORK = "robinhood-mainnet";
|
|
46
|
+
var EAS_NETWORK = COORDINATION_NETWORK;
|
|
47
|
+
function attestationWritesEnabled() {
|
|
48
|
+
return getNetwork() !== "robinhood-fork";
|
|
49
|
+
}
|
|
50
|
+
function skipWriteOnFork(kind) {
|
|
51
|
+
if (attestationWritesEnabled()) return false;
|
|
52
|
+
console.log(
|
|
53
|
+
` ${kind} attestation skipped: writes are disabled on robinhood-fork (ephemeral chain; attestations live on Robinhood mainnet).`
|
|
54
|
+
);
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
async function assertCanPayForAttestation() {
|
|
58
|
+
await withNetwork(EAS_NETWORK, async () => {
|
|
59
|
+
const account = getAccount();
|
|
60
|
+
const balance = await getPublicClient().getBalance({ address: account.address });
|
|
61
|
+
if (balance === 0n) {
|
|
62
|
+
throw new Error(
|
|
63
|
+
`No ETH on Robinhood mainnet (chain 4663) for ${account.address}.
|
|
64
|
+
Attestations are recorded on Robinhood mainnet regardless of which chain your fund is on, so this wallet needs a small mainnet balance (a single attestation costs well under 0.0001 ETH).`
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
});
|
|
44
68
|
}
|
|
45
69
|
function getEasGraphqlUrl() {
|
|
46
70
|
const url = getChainConfig().easGraphqlUrl;
|
|
@@ -93,6 +117,7 @@ function stripReferrerPrefix(message) {
|
|
|
93
117
|
return message.replace(REF_PREFIX_RE, "").replace(CHAIN_PREFIX_RE, "");
|
|
94
118
|
}
|
|
95
119
|
async function createJoinRequest(syndicateId, agentId, vault, creatorAddress, message, referrerAgentId) {
|
|
120
|
+
if (skipWriteOnFork("join request")) return null;
|
|
96
121
|
const sourceNetwork = getNetwork();
|
|
97
122
|
const easNetwork = getEasNetwork();
|
|
98
123
|
const messageWithRef = formatMessageWithRef(message, referrerAgentId);
|
|
@@ -130,6 +155,7 @@ async function createJoinRequest(syndicateId, agentId, vault, creatorAddress, me
|
|
|
130
155
|
});
|
|
131
156
|
}
|
|
132
157
|
async function createApproval(syndicateId, agentId, vault, agentAddress) {
|
|
158
|
+
if (skipWriteOnFork("approval")) return null;
|
|
133
159
|
return withNetwork(getEasNetwork(), async () => {
|
|
134
160
|
assertSchemasRegistered();
|
|
135
161
|
const data = encodeAbiParameters(AGENT_APPROVED_PARAMS, [
|
|
@@ -179,12 +205,14 @@ async function revokeAttestation(schemaUid, attestationUid) {
|
|
|
179
205
|
});
|
|
180
206
|
}
|
|
181
207
|
async function revokeJoinRequest(attestationUid) {
|
|
208
|
+
if (skipWriteOnFork("revoke")) return null;
|
|
182
209
|
return withNetwork(
|
|
183
210
|
getEasNetwork(),
|
|
184
211
|
() => revokeAttestation(EAS_SCHEMAS().SYNDICATE_JOIN_REQUEST, attestationUid)
|
|
185
212
|
);
|
|
186
213
|
}
|
|
187
214
|
async function createResearchAttestation(provider, queryType, prompt, costUsdc, resultUri, recipient) {
|
|
215
|
+
if (skipWriteOnFork("research")) return null;
|
|
188
216
|
const schemas = EAS_SCHEMAS();
|
|
189
217
|
if (schemas.X402_RESEARCH === ZERO_BYTES32) {
|
|
190
218
|
throw new Error(
|
|
@@ -224,6 +252,7 @@ async function createResearchAttestation(provider, queryType, prompt, costUsdc,
|
|
|
224
252
|
return { uid, hash };
|
|
225
253
|
}
|
|
226
254
|
async function createVeniceProvisionAttestation(agent) {
|
|
255
|
+
if (skipWriteOnFork("venice provision")) return null;
|
|
227
256
|
const schemas = EAS_SCHEMAS();
|
|
228
257
|
if (schemas.VENICE_PROVISION === ZERO_BYTES32) return skipAttestation("VENICE_PROVISION");
|
|
229
258
|
const client = getPublicClient();
|
|
@@ -253,6 +282,7 @@ async function createVeniceProvisionAttestation(agent) {
|
|
|
253
282
|
return { uid, hash };
|
|
254
283
|
}
|
|
255
284
|
async function createVeniceInferenceAttestation(model, promptTokens, completionTokens, promptHash, recipient) {
|
|
285
|
+
if (skipWriteOnFork("venice inference")) return null;
|
|
256
286
|
const schemas = EAS_SCHEMAS();
|
|
257
287
|
if (schemas.VENICE_INFERENCE === ZERO_BYTES32) return skipAttestation("VENICE_INFERENCE");
|
|
258
288
|
const client = getPublicClient();
|
|
@@ -287,6 +317,7 @@ async function createVeniceInferenceAttestation(model, promptTokens, completionT
|
|
|
287
317
|
return { uid, hash };
|
|
288
318
|
}
|
|
289
319
|
async function createTradeAttestation(tokenIn, tokenOut, amountIn, amountOut, txHash, routing, recipient) {
|
|
320
|
+
if (skipWriteOnFork("trade")) return null;
|
|
290
321
|
const schemas = EAS_SCHEMAS();
|
|
291
322
|
if (schemas.TRADE_EXECUTED === ZERO_BYTES32) return skipAttestation("TRADE_EXECUTED");
|
|
292
323
|
const client = getPublicClient();
|
|
@@ -435,6 +466,10 @@ async function queryJoinRequestsImpl(recipient) {
|
|
|
435
466
|
|
|
436
467
|
export {
|
|
437
468
|
getEasNetwork,
|
|
469
|
+
COORDINATION_NETWORK,
|
|
470
|
+
EAS_NETWORK,
|
|
471
|
+
attestationWritesEnabled,
|
|
472
|
+
assertCanPayForAttestation,
|
|
438
473
|
getEasScanUrl,
|
|
439
474
|
getEasExplorerUrl,
|
|
440
475
|
formatMessageWithRef,
|
|
@@ -453,4 +488,4 @@ export {
|
|
|
453
488
|
queryApprovals,
|
|
454
489
|
queryJoinRequests
|
|
455
490
|
};
|
|
456
|
-
//# sourceMappingURL=chunk-
|
|
491
|
+
//# sourceMappingURL=chunk-M4GX5PL2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/eas.ts"],"sourcesContent":["/**\n * EAS (Ethereum Attestation Service) wrapper for fund join requests and approvals.\n *\n * Uses viem for on-chain writes and the EAS GraphQL API for queries.\n * No ethers dependency — attestation data is encoded with viem's encodeAbiParameters.\n */\n\nimport type { Address, Hex } from \"viem\";\nimport { encodeAbiParameters, parseAbiParameters, decodeAbiParameters } from \"viem\";\nimport { getPublicClient, getAccount, writeContractWithRetry, waitForReceipt } from \"./client.js\";\nimport { getChain, getNetwork, getChainConfig, withNetwork, isTestnet, CHAIN_REGISTRY, type Network } from \"./network.js\";\nimport { EAS_CONTRACTS, EAS_SCHEMAS } from \"./addresses.js\";\nimport { EAS_ABI } from \"./abis.js\";\n\n// ── Schema definitions ──\n\nconst ZERO_BYTES32 = \"0x0000000000000000000000000000000000000000000000000000000000000000\" as Hex;\n\n// keccak256(\"Attested(address,address,bytes32,bytes32)\")\nconst ATTESTED_TOPIC = \"0x8bf46bf4cfd674fa735a3d63ec1c9ad4153f033c290341f3a588b75685141b35\" as Hex;\n\nconst JOIN_REQUEST_PARAMS = parseAbiParameters(\"uint256, uint256, address, string\");\nconst AGENT_APPROVED_PARAMS = parseAbiParameters(\"uint256, uint256, address\");\nconst X402_RESEARCH_PARAMS = parseAbiParameters(\"string, string, string, string, string\");\nconst VENICE_PROVISION_PARAMS = parseAbiParameters(\"address, string\");\nconst VENICE_INFERENCE_PARAMS = parseAbiParameters(\"string, uint256, uint256, string\");\nconst TRADE_EXECUTED_PARAMS = parseAbiParameters(\"address, address, uint256, string, string, string\");\n\nfunction assertSchemasRegistered() {\n const schemas = EAS_SCHEMAS();\n if (schemas.SYNDICATE_JOIN_REQUEST === ZERO_BYTES32 || schemas.AGENT_APPROVED === ZERO_BYTES32) {\n const flag = isTestnet() ? \" --testnet\" : \"\";\n throw new Error(\n `EAS schemas not registered on ${getNetwork()}. Run: cd cli && npx tsx scripts/register-eas-schemas.ts${flag}`,\n );\n }\n}\n\n/**\n * The chain where fund-coordination attestations live. EAS is not deployed\n * on EITHER Robinhood chain (both registry entries carry `easGraphqlUrl: null`\n * and ZERO contracts), so the default flip to robinhood-fork changes nothing\n * here — this returns the active network — downstream `getEasGraphqlUrl` / `EAS_CONTRACTS()` then fail\n * with a clear \"EAS not available\" error. When an EAS-bearing chain is added\n * back, route coordination attestations to it here.\n */\nexport function getEasNetwork(): Network {\n return EAS_NETWORK;\n}\n\n/**\n * The coordination chain: attestations AND ERC-8004 identity live on Robinhood\n * mainnet regardless of which chain a fund runs on — a join request for a\n * 46630 fund is recorded on 4663, and its agent's identity NFT is minted there.\n */\nexport const COORDINATION_NETWORK: Network = \"robinhood-mainnet\";\nexport const EAS_NETWORK: Network = COORDINATION_NETWORK;\n\n/**\n * Attestation WRITES are a no-op on the Tenderly fork.\n *\n * The fork is ephemeral and is the default network, so routing its writes to\n * mainnet would burn real ETH recording vnet activity into a permanent public\n * record. Reads are unaffected — a fork session still displays 4663\n * attestations. See spec §10.3.\n */\nexport function attestationWritesEnabled(): boolean {\n return getNetwork() !== \"robinhood-fork\";\n}\n\n/** Thrown-free guard used by every write path; returns true when it skipped. */\nfunction skipWriteOnFork(kind: string): boolean {\n if (attestationWritesEnabled()) return false;\n console.log(\n ` ${kind} attestation skipped: writes are disabled on robinhood-fork ` +\n `(ephemeral chain; attestations live on Robinhood mainnet).`,\n );\n return true;\n}\n\n/**\n * Fails before an attestation write when the signer cannot pay for it on the\n * EAS chain. Attestations cost real mainnet ETH even when the fund is on a\n * testnet, which is surprising enough that a bare out-of-gas revert would be\n * the worst possible way to discover it.\n */\nexport async function assertCanPayForAttestation(): Promise<void> {\n await withNetwork(EAS_NETWORK, async () => {\n const account = getAccount();\n const balance = await getPublicClient().getBalance({ address: account.address });\n if (balance === 0n) {\n throw new Error(\n `No ETH on Robinhood mainnet (chain 4663) for ${account.address}.\\n` +\n `Attestations are recorded on Robinhood mainnet regardless of which ` +\n `chain your fund is on, so this wallet needs a small mainnet balance ` +\n `(a single attestation costs well under 0.0001 ETH).`,\n );\n }\n });\n}\n\n// ── GraphQL ──\n\nfunction getEasGraphqlUrl(): string {\n const url = getChainConfig().easGraphqlUrl;\n if (!url) {\n throw new Error(\n `EAS is not available on ${getNetwork()}. Attestation operations require a chain with EAS (e.g. base, base-sepolia).`,\n );\n }\n return url;\n}\n\nexport function getEasScanUrl(uid: Hex): string {\n // Always use the EAS chain's scan host — attestations live on Base, even\n // for HyperEVM funds. Read the registry directly rather than mutating\n // the singleton, since this is a pure URL build.\n const host = CHAIN_REGISTRY[getEasNetwork()].easScanHost;\n if (!host) {\n throw new Error(`EAS scan host is not configured on ${getEasNetwork()}.`);\n }\n return `https://${host}/attestation/view/${uid}`;\n}\n\n/**\n * The block-explorer URL for a tx that ran on the EAS chain. Use this for\n * attestation create/revoke txs so the link points to base(-sepolia) scan\n * even when the active --chain is HyperEVM / Robinhood.\n */\nexport function getEasExplorerUrl(txHash: string): string {\n const host = CHAIN_REGISTRY[getEasNetwork()].explorerHost;\n return `https://${host}/tx/${txHash}`;\n}\n\n// ── Attestation Creation ──\n\n/**\n * Extract the attestation UID from a transaction receipt.\n * The EAS contract emits: event Attested(address indexed recipient, address indexed attester, bytes32 uid, bytes32 indexed schemaUID)\n * uid is a non-indexed parameter in the event data.\n */\nfunction extractAttestationUid(receipt: { logs: readonly { topics: readonly Hex[]; data: Hex }[] }): Hex {\n for (const log of receipt.logs) {\n // Match the Attested event signature to avoid false positives from other events\n if (log.topics[0] !== ATTESTED_TOPIC) continue;\n // Attested event has 4 topics (sig + 3 indexed) and data contains the uid (bytes32)\n if (log.topics.length === 4 && log.data.length >= 66) {\n return (\"0x\" + log.data.slice(2, 66)) as Hex;\n }\n }\n throw new Error(\"Could not extract attestation UID from transaction receipt\");\n}\n\n// ── Message Prefix Helpers ──\n//\n// Join-request messages can carry CLI metadata as bracketed prefixes. Order\n// is `[chain:<network>] [ref:<id>] body` — chain outer because the chain\n// disambiguates the fund, ref inner because it's optional and per-user.\n// Both prefixes are stripped before display.\n\nconst CHAIN_PREFIX_RE = /^\\[chain:([a-z0-9-]+)\\]\\s*/;\n// Tolerate an optional leading [chain:...] prefix so parseReferrer keeps\n// working when both metadata fields are encoded.\nconst REF_PREFIX_RE = /^(?:\\[chain:[a-z0-9-]+\\]\\s*)?\\[ref:(\\d+)\\]\\s*/;\n\n/**\n * Format a message with an optional referrer prefix.\n * e.g. formatMessageWithRef(\"Hello\", 42) → \"[ref:42] Hello\"\n */\nexport function formatMessageWithRef(message: string, referrerAgentId?: number): string {\n if (referrerAgentId == null) return message;\n return `[ref:${referrerAgentId}] ${message}`;\n}\n\n/**\n * Parse a referrer agentId from a message, if present.\n * e.g. parseReferrer(\"[ref:42] Hello\") → 42\n * parseReferrer(\"[chain:hyperevm] [ref:42] Hello\") → 42\n */\nexport function parseReferrer(message: string): number | null {\n const match = message.match(REF_PREFIX_RE);\n return match ? parseInt(match[1], 10) : null;\n}\n\n/**\n * Format a message with a `[chain:<network>]` prefix when the fund\n * lives on a chain other than the EAS chain (Base / Base-Sepolia). Skipped\n * when source matches the EAS chain to avoid noise on the common case.\n */\nexport function formatMessageWithChain(\n message: string,\n sourceNetwork: Network,\n easNetwork: Network,\n): string {\n if (sourceNetwork === easNetwork) return message;\n return `[chain:${sourceNetwork}] ${message}`;\n}\n\n/**\n * Parse the source-chain prefix from a message, if present.\n * Returns null when no `[chain:<network>]` prefix is found, which means the\n * attestation was created from the EAS chain itself (e.g. base attestation\n * for a base fund).\n */\nexport function parseChain(message: string): string | null {\n const match = message.match(CHAIN_PREFIX_RE);\n return match ? match[1] : null;\n}\n\n/**\n * Strip both `[chain:...]` and `[ref:...]` prefixes from a message,\n * returning the clean human-facing body. Name kept for backward compat.\n */\nexport function stripReferrerPrefix(message: string): string {\n // REF_PREFIX_RE already swallows an optional leading chain prefix when ref\n // is present; the second replace handles a chain prefix without ref.\n return message.replace(REF_PREFIX_RE, \"\").replace(CHAIN_PREFIX_RE, \"\");\n}\n\n/**\n * Create a SYNDICATE_JOIN_REQUEST attestation.\n * Attester: the calling agent. Recipient: the fund creator.\n * If referrerAgentId is provided, it's embedded in the message as a [ref:N] prefix.\n */\nexport async function createJoinRequest(\n syndicateId: bigint,\n agentId: bigint,\n vault: Address,\n creatorAddress: Address,\n message: string,\n referrerAgentId?: number,\n): Promise<{ uid: Hex; hash: Hex } | null> {\n if (skipWriteOnFork(\"join request\")) return null;\n // Capture the fund's source chain BEFORE switching to the EAS chain\n // so we can encode it in the message prefix.\n const sourceNetwork = getNetwork();\n const easNetwork = getEasNetwork();\n const messageWithRef = formatMessageWithRef(message, referrerAgentId);\n const encodedMessage = formatMessageWithChain(messageWithRef, sourceNetwork, easNetwork);\n\n return withNetwork(easNetwork, async () => {\n assertSchemasRegistered();\n\n const data = encodeAbiParameters(JOIN_REQUEST_PARAMS, [\n syndicateId, agentId, vault, encodedMessage,\n ]);\n\n const hash = await writeContractWithRetry({\n account: getAccount(),\n chain: getChain(),\n address: EAS_CONTRACTS().EAS,\n abi: EAS_ABI,\n functionName: \"attest\",\n args: [{\n schema: EAS_SCHEMAS().SYNDICATE_JOIN_REQUEST,\n data: {\n recipient: creatorAddress,\n expirationTime: 0n,\n revocable: true,\n refUID: ZERO_BYTES32,\n data,\n value: 0n,\n },\n }],\n value: 0n,\n });\n\n const receipt = await waitForReceipt(hash);\n const uid = extractAttestationUid(receipt);\n\n return { uid, hash };\n });\n}\n\n/**\n * Create an AGENT_APPROVED attestation.\n * Attester: the fund creator. Recipient: the agent wallet.\n */\nexport async function createApproval(\n syndicateId: bigint,\n agentId: bigint,\n vault: Address,\n agentAddress: Address,\n): Promise<{ uid: Hex; hash: Hex } | null> {\n if (skipWriteOnFork(\"approval\")) return null;\n return withNetwork(getEasNetwork(), async () => {\n assertSchemasRegistered();\n\n const data = encodeAbiParameters(AGENT_APPROVED_PARAMS, [\n syndicateId, agentId, vault,\n ]);\n\n const hash = await writeContractWithRetry({\n account: getAccount(),\n chain: getChain(),\n address: EAS_CONTRACTS().EAS,\n abi: EAS_ABI,\n functionName: \"attest\",\n args: [{\n schema: EAS_SCHEMAS().AGENT_APPROVED,\n data: {\n recipient: agentAddress,\n expirationTime: 0n,\n revocable: true,\n refUID: ZERO_BYTES32,\n data,\n value: 0n,\n },\n }],\n value: 0n,\n });\n\n const receipt = await waitForReceipt(hash);\n const uid = extractAttestationUid(receipt);\n\n return { uid, hash };\n });\n}\n\n/**\n * Revoke an attestation. Only the original attester can revoke. Uses the\n * active chain's EAS — call sites that revoke fund-coordination\n * attestations (join requests, approvals) should go through\n * `revokeJoinRequest` / `revokeApproval` so the revoke lands on the same\n * chain as the original attestation (Base / Base-Sepolia).\n */\nexport async function revokeAttestation(\n schemaUid: Hex,\n attestationUid: Hex,\n): Promise<Hex> {\n return writeContractWithRetry({\n account: getAccount(),\n chain: getChain(),\n address: EAS_CONTRACTS().EAS,\n abi: EAS_ABI,\n functionName: \"revoke\",\n args: [{\n schema: schemaUid,\n data: {\n uid: attestationUid,\n value: 0n,\n },\n }],\n value: 0n,\n });\n}\n\n/** Revoke a SYNDICATE_JOIN_REQUEST on the EAS chain (Base / Base-Sepolia). */\nexport async function revokeJoinRequest(attestationUid: Hex): Promise<Hex | null> {\n if (skipWriteOnFork(\"revoke\")) return null;\n return withNetwork(getEasNetwork(), () =>\n revokeAttestation(EAS_SCHEMAS().SYNDICATE_JOIN_REQUEST, attestationUid),\n );\n}\n\n/**\n * Create an X402_RESEARCH attestation — records a research query on-chain.\n * Attester: the agent. Recipient: vault address (links to fund) or agent itself.\n * Schema: \"string provider, string queryType, string prompt, string costUsdc, string resultUri\"\n */\nexport async function createResearchAttestation(\n provider: string,\n queryType: string,\n prompt: string,\n costUsdc: string,\n resultUri: string,\n recipient?: Address,\n): Promise<{ uid: Hex; hash: Hex } | null> {\n if (skipWriteOnFork(\"research\")) return null;\n const schemas = EAS_SCHEMAS();\n if (schemas.X402_RESEARCH === ZERO_BYTES32) {\n throw new Error(\n \"X402_RESEARCH schema not registered. Run: npx tsx scripts/register-eas-schemas.ts --testnet\",\n );\n }\n\n const client = getPublicClient();\n const account = getAccount();\n\n const data = encodeAbiParameters(X402_RESEARCH_PARAMS, [\n provider, queryType, prompt, costUsdc, resultUri,\n ]);\n\n const hash = await writeContractWithRetry({\n account,\n chain: getChain(),\n address: EAS_CONTRACTS().EAS,\n abi: EAS_ABI,\n functionName: \"attest\",\n args: [{\n schema: schemas.X402_RESEARCH,\n data: {\n recipient: recipient ?? account.address,\n expirationTime: 0n,\n revocable: false,\n refUID: ZERO_BYTES32,\n data,\n value: 0n,\n },\n }],\n value: 0n,\n });\n\n const receipt = await waitForReceipt(hash);\n const uid = extractAttestationUid(receipt);\n\n return { uid, hash };\n}\n\n/**\n * Create a VENICE_PROVISION attestation — records that an agent provisioned a Venice API key.\n * Schema: \"address agent, string status\"\n */\nexport async function createVeniceProvisionAttestation(\n agent: Address,\n): Promise<{ uid: Hex; hash: Hex } | null> {\n if (skipWriteOnFork(\"venice provision\")) return null;\n const schemas = EAS_SCHEMAS();\n if (schemas.VENICE_PROVISION === ZERO_BYTES32) return skipAttestation(\"VENICE_PROVISION\");\n\n const client = getPublicClient();\n const account = getAccount();\n\n const data = encodeAbiParameters(VENICE_PROVISION_PARAMS, [agent, \"provisioned\"]);\n\n const hash = await writeContractWithRetry({\n account,\n chain: getChain(),\n address: EAS_CONTRACTS().EAS,\n abi: EAS_ABI,\n functionName: \"attest\",\n args: [{\n schema: schemas.VENICE_PROVISION,\n data: {\n recipient: agent,\n expirationTime: 0n,\n revocable: false,\n refUID: ZERO_BYTES32,\n data,\n value: 0n,\n },\n }],\n value: 0n,\n });\n\n const receipt = await waitForReceipt(hash);\n const uid = extractAttestationUid(receipt);\n return { uid, hash };\n}\n\n/**\n * Create a VENICE_INFERENCE attestation — records an inference call.\n * Attester: the agent. Recipient: vault address (links to fund) or agent itself.\n * Schema: \"string model, uint256 promptTokens, uint256 completionTokens, string promptHash\"\n */\nexport async function createVeniceInferenceAttestation(\n model: string,\n promptTokens: number,\n completionTokens: number,\n promptHash: string,\n recipient?: Address,\n): Promise<{ uid: Hex; hash: Hex } | null> {\n if (skipWriteOnFork(\"venice inference\")) return null;\n const schemas = EAS_SCHEMAS();\n if (schemas.VENICE_INFERENCE === ZERO_BYTES32) return skipAttestation(\"VENICE_INFERENCE\");\n\n const client = getPublicClient();\n const account = getAccount();\n\n const data = encodeAbiParameters(VENICE_INFERENCE_PARAMS, [\n model,\n BigInt(promptTokens),\n BigInt(completionTokens),\n promptHash,\n ]);\n\n const hash = await writeContractWithRetry({\n account,\n chain: getChain(),\n address: EAS_CONTRACTS().EAS,\n abi: EAS_ABI,\n functionName: \"attest\",\n args: [{\n schema: schemas.VENICE_INFERENCE,\n data: {\n recipient: recipient ?? account.address,\n expirationTime: 0n,\n revocable: false,\n refUID: ZERO_BYTES32,\n data,\n value: 0n,\n },\n }],\n value: 0n,\n });\n\n const receipt = await waitForReceipt(hash);\n const uid = extractAttestationUid(receipt);\n return { uid, hash };\n}\n\n/**\n * Create a TRADE_EXECUTED attestation — records a swap on-chain.\n * Attester: the agent. Recipient: vault address (links to fund) or agent itself.\n * Schema: \"address tokenIn, address tokenOut, uint256 amountIn, string amountOut, string txHash, string routing\"\n */\nexport async function createTradeAttestation(\n tokenIn: Address,\n tokenOut: Address,\n amountIn: bigint,\n amountOut: string,\n txHash: string,\n routing: string,\n recipient?: Address,\n): Promise<{ uid: Hex; hash: Hex } | null> {\n if (skipWriteOnFork(\"trade\")) return null;\n const schemas = EAS_SCHEMAS();\n if (schemas.TRADE_EXECUTED === ZERO_BYTES32) return skipAttestation(\"TRADE_EXECUTED\");\n\n const client = getPublicClient();\n const account = getAccount();\n\n const data = encodeAbiParameters(TRADE_EXECUTED_PARAMS, [\n tokenIn, tokenOut, amountIn, amountOut, txHash, routing,\n ]);\n\n const hash = await writeContractWithRetry({\n account,\n chain: getChain(),\n address: EAS_CONTRACTS().EAS,\n abi: EAS_ABI,\n functionName: \"attest\",\n args: [{\n schema: schemas.TRADE_EXECUTED,\n data: {\n recipient: recipient ?? account.address,\n expirationTime: 0n,\n revocable: false,\n refUID: ZERO_BYTES32,\n data,\n value: 0n,\n },\n }],\n value: 0n,\n });\n\n const receipt = await waitForReceipt(hash);\n const uid = extractAttestationUid(receipt);\n return { uid, hash };\n}\n\n/** Skip attestation gracefully when schema isn't registered on this chain. */\nfunction skipAttestation(name: string): { uid: Hex; hash: Hex } {\n return { uid: ZERO_BYTES32, hash: ZERO_BYTES32 };\n}\n\n// ── Attestation Queries ──\n\nexport interface JoinRequestAttestation {\n uid: Hex;\n attester: Address;\n recipient: Address;\n time: number;\n decoded: {\n syndicateId: bigint;\n agentId: bigint;\n vault: Address;\n message: string;\n };\n}\n\n/**\n * Query pending (non-revoked) join requests for a given recipient (creator address).\n * Uses the EAS GraphQL API.\n */\nexport interface ApprovalAttestation {\n uid: Hex;\n attester: Address;\n recipient: Address;\n time: number;\n decoded: {\n syndicateId: bigint;\n agentId: bigint;\n vault: Address;\n };\n}\n\n/**\n * Query existing (non-revoked) AGENT_APPROVED attestations created by a given attester (creator).\n * Used to check for duplicates before creating a new approval and to filter already-approved agents from requests.\n */\nexport async function queryApprovals(\n attester: Address,\n): Promise<ApprovalAttestation[]> {\n return withNetwork(getEasNetwork(), () => queryApprovalsImpl(attester));\n}\n\nasync function queryApprovalsImpl(attester: Address): Promise<ApprovalAttestation[]> {\n assertSchemasRegistered();\n const schemaUid = EAS_SCHEMAS().AGENT_APPROVED;\n 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 return withNetwork(getEasNetwork(), () => queryJoinRequestsImpl(recipient));\n}\n\nasync function queryJoinRequestsImpl(recipient: Address): Promise<JoinRequestAttestation[]> {\n assertSchemasRegistered();\n const schemaUid = EAS_SCHEMAS().SYNDICATE_JOIN_REQUEST;\n 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":[]}
|
|
@@ -39,6 +39,15 @@ var robinhoodFork = defineChain({
|
|
|
39
39
|
testnet: true
|
|
40
40
|
});
|
|
41
41
|
var DEFAULT_MIN_GAS_RESERVE = parseEther("0.0005");
|
|
42
|
+
var robinhoodMainnet = defineChain({
|
|
43
|
+
id: 4663,
|
|
44
|
+
name: "Robinhood Chain",
|
|
45
|
+
nativeCurrency: { name: "Ethereum", symbol: "ETH", decimals: 18 },
|
|
46
|
+
rpcUrls: { default: { http: ["https://rpc.mainnet.chain.robinhood.com"] } },
|
|
47
|
+
blockExplorers: {
|
|
48
|
+
default: { name: "Blockscout", url: "https://robinhoodchain.blockscout.com" }
|
|
49
|
+
}
|
|
50
|
+
});
|
|
42
51
|
var CHAIN_REGISTRY = {
|
|
43
52
|
"robinhood-testnet": {
|
|
44
53
|
chain: robinhoodTestnet,
|
|
@@ -67,9 +76,30 @@ var CHAIN_REGISTRY = {
|
|
|
67
76
|
// Robinhood-mainnet-fork gas (~0.17 gwei) is higher than testnet's ~14 wei —
|
|
68
77
|
// keep a modest reserve so the ETH-wrap deposit path isn't rejected.
|
|
69
78
|
minGasReserve: parseEther("0.0005")
|
|
79
|
+
},
|
|
80
|
+
"robinhood-mainnet": {
|
|
81
|
+
chain: robinhoodMainnet,
|
|
82
|
+
// Public endpoint kept only as a last-resort fallback: it sits behind
|
|
83
|
+
// Cloudflare and challenges non-browser clients under load, and Robinhood's
|
|
84
|
+
// own docs call it unsuitable for production. ROBINHOOD_RPC_URL (Alchemy)
|
|
85
|
+
// is what actually gets used.
|
|
86
|
+
rpcFallbacks: ["https://rpc.mainnet.chain.robinhood.com"],
|
|
87
|
+
rpcEnvVar: "ROBINHOOD_RPC_URL",
|
|
88
|
+
explorerHost: "robinhoodchain.blockscout.com",
|
|
89
|
+
// Self-hosted EAS indexer — easscan does not index 4663. Serves GraphQL at
|
|
90
|
+
// the root, so no /graphql suffix.
|
|
91
|
+
easGraphqlUrl: "https://sherwood-indexer-production.up.railway.app",
|
|
92
|
+
// No easscan-equivalent UI for this chain yet; attestation permalinks are
|
|
93
|
+
// pending the app's own /attestation route (spec §10.2).
|
|
94
|
+
easScanHost: null,
|
|
95
|
+
xmtpEnv: "production",
|
|
96
|
+
isTestnet: false
|
|
70
97
|
}
|
|
71
98
|
};
|
|
72
|
-
var
|
|
99
|
+
var COORDINATION_ONLY_NETWORKS = ["robinhood-mainnet"];
|
|
100
|
+
var VALID_NETWORKS = Object.keys(CHAIN_REGISTRY).filter(
|
|
101
|
+
(n) => !COORDINATION_ONLY_NETWORKS.includes(n)
|
|
102
|
+
);
|
|
73
103
|
var DEFAULT_NETWORK = "robinhood-fork";
|
|
74
104
|
var _network = DEFAULT_NETWORK;
|
|
75
105
|
function setNetwork(n) {
|
|
@@ -139,7 +169,9 @@ export {
|
|
|
139
169
|
robinhoodTestnet,
|
|
140
170
|
robinhoodFork,
|
|
141
171
|
DEFAULT_MIN_GAS_RESERVE,
|
|
172
|
+
robinhoodMainnet,
|
|
142
173
|
CHAIN_REGISTRY,
|
|
174
|
+
COORDINATION_ONLY_NETWORKS,
|
|
143
175
|
VALID_NETWORKS,
|
|
144
176
|
DEFAULT_NETWORK,
|
|
145
177
|
setNetwork,
|
|
@@ -154,4 +186,4 @@ export {
|
|
|
154
186
|
getExplorerUrl,
|
|
155
187
|
isTestnet
|
|
156
188
|
};
|
|
157
|
-
//# sourceMappingURL=chunk-
|
|
189
|
+
//# sourceMappingURL=chunk-PVTZMRC6.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/network.ts"],"sourcesContent":["/**\n * Network state singleton.\n *\n * Called once at CLI startup via the --chain flag's preAction hook.\n * Every other module reads from here — never hardcodes a chain.\n *\n * Deployment targets: the Robinhood Chain mainnet fork (chain 9994663) — the\n * DEFAULT, and what the product ships against (app.sherwood.sh and the docs\n * both point there) — plus the Robinhood L2 testnet (chain 46630), still\n * reachable via `--chain robinhood-testnet`. Sherwood launches on Robinhood\n * first; other chains may be added back later, at which point they re-enter\n * the Network union + CHAIN_REGISTRY below.\n */\n\nimport { type Chain, defineChain, parseEther } from \"viem\";\nimport { getConfigRpcUrl } from \"./config.js\";\n\n// ── Robinhood L2 Testnet (Arbitrum Orbit, chain ID 46630) ──\n\nexport const robinhoodTestnet = defineChain({\n id: 46630,\n name: \"Robinhood Chain Testnet\",\n nativeCurrency: { name: \"Ethereum\", symbol: \"ETH\", decimals: 18 },\n rpcUrls: {\n default: { http: [\"https://rpc.testnet.chain.robinhood.com\"] },\n },\n blockExplorers: {\n default: {\n name: \"Blockscout\",\n url: \"https://explorer.testnet.chain.robinhood.com\",\n },\n },\n testnet: true,\n});\n\n// ── Robinhood Chain mainnet fork (Tenderly Virtual TestNet, chain ID 9994663) ──\n//\n// A fork of Robinhood Chain *mainnet* (USDG stablecoin, official Uniswap v3+v4,\n// Chainlink push feeds, tokenized-stock liquidity). Used for mainnet-faithful\n// e2e + guardian-network simulations. Ephemeral: Tenderly vnets expire — the RPC\n// is overridable via ROBINHOOD_FORK_RPC_URL when a new vnet is minted.\n\n/**\n * The PUBLIC RPC endpoint of vnet `a3fb16`\n * (id 6ad5961e-fbca-452f-939f-ca9a8c020933) — safe to bundle and to hand to\n * users: it serves reads and accepts broadcast txs, but exposes no\n * state-cheat surface.\n *\n * Admin/cheat calls (`tenderly_setBalance`, `tenderly_setStorageAt`,\n * `evm_increaseTime`, …) need that vnet's *admin* RPC, which is private —\n * pull it from the Tenderly dashboard and pass it via ROBINHOOD_FORK_RPC_URL.\n *\n * Two vnets answer to chain id 9994663; block height is the tell — the live\n * one is past block 21,170,000, the stale one forked at ~4.4M.\n */\nconst ROBINHOOD_FORK_PUBLIC_RPC =\n \"https://virtual.robinhood-chain.eu.rpc.tenderly.co/moonwell/wormhole-bridge/231af1\";\n\n/**\n * Tenderly scopes a vnet explorer under its vnet id — the bare\n * `dashboard.tenderly.co` host resolves to the user's own dashboard, not to\n * this fork's blocks, so tx/address links must carry the full prefix.\n */\nconst ROBINHOOD_FORK_EXPLORER =\n \"https://dashboard.tenderly.co/explorer/vnet/6ad5961e-fbca-452f-939f-ca9a8c020933\";\n\nexport const robinhoodFork = defineChain({\n id: 9994663,\n name: \"Robinhood Chain (fork)\",\n nativeCurrency: { name: \"Ethereum\", symbol: \"ETH\", decimals: 18 },\n rpcUrls: {\n default: {\n http: [ROBINHOOD_FORK_PUBLIC_RPC],\n },\n },\n blockExplorers: {\n default: {\n name: \"Tenderly\",\n url: ROBINHOOD_FORK_EXPLORER,\n },\n },\n testnet: true,\n});\n\n// ── Types ──\n\nexport type Network = \"robinhood-testnet\" | \"robinhood-fork\" | \"robinhood-mainnet\";\n\nexport interface ChainConfig {\n chain: Chain;\n /**\n * Ordered list of public RPC URLs tried in sequence when no user RPC is set.\n * First entry is the primary; the rest are fallbacks used transparently via\n * viem's `fallback` transport on rate-limit / network errors.\n */\n rpcFallbacks: string[];\n /** Legacy env var for backwards compat (optional per chain) */\n rpcEnvVar?: string;\n explorerHost: string;\n /**\n * Full URL prefix for explorer links, when the explorer is not rooted at\n * `https://${explorerHost}` — a Tenderly vnet scopes its blocks under\n * `/explorer/vnet/<id>`. Defaults to `https://${explorerHost}`.\n */\n explorerBaseUrl?: string;\n /** EAS GraphQL endpoint — null if EAS is not available on this chain */\n easGraphqlUrl: string | null;\n /** EAS scan host — null if unavailable */\n easScanHost: string | null;\n xmtpEnv: \"production\" | \"dev\";\n isTestnet: boolean;\n /**\n * ETH held back for gas in the native-ETH-wrap deposit path — the floor and\n * fallback for the live per-tx cushion estimate (`estimateGasCushion` in\n * client.ts), NOT a fixed requirement. High-fee chains (Base) want a\n * Base-scale reserve; near-zero-fee chains (Robinhood testnet, ~14-wei base\n * fee) want a tiny one so a valid deposit isn't rejected client-side. Unset →\n * `DEFAULT_MIN_GAS_RESERVE`.\n */\n minGasReserve?: bigint;\n}\n\n/**\n * Base-scale default reserve, used when a chain omits `minGasReserve`. Matches\n * the old hardcoded 0.0005-ETH cushion so higher-fee chains keep prior behavior.\n */\nexport const DEFAULT_MIN_GAS_RESERVE = parseEther(\"0.0005\");\n\n/**\n * Robinhood Chain mainnet (4663) — the EAS **coordination chain**.\n *\n * Sherwood core is NOT deployed here. This entry exists so attestations have a\n * single permanent home regardless of which chain a fund lives on, and it is\n * deliberately excluded from VALID_NETWORKS so it can never be picked as one.\n *\n * See docs/superpowers/specs/2026-08-26-eas-robinhood-mainnet-design.md §5.1.\n */\nexport const robinhoodMainnet = defineChain({\n id: 4663,\n name: \"Robinhood Chain\",\n nativeCurrency: {name: \"Ethereum\", symbol: \"ETH\", decimals: 18},\n rpcUrls: {default: {http: [\"https://rpc.mainnet.chain.robinhood.com\"]}},\n blockExplorers: {\n default: {name: \"Blockscout\", url: \"https://robinhoodchain.blockscout.com\"},\n },\n});\n\n// ── Chain Registry ──\n\nexport const CHAIN_REGISTRY: Record<Network, ChainConfig> = {\n \"robinhood-testnet\": {\n chain: robinhoodTestnet,\n rpcFallbacks: [\"https://rpc.testnet.chain.robinhood.com\"],\n rpcEnvVar: \"ROBINHOOD_TESTNET_RPC_URL\",\n explorerHost: \"explorer.testnet.chain.robinhood.com\",\n easGraphqlUrl: null,\n easScanHost: null,\n xmtpEnv: \"production\",\n isTestnet: true,\n // ~14-wei base fee: a full wrap+approve+deposit sequence costs a few\n // million wei (~1e-11 ETH). 0.00002 ETH is a generous floor that still\n // leaves a 0.00058-ETH wallet room to wrap 0.0005 and deposit.\n minGasReserve: parseEther(\"0.00002\"),\n },\n \"robinhood-fork\": {\n chain: robinhoodFork,\n rpcFallbacks: [ROBINHOOD_FORK_PUBLIC_RPC],\n rpcEnvVar: \"ROBINHOOD_FORK_RPC_URL\",\n explorerHost: \"dashboard.tenderly.co\",\n explorerBaseUrl: ROBINHOOD_FORK_EXPLORER,\n easGraphqlUrl: null,\n easScanHost: null,\n xmtpEnv: \"production\",\n isTestnet: true,\n // Robinhood-mainnet-fork gas (~0.17 gwei) is higher than testnet's ~14 wei —\n // keep a modest reserve so the ETH-wrap deposit path isn't rejected.\n minGasReserve: parseEther(\"0.0005\"),\n },\n \"robinhood-mainnet\": {\n chain: robinhoodMainnet,\n // Public endpoint kept only as a last-resort fallback: it sits behind\n // Cloudflare and challenges non-browser clients under load, and Robinhood's\n // own docs call it unsuitable for production. ROBINHOOD_RPC_URL (Alchemy)\n // is what actually gets used.\n rpcFallbacks: [\"https://rpc.mainnet.chain.robinhood.com\"],\n rpcEnvVar: \"ROBINHOOD_RPC_URL\",\n explorerHost: \"robinhoodchain.blockscout.com\",\n // Self-hosted EAS indexer — easscan does not index 4663. Serves GraphQL at\n // the root, so no /graphql suffix.\n easGraphqlUrl: \"https://sherwood-indexer-production.up.railway.app\",\n // No easscan-equivalent UI for this chain yet; attestation permalinks are\n // pending the app's own /attestation route (spec §10.2).\n easScanHost: null,\n xmtpEnv: \"production\",\n isTestnet: false,\n },\n};\n\n/**\n * Networks a user may select with `--chain`.\n *\n * NOT simply the CHAIN_REGISTRY keys: `robinhood-mainnet` is a coordination\n * chain for attestations only (no Sherwood contracts deployed there), so\n * selecting it as a fund's home chain would resolve every address to zero.\n */\nexport const COORDINATION_ONLY_NETWORKS: readonly Network[] = [\"robinhood-mainnet\"];\n\nexport const VALID_NETWORKS = (Object.keys(CHAIN_REGISTRY) as Network[]).filter(\n (n) => !COORDINATION_ONLY_NETWORKS.includes(n),\n);\n\n/**\n * The network a bare CLI invocation (no `--chain`) targets.\n *\n * The fork is where the product actually lives: app.sherwood.sh defaults to\n * chain 9994663, the docs banner declares it, and the redeployed 46630 factory\n * holds zero syndicates — so a default of `robinhood-testnet` landed a fresh\n * agent on an empty chain. `--chain robinhood-testnet` still selects 46630.\n */\nexport const DEFAULT_NETWORK: Network = \"robinhood-fork\";\n\n// ── Singleton state ──\n\nlet _network: Network = DEFAULT_NETWORK;\n\nexport function setNetwork(n: Network) {\n const config = CHAIN_REGISTRY[n];\n if (!config) {\n throw new Error(\n `Unknown network: ${n}. Valid: ${VALID_NETWORKS.join(\", \")}`,\n );\n }\n _network = n;\n}\n\nexport function getNetwork(): Network {\n return _network;\n}\n\n/**\n * Run `fn` with the network singleton temporarily switched to `network`,\n * restoring the previous network in `finally`.\n *\n * The viem clients (`getPublicClient`, `getWalletClient`) auto-invalidate on\n * chain change, so callers get fresh per-chain RPC + chain context inside the\n * block. Used for cross-chain fund resolution.\n */\nexport async function withNetwork<T>(\n network: Network,\n fn: () => Promise<T>,\n): Promise<T> {\n const previous = _network;\n _network = network;\n try {\n return await fn();\n } finally {\n _network = previous;\n }\n}\n\nexport function getChainConfig(): ChainConfig {\n return CHAIN_REGISTRY[_network];\n}\n\n/**\n * Per-chain ETH gas reserve floor/fallback for the ETH-wrap deposit path.\n * Falls back to the Base-scale default when the active chain doesn't set one.\n */\nexport function getMinGasReserve(): bigint {\n return CHAIN_REGISTRY[_network].minGasReserve ?? DEFAULT_MIN_GAS_RESERVE;\n}\n\n/**\n * Dev/CI-only chain-id override (`SIM_CHAIN_ID`) for custom-chainId vnet forks.\n * viem asserts the node's chainId matches the chain definition on every write,\n * so signing for such a fork requires the id to be swapped at the source.\n *\n * Interlock: honored ONLY while `SIM_ADDRESSES_FILE` is also set (the vnet\n * e2e harness's address override). A bare SIM_CHAIN_ID does nothing, so this\n * can never redirect signing on a real network run.\n */\nexport function applyChainIdOverride(chain: Chain): Chain {\n const raw = process.env.SIM_CHAIN_ID;\n if (!raw || !process.env.SIM_ADDRESSES_FILE) return chain;\n const id = Number(raw);\n if (!Number.isInteger(id) || id <= 0) return chain;\n return { ...chain, id };\n}\n\nexport function getChain(): Chain {\n return applyChainIdOverride(CHAIN_REGISTRY[_network].chain);\n}\n\n/**\n * Ordered list of RPC URLs to try, deduped:\n * 1. User config (~/.sherwood/config.json) — honored first\n * 2. The active chain's legacy env var (`rpcEnvVar` — ROBINHOOD_FORK_RPC_URL\n * on the default fork, ROBINHOOD_TESTNET_RPC_URL on 46630)\n * 3. Public fallback list from CHAIN_REGISTRY\n *\n * Fed to viem's `fallback()` transport so rate-limited RPCs transparently\n * advance to the next entry. See issue #182.\n */\nexport function getRpcUrls(): string[] {\n const cfg = CHAIN_REGISTRY[_network];\n const urls: string[] = [];\n\n const fromConfig = getConfigRpcUrl(_network);\n if (fromConfig) urls.push(fromConfig);\n\n if (cfg.rpcEnvVar && process.env[cfg.rpcEnvVar]) {\n urls.push(process.env[cfg.rpcEnvVar]!);\n }\n\n // Vnet harness (SIM_CHAIN_ID + SIM_ADDRESSES_FILE interlock): the fork RPC\n // is the ONLY valid endpoint — the public fallbacks point at the real\n // network. viem's fallback() otherwise rotates there on a vnet hiccup and\n // silently estimates gas/fees against MAINNET state (live finding: an\n // approve estimated at 21.9k gas on mainnet — no code at that address —\n // reverted out-of-gas on the vnet where it needs ~46k). A vnet call must\n // fail loudly, never retarget the real chain.\n if (process.env.SIM_CHAIN_ID && process.env.SIM_ADDRESSES_FILE && urls.length > 0) {\n return Array.from(new Set(urls));\n }\n\n urls.push(...cfg.rpcFallbacks);\n\n return Array.from(new Set(urls));\n}\n\nexport function getRpcUrl(): string {\n return getRpcUrls()[0];\n}\n\nexport function getExplorerUrl(txHash: string): string {\n const cfg = CHAIN_REGISTRY[_network];\n const base = cfg.explorerBaseUrl ?? `https://${cfg.explorerHost}`;\n return `${base}/tx/${txHash}`;\n}\n\nexport function isTestnet(): boolean {\n return CHAIN_REGISTRY[_network].isTestnet;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
getChain,
|
|
3
3
|
getMinGasReserve,
|
|
4
4
|
getRpcUrls
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-PVTZMRC6.js";
|
|
6
6
|
import {
|
|
7
7
|
requirePrivateKey
|
|
8
8
|
} from "./chunk-3TZIOAPH.js";
|
|
@@ -540,4 +540,4 @@ export {
|
|
|
540
540
|
writeContractWithRetry,
|
|
541
541
|
waitForReceipt
|
|
542
542
|
};
|
|
543
|
-
//# sourceMappingURL=chunk-
|
|
543
|
+
//# sourceMappingURL=chunk-QRMZRAMG.js.map
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getLogsChunked
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-65G5BFYR.js";
|
|
4
4
|
import {
|
|
5
5
|
TOKENS
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-AM6MI2JF.js";
|
|
7
7
|
import {
|
|
8
8
|
GAS_UNITS,
|
|
9
9
|
estimateGasCushion,
|
|
@@ -12,17 +12,17 @@ import {
|
|
|
12
12
|
getWalletClient,
|
|
13
13
|
waitForReceipt,
|
|
14
14
|
writeContractWithRetry
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-QRMZRAMG.js";
|
|
16
16
|
import {
|
|
17
17
|
getChain
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-PVTZMRC6.js";
|
|
19
19
|
import {
|
|
20
20
|
getChainContracts
|
|
21
21
|
} from "./chunk-3TZIOAPH.js";
|
|
22
22
|
import {
|
|
23
23
|
ERC20_ABI,
|
|
24
24
|
SYNDICATE_VAULT_ABI
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-F3MDCUGO.js";
|
|
26
26
|
|
|
27
27
|
// src/lib/vault.ts
|
|
28
28
|
import { formatUnits, parseAbiItem } from "viem";
|
|
@@ -557,4 +557,4 @@ export {
|
|
|
557
557
|
registerAgent,
|
|
558
558
|
getVaultInfo
|
|
559
559
|
};
|
|
560
|
-
//# sourceMappingURL=chunk-
|
|
560
|
+
//# sourceMappingURL=chunk-TWT56FTL.js.map
|
|
@@ -12,8 +12,8 @@ import {
|
|
|
12
12
|
unstickWallet,
|
|
13
13
|
waitForReceipt,
|
|
14
14
|
writeContractWithRetry
|
|
15
|
-
} from "./chunk-
|
|
16
|
-
import "./chunk-
|
|
15
|
+
} from "./chunk-QRMZRAMG.js";
|
|
16
|
+
import "./chunk-PVTZMRC6.js";
|
|
17
17
|
import "./chunk-3TZIOAPH.js";
|
|
18
18
|
export {
|
|
19
19
|
GAS_UNITS,
|
|
@@ -30,4 +30,4 @@ export {
|
|
|
30
30
|
waitForReceipt,
|
|
31
31
|
writeContractWithRetry
|
|
32
32
|
};
|
|
33
|
-
//# sourceMappingURL=client-
|
|
33
|
+
//# sourceMappingURL=client-3SE632Q2.js.map
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
|
+
COORDINATION_NETWORK,
|
|
3
|
+
EAS_NETWORK,
|
|
4
|
+
assertCanPayForAttestation,
|
|
5
|
+
attestationWritesEnabled,
|
|
2
6
|
createApproval,
|
|
3
7
|
createJoinRequest,
|
|
4
8
|
createResearchAttestation,
|
|
@@ -17,13 +21,17 @@ import {
|
|
|
17
21
|
revokeAttestation,
|
|
18
22
|
revokeJoinRequest,
|
|
19
23
|
stripReferrerPrefix
|
|
20
|
-
} from "./chunk-
|
|
21
|
-
import "./chunk-
|
|
22
|
-
import "./chunk-
|
|
23
|
-
import "./chunk-
|
|
24
|
+
} from "./chunk-M4GX5PL2.js";
|
|
25
|
+
import "./chunk-AM6MI2JF.js";
|
|
26
|
+
import "./chunk-QRMZRAMG.js";
|
|
27
|
+
import "./chunk-PVTZMRC6.js";
|
|
24
28
|
import "./chunk-3TZIOAPH.js";
|
|
25
|
-
import "./chunk-
|
|
29
|
+
import "./chunk-F3MDCUGO.js";
|
|
26
30
|
export {
|
|
31
|
+
COORDINATION_NETWORK,
|
|
32
|
+
EAS_NETWORK,
|
|
33
|
+
assertCanPayForAttestation,
|
|
34
|
+
attestationWritesEnabled,
|
|
27
35
|
createApproval,
|
|
28
36
|
createJoinRequest,
|
|
29
37
|
createResearchAttestation,
|
|
@@ -43,4 +51,4 @@ export {
|
|
|
43
51
|
revokeJoinRequest,
|
|
44
52
|
stripReferrerPrefix
|
|
45
53
|
};
|
|
46
|
-
//# sourceMappingURL=eas-
|
|
54
|
+
//# sourceMappingURL=eas-D3BVHBJH.js.map
|
|
@@ -2,8 +2,10 @@ import {
|
|
|
2
2
|
PROPOSAL_STATE,
|
|
3
3
|
PROPOSAL_STATES,
|
|
4
4
|
VOTE_TYPE,
|
|
5
|
+
assertReceiptSuccess,
|
|
5
6
|
cancelProposal,
|
|
6
7
|
classifyReview,
|
|
8
|
+
classifyReviewOpen,
|
|
7
9
|
detectStrategyAdapter,
|
|
8
10
|
emergencyCancel,
|
|
9
11
|
emergencySettle,
|
|
@@ -26,6 +28,7 @@ import {
|
|
|
26
28
|
parseProposalIdFromLogs,
|
|
27
29
|
proposalCount,
|
|
28
30
|
propose,
|
|
31
|
+
scanReviewCandidates,
|
|
29
32
|
setCooldownPeriod,
|
|
30
33
|
setExecutionWindow,
|
|
31
34
|
setMaxPerformanceFeeBps,
|
|
@@ -36,18 +39,20 @@ import {
|
|
|
36
39
|
settleProposal,
|
|
37
40
|
vetoProposal,
|
|
38
41
|
vote
|
|
39
|
-
} from "./chunk-
|
|
40
|
-
import "./chunk-
|
|
41
|
-
import "./chunk-
|
|
42
|
-
import "./chunk-
|
|
42
|
+
} from "./chunk-6N7EVSAZ.js";
|
|
43
|
+
import "./chunk-AM6MI2JF.js";
|
|
44
|
+
import "./chunk-QRMZRAMG.js";
|
|
45
|
+
import "./chunk-PVTZMRC6.js";
|
|
43
46
|
import "./chunk-3TZIOAPH.js";
|
|
44
|
-
import "./chunk-
|
|
47
|
+
import "./chunk-F3MDCUGO.js";
|
|
45
48
|
export {
|
|
46
49
|
PROPOSAL_STATE,
|
|
47
50
|
PROPOSAL_STATES,
|
|
48
51
|
VOTE_TYPE,
|
|
52
|
+
assertReceiptSuccess,
|
|
49
53
|
cancelProposal,
|
|
50
54
|
classifyReview,
|
|
55
|
+
classifyReviewOpen,
|
|
51
56
|
detectStrategyAdapter,
|
|
52
57
|
emergencyCancel,
|
|
53
58
|
emergencySettle,
|
|
@@ -70,6 +75,7 @@ export {
|
|
|
70
75
|
parseProposalIdFromLogs,
|
|
71
76
|
proposalCount,
|
|
72
77
|
propose,
|
|
78
|
+
scanReviewCandidates,
|
|
73
79
|
setCooldownPeriod,
|
|
74
80
|
setExecutionWindow,
|
|
75
81
|
setMaxPerformanceFeeBps,
|
|
@@ -81,4 +87,4 @@ export {
|
|
|
81
87
|
vetoProposal,
|
|
82
88
|
vote
|
|
83
89
|
};
|
|
84
|
-
//# sourceMappingURL=governor-
|
|
90
|
+
//# sourceMappingURL=governor-35IXAEDJ.js.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {
|
|
2
|
+
lookupAgentIdByWallet,
|
|
3
|
+
registerIdentityCommands
|
|
4
|
+
} from "./chunk-ILHOW6IA.js";
|
|
5
|
+
import "./chunk-M4GX5PL2.js";
|
|
6
|
+
import "./chunk-AM6MI2JF.js";
|
|
7
|
+
import "./chunk-QRMZRAMG.js";
|
|
8
|
+
import "./chunk-PVTZMRC6.js";
|
|
9
|
+
import "./chunk-3TZIOAPH.js";
|
|
10
|
+
import "./chunk-F3MDCUGO.js";
|
|
11
|
+
export {
|
|
12
|
+
lookupAgentIdByWallet,
|
|
13
|
+
registerIdentityCommands
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=identity-RMEPBFOL.js.map
|