@sage-protocol/sdk 0.0.5 → 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 +38 -0
- package/dist/index.cjs +127 -3
- package/dist/index.mjs +127 -3
- package/package.json +1 -1
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.
|
|
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
|
});
|
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.
|
|
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
|
});
|
package/package.json
CHANGED