@sage-protocol/sdk 0.1.2 → 0.1.7

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/index.mjs CHANGED
@@ -17,10 +17,10 @@ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "acce
17
17
 
18
18
  // package.json
19
19
  var require_package = __commonJS({
20
- "package.json"(exports, module) {
21
- module.exports = {
20
+ "package.json"(exports2, module2) {
21
+ module2.exports = {
22
22
  name: "@sage-protocol/sdk",
23
- version: "0.1.2",
23
+ version: "0.1.4",
24
24
  description: "Backend-agnostic SDK for interacting with the Sage Protocol (governance, SubDAOs, tokens).",
25
25
  main: "dist/index.cjs",
26
26
  module: "dist/index.mjs",
@@ -56,10 +56,10 @@ var require_package = __commonJS({
56
56
  ],
57
57
  sideEffects: false,
58
58
  browser: {
59
+ child_process: false,
59
60
  fs: false,
60
- path: false,
61
61
  os: false,
62
- child_process: false
62
+ path: false
63
63
  },
64
64
  repository: {
65
65
  type: "git",
@@ -88,6 +88,18 @@ var require_package = __commonJS({
88
88
  sinon: "^17.0.1",
89
89
  tsup: "^8.1.0",
90
90
  typescript: "^5.4.0"
91
+ },
92
+ peerDependencies: {
93
+ react: "^18.0.0 || ^19.0.0",
94
+ swr: "^2.0.0"
95
+ },
96
+ peerDependenciesMeta: {
97
+ react: {
98
+ optional: true
99
+ },
100
+ swr: {
101
+ optional: true
102
+ }
91
103
  }
92
104
  };
93
105
  }
@@ -95,7 +107,7 @@ var require_package = __commonJS({
95
107
 
96
108
  // src/abi/index.js
97
109
  var require_abi = __commonJS({
98
- "src/abi/index.js"(exports, module) {
110
+ "src/abi/index.js"(exports2, module2) {
99
111
  var SubDAO = [
100
112
  "function governor() view returns (address)",
101
113
  "function timelock() view returns (address)",
@@ -301,7 +313,7 @@ var require_abi = __commonJS({
301
313
  var Events = {
302
314
  ProposalCreated: "event ProposalCreated(uint256 id, address proposer, address[] targets, uint256[] values, string[] signatures, bytes[] calldatas, uint256 startBlock, uint256 endBlock, string description)"
303
315
  };
304
- module.exports = {
316
+ module2.exports = {
305
317
  SubDAO,
306
318
  Factory,
307
319
  FactoryRead,
@@ -327,9 +339,9 @@ var require_abi = __commonJS({
327
339
 
328
340
  // src/types.js
329
341
  var require_types = __commonJS({
330
- "src/types.js"(exports, module) {
342
+ "src/types.js"(exports2, module2) {
331
343
  var BigIntZero = 0n;
332
- module.exports = {
344
+ module2.exports = {
333
345
  BigIntZero
334
346
  };
335
347
  }
@@ -337,7 +349,7 @@ var require_types = __commonJS({
337
349
 
338
350
  // src/utils/errors.js
339
351
  var require_errors = __commonJS({
340
- "src/utils/errors.js"(exports, module) {
352
+ "src/utils/errors.js"(exports2, module2) {
341
353
  var SageSDKError = class extends Error {
342
354
  constructor(code, message, details) {
343
355
  super(message);
@@ -354,7 +366,7 @@ var require_errors = __commonJS({
354
366
  MISSING_DEPENDENCY: "ERR_MISSING_DEPENDENCY",
355
367
  API_REQUEST_FAILED: "ERR_API_REQUEST_FAILED"
356
368
  };
357
- module.exports = {
369
+ module2.exports = {
358
370
  SageSDKError,
359
371
  CODES
360
372
  };
@@ -363,7 +375,7 @@ var require_errors = __commonJS({
363
375
 
364
376
  // src/utils/description.js
365
377
  var require_description = __commonJS({
366
- "src/utils/description.js"(exports, module) {
378
+ "src/utils/description.js"(exports2, module2) {
367
379
  var { randomBytes, hexlify } = __require("ethers");
368
380
  var SALT_RE = /\n\n\[SALT:0x[0-9a-fA-F]{64}\]$/;
369
381
  function generateSaltHex() {
@@ -394,7 +406,7 @@ var require_description = __commonJS({
394
406
  return String(desc || "");
395
407
  }
396
408
  }
397
- module.exports = {
409
+ module2.exports = {
398
410
  makeProposalDescription,
399
411
  stripProposalSalt
400
412
  };
@@ -403,7 +415,7 @@ var require_description = __commonJS({
403
415
 
404
416
  // src/subgraph/index.js
405
417
  var require_subgraph = __commonJS({
406
- "src/subgraph/index.js"(exports, module) {
418
+ "src/subgraph/index.js"(exports2, module2) {
407
419
  var axios = __require("axios");
408
420
  var { getAddress } = __require("ethers");
409
421
  var { keccak256, toUtf8Bytes } = __require("ethers");
@@ -526,7 +538,7 @@ var require_subgraph = __commonJS({
526
538
  createdAt: Number(lib.createdAt || 0)
527
539
  }));
528
540
  }
529
- module.exports = {
541
+ module2.exports = {
530
542
  query,
531
543
  listProposals,
532
544
  listProposalsFiltered,
@@ -535,9 +547,9 @@ var require_subgraph = __commonJS({
535
547
  * Canonical proposal timeline. Tries common fields first, then event-style fallbacks.
536
548
  * Returns { id, createdAt, queuedAt, executedAt, canceledAt, eta, state } (numbers/strings may be null when unavailable).
537
549
  */
538
- async getProposalTimeline({ url, id }) {
550
+ async getProposalTimeline({ url, id: id2 }) {
539
551
  if (!url) throw new Error("subgraph url required");
540
- const pid = typeof id === "bigint" ? id.toString() : String(id);
552
+ const pid = typeof id2 === "bigint" ? id2.toString() : String(id2);
541
553
  try {
542
554
  const data = await query(url, `
543
555
  query($id: ID!) {
@@ -725,10 +737,10 @@ var require_subgraph = __commonJS({
725
737
  updatedAt: Number(p.updatedAt || 0)
726
738
  } : null;
727
739
  },
728
- async getProposalById({ url, id }) {
740
+ async getProposalById({ url, id: id2 }) {
729
741
  if (!url) throw new Error("subgraph url required");
730
742
  const doc = `query($id: ID!){ proposal(id:$id){ id proposer description createdAt updatedAt state eta targets values calldatas } }`;
731
- const data = await query(url, doc, { id: String(id) });
743
+ const data = await query(url, doc, { id: String(id2) });
732
744
  const p = data?.proposal;
733
745
  if (!p) return null;
734
746
  return {
@@ -750,7 +762,7 @@ var require_subgraph = __commonJS({
750
762
 
751
763
  // src/adapters/transports.js
752
764
  var require_transports = __commonJS({
753
- "src/adapters/transports.js"(exports, module) {
765
+ "src/adapters/transports.js"(exports2, module2) {
754
766
  function createTransports({ provider, signer = null, subgraph = null }) {
755
767
  return function resolve(kind) {
756
768
  switch (kind) {
@@ -765,7 +777,7 @@ var require_transports = __commonJS({
765
777
  }
766
778
  };
767
779
  }
768
- module.exports = {
780
+ module2.exports = {
769
781
  createTransports
770
782
  };
771
783
  }
@@ -773,10 +785,10 @@ var require_transports = __commonJS({
773
785
 
774
786
  // src/ipfs/index.js
775
787
  var require_ipfs = __commonJS({
776
- "src/ipfs/index.js"(exports, module) {
788
+ "src/ipfs/index.js"(exports2, module2) {
777
789
  var axiosDefault = __require("axios");
778
790
  var FormData = __require("form-data");
779
- var { ethers } = __require("ethers");
791
+ var { ethers: ethers2 } = __require("ethers");
780
792
  var DEFAULT_GATEWAY = "https://ipfs.dev.sageprotocol.io/ipfs";
781
793
  function toLowerSafe(value, fallback = "") {
782
794
  if (value == null) return fallback;
@@ -831,14 +843,14 @@ var require_ipfs = __commonJS({
831
843
  }
832
844
  return Array.from(urls);
833
845
  }
834
- function ensureLeadingSlash(path, fallback = "") {
835
- const value = path || fallback;
846
+ function ensureLeadingSlash(path2, fallback = "") {
847
+ const value = path2 || fallback;
836
848
  if (!value) return fallback;
837
849
  return value.startsWith("/") ? value : `/${value}`;
838
850
  }
839
851
  function generateDeterministicCid(payload) {
840
852
  const content = Buffer.isBuffer(payload) ? payload : typeof payload === "string" ? Buffer.from(payload) : Buffer.from(JSON.stringify(payload));
841
- const hash = ethers.keccak256(content);
853
+ const hash = ethers2.keccak256(content);
842
854
  const hashStr = hash.slice(2);
843
855
  const cidSuffix = (hashStr + hashStr).slice(0, 44);
844
856
  return `Qm${cidSuffix}`;
@@ -910,7 +922,7 @@ var require_ipfs = __commonJS({
910
922
  }
911
923
  function workerUrl(kind, cid) {
912
924
  const base = workerBaseUrl();
913
- const ensure = (path) => path.startsWith("/") ? path : `/${path}`;
925
+ const ensure = (path2) => path2.startsWith("/") ? path2 : `/${path2}`;
914
926
  if (base) {
915
927
  if (kind === "challenge") return `${base}${ensure(config.worker.challengePath || "/auth/challenge")}`;
916
928
  if (kind === "upload") return `${base}${ensure(config.worker.uploadPath || "/ipfs/upload")}`;
@@ -1232,18 +1244,18 @@ var require_ipfs = __commonJS({
1232
1244
  return postWorkerJson("discoveryEventsPath", "/discover/events", payload);
1233
1245
  }
1234
1246
  async function recordMcpUsageEvent({ promptId, metadata, address } = {}) {
1235
- const id = typeof promptId === "string" ? promptId.trim() : "";
1236
- if (!id) throw new Error("promptId required");
1237
- const payload = { promptId: id };
1247
+ const id2 = typeof promptId === "string" ? promptId.trim() : "";
1248
+ if (!id2) throw new Error("promptId required");
1249
+ const payload = { promptId: id2 };
1238
1250
  if (metadata && typeof metadata === "object") payload.metadata = metadata;
1239
1251
  const actor = address || config.worker.address;
1240
1252
  if (actor) payload.address = actor;
1241
1253
  return postWorkerJson("discoveryMcpPath", "/discover/mcp", payload);
1242
1254
  }
1243
1255
  async function recordLaunchEvent({ promptId, metadata, address } = {}) {
1244
- const id = typeof promptId === "string" ? promptId.trim() : "";
1245
- if (!id) throw new Error("promptId required");
1246
- const payload = { promptId: id };
1256
+ const id2 = typeof promptId === "string" ? promptId.trim() : "";
1257
+ if (!id2) throw new Error("promptId required");
1258
+ const payload = { promptId: id2 };
1247
1259
  if (metadata && typeof metadata === "object") payload.metadata = metadata;
1248
1260
  const actor = address || config.worker.address;
1249
1261
  if (actor) payload.address = actor;
@@ -1273,11 +1285,11 @@ var require_ipfs = __commonJS({
1273
1285
  }
1274
1286
  async function reviewGovernanceReport(payload = {}) {
1275
1287
  if (!payload || typeof payload !== "object") throw new Error("payload required");
1276
- const id = typeof payload.id === "string" ? payload.id.trim() : "";
1277
- if (!id) throw new Error("report id required");
1288
+ const id2 = typeof payload.id === "string" ? payload.id.trim() : "";
1289
+ if (!id2) throw new Error("report id required");
1278
1290
  const status = typeof payload.status === "string" ? payload.status.trim() : "";
1279
1291
  if (!status) throw new Error("status required");
1280
- const body = { id, status };
1292
+ const body = { id: id2, status };
1281
1293
  if (typeof payload.note === "string") body.note = payload.note;
1282
1294
  if (typeof payload.action === "string") body.action = payload.action;
1283
1295
  return postWorkerJson("governanceReviewPath", "/governance/report/review", body);
@@ -1393,7 +1405,7 @@ var require_ipfs = __commonJS({
1393
1405
  verified
1394
1406
  };
1395
1407
  }
1396
- module.exports = {
1408
+ module2.exports = {
1397
1409
  DEFAULT_GATEWAY,
1398
1410
  createClient,
1399
1411
  buildGatewayUrls,
@@ -1405,7 +1417,7 @@ var require_ipfs = __commonJS({
1405
1417
 
1406
1418
  // src/library/search.js
1407
1419
  var require_search = __commonJS({
1408
- "src/library/search.js"(exports, module) {
1420
+ "src/library/search.js"(exports2, module2) {
1409
1421
  var { Contract, getAddress } = __require("ethers");
1410
1422
  var ABI = require_abi();
1411
1423
  var { SageSDKError, CODES } = require_errors();
@@ -1576,7 +1588,7 @@ var require_search = __commonJS({
1576
1588
  }
1577
1589
  };
1578
1590
  }
1579
- module.exports = {
1591
+ module2.exports = {
1580
1592
  searchRegistry
1581
1593
  };
1582
1594
  }
@@ -1584,7 +1596,7 @@ var require_search = __commonJS({
1584
1596
 
1585
1597
  // src/library/validation.js
1586
1598
  var require_validation = __commonJS({
1587
- "src/library/validation.js"(exports, module) {
1599
+ "src/library/validation.js"(exports2, module2) {
1588
1600
  var fsDefault = __require("fs");
1589
1601
  var pathDefault = __require("path");
1590
1602
  function defaultAjvFactory() {
@@ -1603,18 +1615,18 @@ var require_validation = __commonJS({
1603
1615
  } catch (_) {
1604
1616
  }
1605
1617
  }
1606
- function normaliseSchemaPaths(schemaPaths, { path }) {
1618
+ function normaliseSchemaPaths(schemaPaths, { path: path2 }) {
1607
1619
  if (Array.isArray(schemaPaths) && schemaPaths.length) {
1608
1620
  return schemaPaths;
1609
1621
  }
1610
1622
  return [
1611
- path.join(process.cwd(), "docs", "schemas", "manifest.schema.json"),
1612
- path.join(__dirname, "..", "..", "docs", "schemas", "manifest.schema.json")
1623
+ path2.join(process.cwd(), "docs", "schemas", "manifest.schema.json"),
1624
+ path2.join(__dirname, "..", "..", "docs", "schemas", "manifest.schema.json")
1613
1625
  ];
1614
1626
  }
1615
- function safeJsonParse(fs, file) {
1627
+ function safeJsonParse(fs2, file) {
1616
1628
  try {
1617
- const raw = fs.readFileSync(file, "utf8");
1629
+ const raw = fs2.readFileSync(file, "utf8");
1618
1630
  return JSON.parse(raw);
1619
1631
  } catch (_) {
1620
1632
  return null;
@@ -1640,17 +1652,17 @@ var require_validation = __commonJS({
1640
1652
  }
1641
1653
  function createManifestValidator(options = {}) {
1642
1654
  const {
1643
- fs = fsDefault,
1644
- path = pathDefault,
1655
+ fs: fs2 = fsDefault,
1656
+ path: path2 = pathDefault,
1645
1657
  ajvFactory = defaultAjvFactory,
1646
1658
  addFormats = defaultAddFormats,
1647
1659
  schemaPaths
1648
1660
  } = options;
1649
- const searchPaths = normaliseSchemaPaths(schemaPaths, { path });
1661
+ const searchPaths = normaliseSchemaPaths(schemaPaths, { path: path2 });
1650
1662
  function loadSchema() {
1651
1663
  for (const schemaPath of searchPaths) {
1652
- if (!fs.existsSync(schemaPath)) continue;
1653
- const schema = safeJsonParse(fs, schemaPath);
1664
+ if (!fs2.existsSync(schemaPath)) continue;
1665
+ const schema = safeJsonParse(fs2, schemaPath);
1654
1666
  if (schema) return { schema, schemaPath };
1655
1667
  }
1656
1668
  return { schema: null, schemaPath: null };
@@ -1723,7 +1735,7 @@ var require_validation = __commonJS({
1723
1735
  if (!manifestPath) {
1724
1736
  throw new Error("manifestPath required");
1725
1737
  }
1726
- const data = safeJsonParse(fs, manifestPath);
1738
+ const data = safeJsonParse(fs2, manifestPath);
1727
1739
  if (!data) {
1728
1740
  return {
1729
1741
  ok: false,
@@ -1756,8 +1768,8 @@ var require_validation = __commonJS({
1756
1768
  seenKeys.add(key);
1757
1769
  const files = Array.isArray(prompt.files) ? prompt.files : [];
1758
1770
  for (const file of files) {
1759
- const resolved = path.isAbsolute(file) ? file : manifestPath ? path.join(path.dirname(manifestPath), file) : file;
1760
- if (!fs.existsSync(resolved)) {
1771
+ const resolved = path2.isAbsolute(file) ? file : manifestPath ? path2.join(path2.dirname(manifestPath), file) : file;
1772
+ if (!fs2.existsSync(resolved)) {
1761
1773
  issues.push({
1762
1774
  type: "missing_file",
1763
1775
  message: `File not found: ${file}`,
@@ -1780,7 +1792,7 @@ var require_validation = __commonJS({
1780
1792
  }
1781
1793
  function bestPracticeCheckFile(manifestPath, options2 = {}) {
1782
1794
  if (!manifestPath) throw new Error("manifestPath required");
1783
- const data = safeJsonParse(fs, manifestPath);
1795
+ const data = safeJsonParse(fs2, manifestPath);
1784
1796
  if (!data) {
1785
1797
  return [{ type: "parse_error", message: `Failed to parse JSON at ${manifestPath}`, manifestPath }];
1786
1798
  }
@@ -1794,7 +1806,7 @@ var require_validation = __commonJS({
1794
1806
  bestPracticeCheckFile
1795
1807
  };
1796
1808
  }
1797
- module.exports = {
1809
+ module2.exports = {
1798
1810
  createManifestValidator
1799
1811
  };
1800
1812
  }
@@ -1802,8 +1814,8 @@ var require_validation = __commonJS({
1802
1814
 
1803
1815
  // src/library/index.js
1804
1816
  var require_library = __commonJS({
1805
- "src/library/index.js"(exports, module) {
1806
- var { Contract, getAddress, keccak256, toUtf8Bytes } = __require("ethers");
1817
+ "src/library/index.js"(exports2, module2) {
1818
+ var { Contract, getAddress, keccak256, toUtf8Bytes, AbiCoder } = __require("ethers");
1807
1819
  var { Interface } = __require("ethers");
1808
1820
  var ABI = require_abi();
1809
1821
  var { SageSDKError, CODES } = require_errors();
@@ -1842,17 +1854,31 @@ var require_library = __commonJS({
1842
1854
  promptCount: Number(promptCount)
1843
1855
  };
1844
1856
  }
1857
+ function _computeLibraryKey(subdao, libraryId) {
1858
+ const coder = AbiCoder.defaultAbiCoder ? AbiCoder.defaultAbiCoder() : new AbiCoder();
1859
+ const encoded = coder.encode(["address", "string"], [getAddress(subdao), String(libraryId)]);
1860
+ return keccak256(encoded);
1861
+ }
1845
1862
  async function getLatestLibrary({ provider, registry, subdao, libraryId = "main" }) {
1846
1863
  if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
1847
1864
  const addr = normalise(registry, "registry");
1848
1865
  const sub = normalise(subdao, "subdao");
1849
1866
  const contract = new Contract(addr, ABI.LibraryRegistry, provider);
1850
- const key = keccak256(toUtf8Bytes(`${sub.toLowerCase()}::${libraryId}`));
1867
+ const key = _computeLibraryKey(sub, libraryId);
1851
1868
  const latestCID = await contract.subdaoLibraryLatest(key).catch(() => "");
1852
1869
  if (!latestCID || latestCID.length === 0) return null;
1853
1870
  const info = await getManifestInfo({ provider, registry: addr, manifestCID: latestCID });
1854
1871
  return info;
1855
1872
  }
1873
+ async function getBeforeAfterForUpdate({ provider, registry, subdao, libraryId = "main", newCid }) {
1874
+ if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
1875
+ const addr = normalise(registry, "registry");
1876
+ const sub = normalise(subdao, "subdao");
1877
+ const contract = new Contract(addr, ABI.LibraryRegistry, provider);
1878
+ const key = _computeLibraryKey(sub, libraryId);
1879
+ const prev = await contract.subdaoLibraryLatest(key).catch(() => "");
1880
+ return { previousCID: prev || null, newCID: String(newCid), libraryId: String(libraryId) };
1881
+ }
1856
1882
  async function hasScopedOwnership({ provider, registry, subdao, manifestCID }) {
1857
1883
  if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
1858
1884
  const addr = normalise(registry, "registry");
@@ -1872,12 +1898,14 @@ var require_library = __commonJS({
1872
1898
  ]);
1873
1899
  return { to, data, value: 0n };
1874
1900
  }
1875
- module.exports = {
1901
+ module2.exports = {
1876
1902
  listManifests,
1877
1903
  getManifestInfo,
1878
1904
  getLatestLibrary,
1879
1905
  hasScopedOwnership,
1880
1906
  buildUpdateLibraryForSubDAOTx,
1907
+ _computeLibraryKey,
1908
+ getBeforeAfterForUpdate,
1881
1909
  /** Build an authorizeTimelock(timelock, subdao) call for a LibraryRegistry. */
1882
1910
  buildAuthorizeTimelockTx: function buildAuthorizeTimelockTx({ registry, timelock, subdao }) {
1883
1911
  const to = normalise(registry, "registry");
@@ -1914,7 +1942,7 @@ var require_library = __commonJS({
1914
1942
 
1915
1943
  // src/governance/index.js
1916
1944
  var require_governance = __commonJS({
1917
- "src/governance/index.js"(exports, module) {
1945
+ "src/governance/index.js"(exports2, module2) {
1918
1946
  var { Contract, Interface, AbiCoder, getAddress, hexlify, keccak256, toUtf8Bytes } = __require("ethers");
1919
1947
  var ABI = require_abi();
1920
1948
  var { BigIntZero } = require_types();
@@ -1964,11 +1992,11 @@ var require_governance = __commonJS({
1964
1992
  stakeAmount
1965
1993
  };
1966
1994
  }
1967
- async function getProposal({ provider, governor, id }) {
1995
+ async function getProposal({ provider, governor, id: id2 }) {
1968
1996
  if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
1969
1997
  const addr = normaliseGovernor(governor);
1970
1998
  const g = new Contract(addr, ABI.Governor, provider);
1971
- const pid = typeof id === "bigint" ? id : String(id).startsWith("0x") ? BigInt(id) : BigInt(String(id));
1999
+ const pid = typeof id2 === "bigint" ? id2 : String(id2).startsWith("0x") ? BigInt(id2) : BigInt(String(id2));
1972
2000
  const [state, snapshot, deadline, votes] = await Promise.all([
1973
2001
  g.state(pid),
1974
2002
  g.proposalSnapshot(pid),
@@ -2022,12 +2050,12 @@ var require_governance = __commonJS({
2022
2050
  }
2023
2051
  return proposals;
2024
2052
  }
2025
- async function getProposalMetadata({ provider, governor, id, fromBlock = 0, toBlock = "latest" }) {
2053
+ async function getProposalMetadata({ provider, governor, id: id2, fromBlock = 0, toBlock = "latest" }) {
2026
2054
  if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
2027
2055
  const addr = normaliseGovernor(governor);
2028
2056
  const iface = new Interface([ABI.Events.ProposalCreated]);
2029
2057
  const topic = iface.getEvent("ProposalCreated").topicHash;
2030
- const pid = typeof id === "bigint" ? id : String(id).startsWith("0x") ? BigInt(id) : BigInt(String(id));
2058
+ const pid = typeof id2 === "bigint" ? id2 : String(id2).startsWith("0x") ? BigInt(id2) : BigInt(String(id2));
2031
2059
  const logs = await provider.getLogs({ address: addr, fromBlock, toBlock, topics: [topic] });
2032
2060
  for (const log of logs) {
2033
2061
  try {
@@ -2088,10 +2116,10 @@ var require_governance = __commonJS({
2088
2116
  function buildCastVoteTx({ governor, proposalId, support, reason }) {
2089
2117
  const addr = normaliseGovernor(governor);
2090
2118
  const iface = new Interface(ABI.Governor);
2091
- const id = typeof proposalId === "bigint" ? proposalId : String(proposalId).startsWith("0x") ? BigInt(proposalId) : BigInt(String(proposalId));
2119
+ const id2 = typeof proposalId === "bigint" ? proposalId : String(proposalId).startsWith("0x") ? BigInt(proposalId) : BigInt(String(proposalId));
2092
2120
  const s = Number(support);
2093
2121
  const hasReason = reason && String(reason).length > 0;
2094
- const data = hasReason ? iface.encodeFunctionData("castVoteWithReason(uint256,uint8,string)", [id, s, String(reason)]) : iface.encodeFunctionData("castVote(uint256,uint8)", [id, s]);
2122
+ const data = hasReason ? iface.encodeFunctionData("castVoteWithReason(uint256,uint8,string)", [id2, s, String(reason)]) : iface.encodeFunctionData("castVote(uint256,uint8)", [id2, s]);
2095
2123
  return { to: addr, data, value: BigIntZero };
2096
2124
  }
2097
2125
  function cueTx(fn, { governor, targets = [], values = [], calldatas = [], descriptionOrHash = "" }) {
@@ -2112,17 +2140,73 @@ var require_governance = __commonJS({
2112
2140
  function buildQueueByIdTx({ governor, proposalId }) {
2113
2141
  const addr = normaliseGovernor(governor);
2114
2142
  const iface = new Interface(ABI.Governor);
2115
- const id = typeof proposalId === "bigint" ? proposalId : String(proposalId).startsWith("0x") ? BigInt(proposalId) : BigInt(String(proposalId));
2116
- const data = iface.encodeFunctionData("queue(uint256)", [id]);
2143
+ const id2 = typeof proposalId === "bigint" ? proposalId : String(proposalId).startsWith("0x") ? BigInt(proposalId) : BigInt(String(proposalId));
2144
+ const data = iface.encodeFunctionData("queue(uint256)", [id2]);
2117
2145
  return { to: addr, data, value: BigIntZero };
2118
2146
  }
2119
2147
  function buildExecuteByIdTx({ governor, proposalId }) {
2120
2148
  const addr = normaliseGovernor(governor);
2121
2149
  const iface = new Interface(ABI.Governor);
2122
- const id = typeof proposalId === "bigint" ? proposalId : String(proposalId).startsWith("0x") ? BigInt(proposalId) : BigInt(String(proposalId));
2123
- const data = iface.encodeFunctionData("execute(uint256)", [id]);
2150
+ const id2 = typeof proposalId === "bigint" ? proposalId : String(proposalId).startsWith("0x") ? BigInt(proposalId) : BigInt(String(proposalId));
2151
+ const data = iface.encodeFunctionData("execute(uint256)", [id2]);
2124
2152
  return { to: addr, data, value: BigIntZero };
2125
2153
  }
2154
+ async function decodeProposalEffects({ provider, governor, proposalId, fromBlock = 0, toBlock = "latest" }) {
2155
+ if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
2156
+ const govAddr = normaliseGovernor(governor);
2157
+ const iface = new Interface([ABI.Events.ProposalCreated]);
2158
+ const topic = iface.getEvent("ProposalCreated").topicHash;
2159
+ const id2 = typeof proposalId === "bigint" ? proposalId : String(proposalId).startsWith("0x") ? BigInt(proposalId) : BigInt(String(proposalId));
2160
+ let parsed = null;
2161
+ let logTxHash = null;
2162
+ const logs = await provider.getLogs({ address: govAddr, fromBlock, toBlock, topics: [topic] });
2163
+ for (const log of logs) {
2164
+ try {
2165
+ const p = iface.parseLog(log);
2166
+ if (BigInt(p.args.id.toString()) === id2) {
2167
+ parsed = p;
2168
+ logTxHash = log.transactionHash;
2169
+ break;
2170
+ }
2171
+ } catch (_) {
2172
+ }
2173
+ }
2174
+ if (!parsed) throw new Error("ProposalCreated event not found");
2175
+ const targets = parsed.args.targets.map(getAddress);
2176
+ const calldatas = parsed.args.calldatas.map((d) => typeof d === "string" ? d : "0x" + Buffer.from(d).toString("hex"));
2177
+ const LibraryIface = new Interface(["function updateLibraryForSubDAO(address,string,string,uint256)", "function subdaoLibraryLatest(bytes32) view returns (string)"]);
2178
+ const PromptIface = new Interface(["function updatePromptByGovernance(string,string)"]);
2179
+ const coder = AbiCoder.defaultAbiCoder ? AbiCoder.defaultAbiCoder() : new AbiCoder();
2180
+ const effects = [];
2181
+ for (let i = 0; i < calldatas.length; i++) {
2182
+ const data = calldatas[i];
2183
+ const sel = data.slice(0, 10);
2184
+ try {
2185
+ const decoded = LibraryIface.decodeFunctionData("updateLibraryForSubDAO", data);
2186
+ const [subdao, libraryId, newCid, promptCount] = decoded;
2187
+ let previousCID = null;
2188
+ try {
2189
+ const reg = new Contract(targets[i], ["function subdaoLibraryLatest(bytes32) view returns (string)"], provider);
2190
+ const key = keccak256(coder.encode(["address", "string"], [getAddress(subdao), String(libraryId)]));
2191
+ const prev = await reg.subdaoLibraryLatest(key).catch(() => "");
2192
+ previousCID = prev && prev.length ? String(prev) : null;
2193
+ } catch (_) {
2194
+ }
2195
+ effects.push({ type: "libraryUpdate", index: i, target: targets[i], subdao: getAddress(subdao), libraryId: String(libraryId), previousCid: previousCID, newCid: String(newCid), promptCount: Number(promptCount) });
2196
+ continue;
2197
+ } catch (_) {
2198
+ }
2199
+ try {
2200
+ const decodedP = PromptIface.decodeFunctionData("updatePromptByGovernance", data);
2201
+ const [key, newCid] = decodedP;
2202
+ effects.push({ type: "promptUpdate", index: i, target: targets[i], key: String(key), newCid: String(newCid) });
2203
+ continue;
2204
+ } catch (_) {
2205
+ }
2206
+ effects.push({ type: "unknown", index: i, target: targets[i], selector: sel });
2207
+ }
2208
+ return { governor: govAddr, proposalId: id2, tx: logTxHash, actions: { count: calldatas.length }, effects };
2209
+ }
2126
2210
  async function getQuorumAt({ provider, governor, blockTag }) {
2127
2211
  if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
2128
2212
  const addr = normaliseGovernor(governor);
@@ -2240,7 +2324,7 @@ var require_governance = __commonJS({
2240
2324
  const token = await g.sxxxToken();
2241
2325
  return buildDelegateTx({ token, delegatee: account });
2242
2326
  }
2243
- module.exports = {
2327
+ module2.exports = {
2244
2328
  getGovernorInfo,
2245
2329
  getProposal,
2246
2330
  listProposals,
@@ -2252,6 +2336,7 @@ var require_governance = __commonJS({
2252
2336
  buildExecuteTx,
2253
2337
  buildQueueByIdTx,
2254
2338
  buildExecuteByIdTx,
2339
+ decodeProposalEffects,
2255
2340
  makeProposalDescription,
2256
2341
  stripProposalSalt,
2257
2342
  getQuorumAt,
@@ -2509,7 +2594,7 @@ var require_governance = __commonJS({
2509
2594
 
2510
2595
  // src/governance/intents.js
2511
2596
  var require_intents = __commonJS({
2512
- "src/governance/intents.js"(exports, module) {
2597
+ "src/governance/intents.js"(exports2, module2) {
2513
2598
  var { Interface, getAddress } = __require("ethers");
2514
2599
  var { SageSDKError, CODES } = require_errors();
2515
2600
  function normalise(addr, label) {
@@ -2533,7 +2618,7 @@ var require_intents = __commonJS({
2533
2618
  "function setPremiumRevSplit(address,uint16,uint16,uint16)",
2534
2619
  "function setCreatorStakeBps(address,uint256)"
2535
2620
  ]);
2536
- module.exports = {
2621
+ module2.exports = {
2537
2622
  // Governor targets
2538
2623
  buildUpdateQuorumTx: ({ governor, quorumPercent }) => ({ to: normalise(governor, "governor"), data: GovIface.encodeFunctionData("updateQuorumNumerator", [Number(quorumPercent)]), value: 0n }),
2539
2624
  buildSetVotingPeriodTx: ({ governor, blocks }) => ({ to: normalise(governor, "governor"), data: GovIface.encodeFunctionData("setVotingPeriodBlocks", [Number(blocks)]), value: 0n }),
@@ -2551,7 +2636,7 @@ var require_intents = __commonJS({
2551
2636
 
2552
2637
  // src/utils/logs.js
2553
2638
  var require_logs = __commonJS({
2554
- "src/utils/logs.js"(exports, module) {
2639
+ "src/utils/logs.js"(exports2, module2) {
2555
2640
  async function fetchLogsChunked({ provider, address, topics = [], fromBlock = 0, toBlock = "latest", chunkSize = 5e4 }) {
2556
2641
  if (!provider) throw new Error("provider required");
2557
2642
  const latest = toBlock === "latest" ? await provider.getBlockNumber() : Number(toBlock);
@@ -2565,7 +2650,7 @@ var require_logs = __commonJS({
2565
2650
  }
2566
2651
  return logs;
2567
2652
  }
2568
- module.exports = {
2653
+ module2.exports = {
2569
2654
  fetchLogsChunked
2570
2655
  };
2571
2656
  }
@@ -2573,7 +2658,7 @@ var require_logs = __commonJS({
2573
2658
 
2574
2659
  // src/subdao/index.js
2575
2660
  var require_subdao = __commonJS({
2576
- "src/subdao/index.js"(exports, module) {
2661
+ "src/subdao/index.js"(exports2, module2) {
2577
2662
  var { Contract, Interface, getAddress } = __require("ethers");
2578
2663
  var ABI = require_abi();
2579
2664
  var { fetchLogsChunked } = require_logs();
@@ -2671,7 +2756,7 @@ var require_subdao = __commonJS({
2671
2756
  const data = SubDAOInterface.encodeFunctionData("unstake", [BigInt(amount)]);
2672
2757
  return { to: addr, data, value: 0n };
2673
2758
  }
2674
- module.exports = {
2759
+ module2.exports = {
2675
2760
  discoverSubDAOs,
2676
2761
  getSubDAOInfo,
2677
2762
  getSubDAOUserStats,
@@ -2784,16 +2869,16 @@ var require_subdao = __commonJS({
2784
2869
  const op = await makeOperator({ signer, subdao: created.subdao, operator, grantAdmin });
2785
2870
  return { ...created, operatorResult: op };
2786
2871
  }
2787
- module.exports.ensureSxxxBurnAllowance = ensureSxxxBurnAllowance;
2788
- module.exports.createSubDAO = createSubDAO;
2789
- module.exports.makeOperator = makeOperator;
2790
- module.exports.createOperatorSubDAO = createOperatorSubDAO;
2872
+ module2.exports.ensureSxxxBurnAllowance = ensureSxxxBurnAllowance;
2873
+ module2.exports.createSubDAO = createSubDAO;
2874
+ module2.exports.makeOperator = makeOperator;
2875
+ module2.exports.createOperatorSubDAO = createOperatorSubDAO;
2791
2876
  }
2792
2877
  });
2793
2878
 
2794
2879
  // src/governance/templates.js
2795
2880
  var require_templates = __commonJS({
2796
- "src/governance/templates.js"(exports, module) {
2881
+ "src/governance/templates.js"(exports2, module2) {
2797
2882
  var { Contract, ZeroAddress, getAddress, isAddress } = __require("ethers");
2798
2883
  var subdao = require_subdao();
2799
2884
  var abi = require_abi();
@@ -2903,7 +2988,7 @@ var require_templates = __commonJS({
2903
2988
  const receipts = await executeSequence(actions);
2904
2989
  return { governor, timelock, receipts };
2905
2990
  }
2906
- module.exports = {
2991
+ module2.exports = {
2907
2992
  communityDraftsBoardExec,
2908
2993
  tokenDemocracy
2909
2994
  };
@@ -2912,7 +2997,7 @@ var require_templates = __commonJS({
2912
2997
 
2913
2998
  // src/adapters/governance/openzeppelin.js
2914
2999
  var require_openzeppelin = __commonJS({
2915
- "src/adapters/governance/openzeppelin.js"(exports, module) {
3000
+ "src/adapters/governance/openzeppelin.js"(exports2, module2) {
2916
3001
  var { Contract, Interface, getAddress } = __require("ethers");
2917
3002
  var axios = __require("axios");
2918
3003
  var ABI = require_abi();
@@ -2958,7 +3043,7 @@ var require_openzeppelin = __commonJS({
2958
3043
  for (const log of logs) {
2959
3044
  try {
2960
3045
  const parsed = iface.parseLog(log);
2961
- const id = BigInt(parsed.args.id.toString());
3046
+ const id2 = BigInt(parsed.args.id.toString());
2962
3047
  const proposer = getAddress(parsed.args.proposer);
2963
3048
  const targets = parsed.args.targets.map(getAddress);
2964
3049
  const values = parsed.args.values.map((v) => BigInt(v.toString()));
@@ -2968,7 +3053,7 @@ var require_openzeppelin = __commonJS({
2968
3053
  const block = await provider.getBlock(log.blockNumber).catch(() => ({ timestamp: 0 }));
2969
3054
  const quorum = await governance.getQuorumAt({ provider, governor: addr, blockTag: BigInt(endBlock || log.blockNumber) }).catch(() => null);
2970
3055
  const signatures = await getSignatureList({ provider, targets, calldatas, abiResolver, selectorResolver, chainId: resolvedChainId });
2971
- items.push({ id, proposer, createdAt: Number(block.timestamp || 0), startBlock, endBlock, quorum, txHash: log.transactionHash, targets, values, calldatas, signatures });
3056
+ items.push({ id: id2, proposer, createdAt: Number(block.timestamp || 0), startBlock, endBlock, quorum, txHash: log.transactionHash, targets, values, calldatas, signatures });
2972
3057
  } catch (_) {
2973
3058
  }
2974
3059
  }
@@ -2976,10 +3061,10 @@ var require_openzeppelin = __commonJS({
2976
3061
  }
2977
3062
  return { items, nextCursor: null };
2978
3063
  }
2979
- async function getTimelineOnchain({ provider, governor, id, fromBlock = 0, toBlock = "latest" }) {
3064
+ async function getTimelineOnchain({ provider, governor, id: id2, fromBlock = 0, toBlock = "latest" }) {
2980
3065
  if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
2981
3066
  const addr = normaliseGovernor(governor);
2982
- const pid = typeof id === "bigint" ? id : String(id).startsWith("0x") ? BigInt(id) : BigInt(String(id));
3067
+ const pid = typeof id2 === "bigint" ? id2 : String(id2).startsWith("0x") ? BigInt(id2) : BigInt(String(id2));
2983
3068
  const iface = new Interface([Events.ProposalQueued, Events.ProposalExecuted, Events.ProposalCanceled]);
2984
3069
  const topics = [
2985
3070
  iface.getEvent("ProposalQueued").topicHash,
@@ -3144,7 +3229,7 @@ var require_openzeppelin = __commonJS({
3144
3229
  }
3145
3230
  return out;
3146
3231
  }
3147
- module.exports = {
3232
+ module2.exports = {
3148
3233
  getProposals,
3149
3234
  getTimelineOnchain,
3150
3235
  getSignatureList,
@@ -3199,7 +3284,7 @@ var require_openzeppelin = __commonJS({
3199
3284
 
3200
3285
  // src/governance/operations.js
3201
3286
  var require_operations = __commonJS({
3202
- "src/governance/operations.js"(exports, module) {
3287
+ "src/governance/operations.js"(exports2, module2) {
3203
3288
  var { Contract, getAddress, Interface, ZeroAddress, ZeroHash, keccak256, toUtf8Bytes, formatEther } = __require("ethers");
3204
3289
  var governance = require_governance();
3205
3290
  var ABI = require_abi();
@@ -3212,9 +3297,9 @@ var require_operations = __commonJS({
3212
3297
  throw new SageSDKError(CODES.INVALID_ARGS, "invalid governor address", { cause: error });
3213
3298
  }
3214
3299
  }
3215
- function normaliseProposalId(id) {
3216
- if (typeof id === "bigint") return id;
3217
- const value = String(id);
3300
+ function normaliseProposalId(id2) {
3301
+ if (typeof id2 === "bigint") return id2;
3302
+ const value = String(id2);
3218
3303
  try {
3219
3304
  return value.startsWith("0x") ? BigInt(value) : BigInt(value);
3220
3305
  } catch (error) {
@@ -3236,7 +3321,7 @@ var require_operations = __commonJS({
3236
3321
  if (!load || !save) return null;
3237
3322
  return { load, save };
3238
3323
  }
3239
- function normaliseTuple(governor, id, metadata) {
3324
+ function normaliseTuple(governor, id2, metadata) {
3240
3325
  const targets = Array.isArray(metadata.targets) ? metadata.targets.map((t) => getAddress(t)) : [];
3241
3326
  let values = Array.isArray(metadata.values) ? metadata.values.map((v) => BigInt(v)) : new Array(targets.length).fill(BigIntZero);
3242
3327
  const calldatas = Array.isArray(metadata.calldatas) ? metadata.calldatas.map(String) : [];
@@ -3246,7 +3331,7 @@ var require_operations = __commonJS({
3246
3331
  const description = metadata.description || metadata.body || "";
3247
3332
  const descriptionHash = metadata.descriptionHash || (typeof metadata.hashDescription === "function" ? metadata.hashDescription(description) : keccak256(toUtf8Bytes(String(description || ""))));
3248
3333
  return {
3249
- id,
3334
+ id: id2,
3250
3335
  governor,
3251
3336
  targets,
3252
3337
  values,
@@ -3271,10 +3356,10 @@ var require_operations = __commonJS({
3271
3356
  }) {
3272
3357
  if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
3273
3358
  const govAddr = normaliseGovernor(governor);
3274
- const id = normaliseProposalId(proposalId);
3359
+ const id2 = normaliseProposalId(proposalId);
3275
3360
  const cacheAdapter = wrapCache(cache);
3276
3361
  if (!refresh && cacheAdapter) {
3277
- const cached = await cacheAdapter.load(govAddr, id);
3362
+ const cached = await cacheAdapter.load(govAddr, id2);
3278
3363
  if (cached) return cached;
3279
3364
  }
3280
3365
  if (helperAddress) {
@@ -3283,10 +3368,10 @@ var require_operations = __commonJS({
3283
3368
  "function getProposalTuple(uint256) view returns (address[] targets,uint256[] values,bytes[] calldatas,bytes32 descriptionHash,bool exists)"
3284
3369
  ];
3285
3370
  const helper = new Contract(helperAddress, helperAbi, provider);
3286
- const res = await helper.getProposalTuple(id);
3371
+ const res = await helper.getProposalTuple(id2);
3287
3372
  if (res && res.exists) {
3288
3373
  const tuple2 = {
3289
- id,
3374
+ id: id2,
3290
3375
  governor: normaliseGovernor(governor),
3291
3376
  targets: res.targets || [],
3292
3377
  values: (res.values || []).map((v) => BigInt(v)),
@@ -3295,7 +3380,7 @@ var require_operations = __commonJS({
3295
3380
  descriptionHash: res.descriptionHash || null,
3296
3381
  createdBlock: null
3297
3382
  };
3298
- if (cacheAdapter) await cacheAdapter.save(governor, id, tuple2);
3383
+ if (cacheAdapter) await cacheAdapter.save(governor, id2, tuple2);
3299
3384
  return tuple2;
3300
3385
  }
3301
3386
  } catch (_) {
@@ -3303,7 +3388,7 @@ var require_operations = __commonJS({
3303
3388
  }
3304
3389
  let metadata = null;
3305
3390
  try {
3306
- metadata = await governance.getProposalMetadata({ provider, governor: govAddr, id });
3391
+ metadata = await governance.getProposalMetadata({ provider, governor: govAddr, id: id2 });
3307
3392
  } catch (_) {
3308
3393
  metadata = null;
3309
3394
  }
@@ -3312,7 +3397,7 @@ var require_operations = __commonJS({
3312
3397
  try {
3313
3398
  const govAbi = new Interface(ABI.Governor);
3314
3399
  const govC = new Contract(govAddr, govAbi, provider);
3315
- const snapshot = hints.snapshot ?? await govC.proposalSnapshot(id).catch(() => null);
3400
+ const snapshot = hints.snapshot ?? await govC.proposalSnapshot(id2).catch(() => null);
3316
3401
  const votingDelay = hints.votingDelay ?? await govC.votingDelay().catch(() => null);
3317
3402
  if (snapshot !== null && votingDelay !== null) {
3318
3403
  const approxCreation = Number(snapshot) - Number(votingDelay);
@@ -3335,9 +3420,9 @@ var require_operations = __commonJS({
3335
3420
  try {
3336
3421
  const parsed = govC.interface.parseLog(log);
3337
3422
  const pid = normaliseProposalId(parsed.args.proposalId);
3338
- if (pid === id) {
3423
+ if (pid === id2) {
3339
3424
  metadata = {
3340
- id,
3425
+ id: id2,
3341
3426
  governor: govAddr,
3342
3427
  targets: Array.from(parsed.args.targets || [], String),
3343
3428
  values: Array.from(parsed.args.values || [], (v) => BigInt(v.toString())),
@@ -3362,7 +3447,7 @@ var require_operations = __commonJS({
3362
3447
  const page = await governance.listProposals({ provider, governor: govAddr, fromBlock, toBlock: "latest" });
3363
3448
  metadata = page.find((entry) => {
3364
3449
  try {
3365
- return normaliseProposalId(entry.id || entry.proposalId) === id;
3450
+ return normaliseProposalId(entry.id || entry.proposalId) === id2;
3366
3451
  } catch (_) {
3367
3452
  return false;
3368
3453
  }
@@ -3372,9 +3457,9 @@ var require_operations = __commonJS({
3372
3457
  if (!metadata) {
3373
3458
  throw new SageSDKError(CODES.NOT_FOUND, "proposal tuple not found");
3374
3459
  }
3375
- const tuple = normaliseTuple(govAddr, id, metadata);
3460
+ const tuple = normaliseTuple(govAddr, id2, metadata);
3376
3461
  if (cacheAdapter) {
3377
- await cacheAdapter.save(govAddr, id, tuple);
3462
+ await cacheAdapter.save(govAddr, id2, tuple);
3378
3463
  }
3379
3464
  return tuple;
3380
3465
  }
@@ -3659,7 +3744,7 @@ var require_operations = __commonJS({
3659
3744
  }
3660
3745
  return results;
3661
3746
  }
3662
- module.exports = {
3747
+ module2.exports = {
3663
3748
  resolveProposalTuple,
3664
3749
  queueProposal,
3665
3750
  executeProposal,
@@ -3670,9 +3755,94 @@ var require_operations = __commonJS({
3670
3755
  }
3671
3756
  });
3672
3757
 
3758
+ // src/governance/grants.js
3759
+ var require_grants = __commonJS({
3760
+ "src/governance/grants.js"(exports2, module2) {
3761
+ var { Interface, getAddress, isAddress, parseUnits } = __require("ethers");
3762
+ var { SageSDKError, CODES } = require_errors();
3763
+ function normalizeAddress(label, value) {
3764
+ if (!value) throw new SageSDKError(CODES.INVALID_ARGS, `${label} required`);
3765
+ if (!isAddress(value)) throw new SageSDKError(CODES.INVALID_ARGS, `${label} invalid`);
3766
+ return getAddress(value);
3767
+ }
3768
+ async function buildGrantProposal({ provider = null, vault, token, recipient, amount, decimals = null, raw = false, description = null }) {
3769
+ const vaultAddr = normalizeAddress("vault", vault);
3770
+ const tokenAddr = normalizeAddress("token", token);
3771
+ const rcptAddr = normalizeAddress("recipient", recipient);
3772
+ if (amount == null) throw new SageSDKError(CODES.INVALID_ARGS, "amount required");
3773
+ let resolvedDecimals = decimals != null ? Number(decimals) : null;
3774
+ let symbol = null;
3775
+ if (provider && resolvedDecimals == null) {
3776
+ try {
3777
+ const erc20 = new (__require("ethers")).Contract(tokenAddr, ["function decimals() view returns (uint8)", "function symbol() view returns (string)"], provider);
3778
+ resolvedDecimals = Number(await erc20.decimals());
3779
+ symbol = await erc20.symbol().catch(() => null);
3780
+ } catch (_) {
3781
+ }
3782
+ }
3783
+ if (resolvedDecimals == null) resolvedDecimals = 18;
3784
+ let amtWei;
3785
+ if (raw) {
3786
+ amtWei = BigInt(String(amount));
3787
+ } else {
3788
+ amtWei = parseUnits(String(amount), resolvedDecimals);
3789
+ }
3790
+ const iface = new Interface(["function withdraw(address token,uint256 amount,address recipient)"]);
3791
+ const data = iface.encodeFunctionData("withdraw", [tokenAddr, amtWei, rcptAddr]);
3792
+ const targets = [vaultAddr];
3793
+ const values = [0n];
3794
+ const calldatas = [data];
3795
+ const desc = description && description.length ? description : `Grant ${String(amount)}${symbol ? " " + symbol : ""} to ${rcptAddr}`;
3796
+ return { targets, values, calldatas, description: desc };
3797
+ }
3798
+ module2.exports = {
3799
+ buildGrantProposal,
3800
+ /**
3801
+ * Build a batched proposal for multiple grants. Each item can specify its own vault
3802
+ * or inherit from defaultVault. Decimals are resolved per-token when provider is present.
3803
+ * items: Array<{ vault?, token, recipient, amount, decimals?, raw? }>
3804
+ */
3805
+ buildBatchGrantProposal: async function buildBatchGrantProposal({ provider = null, items = [], defaultVault = null, description = null }) {
3806
+ if (!Array.isArray(items) || items.length === 0) {
3807
+ throw new SageSDKError(CODES.INVALID_ARGS, "items required");
3808
+ }
3809
+ const targets = [];
3810
+ const values = [];
3811
+ const calldatas = [];
3812
+ const iface = new Interface(["function withdraw(address token,uint256 amount,address recipient)"]);
3813
+ for (const [i, it] of items.entries()) {
3814
+ const vault = it.vault || defaultVault;
3815
+ if (!vault) throw new SageSDKError(CODES.INVALID_ARGS, `item[${i}]: vault missing and no defaultVault provided`);
3816
+ const vaultAddr = normalizeAddress("vault", vault);
3817
+ const tokenAddr = normalizeAddress("token", it.token);
3818
+ const rcptAddr = normalizeAddress("recipient", it.recipient);
3819
+ let resolvedDecimals = it.decimals != null ? Number(it.decimals) : null;
3820
+ if (provider && resolvedDecimals == null && !it.raw) {
3821
+ try {
3822
+ const erc20 = new (__require("ethers")).Contract(tokenAddr, ["function decimals() view returns (uint8)"], provider);
3823
+ resolvedDecimals = Number(await erc20.decimals());
3824
+ } catch (_) {
3825
+ }
3826
+ }
3827
+ if (resolvedDecimals == null) resolvedDecimals = 18;
3828
+ let amtWei;
3829
+ if (it.raw) amtWei = BigInt(String(it.amount));
3830
+ else amtWei = parseUnits(String(it.amount), resolvedDecimals);
3831
+ const data = iface.encodeFunctionData("withdraw", [tokenAddr, amtWei, rcptAddr]);
3832
+ targets.push(vaultAddr);
3833
+ values.push(0n);
3834
+ calldatas.push(data);
3835
+ }
3836
+ const desc = description && description.length ? description : `Batch Grants: ${items.length} transfer(s)`;
3837
+ return { targets, values, calldatas, description: desc };
3838
+ }
3839
+ };
3840
+ }
3841
+ });
3842
+
3673
3843
  // src/timelock/index.js
3674
3844
  var require_timelock = __commonJS({
3675
- "src/timelock/index.js"(exports, module) {
3845
+ "src/timelock/index.js"(exports2, module2) {
3676
3846
  var { Contract, Interface, getAddress } = __require("ethers");
3677
3847
  var { SageSDKError, CODES } = require_errors();
3678
3848
  var TimelockABI = [
@@ -3732,8 +3902,8 @@ var require_timelock = __commonJS({
3732
3902
  for (const log of logs) {
3733
3903
  try {
3734
3904
  const parsed = iface.parseLog(log);
3735
- const id = parsed.args.id;
3736
- const op = operations.get(id) || { id, scheduled: [], executed: [], cancelled: false };
3905
+ const id2 = parsed.args.id;
3906
+ const op = operations.get(id2) || { id: id2, scheduled: [], executed: [], cancelled: false };
3737
3907
  if (parsed.name === "CallScheduled") {
3738
3908
  op.scheduled.push({
3739
3909
  index: Number(parsed.args.index),
@@ -3755,14 +3925,14 @@ var require_timelock = __commonJS({
3755
3925
  } else if (parsed.name === "Cancelled") {
3756
3926
  op.cancelled = true;
3757
3927
  }
3758
- operations.set(id, op);
3928
+ operations.set(id2, op);
3759
3929
  } catch (err) {
3760
3930
  continue;
3761
3931
  }
3762
3932
  }
3763
3933
  return Array.from(operations.values());
3764
3934
  }
3765
- module.exports = {
3935
+ module2.exports = {
3766
3936
  getTimelockInfo,
3767
3937
  listQueuedOperations,
3768
3938
  buildScheduleTx: ({ timelock, target, value = 0n, data = "0x", predecessor = "0x0000000000000000000000000000000000000000000000000000000000000000", salt = "0x0000000000000000000000000000000000000000000000000000000000000000", delay = 0n }) => {
@@ -3778,10 +3948,10 @@ var require_timelock = __commonJS({
3778
3948
  ]);
3779
3949
  return { to, data: payload, value: 0n };
3780
3950
  },
3781
- buildCancelTx: ({ timelock, id }) => {
3782
- if (!id) throw new SageSDKError(CODES.INVALID_ARGS, "operation id required");
3951
+ buildCancelTx: ({ timelock, id: id2 }) => {
3952
+ if (!id2) throw new SageSDKError(CODES.INVALID_ARGS, "operation id required");
3783
3953
  const addr = normalise(timelock, "timelock");
3784
- const payload = TimelockInterface.encodeFunctionData("cancel", [id]);
3954
+ const payload = TimelockInterface.encodeFunctionData("cancel", [id2]);
3785
3955
  return { to: addr, data: payload, value: 0n };
3786
3956
  },
3787
3957
  buildExecuteTx: ({ timelock, target, value = 0n, data = "0x", predecessor = "0x0000000000000000000000000000000000000000000000000000000000000000", salt = "0x0000000000000000000000000000000000000000000000000000000000000000" }) => {
@@ -3801,7 +3971,7 @@ var require_timelock = __commonJS({
3801
3971
 
3802
3972
  // src/factory/index.js
3803
3973
  var require_factory = __commonJS({
3804
- "src/factory/index.js"(exports, module) {
3974
+ "src/factory/index.js"(exports2, module2) {
3805
3975
  var { Contract, Interface, getAddress } = __require("ethers");
3806
3976
  var ABI = require_abi();
3807
3977
  var { SageSDKError, CODES } = require_errors();
@@ -3890,10 +4060,10 @@ var require_factory = __commonJS({
3890
4060
  const moduleContract = new Contract(templateAddr, ABI.TemplateModule, provider);
3891
4061
  const ids = await moduleContract.getActiveTemplates().catch(() => []);
3892
4062
  const templates = [];
3893
- for (const id of ids) {
3894
- const template = await moduleContract.getTemplateStruct(id);
4063
+ for (const id2 of ids) {
4064
+ const template = await moduleContract.getTemplateStruct(id2);
3895
4065
  templates.push({
3896
- id: Number(id),
4066
+ id: Number(id2),
3897
4067
  name: template[0],
3898
4068
  description: template[1],
3899
4069
  accessModel: Number(template[2]),
@@ -4072,7 +4242,7 @@ var require_factory = __commonJS({
4072
4242
  return null;
4073
4243
  }
4074
4244
  }
4075
- module.exports = {
4245
+ module2.exports = {
4076
4246
  getFactoryConfig,
4077
4247
  getFactoryStats,
4078
4248
  listSubDAOs,
@@ -4090,7 +4260,7 @@ var require_factory = __commonJS({
4090
4260
 
4091
4261
  // src/prompt/execute.js
4092
4262
  var require_execute = __commonJS({
4093
- "src/prompt/execute.js"(exports, module) {
4263
+ "src/prompt/execute.js"(exports2, module2) {
4094
4264
  var axios = __require("axios");
4095
4265
  var { createEchoOpenAI } = __require("@merit-systems/echo-typescript-sdk");
4096
4266
  var { generateText } = __require("ai");
@@ -4280,13 +4450,13 @@ ${JSON.stringify(residual, null, 2)}`
4280
4450
  forkDepth: Number(data.forkDepth || 0)
4281
4451
  };
4282
4452
  };
4283
- module.exports = { SageEchoExecutor };
4453
+ module2.exports = { SageEchoExecutor };
4284
4454
  }
4285
4455
  });
4286
4456
 
4287
4457
  // src/prompt/index.js
4288
4458
  var require_prompt = __commonJS({
4289
- "src/prompt/index.js"(exports, module) {
4459
+ "src/prompt/index.js"(exports2, module2) {
4290
4460
  var { Contract, getAddress } = __require("ethers");
4291
4461
  var ABI = require_abi();
4292
4462
  var { SageSDKError, CODES } = require_errors();
@@ -4348,8 +4518,8 @@ var require_prompt = __commonJS({
4348
4518
  for (let i = 1; i <= upto; i++) ids.push(i);
4349
4519
  }
4350
4520
  const results = [];
4351
- for (const id of ids) {
4352
- const key = await contract.getPromptKey(id).catch(() => null);
4521
+ for (const id2 of ids) {
4522
+ const key = await contract.getPromptKey(id2).catch(() => null);
4353
4523
  if (!key) continue;
4354
4524
  results.push(await getPromptData({ provider, registry: addr, key }));
4355
4525
  }
@@ -4361,8 +4531,8 @@ var require_prompt = __commonJS({
4361
4531
  const contract = new Contract(addr, ABI.PromptRegistry, provider);
4362
4532
  const ids = await contract.getByTagPage(tagHash, BigInt(offset), BigInt(Math.min(Number(limit), 100)));
4363
4533
  const out = [];
4364
- for (const id of ids) {
4365
- const key = await contract.getPromptKey(id).catch(() => null);
4534
+ for (const id2 of ids) {
4535
+ const key = await contract.getPromptKey(id2).catch(() => null);
4366
4536
  if (!key) continue;
4367
4537
  out.push(await getPromptData({ provider, registry: addr, key }));
4368
4538
  }
@@ -4374,8 +4544,8 @@ var require_prompt = __commonJS({
4374
4544
  const contract = new Contract(addr, ABI.PromptRegistry, provider);
4375
4545
  const ids = await contract.getByCreatorPage(getAddress(creator), BigInt(offset), BigInt(Math.min(Number(limit), 100)));
4376
4546
  const out = [];
4377
- for (const id of ids) {
4378
- const key = await contract.getPromptKey(id).catch(() => null);
4547
+ for (const id2 of ids) {
4548
+ const key = await contract.getPromptKey(id2).catch(() => null);
4379
4549
  if (!key) continue;
4380
4550
  out.push(await getPromptData({ provider, registry: addr, key }));
4381
4551
  }
@@ -4387,8 +4557,8 @@ var require_prompt = __commonJS({
4387
4557
  const contract = new Contract(addr, ABI.PromptRegistry, provider);
4388
4558
  const ids = await contract.getByCategoryPage(Number(category), BigInt(offset), BigInt(Math.min(Number(limit), 100)));
4389
4559
  const out = [];
4390
- for (const id of ids) {
4391
- const key = await contract.getPromptKey(id).catch(() => null);
4560
+ for (const id2 of ids) {
4561
+ const key = await contract.getPromptKey(id2).catch(() => null);
4392
4562
  if (!key) continue;
4393
4563
  out.push(await getPromptData({ provider, registry: addr, key }));
4394
4564
  }
@@ -4412,7 +4582,7 @@ var require_prompt = __commonJS({
4412
4582
  const contract = new Contract(addr, ABI.PromptRegistry, provider);
4413
4583
  return contract.usageCount(key).catch(() => 0);
4414
4584
  }
4415
- module.exports = {
4585
+ module2.exports = {
4416
4586
  getPromptData,
4417
4587
  listPrompts,
4418
4588
  listByTagPage,
@@ -4461,7 +4631,7 @@ var require_prompt = __commonJS({
4461
4631
 
4462
4632
  // src/ipns/index.js
4463
4633
  var require_ipns = __commonJS({
4464
- "src/ipns/index.js"(exports, module) {
4634
+ "src/ipns/index.js"(exports2, module2) {
4465
4635
  var axiosDefault = __require("axios");
4466
4636
  var contentHashLib = null;
4467
4637
  try {
@@ -4478,9 +4648,9 @@ var require_ipns = __commonJS({
4478
4648
  function removeTrailingSlash(str) {
4479
4649
  return str ? str.replace(/\/$/, "") : str;
4480
4650
  }
4481
- function ensureLeadingSlash(path) {
4482
- if (!path) return "/";
4483
- return path.startsWith("/") ? path : `/${path}`;
4651
+ function ensureLeadingSlash(path2) {
4652
+ if (!path2) return "/";
4653
+ return path2.startsWith("/") ? path2 : `/${path2}`;
4484
4654
  }
4485
4655
  function dedupe(list = []) {
4486
4656
  const seen = /* @__PURE__ */ new Set();
@@ -4575,10 +4745,10 @@ var require_ipns = __commonJS({
4575
4745
  }
4576
4746
  return null;
4577
4747
  }
4578
- async function fetchWithGateways(path, axiosInstance, gateways, { timeout, attempts = 3, baseDelay = 500, jitterMs = 250 } = {}) {
4748
+ async function fetchWithGateways(path2, axiosInstance, gateways, { timeout, attempts = 3, baseDelay = 500, jitterMs = 250 } = {}) {
4579
4749
  const errors = [];
4580
4750
  const unique = dedupe(gateways);
4581
- const suffix = path.replace(/^\/+/, "");
4751
+ const suffix = path2.replace(/^\/+/, "");
4582
4752
  for (let attempt = 0; attempt < attempts; attempt += 1) {
4583
4753
  const delayMs = attempt === 0 ? 0 : jitter(baseDelay * attempt, jitterMs);
4584
4754
  if (delayMs) await delay(delayMs);
@@ -4600,7 +4770,7 @@ var require_ipns = __commonJS({
4600
4770
  }
4601
4771
  }
4602
4772
  }
4603
- const failure = new Error(`Failed to fetch ${path} from gateways`);
4773
+ const failure = new Error(`Failed to fetch ${path2} from gateways`);
4604
4774
  failure.attempts = errors;
4605
4775
  throw failure;
4606
4776
  }
@@ -4843,7 +5013,7 @@ var require_ipns = __commonJS({
4843
5013
  }
4844
5014
  };
4845
5015
  }
4846
- module.exports = {
5016
+ module2.exports = {
4847
5017
  createClient,
4848
5018
  normalizeIpnsName,
4849
5019
  normalizeCid,
@@ -4854,7 +5024,7 @@ var require_ipns = __commonJS({
4854
5024
 
4855
5025
  // src/token/index.js
4856
5026
  var require_token = __commonJS({
4857
- "src/token/index.js"(exports, module) {
5027
+ "src/token/index.js"(exports2, module2) {
4858
5028
  var { Contract, Interface, getAddress } = __require("ethers");
4859
5029
  var ABI = require_abi();
4860
5030
  var { SageSDKError, CODES } = require_errors();
@@ -5006,7 +5176,7 @@ var require_token = __commonJS({
5006
5176
  function getBurnConstants() {
5007
5177
  return { ...BURN_CONSTANTS };
5008
5178
  }
5009
- module.exports = {
5179
+ module2.exports = {
5010
5180
  getBalance,
5011
5181
  getVotes,
5012
5182
  getTotalSupply,
@@ -5026,8 +5196,8 @@ var require_token = __commonJS({
5026
5196
 
5027
5197
  // src/personal/helpers.js
5028
5198
  var require_helpers = __commonJS({
5029
- "src/personal/helpers.js"(exports, module) {
5030
- var { getAddress, ZeroAddress, id } = __require("ethers");
5199
+ "src/personal/helpers.js"(exports2, module2) {
5200
+ var { getAddress, ZeroAddress, id: id2 } = __require("ethers");
5031
5201
  function normaliseAddress(addr, label) {
5032
5202
  if (!addr) throw new Error(`[personal] missing ${label}`);
5033
5203
  const value = addr.toString();
@@ -5038,9 +5208,9 @@ var require_helpers = __commonJS({
5038
5208
  if (typeof key === "string" && key.startsWith("0x") && key.length === 66) {
5039
5209
  return key;
5040
5210
  }
5041
- return id(key);
5211
+ return id2(key);
5042
5212
  }
5043
- module.exports = {
5213
+ module2.exports = {
5044
5214
  normaliseAddress,
5045
5215
  toBytes32Key
5046
5216
  };
@@ -5049,7 +5219,7 @@ var require_helpers = __commonJS({
5049
5219
 
5050
5220
  // src/personal/receipt.js
5051
5221
  var require_receipt = __commonJS({
5052
- "src/personal/receipt.js"(exports, module) {
5222
+ "src/personal/receipt.js"(exports2, module2) {
5053
5223
  var { Contract, getAddress, solidityPackedKeccak256 } = __require("ethers");
5054
5224
  var ABI = require_abi();
5055
5225
  var { normaliseAddress, toBytes32Key } = require_helpers();
@@ -5067,11 +5237,11 @@ var require_receipt = __commonJS({
5067
5237
  const receiptAddress = normaliseAddress(receipt, "receipt");
5068
5238
  const holderAddress = normaliseAddress(holder, "holder");
5069
5239
  const contract = new Contract(receiptAddress, ABI.PersonalLicenseReceipt, provider);
5070
- const id = typeof receiptId === "bigint" ? receiptId : BigInt(receiptId);
5071
- const balance = await contract.balanceOf(holderAddress, id);
5240
+ const id2 = typeof receiptId === "bigint" ? receiptId : BigInt(receiptId);
5241
+ const balance = await contract.balanceOf(holderAddress, id2);
5072
5242
  return typeof balance === "bigint" ? balance : BigInt(balance.toString());
5073
5243
  }
5074
- module.exports = {
5244
+ module2.exports = {
5075
5245
  computeReceiptId,
5076
5246
  getReceiptBalance
5077
5247
  };
@@ -5080,7 +5250,7 @@ var require_receipt = __commonJS({
5080
5250
 
5081
5251
  // src/personal/access.js
5082
5252
  var require_access = __commonJS({
5083
- "src/personal/access.js"(exports, module) {
5253
+ "src/personal/access.js"(exports2, module2) {
5084
5254
  var { uint8arrayToString } = __require("@lit-protocol/uint8arrays");
5085
5255
  var subgraph = require_subgraph();
5086
5256
  var { normaliseAddress, toBytes32Key } = require_helpers();
@@ -5255,7 +5425,7 @@ var require_access = __commonJS({
5255
5425
  }
5256
5426
  return uint8arrayToString(response.decryptedData, "utf8");
5257
5427
  }
5258
- module.exports = {
5428
+ module2.exports = {
5259
5429
  resolveEncryptedResource,
5260
5430
  decryptWithLit
5261
5431
  };
@@ -5264,7 +5434,7 @@ var require_access = __commonJS({
5264
5434
 
5265
5435
  // src/personal/index.js
5266
5436
  var require_personal = __commonJS({
5267
- "src/personal/index.js"(exports, module) {
5437
+ "src/personal/index.js"(exports2, module2) {
5268
5438
  var { Interface } = __require("ethers");
5269
5439
  var ABI = require_abi();
5270
5440
  var { normaliseAddress, toBytes32Key } = require_helpers();
@@ -5292,7 +5462,7 @@ var require_personal = __commonJS({
5292
5462
  ]);
5293
5463
  return { to, data, value: 0n };
5294
5464
  }
5295
- module.exports = {
5465
+ module2.exports = {
5296
5466
  buildCreatePersonalRegistryTx,
5297
5467
  buildSetPriceTx,
5298
5468
  buildBuyTx,
@@ -5304,7 +5474,7 @@ var require_personal = __commonJS({
5304
5474
 
5305
5475
  // src/utils/privateTx.js
5306
5476
  var require_privateTx = __commonJS({
5307
- "src/utils/privateTx.js"(exports, module) {
5477
+ "src/utils/privateTx.js"(exports2, module2) {
5308
5478
  var axios = __require("axios");
5309
5479
  async function sendPrivateRaw({ privateRpcUrl, signedTx, preferences = {} }) {
5310
5480
  const body = {
@@ -5336,7 +5506,7 @@ var require_privateTx = __commonJS({
5336
5506
  const sent = await signer.sendTransaction(tx);
5337
5507
  return { hash: sent.hash, tx: sent };
5338
5508
  }
5339
- module.exports = {
5509
+ module2.exports = {
5340
5510
  sendTransaction
5341
5511
  };
5342
5512
  }
@@ -5344,7 +5514,7 @@ var require_privateTx = __commonJS({
5344
5514
 
5345
5515
  // src/utils/safe.js
5346
5516
  var require_safe = __commonJS({
5347
- "src/utils/safe.js"(exports, module) {
5517
+ "src/utils/safe.js"(exports2, module2) {
5348
5518
  function toSafeTx(tx, opts = {}) {
5349
5519
  const op = Number(opts.operation ?? 0);
5350
5520
  return {
@@ -5360,13 +5530,13 @@ var require_safe = __commonJS({
5360
5530
  function toSafeTxList(txs, opts = {}) {
5361
5531
  return txs.map((t, i) => toSafeTx(t, { ...opts, nonce: opts.nonce != null ? Number(opts.nonce) + i : void 0 }));
5362
5532
  }
5363
- module.exports = { toSafeTx, toSafeTxList };
5533
+ module2.exports = { toSafeTx, toSafeTxList };
5364
5534
  }
5365
5535
  });
5366
5536
 
5367
5537
  // src/treasury/index.js
5368
5538
  var require_treasury = __commonJS({
5369
- "src/treasury/index.js"(exports, module) {
5539
+ "src/treasury/index.js"(exports2, module2) {
5370
5540
  var { Contract, Interface, getAddress } = __require("ethers");
5371
5541
  var ABI = require_abi();
5372
5542
  var { SageSDKError, CODES } = require_errors();
@@ -5447,12 +5617,12 @@ var require_treasury = __commonJS({
5447
5617
  idList = Array.from({ length: total - start }, (_, i) => start + i);
5448
5618
  }
5449
5619
  const withdrawals = [];
5450
- for (const id of idList) {
5451
- const entry = await contract.pendingWithdrawals(id).catch(() => null);
5620
+ for (const id2 of idList) {
5621
+ const entry = await contract.pendingWithdrawals(id2).catch(() => null);
5452
5622
  if (!entry || !entry.exists) continue;
5453
5623
  const [token, recipient, amount, value, requester, balanceBefore, recipientBalanceBefore, depositSnapshot, isLP, isEmergency] = entry;
5454
5624
  withdrawals.push({
5455
- id: Number(id),
5625
+ id: Number(id2),
5456
5626
  token: token && token !== ZERO_ADDRESS ? getAddress(token) : null,
5457
5627
  recipient: recipient && recipient !== ZERO_ADDRESS ? getAddress(recipient) : null,
5458
5628
  amount: toBigInt(amount),
@@ -5627,17 +5797,17 @@ var require_treasury = __commonJS({
5627
5797
  id: parsed?.id != null ? Number(parsed.id) : null
5628
5798
  };
5629
5799
  }
5630
- async function confirmWithdrawal({ signer, treasury, id, waitMs }) {
5800
+ async function confirmWithdrawal({ signer, treasury, id: id2, waitMs }) {
5631
5801
  const contract = createWriteContract({ signer, treasury });
5632
- const tx = await contract.confirmWithdrawal(Number(id));
5802
+ const tx = await contract.confirmWithdrawal(Number(id2));
5633
5803
  const receipt = await waitForReceipt({ signer, tx, waitMs });
5634
- return { transaction: tx, receipt, id: Number(id) };
5804
+ return { transaction: tx, receipt, id: Number(id2) };
5635
5805
  }
5636
- async function cancelWithdrawal({ signer, treasury, id, waitMs }) {
5806
+ async function cancelWithdrawal({ signer, treasury, id: id2, waitMs }) {
5637
5807
  const contract = createWriteContract({ signer, treasury });
5638
- const tx = await contract.cancelWithdrawal(Number(id));
5808
+ const tx = await contract.cancelWithdrawal(Number(id2));
5639
5809
  const receipt = await waitForReceipt({ signer, tx, waitMs });
5640
- return { transaction: tx, receipt, id: Number(id) };
5810
+ return { transaction: tx, receipt, id: Number(id2) };
5641
5811
  }
5642
5812
  async function setPriceOverride({ signer, treasury, token, price, ttlSeconds, waitMs }) {
5643
5813
  const contract = createWriteContract({ signer, treasury });
@@ -5679,7 +5849,7 @@ var require_treasury = __commonJS({
5679
5849
  }
5680
5850
  return null;
5681
5851
  }
5682
- module.exports = {
5852
+ module2.exports = {
5683
5853
  getTreasuryInfo,
5684
5854
  getPendingWithdrawals,
5685
5855
  getCanonicalLiquidityPlans,
@@ -5691,14 +5861,30 @@ var require_treasury = __commonJS({
5691
5861
  confirmWithdrawal,
5692
5862
  cancelWithdrawal,
5693
5863
  setPriceOverride,
5694
- clearPriceOverride
5864
+ clearPriceOverride,
5865
+ // TX builders for app usage
5866
+ buildApproveTx: ({ token, spender, amount, decimals = 18 }) => {
5867
+ if (!token || !spender) throw new SageSDKError(CODES.INVALID_ARGS, "token and spender required");
5868
+ const iface = new Interface(["function approve(address,uint256)"]);
5869
+ return { to: getAddress(token), data: iface.encodeFunctionData("approve", [getAddress(spender), BigInt(amount.toString ? amount.toString() : amount)]), value: 0n };
5870
+ },
5871
+ buildTransferTx: ({ token, to, amount, decimals = 18 }) => {
5872
+ if (!token || !to) throw new SageSDKError(CODES.INVALID_ARGS, "token and to required");
5873
+ const iface = new Interface(["function transfer(address,uint256)"]);
5874
+ return { to: getAddress(token), data: iface.encodeFunctionData("transfer", [getAddress(to), BigInt(amount.toString ? amount.toString() : amount)]), value: 0n };
5875
+ },
5876
+ buildWrapEthTx: ({ weth, amountWei }) => {
5877
+ if (!weth) throw new SageSDKError(CODES.INVALID_ARGS, "weth required");
5878
+ const iface = new Interface(["function deposit() payable"]);
5879
+ return { to: getAddress(weth), data: iface.encodeFunctionData("deposit", []), value: BigInt(amountWei.toString ? amountWei.toString() : amountWei) };
5880
+ }
5695
5881
  };
5696
5882
  }
5697
5883
  });
5698
5884
 
5699
5885
  // src/boost/index.js
5700
5886
  var require_boost = __commonJS({
5701
- "src/boost/index.js"(exports, module) {
5887
+ "src/boost/index.js"(exports2, module2) {
5702
5888
  var { Contract, Interface, getAddress } = __require("ethers");
5703
5889
  var ABI = require_abi();
5704
5890
  var { SageSDKError, CODES } = require_errors();
@@ -5777,7 +5963,7 @@ var require_boost = __commonJS({
5777
5963
  const data = DirectInterface.encodeFunctionData("fund", [Number(proposalId), BigInt(amount ?? 0n)]);
5778
5964
  return { to: addr, data, value: 0n };
5779
5965
  }
5780
- module.exports = {
5966
+ module2.exports = {
5781
5967
  getMerkleConfig,
5782
5968
  buildMerkleFundTx,
5783
5969
  buildMerkleSetRootTx,
@@ -5790,7 +5976,7 @@ var require_boost = __commonJS({
5790
5976
 
5791
5977
  // src/bounty/index.js
5792
5978
  var require_bounty = __commonJS({
5793
- "src/bounty/index.js"(exports, module) {
5979
+ "src/bounty/index.js"(exports2, module2) {
5794
5980
  var { Contract, Interface, getAddress, isAddress } = __require("ethers");
5795
5981
  var subdao = require_subdao();
5796
5982
  var governance = require_governance();
@@ -5903,8 +6089,8 @@ var require_bounty = __commonJS({
5903
6089
  ["function approveBountyCompletion(uint256,string)"],
5904
6090
  signer
5905
6091
  );
5906
- const id = BigInt(bountyId);
5907
- const tx = await bountyContract.approveBountyCompletion(id, String(deliverable));
6092
+ const id2 = BigInt(bountyId);
6093
+ const tx = await bountyContract.approveBountyCompletion(id2, String(deliverable));
5908
6094
  return tx.wait();
5909
6095
  }
5910
6096
  async function proposeApproveWinner({
@@ -5922,18 +6108,18 @@ var require_bounty = __commonJS({
5922
6108
  const context = await subdao.getSubDAOInfo({ provider, subdao: subdaoAddress });
5923
6109
  const governor = normaliseAddress("governor", context.governor);
5924
6110
  const iface = new Interface(["function approveBountyCompletion(uint256,string)"]);
5925
- const id = BigInt(bountyId);
5926
- const data = iface.encodeFunctionData("approveBountyCompletion", [id, String(deliverable)]);
6111
+ const id2 = BigInt(bountyId);
6112
+ const data = iface.encodeFunctionData("approveBountyCompletion", [id2, String(deliverable)]);
5927
6113
  const proposalCall = governance.buildProposeTx({
5928
6114
  governor,
5929
6115
  targets: [bountySystemAddress],
5930
6116
  values: [0n],
5931
6117
  calldatas: [data],
5932
- description: `Approve bounty completion for id=${id}`
6118
+ description: `Approve bounty completion for id=${id2}`
5933
6119
  });
5934
6120
  return { governor, proposalCall };
5935
6121
  }
5936
- module.exports = {
6122
+ module2.exports = {
5937
6123
  configureWinnerMode,
5938
6124
  fundFromTreasury,
5939
6125
  approveWinner,
@@ -5942,251 +6128,9 @@ var require_bounty = __commonJS({
5942
6128
  }
5943
6129
  });
5944
6130
 
5945
- // src/bond/index.js
5946
- var require_bond = __commonJS({
5947
- "src/bond/index.js"(exports, module) {
5948
- var {
5949
- Contract,
5950
- Interface,
5951
- MaxUint256,
5952
- WeiPerEther,
5953
- formatUnits,
5954
- getAddress,
5955
- parseUnits
5956
- } = __require("ethers");
5957
- var ABI = require_abi();
5958
- var { SageSDKError, CODES } = require_errors();
5959
- function normalise(address, label) {
5960
- if (!address) throw new SageSDKError(CODES.INVALID_ARGS, `${label} required`);
5961
- try {
5962
- return getAddress(address);
5963
- } catch (err) {
5964
- throw new SageSDKError(CODES.INVALID_ARGS, `invalid ${label}`, { cause: err });
5965
- }
5966
- }
5967
- var ERC20 = [
5968
- "function decimals() view returns (uint8)",
5969
- "function allowance(address owner, address spender) view returns (uint256)",
5970
- "function approve(address spender, uint256 value) returns (bool)",
5971
- "function balanceOf(address) view returns (uint256)"
5972
- ];
5973
- var BondInterface = new Interface(ABI.BondDepository);
5974
- async function getInfo({ provider, bond }) {
5975
- if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
5976
- const addr = normalise(bond, "bond");
5977
- const c = new Contract(addr, ABI.BondDepository, provider);
5978
- const [terms, price, priceUsd, totalDebt, payoutToken, principalToken, treasury] = await Promise.all([
5979
- c.terms(),
5980
- c.bondPrice(),
5981
- c.bondPriceInUSD().catch(() => 0n),
5982
- // totalDebt is keyed by payout token in this implementation
5983
- c.payoutToken().then((pt) => c.totalDebt(pt)).catch(() => 0n),
5984
- c.payoutToken(),
5985
- c.principalToken(),
5986
- c.treasury()
5987
- ]);
5988
- return {
5989
- bond: addr,
5990
- payoutToken,
5991
- principalToken,
5992
- treasury,
5993
- terms: {
5994
- controlVariable: BigInt(terms.controlVariable?.toString?.() || terms[0]?.toString?.() || "0"),
5995
- minimumPrice: BigInt(terms.minimumPrice?.toString?.() || terms[1]?.toString?.() || "0"),
5996
- maxPayoutBps: BigInt(terms.maxPayout?.toString?.() || terms[2]?.toString?.() || "0"),
5997
- maxDebt: BigInt(terms.maxDebt?.toString?.() || terms[3]?.toString?.() || "0"),
5998
- vestingTerm: BigInt(terms.vestingTerm?.toString?.() || terms[4]?.toString?.() || "0"),
5999
- feeBps: BigInt(terms.fee?.toString?.() || terms[5]?.toString?.() || "0")
6000
- },
6001
- price: BigInt(price.toString()),
6002
- priceUSD: BigInt(priceUsd.toString()),
6003
- totalDebt: BigInt(totalDebt.toString())
6004
- };
6005
- }
6006
- async function getPrice({ provider, bond }) {
6007
- if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
6008
- const c = new Contract(normalise(bond, "bond"), ABI.BondDepository, provider);
6009
- return c.bondPrice();
6010
- }
6011
- async function getUserStatus({ provider, bond, user }) {
6012
- if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
6013
- const addr = normalise(bond, "bond");
6014
- const who = normalise(user, "user");
6015
- const c = new Contract(addr, ABI.BondDepository, provider);
6016
- const [info, pending, vested] = await Promise.all([
6017
- c.bondInfo(who),
6018
- c.pendingPayout(who),
6019
- c.percentVestedFor(who).catch(() => 0n)
6020
- ]);
6021
- return {
6022
- address: who,
6023
- bond: addr,
6024
- payoutRemaining: BigInt(info?.payout?.toString?.() || info[0]?.toString?.() || "0"),
6025
- vestingBlocks: BigInt(info?.vesting?.toString?.() || info[1]?.toString?.() || "0"),
6026
- lastInteractionBlock: BigInt(info?.lastBlock?.toString?.() || info[2]?.toString?.() || "0"),
6027
- pricePaid: BigInt(info?.pricePaid?.toString?.() || info[3]?.toString?.() || "0"),
6028
- pendingPayout: BigInt(pending.toString()),
6029
- percentVestedBps: BigInt(vested.toString())
6030
- };
6031
- }
6032
- function buildDepositTx({ bond, amount, maxPrice }) {
6033
- const to = normalise(bond, "bond");
6034
- const iface = new Interface(ABI.BondDepository);
6035
- const data = iface.encodeFunctionData("deposit", [
6036
- BigInt(amount ?? 0n),
6037
- // principal amount in token units
6038
- BigInt(maxPrice ?? 0n)
6039
- // scaled by 1e18
6040
- ]);
6041
- return { to, data, value: 0n };
6042
- }
6043
- function buildRedeemTx({ bond, recipient, stake = false }) {
6044
- const to = normalise(bond, "bond");
6045
- const iface = new Interface(ABI.BondDepository);
6046
- const data = iface.encodeFunctionData("redeem", [normalise(recipient, "recipient"), !!stake]);
6047
- return { to, data, value: 0n };
6048
- }
6049
- async function getTokenDecimals({ provider, token }) {
6050
- if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
6051
- const c = new Contract(normalise(token, "token"), ERC20, provider);
6052
- const d = await c.decimals().catch(() => 18);
6053
- return Number(d);
6054
- }
6055
- async function getPrincipalAndPayout({ provider, bond }) {
6056
- if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
6057
- const c = new Contract(normalise(bond, "bond"), ABI.BondDepository, provider);
6058
- const [payoutToken, principalToken] = await Promise.all([
6059
- c.payoutToken(),
6060
- c.principalToken()
6061
- ]);
6062
- return { payoutToken, principalToken };
6063
- }
6064
- async function estimatePayout({ provider, bond, amount, principalDecimals, payoutDecimals }) {
6065
- if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
6066
- if (amount == null) throw new SageSDKError(CODES.INVALID_ARGS, "amount required");
6067
- const { principalToken, payoutToken } = await getPrincipalAndPayout({ provider, bond });
6068
- const principalDec = principalDecimals ?? await getTokenDecimals({ provider, token: principalToken });
6069
- const payoutDec = payoutDecimals ?? await getTokenDecimals({ provider, token: payoutToken });
6070
- const amountUnits = parseUnits(String(amount), principalDec);
6071
- const price = await getPrice({ provider, bond });
6072
- if (price === 0n) {
6073
- throw new SageSDKError(CODES.RPC_ERROR, "bond price returned zero");
6074
- }
6075
- const payoutUnits = amountUnits * WeiPerEther / price;
6076
- return {
6077
- inputAmount: String(amount),
6078
- expectedPayout: formatUnits(payoutUnits, payoutDec),
6079
- bondPrice: formatUnits(price, 18),
6080
- principalToken,
6081
- payoutToken,
6082
- principalDecimals: principalDec,
6083
- payoutDecimals: payoutDec
6084
- };
6085
- }
6086
- async function ensurePrincipalAllowance({ signer, bond, amount, principalToken }) {
6087
- if (!signer) throw new SageSDKError(CODES.INVALID_ARGS, "signer required");
6088
- const owner = await signer.getAddress();
6089
- const provider = signer.provider;
6090
- if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "signer requires provider");
6091
- const bondAddress = normalise(bond, "bond");
6092
- const tokenAddress = principalToken ? normalise(principalToken, "principalToken") : (await getPrincipalAndPayout({ provider, bond: bondAddress })).principalToken;
6093
- const principal = new Contract(tokenAddress, ERC20, signer);
6094
- const allowance = await principal.allowance(owner, bondAddress);
6095
- if (allowance >= amount) {
6096
- return { approved: false, transactionHash: null };
6097
- }
6098
- const approvalTx = await principal.approve(bondAddress, MaxUint256);
6099
- const receipt = await approvalTx.wait();
6100
- return {
6101
- approved: true,
6102
- transactionHash: receipt.hash ?? approvalTx.hash ?? null
6103
- };
6104
- }
6105
- async function purchase({ signer, bond, amount, maxPrice }) {
6106
- if (!signer) throw new SageSDKError(CODES.INVALID_ARGS, "signer required");
6107
- if (amount == null) throw new SageSDKError(CODES.INVALID_ARGS, "amount required");
6108
- if (maxPrice == null) throw new SageSDKError(CODES.INVALID_ARGS, "maxPrice required");
6109
- const provider = signer.provider;
6110
- if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "signer requires provider");
6111
- const bondAddress = normalise(bond, "bond");
6112
- const bondContract = new Contract(bondAddress, ABI.BondDepository, signer);
6113
- const { principalToken, payoutToken } = await getPrincipalAndPayout({ provider, bond: bondAddress });
6114
- const principalDec = await getTokenDecimals({ provider, token: principalToken });
6115
- const payoutDec = await getTokenDecimals({ provider, token: payoutToken });
6116
- const amountUnits = parseUnits(String(amount), principalDec);
6117
- const maxPriceUnits = parseUnits(String(maxPrice), 18);
6118
- const currentPrice = await getPrice({ provider, bond: bondAddress });
6119
- if (currentPrice > maxPriceUnits) {
6120
- throw new SageSDKError(CODES.INVALID_ARGS, "current bond price exceeds max price", {
6121
- currentPrice: formatUnits(currentPrice, 18),
6122
- maxPrice: String(maxPrice)
6123
- });
6124
- }
6125
- await ensurePrincipalAllowance({ signer, bond: bondAddress, amount: amountUnits, principalToken });
6126
- const tx = await bondContract.deposit(amountUnits, maxPriceUnits);
6127
- const receipt = await tx.wait();
6128
- let depositEvent = null;
6129
- for (const log of receipt.logs || []) {
6130
- try {
6131
- const parsed = BondInterface.parseLog(log);
6132
- if (parsed?.name === "BondCreated") {
6133
- depositEvent = parsed.args;
6134
- break;
6135
- }
6136
- } catch (_) {
6137
- }
6138
- }
6139
- return {
6140
- transactionHash: receipt.hash ?? tx.hash ?? null,
6141
- deposit: formatUnits(depositEvent?.deposit ?? amountUnits, principalDec),
6142
- payout: depositEvent?.payout != null ? formatUnits(depositEvent.payout, payoutDec) : null,
6143
- expires: depositEvent?.expires ?? null,
6144
- price: formatUnits(currentPrice, 18)
6145
- };
6146
- }
6147
- async function redeem({ signer, bond, recipient, stake = false }) {
6148
- if (!signer) throw new SageSDKError(CODES.INVALID_ARGS, "signer required");
6149
- const provider = signer.provider;
6150
- if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "signer requires provider");
6151
- const bondAddress = normalise(bond, "bond");
6152
- const user = normalise(recipient || await signer.getAddress(), "recipient");
6153
- const bondContract = new Contract(bondAddress, ABI.BondDepository, signer);
6154
- const { payoutToken } = await getPrincipalAndPayout({ provider, bond: bondAddress });
6155
- const payoutDec = await getTokenDecimals({ provider, token: payoutToken });
6156
- const pending = await bondContract.pendingPayout(user);
6157
- if (pending === 0n) {
6158
- return {
6159
- transactionHash: null,
6160
- redeemed: "0",
6161
- message: "No bonds available for redemption"
6162
- };
6163
- }
6164
- const tx = await bondContract.redeem(user, !!stake);
6165
- const receipt = await tx.wait();
6166
- return {
6167
- transactionHash: receipt.hash ?? tx.hash ?? null,
6168
- redeemed: formatUnits(pending, payoutDec)
6169
- };
6170
- }
6171
- module.exports = {
6172
- getInfo,
6173
- getPrice,
6174
- getUserStatus,
6175
- buildDepositTx,
6176
- buildRedeemTx,
6177
- getTokenDecimals,
6178
- getPrincipalAndPayout,
6179
- estimatePayout,
6180
- ensurePrincipalAllowance,
6181
- purchase,
6182
- redeem
6183
- };
6184
- }
6185
- });
6186
-
6187
6131
  // src/utils/provider.js
6188
6132
  var require_provider = __commonJS({
6189
- "src/utils/provider.js"(exports, module) {
6133
+ "src/utils/provider.js"(exports2, module2) {
6190
6134
  var { JsonRpcProvider } = __require("ethers");
6191
6135
  function assertString(value, name) {
6192
6136
  if (typeof value !== "string" || value.trim().length === 0) {
@@ -6197,7 +6141,7 @@ var require_provider = __commonJS({
6197
6141
  assertString(rpcUrl, "rpcUrl");
6198
6142
  return new JsonRpcProvider(rpcUrl);
6199
6143
  }
6200
- module.exports = {
6144
+ module2.exports = {
6201
6145
  getProvider,
6202
6146
  assertString
6203
6147
  };
@@ -6206,8 +6150,8 @@ var require_provider = __commonJS({
6206
6150
 
6207
6151
  // src/wallet/index.js
6208
6152
  var require_wallet = __commonJS({
6209
- "src/wallet/index.js"(exports, module) {
6210
- var { ethers } = __require("ethers");
6153
+ "src/wallet/index.js"(exports2, module2) {
6154
+ var { ethers: ethers2 } = __require("ethers");
6211
6155
  var { SageSDKError, CODES } = require_errors();
6212
6156
  var { getProvider } = require_provider();
6213
6157
  function isBrowser() {
@@ -6234,7 +6178,7 @@ var require_wallet = __commonJS({
6234
6178
  const rpcUrl = src.rpcUrl || getDefaultRpc();
6235
6179
  const provider = getProvider({ rpcUrl });
6236
6180
  const pk = src.privateKey.startsWith("0x") ? src.privateKey : "0x" + src.privateKey;
6237
- const signer = new ethers.Wallet(pk, provider);
6181
+ const signer = new ethers2.Wallet(pk, provider);
6238
6182
  return { signer, provider };
6239
6183
  }
6240
6184
  case "pkEnv": {
@@ -6243,7 +6187,7 @@ var require_wallet = __commonJS({
6243
6187
  if (!pk) throw new SageSDKError(CODES.INVALID_ARGS, `${envName} not set`);
6244
6188
  const rpcUrl = src.rpcUrl || getDefaultRpc();
6245
6189
  const provider = getProvider({ rpcUrl });
6246
- const signer = new ethers.Wallet(pk.startsWith("0x") ? pk : "0x" + pk, provider);
6190
+ const signer = new ethers2.Wallet(pk.startsWith("0x") ? pk : "0x" + pk, provider);
6247
6191
  return { signer, provider };
6248
6192
  }
6249
6193
  case "rpc": {
@@ -6254,7 +6198,7 @@ var require_wallet = __commonJS({
6254
6198
  case "injected": {
6255
6199
  if (!isBrowser()) throw new SageSDKError(CODES.MISSING_DEPENDENCY, "Injected provider only available in browser");
6256
6200
  try {
6257
- const provider = new ethers.BrowserProvider(window.ethereum);
6201
+ const provider = new ethers2.BrowserProvider(window.ethereum);
6258
6202
  const signer = await provider.getSigner();
6259
6203
  return { signer, provider };
6260
6204
  } catch (e) {
@@ -6282,7 +6226,7 @@ var require_wallet = __commonJS({
6282
6226
  return process.env.RPC_URL || process.env.BASE_SEPOLIA_RPC_URL || process.env.BASE_SEPOLIA_RPC || "https://base-sepolia.publicnode.com";
6283
6227
  }
6284
6228
  function create() {
6285
- const wallet = ethers.Wallet.createRandom();
6229
+ const wallet = ethers2.Wallet.createRandom();
6286
6230
  return {
6287
6231
  address: wallet.address,
6288
6232
  // Intentionally do not expose privateKey by default to avoid accidental leaks
@@ -6295,7 +6239,7 @@ var require_wallet = __commonJS({
6295
6239
  throw new SageSDKError(CODES.INVALID_ARGS, "secret required to import wallet");
6296
6240
  }
6297
6241
  const pk = secret.startsWith("0x") ? secret : "0x" + secret;
6298
- const wallet = new ethers.Wallet(pk);
6242
+ const wallet = new ethers2.Wallet(pk);
6299
6243
  return { address: wallet.address, _wallet: wallet };
6300
6244
  }
6301
6245
  function exportWallet(w) {
@@ -6314,7 +6258,7 @@ var require_wallet = __commonJS({
6314
6258
  async function connectInjected() {
6315
6259
  return loadSigner("injected");
6316
6260
  }
6317
- module.exports = {
6261
+ module2.exports = {
6318
6262
  listProviders,
6319
6263
  loadSigner,
6320
6264
  connectInjected,
@@ -6330,7 +6274,7 @@ var require_wallet = __commonJS({
6330
6274
  } catch (_) {
6331
6275
  if (!opts || !opts.mnemonic || !opts.rpcUrl) throw new SageSDKError(CODES.INVALID_ARGS, "mnemonic and rpcUrl required");
6332
6276
  const provider = getProvider({ rpcUrl: opts.rpcUrl });
6333
- const wallet = ethers.HDNodeWallet.fromPhrase(opts.mnemonic, opts.path);
6277
+ const wallet = ethers2.HDNodeWallet.fromPhrase(opts.mnemonic, opts.path);
6334
6278
  const signer = wallet.connect(provider);
6335
6279
  return { signer, provider };
6336
6280
  }
@@ -6342,7 +6286,7 @@ var require_wallet = __commonJS({
6342
6286
  } catch (_) {
6343
6287
  if (!opts || !opts.json || !opts.password || !opts.rpcUrl) throw new SageSDKError(CODES.INVALID_ARGS, "json, password, rpcUrl required");
6344
6288
  const provider = getProvider({ rpcUrl: opts.rpcUrl });
6345
- const signer = await ethers.Wallet.fromEncryptedJson(opts.json, opts.password);
6289
+ const signer = await ethers2.Wallet.fromEncryptedJson(opts.json, opts.password);
6346
6290
  return { signer: signer.connect(provider), provider };
6347
6291
  }
6348
6292
  },
@@ -6388,7 +6332,7 @@ var require_wallet = __commonJS({
6388
6332
 
6389
6333
  // src/wallet/session.js
6390
6334
  var require_session = __commonJS({
6391
- "src/wallet/session.js"(exports, module) {
6335
+ "src/wallet/session.js"(exports2, module2) {
6392
6336
  var DEFAULT_WALLET_TYPE = "cast";
6393
6337
  function resolveWalletType({ config, env = process.env } = {}) {
6394
6338
  const envType = String(env.WALLET_TYPE || "").trim();
@@ -6416,7 +6360,7 @@ var require_session = __commonJS({
6416
6360
  return false;
6417
6361
  }
6418
6362
  }
6419
- module.exports = {
6363
+ module2.exports = {
6420
6364
  DEFAULT_WALLET_TYPE,
6421
6365
  resolveWalletType,
6422
6366
  shouldAllowInsecurePrivateKey,
@@ -6444,6 +6388,32 @@ var require_cast_manager = __commonJS({
6444
6388
  blue: (text) => `\x1B[34m${text}\x1B[0m`,
6445
6389
  cyan: (text) => `\x1B[36m${text}\x1B[0m`
6446
6390
  };
6391
+ function optionalRequire(id) {
6392
+ try {
6393
+ const req = typeof __non_webpack_require__ === "function" ? __non_webpack_require__ : eval("require");
6394
+ return req(id);
6395
+ } catch (_) {
6396
+ return null;
6397
+ }
6398
+ }
6399
+ function loadConfigBridge() {
6400
+ const shared = optionalRequire("@sage-protocol/shared");
6401
+ if (shared) {
6402
+ if (shared.ConfigManager) return shared.ConfigManager;
6403
+ if (typeof shared.getProjectDir === "function" || typeof shared.readProfiles === "function") {
6404
+ return shared;
6405
+ }
6406
+ }
6407
+ const local = optionalRequire("./config");
6408
+ if (local) {
6409
+ if (local.ConfigManager) return local.ConfigManager;
6410
+ return local;
6411
+ }
6412
+ return {
6413
+ getProjectDir: () => process.cwd(),
6414
+ readProfiles: () => ({ profiles: {}, activeProfile: "default" })
6415
+ };
6416
+ }
6447
6417
  var CastSigner = class extends ethers.VoidSigner {
6448
6418
  constructor(address, provider, castWalletManager) {
6449
6419
  super(address, provider);
@@ -6578,13 +6548,8 @@ var require_cast_manager = __commonJS({
6578
6548
  if (!address) return;
6579
6549
  try {
6580
6550
  const normalized = ethers.getAddress(address);
6581
- let cfgModule;
6582
- try {
6583
- ({ ConfigManager: cfgModule } = __require("@sage-protocol/shared"));
6584
- } catch (_) {
6585
- cfgModule = __require("./config");
6586
- }
6587
- const projectDir = cfgModule.getProjectDir ? cfgModule.getProjectDir() : process.cwd();
6551
+ const cfgModule = loadConfigBridge();
6552
+ const projectDir = typeof cfgModule.getProjectDir === "function" ? cfgModule.getProjectDir() : process.cwd();
6588
6553
  const cfgPath = path.join(projectDir, ".sage", "config.json");
6589
6554
  const current = fs.existsSync(cfgPath) ? JSON.parse(fs.readFileSync(cfgPath, "utf8") || "{}") : {};
6590
6555
  const active = current.activeProfile || "default";
@@ -6670,14 +6635,9 @@ var require_cast_manager = __commonJS({
6670
6635
  console.log(colors.blue("\u{1F517} Connecting wallet using Cast keystore..."));
6671
6636
  this.ensureKeystoreDir();
6672
6637
  try {
6673
- let cliConfig;
6674
- try {
6675
- ({ ConfigManager: cliConfig } = __require("@sage-protocol/shared"));
6676
- } catch (_) {
6677
- cliConfig = __require("./config");
6678
- }
6679
- const profiles = cliConfig.readProfiles();
6680
- const active = profiles.activeProfile || "default";
6638
+ const cliConfig = loadConfigBridge();
6639
+ const profiles = typeof cliConfig.readProfiles === "function" ? cliConfig.readProfiles() : { profiles: {}, activeProfile: "default" };
6640
+ const active = profiles?.activeProfile || "default";
6681
6641
  const wanted = profiles?.profiles?.[active]?.wallet?.defaultAccount;
6682
6642
  if (wanted && this.keystoreDir && fs.existsSync(this.keystoreDir)) {
6683
6643
  const files = fs.readdirSync(this.keystoreDir);
@@ -6713,7 +6673,7 @@ var require_cast_manager = __commonJS({
6713
6673
  this.ensureAccountSynced(walletData.address, walletData.keystorePath, { silent: true });
6714
6674
  }
6715
6675
  try {
6716
- const { checkRpcHealth } = __require("./utils/rpc-health");
6676
+ const { checkRpcHealth } = optionalRequire("./utils/rpc-health") || {};
6717
6677
  const candidates = [
6718
6678
  this.rpcUrl,
6719
6679
  process.env.BASE_SEPOLIA_RPC,
@@ -7675,10 +7635,10 @@ ${error}` : ""}`;
7675
7635
 
7676
7636
  // src/wallet/cdp-manager.js
7677
7637
  var require_cdp_manager = __commonJS({
7678
- "src/wallet/cdp-manager.js"(exports, module) {
7679
- var fs = __require("fs");
7680
- var path = __require("path");
7681
- var { ethers } = __require("ethers");
7638
+ "src/wallet/cdp-manager.js"(exports2, module2) {
7639
+ var fs2 = __require("fs");
7640
+ var path2 = __require("path");
7641
+ var { ethers: ethers2 } = __require("ethers");
7682
7642
  var MinimalCdpSigner = class {
7683
7643
  constructor(manager, provider) {
7684
7644
  this._mgr = manager;
@@ -7707,7 +7667,7 @@ var require_cdp_manager = __commonJS({
7707
7667
  this.provider = null;
7708
7668
  this.signer = null;
7709
7669
  this.connected = false;
7710
- this._profilePath = path.join(process.cwd(), ".cdp-wallet.json");
7670
+ this._profilePath = path2.join(process.cwd(), ".cdp-wallet.json");
7711
7671
  this._client = null;
7712
7672
  this._userId = null;
7713
7673
  this._walletId = null;
@@ -7730,9 +7690,9 @@ var require_cdp_manager = __commonJS({
7730
7690
  }
7731
7691
  }
7732
7692
  _loadProfile() {
7733
- if (fs.existsSync(this._profilePath)) {
7693
+ if (fs2.existsSync(this._profilePath)) {
7734
7694
  try {
7735
- const x = JSON.parse(fs.readFileSync(this._profilePath, "utf8"));
7695
+ const x = JSON.parse(fs2.readFileSync(this._profilePath, "utf8"));
7736
7696
  this._userId = x.userId || null;
7737
7697
  this._walletId = x.walletId || null;
7738
7698
  this.account = x.address || null;
@@ -7742,14 +7702,14 @@ var require_cdp_manager = __commonJS({
7742
7702
  }
7743
7703
  _saveProfile() {
7744
7704
  const payload = { userId: this._userId, walletId: this._walletId, address: this.account };
7745
- fs.writeFileSync(this._profilePath, JSON.stringify(payload, null, 2));
7705
+ fs2.writeFileSync(this._profilePath, JSON.stringify(payload, null, 2));
7746
7706
  }
7747
7707
  async connect() {
7748
7708
  if (!process.env.CDP_API_KEY_ID || !process.env.CDP_API_KEY_SECRET) {
7749
7709
  throw new Error("Missing CDP_API_KEY_ID/CDP_API_KEY_SECRET in env");
7750
7710
  }
7751
7711
  const rpc = process.env.RPC_URL || "https://base-sepolia.publicnode.com";
7752
- this.provider = new ethers.JsonRpcProvider(rpc);
7712
+ this.provider = new ethers2.JsonRpcProvider(rpc);
7753
7713
  this._loadProfile();
7754
7714
  let client;
7755
7715
  try {
@@ -7761,7 +7721,7 @@ var require_cdp_manager = __commonJS({
7761
7721
  const email = process.env.CDP_USER_EMAIL || await this._promptEmail();
7762
7722
  const fakeUserId = `user_${Buffer.from(email).toString("hex").slice(0, 8)}`;
7763
7723
  const fakeWalletId = `w_${Date.now()}`;
7764
- const fakeAddress = this.account || ethers.Wallet.createRandom().address;
7724
+ const fakeAddress = this.account || ethers2.Wallet.createRandom().address;
7765
7725
  this._userId = fakeUserId;
7766
7726
  this._walletId = fakeWalletId;
7767
7727
  this.account = fakeAddress;
@@ -7775,7 +7735,7 @@ var require_cdp_manager = __commonJS({
7775
7735
  console.log("\u{1F4CD} Address:", this.account);
7776
7736
  try {
7777
7737
  const bal = await this.getBalance();
7778
- console.log("\u{1F4B0} Balance:", ethers.formatEther(bal), "ETH");
7738
+ console.log("\u{1F4B0} Balance:", ethers2.formatEther(bal), "ETH");
7779
7739
  } catch (_) {
7780
7740
  }
7781
7741
  }
@@ -7800,7 +7760,7 @@ var require_cdp_manager = __commonJS({
7800
7760
  if (!process.env.SAGE_QUIET_JSON) {
7801
7761
  console.log("\u{1F4DD} Transaction Details:");
7802
7762
  console.log("To:", to);
7803
- console.log("Value:", ethers.formatEther(value));
7763
+ console.log("Value:", ethers2.formatEther(value));
7804
7764
  console.log("Data:", data);
7805
7765
  console.log("\u{1F4E8} Check your email/app to approve the transaction...");
7806
7766
  }
@@ -7845,14 +7805,14 @@ var require_cdp_manager = __commonJS({
7845
7805
  if (!process.env.SAGE_QUIET_JSON) console.log("\u2705 CDP wallet disconnected");
7846
7806
  }
7847
7807
  };
7848
- module.exports = CDPWalletManager;
7808
+ module2.exports = CDPWalletManager;
7849
7809
  }
7850
7810
  });
7851
7811
 
7852
7812
  // src/wallet/typed.js
7853
7813
  var require_typed = __commonJS({
7854
- "src/wallet/typed.js"(exports, module) {
7855
- var { ethers } = __require("ethers");
7814
+ "src/wallet/typed.js"(exports2, module2) {
7815
+ var { ethers: ethers2 } = __require("ethers");
7856
7816
  function buildGovernorDomain({ name, chainId, verifyingContract }) {
7857
7817
  if (!name || !chainId || !verifyingContract) throw new Error("name, chainId, verifyingContract required");
7858
7818
  return { name, version: "1", chainId: Number(chainId), verifyingContract };
@@ -7888,7 +7848,7 @@ var require_typed = __commonJS({
7888
7848
  const typed = { owner, spender, value, nonce, deadline };
7889
7849
  return await signer.signTypedData(domain, PermitTypes, typed);
7890
7850
  }
7891
- module.exports = {
7851
+ module2.exports = {
7892
7852
  buildGovernorDomain,
7893
7853
  BallotTypes,
7894
7854
  signVoteBySig,
@@ -7901,7 +7861,7 @@ var require_typed = __commonJS({
7901
7861
 
7902
7862
  // src/doppler/index.js
7903
7863
  var require_doppler = __commonJS({
7904
- "src/doppler/index.js"(exports, module) {
7864
+ "src/doppler/index.js"(exports2, module2) {
7905
7865
  var { createPublicClient, createWalletClient, http } = __require("viem");
7906
7866
  var { privateKeyToAccount } = __require("viem/accounts");
7907
7867
  var { erc20Abi } = __require("viem");
@@ -7969,12 +7929,40 @@ var require_doppler = __commonJS({
7969
7929
  }
7970
7930
  return { auctionAddress, note: "Lens API not available in this doppler-sdk version" };
7971
7931
  }
7932
+ async function listAuctions(sdk, { limit = 10, cursor } = {}) {
7933
+ const lens = sdk.lens;
7934
+ if (lens) {
7935
+ if (typeof lens.listAuctions === "function") {
7936
+ try {
7937
+ return await lens.listAuctions({ limit, cursor });
7938
+ } catch (e) {
7939
+ }
7940
+ }
7941
+ if (typeof lens.getAuctions === "function") {
7942
+ try {
7943
+ return await lens.getAuctions({ limit, cursor });
7944
+ } catch (e) {
7945
+ }
7946
+ }
7947
+ }
7948
+ const fac = sdk.factory;
7949
+ if (fac && typeof fac.listAuctions === "function") {
7950
+ try {
7951
+ return await fac.listAuctions({ limit, cursor });
7952
+ } catch (e) {
7953
+ }
7954
+ }
7955
+ return { ok: false, error: "LIST_UNSUPPORTED", message: "Listing auctions not supported by this doppler-sdk version" };
7956
+ }
7972
7957
  async function buyTokens(sdk, { auctionAddress, numeraireAmount }) {
7973
7958
  const trade = sdk.trade || sdk.swap || sdk.auction;
7974
7959
  if (trade && typeof trade.buy === "function") {
7975
- return await trade.buy({ auctionAddress, numeraireAmount });
7960
+ try {
7961
+ return await trade.buy({ auctionAddress, numeraireAmount });
7962
+ } catch (e) {
7963
+ }
7976
7964
  }
7977
- throw new Error("Buy is not supported by the current doppler-sdk version");
7965
+ return { ok: false, error: "BUY_UNSUPPORTED", message: "Buy not supported by this doppler-sdk version. Use executeV3BuyExactIn/urExecute helpers or upgrade doppler-sdk." };
7978
7966
  }
7979
7967
  async function migrate(sdk, asset) {
7980
7968
  if (sdk.airlock && typeof sdk.airlock.migrate === "function") {
@@ -7982,14 +7970,15 @@ var require_doppler = __commonJS({
7982
7970
  }
7983
7971
  throw new Error("Migrate is not supported by the current doppler-sdk version");
7984
7972
  }
7985
- module.exports = {
7973
+ module2.exports = {
7986
7974
  initDoppler,
7987
7975
  deployDynamicAuction,
7988
7976
  getAuctionStatus,
7977
+ listAuctions,
7989
7978
  buyTokens,
7990
7979
  migrate
7991
7980
  };
7992
- module.exports.deployStaticAuction = async function deployStaticAuction(sdk, user, p) {
7981
+ module2.exports.deployStaticAuction = async function deployStaticAuction(sdk, user, p) {
7993
7982
  const StaticAuctionBuilder = dopplerLib.StaticAuctionBuilder || dopplerLib.default?.StaticAuctionBuilder;
7994
7983
  if (!StaticAuctionBuilder) throw new Error("StaticAuctionBuilder missing from doppler-sdk");
7995
7984
  const builder = new StaticAuctionBuilder().tokenConfig({ name: p.token.name, symbol: p.token.symbol, tokenURI: p.token.tokenURI }).saleConfig({ initialSupply: p.sale.initialSupply, numTokensToSell: p.sale.numTokensToSell, numeraire: p.sale.numeraire }).poolByTicks({ startTick: p.pool.startTick, endTick: p.pool.endTick, fee: p.pool.fee, numPositions: p.pool.numPositions || 15 }).withUserAddress(user);
@@ -8001,11 +7990,11 @@ var require_doppler = __commonJS({
8001
7990
  const res = await sdk.factory.createStaticAuction(params);
8002
7991
  return res;
8003
7992
  };
8004
- module.exports.getStaticPoolInfo = async function getStaticPoolInfo(sdk, poolAddress) {
7993
+ module2.exports.getStaticPoolInfo = async function getStaticPoolInfo(sdk, poolAddress) {
8005
7994
  const auction = await sdk.getStaticAuction(poolAddress);
8006
7995
  return auction.getPoolInfo();
8007
7996
  };
8008
- module.exports.quoteV3ExactIn = async function quoteV3ExactIn(sdk, { tokenIn, tokenOut, amountIn, fee, sqrtPriceLimitX96 = 0n }) {
7997
+ module2.exports.quoteV3ExactIn = async function quoteV3ExactIn(sdk, { tokenIn, tokenOut, amountIn, fee, sqrtPriceLimitX96 = 0n }) {
8009
7998
  return sdk.quoter.quoteExactInputV3({ tokenIn, tokenOut, amountIn, fee, sqrtPriceLimitX96 });
8010
7999
  };
8011
8000
  var WETH_ABI = [
@@ -8013,7 +8002,7 @@ var require_doppler = __commonJS({
8013
8002
  { type: "function", name: "withdraw", stateMutability: "nonpayable", inputs: [{ name: "wad", type: "uint256" }], outputs: [] },
8014
8003
  { type: "function", name: "balanceOf", stateMutability: "view", inputs: [{ name: "a", type: "address" }], outputs: [{ type: "uint256" }] }
8015
8004
  ];
8016
- module.exports.wrapEthToWethIfNeeded = async function wrapEthToWethIfNeeded({ rpcUrl, chainId, privateKey, weth, owner, minAmount }) {
8005
+ module2.exports.wrapEthToWethIfNeeded = async function wrapEthToWethIfNeeded({ rpcUrl, chainId, privateKey, weth, owner, minAmount }) {
8017
8006
  const chain = getChainById(chainId);
8018
8007
  const accountObj = privateKeyToAccount(privateKey.startsWith("0x") ? privateKey : `0x${privateKey}`);
8019
8008
  const publicClient = createPublicClient({ chain, transport: http(rpcUrl) });
@@ -8025,17 +8014,17 @@ var require_doppler = __commonJS({
8025
8014
  await publicClient.waitForTransactionReceipt({ hash });
8026
8015
  return { deposited: needed, hash };
8027
8016
  };
8028
- module.exports.getDynamicHookInfo = async function getDynamicHookInfo(sdk, hookAddress) {
8017
+ module2.exports.getDynamicHookInfo = async function getDynamicHookInfo(sdk, hookAddress) {
8029
8018
  const auction = await sdk.getDynamicAuction(hookAddress);
8030
8019
  return auction.getHookInfo();
8031
8020
  };
8032
- module.exports.quoteV4ExactIn = async function quoteV4ExactIn(sdk, { poolKey, zeroForOne, exactAmount, hookData }) {
8021
+ module2.exports.quoteV4ExactIn = async function quoteV4ExactIn(sdk, { poolKey, zeroForOne, exactAmount, hookData }) {
8033
8022
  return sdk.quoter.quoteExactInputV4({ poolKey, zeroForOne, exactAmount, hookData });
8034
8023
  };
8035
8024
  var UR_ABI = [
8036
8025
  { name: "execute", type: "function", stateMutability: "payable", inputs: [{ name: "commands", type: "bytes" }, { name: "inputs", type: "bytes[]" }], outputs: [] }
8037
8026
  ];
8038
- module.exports.urExecute = async function urExecute({ rpcUrl, chainId, privateKey, universalRouter, commands, inputs, value }) {
8027
+ module2.exports.urExecute = async function urExecute({ rpcUrl, chainId, privateKey, universalRouter, commands, inputs, value }) {
8039
8028
  const chain = getChainById(chainId);
8040
8029
  const accountObj = privateKeyToAccount(privateKey.startsWith("0x") ? privateKey : `0x${privateKey}`);
8041
8030
  const publicClient = createPublicClient({ chain, transport: http(rpcUrl) });
@@ -8044,7 +8033,7 @@ var require_doppler = __commonJS({
8044
8033
  const receipt = await publicClient.waitForTransactionReceipt({ hash });
8045
8034
  return { hash, receipt };
8046
8035
  };
8047
- module.exports.simulateCreateStaticAuction = async function simulateCreateStaticAuction(sdk, builderParams) {
8036
+ module2.exports.simulateCreateStaticAuction = async function simulateCreateStaticAuction(sdk, builderParams) {
8048
8037
  const StaticAuctionBuilder = dopplerLib.StaticAuctionBuilder || dopplerLib.default?.StaticAuctionBuilder;
8049
8038
  if (!StaticAuctionBuilder) throw new Error("StaticAuctionBuilder missing from doppler-sdk");
8050
8039
  const builder = new StaticAuctionBuilder().tokenConfig(builderParams.token).saleConfig(builderParams.sale).poolByTicks(builderParams.pool).withUserAddress(builderParams.userAddress);
@@ -8055,10 +8044,10 @@ var require_doppler = __commonJS({
8055
8044
  const params = builder.build();
8056
8045
  return sdk.factory.simulateCreateStaticAuction(params);
8057
8046
  };
8058
- module.exports.simulateBundleExactOut = async function simulateBundleExactOut(sdk, createParams, { tokenIn, tokenOut, amount, fee, sqrtPriceLimitX96 = 0n }) {
8047
+ module2.exports.simulateBundleExactOut = async function simulateBundleExactOut(sdk, createParams, { tokenIn, tokenOut, amount, fee, sqrtPriceLimitX96 = 0n }) {
8059
8048
  return sdk.factory.simulateBundleExactOutput(createParams, { tokenIn, tokenOut, amount, fee, sqrtPriceLimitX96 });
8060
8049
  };
8061
- module.exports.factoryBundle = async function factoryBundle(sdk, createParams, { commands, inputs, value }) {
8050
+ module2.exports.factoryBundle = async function factoryBundle(sdk, createParams, { commands, inputs, value }) {
8062
8051
  return sdk.factory.bundle(createParams, commands, inputs, { value });
8063
8052
  };
8064
8053
  var V3_SWAP_ROUTER_ABI = [
@@ -8085,7 +8074,7 @@ var require_doppler = __commonJS({
8085
8074
  outputs: [{ name: "amountOut", type: "uint256" }]
8086
8075
  }
8087
8076
  ];
8088
- module.exports.executeV3BuyExactIn = async function executeV3BuyExactIn({
8077
+ module2.exports.executeV3BuyExactIn = async function executeV3BuyExactIn({
8089
8078
  rpcUrl,
8090
8079
  chainId,
8091
8080
  privateKey,
@@ -8140,15 +8129,962 @@ var require_doppler = __commonJS({
8140
8129
  }
8141
8130
  });
8142
8131
 
8132
+ // src/services/utils/cache.js
8133
+ var require_cache = __commonJS({
8134
+ "src/services/utils/cache.js"(exports2, module2) {
8135
+ var SimpleCache = class {
8136
+ constructor(options = {}) {
8137
+ this.enabled = options.enabled !== false;
8138
+ this.defaultTTL = options.ttl || 3e4;
8139
+ this.maxSize = options.maxSize || 100;
8140
+ this._store = /* @__PURE__ */ new Map();
8141
+ }
8142
+ /**
8143
+ * Get value from cache
8144
+ * @param {string} key - Cache key
8145
+ * @returns {any|null} - Cached value or null if expired/missing
8146
+ */
8147
+ get(key) {
8148
+ if (!this.enabled) return null;
8149
+ const entry = this._store.get(key);
8150
+ if (!entry) return null;
8151
+ if (Date.now() > entry.expires) {
8152
+ this._store.delete(key);
8153
+ return null;
8154
+ }
8155
+ return entry.data;
8156
+ }
8157
+ /**
8158
+ * Set value in cache with TTL
8159
+ * @param {string} key - Cache key
8160
+ * @param {any} data - Data to cache
8161
+ * @param {number} ttl - Time to live in milliseconds (optional)
8162
+ */
8163
+ set(key, data, ttl) {
8164
+ if (!this.enabled) return;
8165
+ if (this._store.size >= this.maxSize && !this._store.has(key)) {
8166
+ const firstKey = this._store.keys().next().value;
8167
+ this._store.delete(firstKey);
8168
+ }
8169
+ this._store.set(key, {
8170
+ data,
8171
+ expires: Date.now() + (ttl || this.defaultTTL)
8172
+ });
8173
+ }
8174
+ /**
8175
+ * Clear all cached entries
8176
+ */
8177
+ clear() {
8178
+ this._store.clear();
8179
+ }
8180
+ /**
8181
+ * Delete specific key
8182
+ * @param {string} key - Cache key to delete
8183
+ */
8184
+ delete(key) {
8185
+ this._store.delete(key);
8186
+ }
8187
+ /**
8188
+ * Get cache statistics
8189
+ * @returns {object} - Cache stats (size, enabled)
8190
+ */
8191
+ stats() {
8192
+ return {
8193
+ size: this._store.size,
8194
+ maxSize: this.maxSize,
8195
+ enabled: this.enabled
8196
+ };
8197
+ }
8198
+ };
8199
+ module2.exports = { SimpleCache };
8200
+ }
8201
+ });
8202
+
8203
+ // src/services/utils/retry.js
8204
+ var require_retry = __commonJS({
8205
+ "src/services/utils/retry.js"(exports2, module2) {
8206
+ async function retryWithBackoff(fn, options = {}) {
8207
+ const {
8208
+ attempts = 3,
8209
+ baseDelay = 1e3,
8210
+ maxDelay = 1e4,
8211
+ onRetry = null
8212
+ } = options;
8213
+ let lastError;
8214
+ for (let i = 0; i < attempts; i++) {
8215
+ try {
8216
+ return await fn();
8217
+ } catch (error) {
8218
+ lastError = error;
8219
+ if (i === attempts - 1) {
8220
+ break;
8221
+ }
8222
+ const delay = Math.min(baseDelay * Math.pow(2, i), maxDelay);
8223
+ if (onRetry) {
8224
+ onRetry({
8225
+ attempt: i + 1,
8226
+ totalAttempts: attempts,
8227
+ delay,
8228
+ error
8229
+ });
8230
+ }
8231
+ await sleep(delay);
8232
+ }
8233
+ }
8234
+ throw lastError;
8235
+ }
8236
+ function sleep(ms) {
8237
+ return new Promise((resolve) => setTimeout(resolve, ms));
8238
+ }
8239
+ module2.exports = { retryWithBackoff, sleep };
8240
+ }
8241
+ });
8242
+
8243
+ // src/errors/index.js
8244
+ var require_errors2 = __commonJS({
8245
+ "src/errors/index.js"(exports2, module2) {
8246
+ var SageSDKError = class extends Error {
8247
+ constructor(message, code, retryable = false, originalError = null) {
8248
+ super(message);
8249
+ this.name = this.constructor.name;
8250
+ this.code = code;
8251
+ this.retryable = retryable;
8252
+ this.originalError = originalError;
8253
+ }
8254
+ };
8255
+ var SubgraphError = class extends SageSDKError {
8256
+ /**
8257
+ * @param {string} message - Error message
8258
+ * @param {'TIMEOUT'|'NETWORK'|'INVALID_RESPONSE'|'NOT_FOUND'|'QUERY_FAILED'} code - Error code
8259
+ * @param {boolean} retryable - Whether error is retryable
8260
+ * @param {Error} originalError - Original error (optional)
8261
+ */
8262
+ constructor(message, code, retryable = false, originalError = null) {
8263
+ super(message, code, retryable, originalError);
8264
+ }
8265
+ };
8266
+ var IPFSError = class extends SageSDKError {
8267
+ /**
8268
+ * @param {string} message - Error message
8269
+ * @param {'TIMEOUT'|'PIN_FAILED'|'INVALID_CID'|'NOT_FOUND'|'GATEWAY_FAILED'|'UPLOAD_FAILED'} code - Error code
8270
+ * @param {boolean} retryable - Whether error is retryable
8271
+ * @param {Error} originalError - Original error (optional)
8272
+ */
8273
+ constructor(message, code, retryable = false, originalError = null) {
8274
+ super(message, code, retryable, originalError);
8275
+ }
8276
+ };
8277
+ function formatErrorMessage(error) {
8278
+ if (!error) return "An unknown error occurred";
8279
+ if (error instanceof SubgraphError || error instanceof IPFSError) {
8280
+ switch (error.code) {
8281
+ case "TIMEOUT":
8282
+ return "Request timed out. Please try again.";
8283
+ case "NETWORK":
8284
+ return "Network error. Check your connection and try again.";
8285
+ case "INVALID_RESPONSE":
8286
+ return "Received invalid data from server.";
8287
+ case "NOT_FOUND":
8288
+ return "Content not found.";
8289
+ case "PIN_FAILED":
8290
+ return "Failed to pin content to IPFS. Please try again.";
8291
+ case "INVALID_CID":
8292
+ return "Invalid content identifier (CID).";
8293
+ case "GATEWAY_FAILED":
8294
+ return "All IPFS gateways failed. Content may be temporarily unavailable.";
8295
+ case "UPLOAD_FAILED":
8296
+ return "Failed to upload content. Please try again.";
8297
+ case "QUERY_FAILED":
8298
+ return "Failed to query data. Please try again.";
8299
+ default:
8300
+ return error.message || "An error occurred";
8301
+ }
8302
+ }
8303
+ return error.message || "An error occurred";
8304
+ }
8305
+ function isRetryable(error) {
8306
+ if (error instanceof SageSDKError) {
8307
+ return error.retryable;
8308
+ }
8309
+ if (error.name === "AbortError" || error.name === "TimeoutError") {
8310
+ return true;
8311
+ }
8312
+ const message = String(error.message || "").toLowerCase();
8313
+ const retryablePatterns = [
8314
+ "timeout",
8315
+ "network",
8316
+ "econnrefused",
8317
+ "econnreset",
8318
+ "etimedout",
8319
+ "fetch failed"
8320
+ ];
8321
+ return retryablePatterns.some((pattern) => message.includes(pattern));
8322
+ }
8323
+ module2.exports = {
8324
+ SageSDKError,
8325
+ SubgraphError,
8326
+ IPFSError,
8327
+ formatErrorMessage,
8328
+ isRetryable
8329
+ };
8330
+ }
8331
+ });
8332
+
8333
+ // src/services/subgraph/client.js
8334
+ var require_client = __commonJS({
8335
+ "src/services/subgraph/client.js"(exports2, module2) {
8336
+ var subgraph = require_subgraph();
8337
+ var { SimpleCache } = require_cache();
8338
+ var { retryWithBackoff } = require_retry();
8339
+ var { SubgraphError } = require_errors2();
8340
+ var SubgraphService = class {
8341
+ /**
8342
+ * @param {object} config - Service configuration
8343
+ * @param {string} config.url - Subgraph GraphQL endpoint
8344
+ * @param {number} [config.timeout=10000] - Request timeout in ms
8345
+ * @param {number} [config.retries=3] - Number of retry attempts
8346
+ * @param {object} [config.cache] - Cache configuration
8347
+ * @param {boolean} [config.cache.enabled=true] - Enable caching
8348
+ * @param {number} [config.cache.ttl=30000] - Cache TTL in ms
8349
+ * @param {number} [config.cache.maxSize=100] - Max cache entries
8350
+ */
8351
+ constructor(config) {
8352
+ if (!config || !config.url) {
8353
+ throw new Error("SubgraphService requires a url in config");
8354
+ }
8355
+ this.url = config.url;
8356
+ this.timeout = config.timeout || 1e4;
8357
+ this.retries = config.retries || 3;
8358
+ this._cache = new SimpleCache({
8359
+ enabled: config.cache?.enabled !== false,
8360
+ ttl: config.cache?.ttl || 3e4,
8361
+ maxSize: config.cache?.maxSize || 100
8362
+ });
8363
+ }
8364
+ /**
8365
+ * Get list of SubDAOs
8366
+ * @param {object} [options] - Query options
8367
+ * @param {number} [options.limit=50] - Max results
8368
+ * @param {number} [options.skip=0] - Results to skip
8369
+ * @param {boolean} [options.cache=true] - Use cache
8370
+ * @returns {Promise<Array>} - List of SubDAOs
8371
+ */
8372
+ async getSubDAOs(options = {}) {
8373
+ const { limit = 50, skip = 0, cache = true } = options;
8374
+ const cacheKey = `subdaos:${limit}:${skip}`;
8375
+ if (cache) {
8376
+ const cached = this._cache.get(cacheKey);
8377
+ if (cached) return cached;
8378
+ }
8379
+ try {
8380
+ const result = await retryWithBackoff(
8381
+ () => this._querySubDAOs({ limit, skip }),
8382
+ { attempts: this.retries }
8383
+ );
8384
+ if (cache) {
8385
+ this._cache.set(cacheKey, result);
8386
+ }
8387
+ return result;
8388
+ } catch (error) {
8389
+ throw new SubgraphError(
8390
+ `Failed to fetch SubDAOs: ${error.message}`,
8391
+ "QUERY_FAILED",
8392
+ true,
8393
+ error
8394
+ );
8395
+ }
8396
+ }
8397
+ /**
8398
+ * Get list of proposals
8399
+ * @param {object} [options] - Query options
8400
+ * @param {string} [options.governor] - Filter by governor address
8401
+ * @param {string} [options.subdao] - Filter by SubDAO address
8402
+ * @param {string[]} [options.states] - Filter by proposal states
8403
+ * @param {number} [options.fromTimestamp] - Filter by creation time (>=)
8404
+ * @param {number} [options.toTimestamp] - Filter by creation time (<=)
8405
+ * @param {number} [options.limit=20] - Max results
8406
+ * @param {number} [options.skip=0] - Results to skip
8407
+ * @param {boolean} [options.cache=true] - Use cache
8408
+ * @returns {Promise<Array>} - List of proposals
8409
+ */
8410
+ async getProposals(options = {}) {
8411
+ const {
8412
+ governor,
8413
+ subdao,
8414
+ states,
8415
+ fromTimestamp,
8416
+ toTimestamp,
8417
+ limit = 20,
8418
+ skip = 0,
8419
+ cache = true
8420
+ } = options;
8421
+ const cacheKey = `proposals:${JSON.stringify({
8422
+ governor,
8423
+ subdao,
8424
+ states,
8425
+ fromTimestamp,
8426
+ toTimestamp,
8427
+ limit,
8428
+ skip
8429
+ })}`;
8430
+ if (cache) {
8431
+ const cached = this._cache.get(cacheKey);
8432
+ if (cached) return cached;
8433
+ }
8434
+ try {
8435
+ const result = await retryWithBackoff(
8436
+ () => this._queryProposals({
8437
+ governor,
8438
+ subdao,
8439
+ states,
8440
+ fromTimestamp,
8441
+ toTimestamp,
8442
+ limit,
8443
+ skip
8444
+ }),
8445
+ { attempts: this.retries }
8446
+ );
8447
+ if (cache) {
8448
+ this._cache.set(cacheKey, result);
8449
+ }
8450
+ return result;
8451
+ } catch (error) {
8452
+ throw new SubgraphError(
8453
+ `Failed to fetch proposals: ${error.message}`,
8454
+ "QUERY_FAILED",
8455
+ true,
8456
+ error
8457
+ );
8458
+ }
8459
+ }
8460
+ /**
8461
+ * Get proposal by ID
8462
+ * @param {string} id - Proposal ID
8463
+ * @param {object} [options] - Query options
8464
+ * @param {boolean} [options.cache=true] - Use cache
8465
+ * @returns {Promise<object|null>} - Proposal or null
8466
+ */
8467
+ async getProposalById(id2, options = {}) {
8468
+ const { cache = true } = options;
8469
+ const cacheKey = `proposal:${id2}`;
8470
+ if (cache) {
8471
+ const cached = this._cache.get(cacheKey);
8472
+ if (cached !== null) return cached;
8473
+ }
8474
+ try {
8475
+ const result = await retryWithBackoff(
8476
+ () => subgraph.getProposalById({ url: this.url, id: id2 }),
8477
+ { attempts: this.retries }
8478
+ );
8479
+ if (cache) {
8480
+ this._cache.set(cacheKey, result);
8481
+ }
8482
+ return result;
8483
+ } catch (error) {
8484
+ throw new SubgraphError(
8485
+ `Failed to fetch proposal ${id2}: ${error.message}`,
8486
+ "QUERY_FAILED",
8487
+ true,
8488
+ error
8489
+ );
8490
+ }
8491
+ }
8492
+ /**
8493
+ * Get libraries
8494
+ * @param {object} [options] - Query options
8495
+ * @param {string} [options.subdao] - Filter by SubDAO address
8496
+ * @param {number} [options.limit=50] - Max results
8497
+ * @param {number} [options.skip=0] - Results to skip
8498
+ * @param {boolean} [options.cache=true] - Use cache
8499
+ * @returns {Promise<Array>} - List of libraries
8500
+ */
8501
+ async getLibraries(options = {}) {
8502
+ const { subdao, limit = 50, skip = 0, cache = true } = options;
8503
+ const cacheKey = `libraries:${subdao || "all"}:${limit}:${skip}`;
8504
+ if (cache) {
8505
+ const cached = this._cache.get(cacheKey);
8506
+ if (cached) return cached;
8507
+ }
8508
+ try {
8509
+ const result = await retryWithBackoff(
8510
+ () => subgraph.listLibraries({ url: this.url, subdao, first: limit, skip }),
8511
+ { attempts: this.retries }
8512
+ );
8513
+ if (cache) {
8514
+ this._cache.set(cacheKey, result);
8515
+ }
8516
+ return result;
8517
+ } catch (error) {
8518
+ throw new SubgraphError(
8519
+ `Failed to fetch libraries: ${error.message}`,
8520
+ "QUERY_FAILED",
8521
+ true,
8522
+ error
8523
+ );
8524
+ }
8525
+ }
8526
+ /**
8527
+ * Get prompts by tag
8528
+ * @param {object} options - Query options
8529
+ * @param {string} options.tagsHash - Tag hash to filter by
8530
+ * @param {string} [options.registry] - Filter by registry address
8531
+ * @param {number} [options.limit=50] - Max results
8532
+ * @param {number} [options.skip=0] - Results to skip
8533
+ * @param {boolean} [options.cache=true] - Use cache
8534
+ * @returns {Promise<Array>} - List of prompts
8535
+ */
8536
+ async getPromptsByTag(options) {
8537
+ if (!options || !options.tagsHash) {
8538
+ throw new Error("tagsHash is required");
8539
+ }
8540
+ const { tagsHash, registry, limit = 50, skip = 0, cache = true } = options;
8541
+ const cacheKey = `prompts-tag:${tagsHash}:${registry || "all"}:${limit}:${skip}`;
8542
+ if (cache) {
8543
+ const cached = this._cache.get(cacheKey);
8544
+ if (cached) return cached;
8545
+ }
8546
+ try {
8547
+ const result = await retryWithBackoff(
8548
+ () => subgraph.listPromptsByTag({
8549
+ url: this.url,
8550
+ tagsHash,
8551
+ registry,
8552
+ first: limit,
8553
+ skip
8554
+ }),
8555
+ { attempts: this.retries }
8556
+ );
8557
+ if (cache) {
8558
+ this._cache.set(cacheKey, result);
8559
+ }
8560
+ return result;
8561
+ } catch (error) {
8562
+ throw new SubgraphError(
8563
+ `Failed to fetch prompts by tag: ${error.message}`,
8564
+ "QUERY_FAILED",
8565
+ true,
8566
+ error
8567
+ );
8568
+ }
8569
+ }
8570
+ /**
8571
+ * Get registry prompts
8572
+ * @param {object} options - Query options
8573
+ * @param {string} options.registry - Registry address
8574
+ * @param {number} [options.limit=50] - Max results
8575
+ * @param {number} [options.skip=0] - Results to skip
8576
+ * @param {boolean} [options.cache=true] - Use cache
8577
+ * @returns {Promise<Array>} - List of prompts
8578
+ */
8579
+ async getRegistryPrompts(options) {
8580
+ if (!options || !options.registry) {
8581
+ throw new Error("registry is required");
8582
+ }
8583
+ const { registry, limit = 50, skip = 0, cache = true } = options;
8584
+ const cacheKey = `registry-prompts:${registry}:${limit}:${skip}`;
8585
+ if (cache) {
8586
+ const cached = this._cache.get(cacheKey);
8587
+ if (cached) return cached;
8588
+ }
8589
+ try {
8590
+ const result = await retryWithBackoff(
8591
+ () => subgraph.listRegistryPrompts({
8592
+ url: this.url,
8593
+ registry,
8594
+ first: limit,
8595
+ skip
8596
+ }),
8597
+ { attempts: this.retries }
8598
+ );
8599
+ if (cache) {
8600
+ this._cache.set(cacheKey, result);
8601
+ }
8602
+ return result;
8603
+ } catch (error) {
8604
+ throw new SubgraphError(
8605
+ `Failed to fetch registry prompts: ${error.message}`,
8606
+ "QUERY_FAILED",
8607
+ true,
8608
+ error
8609
+ );
8610
+ }
8611
+ }
8612
+ /**
8613
+ * Clear cache
8614
+ */
8615
+ clearCache() {
8616
+ this._cache.clear();
8617
+ }
8618
+ /**
8619
+ * Get cache statistics
8620
+ * @returns {object} - Cache stats
8621
+ */
8622
+ getCacheStats() {
8623
+ return this._cache.stats();
8624
+ }
8625
+ // Private methods
8626
+ async _querySubDAOs({ limit, skip }) {
8627
+ const data = await subgraph.query(
8628
+ this.url,
8629
+ `
8630
+ query($first: Int!, $skip: Int!) {
8631
+ subDAOs(first: $first, skip: $skip, orderBy: createdAt, orderDirection: desc) {
8632
+ id
8633
+ address
8634
+ name
8635
+ description
8636
+ governor
8637
+ registry
8638
+ token
8639
+ createdAt
8640
+ }
8641
+ }
8642
+ `,
8643
+ { first: limit, skip }
8644
+ );
8645
+ return data?.subDAOs || [];
8646
+ }
8647
+ async _queryProposals({ governor, subdao, states, fromTimestamp, toTimestamp, limit, skip }) {
8648
+ return await subgraph.listProposalsFiltered({
8649
+ url: this.url,
8650
+ governor,
8651
+ states,
8652
+ fromTimestamp,
8653
+ toTimestamp,
8654
+ first: limit,
8655
+ skip
8656
+ });
8657
+ }
8658
+ };
8659
+ module2.exports = { SubgraphService };
8660
+ }
8661
+ });
8662
+
8663
+ // src/services/ipfs/client.js
8664
+ var require_client2 = __commonJS({
8665
+ "src/services/ipfs/client.js"(exports2, module2) {
8666
+ var ipfs = require_ipfs();
8667
+ var { SimpleCache } = require_cache();
8668
+ var { retryWithBackoff } = require_retry();
8669
+ var { IPFSError } = require_errors2();
8670
+ var IPFSService = class {
8671
+ /**
8672
+ * @param {object} config - Service configuration
8673
+ * @param {string} config.workerBaseUrl - IPFS worker base URL
8674
+ * @param {string} config.gateway - Primary IPFS gateway URL
8675
+ * @param {object} [config.signer] - ethers v6 signer for worker auth
8676
+ * @param {Function} [config.getAuth] - Function to get auth credentials
8677
+ * @param {string} [config.workerToken] - Bearer token for worker auth
8678
+ * @param {number} [config.timeout=15000] - Request timeout in ms
8679
+ * @param {number} [config.retries=2] - Number of retry attempts
8680
+ * @param {object} [config.cache] - Cache configuration
8681
+ * @param {boolean} [config.cache.enabled=true] - Enable caching
8682
+ * @param {number} [config.cache.ttl=300000] - Cache TTL in ms (default 5min for immutable CIDs)
8683
+ * @param {number} [config.cache.maxSize=50] - Max cache entries
8684
+ */
8685
+ constructor(config) {
8686
+ if (!config) {
8687
+ throw new Error("IPFSService requires a config object");
8688
+ }
8689
+ this.workerBaseUrl = config.workerBaseUrl;
8690
+ this.gateway = config.gateway;
8691
+ this.timeout = config.timeout || 15e3;
8692
+ this.retries = config.retries || 2;
8693
+ this._client = ipfs.createClient({
8694
+ workerBaseUrl: config.workerBaseUrl,
8695
+ gateway: config.gateway,
8696
+ workerSigner: config.signer,
8697
+ workerGetAuth: config.getAuth,
8698
+ workerToken: config.workerToken,
8699
+ timeoutMs: this.timeout,
8700
+ retries: this.retries
8701
+ });
8702
+ this._cache = new SimpleCache({
8703
+ enabled: config.cache?.enabled !== false,
8704
+ ttl: config.cache?.ttl || 3e5,
8705
+ // 5 minutes
8706
+ maxSize: config.cache?.maxSize || 50
8707
+ });
8708
+ }
8709
+ /**
8710
+ * Upload content to IPFS worker
8711
+ * @param {any} content - Content to upload (will be JSON stringified)
8712
+ * @param {object} [options] - Upload options
8713
+ * @param {string} [options.name] - Content name
8714
+ * @param {boolean} [options.warm=false] - Warm gateways after upload
8715
+ * @returns {Promise<string>} - CID of uploaded content
8716
+ */
8717
+ async upload(content, options = {}) {
8718
+ const { name = "upload", warm = false } = options;
8719
+ try {
8720
+ const result = await retryWithBackoff(
8721
+ () => this._client.uploadJson(content, name, {
8722
+ provider: "worker",
8723
+ warm
8724
+ }),
8725
+ { attempts: this.retries }
8726
+ );
8727
+ return result.cid;
8728
+ } catch (error) {
8729
+ throw new IPFSError(
8730
+ `Failed to upload content: ${error.message}`,
8731
+ "UPLOAD_FAILED",
8732
+ true,
8733
+ error
8734
+ );
8735
+ }
8736
+ }
8737
+ /**
8738
+ * Fetch JSON content by CID with parallel gateway fetching
8739
+ * @param {string} cid - IPFS CID
8740
+ * @param {object} [options] - Fetch options
8741
+ * @param {boolean} [options.cache=true] - Use cache
8742
+ * @param {number} [options.timeout=5000] - Timeout per gateway in ms
8743
+ * @param {string[]} [options.extraGateways] - Additional gateways to try
8744
+ * @returns {Promise<any|null>} - Parsed JSON content or null
8745
+ */
8746
+ async fetchByCID(cid, options = {}) {
8747
+ if (!cid) {
8748
+ throw new IPFSError("CID is required", "INVALID_CID", false);
8749
+ }
8750
+ const { cache = true, timeout = 5e3, extraGateways = [] } = options;
8751
+ if (cache) {
8752
+ const cached = this._cache.get(cid);
8753
+ if (cached) return cached;
8754
+ }
8755
+ const urls = this._client.buildGatewayUrls(cid, extraGateways);
8756
+ try {
8757
+ const result = await this._parallelFetch(urls, timeout);
8758
+ if (result === null) {
8759
+ throw new IPFSError(
8760
+ `All gateways failed for CID ${cid}`,
8761
+ "GATEWAY_FAILED",
8762
+ true
8763
+ );
8764
+ }
8765
+ if (cache) {
8766
+ this._cache.set(cid, result);
8767
+ }
8768
+ return result;
8769
+ } catch (error) {
8770
+ if (error instanceof IPFSError) throw error;
8771
+ throw new IPFSError(
8772
+ `Failed to fetch CID ${cid}: ${error.message}`,
8773
+ "GATEWAY_FAILED",
8774
+ true,
8775
+ error
8776
+ );
8777
+ }
8778
+ }
8779
+ /**
8780
+ * Pin CIDs to IPFS worker
8781
+ * @param {string|string[]} cids - CID or array of CIDs to pin
8782
+ * @param {object} [options] - Pin options
8783
+ * @param {boolean} [options.warm=false] - Warm gateways after pinning
8784
+ * @returns {Promise<void>}
8785
+ */
8786
+ async pin(cids, options = {}) {
8787
+ const { warm = false } = options;
8788
+ const cidList = Array.isArray(cids) ? cids : [cids];
8789
+ if (cidList.length === 0) {
8790
+ throw new IPFSError("At least one CID is required", "INVALID_CID", false);
8791
+ }
8792
+ try {
8793
+ await retryWithBackoff(
8794
+ () => this._client.pin({ cids: cidList, warm }),
8795
+ { attempts: this.retries }
8796
+ );
8797
+ } catch (error) {
8798
+ throw new IPFSError(
8799
+ `Failed to pin CIDs: ${error.message}`,
8800
+ "PIN_FAILED",
8801
+ true,
8802
+ error
8803
+ );
8804
+ }
8805
+ }
8806
+ /**
8807
+ * Warm gateways for a CID (prefetch)
8808
+ * @param {string} cid - CID to warm
8809
+ * @param {object} [options] - Warm options
8810
+ * @param {string[]} [options.gateways] - Specific gateways to warm
8811
+ * @returns {Promise<object>} - Warm result
8812
+ */
8813
+ async warm(cid, options = {}) {
8814
+ const { gateways } = options;
8815
+ try {
8816
+ return await this._client.warmGateways(cid, { gateways });
8817
+ } catch (error) {
8818
+ return { warmed: [] };
8819
+ }
8820
+ }
8821
+ /**
8822
+ * Clear cache
8823
+ */
8824
+ clearCache() {
8825
+ this._cache.clear();
8826
+ }
8827
+ /**
8828
+ * Get cache statistics
8829
+ * @returns {object} - Cache stats
8830
+ */
8831
+ getCacheStats() {
8832
+ return this._cache.stats();
8833
+ }
8834
+ // Private methods
8835
+ /**
8836
+ * Fetch from multiple gateways in parallel
8837
+ * @param {string[]} urls - Gateway URLs to try
8838
+ * @param {number} timeout - Timeout per gateway in ms
8839
+ * @returns {Promise<any|null>} - First successful result or null
8840
+ * @private
8841
+ */
8842
+ async _parallelFetch(urls, timeout) {
8843
+ if (!urls || urls.length === 0) {
8844
+ return null;
8845
+ }
8846
+ const fetchOne = async (url) => {
8847
+ const controller = new AbortController();
8848
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
8849
+ try {
8850
+ const response = await fetch(url, {
8851
+ signal: controller.signal,
8852
+ headers: { Accept: "application/json" }
8853
+ });
8854
+ clearTimeout(timeoutId);
8855
+ if (!response.ok) {
8856
+ return null;
8857
+ }
8858
+ const text = await response.text();
8859
+ try {
8860
+ return JSON.parse(text);
8861
+ } catch {
8862
+ return text;
8863
+ }
8864
+ } catch (error) {
8865
+ clearTimeout(timeoutId);
8866
+ return null;
8867
+ }
8868
+ };
8869
+ const results = await Promise.allSettled(urls.map((url) => fetchOne(url)));
8870
+ for (const result of results) {
8871
+ if (result.status === "fulfilled" && result.value !== null) {
8872
+ return result.value;
8873
+ }
8874
+ }
8875
+ return null;
8876
+ }
8877
+ };
8878
+ module2.exports = { IPFSService };
8879
+ }
8880
+ });
8881
+
8882
+ // src/hooks/useSubDAOs.js
8883
+ var require_useSubDAOs = __commonJS({
8884
+ "src/hooks/useSubDAOs.js"(exports2, module2) {
8885
+ var useSWR = __require("swr");
8886
+ function useSubDAOs(subgraphService, options = {}) {
8887
+ const {
8888
+ limit = 50,
8889
+ skip = 0,
8890
+ cache = true,
8891
+ refreshInterval,
8892
+ revalidateOnFocus = true,
8893
+ revalidateOnReconnect = true
8894
+ } = options;
8895
+ const cacheKey = subgraphService ? ["subdaos", subgraphService.url, limit, skip] : null;
8896
+ const fetcher = async () => {
8897
+ if (!subgraphService) {
8898
+ throw new Error("SubgraphService is required");
8899
+ }
8900
+ return await subgraphService.getSubDAOs({ limit, skip, cache });
8901
+ };
8902
+ return useSWR(cacheKey, fetcher, {
8903
+ refreshInterval,
8904
+ revalidateOnFocus,
8905
+ revalidateOnReconnect,
8906
+ dedupingInterval: cache ? 3e4 : 0
8907
+ // Match service cache TTL
8908
+ });
8909
+ }
8910
+ module2.exports = { useSubDAOs };
8911
+ }
8912
+ });
8913
+
8914
+ // src/hooks/useProposals.js
8915
+ var require_useProposals = __commonJS({
8916
+ "src/hooks/useProposals.js"(exports2, module2) {
8917
+ var useSWR = __require("swr");
8918
+ function useProposals(subgraphService, options = {}) {
8919
+ const {
8920
+ governor,
8921
+ subdao,
8922
+ states,
8923
+ fromTimestamp,
8924
+ toTimestamp,
8925
+ limit = 20,
8926
+ skip = 0,
8927
+ cache = true,
8928
+ refreshInterval,
8929
+ revalidateOnFocus = true,
8930
+ revalidateOnReconnect = true
8931
+ } = options;
8932
+ const cacheKey = subgraphService ? [
8933
+ "proposals",
8934
+ subgraphService.url,
8935
+ governor,
8936
+ subdao,
8937
+ states?.join(","),
8938
+ fromTimestamp,
8939
+ toTimestamp,
8940
+ limit,
8941
+ skip
8942
+ ] : null;
8943
+ const fetcher = async () => {
8944
+ if (!subgraphService) {
8945
+ throw new Error("SubgraphService is required");
8946
+ }
8947
+ return await subgraphService.getProposals({
8948
+ governor,
8949
+ subdao,
8950
+ states,
8951
+ fromTimestamp,
8952
+ toTimestamp,
8953
+ limit,
8954
+ skip,
8955
+ cache
8956
+ });
8957
+ };
8958
+ return useSWR(cacheKey, fetcher, {
8959
+ refreshInterval,
8960
+ revalidateOnFocus,
8961
+ revalidateOnReconnect,
8962
+ dedupingInterval: cache ? 3e4 : 0
8963
+ // Match service cache TTL
8964
+ });
8965
+ }
8966
+ module2.exports = { useProposals };
8967
+ }
8968
+ });
8969
+
8970
+ // src/hooks/useFetchCID.js
8971
+ var require_useFetchCID = __commonJS({
8972
+ "src/hooks/useFetchCID.js"(exports2, module2) {
8973
+ var useSWR = __require("swr");
8974
+ function useFetchCID(ipfsService, cid, options = {}) {
8975
+ const {
8976
+ cache = true,
8977
+ timeout = 5e3,
8978
+ extraGateways = [],
8979
+ refreshInterval,
8980
+ revalidateOnFocus = false,
8981
+ // CIDs are immutable
8982
+ revalidateOnReconnect = false
8983
+ // CIDs are immutable
8984
+ } = options;
8985
+ const cacheKey = ipfsService && cid ? ["ipfs-cid", cid] : null;
8986
+ const fetcher = async () => {
8987
+ if (!ipfsService) {
8988
+ throw new Error("IPFSService is required");
8989
+ }
8990
+ if (!cid) {
8991
+ throw new Error("CID is required");
8992
+ }
8993
+ return await ipfsService.fetchByCID(cid, {
8994
+ cache,
8995
+ timeout,
8996
+ extraGateways
8997
+ });
8998
+ };
8999
+ return useSWR(cacheKey, fetcher, {
9000
+ refreshInterval,
9001
+ revalidateOnFocus,
9002
+ revalidateOnReconnect,
9003
+ dedupingInterval: cache ? 3e5 : 0,
9004
+ // Match service cache TTL (5min)
9005
+ // CIDs are immutable, so we can cache errors too
9006
+ shouldRetryOnError: true,
9007
+ errorRetryInterval: 5e3,
9008
+ errorRetryCount: 3
9009
+ });
9010
+ }
9011
+ module2.exports = { useFetchCID };
9012
+ }
9013
+ });
9014
+
9015
+ // src/hooks/useUpload.js
9016
+ var require_useUpload = __commonJS({
9017
+ "src/hooks/useUpload.js"(exports2, module2) {
9018
+ var { useState, useCallback } = __require("react");
9019
+ function useUpload(ipfsService) {
9020
+ const [isUploading, setIsUploading] = useState(false);
9021
+ const [error, setError] = useState(null);
9022
+ const [data, setData] = useState(null);
9023
+ const upload = useCallback(
9024
+ async (content, options = {}) => {
9025
+ if (!ipfsService) {
9026
+ const err = new Error("IPFSService is required");
9027
+ setError(err);
9028
+ throw err;
9029
+ }
9030
+ setIsUploading(true);
9031
+ setError(null);
9032
+ try {
9033
+ const cid = await ipfsService.upload(content, options);
9034
+ setData(cid);
9035
+ return cid;
9036
+ } catch (err) {
9037
+ setError(err);
9038
+ throw err;
9039
+ } finally {
9040
+ setIsUploading(false);
9041
+ }
9042
+ },
9043
+ [ipfsService]
9044
+ );
9045
+ const reset = useCallback(() => {
9046
+ setIsUploading(false);
9047
+ setError(null);
9048
+ setData(null);
9049
+ }, []);
9050
+ return {
9051
+ upload,
9052
+ isUploading,
9053
+ error,
9054
+ data,
9055
+ reset
9056
+ };
9057
+ }
9058
+ module2.exports = { useUpload };
9059
+ }
9060
+ });
9061
+
9062
+ // src/hooks/index.js
9063
+ var require_hooks = __commonJS({
9064
+ "src/hooks/index.js"(exports2, module2) {
9065
+ var { useSubDAOs } = require_useSubDAOs();
9066
+ var { useProposals } = require_useProposals();
9067
+ var { useFetchCID } = require_useFetchCID();
9068
+ var { useUpload } = require_useUpload();
9069
+ module2.exports = {
9070
+ useSubDAOs,
9071
+ useProposals,
9072
+ useFetchCID,
9073
+ useUpload
9074
+ };
9075
+ }
9076
+ });
9077
+
8143
9078
  // src/index.js
8144
9079
  var require_src = __commonJS({
8145
- "src/index.js"(exports, module) {
9080
+ "src/index.js"(exports2, module2) {
8146
9081
  var pkg = require_package();
8147
9082
  var abi = require_abi();
8148
9083
  var governance = require_governance();
8149
9084
  governance.intents = require_intents();
8150
9085
  var governanceTemplates = require_templates();
8151
9086
  governance.operations = require_operations();
9087
+ governance.grants = require_grants();
8152
9088
  var subdao = require_subdao();
8153
9089
  var timelock = require_timelock();
8154
9090
  var factory = require_factory();
@@ -8165,7 +9101,6 @@ var require_src = __commonJS({
8165
9101
  var treasury = require_treasury();
8166
9102
  var boost = require_boost();
8167
9103
  var bounty = require_bounty();
8168
- var bond = require_bond();
8169
9104
  var wallet = require_wallet();
8170
9105
  wallet.session = require_session();
8171
9106
  var walletCastManager = require_cast_manager();
@@ -8180,7 +9115,17 @@ var require_src = __commonJS({
8180
9115
  openzeppelin: require_openzeppelin()
8181
9116
  }
8182
9117
  };
8183
- module.exports = {
9118
+ var { SubgraphService } = require_client();
9119
+ var { IPFSService } = require_client2();
9120
+ var serviceErrors = require_errors2();
9121
+ var { SimpleCache } = require_cache();
9122
+ var { retryWithBackoff } = require_retry();
9123
+ var hooks = null;
9124
+ try {
9125
+ hooks = require_hooks();
9126
+ } catch (err) {
9127
+ }
9128
+ module2.exports = {
8184
9129
  version: pkg.version,
8185
9130
  getProvider: utils.getProvider,
8186
9131
  abi,
@@ -8198,7 +9143,7 @@ var require_src = __commonJS({
8198
9143
  personal,
8199
9144
  treasury,
8200
9145
  boost,
8201
- bond,
9146
+ // bond module removed; bonds deprecated in CLI/SDK
8202
9147
  subgraph,
8203
9148
  utils: { ...utils, privateTx, safe },
8204
9149
  bounty,
@@ -8210,6 +9155,18 @@ var require_src = __commonJS({
8210
9155
  errors,
8211
9156
  doppler,
8212
9157
  adapters,
9158
+ // New service layer exports
9159
+ services: {
9160
+ SubgraphService,
9161
+ IPFSService
9162
+ },
9163
+ serviceErrors,
9164
+ serviceUtils: {
9165
+ SimpleCache,
9166
+ retryWithBackoff
9167
+ },
9168
+ // React hooks (optional - requires react + swr peer dependencies)
9169
+ hooks,
8213
9170
  // Legacy exports (deprecated): maintain compatibility while consumers migrate
8214
9171
  resolveGovernanceContext: async function legacyResolveGovernanceContext(args) {
8215
9172
  console.warn("[@sage-protocol/sdk] resolveGovernanceContext is deprecated. Use governance helpers instead.");