@sherwoodagent/cli 0.73.4 → 0.74.2
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-KP7M4IPM.js → abis-D7EDCKVZ.js} +2 -2
- package/dist/{addresses-DGB3D457.js → addresses-OFFTM6NG.js} +4 -4
- package/dist/{agent-UNSW5IPO.js → agent-IJOOONON.js} +8 -8
- package/dist/{chat-KT2WVDT2.js → chat-3PM3GP3C.js} +9 -10
- package/dist/{chat-KT2WVDT2.js.map → chat-3PM3GP3C.js.map} +1 -1
- package/dist/{chunk-ROKE6ZAW.js → chunk-2OHX3O55.js} +6 -20
- package/dist/chunk-2OHX3O55.js.map +1 -0
- package/dist/{chunk-GSC7PVEO.js → chunk-6MV4ESXM.js} +43 -7
- package/dist/chunk-6MV4ESXM.js.map +1 -0
- package/dist/chunk-7BMCLMSE.js +173 -0
- package/dist/chunk-7BMCLMSE.js.map +1 -0
- package/dist/{chunk-NPWYX6NU.js → chunk-BD4ZV7FQ.js} +3 -3
- package/dist/{chunk-BKJ7HYX7.js → chunk-DGLLSZ2D.js} +10 -10
- package/dist/chunk-DGLLSZ2D.js.map +1 -0
- package/dist/chunk-EGJESQXZ.js +1 -0
- package/dist/chunk-I2PC6TBZ.js +3887 -0
- package/dist/chunk-I2PC6TBZ.js.map +1 -0
- package/dist/{chunk-CHWBQJLT.js → chunk-JF7KAVOM.js} +8 -21
- package/dist/chunk-JF7KAVOM.js.map +1 -0
- package/dist/{chunk-DXJJMRBM.js → chunk-LHVSS27T.js} +2 -2
- package/dist/{chunk-2U4TWPWQ.js → chunk-MUINMYCE.js} +5 -5
- package/dist/{chunk-GU5VZGXB.js → chunk-N3NVFSDQ.js} +5 -5
- package/dist/{chunk-CZRJ5GWE.js → chunk-RAP6MUMB.js} +54 -24
- package/dist/chunk-RAP6MUMB.js.map +1 -0
- package/dist/{chunk-ZURDCYGU.js → chunk-RE3PPAXZ.js} +9 -5
- package/dist/chunk-RE3PPAXZ.js.map +1 -0
- package/dist/{chunk-IFL5SREW.js → chunk-UINMHN6S.js} +2 -2
- package/dist/chunk-WBQMGZ5X.js +1253 -0
- package/dist/chunk-WBQMGZ5X.js.map +1 -0
- package/dist/{client-NAL3HVLK.js → client-C3C6IXAH.js} +4 -4
- package/dist/{config-FAQO37S7.js → config-7HU4X7EK.js} +4 -4
- package/dist/{eas-QAH7XVLK.js → eas-G4TPLJ6S.js} +7 -7
- package/dist/{governor-S56M6BV6.js → governor-PYQQ7QRG.js} +7 -7
- package/dist/index.js +201 -1286
- package/dist/index.js.map +1 -1
- package/dist/{network-MKMX2NG6.js → network-WU2QC3L4.js} +3 -3
- package/dist/{price-HHDBMKIE.js → price-DGGB6W2G.js} +15 -37
- package/dist/price-DGGB6W2G.js.map +1 -0
- package/dist/providers-YOOQFBN2.js +31 -0
- package/dist/providers-YOOQFBN2.js.map +1 -0
- package/dist/{research-IJBOMYL3.js → research-KX3LCAOQ.js} +9 -9
- package/dist/{session-L67AVWBY.js → session-GUVSID3Z.js} +19 -174
- package/dist/session-GUVSID3Z.js.map +1 -0
- package/dist/{trade-LGFQEK3I.js → trade-WDPMFFYB.js} +277 -43
- package/dist/trade-WDPMFFYB.js.map +1 -0
- package/dist/{vault-XWFPGHRA.js → vault-WDRLJLJ6.js} +14 -9
- package/dist/{xmtp-6US7GH3Z.js → xmtp-Q4ZSQV2Q.js} +11 -15
- package/dist/xmtp-Q4ZSQV2Q.js.map +1 -0
- package/package.json +2 -1
- package/dist/chunk-BKJ7HYX7.js.map +0 -1
- package/dist/chunk-BQMOE4FJ.js +0 -1629
- package/dist/chunk-BQMOE4FJ.js.map +0 -1
- package/dist/chunk-CHWBQJLT.js.map +0 -1
- package/dist/chunk-CZRJ5GWE.js.map +0 -1
- package/dist/chunk-DIZEB2VV.js +0 -325
- package/dist/chunk-DIZEB2VV.js.map +0 -1
- package/dist/chunk-GSC7PVEO.js.map +0 -1
- package/dist/chunk-ROKE6ZAW.js.map +0 -1
- package/dist/chunk-ZURDCYGU.js.map +0 -1
- package/dist/price-HHDBMKIE.js.map +0 -1
- package/dist/research-4TBGYEVI.js +0 -14
- package/dist/session-L67AVWBY.js.map +0 -1
- package/dist/trade-LGFQEK3I.js.map +0 -1
- package/dist/xmtp-6US7GH3Z.js.map +0 -1
- /package/dist/{abis-KP7M4IPM.js.map → abis-D7EDCKVZ.js.map} +0 -0
- /package/dist/{addresses-DGB3D457.js.map → addresses-OFFTM6NG.js.map} +0 -0
- /package/dist/{agent-UNSW5IPO.js.map → agent-IJOOONON.js.map} +0 -0
- /package/dist/{chunk-NPWYX6NU.js.map → chunk-BD4ZV7FQ.js.map} +0 -0
- /package/dist/{client-NAL3HVLK.js.map → chunk-EGJESQXZ.js.map} +0 -0
- /package/dist/{chunk-DXJJMRBM.js.map → chunk-LHVSS27T.js.map} +0 -0
- /package/dist/{chunk-2U4TWPWQ.js.map → chunk-MUINMYCE.js.map} +0 -0
- /package/dist/{chunk-GU5VZGXB.js.map → chunk-N3NVFSDQ.js.map} +0 -0
- /package/dist/{chunk-IFL5SREW.js.map → chunk-UINMHN6S.js.map} +0 -0
- /package/dist/{config-FAQO37S7.js.map → client-C3C6IXAH.js.map} +0 -0
- /package/dist/{eas-QAH7XVLK.js.map → config-7HU4X7EK.js.map} +0 -0
- /package/dist/{governor-S56M6BV6.js.map → eas-G4TPLJ6S.js.map} +0 -0
- /package/dist/{network-MKMX2NG6.js.map → governor-PYQQ7QRG.js.map} +0 -0
- /package/dist/{research-4TBGYEVI.js.map → network-WU2QC3L4.js.map} +0 -0
- /package/dist/{research-IJBOMYL3.js.map → research-KX3LCAOQ.js.map} +0 -0
- /package/dist/{vault-XWFPGHRA.js.map → vault-WDRLJLJ6.js.map} +0 -0
|
@@ -1,25 +1,20 @@
|
|
|
1
|
-
import {
|
|
2
|
-
executeBatch,
|
|
3
|
-
setVaultAddress
|
|
4
|
-
} from "./chunk-CZRJ5GWE.js";
|
|
5
1
|
import {
|
|
6
2
|
ENS,
|
|
7
3
|
SHERWOOD
|
|
8
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-UINMHN6S.js";
|
|
9
5
|
import {
|
|
10
6
|
getPublicClient
|
|
11
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-2OHX3O55.js";
|
|
12
8
|
import {
|
|
13
9
|
VALID_NETWORKS,
|
|
14
10
|
withNetwork
|
|
15
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-LHVSS27T.js";
|
|
16
12
|
import {
|
|
17
13
|
L2_REGISTRY_ABI,
|
|
18
14
|
SYNDICATE_FACTORY_ABI
|
|
19
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-I2PC6TBZ.js";
|
|
20
16
|
|
|
21
17
|
// src/lib/ens.ts
|
|
22
|
-
import { encodeFunctionData } from "viem";
|
|
23
18
|
import { namehash } from "viem/ens";
|
|
24
19
|
var ENS_DOMAIN = "sherwoodagent.eth";
|
|
25
20
|
var ZERO = "0x0000000000000000000000000000000000000000";
|
|
@@ -91,17 +86,9 @@ async function resolveVaultFund(vaultAddress) {
|
|
|
91
86
|
function getSubdomainNode(subdomain) {
|
|
92
87
|
return namehash(`${subdomain}.${ENS_DOMAIN}`);
|
|
93
88
|
}
|
|
94
|
-
async function setTextRecord(
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
setVaultAddress(vaultAddress);
|
|
98
|
-
const setTextData = encodeFunctionData({
|
|
99
|
-
abi: L2_REGISTRY_ABI,
|
|
100
|
-
functionName: "setText",
|
|
101
|
-
args: [node, key, value]
|
|
102
|
-
});
|
|
103
|
-
return executeBatch(
|
|
104
|
-
[{ target: l2Registry, data: setTextData, value: 0n }]
|
|
89
|
+
async function setTextRecord(_subdomain, _key, _value, _vaultAddress) {
|
|
90
|
+
throw new Error(
|
|
91
|
+
"ENS text-record writes are not available: the vault no longer exposes owner-direct batch execution (executeBatch was removed on-chain, V-C3). Fund metadata on IPFS is the operative store for these records \u2014 use `sherwood chat <name> publish-metadata`."
|
|
105
92
|
);
|
|
106
93
|
}
|
|
107
94
|
async function getTextRecord(subdomain, key) {
|
|
@@ -124,4 +111,4 @@ export {
|
|
|
124
111
|
setTextRecord,
|
|
125
112
|
getTextRecord
|
|
126
113
|
};
|
|
127
|
-
//# sourceMappingURL=chunk-
|
|
114
|
+
//# sourceMappingURL=chunk-JF7KAVOM.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/ens.ts"],"sourcesContent":["/**\n * ENS resolution + text records via Durin L2Registry on Base.\n *\n * Two responsibilities:\n * 1. Resolve fund subdomain → on-chain fund data (via factory)\n * 2. Read ENS text records (via L2Registry)\n *\n * The vault owns the ENS subdomain node (registered in the factory via\n * `ensRegistrar.register(subdomain, vault)`), so only the vault can write\n * text records. Writes used to route through the vault's owner-direct\n * `executeBatch` → L2Registry.setText — that function was removed on-chain\n * (V-C3; only the governor-driven `executeGovernorBatch` exists), so\n * `setTextRecord` now fails fast (see below) and IPFS fund metadata is the\n * operative store for these records.\n */\n\nimport type { Address, Hex } from \"viem\";\nimport { namehash } from \"viem/ens\";\nimport { getPublicClient } from \"./client.js\";\nimport {\n withNetwork,\n VALID_NETWORKS,\n type Network,\n} from \"./network.js\";\nimport { SYNDICATE_FACTORY_ABI, L2_REGISTRY_ABI } from \"./abis.js\";\nimport { ENS, SHERWOOD } from \"./addresses.js\";\n\nconst ENS_DOMAIN = \"sherwoodagent.eth\";\n\n/** Sentinel for \"no ENS registry deployed on this chain\" (e.g. Robinhood testnet). */\nconst ZERO: Address = \"0x0000000000000000000000000000000000000000\";\n\nfunction getFactoryAddress(): Address {\n return SHERWOOD().FACTORY;\n}\n\n// ── Fund Resolution (via factory) ──\n\nexport interface FundResolution {\n id: bigint;\n vault: Address;\n creator: Address;\n subdomain: string;\n}\n\n/**\n * Resolve a fund subdomain to its on-chain data.\n * Uses factory.subdomainToSyndicate() → factory.syndicates().\n */\nexport async function resolveFund(subdomain: string): Promise<FundResolution> {\n const client = getPublicClient();\n const factory = getFactoryAddress();\n\n // Get fund ID from subdomain\n const fundId = (await client.readContract({\n address: factory,\n abi: SYNDICATE_FACTORY_ABI,\n functionName: \"subdomainToSyndicate\",\n args: [subdomain],\n })) as bigint;\n\n if (fundId === 0n) {\n throw new Error(`Fund \"${subdomain}\" not found`);\n }\n\n // Get full fund record\n const result = (await client.readContract({\n address: factory,\n abi: SYNDICATE_FACTORY_ABI,\n functionName: \"syndicates\",\n args: [fundId],\n })) as [bigint, Address, Address, string, bigint, boolean, string];\n\n return {\n id: result[0],\n vault: result[1],\n creator: result[2],\n subdomain: result[6],\n };\n}\n\n/**\n * Probe every supported chain for a subdomain registration. Returns every hit —\n * most queries find zero or one, but post-CREATE3 the same subdomain may exist\n * on multiple chains and the caller needs to disambiguate. RPC errors on\n * individual chains are swallowed so a flaky chain doesn't fail the whole\n * search. The current deployment target is a single (ungated) chain, so this\n * iterates VALID_NETWORKS directly.\n */\nexport async function searchFundAcrossChains(\n subdomain: string,\n): Promise<{ network: Network; result: FundResolution }[]> {\n const candidates = VALID_NETWORKS;\n\n const hits: { network: Network; result: FundResolution }[] = [];\n for (const net of candidates) {\n try {\n const result = await withNetwork(net, () => resolveFund(subdomain));\n hits.push({ network: net, result });\n } catch {\n // Not registered on this chain, or RPC failed — keep searching.\n }\n }\n return hits;\n}\n\n/**\n * Reverse lookup: vault address → fund info.\n * Uses factory.vaultToSyndicate() → factory.syndicates().\n */\nexport async function resolveVaultFund(\n vaultAddress: Address,\n): Promise<FundResolution> {\n const client = getPublicClient();\n const factory = getFactoryAddress();\n\n const fundId = (await client.readContract({\n address: factory,\n abi: SYNDICATE_FACTORY_ABI,\n functionName: \"vaultToSyndicate\",\n args: [vaultAddress],\n })) as bigint;\n\n if (fundId === 0n) {\n throw new Error(`No fund found for vault ${vaultAddress}`);\n }\n\n const result = (await client.readContract({\n address: factory,\n abi: SYNDICATE_FACTORY_ABI,\n functionName: \"syndicates\",\n args: [fundId],\n })) as [bigint, Address, Address, string, bigint, boolean, string];\n\n return {\n id: result[0],\n vault: result[1],\n creator: result[2],\n subdomain: result[6],\n };\n}\n\n// ── ENS Text Records (via L2Registry) ──\n\n/**\n * Compute the ENS node hash for a subdomain under sherwoodagent.eth.\n */\nfunction getSubdomainNode(subdomain: string): Hex {\n return namehash(`${subdomain}.${ENS_DOMAIN}`);\n}\n\n/**\n * Write a text record to the L2Registry — CURRENTLY IMPOSSIBLE.\n *\n * The vault owns the ENS node, so only the vault can call setText, and the\n * write used to route through the vault's owner-direct `executeBatch`. That\n * function was removed on-chain (V-C3) — the only remaining batch path is\n * the governor-driven `executeGovernorBatch` — so this call reverted\n * opaquely at runtime. Fail fast with an honest error instead; callers\n * already treat the write as best-effort and fall back to IPFS fund\n * metadata (`sherwood chat <name> publish-metadata`), which the dashboard\n * resolves before ENS.\n *\n * Parameters are kept for API stability with the best-effort call sites.\n */\nexport async function setTextRecord(\n _subdomain: string,\n _key: string,\n _value: string,\n _vaultAddress: Address,\n): Promise<Hex> {\n throw new Error(\n \"ENS text-record writes are not available: the vault no longer exposes \" +\n \"owner-direct batch execution (executeBatch was removed on-chain, V-C3). \" +\n \"Fund metadata on IPFS is the operative store for these records — use \" +\n \"`sherwood chat <name> publish-metadata`.\",\n );\n}\n\n/**\n * Read a text record from the L2Registry.\n * Used to look up xmtpGroupId when not cached locally.\n *\n * Chains without a deployed ENS registry (e.g. Robinhood testnet, where\n * `L2_REGISTRY == address(0)`) have no text records — reading `text()` from\n * the zero address makes viem throw `ContractFunctionZeroDataError`. Return\n * \"\" instead so callers (chat init idempotency probe, getGroup ENS fallback)\n * degrade to the cache / name-search paths rather than hard-failing. Every\n * caller already treats \"\" as \"not set\".\n */\nexport async function getTextRecord(\n subdomain: string,\n key: string,\n): Promise<string> {\n const registry = ENS().L2_REGISTRY;\n if (registry.toLowerCase() === ZERO.toLowerCase()) return \"\";\n\n const client = getPublicClient();\n const node = getSubdomainNode(subdomain);\n\n return client.readContract({\n address: registry,\n abi: L2_REGISTRY_ABI,\n functionName: \"text\",\n args: [node, key],\n }) as Promise<string>;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAiBA,SAAS,gBAAgB;AAUzB,IAAM,aAAa;AAGnB,IAAM,OAAgB;AAEtB,SAAS,oBAA6B;AACpC,SAAO,SAAS,EAAE;AACpB;AAeA,eAAsB,YAAY,WAA4C;AAC5E,QAAM,SAAS,gBAAgB;AAC/B,QAAM,UAAU,kBAAkB;AAGlC,QAAM,SAAU,MAAM,OAAO,aAAa;AAAA,IACxC,SAAS;AAAA,IACT,KAAK;AAAA,IACL,cAAc;AAAA,IACd,MAAM,CAAC,SAAS;AAAA,EAClB,CAAC;AAED,MAAI,WAAW,IAAI;AACjB,UAAM,IAAI,MAAM,SAAS,SAAS,aAAa;AAAA,EACjD;AAGA,QAAM,SAAU,MAAM,OAAO,aAAa;AAAA,IACxC,SAAS;AAAA,IACT,KAAK;AAAA,IACL,cAAc;AAAA,IACd,MAAM,CAAC,MAAM;AAAA,EACf,CAAC;AAED,SAAO;AAAA,IACL,IAAI,OAAO,CAAC;AAAA,IACZ,OAAO,OAAO,CAAC;AAAA,IACf,SAAS,OAAO,CAAC;AAAA,IACjB,WAAW,OAAO,CAAC;AAAA,EACrB;AACF;AAUA,eAAsB,uBACpB,WACyD;AACzD,QAAM,aAAa;AAEnB,QAAM,OAAuD,CAAC;AAC9D,aAAW,OAAO,YAAY;AAC5B,QAAI;AACF,YAAM,SAAS,MAAM,YAAY,KAAK,MAAM,YAAY,SAAS,CAAC;AAClE,WAAK,KAAK,EAAE,SAAS,KAAK,OAAO,CAAC;AAAA,IACpC,QAAQ;AAAA,IAER;AAAA,EACF;AACA,SAAO;AACT;AAMA,eAAsB,iBACpB,cACyB;AACzB,QAAM,SAAS,gBAAgB;AAC/B,QAAM,UAAU,kBAAkB;AAElC,QAAM,SAAU,MAAM,OAAO,aAAa;AAAA,IACxC,SAAS;AAAA,IACT,KAAK;AAAA,IACL,cAAc;AAAA,IACd,MAAM,CAAC,YAAY;AAAA,EACrB,CAAC;AAED,MAAI,WAAW,IAAI;AACjB,UAAM,IAAI,MAAM,2BAA2B,YAAY,EAAE;AAAA,EAC3D;AAEA,QAAM,SAAU,MAAM,OAAO,aAAa;AAAA,IACxC,SAAS;AAAA,IACT,KAAK;AAAA,IACL,cAAc;AAAA,IACd,MAAM,CAAC,MAAM;AAAA,EACf,CAAC;AAED,SAAO;AAAA,IACL,IAAI,OAAO,CAAC;AAAA,IACZ,OAAO,OAAO,CAAC;AAAA,IACf,SAAS,OAAO,CAAC;AAAA,IACjB,WAAW,OAAO,CAAC;AAAA,EACrB;AACF;AAOA,SAAS,iBAAiB,WAAwB;AAChD,SAAO,SAAS,GAAG,SAAS,IAAI,UAAU,EAAE;AAC9C;AAgBA,eAAsB,cACpB,YACA,MACA,QACA,eACc;AACd,QAAM,IAAI;AAAA,IACR;AAAA,EAIF;AACF;AAaA,eAAsB,cACpB,WACA,KACiB;AACjB,QAAM,WAAW,IAAI,EAAE;AACvB,MAAI,SAAS,YAAY,MAAM,KAAK,YAAY,EAAG,QAAO;AAE1D,QAAM,SAAS,gBAAgB;AAC/B,QAAM,OAAO,iBAAiB,SAAS;AAEvC,SAAO,OAAO,aAAa;AAAA,IACzB,SAAS;AAAA,IACT,KAAK;AAAA,IACL,cAAc;AAAA,IACd,MAAM,CAAC,MAAM,GAAG;AAAA,EAClB,CAAC;AACH;","names":[]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getConfigRpcUrl
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-6MV4ESXM.js";
|
|
4
4
|
|
|
5
5
|
// src/lib/network.ts
|
|
6
6
|
import { defineChain, parseEther } from "viem";
|
|
@@ -118,4 +118,4 @@ export {
|
|
|
118
118
|
getExplorerUrl,
|
|
119
119
|
isTestnet
|
|
120
120
|
};
|
|
121
|
-
//# sourceMappingURL=chunk-
|
|
121
|
+
//# sourceMappingURL=chunk-LHVSS27T.js.map
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import {
|
|
2
2
|
SHERWOOD
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-UINMHN6S.js";
|
|
4
4
|
import {
|
|
5
5
|
getAccount,
|
|
6
6
|
getPublicClient,
|
|
7
7
|
waitForReceipt,
|
|
8
8
|
writeContractWithRetry
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-2OHX3O55.js";
|
|
10
10
|
import {
|
|
11
11
|
getChain
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-LHVSS27T.js";
|
|
13
13
|
import {
|
|
14
14
|
SYNDICATE_FACTORY_ABI
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-I2PC6TBZ.js";
|
|
16
16
|
|
|
17
17
|
// src/lib/factory.ts
|
|
18
18
|
import { decodeEventLog } from "viem";
|
|
@@ -144,4 +144,4 @@ export {
|
|
|
144
144
|
getActiveFunds,
|
|
145
145
|
updateMetadata
|
|
146
146
|
};
|
|
147
|
-
//# sourceMappingURL=chunk-
|
|
147
|
+
//# sourceMappingURL=chunk-MUINMYCE.js.map
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
EAS_CONTRACTS,
|
|
3
3
|
EAS_SCHEMAS
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-UINMHN6S.js";
|
|
5
5
|
import {
|
|
6
6
|
getAccount,
|
|
7
7
|
getPublicClient,
|
|
8
8
|
waitForReceipt,
|
|
9
9
|
writeContractWithRetry
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-2OHX3O55.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-LHVSS27T.js";
|
|
19
19
|
import {
|
|
20
20
|
EAS_ABI
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-I2PC6TBZ.js";
|
|
22
22
|
|
|
23
23
|
// src/lib/eas.ts
|
|
24
24
|
import { encodeAbiParameters, parseAbiParameters, decodeAbiParameters } from "viem";
|
|
@@ -453,4 +453,4 @@ export {
|
|
|
453
453
|
queryApprovals,
|
|
454
454
|
queryJoinRequests
|
|
455
455
|
};
|
|
456
|
-
//# sourceMappingURL=chunk-
|
|
456
|
+
//# sourceMappingURL=chunk-N3NVFSDQ.js.map
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getLogsChunked
|
|
3
|
+
} from "./chunk-7BMCLMSE.js";
|
|
1
4
|
import {
|
|
2
5
|
TOKENS
|
|
3
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-UINMHN6S.js";
|
|
4
7
|
import {
|
|
5
8
|
GAS_UNITS,
|
|
6
9
|
estimateGasCushion,
|
|
@@ -9,20 +12,20 @@ import {
|
|
|
9
12
|
getWalletClient,
|
|
10
13
|
waitForReceipt,
|
|
11
14
|
writeContractWithRetry
|
|
12
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-2OHX3O55.js";
|
|
13
16
|
import {
|
|
14
17
|
getChain
|
|
15
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-LHVSS27T.js";
|
|
16
19
|
import {
|
|
17
20
|
getChainContracts
|
|
18
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-6MV4ESXM.js";
|
|
19
22
|
import {
|
|
20
23
|
ERC20_ABI,
|
|
21
24
|
SYNDICATE_VAULT_ABI
|
|
22
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-I2PC6TBZ.js";
|
|
23
26
|
|
|
24
27
|
// src/lib/vault.ts
|
|
25
|
-
import { formatUnits } from "viem";
|
|
28
|
+
import { formatUnits, parseAbiItem } from "viem";
|
|
26
29
|
var _vaultOverride = null;
|
|
27
30
|
function setVaultAddress(addr) {
|
|
28
31
|
_vaultOverride = addr;
|
|
@@ -350,23 +353,49 @@ async function getShareBalance(address) {
|
|
|
350
353
|
args: [owner]
|
|
351
354
|
});
|
|
352
355
|
}
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
356
|
+
var AGENT_PAGE_LIMIT = 100n;
|
|
357
|
+
async function getAgentAddresses(vault) {
|
|
358
|
+
const client = getPublicClient();
|
|
359
|
+
const address = vault ?? getVaultAddress();
|
|
360
|
+
const agents = [];
|
|
361
|
+
for (let offset = 0n; ; offset += AGENT_PAGE_LIMIT) {
|
|
362
|
+
const page = await client.readContract({
|
|
363
|
+
address,
|
|
364
|
+
abi: SYNDICATE_VAULT_ABI,
|
|
365
|
+
functionName: "agentsPaginated",
|
|
366
|
+
args: [offset, AGENT_PAGE_LIMIT]
|
|
367
|
+
});
|
|
368
|
+
agents.push(...page);
|
|
369
|
+
if (BigInt(page.length) < AGENT_PAGE_LIMIT) break;
|
|
370
|
+
}
|
|
371
|
+
return agents;
|
|
372
|
+
}
|
|
373
|
+
var ERC4626_FLOW_EVENTS = [
|
|
374
|
+
parseAbiItem(
|
|
375
|
+
"event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares)"
|
|
376
|
+
),
|
|
377
|
+
parseAbiItem(
|
|
378
|
+
"event Withdraw(address indexed sender, address indexed receiver, address indexed owner, uint256 assets, uint256 shares)"
|
|
379
|
+
)
|
|
380
|
+
];
|
|
381
|
+
async function getNetDeposited(vault) {
|
|
382
|
+
const client = getPublicClient();
|
|
383
|
+
const address = vault ?? getVaultAddress();
|
|
384
|
+
const toBlock = await client.getBlockNumber();
|
|
385
|
+
const logs = await getLogsChunked({
|
|
386
|
+
address,
|
|
387
|
+
events: ERC4626_FLOW_EVENTS,
|
|
388
|
+
fromBlock: 0n,
|
|
389
|
+
toBlock
|
|
367
390
|
});
|
|
368
|
-
|
|
369
|
-
|
|
391
|
+
let net = 0n;
|
|
392
|
+
for (const log of logs) {
|
|
393
|
+
const { eventName, args } = log;
|
|
394
|
+
const assets = args?.assets ?? 0n;
|
|
395
|
+
if (eventName === "Deposit") net += assets;
|
|
396
|
+
else if (eventName === "Withdraw") net -= assets;
|
|
397
|
+
}
|
|
398
|
+
return net > 0n ? net : 0n;
|
|
370
399
|
}
|
|
371
400
|
async function approveDepositor(depositor) {
|
|
372
401
|
const hash = await writeContractWithRetry({
|
|
@@ -517,7 +546,8 @@ export {
|
|
|
517
546
|
preflightRedeem,
|
|
518
547
|
redeem,
|
|
519
548
|
getShareBalance,
|
|
520
|
-
|
|
549
|
+
getAgentAddresses,
|
|
550
|
+
getNetDeposited,
|
|
521
551
|
approveDepositor,
|
|
522
552
|
removeDepositor,
|
|
523
553
|
approveDepositors,
|
|
@@ -527,4 +557,4 @@ export {
|
|
|
527
557
|
registerAgent,
|
|
528
558
|
getVaultInfo
|
|
529
559
|
};
|
|
530
|
-
//# sourceMappingURL=chunk-
|
|
560
|
+
//# sourceMappingURL=chunk-RAP6MUMB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/vault.ts"],"sourcesContent":["/**\n * SyndicateVault contract wrapper.\n *\n * The vault is the onchain identity — it holds all positions via delegatecall\n * to a shared BatchExecutorLib. No separate executor contract needed.\n */\n\nimport type { Address, Hex } from \"viem\";\nimport { formatUnits, parseAbiItem } from \"viem\";\nimport { getChain } from \"./network.js\";\nimport {\n getPublicClient,\n getAccount,\n getWalletClient,\n writeContractWithRetry,\n waitForReceipt,\n estimateGasCushion,\n GAS_UNITS,\n} from \"./client.js\";\nimport { SYNDICATE_VAULT_ABI, ERC20_ABI } from \"./abis.js\";\nimport { getLogsChunked } from \"./events.js\";\nimport { getChainContracts } from \"./config.js\";\nimport { TOKENS } from \"./addresses.js\";\n\n// Per-command override (set by --vault flag in index.ts)\nlet _vaultOverride: Address | null = null;\n\nexport function setVaultAddress(addr: Address): void {\n _vaultOverride = addr;\n}\n\nexport function getVaultAddress(): Address {\n // 1. Per-command override (--vault flag)\n if (_vaultOverride) return _vaultOverride;\n\n // 2. Config (~/.sherwood/config.json) — default vault\n const chainId = getChain().id;\n const fromConfig = getChainContracts(chainId).vault;\n if (fromConfig) return fromConfig as Address;\n\n throw new Error(\n \"Vault address not found. Pass --vault <addr> or run 'sherwood config set --vault <addr>'.\",\n );\n}\n\n// ── Asset Helpers ──\n\n/**\n * Read the vault's underlying ERC-20 asset address.\n */\nexport async function getAssetAddress(): Promise<Address> {\n const client = getPublicClient();\n return client.readContract({\n address: getVaultAddress(),\n abi: SYNDICATE_VAULT_ABI,\n functionName: \"asset\",\n }) as Promise<Address>;\n}\n\n/**\n * Read decimals from the vault's underlying asset.\n * Works with any ERC-20 (USDC=6, WETH=18, WBTC=8, etc.).\n */\nexport async function getAssetDecimals(): Promise<number> {\n const client = getPublicClient();\n const asset = await getAssetAddress();\n return client.readContract({\n address: asset,\n abi: ERC20_ABI,\n functionName: \"decimals\",\n }) as Promise<number>;\n}\n\n/**\n * Read the vault owner (OwnableUpgradeable).\n */\nexport async function getVaultOwner(vault?: Address): Promise<Address> {\n const client = getPublicClient();\n return client.readContract({\n address: vault ?? getVaultAddress(),\n abi: SYNDICATE_VAULT_ABI,\n functionName: \"owner\",\n }) as Promise<Address>;\n}\n\n/**\n * Read the vault's agent performance fee (basis points). Owner-set, default\n * 500 (5%). Snapshotted onto a proposal at propose time and clamped to the\n * governor's `maxPerformanceFeeBps` at settlement.\n */\nexport async function getAgentFeeBps(vault?: Address): Promise<bigint> {\n const client = getPublicClient();\n return client.readContract({\n address: vault ?? getVaultAddress(),\n abi: SYNDICATE_VAULT_ABI,\n functionName: \"agentFeeBps\",\n }) as Promise<bigint>;\n}\n\n/**\n * Set the vault's agent performance fee (basis points). Vault owner only;\n * reverts above 1500 (15%).\n */\nexport async function setAgentFeeBps(bps: bigint): Promise<Hex> {\n const hash = await writeContractWithRetry({\n account: getAccount(),\n chain: getChain(),\n address: getVaultAddress(),\n abi: SYNDICATE_VAULT_ABI,\n functionName: \"setAgentFeeBps\",\n args: [bps],\n });\n await waitForReceipt(hash);\n return hash;\n}\n\n// ── WETH ABI (for auto-wrapping ETH) ──\n\nconst WETH_ABI = [\n {\n name: \"deposit\",\n type: \"function\",\n stateMutability: \"payable\",\n inputs: [],\n outputs: [],\n },\n] as const;\n\n// ── Pre-flight Checks ──\n\n/**\n * Validate that a deposit can succeed before submitting any transactions.\n * Throws descriptive errors if any pre-condition fails.\n */\nexport async function preflightDeposit(amount: bigint): Promise<void> {\n const client = getPublicClient();\n const vaultAddress = getVaultAddress();\n const account = getAccount();\n const asset = await getAssetAddress();\n const decimals = await getAssetDecimals();\n\n // 1. Check asset balance\n const balance = (await client.readContract({\n address: asset,\n abi: ERC20_ABI,\n functionName: \"balanceOf\",\n args: [account.address],\n })) as bigint;\n\n if (balance < amount) {\n const symbol = (await client.readContract({\n address: asset,\n abi: ERC20_ABI,\n functionName: \"symbol\",\n })) as string;\n throw new Error(\n `Insufficient ${symbol}. Have ${formatUnits(balance, decimals)}, need ${formatUnits(amount, decimals)}.`,\n );\n }\n\n // 2. Check ETH for gas — cushion derived from live chain gas (approve +\n // deposit), floored per-chain. Never a fixed Base-calibrated constant: on a\n // ~14-wei-base-fee chain 0.0005 ETH was ~7 orders too high and rejected\n // valid deposits client-side.\n const ethBalance = await client.getBalance({ address: account.address });\n const minGas = await estimateGasCushion(GAS_UNITS.approve + GAS_UNITS.deposit);\n if (ethBalance < minGas) {\n throw new Error(\n `Insufficient ETH for gas. Have ${formatUnits(ethBalance, 18)} ETH, need at least ` +\n `${formatUnits(minGas, 18)} ETH. Top up your wallet with ETH on ${getChain().name}.`,\n );\n }\n\n // 3. Check vault not paused\n const paused = (await client.readContract({\n address: vaultAddress,\n abi: SYNDICATE_VAULT_ABI,\n functionName: \"paused\",\n })) as boolean;\n if (paused) {\n throw new Error(\"Vault is paused — deposits are temporarily disabled.\");\n }\n\n // 4. Active proposal: deposits lock UNLESS Lane A (the V2 oracle instant\n // lane, PR #357) is live for the running strategy — then the vault accepts\n // instant entries up to maxDeposit. The old unconditional refusal made Lane\n // A unusable through the CLI (vnet e2e finding, issue #416).\n const locked = (await client.readContract({\n address: vaultAddress,\n abi: SYNDICATE_VAULT_ABI,\n functionName: \"redemptionsLocked\",\n })) as boolean;\n if (locked) {\n const cap = (await client.readContract({\n address: vaultAddress,\n abi: SYNDICATE_VAULT_ABI,\n functionName: \"maxDeposit\",\n args: [account.address],\n })) as bigint;\n if (cap < amount) {\n throw new Error(\n cap === 0n\n ? \"Deposits are locked while a strategy is executing (Lane A unavailable for this strategy). \" +\n \"Queue an async deposit instead:\\n sherwood queue request-deposit --vault <vault> --amount <usdc>\"\n : `Deposit exceeds the Lane A instant cap while a strategy is executing (maxDeposit ${cap.toString()} ` +\n `raw asset units, requested ${amount.toString()}). Reduce the amount or queue it:\\n` +\n \" sherwood queue request-deposit --vault <vault> --amount <usdc>\",\n );\n }\n }\n\n // 5. Check depositor approval (if whitelist vault)\n const openDeposits = (await client.readContract({\n address: vaultAddress,\n abi: SYNDICATE_VAULT_ABI,\n functionName: \"openDeposits\",\n })) as boolean;\n if (!openDeposits) {\n const approved = (await client.readContract({\n address: vaultAddress,\n abi: SYNDICATE_VAULT_ABI,\n functionName: \"isApprovedDepositor\",\n args: [account.address],\n })) as boolean;\n if (!approved) {\n throw new Error(\n \"Your address is not an approved depositor. Ask the vault creator to approve you:\\n sherwood fund approve-depositor --depositor \" +\n account.address,\n );\n }\n }\n}\n\n// ── LP Functions ──\n\n/**\n * Deposit into the vault with optional ETH auto-wrapping for WETH vaults.\n * When `useEth` is true and the vault asset is WETH, wraps ETH first.\n */\nexport async function depositWithEthWrap(amount: bigint): Promise<Hex> {\n const client = getPublicClient();\n const account = getAccount();\n const asset = await getAssetAddress();\n const wethAddress = TOKENS().WETH;\n\n if (asset.toLowerCase() !== wethAddress.toLowerCase()) {\n throw new Error(\"--use-eth is only supported for WETH vaults.\");\n }\n\n // Check current WETH balance — only wrap the shortfall\n const wethBalance = (await client.readContract({\n address: wethAddress,\n abi: ERC20_ABI,\n functionName: \"balanceOf\",\n args: [account.address],\n })) as bigint;\n\n if (wethBalance < amount) {\n const shortfall = amount - wethBalance;\n\n // Verify sufficient ETH to cover shortfall + gas. The gas cushion is\n // derived from live chain gas (wrap + approve + deposit), floored per-chain\n // — not a fixed Base-calibrated constant that would reject valid low-fee\n // deposits (e.g. a 0.00058-ETH wallet wrapping 0.0005 on Robinhood testnet).\n const ethBalance = await client.getBalance({ address: account.address });\n const minGas = await estimateGasCushion(\n GAS_UNITS.wrap + GAS_UNITS.approve + GAS_UNITS.deposit,\n );\n if (ethBalance < shortfall + minGas) {\n throw new Error(\n `Insufficient ETH on ${getChain().name}. Have ${formatUnits(ethBalance, 18)} ETH, need ` +\n `${formatUnits(shortfall, 18)} to wrap + ~${formatUnits(minGas, 18)} for gas.`,\n );\n }\n\n // Wrap ETH → WETH\n const wallet = getWalletClient();\n const wrapHash = await wallet.writeContract({\n address: wethAddress,\n abi: WETH_ABI,\n functionName: \"deposit\",\n args: [],\n value: shortfall,\n account,\n chain: getChain(),\n });\n const wrapReceipt = await client.waitForTransactionReceipt({ hash: wrapHash });\n // A reverted wrap leaves WETH short; the downstream deposit would then\n // revert on transferFrom. Fail loudly here instead.\n if (wrapReceipt.status !== \"success\") {\n throw new Error(`ETH->WETH wrap reverted on-chain (tx ${wrapHash}).`);\n }\n }\n\n // Proceed with normal deposit\n return deposit(amount);\n}\n\n/**\n * Deposit into the vault. Handles approval + deposit for the vault's asset.\n */\nexport async function deposit(amount: bigint): Promise<Hex> {\n const client = getPublicClient();\n const vaultAddress = getVaultAddress();\n const account = getAccount();\n const asset = await getAssetAddress();\n\n // Check existing allowance — skip approve if sufficient\n const currentAllowance = (await client.readContract({\n address: asset,\n abi: ERC20_ABI,\n functionName: \"allowance\",\n args: [account.address, vaultAddress],\n })) as bigint;\n\n if (currentAllowance < amount) {\n const approveHash = await writeContractWithRetry({\n account,\n chain: getChain(),\n address: asset,\n abi: ERC20_ABI,\n functionName: \"approve\",\n args: [vaultAddress, amount],\n });\n // Wait for approve to confirm before deposit — prevents nonce collision\n const approveReceipt = await waitForReceipt(approveHash);\n // A reverted approve leaves allowance below `amount`; the deposit's\n // transferFrom would then revert. Surface it here.\n if (approveReceipt.status !== \"success\") {\n throw new Error(`Asset approve reverted on-chain (tx ${approveHash}).`);\n }\n }\n\n // Snapshot share balance before deposit so we can assert shares were minted.\n const sharesBefore = (await client.readContract({\n address: vaultAddress,\n abi: SYNDICATE_VAULT_ABI,\n functionName: \"balanceOf\",\n args: [account.address],\n })) as bigint;\n\n // Deposit — retry wrapper handles nonce/gas automatically\n const depositHash = await writeContractWithRetry({\n account,\n chain: getChain(),\n address: vaultAddress,\n abi: SYNDICATE_VAULT_ABI,\n functionName: \"deposit\",\n args: [amount, account.address],\n });\n const receipt = await waitForReceipt(depositHash);\n\n // A mined-but-reverted deposit is NOT a success. viem's\n // waitForTransactionReceipt resolves even for `status: \"reverted\"` txs, so\n // without this guard a reverted deposit would be reported as a successful\n // one and the caller would believe it holds shares it does not.\n if (receipt.status !== \"success\") {\n throw new Error(\n `Deposit transaction reverted on-chain (tx ${depositHash}). No shares were minted.`,\n );\n }\n\n // Confirm shares were actually minted to the receiver. Guards against a\n // silent zero-share mint (e.g. rounding on an inflated vault) that would\n // otherwise pass unnoticed because the tx did not revert.\n const sharesAfter = (await client.readContract({\n address: vaultAddress,\n abi: SYNDICATE_VAULT_ABI,\n functionName: \"balanceOf\",\n args: [account.address],\n })) as bigint;\n if (sharesAfter <= sharesBefore) {\n throw new Error(\n `Deposit confirmed on-chain (tx ${depositHash}) but minted 0 shares ` +\n `(balance ${sharesBefore} -> ${sharesAfter}). Aborting to avoid reporting a phantom deposit.`,\n );\n }\n\n return depositHash;\n}\n\n// ── Redeem ──\n\n/**\n * Pre-flight check for redeem. Validates that the caller has enough shares\n * and that the vault allows redemption right now.\n */\nexport async function preflightRedeem(shares: bigint): Promise<void> {\n const client = getPublicClient();\n const vaultAddress = getVaultAddress();\n const account = getAccount();\n\n if (shares === 0n) {\n throw new Error(\"No shares to redeem.\");\n }\n\n // 1. Check share balance\n const balance = (await client.readContract({\n address: vaultAddress,\n abi: SYNDICATE_VAULT_ABI,\n functionName: \"balanceOf\",\n args: [account.address],\n })) as bigint;\n\n if (balance < shares) {\n throw new Error(\n `Insufficient shares. Have ${balance.toString()}, need ${shares.toString()}.`,\n );\n }\n\n // 2. Check vault not paused\n const paused = (await client.readContract({\n address: vaultAddress,\n abi: SYNDICATE_VAULT_ABI,\n functionName: \"paused\",\n })) as boolean;\n if (paused) {\n throw new Error(\"Vault is paused — redemptions are temporarily disabled.\");\n }\n\n // 3. Active proposal: redemptions lock UNLESS Lane A (the V2 oracle instant\n // lane, PR #357) is live — then instant exits are allowed up to maxRedeem.\n // The old unconditional refusal made Lane A unusable through the CLI (vnet\n // e2e finding, issue #416).\n const locked = (await client.readContract({\n address: vaultAddress,\n abi: SYNDICATE_VAULT_ABI,\n functionName: \"redemptionsLocked\",\n })) as boolean;\n if (locked) {\n const cap = (await client.readContract({\n address: vaultAddress,\n abi: SYNDICATE_VAULT_ABI,\n functionName: \"maxRedeem\",\n args: [account.address],\n })) as bigint;\n if (cap < shares) {\n throw new Error(\n cap === 0n\n ? \"Redemptions are locked while a strategy is executing (Lane A unavailable for this strategy). \" +\n \"Queue an async redeem instead:\\n sherwood queue request-redeem --vault <vault> --shares <raw-shares>\"\n : `Redeem exceeds the Lane A instant cap while a strategy is executing (maxRedeem ${cap.toString()} ` +\n `raw shares, requested ${shares.toString()}). Reduce the share amount or queue it:\\n` +\n \" sherwood queue request-redeem --vault <vault> --shares <raw-shares>\",\n );\n }\n }\n\n // 4. Check ETH for gas — cushion derived from live chain gas (redeem),\n // floored per-chain; never a fixed Base-calibrated constant.\n const ethBalance = await client.getBalance({ address: account.address });\n const minGas = await estimateGasCushion(GAS_UNITS.redeem);\n if (ethBalance < minGas) {\n throw new Error(\n `Insufficient ETH for gas on ${getChain().name}. Have ${formatUnits(ethBalance, 18)} ETH, ` +\n `need at least ${formatUnits(minGas, 18)} ETH.`,\n );\n }\n}\n\n/**\n * Redeem shares for the underlying asset (standard ERC-4626 redeem).\n * Returns the tx hash and the assets received.\n */\nexport async function redeem(\n shares: bigint,\n receiver?: Address,\n): Promise<{ hash: Hex; assetsOut: bigint }> {\n const client = getPublicClient();\n const vaultAddress = getVaultAddress();\n const account = getAccount();\n const to = receiver ?? account.address;\n\n // Preview so we can report assets received\n const assetsOut = (await client.readContract({\n address: vaultAddress,\n abi: SYNDICATE_VAULT_ABI,\n functionName: \"previewRedeem\",\n args: [shares],\n })) as bigint;\n\n const hash = await writeContractWithRetry({\n account,\n chain: getChain(),\n address: vaultAddress,\n abi: SYNDICATE_VAULT_ABI,\n functionName: \"redeem\",\n args: [shares, to, account.address],\n });\n await waitForReceipt(hash);\n return { hash, assetsOut };\n}\n\n/**\n * Read the current share balance for an address (defaults to the caller).\n */\nexport async function getShareBalance(address?: Address): Promise<bigint> {\n const client = getPublicClient();\n const owner = address ?? getAccount().address;\n return client.readContract({\n address: getVaultAddress(),\n abi: SYNDICATE_VAULT_ABI,\n functionName: \"balanceOf\",\n args: [owner],\n }) as Promise<bigint>;\n}\n\n// NOTE: there is deliberately NO `executeBatch` wrapper here. The vault's\n// owner-direct `executeBatch` was removed on-chain (V-C3) — the only batch\n// path is the governor-driven `executeGovernorBatch` (proposal lifecycle).\n\n// ── Agent Reads ──\n\n/** Mirrors SyndicateVault.MAX_PAGE_LIMIT — the hard clamp on page size. */\nconst AGENT_PAGE_LIMIT = 100n;\n\n/**\n * Read the full registered-agent set by iterating `agentsPaginated`\n * (the vault's `getAgentAddresses` was replaced by the paginated view, V-M3).\n * Starts at offset 0 and advances by the page limit until a short page.\n */\nexport async function getAgentAddresses(vault?: Address): Promise<Address[]> {\n const client = getPublicClient();\n const address = vault ?? getVaultAddress();\n const agents: Address[] = [];\n for (let offset = 0n; ; offset += AGENT_PAGE_LIMIT) {\n const page = (await client.readContract({\n address,\n abi: SYNDICATE_VAULT_ABI,\n functionName: \"agentsPaginated\",\n args: [offset, AGENT_PAGE_LIMIT],\n })) as Address[];\n agents.push(...page);\n if (BigInt(page.length) < AGENT_PAGE_LIMIT) break;\n }\n return agents;\n}\n\n// ── Principal (event-derived) ──\n\n/** ERC-4626 flow events scanned by getNetDeposited (parseAbiItem form for getLogs). */\nconst ERC4626_FLOW_EVENTS = [\n parseAbiItem(\n \"event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares)\",\n ),\n parseAbiItem(\n \"event Withdraw(address indexed sender, address indexed receiver, address indexed owner, uint256 assets, uint256 shares)\",\n ),\n] as const;\n\n/**\n * Net deposited principal, derived from the ERC-4626 event history:\n * sum(Deposit.assets) − sum(Withdraw.assets), floored at 0. Scanned 0→latest\n * through `getLogsChunked` (≤10,000 blocks per eth_getLogs, the lib/events.ts\n * precedent) so range-capped public RPCs neither error nor truncate on\n * long-lived vaults.\n *\n * DISPLAY-GRADE ESTIMATE ONLY — the vault's `totalDeposited` view was\n * removed on-chain (the V2 vault tracks no principal) and the event history\n * has hard blind spots, not just noise:\n * - Lane-B settlements (`settleDeposit` / `settleRedeem`) and\n * strategy-serviced custody flows (`strategyMint` / `strategyBurn`) use\n * raw `_mint`/`_burn` with NO ERC-4626 Deposit/Withdraw events — those\n * flows are entirely invisible to this estimate.\n * - Withdrawals include realized profit, so on a profitable vault the net\n * undershoots true remaining principal (and can go negative — hence the\n * floor).\n * Do not use as an accounting source of truth.\n */\nexport async function getNetDeposited(vault?: Address): Promise<bigint> {\n const client = getPublicClient();\n const address = vault ?? getVaultAddress();\n const toBlock = await client.getBlockNumber();\n const logs = await getLogsChunked({\n address,\n events: ERC4626_FLOW_EVENTS,\n fromBlock: 0n,\n toBlock,\n });\n let net = 0n;\n for (const log of logs) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const { eventName, args } = log as any;\n const assets: bigint = args?.assets ?? 0n;\n if (eventName === \"Deposit\") net += assets;\n else if (eventName === \"Withdraw\") net -= assets;\n }\n return net > 0n ? net : 0n;\n}\n\n// ── Depositor Management ──\n\n/**\n * Approve a depositor address (owner only).\n */\nexport async function approveDepositor(depositor: Address): Promise<Hex> {\n const hash = await writeContractWithRetry({\n account: getAccount(),\n chain: getChain(),\n address: getVaultAddress(),\n abi: SYNDICATE_VAULT_ABI,\n functionName: \"approveDepositor\",\n args: [depositor],\n });\n await waitForReceipt(hash);\n return hash;\n}\n\n/**\n * Remove a depositor from the whitelist (owner only).\n */\nexport async function removeDepositor(depositor: Address): Promise<Hex> {\n const hash = await writeContractWithRetry({\n account: getAccount(),\n chain: getChain(),\n address: getVaultAddress(),\n abi: SYNDICATE_VAULT_ABI,\n functionName: \"removeDepositor\",\n args: [depositor],\n });\n await waitForReceipt(hash);\n return hash;\n}\n\n/**\n * Approve multiple depositors in a batch (owner only).\n */\nexport async function approveDepositors(depositors: Address[]): Promise<Hex> {\n const hash = await writeContractWithRetry({\n account: getAccount(),\n chain: getChain(),\n address: getVaultAddress(),\n abi: SYNDICATE_VAULT_ABI,\n functionName: \"approveDepositors\",\n args: [depositors],\n });\n await waitForReceipt(hash);\n return hash;\n}\n\n/**\n * Check if an address is a registered agent on the vault.\n */\nexport async function isAgent(agentAddress: Address): Promise<boolean> {\n const client = getPublicClient();\n return client.readContract({\n address: getVaultAddress(),\n abi: SYNDICATE_VAULT_ABI,\n functionName: \"isAgent\",\n args: [agentAddress],\n }) as Promise<boolean>;\n}\n\n/**\n * Check if an address is an approved depositor.\n */\nexport async function isApprovedDepositor(depositor: Address): Promise<boolean> {\n const client = getPublicClient();\n return client.readContract({\n address: getVaultAddress(),\n abi: SYNDICATE_VAULT_ABI,\n functionName: \"isApprovedDepositor\",\n args: [depositor],\n }) as Promise<boolean>;\n}\n\n/**\n * Get LP share balance and asset value.\n */\nexport async function getBalance(address?: Address): Promise<{\n shares: bigint;\n assetsValue: string;\n percentOfVault: string;\n}> {\n const client = getPublicClient();\n const vaultAddress = getVaultAddress();\n const account = address || getAccount().address;\n\n const [shares, totalSupply] = await Promise.all([\n client.readContract({\n address: vaultAddress,\n abi: SYNDICATE_VAULT_ABI,\n functionName: \"balanceOf\",\n args: [account],\n }) as Promise<bigint>,\n client.readContract({\n address: vaultAddress,\n abi: SYNDICATE_VAULT_ABI,\n functionName: \"totalSupply\",\n }) as Promise<bigint>,\n ]);\n\n let assetsValue = 0n;\n if (shares > 0n) {\n assetsValue = (await client.readContract({\n address: vaultAddress,\n abi: SYNDICATE_VAULT_ABI,\n functionName: \"convertToAssets\",\n args: [shares],\n })) as bigint;\n }\n\n const percent =\n totalSupply > 0n ? ((Number(shares) / Number(totalSupply)) * 100).toFixed(2) : \"0.00\";\n\n const decimals = await getAssetDecimals();\n\n return {\n shares,\n assetsValue: formatUnits(assetsValue, decimals),\n percentOfVault: `${percent}%`,\n };\n}\n\n// ── Agent Management ──\n\n/**\n * Register a new agent (owner only). Requires ERC-8004 agent identity.\n */\nexport async function registerAgent(\n agentId: bigint,\n agentAddress: Address,\n): Promise<Hex> {\n const hash = await writeContractWithRetry({\n account: getAccount(),\n chain: getChain(),\n address: getVaultAddress(),\n abi: SYNDICATE_VAULT_ABI,\n functionName: \"registerAgent\",\n args: [agentId, agentAddress],\n });\n await waitForReceipt(hash);\n return hash;\n}\n\n// ── Views ──\n\nexport interface VaultInfo {\n address: Address;\n totalAssets: string;\n agentCount: bigint;\n redemptionsLocked: boolean;\n managementFeeBps: bigint;\n}\n\n/**\n * Get vault overview info.\n */\nexport async function getVaultInfo(): Promise<VaultInfo> {\n const client = getPublicClient();\n const vaultAddress = getVaultAddress();\n\n const [totalAssets, agentCount, redemptionsLocked, managementFeeBps, decimals] =\n await Promise.all([\n client.readContract({\n address: vaultAddress,\n abi: SYNDICATE_VAULT_ABI,\n functionName: \"totalAssets\",\n }) as Promise<bigint>,\n client.readContract({\n address: vaultAddress,\n abi: SYNDICATE_VAULT_ABI,\n functionName: \"getAgentCount\",\n }) as Promise<bigint>,\n client.readContract({\n address: vaultAddress,\n abi: SYNDICATE_VAULT_ABI,\n functionName: \"redemptionsLocked\",\n }) as Promise<boolean>,\n client.readContract({\n address: vaultAddress,\n abi: SYNDICATE_VAULT_ABI,\n functionName: \"managementFeeBps\",\n }) as Promise<bigint>,\n getAssetDecimals(),\n ]);\n\n return {\n address: vaultAddress,\n totalAssets: formatUnits(totalAssets, decimals),\n agentCount,\n redemptionsLocked,\n managementFeeBps,\n };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,23 +1,25 @@
|
|
|
1
1
|
import {
|
|
2
2
|
SHERWOOD
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-UINMHN6S.js";
|
|
4
4
|
import {
|
|
5
5
|
getAccount,
|
|
6
6
|
getPublicClient,
|
|
7
7
|
waitForReceipt,
|
|
8
8
|
writeContractWithRetry
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-2OHX3O55.js";
|
|
10
10
|
import {
|
|
11
11
|
getChain
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-LHVSS27T.js";
|
|
13
13
|
import {
|
|
14
14
|
PROTOCOL_CONFIG_ABI,
|
|
15
15
|
SYNDICATE_FACTORY_ABI,
|
|
16
16
|
SYNDICATE_GOVERNOR_ABI
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-I2PC6TBZ.js";
|
|
18
18
|
|
|
19
19
|
// src/lib/governor.ts
|
|
20
20
|
import { parseEventLogs } from "viem";
|
|
21
|
+
|
|
22
|
+
// src/lib/generated/proposal-state.ts
|
|
21
23
|
var PROPOSAL_STATES = [
|
|
22
24
|
"Draft",
|
|
23
25
|
"Pending",
|
|
@@ -40,6 +42,8 @@ var PROPOSAL_STATE = {
|
|
|
40
42
|
Settled: 7,
|
|
41
43
|
Cancelled: 8
|
|
42
44
|
};
|
|
45
|
+
|
|
46
|
+
// src/lib/governor.ts
|
|
43
47
|
var VOTE_TYPE = {
|
|
44
48
|
For: 0,
|
|
45
49
|
Against: 1,
|
|
@@ -425,4 +429,4 @@ export {
|
|
|
425
429
|
vetoProposal,
|
|
426
430
|
setProtocolFeeBps
|
|
427
431
|
};
|
|
428
|
-
//# sourceMappingURL=chunk-
|
|
432
|
+
//# sourceMappingURL=chunk-RE3PPAXZ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/governor.ts","../src/lib/generated/proposal-state.ts"],"sourcesContent":["/**\n * Governor contract wrapper — reads/writes to SyndicateGovernor.\n *\n * Per-vault governor design: the factory deploys ONE governor per vault\n * (BeaconProxy). Every helper takes the vault address and resolves its\n * governor via `factory.governorOf(vault)` (memoized per chain+vault —\n * the binding is set once at createSyndicate and never changes).\n *\n * Protocol-wide fee parameters (protocol/guardian fee bps + recipients)\n * live on the separate ProtocolConfig contract, resolved via\n * `factory.protocolConfig()`.\n */\n\nimport type { Address, Hex, Log } from \"viem\";\nimport { parseEventLogs } from \"viem\";\nimport { getPublicClient, getAccount, writeContractWithRetry, waitForReceipt } from \"./client.js\";\nimport { getChain } from \"./network.js\";\nimport { SHERWOOD } from \"./addresses.js\";\nimport { SYNDICATE_GOVERNOR_ABI, SYNDICATE_FACTORY_ABI, PROTOCOL_CONFIG_ABI } from \"./abis.js\";\nimport { PROPOSAL_STATE, PROPOSAL_STATES } from \"./generated/proposal-state.js\";\n\n// ── Types ──\n\nexport interface GovernorParams {\n votingPeriod: bigint;\n executionWindow: bigint;\n vetoThresholdBps: bigint;\n maxPerformanceFeeBps: bigint;\n cooldownPeriod: bigint;\n collaborationWindow: bigint;\n maxCoProposers: bigint;\n minStrategyDuration: bigint;\n maxStrategyDuration: bigint;\n}\n\nexport interface StrategyProposal {\n id: bigint;\n proposer: Address;\n vault: Address;\n /** Strategy contract address whose `positionValue()` the vault polls\n * for live NAV. Set at propose time, immutable thereafter. address(0)\n * for queue-only proposals (no live NAV). */\n strategy: Address;\n metadataURI: string;\n /** Agent fee (bps) snapshotted from the vault's `agentFeeBps` at propose. */\n performanceFeeBps: bigint;\n strategyDuration: bigint;\n votesFor: bigint;\n votesAgainst: bigint;\n votesAbstain: bigint;\n snapshotTimestamp: bigint;\n voteEnd: bigint;\n reviewEnd: bigint;\n executeBy: bigint;\n executedAt: bigint;\n state: number;\n vetoThresholdBps: bigint;\n /** Fee snapshot taken from ProtocolConfig at propose time (PR #421). These\n * four fields sit between `vetoThresholdBps` and `selfManagesFees` in the\n * on-chain `StrategyProposal` struct — omitting them corrupts tuple decode. */\n snapshotProtocolFeeBps: bigint;\n snapshotProtocolFeeRecipient: Address;\n snapshotGuardianFeeBps: bigint;\n snapshotGuardiansFeeRecipient: Address;\n /** `IStrategy.selfManagesFees()` snapshotted at propose (PR #388 #2); read\n * from storage at settle so it can't flip mid-flight or brick settlement. */\n selfManagesFees: boolean;\n}\n\nexport interface CoProposer {\n agent: Address;\n splitBps: bigint;\n}\n\nexport interface BatchCall {\n target: Address;\n data: Hex;\n value: bigint;\n}\n\n// ProposalState ordering is code-generated from the Solidity enum\n// (contracts/src/interfaces/ISyndicateGovernor.sol) — `npm run codegen`.\n// History: PR #229 inserted GuardianReview at index 2 and this hand-kept\n// mirror drifted for ~2 months, mislabeling Approved (3) as Rejected and\n// making `proposal execute` reject valid approved proposals. The generated\n// module (checked by codegen-drift.test.ts + CI) makes that impossible.\nexport { PROPOSAL_STATE, PROPOSAL_STATES };\n\nexport const VOTE_TYPE = {\n For: 0,\n Against: 1,\n Abstain: 2,\n} as const;\n\n// ── Client-side action gates (mirror SyndicateGovernor) ──\n//\n// The governor's mutating entrypoints resolve state INLINE and can act on a\n// state the read-only `getProposalState` view is still reporting as\n// GuardianReview. The client gates below reproduce that divergence so the CLI\n// stops refusing txs the contract would accept (issue #452).\n\n/** Result of the `proposal execute` client gate. */\nexport type ExecuteGate =\n | { kind: \"send\" } // state == Approved — straightforward execute.\n | { kind: \"send-self-resolve\" } // GuardianReview, window elapsed, still within\n // the execution window — executeProposal\n // self-resolves the (cold-start) review inline.\n | { kind: \"refuse-review-open\" } // GuardianReview, review window still open — the\n // tx WOULD revert (ProposalNotApproved).\n | { kind: \"refuse-expired\" } // GuardianReview past executeBy — the inline\n // self-resolve maps to Expired, tx WOULD revert.\n | { kind: \"refuse-state\" }; // any other non-executable state.\n\n/**\n * Decide whether `executeProposal(id)` should be broadcast.\n *\n * Mirrors `SyndicateGovernor.executeProposal` (contracts/src/SyndicateGovernor.sol:342)\n * vs. the `getProposalState` view:\n * - The view (`_resolveStateView` @824 / `_resolveAfterVote` @865) keeps\n * reporting `GuardianReview` once the review window elapses but the registry\n * has not cached a resolution — a zero-guardian / never-opened cold-start\n * review NEVER auto-opens, so the view is stuck there indefinitely.\n * - `executeProposal` runs the MUTATING `_resolveState` (@789) which, when the\n * window elapsed (`now > reviewEnd`), calls `registry.resolveReview` inline\n * (cold-start ⇒ blocked=false) and maps to Approved when `now <= executeBy`\n * (else Expired) — then executes in the same tx.\n * Invariant `voteEnd < reviewEnd < executeBy` (@528-530) holds for any past-vote\n * proposal, so `reviewEnd`/`executeBy` are always populated in the GuardianReview\n * branch.\n *\n * `now` MUST be chain time (latest block timestamp), not wall-clock — on a\n * time-warped vnet the two diverge and the contract compares against chain time.\n */\nexport function evaluateExecuteGate(args: {\n state: number;\n reviewEnd: bigint;\n executeBy: bigint;\n now: bigint;\n}): ExecuteGate {\n const { state, reviewEnd, executeBy, now } = args;\n if (state === PROPOSAL_STATE.Approved) return { kind: \"send\" };\n if (state === PROPOSAL_STATE.GuardianReview) {\n if (now <= reviewEnd) return { kind: \"refuse-review-open\" };\n if (now > executeBy) return { kind: \"refuse-expired\" };\n return { kind: \"send-self-resolve\" };\n }\n return { kind: \"refuse-state\" };\n}\n\n/**\n * Classification for the `resolve-reviews` keeper.\n * - `resolvable`: an OPENED, unresolved review past its window — needs a real\n * `resolveReview` tx (computes block quorum, may slash approvers).\n * - `cold-start`: an UNOPENED, unresolved review past its window — the\n * zero-guardian case. `resolveReview` would only mark it resolved/not-blocked\n * (GuardianRegistry.resolveReview @639-643), which `executeProposal`\n * already does inline, so the keeper should report it (pointing at\n * `proposal execute`) rather than spend a redundant tx.\n * - `none`: not past window yet, or already resolved.\n */\nexport type ReviewResolveClass = \"resolvable\" | \"cold-start\" | \"none\";\n\nexport function classifyReview(args: {\n opened: boolean;\n resolved: boolean;\n reviewEnd: bigint;\n now: bigint;\n}): ReviewResolveClass {\n const { opened, resolved, reviewEnd, now } = args;\n const pastWindow = reviewEnd > 0n && now >= reviewEnd;\n if (!pastWindow || resolved) return \"none\";\n return opened ? \"resolvable\" : \"cold-start\";\n}\n\n// ── Duration parser ──\n\nexport function parseDuration(input: string): bigint {\n const match = input.match(/^(\\d+)(d|h|m|s)?$/);\n if (!match) throw new Error(`Invalid duration: ${input}`);\n const value = BigInt(match[1]);\n switch (match[2]) {\n case \"d\":\n return value * 86400n;\n case \"h\":\n return value * 3600n;\n case \"m\":\n return value * 60n;\n case \"s\":\n case undefined:\n return value;\n default:\n throw new Error(`Unknown duration unit: ${match[2]}`);\n }\n}\n\n// ── Address helpers ──\n\n// governorOf(vault) is set once at createSyndicate and never rebinds, so\n// it is safe to memoize per chain+vault for the lifetime of the process.\nconst governorCache = new Map<string, Address>();\n\n/** Resolve the per-vault governor via `factory.governorOf(vault)`. */\nexport async function getGovernorOf(vault: Address): Promise<Address> {\n const key = `${getChain().id}:${vault.toLowerCase()}`;\n const cached = governorCache.get(key);\n if (cached) return cached;\n\n const client = getPublicClient();\n const governor = await client.readContract({\n address: SHERWOOD().FACTORY,\n abi: SYNDICATE_FACTORY_ABI,\n functionName: \"governorOf\",\n args: [vault],\n }) as Address;\n\n if (governor === \"0x0000000000000000000000000000000000000000\") {\n throw new Error(`No governor registered for vault ${vault} — is it a factory-created vault?`);\n }\n\n governorCache.set(key, governor);\n return governor;\n}\n\n// ProtocolConfig is a protocol-wide singleton behind the factory — same\n// set-once semantics as governorOf, memoized per chain.\nconst protocolConfigCache = new Map<number, Address>();\n\n/** Resolve the ProtocolConfig address via `factory.protocolConfig()`. */\nexport async function getProtocolConfigAddress(): Promise<Address> {\n const chainId = getChain().id;\n const cached = protocolConfigCache.get(chainId);\n if (cached) return cached;\n\n const client = getPublicClient();\n const config = await client.readContract({\n address: SHERWOOD().FACTORY,\n abi: SYNDICATE_FACTORY_ABI,\n functionName: \"protocolConfig\",\n }) as Address;\n\n protocolConfigCache.set(chainId, config);\n return config;\n}\n\n// ── Read helpers ──\n\nexport async function getGovernorParams(vault: Address): Promise<GovernorParams> {\n const client = getPublicClient();\n const result = await client.readContract({\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"getGovernorParams\",\n }) as {\n votingPeriod: bigint;\n executionWindow: bigint;\n vetoThresholdBps: bigint;\n maxPerformanceFeeBps: bigint;\n cooldownPeriod: bigint;\n collaborationWindow: bigint;\n maxCoProposers: bigint;\n minStrategyDuration: bigint;\n maxStrategyDuration: bigint;\n };\n return result;\n}\n\nexport async function getProposal(vault: Address, id: bigint): Promise<StrategyProposal> {\n const client = getPublicClient();\n const result = await client.readContract({\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"getProposal\",\n args: [id],\n }) as StrategyProposal;\n return result;\n}\n\nexport async function getProposalState(vault: Address, id: bigint): Promise<number> {\n const client = getPublicClient();\n return client.readContract({\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"getProposalState\",\n args: [id],\n }) as Promise<number>;\n}\n\nexport async function proposalCount(vault: Address): Promise<bigint> {\n const client = getPublicClient();\n return client.readContract({\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"proposalCount\",\n }) as Promise<bigint>;\n}\n\nexport async function getVoteWeight(vault: Address, proposalId: bigint, voter: Address): Promise<bigint> {\n const client = getPublicClient();\n return client.readContract({\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"getVoteWeight\",\n args: [proposalId, voter],\n }) as Promise<bigint>;\n}\n\nexport async function hasVoted(vault: Address, proposalId: bigint, voter: Address): Promise<boolean> {\n const client = getPublicClient();\n return client.readContract({\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"hasVoted\",\n args: [proposalId, voter],\n }) as Promise<boolean>;\n}\n\n// `getProposalCalls` (concat of execute + settle) was dropped in V1.5\n// to reclaim governor bytecode under EIP-170. Use `getExecuteCalls`\n// + `getSettlementCalls` instead — same data, no on-chain copy loop.\n\nexport async function getExecuteCalls(vault: Address, proposalId: bigint): Promise<BatchCall[]> {\n const client = getPublicClient();\n const result = await client.readContract({\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"getExecuteCalls\",\n args: [proposalId],\n }) as { target: Address; data: Hex; value: bigint }[];\n return result.map((c) => ({ target: c.target, data: c.data, value: c.value }));\n}\n\nexport async function getSettlementCalls(vault: Address, proposalId: bigint): Promise<BatchCall[]> {\n const client = getPublicClient();\n const result = await client.readContract({\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"getSettlementCalls\",\n args: [proposalId],\n }) as { target: Address; data: Hex; value: bigint }[];\n return result.map((c) => ({ target: c.target, data: c.data, value: c.value }));\n}\n\n// Per-vault governor: `getRegisteredVaults` / `isRegisteredVault` were\n// removed on-chain — a governor serves exactly one vault (`governor.vault()`).\n// Enumerate vaults via the factory (`getAllActiveSyndicates`) instead.\n\nexport async function getActiveProposal(vault: Address): Promise<bigint> {\n const client = getPublicClient();\n return client.readContract({\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"getActiveProposal\",\n }) as Promise<bigint>;\n}\n\nexport async function getCooldownEnd(vault: Address): Promise<bigint> {\n const client = getPublicClient();\n return client.readContract({\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"getCooldownEnd\",\n }) as Promise<bigint>;\n}\n\nexport async function openProposalCount(vault: Address): Promise<bigint> {\n const client = getPublicClient();\n return client.readContract({\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"openProposalCount\",\n }) as Promise<bigint>;\n}\n\nexport async function getCapitalSnapshot(vault: Address, proposalId: bigint): Promise<bigint> {\n const client = getPublicClient();\n return client.readContract({\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"getCapitalSnapshot\",\n args: [proposalId],\n }) as Promise<bigint>;\n}\n\n/**\n * Extract proposalId from ProposalCreated event logs.\n * Returns undefined if the event is not found or parsing fails.\n */\nexport function parseProposalIdFromLogs(logs: Log[]): bigint | undefined {\n try {\n const parsed = parseEventLogs({\n abi: SYNDICATE_GOVERNOR_ABI,\n logs,\n eventName: \"ProposalCreated\",\n });\n return parsed[0]?.args.proposalId;\n } catch {\n return undefined;\n }\n}\n\n// ── Write helpers ──\n\nexport async function propose(\n vault: Address,\n strategy: Address,\n metadataURI: string,\n strategyDuration: bigint,\n executeCalls: BatchCall[],\n settlementCalls: BatchCall[],\n coProposers: CoProposer[] = [],\n): Promise<{ hash: Hex; proposalId: bigint }> {\n const hash = await writeContractWithRetry({\n account: getAccount(),\n chain: getChain(),\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"propose\",\n args: [vault, strategy, metadataURI, strategyDuration, executeCalls, settlementCalls, coProposers],\n });\n\n const receipt = await waitForReceipt(hash);\n\n // Parse proposalId from the ProposalCreated event in the receipt logs.\n // Falls back to proposalCount() if event parsing fails.\n let proposalId = parseProposalIdFromLogs(receipt.logs);\n if (proposalId === undefined) {\n try {\n proposalId = await proposalCount(vault);\n } catch {\n proposalId = 0n;\n }\n }\n\n return { hash: receipt.transactionHash, proposalId };\n}\n\nexport async function vote(vault: Address, proposalId: bigint, support: number): Promise<Hex> {\n const hash = await writeContractWithRetry({\n account: getAccount(),\n chain: getChain(),\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"vote\",\n args: [proposalId, support],\n });\n const receipt = await waitForReceipt(hash);\n return receipt.transactionHash;\n}\n\nexport async function executeProposal(vault: Address, proposalId: bigint): Promise<Hex> {\n const hash = await writeContractWithRetry({\n account: getAccount(),\n chain: getChain(),\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"executeProposal\",\n args: [proposalId],\n });\n const receipt = await waitForReceipt(hash);\n return receipt.transactionHash;\n}\n\n/**\n * Walk a proposal's executeCalls and pick the strategy clone — the\n * target of the call whose selector matches `BaseStrategy.execute()`\n * (0x61461954). This is the canonical entry point that every Sherwood\n * strategy template inherits from BaseStrategy, so it's a reliable\n * marker even across template families (Moonwell / Aerodrome /\n * Hyperliquid / Mamo / Venice / Portfolio).\n *\n * Returns null when no execute() call is present (e.g. proposals that\n * only do approves and direct ERC-20 transfers without a strategy).\n */\nexport function detectStrategyAdapter(\n calls: { target: Address; data: Hex; value: bigint }[],\n): Address | null {\n const STRATEGY_EXECUTE_SELECTOR = \"0x61461954\";\n for (const call of calls) {\n if (call.data.slice(0, 10).toLowerCase() === STRATEGY_EXECUTE_SELECTOR) {\n return call.target;\n }\n }\n return null;\n}\n\nexport async function settleProposal(vault: Address, proposalId: bigint): Promise<Hex> {\n const hash = await writeContractWithRetry({\n account: getAccount(),\n chain: getChain(),\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"settleProposal\",\n args: [proposalId],\n });\n const receipt = await waitForReceipt(hash);\n return receipt.transactionHash;\n}\n\nexport async function emergencySettle(vault: Address, proposalId: bigint, calls: BatchCall[]): Promise<Hex> {\n const hash = await writeContractWithRetry({\n account: getAccount(),\n chain: getChain(),\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"emergencySettleWithCalls\",\n args: [proposalId, calls],\n });\n const receipt = await waitForReceipt(hash);\n return receipt.transactionHash;\n}\n\nexport async function cancelProposal(vault: Address, proposalId: bigint): Promise<Hex> {\n const hash = await writeContractWithRetry({\n account: getAccount(),\n chain: getChain(),\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"cancelProposal\",\n args: [proposalId],\n });\n const receipt = await waitForReceipt(hash);\n return receipt.transactionHash;\n}\n\nexport async function emergencyCancel(vault: Address, proposalId: bigint): Promise<Hex> {\n const hash = await writeContractWithRetry({\n account: getAccount(),\n chain: getChain(),\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"emergencyCancel\",\n args: [proposalId],\n });\n const receipt = await waitForReceipt(hash);\n return receipt.transactionHash;\n}\n\n// ── Parameter setters ──\n//\n// Per-vault governor: governance parameters are per-vault now, set by the\n// VAULT OWNER on that vault's governor. Setters revert with\n// `ParamsFrozenDuringProposal` while any proposal is open on the vault.\n\ntype GovernorParamSetter =\n | \"setVotingPeriod\"\n | \"setExecutionWindow\"\n | \"setVetoThresholdBps\"\n | \"setMaxPerformanceFeeBps\"\n | \"setMaxStrategyDuration\"\n | \"setCooldownPeriod\";\n\nasync function setGovernorParam(\n vault: Address,\n functionName: GovernorParamSetter,\n value: bigint,\n): Promise<Hex> {\n const hash = await writeContractWithRetry({\n account: getAccount(),\n chain: getChain(),\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName,\n args: [value],\n });\n const receipt = await waitForReceipt(hash);\n return receipt.transactionHash;\n}\n\nexport async function setVotingPeriod(vault: Address, seconds: bigint): Promise<Hex> {\n return setGovernorParam(vault, \"setVotingPeriod\", seconds);\n}\n\nexport async function setExecutionWindow(vault: Address, seconds: bigint): Promise<Hex> {\n return setGovernorParam(vault, \"setExecutionWindow\", seconds);\n}\n\nexport async function setVetoThresholdBps(vault: Address, bps: bigint): Promise<Hex> {\n return setGovernorParam(vault, \"setVetoThresholdBps\", bps);\n}\n\nexport async function setMaxPerformanceFeeBps(vault: Address, bps: bigint): Promise<Hex> {\n return setGovernorParam(vault, \"setMaxPerformanceFeeBps\", bps);\n}\n\nexport async function setMaxStrategyDuration(vault: Address, seconds: bigint): Promise<Hex> {\n return setGovernorParam(vault, \"setMaxStrategyDuration\", seconds);\n}\n\nexport async function setCooldownPeriod(vault: Address, seconds: bigint): Promise<Hex> {\n return setGovernorParam(vault, \"setCooldownPeriod\", seconds);\n}\n\nexport async function vetoProposal(vault: Address, proposalId: bigint): Promise<Hex> {\n const hash = await writeContractWithRetry({\n account: getAccount(),\n chain: getChain(),\n address: await getGovernorOf(vault),\n abi: SYNDICATE_GOVERNOR_ABI,\n functionName: \"vetoProposal\",\n args: [proposalId],\n });\n const receipt = await waitForReceipt(hash);\n return receipt.transactionHash;\n}\n\n// ── ProtocolConfig fee setters (protocol-owner only) ──\n//\n// Fee parameters moved off the governor onto the protocol-wide\n// ProtocolConfig contract (resolved via `factory.protocolConfig()`).\n\nexport async function setProtocolFeeBps(bps: bigint): Promise<Hex> {\n const hash = await writeContractWithRetry({\n account: getAccount(),\n chain: getChain(),\n address: await getProtocolConfigAddress(),\n abi: PROTOCOL_CONFIG_ABI,\n functionName: \"setProtocolFeeBps\",\n args: [bps],\n });\n const receipt = await waitForReceipt(hash);\n return receipt.transactionHash;\n}\n","/**\n * AUTO-GENERATED by cli/scripts/codegen-contracts.ts — do not edit.\n * Regenerate: npm run codegen (in cli/)\n *\n * Source of truth: contracts/src/interfaces/ISyndicateGovernor.sol (enum ProposalState)\n */\n\n/** On-chain `ProposalState` member names, index === Solidity enum value. */\nexport const PROPOSAL_STATES = [\n \"Draft\",\n \"Pending\",\n \"GuardianReview\",\n \"Approved\",\n \"Rejected\",\n \"Expired\",\n \"Executed\",\n \"Settled\",\n \"Cancelled\",\n] as const;\n\nexport type ProposalStateName = (typeof PROPOSAL_STATES)[number];\n\n/** Name → Solidity enum value. */\nexport const PROPOSAL_STATE = {\n Draft: 0,\n Pending: 1,\n GuardianReview: 2,\n Approved: 3,\n Rejected: 4,\n Expired: 5,\n Executed: 6,\n Settled: 7,\n Cancelled: 8,\n} as const;\n"],"mappings":"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","names":[]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getNetwork
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-LHVSS27T.js";
|
|
4
4
|
|
|
5
5
|
// src/lib/addresses.ts
|
|
6
6
|
import { isAddress } from "viem";
|
|
@@ -305,4 +305,4 @@ export {
|
|
|
305
305
|
SYNTHRA,
|
|
306
306
|
CHAINLINK
|
|
307
307
|
};
|
|
308
|
-
//# sourceMappingURL=chunk-
|
|
308
|
+
//# sourceMappingURL=chunk-UINMHN6S.js.map
|