@sage-protocol/sdk 0.0.6 → 0.0.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/README.md CHANGED
@@ -77,6 +77,44 @@ Next Phases
77
77
  -----------
78
78
  Phase 6 focuses on integration polish and packaging. Track progress in the [SDK Improvement Specification](../../docs/SDK_Improvement_Specification.md).
79
79
 
80
+ New governance/factory/library helpers (2025‑10)
81
+ -----------------------------------------------
82
+
83
+ Proposal ID and preflight
84
+ ```js
85
+ import sdk from '@sage-protocol/sdk';
86
+ const idHex = sdk.governance.computeProposalIdHex({ targets, values, calldatas, description });
87
+ const pre = await sdk.governance.simulatePropose({ provider, governor, targets, values, calldatas, description, sender });
88
+ if (!pre.ok) throw new Error(`preflight failed: ${pre.error?.message}`);
89
+ ```
90
+
91
+ Votes at latest‑1 (ERC20Votes)
92
+ ```js
93
+ // Token path
94
+ const votes1 = await sdk.governance.getVotesLatestMinusOne({ provider, token: sxxxToken, account: user });
95
+ // Governor path (auto‑resolves token)
96
+ const votes2 = await sdk.governance.getVotesLatestMinusOne({ provider, governor, account: user });
97
+ ```
98
+
99
+ Factory‑mapped registry
100
+ ```js
101
+ const mapped = await sdk.factory.getSubDAORegistry({ provider, factory, subdao });
102
+ ```
103
+
104
+ Registry preflight as timelock
105
+ ```js
106
+ const { to, data } = sdk.library.buildUpdateLibraryForSubDAOTx({ registry, subdao, manifestCID, promptCount, libraryId: 'main' });
107
+ const sim = await sdk.library.simulateAsTimelock({ provider, registry, to, data, timelock });
108
+ if (!sim.ok) throw new Error(`registry preflight failed: ${sim.error?.message}`);
109
+ ```
110
+
111
+ Propose by hash (arrays + bytes32)
112
+ ```js
113
+ // For governors that prefer descriptionHash (or deterministic IDs)
114
+ const dh = sdk.governance.hashDescription(description);
115
+ const tx = sdk.governance.buildProposeTxByHash({ governor, targets, values, calldatas, descriptionHash: dh });
116
+ ```
117
+
80
118
  API Notes and Examples
81
119
  ----------------------
