@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 +38 -0
- package/dist/index.cjs +140 -16
- package/dist/index.mjs +140 -16
- 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
|
});
|
|
@@ -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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
6143
|
+
({ ConfigManager: cliConfig } = __require("@sage/shared"));
|
|
6020
6144
|
} catch (_) {
|
|
6021
6145
|
cliConfig = __require("./config");
|
|
6022
6146
|
}
|
package/package.json
CHANGED