@sage-protocol/sdk 0.2.3 → 0.2.5

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/README.md CHANGED
@@ -44,6 +44,7 @@ const sdk = require('@sage-protocol/sdk');
44
44
  | `subdao` | Discovery, staking, user stats |
45
45
  | `token` | SXXX balances, allowances |
46
46
  | `treasury` | Reserve snapshots, withdrawals |
47
+ | `reputation` | Author metrics, leaderboard, achievements |
47
48
  | `boost` | Merkle/Direct boost helpers |
48
49
  | `subgraph` | GraphQL queries |
49
50
  | `services` | High-level SubgraphService + IPFSService |
@@ -14,7 +14,7 @@ var require_package = __commonJS({
14
14
  "package.json"(exports, module) {
15
15
  module.exports = {
16
16
  name: "@sage-protocol/sdk",
17
- version: "0.2.3",
17
+ version: "0.2.5",
18
18
  description: "Backend-agnostic SDK for interacting with the Sage Protocol (governance, SubDAOs, tokens).",
19
19
  main: "dist/index.cjs",
20
20
  module: "dist/index.mjs",
@@ -80,7 +80,7 @@ var require_package = __commonJS({
80
80
  },
81
81
  devDependencies: {
82
82
  proxyquire: "^2.1.3",
83
- sinon: "^17.0.1",
83
+ sinon: "^21.0.0",
84
84
  tsup: "^8.1.0",
85
85
  typescript: "^5.4.0"
86
86
  },
@@ -180,15 +180,21 @@ var require_abi = __commonJS({
180
180
  "function libraryByDAO(address) view returns (string manifestCID, address lastUpdater, uint256 lastUpdated, string version, address forkedFromDAO, uint256 sxxxForkFee, uint256 nonce)",
181
181
  "function daoTimelock(address) view returns (address)",
182
182
  "function getLibrary(address) view returns (tuple(string manifestCID, address lastUpdater, uint256 lastUpdated, string version, address forkedFromDAO, uint256 sxxxForkFee, uint256 nonce))",
183
+ "function getLibraryIds(address dao) view returns (bytes32[] memory)",
184
+ "function getLibraryStream(address dao, string libraryId) view returns (tuple(string manifestCID, address lastUpdater, uint256 lastUpdated, string version, address forkedFromDAO, uint256 sxxxForkFee, uint256 nonce))",
183
185
  "function getLibraryForkFee(address dao) view returns (uint256)",
184
186
  "function setLibraryForkFee(address dao, uint256 fee)",
185
187
  "function updateLibrary(address dao, string manifestCID, string version)",
186
188
  "function updateLibraryCAS(address dao, string manifestCID, string version, uint256 expectedNonce)",
189
+ "function updateLibraryStream(address dao, string libraryId, string manifestCID, string version)",
190
+ "function updateLibraryStreamCAS(address dao, string libraryId, string manifestCID, string version, uint256 expectedNonce)",
187
191
  "function registerDAO(address dao, address timelock)",
188
192
  "function registerForkedDAO(address childDAO, address childTimelock, address parentDAO, string manifestCID, string version)",
189
193
  "function initializeLibraryFromFork(address sourceDao, address forkedDao)",
190
194
  "event LibraryUpdated(address indexed dao, string manifestCID, address indexed timelock, string version, uint256 nonce)",
191
- "event DAORegistered(address indexed dao, address indexed timelock)",
195
+ "event DAORegistered(address indexed dao, address indexed timelock, address indexed creator)",
196
+ "event LibraryCreated(address indexed dao, bytes32 indexed libraryIdHash, string libraryId, address indexed creator)",
197
+ "event LibraryStreamUpdated(address indexed dao, bytes32 indexed libraryIdHash, string libraryId, string manifestCID, address indexed updater, string version, uint256 nonce)",
192
198
  "event LibraryForked(address indexed sourceDao, address indexed forkedDao, string manifestCID)",
193
199
  "event LibraryForkFeeUpdated(address indexed dao, uint256 fee)",
194
200
  "error NonceMismatch(uint256 expected, uint256 actual)"
@@ -798,7 +804,7 @@ var require_subgraph = __commonJS({
798
804
  const whereClause = hasFilter ? "where:{ subdao:$subdao }" : "";
799
805
  const doc = `
800
806
  query($subdao:Bytes,$first:Int!,$skip:Int!){
801
- subDAOLibraryPointers(
807
+ libraryProjects(
802
808
  ${whereClause}
803
809
  first:$first,
804
810
  skip:$skip,
@@ -807,10 +813,9 @@ var require_subgraph = __commonJS({
807
813
  ){
808
814
  id
809
815
  subdao
810
- libraryId
811
816
  manifestCID
812
- previousCID
813
- promptCount
817
+ version
818
+ nonce
814
819
  updatedAt
815
820
  }
816
821
  }
@@ -825,7 +830,7 @@ var require_subgraph = __commonJS({
825
830
  variables.subdao = addr.toLowerCase();
826
831
  }
827
832
  const data = await query(url, doc, variables);
828
- return mapSafe(data?.subDAOLibraryPointers, (row) => {
833
+ return mapSafe(data?.libraryProjects, (row) => {
829
834
  const id = row?.id;
830
835
  const manifestCID = row?.manifestCID;
831
836
  const sub = safeGetAddress(row?.subdao);
@@ -833,10 +838,10 @@ var require_subgraph = __commonJS({
833
838
  return {
834
839
  id: String(id),
835
840
  subdao: sub,
836
- libraryId: String(row.libraryId || "main"),
841
+ libraryId: String(id),
837
842
  manifestCID: String(manifestCID),
838
- previousCID: row.previousCID || null,
839
- promptCount: row.promptCount != null ? Number(row.promptCount) : null,
843
+ previousCID: null,
844
+ promptCount: null,
840
845
  updatedAt: row.updatedAt != null ? Number(row.updatedAt) : null
841
846
  };
842
847
  });
package/dist/index.cjs CHANGED
@@ -14,7 +14,7 @@ var require_package = __commonJS({
14
14
  "package.json"(exports2, module2) {
15
15
  module2.exports = {
16
16
  name: "@sage-protocol/sdk",
17
- version: "0.2.3",
17
+ version: "0.2.5",
18
18
  description: "Backend-agnostic SDK for interacting with the Sage Protocol (governance, SubDAOs, tokens).",
19
19
  main: "dist/index.cjs",
20
20
  module: "dist/index.mjs",
@@ -80,7 +80,7 @@ var require_package = __commonJS({
80
80
  },
81
81
  devDependencies: {
82
82
  proxyquire: "^2.1.3",
83
- sinon: "^17.0.1",
83
+ sinon: "^21.0.0",
84
84
  tsup: "^8.1.0",
85
85
  typescript: "^5.4.0"
86
86
  },
@@ -180,15 +180,21 @@ var require_abi = __commonJS({
180
180
  "function libraryByDAO(address) view returns (string manifestCID, address lastUpdater, uint256 lastUpdated, string version, address forkedFromDAO, uint256 sxxxForkFee, uint256 nonce)",
181
181
  "function daoTimelock(address) view returns (address)",
182
182
  "function getLibrary(address) view returns (tuple(string manifestCID, address lastUpdater, uint256 lastUpdated, string version, address forkedFromDAO, uint256 sxxxForkFee, uint256 nonce))",
183
+ "function getLibraryIds(address dao) view returns (bytes32[] memory)",
184
+ "function getLibraryStream(address dao, string libraryId) view returns (tuple(string manifestCID, address lastUpdater, uint256 lastUpdated, string version, address forkedFromDAO, uint256 sxxxForkFee, uint256 nonce))",
183
185
  "function getLibraryForkFee(address dao) view returns (uint256)",
184
186
  "function setLibraryForkFee(address dao, uint256 fee)",
185
187
  "function updateLibrary(address dao, string manifestCID, string version)",
186
188
  "function updateLibraryCAS(address dao, string manifestCID, string version, uint256 expectedNonce)",
189
+ "function updateLibraryStream(address dao, string libraryId, string manifestCID, string version)",
190
+ "function updateLibraryStreamCAS(address dao, string libraryId, string manifestCID, string version, uint256 expectedNonce)",
187
191
  "function registerDAO(address dao, address timelock)",
188
192
  "function registerForkedDAO(address childDAO, address childTimelock, address parentDAO, string manifestCID, string version)",
189
193
  "function initializeLibraryFromFork(address sourceDao, address forkedDao)",
190
194
  "event LibraryUpdated(address indexed dao, string manifestCID, address indexed timelock, string version, uint256 nonce)",
191
- "event DAORegistered(address indexed dao, address indexed timelock)",
195
+ "event DAORegistered(address indexed dao, address indexed timelock, address indexed creator)",
196
+ "event LibraryCreated(address indexed dao, bytes32 indexed libraryIdHash, string libraryId, address indexed creator)",
197
+ "event LibraryStreamUpdated(address indexed dao, bytes32 indexed libraryIdHash, string libraryId, string manifestCID, address indexed updater, string version, uint256 nonce)",
192
198
  "event LibraryForked(address indexed sourceDao, address indexed forkedDao, string manifestCID)",
193
199
  "event LibraryForkFeeUpdated(address indexed dao, uint256 fee)",
194
200
  "error NonceMismatch(uint256 expected, uint256 actual)"
@@ -792,7 +798,7 @@ var require_subgraph = __commonJS({
792
798
  const whereClause = hasFilter ? "where:{ subdao:$subdao }" : "";
793
799
  const doc = `
794
800
  query($subdao:Bytes,$first:Int!,$skip:Int!){
795
- subDAOLibraryPointers(
801
+ libraryProjects(
796
802
  ${whereClause}
797
803
  first:$first,
798
804
  skip:$skip,
@@ -801,14 +807,10 @@ var require_subgraph = __commonJS({
801
807
  ){
802
808
  id
803
809
  subdao
804
- libraryId
805
810
  manifestCID
806
- previousCID
807
- promptCount
811
+ version
812
+ nonce
808
813
  updatedAt
809
- createdAt
810
- blockNumber
811
- blockTimestamp
812
814
  }
813
815
  }
814
816
  `;
@@ -822,23 +824,24 @@ var require_subgraph = __commonJS({
822
824
  variables.subdao = addr.toLowerCase();
823
825
  }
824
826
  const data = await query(url, doc, variables);
825
- return mapSafe(data?.subDAOLibraryPointers, (row) => {
827
+ return mapSafe(data?.libraryProjects, (row) => {
826
828
  const id2 = row?.id;
827
829
  const manifestCID = row?.manifestCID;
828
830
  const sub = safeGetAddress(row?.subdao);
829
831
  if (!id2 || !manifestCID || !sub) return null;
830
- const timestamp = (row.updatedAt != null ? Number(row.updatedAt) : null) || (row.createdAt != null ? Number(row.createdAt) : null) || (row.blockTimestamp != null ? Number(row.blockTimestamp) : null);
831
832
  return {
832
833
  id: String(id2),
833
834
  subdao: sub,
834
- libraryId: String(row.libraryId || "main"),
835
+ libraryId: String(id2),
835
836
  manifestCID: String(manifestCID),
836
- previousCID: row.previousCID || null,
837
- promptCount: row.promptCount != null ? Number(row.promptCount) : null,
838
- updatedAt: timestamp,
839
- createdAt: row.createdAt != null ? Number(row.createdAt) : null,
840
- blockNumber: row.blockNumber != null ? Number(row.blockNumber) : null,
841
- blockTimestamp: row.blockTimestamp != null ? Number(row.blockTimestamp) : null
837
+ previousCID: null,
838
+ // LibraryProject doesn't track previous CID
839
+ promptCount: null,
840
+ // LibraryProject doesn't track prompt count
841
+ updatedAt: row.updatedAt != null ? Number(row.updatedAt) : null,
842
+ createdAt: null,
843
+ blockNumber: null,
844
+ blockTimestamp: null
842
845
  };
843
846
  });
844
847
  }
@@ -2124,7 +2127,7 @@ var require_subgraph2 = __commonJS({
2124
2127
  const whereClause = hasFilter ? "where:{ subdao:$subdao }" : "";
2125
2128
  const doc = `
2126
2129
  query($subdao:Bytes,$first:Int!,$skip:Int!){
2127
- subDAOLibraryPointers(
2130
+ libraryProjects(
2128
2131
  ${whereClause}
2129
2132
  first:$first,
2130
2133
  skip:$skip,
@@ -2133,10 +2136,9 @@ var require_subgraph2 = __commonJS({
2133
2136
  ){
2134
2137
  id
2135
2138
  subdao
2136
- libraryId
2137
2139
  manifestCID
2138
- previousCID
2139
- promptCount
2140
+ version
2141
+ nonce
2140
2142
  updatedAt
2141
2143
  }
2142
2144
  }
@@ -2151,7 +2153,7 @@ var require_subgraph2 = __commonJS({
2151
2153
  variables.subdao = addr.toLowerCase();
2152
2154
  }
2153
2155
  const data = await query(url, doc, variables);
2154
- return mapSafe(data?.subDAOLibraryPointers, (row) => {
2156
+ return mapSafe(data?.libraryProjects, (row) => {
2155
2157
  const id2 = row?.id;
2156
2158
  const manifestCID = row?.manifestCID;
2157
2159
  const sub = safeGetAddress(row?.subdao);
@@ -2159,10 +2161,10 @@ var require_subgraph2 = __commonJS({
2159
2161
  return {
2160
2162
  id: String(id2),
2161
2163
  subdao: sub,
2162
- libraryId: String(row.libraryId || "main"),
2164
+ libraryId: String(id2),
2163
2165
  manifestCID: String(manifestCID),
2164
- previousCID: row.previousCID || null,
2165
- promptCount: row.promptCount != null ? Number(row.promptCount) : null,
2166
+ previousCID: null,
2167
+ promptCount: null,
2166
2168
  updatedAt: row.updatedAt != null ? Number(row.updatedAt) : null
2167
2169
  };
2168
2170
  });
@@ -3825,6 +3827,16 @@ var require_library = __commonJS({
3825
3827
  throw new SageSDKError(CODES.INVALID_ARGS, `invalid ${label}`, { cause: err });
3826
3828
  }
3827
3829
  }
3830
+ function normaliseLibraryId(libraryId) {
3831
+ const raw = (libraryId == null ? "" : String(libraryId)).trim().toLowerCase();
3832
+ if (!raw) return "default";
3833
+ if (raw === "main") return "default";
3834
+ const ok = /^[a-z0-9]([a-z0-9-]{0,62}[a-z0-9])?$/.test(raw) && !raw.includes("--");
3835
+ if (!ok) {
3836
+ throw new SageSDKError(CODES.INVALID_ARGS, `invalid libraryId`, { libraryId });
3837
+ }
3838
+ return raw;
3839
+ }
3828
3840
  async function listManifests({ provider, registry, factoryAddress, offset = 0, limit = 50 }) {
3829
3841
  if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
3830
3842
  if (!factoryAddress) throw new SageSDKError(CODES.INVALID_ARGS, "factoryAddress required for V4 listing");
@@ -3863,6 +3875,35 @@ var require_library = __commonJS({
3863
3875
  sxxxForkFee: BigInt(info.sxxxForkFee.toString())
3864
3876
  };
3865
3877
  }
3878
+ async function getLibraryStreamInfo({ provider, registry, subdao: subdao2, libraryId = "default" }) {
3879
+ if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
3880
+ if (!subdao2) throw new SageSDKError(CODES.INVALID_ARGS, "subdao required");
3881
+ const addr = normalise(registry, "registry");
3882
+ const dao = normalise(subdao2, "subdao");
3883
+ const libId = normaliseLibraryId(libraryId);
3884
+ const contract = new Contract(addr, ABI.LibraryRegistry, provider);
3885
+ const info = await contract.getLibraryStream(dao, libId);
3886
+ return {
3887
+ libraryId: libId,
3888
+ manifestCID: info.manifestCID,
3889
+ previousCID: "",
3890
+ timestamp: BigInt(info.lastUpdated.toString()),
3891
+ proposer: getAddress(info.lastUpdater),
3892
+ promptCount: 0,
3893
+ version: info.version,
3894
+ nonce: BigInt(info.nonce.toString()),
3895
+ forkedFromDAO: info.forkedFromDAO && info.forkedFromDAO !== "0x0000000000000000000000000000000000000000" ? getAddress(info.forkedFromDAO) : null,
3896
+ sxxxForkFee: BigInt(info.sxxxForkFee.toString())
3897
+ };
3898
+ }
3899
+ async function getLibraryIds({ provider, registry, subdao: subdao2 }) {
3900
+ if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
3901
+ if (!subdao2) throw new SageSDKError(CODES.INVALID_ARGS, "subdao required");
3902
+ const addr = normalise(registry, "registry");
3903
+ const dao = normalise(subdao2, "subdao");
3904
+ const contract = new Contract(addr, ABI.LibraryRegistry, provider);
3905
+ return await contract.getLibraryIds(dao);
3906
+ }
3866
3907
  async function getManifestInfo({ provider, registry, manifestCID }) {
3867
3908
  throw new SageSDKError(CODES.UNSUPPORTED_OPERATION, "getManifestInfo(cid) is not supported in V4. Use getLibraryInfo(subdao).");
3868
3909
  }
@@ -3885,26 +3926,42 @@ var require_library = __commonJS({
3885
3926
  const info = await getLatestLibrary({ provider, registry, subdao: subdao2 });
3886
3927
  return info && info.manifestCID === manifestCID;
3887
3928
  }
3888
- function buildUpdateLibraryTx({ registry, subdao: subdao2, manifestCID, version = "1.0.0" }) {
3929
+ function buildUpdateLibraryTx({ registry, subdao: subdao2, libraryId = "default", manifestCID, version = "1.0.0" }) {
3889
3930
  const to = normalise(registry, "registry");
3890
3931
  if (!manifestCID) throw new SageSDKError(CODES.INVALID_ARGS, "manifestCID required");
3891
- const iface = new Interface(["function updateLibrary(address,string,string)"]);
3892
- const data = iface.encodeFunctionData("updateLibrary", [
3893
- normalise(subdao2, "subdao"),
3894
- String(manifestCID),
3895
- String(version)
3896
- ]);
3932
+ const dao = normalise(subdao2, "subdao");
3933
+ const libId = normaliseLibraryId(libraryId);
3934
+ if (libId === "default") {
3935
+ const iface2 = new Interface(["function updateLibrary(address,string,string)"]);
3936
+ const data2 = iface2.encodeFunctionData("updateLibrary", [dao, String(manifestCID), String(version)]);
3937
+ return { to, data: data2, value: 0n };
3938
+ }
3939
+ const iface = new Interface(["function updateLibraryStream(address,string,string,string)"]);
3940
+ const data = iface.encodeFunctionData("updateLibraryStream", [dao, libId, String(manifestCID), String(version)]);
3897
3941
  return { to, data, value: 0n };
3898
3942
  }
3899
- function buildUpdateLibraryCAS({ registry, subdao: subdao2, manifestCID, version = "1.0.0", expectedNonce }) {
3943
+ function buildUpdateLibraryCAS({ registry, subdao: subdao2, libraryId = "default", manifestCID, version = "1.0.0", expectedNonce }) {
3900
3944
  const to = normalise(registry, "registry");
3901
3945
  if (!manifestCID) throw new SageSDKError(CODES.INVALID_ARGS, "manifestCID required");
3902
3946
  if (expectedNonce === void 0 || expectedNonce === null) {
3903
3947
  throw new SageSDKError(CODES.INVALID_ARGS, "expectedNonce required for CAS update");
3904
3948
  }
3905
- const iface = new Interface(["function updateLibraryCAS(address,string,string,uint256)"]);
3906
- const data = iface.encodeFunctionData("updateLibraryCAS", [
3907
- normalise(subdao2, "subdao"),
3949
+ const dao = normalise(subdao2, "subdao");
3950
+ const libId = normaliseLibraryId(libraryId);
3951
+ if (libId === "default") {
3952
+ const iface2 = new Interface(["function updateLibraryCAS(address,string,string,uint256)"]);
3953
+ const data2 = iface2.encodeFunctionData("updateLibraryCAS", [
3954
+ dao,
3955
+ String(manifestCID),
3956
+ String(version),
3957
+ BigInt(expectedNonce)
3958
+ ]);
3959
+ return { to, data: data2, value: 0n };
3960
+ }
3961
+ const iface = new Interface(["function updateLibraryStreamCAS(address,string,string,string,uint256)"]);
3962
+ const data = iface.encodeFunctionData("updateLibraryStreamCAS", [
3963
+ dao,
3964
+ libId,
3908
3965
  String(manifestCID),
3909
3966
  String(version),
3910
3967
  BigInt(expectedNonce)
@@ -3915,6 +3972,8 @@ var require_library = __commonJS({
3915
3972
  listManifests,
3916
3973
  getManifestInfo,
3917
3974
  getLibraryInfo,
3975
+ getLibraryStreamInfo,
3976
+ getLibraryIds,
3918
3977
  getLatestLibrary,
3919
3978
  hasScopedOwnership,
3920
3979
  buildUpdateLibraryTx,
@@ -4470,7 +4529,12 @@ var require_governance = __commonJS({
4470
4529
  if (!parsed) throw new Error("ProposalCreated event not found");
4471
4530
  const targets = parsed.args.targets.map(getAddress);
4472
4531
  const calldatas = parsed.args.calldatas.map((d) => typeof d === "string" ? d : "0x" + Buffer.from(d).toString("hex"));
4473
- const LibraryIface = new Interface(["function updateLibrary(address,string,string)"]);
4532
+ const LibraryIface = new Interface([
4533
+ "function updateLibrary(address dao, string manifestCID, string version)",
4534
+ "function updateLibraryCAS(address dao, string manifestCID, string version, uint256 expectedNonce)",
4535
+ "function updateLibraryStream(address dao, string libraryId, string manifestCID, string version)",
4536
+ "function updateLibraryStreamCAS(address dao, string libraryId, string manifestCID, string version, uint256 expectedNonce)"
4537
+ ]);
4474
4538
  const PromptIface = new Interface(["function updatePromptByGovernance(string,string)"]);
4475
4539
  const effects = [];
4476
4540
  for (let i = 0; i < calldatas.length; i++) {
@@ -4484,7 +4548,10 @@ var require_governance = __commonJS({
4484
4548
  try {
4485
4549
  const reg = new Contract(
4486
4550
  targets[i],
4487
- ["function libraryByDAO(address) view returns (tuple(string manifestCID,address lastUpdater,uint256 lastUpdated,string version,address forkedFromDAO,uint256 sxxxForkFee))"],
4551
+ [
4552
+ "function libraryByDAO(address) view returns (tuple(string manifestCID,address lastUpdater,uint256 lastUpdated,string version,address forkedFromDAO,uint256 sxxxForkFee))",
4553
+ "function getLibraryStream(address,string) view returns (tuple(string manifestCID,address lastUpdater,uint256 lastUpdated,string version,address forkedFromDAO,uint256 sxxxForkFee,uint256 nonce))"
4554
+ ],
4488
4555
  provider
4489
4556
  );
4490
4557
  const info = await reg.libraryByDAO(dao).catch(() => null);
@@ -4495,10 +4562,130 @@ var require_governance = __commonJS({
4495
4562
  } catch (_) {
4496
4563
  }
4497
4564
  effects.push({
4498
- type: "libraryUpdateV4",
4565
+ type: "libraryUpdate",
4566
+ index: i,
4567
+ target: targets[i],
4568
+ dao: getAddress(dao),
4569
+ libraryId: "default",
4570
+ previousCid: previousCID,
4571
+ previousVersion,
4572
+ newCid: String(newCid),
4573
+ newVersion: String(version)
4574
+ });
4575
+ continue;
4576
+ } catch (_) {
4577
+ }
4578
+ try {
4579
+ const decoded = LibraryIface.decodeFunctionData("updateLibraryCAS", data);
4580
+ const [dao, newCid, version] = decoded;
4581
+ let previousCID = null;
4582
+ let previousVersion = null;
4583
+ try {
4584
+ const reg = new Contract(
4585
+ targets[i],
4586
+ [
4587
+ "function libraryByDAO(address) view returns (tuple(string manifestCID,address lastUpdater,uint256 lastUpdated,string version,address forkedFromDAO,uint256 sxxxForkFee))",
4588
+ "function getLibraryStream(address,string) view returns (tuple(string manifestCID,address lastUpdater,uint256 lastUpdated,string version,address forkedFromDAO,uint256 sxxxForkFee,uint256 nonce))"
4589
+ ],
4590
+ provider
4591
+ );
4592
+ const info = await reg.libraryByDAO(dao).catch(() => null);
4593
+ if (info && typeof info.manifestCID === "string") {
4594
+ previousCID = info.manifestCID || null;
4595
+ previousVersion = info.version || null;
4596
+ }
4597
+ } catch (_) {
4598
+ }
4599
+ effects.push({
4600
+ type: "libraryUpdate",
4601
+ index: i,
4602
+ target: targets[i],
4603
+ dao: getAddress(dao),
4604
+ libraryId: "default",
4605
+ previousCid: previousCID,
4606
+ previousVersion,
4607
+ newCid: String(newCid),
4608
+ newVersion: String(version)
4609
+ });
4610
+ continue;
4611
+ } catch (_) {
4612
+ }
4613
+ try {
4614
+ const decoded = LibraryIface.decodeFunctionData("updateLibraryStream", data);
4615
+ const [dao, libraryId, newCid, version] = decoded;
4616
+ let previousCID = null;
4617
+ let previousVersion = null;
4618
+ try {
4619
+ const reg = new Contract(
4620
+ targets[i],
4621
+ [
4622
+ "function getLibraryStream(address,string) view returns (tuple(string manifestCID,address lastUpdater,uint256 lastUpdated,string version,address forkedFromDAO,uint256 sxxxForkFee,uint256 nonce))",
4623
+ "function libraryByDAO(address) view returns (tuple(string manifestCID,address lastUpdater,uint256 lastUpdated,string version,address forkedFromDAO,uint256 sxxxForkFee))"
4624
+ ],
4625
+ provider
4626
+ );
4627
+ let info = null;
4628
+ try {
4629
+ info = await reg.getLibraryStream(dao, String(libraryId));
4630
+ } catch (_) {
4631
+ if (String(libraryId) === "default") {
4632
+ info = await reg.libraryByDAO(dao).catch(() => null);
4633
+ }
4634
+ }
4635
+ if (info && typeof info.manifestCID === "string") {
4636
+ previousCID = info.manifestCID || null;
4637
+ previousVersion = info.version || null;
4638
+ }
4639
+ } catch (_) {
4640
+ }
4641
+ effects.push({
4642
+ type: "libraryUpdate",
4499
4643
  index: i,
4500
4644
  target: targets[i],
4501
4645
  dao: getAddress(dao),
4646
+ libraryId: String(libraryId),
4647
+ previousCid: previousCID,
4648
+ previousVersion,
4649
+ newCid: String(newCid),
4650
+ newVersion: String(version)
4651
+ });
4652
+ continue;
4653
+ } catch (_) {
4654
+ }
4655
+ try {
4656
+ const decoded = LibraryIface.decodeFunctionData("updateLibraryStreamCAS", data);
4657
+ const [dao, libraryId, newCid, version] = decoded;
4658
+ let previousCID = null;
4659
+ let previousVersion = null;
4660
+ try {
4661
+ const reg = new Contract(
4662
+ targets[i],
4663
+ [
4664
+ "function getLibraryStream(address,string) view returns (tuple(string manifestCID,address lastUpdater,uint256 lastUpdated,string version,address forkedFromDAO,uint256 sxxxForkFee,uint256 nonce))",
4665
+ "function libraryByDAO(address) view returns (tuple(string manifestCID,address lastUpdater,uint256 lastUpdated,string version,address forkedFromDAO,uint256 sxxxForkFee))"
4666
+ ],
4667
+ provider
4668
+ );
4669
+ let info = null;
4670
+ try {
4671
+ info = await reg.getLibraryStream(dao, String(libraryId));
4672
+ } catch (_) {
4673
+ if (String(libraryId) === "default") {
4674
+ info = await reg.libraryByDAO(dao).catch(() => null);
4675
+ }
4676
+ }
4677
+ if (info && typeof info.manifestCID === "string") {
4678
+ previousCID = info.manifestCID || null;
4679
+ previousVersion = info.version || null;
4680
+ }
4681
+ } catch (_) {
4682
+ }
4683
+ effects.push({
4684
+ type: "libraryUpdate",
4685
+ index: i,
4686
+ target: targets[i],
4687
+ dao: getAddress(dao),
4688
+ libraryId: String(libraryId),
4502
4689
  previousCid: previousCID,
4503
4690
  previousVersion,
4504
4691
  newCid: String(newCid),
@@ -4835,9 +5022,127 @@ var require_governance = __commonJS({
4835
5022
  description: desc.description
4836
5023
  };
4837
5024
  }
5025
+ async function getProposalVotingStatus({ provider, governor, proposalId }) {
5026
+ if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
5027
+ if (!proposalId) throw new SageSDKError(CODES.INVALID_ARGS, "proposalId required");
5028
+ const addr = normaliseGovernor(governor);
5029
+ const g = new Contract(addr, ABI.Governor, provider);
5030
+ const pid = typeof proposalId === "bigint" ? proposalId : BigInt(String(proposalId));
5031
+ const [
5032
+ stateNum,
5033
+ snapshot,
5034
+ deadline,
5035
+ votes,
5036
+ votingDelay,
5037
+ votingPeriod,
5038
+ proposalThreshold,
5039
+ govName
5040
+ ] = await Promise.all([
5041
+ g.state(pid).catch(() => null),
5042
+ g.proposalSnapshot(pid).catch(() => null),
5043
+ g.proposalDeadline(pid).catch(() => null),
5044
+ g.proposalVotes(pid).catch(() => null),
5045
+ g.votingDelay().catch(() => null),
5046
+ g.votingPeriod().catch(() => null),
5047
+ g.proposalThreshold().catch(() => null),
5048
+ g.name().catch(() => null)
5049
+ ]);
5050
+ let quorum = null;
5051
+ if (snapshot != null) {
5052
+ try {
5053
+ quorum = await g.quorum(snapshot);
5054
+ quorum = BigInt(quorum.toString());
5055
+ } catch {
5056
+ try {
5057
+ const qv = await g.quorumVotes();
5058
+ quorum = BigInt(qv.toString());
5059
+ } catch {
5060
+ }
5061
+ }
5062
+ }
5063
+ let forVotes = 0n;
5064
+ let againstVotes = 0n;
5065
+ let abstainVotes = 0n;
5066
+ if (Array.isArray(votes)) {
5067
+ againstVotes = BigInt(votes[0]);
5068
+ forVotes = BigInt(votes[1]);
5069
+ abstainVotes = BigInt(votes[2]);
5070
+ } else if (votes && typeof votes === "object") {
5071
+ if (votes.againstVotes != null) againstVotes = BigInt(votes.againstVotes);
5072
+ if (votes.forVotes != null) forVotes = BigInt(votes.forVotes);
5073
+ if (votes.abstainVotes != null) abstainVotes = BigInt(votes.abstainVotes);
5074
+ }
5075
+ const totalVotes = forVotes + againstVotes + abstainVotes;
5076
+ const participatingVotes = forVotes + againstVotes;
5077
+ const quorumMet = quorum != null ? forVotes >= quorum : null;
5078
+ const quorumProgress = quorum != null && quorum > 0n ? Number(forVotes * 10000n / quorum) / 100 : null;
5079
+ const stateMap = ["PENDING", "ACTIVE", "CANCELED", "DEFEATED", "SUCCEEDED", "QUEUED", "EXPIRED", "EXECUTED"];
5080
+ const state = typeof stateNum === "number" && stateNum >= 0 && stateNum < stateMap.length ? stateMap[stateNum] : null;
5081
+ const BLOCK_TIME_SECONDS = 2;
5082
+ const votingDelaySeconds = votingDelay != null ? Number(votingDelay) * BLOCK_TIME_SECONDS : null;
5083
+ const votingPeriodSeconds = votingPeriod != null ? Number(votingPeriod) * BLOCK_TIME_SECONDS : null;
5084
+ const formatSXXX = (val) => {
5085
+ if (val == null) return null;
5086
+ const num = Number(val) / 1e18;
5087
+ if (num >= 1e6) return `${(num / 1e6).toFixed(1)}M`;
5088
+ if (num >= 1e3) return `${(num / 1e3).toFixed(1)}K`;
5089
+ return num.toFixed(2);
5090
+ };
5091
+ const formatDuration = (seconds) => {
5092
+ if (seconds == null) return null;
5093
+ if (seconds < 60) return `${seconds} seconds`;
5094
+ if (seconds < 3600) return `${Math.round(seconds / 60)} minutes`;
5095
+ if (seconds < 86400) return `${(seconds / 3600).toFixed(1)} hours`;
5096
+ return `${(seconds / 86400).toFixed(1)} days`;
5097
+ };
5098
+ return {
5099
+ governor: addr,
5100
+ governorName: govName,
5101
+ proposalId: pid.toString(),
5102
+ state,
5103
+ stateNum: typeof stateNum === "number" ? stateNum : null,
5104
+ // Raw values (bigint as string for JSON serialization)
5105
+ votes: {
5106
+ for: forVotes.toString(),
5107
+ against: againstVotes.toString(),
5108
+ abstain: abstainVotes.toString(),
5109
+ total: totalVotes.toString()
5110
+ },
5111
+ quorum: quorum?.toString() || null,
5112
+ proposalThreshold: proposalThreshold?.toString() || null,
5113
+ snapshot: snapshot?.toString() || null,
5114
+ deadline: deadline?.toString() || null,
5115
+ votingDelay: votingDelay?.toString() || null,
5116
+ votingPeriod: votingPeriod?.toString() || null,
5117
+ // Computed status
5118
+ quorumMet,
5119
+ quorumProgress,
5120
+ // percentage (0-100+)
5121
+ passing: forVotes > againstVotes,
5122
+ // Formatted for display
5123
+ formatted: {
5124
+ forVotes: formatSXXX(forVotes),
5125
+ againstVotes: formatSXXX(againstVotes),
5126
+ abstainVotes: formatSXXX(abstainVotes),
5127
+ totalVotes: formatSXXX(totalVotes),
5128
+ quorum: formatSXXX(quorum),
5129
+ proposalThreshold: formatSXXX(proposalThreshold),
5130
+ votingDelay: formatDuration(votingDelaySeconds),
5131
+ votingPeriod: formatDuration(votingPeriodSeconds)
5132
+ },
5133
+ // Plain language summary
5134
+ summary: {
5135
+ quorumStatus: quorum != null ? quorumMet ? `Quorum reached (${formatSXXX(forVotes)} of ${formatSXXX(quorum)} SXXX required)` : `${formatSXXX(forVotes)} of ${formatSXXX(quorum)} SXXX needed for quorum (${quorumProgress?.toFixed(1)}%)` : "Quorum information unavailable",
5136
+ voteStatus: `${formatSXXX(forVotes)} SXXX for, ${formatSXXX(againstVotes)} SXXX against`,
5137
+ outcome: forVotes > againstVotes ? "Currently passing" : forVotes < againstVotes ? "Currently failing" : "Tied",
5138
+ votingPeriod: votingPeriodSeconds ? `Voting period: ${formatDuration(votingPeriodSeconds)}` : null
5139
+ }
5140
+ };
5141
+ }
4838
5142
  module2.exports = {
4839
5143
  getGovernorInfo,
4840
5144
  getProposal,
5145
+ getProposalVotingStatus,
4841
5146
  listProposals,
4842
5147
  getProposalMetadata,
4843
5148
  hashDescription,