82
120
 
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.0.5",
17
+ version: "0.0.7",
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",
@@ -107,6 +107,8 @@ var require_abi = __commonJS({
107
107
  "function simpleKeyStoreAddress() view returns (address)",
108
108
  "function governanceConfigAddress() view returns (address)",
109
109
  "function libraryRegistryAddress() view returns (address)",
110
+ // Canonical per‑SubDAO mapping
111
+ "function subdaoToRegistry(address) view returns (address)",
110
112
  "function templateModule() view returns (address)",
111
113
  "function stats() view returns (uint128 totalSubDAOsCreated, uint128 totalBurnedForCreation)",
112
114
  // On-chain enumeration fallback (naming follows FactoryCoreFacet)
@@ -194,6 +196,7 @@ var require_abi = __commonJS({
194
196
  var ERC20Votes = [
195
197
  "function balanceOf(address) view returns (uint256)",
196
198
  "function getVotes(address) view returns (uint256)",
199
+ "function getPastVotes(address,uint256) view returns (uint256)",
197
200
  "function allowance(address,address) view returns (uint256)",
198
201
  "function delegate(address)",
199
202
  "function delegates(address) view returns (address)",
@@ -377,7 +380,7 @@ var require_description = __commonJS({
377
380
  // src/governance/index.js
378
381
  var require_governance = __commonJS({
379
382
  "src/governance/index.js"(exports2, module2) {
380
- var { Contract, Interface, getAddress, hexlify, keccak256, toUtf8Bytes } = require("ethers");
383
+ var { Contract, Interface, AbiCoder, getAddress, hexlify, keccak256, toUtf8Bytes } = require("ethers");
381
384
  var ABI = require_abi();
382
385
  var { BigIntZero } = require_types();
383
386
  var { SageSDKError, CODES } = require_errors();
@@ -518,6 +521,15 @@ var require_governance = __commonJS({
518
521
  function hashDescription(description) {
519
522
  return keccak256(toUtf8Bytes(String(description)));
520
523
  }
524
+ function computeProposalIdHex({ targets = [], values = [], calldatas = [], description = "" }) {
525
+ const coder = AbiCoder.defaultAbiCoder();
526
+ const t = targets.map((a) => getAddress(a));
527
+ const v = values.map((value) => BigInt(String(value)));
528
+ const c = calldatas.map((data) => hexlify(data));
529
+ const descHash = hashDescription(description);
530
+ const encoded = coder.encode(["address[]", "uint256[]", "bytes[]", "bytes32"], [t, v, c, descHash]);
531
+ return keccak256(encoded);
532
+ }
521
533
  function buildProposeTx({ governor, targets = [], values = [], calldatas = [], descriptionOrHash = "" }) {
522
534
  const addr = normaliseGovernor(governor);
523
535
  const iface = new Interface(ABI.Governor);
@@ -594,6 +606,73 @@ var require_governance = __commonJS({
594
606
  const tag = latest > 0 ? BigInt(latest - 1) : 0n;
595
607
  return getQuorumAt({ provider, governor, blockTag: tag });
596
608
  }
609
+ async function getVotesLatestMinusOne({ provider, token: token2, governor, account }) {
610
+ if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
611
+ if (!token2 && !governor) throw new SageSDKError(CODES.INVALID_ARGS, "token or governor required");
612
+ if (!account) throw new SageSDKError(CODES.INVALID_ARGS, "account required");
613
+ let addr;
614
+ if (token2) {
615
+ addr = getAddress(token2);
616
+ } else {
617
+ const govAddr = normaliseGovernor(governor);
618
+ try {
619
+ const iface = new Interface(["function sxxxToken() view returns (address)"]);
620
+ const data = iface.encodeFunctionData("sxxxToken", []);
621
+ const ret = await provider.call({ to: govAddr, data });
622
+ const [tok] = AbiCoder.defaultAbiCoder().decode(["address"], ret);
623
+ addr = getAddress(tok);
624
+ } catch (err) {
625
+ throw new SageSDKError(CODES.NOT_FOUND, "failed to resolve governance token from governor", { cause: err });
626
+ }
627
+ }
628
+ const user = getAddress(account);
629
+ const latest = await provider.getBlockNumber();
630
+ const snapshot = latest > 0 ? BigInt(latest - 1) : 0n;
631
+ try {
632
+ const iface = new Interface(["function getPastVotes(address,uint256) view returns (uint256)"]);
633
+ const data = iface.encodeFunctionData("getPastVotes", [user, snapshot]);
634
+ const ret = await provider.call({ to: addr, data });
635
+ if (ret && ret !== "0x") {
636
+ const [val] = AbiCoder.defaultAbiCoder().decode(["uint256"], ret);
637
+ return BigInt(val.toString());
638
+ }
639
+ } catch (_) {
640
+ }
641
+ try {
642
+ const iface2 = new Interface(["function getVotes(address) view returns (uint256)"]);
643
+ const d2 = iface2.encodeFunctionData("getVotes", [user]);
644
+ const ret2 = await provider.call({ to: addr, data: d2 });
645
+ if (ret2 && ret2 !== "0x") {
646
+ const [val2] = AbiCoder.defaultAbiCoder().decode(["uint256"], ret2);
647
+ return BigInt(val2.toString());
648
+ }
649
+ } catch (_) {
650
+ }
651
+ return 0n;
652
+ }
653
+ async function simulatePropose({ provider, governor, targets = [], values = [], calldatas = [], description = "", sender }) {
654
+ if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
655
+ const addr = normaliseGovernor(governor);
656
+ const iface = new Interface(ABI.Governor);
657
+ const salted = makeProposalDescription(String(description || ""));
658
+ const t = targets.map((a) => getAddress(a));
659
+ const v = values.map((value) => BigInt(String(value)));
660
+ const c = calldatas.map((data2) => hexlify(data2));
661
+ let data;
662
+ try {
663
+ data = iface.encodeFunctionData("propose(address[],uint256[],bytes[],string)", [t, v, c, salted]);
664
+ } catch (err) {
665
+ return { ok: false, error: { type: "EncodeError", message: String(err && err.message || err) } };
666
+ }
667
+ try {
668
+ await provider.call({ to: addr, data, from: sender ? getAddress(sender) : void 0 });
669
+ return { ok: true };
670
+ } catch (err) {
671
+ let message = "execution reverted";
672
+ if (err && err.message) message = err.message;
673
+ return { ok: false, error: { type: "Revert", message } };
674
+ }
675
+ }
597
676
  async function detectGovernorOverloads({ provider, governor }) {
598
677
  if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
599
678
  const addr = normaliseGovernor(governor);
@@ -643,6 +722,25 @@ var require_governance = __commonJS({
643
722
  detectGovernorOverloads,
644
723
  buildDelegateTx,
645
724
  buildDelegateSelfTx,
725
+ computeProposalIdHex,
726
+ getVotesLatestMinusOne,
727
+ simulatePropose,
728
+ /**
729
+ * Explicit arrays+bytes32 builder for propose-by-hash governors or deterministic descriptions.
730
+ */
731
+ buildProposeTxByHash: function buildProposeTxByHash({ governor, targets = [], values = [], calldatas = [], descriptionHash }) {
732
+ const addr = normaliseGovernor(governor);
733
+ const iface = new Interface(ABI.Governor);
734
+ const t = targets.map((a) => getAddress(a));
735
+ const v = values.map((value) => BigInt(String(value)));
736
+ const c = calldatas.map((data2) => hexlify(data2));
737
+ const dh = typeof descriptionHash === "string" && /^0x[0-9a-fA-F]{64}$/.test(descriptionHash) ? descriptionHash : hashDescription(String(descriptionHash || ""));
738
+ if (t.length !== v.length || t.length !== c.length) {
739
+ throw new SageSDKError(CODES.INVALID_ARGS, "targets, values, calldatas length mismatch");
740
+ }
741
+ const data = iface.encodeFunctionData("propose(address[],uint256[],bytes[],bytes32)", [t, v, c, dh]);
742
+ return { to: addr, data, value: BigIntZero };
743
+ },
646
744
  /**
647
745
  * Detect governance mode and operator status.
648
746
  * Heuristics mirror CLI detectGovMode.
@@ -2169,11 +2267,24 @@ var require_factory = __commonJS({
2169
2267
  }
2170
2268
  return out;
2171
2269
  }
2270
+ async function getSubDAORegistry({ provider, factory: factory2, subdao: subdao2 }) {
2271
+ if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
2272
+ const addr = normalise(factory2, "factory");
2273
+ const contract = new Contract(addr, ABI.FactoryRead, provider);
2274
+ try {
2275
+ const mapped = await contract.subdaoToRegistry(normalise(subdao2, "subdao"));
2276
+ const zero = "0x0000000000000000000000000000000000000000";
2277
+ return mapped && mapped !== zero ? getAddress(mapped) : null;
2278
+ } catch (_) {
2279
+ return null;
2280
+ }
2281
+ }
2172
2282
  module2.exports = {
2173
2283
  getFactoryConfig,
2174
2284
  getFactoryStats,
2175
2285
  listSubDAOs,
2176
2286
  listSubDAOsIndexed,
2287
+ getSubDAORegistry,
2177
2288
  listTemplates,
2178
2289
  getTemplateDetails,
2179
2290
  buildCreateSubDAOTx,
@@ -3100,7 +3211,20 @@ var require_library = __commonJS({
3100
3211
  hasScopedOwnership,
3101
3212
  buildUpdateLibraryForSubDAOTx,
3102
3213
  searchRegistry,
3103
- validation
3214
+ validation,
3215
+ /** Simulate calling a registry function as the timelock to verify authority/roles */
3216
+ simulateAsTimelock: async function simulateAsTimelock({ provider, registry, to, data, timelock: timelock2 }) {
3217
+ if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
3218
+ const reg = normalise(registry, "registry");
3219
+ const tgt = to ? normalise(to, "to") : reg;
3220
+ const from = normalise(timelock2, "timelock");
3221
+ try {
3222
+ await provider.call({ to: tgt, data, from });
3223
+ return { ok: true };
3224
+ } catch (err) {
3225
+ return { ok: false, error: { type: "Revert", message: String(err && err.message || err) } };
3226
+ }
3227
+ }
3104
3228
  };
3105
3229
  }
3106
3230
  });
@@ -5660,10 +5784,10 @@ var require_wallet = __commonJS({
5660
5784
  import: importWallet,
5661
5785
  export: exportWallet,
5662
5786
  sign,
5663
- // Optional advanced helpers (prefer @sage-protocol/wallet-manager when available)
5787
+ // Optional advanced helpers (prefer @sage/wallet-manager when available)
5664
5788
  fromMnemonic: async function fromMnemonic(opts) {
5665
5789
  try {
5666
- const wm = require("@sage-protocol/wallet-manager");
5790
+ const wm = require("@sage/wallet-manager");
5667
5791
  return await wm.fromMnemonic(opts);
5668
5792
  } catch (_) {
5669
5793
  if (!opts || !opts.mnemonic || !opts.rpcUrl) throw new SageSDKError(CODES.INVALID_ARGS, "mnemonic and rpcUrl required");
@@ -5675,7 +5799,7 @@ var require_wallet = __commonJS({
5675
5799
  },
5676
5800
  fromJsonKeystore: async function fromJsonKeystore(opts) {
5677
5801
  try {
5678
- const wm = require("@sage-protocol/wallet-manager");
5802
+ const wm = require("@sage/wallet-manager");
5679
5803
  return await wm.fromJsonKeystore(opts);
5680
5804
  } catch (_) {
5681
5805
  if (!opts || !opts.json || !opts.password || !opts.rpcUrl) throw new SageSDKError(CODES.INVALID_ARGS, "json, password, rpcUrl required");
@@ -5686,38 +5810,38 @@ var require_wallet = __commonJS({
5686
5810
  },
5687
5811
  fromCdp: async function fromCdp(opts) {
5688
5812
  try {
5689
- const wm = require("@sage-protocol/wallet-manager");
5813
+ const wm = require("@sage/wallet-manager");
5690
5814
  if (wm?.cdp?.fromCdp) return await wm.cdp.fromCdp(opts);
5691
5815
  throw new Error("cdp adapter not found");
5692
5816
  } catch (e) {
5693
- throw new SageSDKError(CODES.MISSING_DEPENDENCY, `@sage-protocol/wallet-manager cdp adapter required: ${e.message}`);
5817
+ throw new SageSDKError(CODES.MISSING_DEPENDENCY, `@sage/wallet-manager cdp adapter required: ${e.message}`);
5694
5818
  }
5695
5819
  },
5696
5820
  fromPrivy: async function fromPrivy(opts) {
5697
5821
  try {
5698
- const wm = require("@sage-protocol/wallet-manager");
5822
+ const wm = require("@sage/wallet-manager");
5699
5823
  if (wm?.privy?.fromPrivyDeterministic) return await wm.privy.fromPrivyDeterministic(opts);
5700
5824
  throw new Error("privy adapter not found");
5701
5825
  } catch (e) {
5702
- throw new SageSDKError(CODES.MISSING_DEPENDENCY, `@sage-protocol/wallet-manager privy adapter required: ${e.message}`);
5826
+ throw new SageSDKError(CODES.MISSING_DEPENDENCY, `@sage/wallet-manager privy adapter required: ${e.message}`);
5703
5827
  }
5704
5828
  },
5705
5829
  fromWalletConnect: async function fromWalletConnect(opts) {
5706
5830
  try {
5707
- const wm = require("@sage-protocol/wallet-manager");
5831
+ const wm = require("@sage/wallet-manager");
5708
5832
  if (wm?.walletconnect?.fromWalletConnect) return await wm.walletconnect.fromWalletConnect(opts);
5709
5833
  throw new Error("walletconnect adapter not found");
5710
5834
  } catch (e) {
5711
- throw new SageSDKError(CODES.MISSING_DEPENDENCY, `@sage-protocol/wallet-manager walletconnect adapter required: ${e.message}`);
5835
+ throw new SageSDKError(CODES.MISSING_DEPENDENCY, `@sage/wallet-manager walletconnect adapter required: ${e.message}`);
5712
5836
  }
5713
5837
  },
5714
5838
  fromWeb3Auth: async function fromWeb3Auth(opts) {
5715
5839
  try {
5716
- const wm = require("@sage-protocol/wallet-manager");
5840
+ const wm = require("@sage/wallet-manager");
5717
5841
  if (wm?.web3auth?.fromWeb3Auth) return await wm.web3auth.fromWeb3Auth(opts);
5718
5842
  throw new Error("web3auth adapter not found");
5719
5843
  } catch (e) {
5720
- throw new SageSDKError(CODES.MISSING_DEPENDENCY, `@sage-protocol/wallet-manager web3auth adapter required: ${e.message}`);
5844
+ throw new SageSDKError(CODES.MISSING_DEPENDENCY, `@sage/wallet-manager web3auth adapter required: ${e.message}`);
5721
5845
  }
5722
5846
  }
5723
5847
  };
@@ -5918,7 +6042,7 @@ var require_cast_manager = __commonJS({
5918
6042
  const normalized = ethers.getAddress(address);
5919
6043
  let cfgModule;
5920
6044
  try {
5921
- ({ ConfigManager: cfgModule } = require("@sage-protocol/shared"));
6045
+ ({ ConfigManager: cfgModule } = require("@sage/shared"));
5922
6046
  } catch (_) {
5923
6047
  cfgModule = require("./config");
5924
6048
  }
@@ -6010,7 +6134,7 @@ var require_cast_manager = __commonJS({
6010
6134
  try {
6011
6135
  let cliConfig;
6012
6136
  try {
6013
- ({ ConfigManager: cliConfig } = require("@sage-protocol/shared"));
6137
+ ({ ConfigManager: cliConfig } = require("@sage/shared"));
6014
6138
  } catch (_) {
6015
6139
  cliConfig = require("./config");
6016
6140
  }
package/dist/index.mjs CHANGED
@@ -20,7 +20,7 @@ var require_package = __commonJS({
20
20
  "package.json"(exports, module) {
21
21
  module.exports = {
22
22
  name: "@sage-protocol/sdk",
23
- version: "0.0.5",
23
+ version: "0.0.7",
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",
@@ -113,6 +113,8 @@ var require_abi = __commonJS({
113
113
  "function simpleKeyStoreAddress() view returns (address)",
114
114
  "function governanceConfigAddress() view returns (address)",
115
115
  "function libraryRegistryAddress() view returns (address)",
116
+ // Canonical per‑SubDAO mapping
117
+ "function subdaoToRegistry(address) view returns (address)",
116
118
  "function templateModule() view returns (address)",
117
119
  "function stats() view returns (uint128 totalSubDAOsCreated, uint128 totalBurnedForCreation)",
118
120
  // On-chain enumeration fallback (naming follows FactoryCoreFacet)
@@ -200,6 +202,7 @@ var require_abi = __commonJS({
200
202
  var ERC20Votes = [
201
203
  "function balanceOf(address) view returns (uint256)",
202
204
  "function getVotes(address) view returns (uint256)",
205
+ "function getPastVotes(address,uint256) view returns (uint256)",
203
206
  "function allowance(address,address) view returns (uint256)",
204
207
  "function delegate(address)",
205
208
  "function delegates(address) view returns (address)",
@@ -383,7 +386,7 @@ var require_description = __commonJS({
383
386
  // src/governance/index.js
384
387
  var require_governance = __commonJS({
385
388
  "src/governance/index.js"(exports, module) {
386
- var { Contract, Interface, getAddress, hexlify, keccak256, toUtf8Bytes } = __require("ethers");
389
+ var { Contract, Interface, AbiCoder, getAddress, hexlify, keccak256, toUtf8Bytes } = __require("ethers");
387
390
  var ABI = require_abi();
388
391
  var { BigIntZero } = require_types();
389
392
  var { SageSDKError, CODES } = require_errors();
@@ -524,6 +527,15 @@ var require_governance = __commonJS({
524
527
  function hashDescription(description) {
525
528
  return keccak256(toUtf8Bytes(String(description)));
526
529
  }
530
+ function computeProposalIdHex({ targets = [], values = [], calldatas = [], description = "" }) {
531
+ const coder = AbiCoder.defaultAbiCoder();
532
+ const t = targets.map((a) => getAddress(a));
533
+ const v = values.map((value) => BigInt(String(value)));
534
+ const c = calldatas.map((data) => hexlify(data));
535
+ const descHash = hashDescription(description);
536
+ const encoded = coder.encode(["address[]", "uint256[]", "bytes[]", "bytes32"], [t, v, c, descHash]);
537
+ return keccak256(encoded);
538
+ }
527
539
  function buildProposeTx({ governor, targets = [], values = [], calldatas = [], descriptionOrHash = "" }) {
528
540
  const addr = normaliseGovernor(governor);
529
541
  const iface = new Interface(ABI.Governor);
@@ -600,6 +612,73 @@ var require_governance = __commonJS({
600
612
  const tag = latest > 0 ? BigInt(latest - 1) : 0n;
601
613
  return getQuorumAt({ provider, governor, blockTag: tag });
602
614
  }
615
+ async function getVotesLatestMinusOne({ provider, token, governor, account }) {
616
+ if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
617
+ if (!token && !governor) throw new SageSDKError(CODES.INVALID_ARGS, "token or governor required");
618
+ if (!account) throw new SageSDKError(CODES.INVALID_ARGS, "account required");
619
+ let addr;
620
+ if (token) {
621
+ addr = getAddress(token);
622
+ } else {
623
+ const govAddr = normaliseGovernor(governor);
624
+ try {
625
+ const iface = new Interface(["function sxxxToken() view returns (address)"]);
626
+ const data = iface.encodeFunctionData("sxxxToken", []);
627
+ const ret = await provider.call({ to: govAddr, data });
628
+ const [tok] = AbiCoder.defaultAbiCoder().decode(["address"], ret);
629
+ addr = getAddress(tok);
630
+ } catch (err) {
631
+ throw new SageSDKError(CODES.NOT_FOUND, "failed to resolve governance token from governor", { cause: err });
632
+ }
633
+ }
634
+ const user = getAddress(account);
635
+ const latest = await provider.getBlockNumber();
636
+ const snapshot = latest > 0 ? BigInt(latest - 1) : 0n;
637
+ try {
638
+ const iface = new Interface(["function getPastVotes(address,uint256) view returns (uint256)"]);
639
+ const data = iface.encodeFunctionData("getPastVotes", [user, snapshot]);
640
+ const ret = await provider.call({ to: addr, data });
641
+ if (ret && ret !== "0x") {
642
+ const [val] = AbiCoder.defaultAbiCoder().decode(["uint256"], ret);
643
+ return BigInt(val.toString());
644
+ }
645
+ } catch (_) {
646
+ }
647
+ try {
648
+ const iface2 = new Interface(["function getVotes(address) view returns (uint256)"]);
649
+ const d2 = iface2.encodeFunctionData("getVotes", [user]);
650
+ const ret2 = await provider.call({ to: addr, data: d2 });
651
+ if (ret2 && ret2 !== "0x") {
652
+ const [val2] = AbiCoder.defaultAbiCoder().decode(["uint256"], ret2);
653
+ return BigInt(val2.toString());
654
+ }
655
+ } catch (_) {
656
+ }
657
+ return 0n;
658
+ }
659
+ async function simulatePropose({ provider, governor, targets = [], values = [], calldatas = [], description = "", sender }) {
660
+ if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
661
+ const addr = normaliseGovernor(governor);
662
+ const iface = new Interface(ABI.Governor);
663
+ const salted = makeProposalDescription(String(description || ""));
664
+ const t = targets.map((a) => getAddress(a));
665
+ const v = values.map((value) => BigInt(String(value)));
666
+ const c = calldatas.map((data2) => hexlify(data2));
667
+ let data;
668
+ try {
669
+ data = iface.encodeFunctionData("propose(address[],uint256[],bytes[],string)", [t, v, c, salted]);
670
+ } catch (err) {
671
+ return { ok: false, error: { type: "EncodeError", message: String(err && err.message || err) } };
672
+ }
673
+ try {
674
+ await provider.call({ to: addr, data, from: sender ? getAddress(sender) : void 0 });
675
+ return { ok: true };
676
+ } catch (err) {
677
+ let message = "execution reverted";
678
+ if (err && err.message) message = err.message;
679
+ return { ok: false, error: { type: "Revert", message } };
680
+ }
681
+ }
603
682
  async function detectGovernorOverloads({ provider, governor }) {
604
683
  if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
605
684
  const addr = normaliseGovernor(governor);
@@ -649,6 +728,25 @@ var require_governance = __commonJS({
649
728
  detectGovernorOverloads,
650
729
  buildDelegateTx,
651
730
  buildDelegateSelfTx,
731
+ computeProposalIdHex,
732
+ getVotesLatestMinusOne,
733
+ simulatePropose,
734
+ /**
735
+ * Explicit arrays+bytes32 builder for propose-by-hash governors or deterministic descriptions.
736
+ */
737
+ buildProposeTxByHash: function buildProposeTxByHash({ governor, targets = [], values = [], calldatas = [], descriptionHash }) {
738
+ const addr = normaliseGovernor(governor);
739
+ const iface = new Interface(ABI.Governor);
740
+ const t = targets.map((a) => getAddress(a));
741
+ const v = values.map((value) => BigInt(String(value)));
742
+ const c = calldatas.map((data2) => hexlify(data2));
743
+ const dh = typeof descriptionHash === "string" && /^0x[0-9a-fA-F]{64}$/.test(descriptionHash) ? descriptionHash : hashDescription(String(descriptionHash || ""));
744
+ if (t.length !== v.length || t.length !== c.length) {
745
+ throw new SageSDKError(CODES.INVALID_ARGS, "targets, values, calldatas length mismatch");
746
+ }
747
+ const data = iface.encodeFunctionData("propose(address[],uint256[],bytes[],bytes32)", [t, v, c, dh]);
748
+ return { to: addr, data, value: BigIntZero };
749
+ },
652
750
  /**
653
751
  * Detect governance mode and operator status.
654
752
  * Heuristics mirror CLI detectGovMode.
@@ -2175,11 +2273,24 @@ var require_factory = __commonJS({
2175
2273
  }
2176
2274
  return out;
2177
2275
  }
2276
+ async function getSubDAORegistry({ provider, factory, subdao }) {
2277
+ if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
2278
+ const addr = normalise(factory, "factory");
2279
+ const contract = new Contract(addr, ABI.FactoryRead, provider);
2280
+ try {
2281
+ const mapped = await contract.subdaoToRegistry(normalise(subdao, "subdao"));
2282
+ const zero = "0x0000000000000000000000000000000000000000";
2283
+ return mapped && mapped !== zero ? getAddress(mapped) : null;
2284
+ } catch (_) {
2285
+ return null;
2286
+ }
2287
+ }
2178
2288
  module.exports = {
2179
2289
  getFactoryConfig,
2180
2290
  getFactoryStats,
2181
2291
  listSubDAOs,
2182
2292
  listSubDAOsIndexed,
2293
+ getSubDAORegistry,
2183
2294
  listTemplates,
2184
2295
  getTemplateDetails,
2185
2296
  buildCreateSubDAOTx,
@@ -3106,7 +3217,20 @@ var require_library = __commonJS({
3106
3217
  hasScopedOwnership,
3107
3218
  buildUpdateLibraryForSubDAOTx,
3108
3219
  searchRegistry,
3109
- validation
3220
+ validation,
3221
+ /** Simulate calling a registry function as the timelock to verify authority/roles */
3222
+ simulateAsTimelock: async function simulateAsTimelock({ provider, registry, to, data, timelock }) {
3223
+ if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
3224
+ const reg = normalise(registry, "registry");
3225
+ const tgt = to ? normalise(to, "to") : reg;
3226
+ const from = normalise(timelock, "timelock");
3227
+ try {
3228
+ await provider.call({ to: tgt, data, from });
3229
+ return { ok: true };
3230
+ } catch (err) {
3231
+ return { ok: false, error: { type: "Revert", message: String(err && err.message || err) } };
3232
+ }
3233
+ }
3110
3234
  };
3111
3235
  }
3112
3236
  });
@@ -5666,10 +5790,10 @@ var require_wallet = __commonJS({
5666
5790
  import: importWallet,
5667
5791
  export: exportWallet,
5668
5792
  sign,
5669
- // Optional advanced helpers (prefer @sage-protocol/wallet-manager when available)
5793
+ // Optional advanced helpers (prefer @sage/wallet-manager when available)
5670
5794
  fromMnemonic: async function fromMnemonic(opts) {
5671
5795
  try {
5672
- const wm = __require("@sage-protocol/wallet-manager");
5796
+ const wm = __require("@sage/wallet-manager");
5673
5797
  return await wm.fromMnemonic(opts);
5674
5798
  } catch (_) {
5675
5799
  if (!opts || !opts.mnemonic || !opts.rpcUrl) throw new SageSDKError(CODES.INVALID_ARGS, "mnemonic and rpcUrl required");
@@ -5681,7 +5805,7 @@ var require_wallet = __commonJS({
5681
5805
  },
5682
5806
  fromJsonKeystore: async function fromJsonKeystore(opts) {
5683
5807
  try {
5684
- const wm = __require("@sage-protocol/wallet-manager");
5808
+ const wm = __require("@sage/wallet-manager");
5685
5809
  return await wm.fromJsonKeystore(opts);
5686
5810
  } catch (_) {
5687
5811
  if (!opts || !opts.json || !opts.password || !opts.rpcUrl) throw new SageSDKError(CODES.INVALID_ARGS, "json, password, rpcUrl required");
@@ -5692,38 +5816,38 @@ var require_wallet = __commonJS({
5692
5816
  },
5693
5817
  fromCdp: async function fromCdp(opts) {
5694
5818
  try {
5695
- const wm = __require("@sage-protocol/wallet-manager");
5819
+ const wm = __require("@sage/wallet-manager");
5696
5820
  if (wm?.cdp?.fromCdp) return await wm.cdp.fromCdp(opts);
5697
5821
  throw new Error("cdp adapter not found");
5698
5822
  } catch (e) {
5699
- throw new SageSDKError(CODES.MISSING_DEPENDENCY, `@sage-protocol/wallet-manager cdp adapter required: ${e.message}`);
5823
+ throw new SageSDKError(CODES.MISSING_DEPENDENCY, `@sage/wallet-manager cdp adapter required: ${e.message}`);
5700
5824
  }
5701
5825
  },
5702
5826
  fromPrivy: async function fromPrivy(opts) {
5703
5827
  try {
5704
- const wm = __require("@sage-protocol/wallet-manager");
5828
+ const wm = __require("@sage/wallet-manager");
5705
5829
  if (wm?.privy?.fromPrivyDeterministic) return await wm.privy.fromPrivyDeterministic(opts);
5706
5830
  throw new Error("privy adapter not found");
5707
5831
  } catch (e) {
5708
- throw new SageSDKError(CODES.MISSING_DEPENDENCY, `@sage-protocol/wallet-manager privy adapter required: ${e.message}`);
5832
+ throw new SageSDKError(CODES.MISSING_DEPENDENCY, `@sage/wallet-manager privy adapter required: ${e.message}`);
5709
5833
  }
5710
5834
  },
5711
5835
  fromWalletConnect: async function fromWalletConnect(opts) {
5712
5836
  try {
5713
- const wm = __require("@sage-protocol/wallet-manager");
5837
+ const wm = __require("@sage/wallet-manager");
5714
5838
  if (wm?.walletconnect?.fromWalletConnect) return await wm.walletconnect.fromWalletConnect(opts);
5715
5839
  throw new Error("walletconnect adapter not found");
5716
5840
  } catch (e) {
5717
- throw new SageSDKError(CODES.MISSING_DEPENDENCY, `@sage-protocol/wallet-manager walletconnect adapter required: ${e.message}`);
5841
+ throw new SageSDKError(CODES.MISSING_DEPENDENCY, `@sage/wallet-manager walletconnect adapter required: ${e.message}`);
5718
5842
  }
5719
5843
  },
5720
5844
  fromWeb3Auth: async function fromWeb3Auth(opts) {
5721
5845
  try {
5722
- const wm = __require("@sage-protocol/wallet-manager");
5846
+ const wm = __require("@sage/wallet-manager");
5723
5847
  if (wm?.web3auth?.fromWeb3Auth) return await wm.web3auth.fromWeb3Auth(opts);
5724
5848
  throw new Error("web3auth adapter not found");
5725
5849
  } catch (e) {
5726
- throw new SageSDKError(CODES.MISSING_DEPENDENCY, `@sage-protocol/wallet-manager web3auth adapter required: ${e.message}`);
5850
+ throw new SageSDKError(CODES.MISSING_DEPENDENCY, `@sage/wallet-manager web3auth adapter required: ${e.message}`);
5727
5851
  }
5728
5852
  }
5729
5853
  };
@@ -5924,7 +6048,7 @@ var require_cast_manager = __commonJS({
5924
6048
  const normalized = ethers.getAddress(address);
5925
6049
  let cfgModule;
5926
6050
  try {
5927
- ({ ConfigManager: cfgModule } = __require("@sage-protocol/shared"));
6051
+ ({ ConfigManager: cfgModule } = __require("@sage/shared"));
5928
6052
  } catch (_) {
5929
6053
  cfgModule = __require("./config");
5930
6054
  }
@@ -6016,7 +6140,7 @@ var require_cast_manager = __commonJS({
6016
6140
  try {
6017
6141
  let cliConfig;
6018
6142
  try {
6019
- ({ ConfigManager: cliConfig } = __require("@sage-protocol/shared"));
6143
+ ({ ConfigManager: cliConfig } = __require("@sage/shared"));
6020
6144
  } catch (_) {
6021
6145
  cliConfig = __require("./config");
6022
6146
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sage-protocol/sdk",
3
- "version": "0.0.6",
3
+ "version": "0.0.7",
4
4
  "description": "Backend-agnostic SDK for interacting with the Sage Protocol (governance, SubDAOs, tokens).",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.mjs",