@sage-protocol/sdk 0.1.2 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +288 -0
- package/dist/browser/index.mjs +155 -10
- package/dist/index.cjs +1351 -394
- package/dist/index.mjs +1444 -487
- package/dist/node/index.cjs +1351 -394
- package/dist/node/index.mjs +1446 -489
- package/package.json +15 -3
package/dist/node/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.1.
|
|
17
|
+
version: "0.1.4",
|
|
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",
|
|
@@ -50,10 +50,10 @@ var require_package = __commonJS({
|
|
|
50
50
|
],
|
|
51
51
|
sideEffects: false,
|
|
52
52
|
browser: {
|
|
53
|
+
child_process: false,
|
|
53
54
|
fs: false,
|
|
54
|
-
path: false,
|
|
55
55
|
os: false,
|
|
56
|
-
|
|
56
|
+
path: false
|
|
57
57
|
},
|
|
58
58
|
repository: {
|
|
59
59
|
type: "git",
|
|
@@ -82,6 +82,18 @@ var require_package = __commonJS({
|
|
|
82
82
|
sinon: "^17.0.1",
|
|
83
83
|
tsup: "^8.1.0",
|
|
84
84
|
typescript: "^5.4.0"
|
|
85
|
+
},
|
|
86
|
+
peerDependencies: {
|
|
87
|
+
react: "^18.0.0 || ^19.0.0",
|
|
88
|
+
swr: "^2.0.0"
|
|
89
|
+
},
|
|
90
|
+
peerDependenciesMeta: {
|
|
91
|
+
react: {
|
|
92
|
+
optional: true
|
|
93
|
+
},
|
|
94
|
+
swr: {
|
|
95
|
+
optional: true
|
|
96
|
+
}
|
|
85
97
|
}
|
|
86
98
|
};
|
|
87
99
|
}
|
|
@@ -529,9 +541,9 @@ var require_subgraph = __commonJS({
|
|
|
529
541
|
* Canonical proposal timeline. Tries common fields first, then event-style fallbacks.
|
|
530
542
|
* Returns { id, createdAt, queuedAt, executedAt, canceledAt, eta, state } (numbers/strings may be null when unavailable).
|
|
531
543
|
*/
|
|
532
|
-
async getProposalTimeline({ url, id }) {
|
|
544
|
+
async getProposalTimeline({ url, id: id2 }) {
|
|
533
545
|
if (!url) throw new Error("subgraph url required");
|
|
534
|
-
const pid = typeof
|
|
546
|
+
const pid = typeof id2 === "bigint" ? id2.toString() : String(id2);
|
|
535
547
|
try {
|
|
536
548
|
const data = await query(url, `
|
|
537
549
|
query($id: ID!) {
|
|
@@ -719,10 +731,10 @@ var require_subgraph = __commonJS({
|
|
|
719
731
|
updatedAt: Number(p.updatedAt || 0)
|
|
720
732
|
} : null;
|
|
721
733
|
},
|
|
722
|
-
async getProposalById({ url, id }) {
|
|
734
|
+
async getProposalById({ url, id: id2 }) {
|
|
723
735
|
if (!url) throw new Error("subgraph url required");
|
|
724
736
|
const doc = `query($id: ID!){ proposal(id:$id){ id proposer description createdAt updatedAt state eta targets values calldatas } }`;
|
|
725
|
-
const data = await query(url, doc, { id: String(
|
|
737
|
+
const data = await query(url, doc, { id: String(id2) });
|
|
726
738
|
const p = data?.proposal;
|
|
727
739
|
if (!p) return null;
|
|
728
740
|
return {
|
|
@@ -770,7 +782,7 @@ var require_ipfs = __commonJS({
|
|
|
770
782
|
"src/ipfs/index.js"(exports2, module2) {
|
|
771
783
|
var axiosDefault = require("axios");
|
|
772
784
|
var FormData = require("form-data");
|
|
773
|
-
var { ethers } = require("ethers");
|
|
785
|
+
var { ethers: ethers2 } = require("ethers");
|
|
774
786
|
var DEFAULT_GATEWAY = "https://ipfs.dev.sageprotocol.io/ipfs";
|
|
775
787
|
function toLowerSafe(value, fallback = "") {
|
|
776
788
|
if (value == null) return fallback;
|
|
@@ -825,14 +837,14 @@ var require_ipfs = __commonJS({
|
|
|
825
837
|
}
|
|
826
838
|
return Array.from(urls);
|
|
827
839
|
}
|
|
828
|
-
function ensureLeadingSlash(
|
|
829
|
-
const value =
|
|
840
|
+
function ensureLeadingSlash(path2, fallback = "") {
|
|
841
|
+
const value = path2 || fallback;
|
|
830
842
|
if (!value) return fallback;
|
|
831
843
|
return value.startsWith("/") ? value : `/${value}`;
|
|
832
844
|
}
|
|
833
845
|
function generateDeterministicCid(payload) {
|
|
834
846
|
const content = Buffer.isBuffer(payload) ? payload : typeof payload === "string" ? Buffer.from(payload) : Buffer.from(JSON.stringify(payload));
|
|
835
|
-
const hash =
|
|
847
|
+
const hash = ethers2.keccak256(content);
|
|
836
848
|
const hashStr = hash.slice(2);
|
|
837
849
|
const cidSuffix = (hashStr + hashStr).slice(0, 44);
|
|
838
850
|
return `Qm${cidSuffix}`;
|
|
@@ -904,7 +916,7 @@ var require_ipfs = __commonJS({
|
|
|
904
916
|
}
|
|
905
917
|
function workerUrl(kind, cid) {
|
|
906
918
|
const base = workerBaseUrl();
|
|
907
|
-
const ensure = (
|
|
919
|
+
const ensure = (path2) => path2.startsWith("/") ? path2 : `/${path2}`;
|
|
908
920
|
if (base) {
|
|
909
921
|
if (kind === "challenge") return `${base}${ensure(config.worker.challengePath || "/auth/challenge")}`;
|
|
910
922
|
if (kind === "upload") return `${base}${ensure(config.worker.uploadPath || "/ipfs/upload")}`;
|
|
@@ -1226,18 +1238,18 @@ var require_ipfs = __commonJS({
|
|
|
1226
1238
|
return postWorkerJson("discoveryEventsPath", "/discover/events", payload);
|
|
1227
1239
|
}
|
|
1228
1240
|
async function recordMcpUsageEvent({ promptId, metadata, address } = {}) {
|
|
1229
|
-
const
|
|
1230
|
-
if (!
|
|
1231
|
-
const payload = { promptId:
|
|
1241
|
+
const id2 = typeof promptId === "string" ? promptId.trim() : "";
|
|
1242
|
+
if (!id2) throw new Error("promptId required");
|
|
1243
|
+
const payload = { promptId: id2 };
|
|
1232
1244
|
if (metadata && typeof metadata === "object") payload.metadata = metadata;
|
|
1233
1245
|
const actor = address || config.worker.address;
|
|
1234
1246
|
if (actor) payload.address = actor;
|
|
1235
1247
|
return postWorkerJson("discoveryMcpPath", "/discover/mcp", payload);
|
|
1236
1248
|
}
|
|
1237
1249
|
async function recordLaunchEvent({ promptId, metadata, address } = {}) {
|
|
1238
|
-
const
|
|
1239
|
-
if (!
|
|
1240
|
-
const payload = { promptId:
|
|
1250
|
+
const id2 = typeof promptId === "string" ? promptId.trim() : "";
|
|
1251
|
+
if (!id2) throw new Error("promptId required");
|
|
1252
|
+
const payload = { promptId: id2 };
|
|
1241
1253
|
if (metadata && typeof metadata === "object") payload.metadata = metadata;
|
|
1242
1254
|
const actor = address || config.worker.address;
|
|
1243
1255
|
if (actor) payload.address = actor;
|
|
@@ -1267,11 +1279,11 @@ var require_ipfs = __commonJS({
|
|
|
1267
1279
|
}
|
|
1268
1280
|
async function reviewGovernanceReport(payload = {}) {
|
|
1269
1281
|
if (!payload || typeof payload !== "object") throw new Error("payload required");
|
|
1270
|
-
const
|
|
1271
|
-
if (!
|
|
1282
|
+
const id2 = typeof payload.id === "string" ? payload.id.trim() : "";
|
|
1283
|
+
if (!id2) throw new Error("report id required");
|
|
1272
1284
|
const status = typeof payload.status === "string" ? payload.status.trim() : "";
|
|
1273
1285
|
if (!status) throw new Error("status required");
|
|
1274
|
-
const body = { id, status };
|
|
1286
|
+
const body = { id: id2, status };
|
|
1275
1287
|
if (typeof payload.note === "string") body.note = payload.note;
|
|
1276
1288
|
if (typeof payload.action === "string") body.action = payload.action;
|
|
1277
1289
|
return postWorkerJson("governanceReviewPath", "/governance/report/review", body);
|
|
@@ -1597,18 +1609,18 @@ var require_validation = __commonJS({
|
|
|
1597
1609
|
} catch (_) {
|
|
1598
1610
|
}
|
|
1599
1611
|
}
|
|
1600
|
-
function normaliseSchemaPaths(schemaPaths, { path }) {
|
|
1612
|
+
function normaliseSchemaPaths(schemaPaths, { path: path2 }) {
|
|
1601
1613
|
if (Array.isArray(schemaPaths) && schemaPaths.length) {
|
|
1602
1614
|
return schemaPaths;
|
|
1603
1615
|
}
|
|
1604
1616
|
return [
|
|
1605
|
-
|
|
1606
|
-
|
|
1617
|
+
path2.join(process.cwd(), "docs", "schemas", "manifest.schema.json"),
|
|
1618
|
+
path2.join(__dirname, "..", "..", "docs", "schemas", "manifest.schema.json")
|
|
1607
1619
|
];
|
|
1608
1620
|
}
|
|
1609
|
-
function safeJsonParse(
|
|
1621
|
+
function safeJsonParse(fs2, file) {
|
|
1610
1622
|
try {
|
|
1611
|
-
const raw =
|
|
1623
|
+
const raw = fs2.readFileSync(file, "utf8");
|
|
1612
1624
|
return JSON.parse(raw);
|
|
1613
1625
|
} catch (_) {
|
|
1614
1626
|
return null;
|
|
@@ -1634,17 +1646,17 @@ var require_validation = __commonJS({
|
|
|
1634
1646
|
}
|
|
1635
1647
|
function createManifestValidator(options = {}) {
|
|
1636
1648
|
const {
|
|
1637
|
-
fs = fsDefault,
|
|
1638
|
-
path = pathDefault,
|
|
1649
|
+
fs: fs2 = fsDefault,
|
|
1650
|
+
path: path2 = pathDefault,
|
|
1639
1651
|
ajvFactory = defaultAjvFactory,
|
|
1640
1652
|
addFormats = defaultAddFormats,
|
|
1641
1653
|
schemaPaths
|
|
1642
1654
|
} = options;
|
|
1643
|
-
const searchPaths = normaliseSchemaPaths(schemaPaths, { path });
|
|
1655
|
+
const searchPaths = normaliseSchemaPaths(schemaPaths, { path: path2 });
|
|
1644
1656
|
function loadSchema() {
|
|
1645
1657
|
for (const schemaPath of searchPaths) {
|
|
1646
|
-
if (!
|
|
1647
|
-
const schema = safeJsonParse(
|
|
1658
|
+
if (!fs2.existsSync(schemaPath)) continue;
|
|
1659
|
+
const schema = safeJsonParse(fs2, schemaPath);
|
|
1648
1660
|
if (schema) return { schema, schemaPath };
|
|
1649
1661
|
}
|
|
1650
1662
|
return { schema: null, schemaPath: null };
|
|
@@ -1717,7 +1729,7 @@ var require_validation = __commonJS({
|
|
|
1717
1729
|
if (!manifestPath) {
|
|
1718
1730
|
throw new Error("manifestPath required");
|
|
1719
1731
|
}
|
|
1720
|
-
const data = safeJsonParse(
|
|
1732
|
+
const data = safeJsonParse(fs2, manifestPath);
|
|
1721
1733
|
if (!data) {
|
|
1722
1734
|
return {
|
|
1723
1735
|
ok: false,
|
|
@@ -1750,8 +1762,8 @@ var require_validation = __commonJS({
|
|
|
1750
1762
|
seenKeys.add(key);
|
|
1751
1763
|
const files = Array.isArray(prompt.files) ? prompt.files : [];
|
|
1752
1764
|
for (const file of files) {
|
|
1753
|
-
const resolved =
|
|
1754
|
-
if (!
|
|
1765
|
+
const resolved = path2.isAbsolute(file) ? file : manifestPath ? path2.join(path2.dirname(manifestPath), file) : file;
|
|
1766
|
+
if (!fs2.existsSync(resolved)) {
|
|
1755
1767
|
issues.push({
|
|
1756
1768
|
type: "missing_file",
|
|
1757
1769
|
message: `File not found: ${file}`,
|
|
@@ -1774,7 +1786,7 @@ var require_validation = __commonJS({
|
|
|
1774
1786
|
}
|
|
1775
1787
|
function bestPracticeCheckFile(manifestPath, options2 = {}) {
|
|
1776
1788
|
if (!manifestPath) throw new Error("manifestPath required");
|
|
1777
|
-
const data = safeJsonParse(
|
|
1789
|
+
const data = safeJsonParse(fs2, manifestPath);
|
|
1778
1790
|
if (!data) {
|
|
1779
1791
|
return [{ type: "parse_error", message: `Failed to parse JSON at ${manifestPath}`, manifestPath }];
|
|
1780
1792
|
}
|
|
@@ -1797,7 +1809,7 @@ var require_validation = __commonJS({
|
|
|
1797
1809
|
// src/library/index.js
|
|
1798
1810
|
var require_library = __commonJS({
|
|
1799
1811
|
"src/library/index.js"(exports2, module2) {
|
|
1800
|
-
var { Contract, getAddress, keccak256, toUtf8Bytes } = require("ethers");
|
|
1812
|
+
var { Contract, getAddress, keccak256, toUtf8Bytes, AbiCoder } = require("ethers");
|
|
1801
1813
|
var { Interface } = require("ethers");
|
|
1802
1814
|
var ABI = require_abi();
|
|
1803
1815
|
var { SageSDKError, CODES } = require_errors();
|
|
@@ -1836,17 +1848,31 @@ var require_library = __commonJS({
|
|
|
1836
1848
|
promptCount: Number(promptCount)
|
|
1837
1849
|
};
|
|
1838
1850
|
}
|
|
1851
|
+
function _computeLibraryKey(subdao, libraryId) {
|
|
1852
|
+
const coder = AbiCoder.defaultAbiCoder ? AbiCoder.defaultAbiCoder() : new AbiCoder();
|
|
1853
|
+
const encoded = coder.encode(["address", "string"], [getAddress(subdao), String(libraryId)]);
|
|
1854
|
+
return keccak256(encoded);
|
|
1855
|
+
}
|
|
1839
1856
|
async function getLatestLibrary({ provider, registry, subdao, libraryId = "main" }) {
|
|
1840
1857
|
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
|
|
1841
1858
|
const addr = normalise(registry, "registry");
|
|
1842
1859
|
const sub = normalise(subdao, "subdao");
|
|
1843
1860
|
const contract = new Contract(addr, ABI.LibraryRegistry, provider);
|
|
1844
|
-
const key =
|
|
1861
|
+
const key = _computeLibraryKey(sub, libraryId);
|
|
1845
1862
|
const latestCID = await contract.subdaoLibraryLatest(key).catch(() => "");
|
|
1846
1863
|
if (!latestCID || latestCID.length === 0) return null;
|
|
1847
1864
|
const info = await getManifestInfo({ provider, registry: addr, manifestCID: latestCID });
|
|
1848
1865
|
return info;
|
|
1849
1866
|
}
|
|
1867
|
+
async function getBeforeAfterForUpdate({ provider, registry, subdao, libraryId = "main", newCid }) {
|
|
1868
|
+
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
|
|
1869
|
+
const addr = normalise(registry, "registry");
|
|
1870
|
+
const sub = normalise(subdao, "subdao");
|
|
1871
|
+
const contract = new Contract(addr, ABI.LibraryRegistry, provider);
|
|
1872
|
+
const key = _computeLibraryKey(sub, libraryId);
|
|
1873
|
+
const prev = await contract.subdaoLibraryLatest(key).catch(() => "");
|
|
1874
|
+
return { previousCID: prev || null, newCID: String(newCid), libraryId: String(libraryId) };
|
|
1875
|
+
}
|
|
1850
1876
|
async function hasScopedOwnership({ provider, registry, subdao, manifestCID }) {
|
|
1851
1877
|
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
|
|
1852
1878
|
const addr = normalise(registry, "registry");
|
|
@@ -1872,6 +1898,8 @@ var require_library = __commonJS({
|
|
|
1872
1898
|
getLatestLibrary,
|
|
1873
1899
|
hasScopedOwnership,
|
|
1874
1900
|
buildUpdateLibraryForSubDAOTx,
|
|
1901
|
+
_computeLibraryKey,
|
|
1902
|
+
getBeforeAfterForUpdate,
|
|
1875
1903
|
/** Build an authorizeTimelock(timelock, subdao) call for a LibraryRegistry. */
|
|
1876
1904
|
buildAuthorizeTimelockTx: function buildAuthorizeTimelockTx({ registry, timelock, subdao }) {
|
|
1877
1905
|
const to = normalise(registry, "registry");
|
|
@@ -1958,11 +1986,11 @@ var require_governance = __commonJS({
|
|
|
1958
1986
|
stakeAmount
|
|
1959
1987
|
};
|
|
1960
1988
|
}
|
|
1961
|
-
async function getProposal({ provider, governor, id }) {
|
|
1989
|
+
async function getProposal({ provider, governor, id: id2 }) {
|
|
1962
1990
|
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
|
|
1963
1991
|
const addr = normaliseGovernor(governor);
|
|
1964
1992
|
const g = new Contract(addr, ABI.Governor, provider);
|
|
1965
|
-
const pid = typeof
|
|
1993
|
+
const pid = typeof id2 === "bigint" ? id2 : String(id2).startsWith("0x") ? BigInt(id2) : BigInt(String(id2));
|
|
1966
1994
|
const [state, snapshot, deadline, votes] = await Promise.all([
|
|
1967
1995
|
g.state(pid),
|
|
1968
1996
|
g.proposalSnapshot(pid),
|
|
@@ -2016,12 +2044,12 @@ var require_governance = __commonJS({
|
|
|
2016
2044
|
}
|
|
2017
2045
|
return proposals;
|
|
2018
2046
|
}
|
|
2019
|
-
async function getProposalMetadata({ provider, governor, id, fromBlock = 0, toBlock = "latest" }) {
|
|
2047
|
+
async function getProposalMetadata({ provider, governor, id: id2, fromBlock = 0, toBlock = "latest" }) {
|
|
2020
2048
|
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
|
|
2021
2049
|
const addr = normaliseGovernor(governor);
|
|
2022
2050
|
const iface = new Interface([ABI.Events.ProposalCreated]);
|
|
2023
2051
|
const topic = iface.getEvent("ProposalCreated").topicHash;
|
|
2024
|
-
const pid = typeof
|
|
2052
|
+
const pid = typeof id2 === "bigint" ? id2 : String(id2).startsWith("0x") ? BigInt(id2) : BigInt(String(id2));
|
|
2025
2053
|
const logs = await provider.getLogs({ address: addr, fromBlock, toBlock, topics: [topic] });
|
|
2026
2054
|
for (const log of logs) {
|
|
2027
2055
|
try {
|
|
@@ -2082,10 +2110,10 @@ var require_governance = __commonJS({
|
|
|
2082
2110
|
function buildCastVoteTx({ governor, proposalId, support, reason }) {
|
|
2083
2111
|
const addr = normaliseGovernor(governor);
|
|
2084
2112
|
const iface = new Interface(ABI.Governor);
|
|
2085
|
-
const
|
|
2113
|
+
const id2 = typeof proposalId === "bigint" ? proposalId : String(proposalId).startsWith("0x") ? BigInt(proposalId) : BigInt(String(proposalId));
|
|
2086
2114
|
const s = Number(support);
|
|
2087
2115
|
const hasReason = reason && String(reason).length > 0;
|
|
2088
|
-
const data = hasReason ? iface.encodeFunctionData("castVoteWithReason(uint256,uint8,string)", [
|
|
2116
|
+
const data = hasReason ? iface.encodeFunctionData("castVoteWithReason(uint256,uint8,string)", [id2, s, String(reason)]) : iface.encodeFunctionData("castVote(uint256,uint8)", [id2, s]);
|
|
2089
2117
|
return { to: addr, data, value: BigIntZero };
|
|
2090
2118
|
}
|
|
2091
2119
|
function cueTx(fn, { governor, targets = [], values = [], calldatas = [], descriptionOrHash = "" }) {
|
|
@@ -2106,17 +2134,73 @@ var require_governance = __commonJS({
|
|
|
2106
2134
|
function buildQueueByIdTx({ governor, proposalId }) {
|
|
2107
2135
|
const addr = normaliseGovernor(governor);
|
|
2108
2136
|
const iface = new Interface(ABI.Governor);
|
|
2109
|
-
const
|
|
2110
|
-
const data = iface.encodeFunctionData("queue(uint256)", [
|
|
2137
|
+
const id2 = typeof proposalId === "bigint" ? proposalId : String(proposalId).startsWith("0x") ? BigInt(proposalId) : BigInt(String(proposalId));
|
|
2138
|
+
const data = iface.encodeFunctionData("queue(uint256)", [id2]);
|
|
2111
2139
|
return { to: addr, data, value: BigIntZero };
|
|
2112
2140
|
}
|
|
2113
2141
|
function buildExecuteByIdTx({ governor, proposalId }) {
|
|
2114
2142
|
const addr = normaliseGovernor(governor);
|
|
2115
2143
|
const iface = new Interface(ABI.Governor);
|
|
2116
|
-
const
|
|
2117
|
-
const data = iface.encodeFunctionData("execute(uint256)", [
|
|
2144
|
+
const id2 = typeof proposalId === "bigint" ? proposalId : String(proposalId).startsWith("0x") ? BigInt(proposalId) : BigInt(String(proposalId));
|
|
2145
|
+
const data = iface.encodeFunctionData("execute(uint256)", [id2]);
|
|
2118
2146
|
return { to: addr, data, value: BigIntZero };
|
|
2119
2147
|
}
|
|
2148
|
+
async function decodeProposalEffects({ provider, governor, proposalId, fromBlock = 0, toBlock = "latest" }) {
|
|
2149
|
+
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
|
|
2150
|
+
const govAddr = normaliseGovernor(governor);
|
|
2151
|
+
const iface = new Interface([ABI.Events.ProposalCreated]);
|
|
2152
|
+
const topic = iface.getEvent("ProposalCreated").topicHash;
|
|
2153
|
+
const id2 = typeof proposalId === "bigint" ? proposalId : String(proposalId).startsWith("0x") ? BigInt(proposalId) : BigInt(String(proposalId));
|
|
2154
|
+
let parsed = null;
|
|
2155
|
+
let logTxHash = null;
|
|
2156
|
+
const logs = await provider.getLogs({ address: govAddr, fromBlock, toBlock, topics: [topic] });
|
|
2157
|
+
for (const log of logs) {
|
|
2158
|
+
try {
|
|
2159
|
+
const p = iface.parseLog(log);
|
|
2160
|
+
if (BigInt(p.args.id.toString()) === id2) {
|
|
2161
|
+
parsed = p;
|
|
2162
|
+
logTxHash = log.transactionHash;
|
|
2163
|
+
break;
|
|
2164
|
+
}
|
|
2165
|
+
} catch (_) {
|
|
2166
|
+
}
|
|
2167
|
+
}
|
|
2168
|
+
if (!parsed) throw new Error("ProposalCreated event not found");
|
|
2169
|
+
const targets = parsed.args.targets.map(getAddress);
|
|
2170
|
+
const calldatas = parsed.args.calldatas.map((d) => typeof d === "string" ? d : "0x" + Buffer.from(d).toString("hex"));
|
|
2171
|
+
const LibraryIface = new Interface(["function updateLibraryForSubDAO(address,string,string,uint256)", "function subdaoLibraryLatest(bytes32) view returns (string)"]);
|
|
2172
|
+
const PromptIface = new Interface(["function updatePromptByGovernance(string,string)"]);
|
|
2173
|
+
const coder = AbiCoder.defaultAbiCoder ? AbiCoder.defaultAbiCoder() : new AbiCoder();
|
|
2174
|
+
const effects = [];
|
|
2175
|
+
for (let i = 0; i < calldatas.length; i++) {
|
|
2176
|
+
const data = calldatas[i];
|
|
2177
|
+
const sel = data.slice(0, 10);
|
|
2178
|
+
try {
|
|
2179
|
+
const decoded = LibraryIface.decodeFunctionData("updateLibraryForSubDAO", data);
|
|
2180
|
+
const [subdao, libraryId, newCid, promptCount] = decoded;
|
|
2181
|
+
let previousCID = null;
|
|
2182
|
+
try {
|
|
2183
|
+
const reg = new Contract(targets[i], ["function subdaoLibraryLatest(bytes32) view returns (string)"], provider);
|
|
2184
|
+
const key = keccak256(coder.encode(["address", "string"], [getAddress(subdao), String(libraryId)]));
|
|
2185
|
+
const prev = await reg.subdaoLibraryLatest(key).catch(() => "");
|
|
2186
|
+
previousCID = prev && prev.length ? String(prev) : null;
|
|
2187
|
+
} catch (_) {
|
|
2188
|
+
}
|
|
2189
|
+
effects.push({ type: "libraryUpdate", index: i, target: targets[i], subdao: getAddress(subdao), libraryId: String(libraryId), previousCid: previousCID, newCid: String(newCid), promptCount: Number(promptCount) });
|
|
2190
|
+
continue;
|
|
2191
|
+
} catch (_) {
|
|
2192
|
+
}
|
|
2193
|
+
try {
|
|
2194
|
+
const decodedP = PromptIface.decodeFunctionData("updatePromptByGovernance", data);
|
|
2195
|
+
const [key, newCid] = decodedP;
|
|
2196
|
+
effects.push({ type: "promptUpdate", index: i, target: targets[i], key: String(key), newCid: String(newCid) });
|
|
2197
|
+
continue;
|
|
2198
|
+
} catch (_) {
|
|
2199
|
+
}
|
|
2200
|
+
effects.push({ type: "unknown", index: i, target: targets[i], selector: sel });
|
|
2201
|
+
}
|
|
2202
|
+
return { governor: govAddr, proposalId: id2, tx: logTxHash, actions: { count: calldatas.length }, effects };
|
|
2203
|
+
}
|
|
2120
2204
|
async function getQuorumAt({ provider, governor, blockTag }) {
|
|
2121
2205
|
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
|
|
2122
2206
|
const addr = normaliseGovernor(governor);
|
|
@@ -2246,6 +2330,7 @@ var require_governance = __commonJS({
|
|
|
2246
2330
|
buildExecuteTx,
|
|
2247
2331
|
buildQueueByIdTx,
|
|
2248
2332
|
buildExecuteByIdTx,
|
|
2333
|
+
decodeProposalEffects,
|
|
2249
2334
|
makeProposalDescription,
|
|
2250
2335
|
stripProposalSalt,
|
|
2251
2336
|
getQuorumAt,
|
|
@@ -2952,7 +3037,7 @@ var require_openzeppelin = __commonJS({
|
|
|
2952
3037
|
for (const log of logs) {
|
|
2953
3038
|
try {
|
|
2954
3039
|
const parsed = iface.parseLog(log);
|
|
2955
|
-
const
|
|
3040
|
+
const id2 = BigInt(parsed.args.id.toString());
|
|
2956
3041
|
const proposer = getAddress(parsed.args.proposer);
|
|
2957
3042
|
const targets = parsed.args.targets.map(getAddress);
|
|
2958
3043
|
const values = parsed.args.values.map((v) => BigInt(v.toString()));
|
|
@@ -2962,7 +3047,7 @@ var require_openzeppelin = __commonJS({
|
|
|
2962
3047
|
const block = await provider.getBlock(log.blockNumber).catch(() => ({ timestamp: 0 }));
|
|
2963
3048
|
const quorum = await governance.getQuorumAt({ provider, governor: addr, blockTag: BigInt(endBlock || log.blockNumber) }).catch(() => null);
|
|
2964
3049
|
const signatures = await getSignatureList({ provider, targets, calldatas, abiResolver, selectorResolver, chainId: resolvedChainId });
|
|
2965
|
-
items.push({ id, proposer, createdAt: Number(block.timestamp || 0), startBlock, endBlock, quorum, txHash: log.transactionHash, targets, values, calldatas, signatures });
|
|
3050
|
+
items.push({ id: id2, proposer, createdAt: Number(block.timestamp || 0), startBlock, endBlock, quorum, txHash: log.transactionHash, targets, values, calldatas, signatures });
|
|
2966
3051
|
} catch (_) {
|
|
2967
3052
|
}
|
|
2968
3053
|
}
|
|
@@ -2970,10 +3055,10 @@ var require_openzeppelin = __commonJS({
|
|
|
2970
3055
|
}
|
|
2971
3056
|
return { items, nextCursor: null };
|
|
2972
3057
|
}
|
|
2973
|
-
async function getTimelineOnchain({ provider, governor, id, fromBlock = 0, toBlock = "latest" }) {
|
|
3058
|
+
async function getTimelineOnchain({ provider, governor, id: id2, fromBlock = 0, toBlock = "latest" }) {
|
|
2974
3059
|
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
|
|
2975
3060
|
const addr = normaliseGovernor(governor);
|
|
2976
|
-
const pid = typeof
|
|
3061
|
+
const pid = typeof id2 === "bigint" ? id2 : String(id2).startsWith("0x") ? BigInt(id2) : BigInt(String(id2));
|
|
2977
3062
|
const iface = new Interface([Events.ProposalQueued, Events.ProposalExecuted, Events.ProposalCanceled]);
|
|
2978
3063
|
const topics = [
|
|
2979
3064
|
iface.getEvent("ProposalQueued").topicHash,
|
|
@@ -3206,9 +3291,9 @@ var require_operations = __commonJS({
|
|
|
3206
3291
|
throw new SageSDKError(CODES.INVALID_ARGS, "invalid governor address", { cause: error });
|
|
3207
3292
|
}
|
|
3208
3293
|
}
|
|
3209
|
-
function normaliseProposalId(
|
|
3210
|
-
if (typeof
|
|
3211
|
-
const value = String(
|
|
3294
|
+
function normaliseProposalId(id2) {
|
|
3295
|
+
if (typeof id2 === "bigint") return id2;
|
|
3296
|
+
const value = String(id2);
|
|
3212
3297
|
try {
|
|
3213
3298
|
return value.startsWith("0x") ? BigInt(value) : BigInt(value);
|
|
3214
3299
|
} catch (error) {
|
|
@@ -3230,7 +3315,7 @@ var require_operations = __commonJS({
|
|
|
3230
3315
|
if (!load || !save) return null;
|
|
3231
3316
|
return { load, save };
|
|
3232
3317
|
}
|
|
3233
|
-
function normaliseTuple(governor,
|
|
3318
|
+
function normaliseTuple(governor, id2, metadata) {
|
|
3234
3319
|
const targets = Array.isArray(metadata.targets) ? metadata.targets.map((t) => getAddress(t)) : [];
|
|
3235
3320
|
let values = Array.isArray(metadata.values) ? metadata.values.map((v) => BigInt(v)) : new Array(targets.length).fill(BigIntZero);
|
|
3236
3321
|
const calldatas = Array.isArray(metadata.calldatas) ? metadata.calldatas.map(String) : [];
|
|
@@ -3240,7 +3325,7 @@ var require_operations = __commonJS({
|
|
|
3240
3325
|
const description = metadata.description || metadata.body || "";
|
|
3241
3326
|
const descriptionHash = metadata.descriptionHash || (typeof metadata.hashDescription === "function" ? metadata.hashDescription(description) : keccak256(toUtf8Bytes(String(description || ""))));
|
|
3242
3327
|
return {
|
|
3243
|
-
id,
|
|
3328
|
+
id: id2,
|
|
3244
3329
|
governor,
|
|
3245
3330
|
targets,
|
|
3246
3331
|
values,
|
|
@@ -3265,10 +3350,10 @@ var require_operations = __commonJS({
|
|
|
3265
3350
|
}) {
|
|
3266
3351
|
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
|
|
3267
3352
|
const govAddr = normaliseGovernor(governor);
|
|
3268
|
-
const
|
|
3353
|
+
const id2 = normaliseProposalId(proposalId);
|
|
3269
3354
|
const cacheAdapter = wrapCache(cache);
|
|
3270
3355
|
if (!refresh && cacheAdapter) {
|
|
3271
|
-
const cached = await cacheAdapter.load(govAddr,
|
|
3356
|
+
const cached = await cacheAdapter.load(govAddr, id2);
|
|
3272
3357
|
if (cached) return cached;
|
|
3273
3358
|
}
|
|
3274
3359
|
if (helperAddress) {
|
|
@@ -3277,10 +3362,10 @@ var require_operations = __commonJS({
|
|
|
3277
3362
|
"function getProposalTuple(uint256) view returns (address[] targets,uint256[] values,bytes[] calldatas,bytes32 descriptionHash,bool exists)"
|
|
3278
3363
|
];
|
|
3279
3364
|
const helper = new Contract(helperAddress, helperAbi, provider);
|
|
3280
|
-
const res = await helper.getProposalTuple(
|
|
3365
|
+
const res = await helper.getProposalTuple(id2);
|
|
3281
3366
|
if (res && res.exists) {
|
|
3282
3367
|
const tuple2 = {
|
|
3283
|
-
id,
|
|
3368
|
+
id: id2,
|
|
3284
3369
|
governor: normaliseGovernor(governor),
|
|
3285
3370
|
targets: res.targets || [],
|
|
3286
3371
|
values: (res.values || []).map((v) => BigInt(v)),
|
|
@@ -3289,7 +3374,7 @@ var require_operations = __commonJS({
|
|
|
3289
3374
|
descriptionHash: res.descriptionHash || null,
|
|
3290
3375
|
createdBlock: null
|
|
3291
3376
|
};
|
|
3292
|
-
if (cacheAdapter) await cacheAdapter.save(governor,
|
|
3377
|
+
if (cacheAdapter) await cacheAdapter.save(governor, id2, tuple2);
|
|
3293
3378
|
return tuple2;
|
|
3294
3379
|
}
|
|
3295
3380
|
} catch (_) {
|
|
@@ -3297,7 +3382,7 @@ var require_operations = __commonJS({
|
|
|
3297
3382
|
}
|
|
3298
3383
|
let metadata = null;
|
|
3299
3384
|
try {
|
|
3300
|
-
metadata = await governance.getProposalMetadata({ provider, governor: govAddr, id });
|
|
3385
|
+
metadata = await governance.getProposalMetadata({ provider, governor: govAddr, id: id2 });
|
|
3301
3386
|
} catch (_) {
|
|
3302
3387
|
metadata = null;
|
|
3303
3388
|
}
|
|
@@ -3306,7 +3391,7 @@ var require_operations = __commonJS({
|
|
|
3306
3391
|
try {
|
|
3307
3392
|
const govAbi = new Interface(ABI.Governor);
|
|
3308
3393
|
const govC = new Contract(govAddr, govAbi, provider);
|
|
3309
|
-
const snapshot = hints.snapshot ?? await govC.proposalSnapshot(
|
|
3394
|
+
const snapshot = hints.snapshot ?? await govC.proposalSnapshot(id2).catch(() => null);
|
|
3310
3395
|
const votingDelay = hints.votingDelay ?? await govC.votingDelay().catch(() => null);
|
|
3311
3396
|
if (snapshot !== null && votingDelay !== null) {
|
|
3312
3397
|
const approxCreation = Number(snapshot) - Number(votingDelay);
|
|
@@ -3329,9 +3414,9 @@ var require_operations = __commonJS({
|
|
|
3329
3414
|
try {
|
|
3330
3415
|
const parsed = govC.interface.parseLog(log);
|
|
3331
3416
|
const pid = normaliseProposalId(parsed.args.proposalId);
|
|
3332
|
-
if (pid ===
|
|
3417
|
+
if (pid === id2) {
|
|
3333
3418
|
metadata = {
|
|
3334
|
-
id,
|
|
3419
|
+
id: id2,
|
|
3335
3420
|
governor: govAddr,
|
|
3336
3421
|
targets: Array.from(parsed.args.targets || [], String),
|
|
3337
3422
|
values: Array.from(parsed.args.values || [], (v) => BigInt(v.toString())),
|
|
@@ -3356,7 +3441,7 @@ var require_operations = __commonJS({
|
|
|
3356
3441
|
const page = await governance.listProposals({ provider, governor: govAddr, fromBlock, toBlock: "latest" });
|
|
3357
3442
|
metadata = page.find((entry) => {
|
|
3358
3443
|
try {
|
|
3359
|
-
return normaliseProposalId(entry.id || entry.proposalId) ===
|
|
3444
|
+
return normaliseProposalId(entry.id || entry.proposalId) === id2;
|
|
3360
3445
|
} catch (_) {
|
|
3361
3446
|
return false;
|
|
3362
3447
|
}
|
|
@@ -3366,9 +3451,9 @@ var require_operations = __commonJS({
|
|
|
3366
3451
|
if (!metadata) {
|
|
3367
3452
|
throw new SageSDKError(CODES.NOT_FOUND, "proposal tuple not found");
|
|
3368
3453
|
}
|
|
3369
|
-
const tuple = normaliseTuple(govAddr,
|
|
3454
|
+
const tuple = normaliseTuple(govAddr, id2, metadata);
|
|
3370
3455
|
if (cacheAdapter) {
|
|
3371
|
-
await cacheAdapter.save(govAddr,
|
|
3456
|
+
await cacheAdapter.save(govAddr, id2, tuple);
|
|
3372
3457
|
}
|
|
3373
3458
|
return tuple;
|
|
3374
3459
|
}
|
|
@@ -3664,6 +3749,91 @@ var require_operations = __commonJS({
|
|
|
3664
3749
|
}
|
|
3665
3750
|
});
|
|
3666
3751
|
|
|
3752
|
+
// src/governance/grants.js
|
|
3753
|
+
var require_grants = __commonJS({
|
|
3754
|
+
"src/governance/grants.js"(exports2, module2) {
|
|
3755
|
+
var { Interface, getAddress, isAddress, parseUnits } = require("ethers");
|
|
3756
|
+
var { SageSDKError, CODES } = require_errors();
|
|
3757
|
+
function normalizeAddress(label, value) {
|
|
3758
|
+
if (!value) throw new SageSDKError(CODES.INVALID_ARGS, `${label} required`);
|
|
3759
|
+
if (!isAddress(value)) throw new SageSDKError(CODES.INVALID_ARGS, `${label} invalid`);
|
|
3760
|
+
return getAddress(value);
|
|
3761
|
+
}
|
|
3762
|
+
async function buildGrantProposal({ provider = null, vault, token, recipient, amount, decimals = null, raw = false, description = null }) {
|
|
3763
|
+
const vaultAddr = normalizeAddress("vault", vault);
|
|
3764
|
+
const tokenAddr = normalizeAddress("token", token);
|
|
3765
|
+
const rcptAddr = normalizeAddress("recipient", recipient);
|
|
3766
|
+
if (amount == null) throw new SageSDKError(CODES.INVALID_ARGS, "amount required");
|
|
3767
|
+
let resolvedDecimals = decimals != null ? Number(decimals) : null;
|
|
3768
|
+
let symbol = null;
|
|
3769
|
+
if (provider && resolvedDecimals == null) {
|
|
3770
|
+
try {
|
|
3771
|
+
const erc20 = new (require("ethers")).Contract(tokenAddr, ["function decimals() view returns (uint8)", "function symbol() view returns (string)"], provider);
|
|
3772
|
+
resolvedDecimals = Number(await erc20.decimals());
|
|
3773
|
+
symbol = await erc20.symbol().catch(() => null);
|
|
3774
|
+
} catch (_) {
|
|
3775
|
+
}
|
|
3776
|
+
}
|
|
3777
|
+
if (resolvedDecimals == null) resolvedDecimals = 18;
|
|
3778
|
+
let amtWei;
|
|
3779
|
+
if (raw) {
|
|
3780
|
+
amtWei = BigInt(String(amount));
|
|
3781
|
+
} else {
|
|
3782
|
+
amtWei = parseUnits(String(amount), resolvedDecimals);
|
|
3783
|
+
}
|
|
3784
|
+
const iface = new Interface(["function withdraw(address token,uint256 amount,address recipient)"]);
|
|
3785
|
+
const data = iface.encodeFunctionData("withdraw", [tokenAddr, amtWei, rcptAddr]);
|
|
3786
|
+
const targets = [vaultAddr];
|
|
3787
|
+
const values = [0n];
|
|
3788
|
+
const calldatas = [data];
|
|
3789
|
+
const desc = description && description.length ? description : `Grant ${String(amount)}${symbol ? " " + symbol : ""} to ${rcptAddr}`;
|
|
3790
|
+
return { targets, values, calldatas, description: desc };
|
|
3791
|
+
}
|
|
3792
|
+
module2.exports = {
|
|
3793
|
+
buildGrantProposal,
|
|
3794
|
+
/**
|
|
3795
|
+
* Build a batched proposal for multiple grants. Each item can specify its own vault
|
|
3796
|
+
* or inherit from defaultVault. Decimals are resolved per-token when provider is present.
|
|
3797
|
+
* items: Array<{ vault?, token, recipient, amount, decimals?, raw? }>
|
|
3798
|
+
*/
|
|
3799
|
+
buildBatchGrantProposal: async function buildBatchGrantProposal({ provider = null, items = [], defaultVault = null, description = null }) {
|
|
3800
|
+
if (!Array.isArray(items) || items.length === 0) {
|
|
3801
|
+
throw new SageSDKError(CODES.INVALID_ARGS, "items required");
|
|
3802
|
+
}
|
|
3803
|
+
const targets = [];
|
|
3804
|
+
const values = [];
|
|
3805
|
+
const calldatas = [];
|
|
3806
|
+
const iface = new Interface(["function withdraw(address token,uint256 amount,address recipient)"]);
|
|
3807
|
+
for (const [i, it] of items.entries()) {
|
|
3808
|
+
const vault = it.vault || defaultVault;
|
|
3809
|
+
if (!vault) throw new SageSDKError(CODES.INVALID_ARGS, `item[${i}]: vault missing and no defaultVault provided`);
|
|
3810
|
+
const vaultAddr = normalizeAddress("vault", vault);
|
|
3811
|
+
const tokenAddr = normalizeAddress("token", it.token);
|
|
3812
|
+
const rcptAddr = normalizeAddress("recipient", it.recipient);
|
|
3813
|
+
let resolvedDecimals = it.decimals != null ? Number(it.decimals) : null;
|
|
3814
|
+
if (provider && resolvedDecimals == null && !it.raw) {
|
|
3815
|
+
try {
|
|
3816
|
+
const erc20 = new (require("ethers")).Contract(tokenAddr, ["function decimals() view returns (uint8)"], provider);
|
|
3817
|
+
resolvedDecimals = Number(await erc20.decimals());
|
|
3818
|
+
} catch (_) {
|
|
3819
|
+
}
|
|
3820
|
+
}
|
|
3821
|
+
if (resolvedDecimals == null) resolvedDecimals = 18;
|
|
3822
|
+
let amtWei;
|
|
3823
|
+
if (it.raw) amtWei = BigInt(String(it.amount));
|
|
3824
|
+
else amtWei = parseUnits(String(it.amount), resolvedDecimals);
|
|
3825
|
+
const data = iface.encodeFunctionData("withdraw", [tokenAddr, amtWei, rcptAddr]);
|
|
3826
|
+
targets.push(vaultAddr);
|
|
3827
|
+
values.push(0n);
|
|
3828
|
+
calldatas.push(data);
|
|
3829
|
+
}
|
|
3830
|
+
const desc = description && description.length ? description : `Batch Grants: ${items.length} transfer(s)`;
|
|
3831
|
+
return { targets, values, calldatas, description: desc };
|
|
3832
|
+
}
|
|
3833
|
+
};
|
|
3834
|
+
}
|
|
3835
|
+
});
|
|
3836
|
+
|
|
3667
3837
|
// src/timelock/index.js
|
|
3668
3838
|
var require_timelock = __commonJS({
|
|
3669
3839
|
"src/timelock/index.js"(exports2, module2) {
|
|
@@ -3726,8 +3896,8 @@ var require_timelock = __commonJS({
|
|
|
3726
3896
|
for (const log of logs) {
|
|
3727
3897
|
try {
|
|
3728
3898
|
const parsed = iface.parseLog(log);
|
|
3729
|
-
const
|
|
3730
|
-
const op = operations.get(
|
|
3899
|
+
const id2 = parsed.args.id;
|
|
3900
|
+
const op = operations.get(id2) || { id: id2, scheduled: [], executed: [], cancelled: false };
|
|
3731
3901
|
if (parsed.name === "CallScheduled") {
|
|
3732
3902
|
op.scheduled.push({
|
|
3733
3903
|
index: Number(parsed.args.index),
|
|
@@ -3749,7 +3919,7 @@ var require_timelock = __commonJS({
|
|
|
3749
3919
|
} else if (parsed.name === "Cancelled") {
|
|
3750
3920
|
op.cancelled = true;
|
|
3751
3921
|
}
|
|
3752
|
-
operations.set(
|
|
3922
|
+
operations.set(id2, op);
|
|
3753
3923
|
} catch (err) {
|
|
3754
3924
|
continue;
|
|
3755
3925
|
}
|
|
@@ -3772,10 +3942,10 @@ var require_timelock = __commonJS({
|
|
|
3772
3942
|
]);
|
|
3773
3943
|
return { to, data: payload, value: 0n };
|
|
3774
3944
|
},
|
|
3775
|
-
buildCancelTx: ({ timelock, id }) => {
|
|
3776
|
-
if (!
|
|
3945
|
+
buildCancelTx: ({ timelock, id: id2 }) => {
|
|
3946
|
+
if (!id2) throw new SageSDKError(CODES.INVALID_ARGS, "operation id required");
|
|
3777
3947
|
const addr = normalise(timelock, "timelock");
|
|
3778
|
-
const payload = TimelockInterface.encodeFunctionData("cancel", [
|
|
3948
|
+
const payload = TimelockInterface.encodeFunctionData("cancel", [id2]);
|
|
3779
3949
|
return { to: addr, data: payload, value: 0n };
|
|
3780
3950
|
},
|
|
3781
3951
|
buildExecuteTx: ({ timelock, target, value = 0n, data = "0x", predecessor = "0x0000000000000000000000000000000000000000000000000000000000000000", salt = "0x0000000000000000000000000000000000000000000000000000000000000000" }) => {
|
|
@@ -3884,10 +4054,10 @@ var require_factory = __commonJS({
|
|
|
3884
4054
|
const moduleContract = new Contract(templateAddr, ABI.TemplateModule, provider);
|
|
3885
4055
|
const ids = await moduleContract.getActiveTemplates().catch(() => []);
|
|
3886
4056
|
const templates = [];
|
|
3887
|
-
for (const
|
|
3888
|
-
const template = await moduleContract.getTemplateStruct(
|
|
4057
|
+
for (const id2 of ids) {
|
|
4058
|
+
const template = await moduleContract.getTemplateStruct(id2);
|
|
3889
4059
|
templates.push({
|
|
3890
|
-
id: Number(
|
|
4060
|
+
id: Number(id2),
|
|
3891
4061
|
name: template[0],
|
|
3892
4062
|
description: template[1],
|
|
3893
4063
|
accessModel: Number(template[2]),
|
|
@@ -4342,8 +4512,8 @@ var require_prompt = __commonJS({
|
|
|
4342
4512
|
for (let i = 1; i <= upto; i++) ids.push(i);
|
|
4343
4513
|
}
|
|
4344
4514
|
const results = [];
|
|
4345
|
-
for (const
|
|
4346
|
-
const key = await contract.getPromptKey(
|
|
4515
|
+
for (const id2 of ids) {
|
|
4516
|
+
const key = await contract.getPromptKey(id2).catch(() => null);
|
|
4347
4517
|
if (!key) continue;
|
|
4348
4518
|
results.push(await getPromptData({ provider, registry: addr, key }));
|
|
4349
4519
|
}
|
|
@@ -4355,8 +4525,8 @@ var require_prompt = __commonJS({
|
|
|
4355
4525
|
const contract = new Contract(addr, ABI.PromptRegistry, provider);
|
|
4356
4526
|
const ids = await contract.getByTagPage(tagHash, BigInt(offset), BigInt(Math.min(Number(limit), 100)));
|
|
4357
4527
|
const out = [];
|
|
4358
|
-
for (const
|
|
4359
|
-
const key = await contract.getPromptKey(
|
|
4528
|
+
for (const id2 of ids) {
|
|
4529
|
+
const key = await contract.getPromptKey(id2).catch(() => null);
|
|
4360
4530
|
if (!key) continue;
|
|
4361
4531
|
out.push(await getPromptData({ provider, registry: addr, key }));
|
|
4362
4532
|
}
|
|
@@ -4368,8 +4538,8 @@ var require_prompt = __commonJS({
|
|
|
4368
4538
|
const contract = new Contract(addr, ABI.PromptRegistry, provider);
|
|
4369
4539
|
const ids = await contract.getByCreatorPage(getAddress(creator), BigInt(offset), BigInt(Math.min(Number(limit), 100)));
|
|
4370
4540
|
const out = [];
|
|
4371
|
-
for (const
|
|
4372
|
-
const key = await contract.getPromptKey(
|
|
4541
|
+
for (const id2 of ids) {
|
|
4542
|
+
const key = await contract.getPromptKey(id2).catch(() => null);
|
|
4373
4543
|
if (!key) continue;
|
|
4374
4544
|
out.push(await getPromptData({ provider, registry: addr, key }));
|
|
4375
4545
|
}
|
|
@@ -4381,8 +4551,8 @@ var require_prompt = __commonJS({
|
|
|
4381
4551
|
const contract = new Contract(addr, ABI.PromptRegistry, provider);
|
|
4382
4552
|
const ids = await contract.getByCategoryPage(Number(category), BigInt(offset), BigInt(Math.min(Number(limit), 100)));
|
|
4383
4553
|
const out = [];
|
|
4384
|
-
for (const
|
|
4385
|
-
const key = await contract.getPromptKey(
|
|
4554
|
+
for (const id2 of ids) {
|
|
4555
|
+
const key = await contract.getPromptKey(id2).catch(() => null);
|
|
4386
4556
|
if (!key) continue;
|
|
4387
4557
|
out.push(await getPromptData({ provider, registry: addr, key }));
|
|
4388
4558
|
}
|
|
@@ -4472,9 +4642,9 @@ var require_ipns = __commonJS({
|
|
|
4472
4642
|
function removeTrailingSlash(str) {
|
|
4473
4643
|
return str ? str.replace(/\/$/, "") : str;
|
|
4474
4644
|
}
|
|
4475
|
-
function ensureLeadingSlash(
|
|
4476
|
-
if (!
|
|
4477
|
-
return
|
|
4645
|
+
function ensureLeadingSlash(path2) {
|
|
4646
|
+
if (!path2) return "/";
|
|
4647
|
+
return path2.startsWith("/") ? path2 : `/${path2}`;
|
|
4478
4648
|
}
|
|
4479
4649
|
function dedupe(list = []) {
|
|
4480
4650
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -4569,10 +4739,10 @@ var require_ipns = __commonJS({
|
|
|
4569
4739
|
}
|
|
4570
4740
|
return null;
|
|
4571
4741
|
}
|
|
4572
|
-
async function fetchWithGateways(
|
|
4742
|
+
async function fetchWithGateways(path2, axiosInstance, gateways, { timeout, attempts = 3, baseDelay = 500, jitterMs = 250 } = {}) {
|
|
4573
4743
|
const errors = [];
|
|
4574
4744
|
const unique = dedupe(gateways);
|
|
4575
|
-
const suffix =
|
|
4745
|
+
const suffix = path2.replace(/^\/+/, "");
|
|
4576
4746
|
for (let attempt = 0; attempt < attempts; attempt += 1) {
|
|
4577
4747
|
const delayMs = attempt === 0 ? 0 : jitter(baseDelay * attempt, jitterMs);
|
|
4578
4748
|
if (delayMs) await delay(delayMs);
|
|
@@ -4594,7 +4764,7 @@ var require_ipns = __commonJS({
|
|
|
4594
4764
|
}
|
|
4595
4765
|
}
|
|
4596
4766
|
}
|
|
4597
|
-
const failure = new Error(`Failed to fetch ${
|
|
4767
|
+
const failure = new Error(`Failed to fetch ${path2} from gateways`);
|
|
4598
4768
|
failure.attempts = errors;
|
|
4599
4769
|
throw failure;
|
|
4600
4770
|
}
|
|
@@ -5021,7 +5191,7 @@ var require_token = __commonJS({
|
|
|
5021
5191
|
// src/personal/helpers.js
|
|
5022
5192
|
var require_helpers = __commonJS({
|
|
5023
5193
|
"src/personal/helpers.js"(exports2, module2) {
|
|
5024
|
-
var { getAddress, ZeroAddress, id } = require("ethers");
|
|
5194
|
+
var { getAddress, ZeroAddress, id: id2 } = require("ethers");
|
|
5025
5195
|
function normaliseAddress(addr, label) {
|
|
5026
5196
|
if (!addr) throw new Error(`[personal] missing ${label}`);
|
|
5027
5197
|
const value = addr.toString();
|
|
@@ -5032,7 +5202,7 @@ var require_helpers = __commonJS({
|
|
|
5032
5202
|
if (typeof key === "string" && key.startsWith("0x") && key.length === 66) {
|
|
5033
5203
|
return key;
|
|
5034
5204
|
}
|
|
5035
|
-
return
|
|
5205
|
+
return id2(key);
|
|
5036
5206
|
}
|
|
5037
5207
|
module2.exports = {
|
|
5038
5208
|
normaliseAddress,
|
|
@@ -5061,8 +5231,8 @@ var require_receipt = __commonJS({
|
|
|
5061
5231
|
const receiptAddress = normaliseAddress(receipt, "receipt");
|
|
5062
5232
|
const holderAddress = normaliseAddress(holder, "holder");
|
|
5063
5233
|
const contract = new Contract(receiptAddress, ABI.PersonalLicenseReceipt, provider);
|
|
5064
|
-
const
|
|
5065
|
-
const balance = await contract.balanceOf(holderAddress,
|
|
5234
|
+
const id2 = typeof receiptId === "bigint" ? receiptId : BigInt(receiptId);
|
|
5235
|
+
const balance = await contract.balanceOf(holderAddress, id2);
|
|
5066
5236
|
return typeof balance === "bigint" ? balance : BigInt(balance.toString());
|
|
5067
5237
|
}
|
|
5068
5238
|
module2.exports = {
|
|
@@ -5441,12 +5611,12 @@ var require_treasury = __commonJS({
|
|
|
5441
5611
|
idList = Array.from({ length: total - start }, (_, i) => start + i);
|
|
5442
5612
|
}
|
|
5443
5613
|
const withdrawals = [];
|
|
5444
|
-
for (const
|
|
5445
|
-
const entry = await contract.pendingWithdrawals(
|
|
5614
|
+
for (const id2 of idList) {
|
|
5615
|
+
const entry = await contract.pendingWithdrawals(id2).catch(() => null);
|
|
5446
5616
|
if (!entry || !entry.exists) continue;
|
|
5447
5617
|
const [token, recipient, amount, value, requester, balanceBefore, recipientBalanceBefore, depositSnapshot, isLP, isEmergency] = entry;
|
|
5448
5618
|
withdrawals.push({
|
|
5449
|
-
id: Number(
|
|
5619
|
+
id: Number(id2),
|
|
5450
5620
|
token: token && token !== ZERO_ADDRESS ? getAddress(token) : null,
|
|
5451
5621
|
recipient: recipient && recipient !== ZERO_ADDRESS ? getAddress(recipient) : null,
|
|
5452
5622
|
amount: toBigInt(amount),
|
|
@@ -5621,17 +5791,17 @@ var require_treasury = __commonJS({
|
|
|
5621
5791
|
id: parsed?.id != null ? Number(parsed.id) : null
|
|
5622
5792
|
};
|
|
5623
5793
|
}
|
|
5624
|
-
async function confirmWithdrawal({ signer, treasury, id, waitMs }) {
|
|
5794
|
+
async function confirmWithdrawal({ signer, treasury, id: id2, waitMs }) {
|
|
5625
5795
|
const contract = createWriteContract({ signer, treasury });
|
|
5626
|
-
const tx = await contract.confirmWithdrawal(Number(
|
|
5796
|
+
const tx = await contract.confirmWithdrawal(Number(id2));
|
|
5627
5797
|
const receipt = await waitForReceipt({ signer, tx, waitMs });
|
|
5628
|
-
return { transaction: tx, receipt, id: Number(
|
|
5798
|
+
return { transaction: tx, receipt, id: Number(id2) };
|
|
5629
5799
|
}
|
|
5630
|
-
async function cancelWithdrawal({ signer, treasury, id, waitMs }) {
|
|
5800
|
+
async function cancelWithdrawal({ signer, treasury, id: id2, waitMs }) {
|
|
5631
5801
|
const contract = createWriteContract({ signer, treasury });
|
|
5632
|
-
const tx = await contract.cancelWithdrawal(Number(
|
|
5802
|
+
const tx = await contract.cancelWithdrawal(Number(id2));
|
|
5633
5803
|
const receipt = await waitForReceipt({ signer, tx, waitMs });
|
|
5634
|
-
return { transaction: tx, receipt, id: Number(
|
|
5804
|
+
return { transaction: tx, receipt, id: Number(id2) };
|
|
5635
5805
|
}
|
|
5636
5806
|
async function setPriceOverride({ signer, treasury, token, price, ttlSeconds, waitMs }) {
|
|
5637
5807
|
const contract = createWriteContract({ signer, treasury });
|
|
@@ -5685,7 +5855,23 @@ var require_treasury = __commonJS({
|
|
|
5685
5855
|
confirmWithdrawal,
|
|
5686
5856
|
cancelWithdrawal,
|
|
5687
5857
|
setPriceOverride,
|
|
5688
|
-
clearPriceOverride
|
|
5858
|
+
clearPriceOverride,
|
|
5859
|
+
// TX builders for app usage
|
|
5860
|
+
buildApproveTx: ({ token, spender, amount, decimals = 18 }) => {
|
|
5861
|
+
if (!token || !spender) throw new SageSDKError(CODES.INVALID_ARGS, "token and spender required");
|
|
5862
|
+
const iface = new Interface(["function approve(address,uint256)"]);
|
|
5863
|
+
return { to: getAddress(token), data: iface.encodeFunctionData("approve", [getAddress(spender), BigInt(amount.toString ? amount.toString() : amount)]), value: 0n };
|
|
5864
|
+
},
|
|
5865
|
+
buildTransferTx: ({ token, to, amount, decimals = 18 }) => {
|
|
5866
|
+
if (!token || !to) throw new SageSDKError(CODES.INVALID_ARGS, "token and to required");
|
|
5867
|
+
const iface = new Interface(["function transfer(address,uint256)"]);
|
|
5868
|
+
return { to: getAddress(token), data: iface.encodeFunctionData("transfer", [getAddress(to), BigInt(amount.toString ? amount.toString() : amount)]), value: 0n };
|
|
5869
|
+
},
|
|
5870
|
+
buildWrapEthTx: ({ weth, amountWei }) => {
|
|
5871
|
+
if (!weth) throw new SageSDKError(CODES.INVALID_ARGS, "weth required");
|
|
5872
|
+
const iface = new Interface(["function deposit() payable"]);
|
|
5873
|
+
return { to: getAddress(weth), data: iface.encodeFunctionData("deposit", []), value: BigInt(amountWei.toString ? amountWei.toString() : amountWei) };
|
|
5874
|
+
}
|
|
5689
5875
|
};
|
|
5690
5876
|
}
|
|
5691
5877
|
});
|
|
@@ -5897,8 +6083,8 @@ var require_bounty = __commonJS({
|
|
|
5897
6083
|
["function approveBountyCompletion(uint256,string)"],
|
|
5898
6084
|
signer
|
|
5899
6085
|
);
|
|
5900
|
-
const
|
|
5901
|
-
const tx = await bountyContract.approveBountyCompletion(
|
|
6086
|
+
const id2 = BigInt(bountyId);
|
|
6087
|
+
const tx = await bountyContract.approveBountyCompletion(id2, String(deliverable));
|
|
5902
6088
|
return tx.wait();
|
|
5903
6089
|
}
|
|
5904
6090
|
async function proposeApproveWinner({
|
|
@@ -5916,14 +6102,14 @@ var require_bounty = __commonJS({
|
|
|
5916
6102
|
const context = await subdao.getSubDAOInfo({ provider, subdao: subdaoAddress });
|
|
5917
6103
|
const governor = normaliseAddress("governor", context.governor);
|
|
5918
6104
|
const iface = new Interface(["function approveBountyCompletion(uint256,string)"]);
|
|
5919
|
-
const
|
|
5920
|
-
const data = iface.encodeFunctionData("approveBountyCompletion", [
|
|
6105
|
+
const id2 = BigInt(bountyId);
|
|
6106
|
+
const data = iface.encodeFunctionData("approveBountyCompletion", [id2, String(deliverable)]);
|
|
5921
6107
|
const proposalCall = governance.buildProposeTx({
|
|
5922
6108
|
governor,
|
|
5923
6109
|
targets: [bountySystemAddress],
|
|
5924
6110
|
values: [0n],
|
|
5925
6111
|
calldatas: [data],
|
|
5926
|
-
description: `Approve bounty completion for id=${
|
|
6112
|
+
description: `Approve bounty completion for id=${id2}`
|
|
5927
6113
|
});
|
|
5928
6114
|
return { governor, proposalCall };
|
|
5929
6115
|
}
|
|
@@ -5936,248 +6122,6 @@ var require_bounty = __commonJS({
|
|
|
5936
6122
|
}
|
|
5937
6123
|
});
|
|
5938
6124
|
|
|
5939
|
-
// src/bond/index.js
|
|
5940
|
-
var require_bond = __commonJS({
|
|
5941
|
-
"src/bond/index.js"(exports2, module2) {
|
|
5942
|
-
var {
|
|
5943
|
-
Contract,
|
|
5944
|
-
Interface,
|
|
5945
|
-
MaxUint256,
|
|
5946
|
-
WeiPerEther,
|
|
5947
|
-
formatUnits,
|
|
5948
|
-
getAddress,
|
|
5949
|
-
parseUnits
|
|
5950
|
-
} = require("ethers");
|
|
5951
|
-
var ABI = require_abi();
|
|
5952
|
-
var { SageSDKError, CODES } = require_errors();
|
|
5953
|
-
function normalise(address, label) {
|
|
5954
|
-
if (!address) throw new SageSDKError(CODES.INVALID_ARGS, `${label} required`);
|
|
5955
|
-
try {
|
|
5956
|
-
return getAddress(address);
|
|
5957
|
-
} catch (err) {
|
|
5958
|
-
throw new SageSDKError(CODES.INVALID_ARGS, `invalid ${label}`, { cause: err });
|
|
5959
|
-
}
|
|
5960
|
-
}
|
|
5961
|
-
var ERC20 = [
|
|
5962
|
-
"function decimals() view returns (uint8)",
|
|
5963
|
-
"function allowance(address owner, address spender) view returns (uint256)",
|
|
5964
|
-
"function approve(address spender, uint256 value) returns (bool)",
|
|
5965
|
-
"function balanceOf(address) view returns (uint256)"
|
|
5966
|
-
];
|
|
5967
|
-
var BondInterface = new Interface(ABI.BondDepository);
|
|
5968
|
-
async function getInfo({ provider, bond }) {
|
|
5969
|
-
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
|
|
5970
|
-
const addr = normalise(bond, "bond");
|
|
5971
|
-
const c = new Contract(addr, ABI.BondDepository, provider);
|
|
5972
|
-
const [terms, price, priceUsd, totalDebt, payoutToken, principalToken, treasury] = await Promise.all([
|
|
5973
|
-
c.terms(),
|
|
5974
|
-
c.bondPrice(),
|
|
5975
|
-
c.bondPriceInUSD().catch(() => 0n),
|
|
5976
|
-
// totalDebt is keyed by payout token in this implementation
|
|
5977
|
-
c.payoutToken().then((pt) => c.totalDebt(pt)).catch(() => 0n),
|
|
5978
|
-
c.payoutToken(),
|
|
5979
|
-
c.principalToken(),
|
|
5980
|
-
c.treasury()
|
|
5981
|
-
]);
|
|
5982
|
-
return {
|
|
5983
|
-
bond: addr,
|
|
5984
|
-
payoutToken,
|
|
5985
|
-
principalToken,
|
|
5986
|
-
treasury,
|
|
5987
|
-
terms: {
|
|
5988
|
-
controlVariable: BigInt(terms.controlVariable?.toString?.() || terms[0]?.toString?.() || "0"),
|
|
5989
|
-
minimumPrice: BigInt(terms.minimumPrice?.toString?.() || terms[1]?.toString?.() || "0"),
|
|
5990
|
-
maxPayoutBps: BigInt(terms.maxPayout?.toString?.() || terms[2]?.toString?.() || "0"),
|
|
5991
|
-
maxDebt: BigInt(terms.maxDebt?.toString?.() || terms[3]?.toString?.() || "0"),
|
|
5992
|
-
vestingTerm: BigInt(terms.vestingTerm?.toString?.() || terms[4]?.toString?.() || "0"),
|
|
5993
|
-
feeBps: BigInt(terms.fee?.toString?.() || terms[5]?.toString?.() || "0")
|
|
5994
|
-
},
|
|
5995
|
-
price: BigInt(price.toString()),
|
|
5996
|
-
priceUSD: BigInt(priceUsd.toString()),
|
|
5997
|
-
totalDebt: BigInt(totalDebt.toString())
|
|
5998
|
-
};
|
|
5999
|
-
}
|
|
6000
|
-
async function getPrice({ provider, bond }) {
|
|
6001
|
-
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
|
|
6002
|
-
const c = new Contract(normalise(bond, "bond"), ABI.BondDepository, provider);
|
|
6003
|
-
return c.bondPrice();
|
|
6004
|
-
}
|
|
6005
|
-
async function getUserStatus({ provider, bond, user }) {
|
|
6006
|
-
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
|
|
6007
|
-
const addr = normalise(bond, "bond");
|
|
6008
|
-
const who = normalise(user, "user");
|
|
6009
|
-
const c = new Contract(addr, ABI.BondDepository, provider);
|
|
6010
|
-
const [info, pending, vested] = await Promise.all([
|
|
6011
|
-
c.bondInfo(who),
|
|
6012
|
-
c.pendingPayout(who),
|
|
6013
|
-
c.percentVestedFor(who).catch(() => 0n)
|
|
6014
|
-
]);
|
|
6015
|
-
return {
|
|
6016
|
-
address: who,
|
|
6017
|
-
bond: addr,
|
|
6018
|
-
payoutRemaining: BigInt(info?.payout?.toString?.() || info[0]?.toString?.() || "0"),
|
|
6019
|
-
vestingBlocks: BigInt(info?.vesting?.toString?.() || info[1]?.toString?.() || "0"),
|
|
6020
|
-
lastInteractionBlock: BigInt(info?.lastBlock?.toString?.() || info[2]?.toString?.() || "0"),
|
|
6021
|
-
pricePaid: BigInt(info?.pricePaid?.toString?.() || info[3]?.toString?.() || "0"),
|
|
6022
|
-
pendingPayout: BigInt(pending.toString()),
|
|
6023
|
-
percentVestedBps: BigInt(vested.toString())
|
|
6024
|
-
};
|
|
6025
|
-
}
|
|
6026
|
-
function buildDepositTx({ bond, amount, maxPrice }) {
|
|
6027
|
-
const to = normalise(bond, "bond");
|
|
6028
|
-
const iface = new Interface(ABI.BondDepository);
|
|
6029
|
-
const data = iface.encodeFunctionData("deposit", [
|
|
6030
|
-
BigInt(amount ?? 0n),
|
|
6031
|
-
// principal amount in token units
|
|
6032
|
-
BigInt(maxPrice ?? 0n)
|
|
6033
|
-
// scaled by 1e18
|
|
6034
|
-
]);
|
|
6035
|
-
return { to, data, value: 0n };
|
|
6036
|
-
}
|
|
6037
|
-
function buildRedeemTx({ bond, recipient, stake = false }) {
|
|
6038
|
-
const to = normalise(bond, "bond");
|
|
6039
|
-
const iface = new Interface(ABI.BondDepository);
|
|
6040
|
-
const data = iface.encodeFunctionData("redeem", [normalise(recipient, "recipient"), !!stake]);
|
|
6041
|
-
return { to, data, value: 0n };
|
|
6042
|
-
}
|
|
6043
|
-
async function getTokenDecimals({ provider, token }) {
|
|
6044
|
-
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
|
|
6045
|
-
const c = new Contract(normalise(token, "token"), ERC20, provider);
|
|
6046
|
-
const d = await c.decimals().catch(() => 18);
|
|
6047
|
-
return Number(d);
|
|
6048
|
-
}
|
|
6049
|
-
async function getPrincipalAndPayout({ provider, bond }) {
|
|
6050
|
-
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
|
|
6051
|
-
const c = new Contract(normalise(bond, "bond"), ABI.BondDepository, provider);
|
|
6052
|
-
const [payoutToken, principalToken] = await Promise.all([
|
|
6053
|
-
c.payoutToken(),
|
|
6054
|
-
c.principalToken()
|
|
6055
|
-
]);
|
|
6056
|
-
return { payoutToken, principalToken };
|
|
6057
|
-
}
|
|
6058
|
-
async function estimatePayout({ provider, bond, amount, principalDecimals, payoutDecimals }) {
|
|
6059
|
-
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
|
|
6060
|
-
if (amount == null) throw new SageSDKError(CODES.INVALID_ARGS, "amount required");
|
|
6061
|
-
const { principalToken, payoutToken } = await getPrincipalAndPayout({ provider, bond });
|
|
6062
|
-
const principalDec = principalDecimals ?? await getTokenDecimals({ provider, token: principalToken });
|
|
6063
|
-
const payoutDec = payoutDecimals ?? await getTokenDecimals({ provider, token: payoutToken });
|
|
6064
|
-
const amountUnits = parseUnits(String(amount), principalDec);
|
|
6065
|
-
const price = await getPrice({ provider, bond });
|
|
6066
|
-
if (price === 0n) {
|
|
6067
|
-
throw new SageSDKError(CODES.RPC_ERROR, "bond price returned zero");
|
|
6068
|
-
}
|
|
6069
|
-
const payoutUnits = amountUnits * WeiPerEther / price;
|
|
6070
|
-
return {
|
|
6071
|
-
inputAmount: String(amount),
|
|
6072
|
-
expectedPayout: formatUnits(payoutUnits, payoutDec),
|
|
6073
|
-
bondPrice: formatUnits(price, 18),
|
|
6074
|
-
principalToken,
|
|
6075
|
-
payoutToken,
|
|
6076
|
-
principalDecimals: principalDec,
|
|
6077
|
-
payoutDecimals: payoutDec
|
|
6078
|
-
};
|
|
6079
|
-
}
|
|
6080
|
-
async function ensurePrincipalAllowance({ signer, bond, amount, principalToken }) {
|
|
6081
|
-
if (!signer) throw new SageSDKError(CODES.INVALID_ARGS, "signer required");
|
|
6082
|
-
const owner = await signer.getAddress();
|
|
6083
|
-
const provider = signer.provider;
|
|
6084
|
-
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "signer requires provider");
|
|
6085
|
-
const bondAddress = normalise(bond, "bond");
|
|
6086
|
-
const tokenAddress = principalToken ? normalise(principalToken, "principalToken") : (await getPrincipalAndPayout({ provider, bond: bondAddress })).principalToken;
|
|
6087
|
-
const principal = new Contract(tokenAddress, ERC20, signer);
|
|
6088
|
-
const allowance = await principal.allowance(owner, bondAddress);
|
|
6089
|
-
if (allowance >= amount) {
|
|
6090
|
-
return { approved: false, transactionHash: null };
|
|
6091
|
-
}
|
|
6092
|
-
const approvalTx = await principal.approve(bondAddress, MaxUint256);
|
|
6093
|
-
const receipt = await approvalTx.wait();
|
|
6094
|
-
return {
|
|
6095
|
-
approved: true,
|
|
6096
|
-
transactionHash: receipt.hash ?? approvalTx.hash ?? null
|
|
6097
|
-
};
|
|
6098
|
-
}
|
|
6099
|
-
async function purchase({ signer, bond, amount, maxPrice }) {
|
|
6100
|
-
if (!signer) throw new SageSDKError(CODES.INVALID_ARGS, "signer required");
|
|
6101
|
-
if (amount == null) throw new SageSDKError(CODES.INVALID_ARGS, "amount required");
|
|
6102
|
-
if (maxPrice == null) throw new SageSDKError(CODES.INVALID_ARGS, "maxPrice required");
|
|
6103
|
-
const provider = signer.provider;
|
|
6104
|
-
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "signer requires provider");
|
|
6105
|
-
const bondAddress = normalise(bond, "bond");
|
|
6106
|
-
const bondContract = new Contract(bondAddress, ABI.BondDepository, signer);
|
|
6107
|
-
const { principalToken, payoutToken } = await getPrincipalAndPayout({ provider, bond: bondAddress });
|
|
6108
|
-
const principalDec = await getTokenDecimals({ provider, token: principalToken });
|
|
6109
|
-
const payoutDec = await getTokenDecimals({ provider, token: payoutToken });
|
|
6110
|
-
const amountUnits = parseUnits(String(amount), principalDec);
|
|
6111
|
-
const maxPriceUnits = parseUnits(String(maxPrice), 18);
|
|
6112
|
-
const currentPrice = await getPrice({ provider, bond: bondAddress });
|
|
6113
|
-
if (currentPrice > maxPriceUnits) {
|
|
6114
|
-
throw new SageSDKError(CODES.INVALID_ARGS, "current bond price exceeds max price", {
|
|
6115
|
-
currentPrice: formatUnits(currentPrice, 18),
|
|
6116
|
-
maxPrice: String(maxPrice)
|
|
6117
|
-
});
|
|
6118
|
-
}
|
|
6119
|
-
await ensurePrincipalAllowance({ signer, bond: bondAddress, amount: amountUnits, principalToken });
|
|
6120
|
-
const tx = await bondContract.deposit(amountUnits, maxPriceUnits);
|
|
6121
|
-
const receipt = await tx.wait();
|
|
6122
|
-
let depositEvent = null;
|
|
6123
|
-
for (const log of receipt.logs || []) {
|
|
6124
|
-
try {
|
|
6125
|
-
const parsed = BondInterface.parseLog(log);
|
|
6126
|
-
if (parsed?.name === "BondCreated") {
|
|
6127
|
-
depositEvent = parsed.args;
|
|
6128
|
-
break;
|
|
6129
|
-
}
|
|
6130
|
-
} catch (_) {
|
|
6131
|
-
}
|
|
6132
|
-
}
|
|
6133
|
-
return {
|
|
6134
|
-
transactionHash: receipt.hash ?? tx.hash ?? null,
|
|
6135
|
-
deposit: formatUnits(depositEvent?.deposit ?? amountUnits, principalDec),
|
|
6136
|
-
payout: depositEvent?.payout != null ? formatUnits(depositEvent.payout, payoutDec) : null,
|
|
6137
|
-
expires: depositEvent?.expires ?? null,
|
|
6138
|
-
price: formatUnits(currentPrice, 18)
|
|
6139
|
-
};
|
|
6140
|
-
}
|
|
6141
|
-
async function redeem({ signer, bond, recipient, stake = false }) {
|
|
6142
|
-
if (!signer) throw new SageSDKError(CODES.INVALID_ARGS, "signer required");
|
|
6143
|
-
const provider = signer.provider;
|
|
6144
|
-
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "signer requires provider");
|
|
6145
|
-
const bondAddress = normalise(bond, "bond");
|
|
6146
|
-
const user = normalise(recipient || await signer.getAddress(), "recipient");
|
|
6147
|
-
const bondContract = new Contract(bondAddress, ABI.BondDepository, signer);
|
|
6148
|
-
const { payoutToken } = await getPrincipalAndPayout({ provider, bond: bondAddress });
|
|
6149
|
-
const payoutDec = await getTokenDecimals({ provider, token: payoutToken });
|
|
6150
|
-
const pending = await bondContract.pendingPayout(user);
|
|
6151
|
-
if (pending === 0n) {
|
|
6152
|
-
return {
|
|
6153
|
-
transactionHash: null,
|
|
6154
|
-
redeemed: "0",
|
|
6155
|
-
message: "No bonds available for redemption"
|
|
6156
|
-
};
|
|
6157
|
-
}
|
|
6158
|
-
const tx = await bondContract.redeem(user, !!stake);
|
|
6159
|
-
const receipt = await tx.wait();
|
|
6160
|
-
return {
|
|
6161
|
-
transactionHash: receipt.hash ?? tx.hash ?? null,
|
|
6162
|
-
redeemed: formatUnits(pending, payoutDec)
|
|
6163
|
-
};
|
|
6164
|
-
}
|
|
6165
|
-
module2.exports = {
|
|
6166
|
-
getInfo,
|
|
6167
|
-
getPrice,
|
|
6168
|
-
getUserStatus,
|
|
6169
|
-
buildDepositTx,
|
|
6170
|
-
buildRedeemTx,
|
|
6171
|
-
getTokenDecimals,
|
|
6172
|
-
getPrincipalAndPayout,
|
|
6173
|
-
estimatePayout,
|
|
6174
|
-
ensurePrincipalAllowance,
|
|
6175
|
-
purchase,
|
|
6176
|
-
redeem
|
|
6177
|
-
};
|
|
6178
|
-
}
|
|
6179
|
-
});
|
|
6180
|
-
|
|
6181
6125
|
// src/utils/provider.js
|
|
6182
6126
|
var require_provider = __commonJS({
|
|
6183
6127
|
"src/utils/provider.js"(exports2, module2) {
|
|
@@ -6201,7 +6145,7 @@ var require_provider = __commonJS({
|
|
|
6201
6145
|
// src/wallet/index.js
|
|
6202
6146
|
var require_wallet = __commonJS({
|
|
6203
6147
|
"src/wallet/index.js"(exports2, module2) {
|
|
6204
|
-
var { ethers } = require("ethers");
|
|
6148
|
+
var { ethers: ethers2 } = require("ethers");
|
|
6205
6149
|
var { SageSDKError, CODES } = require_errors();
|
|
6206
6150
|
var { getProvider } = require_provider();
|
|
6207
6151
|
function isBrowser() {
|
|
@@ -6228,7 +6172,7 @@ var require_wallet = __commonJS({
|
|
|
6228
6172
|
const rpcUrl = src.rpcUrl || getDefaultRpc();
|
|
6229
6173
|
const provider = getProvider({ rpcUrl });
|
|
6230
6174
|
const pk = src.privateKey.startsWith("0x") ? src.privateKey : "0x" + src.privateKey;
|
|
6231
|
-
const signer = new
|
|
6175
|
+
const signer = new ethers2.Wallet(pk, provider);
|
|
6232
6176
|
return { signer, provider };
|
|
6233
6177
|
}
|
|
6234
6178
|
case "pkEnv": {
|
|
@@ -6237,7 +6181,7 @@ var require_wallet = __commonJS({
|
|
|
6237
6181
|
if (!pk) throw new SageSDKError(CODES.INVALID_ARGS, `${envName} not set`);
|
|
6238
6182
|
const rpcUrl = src.rpcUrl || getDefaultRpc();
|
|
6239
6183
|
const provider = getProvider({ rpcUrl });
|
|
6240
|
-
const signer = new
|
|
6184
|
+
const signer = new ethers2.Wallet(pk.startsWith("0x") ? pk : "0x" + pk, provider);
|
|
6241
6185
|
return { signer, provider };
|
|
6242
6186
|
}
|
|
6243
6187
|
case "rpc": {
|
|
@@ -6248,7 +6192,7 @@ var require_wallet = __commonJS({
|
|
|
6248
6192
|
case "injected": {
|
|
6249
6193
|
if (!isBrowser()) throw new SageSDKError(CODES.MISSING_DEPENDENCY, "Injected provider only available in browser");
|
|
6250
6194
|
try {
|
|
6251
|
-
const provider = new
|
|
6195
|
+
const provider = new ethers2.BrowserProvider(window.ethereum);
|
|
6252
6196
|
const signer = await provider.getSigner();
|
|
6253
6197
|
return { signer, provider };
|
|
6254
6198
|
} catch (e) {
|
|
@@ -6276,7 +6220,7 @@ var require_wallet = __commonJS({
|
|
|
6276
6220
|
return process.env.RPC_URL || process.env.BASE_SEPOLIA_RPC_URL || process.env.BASE_SEPOLIA_RPC || "https://base-sepolia.publicnode.com";
|
|
6277
6221
|
}
|
|
6278
6222
|
function create() {
|
|
6279
|
-
const wallet =
|
|
6223
|
+
const wallet = ethers2.Wallet.createRandom();
|
|
6280
6224
|
return {
|
|
6281
6225
|
address: wallet.address,
|
|
6282
6226
|
// Intentionally do not expose privateKey by default to avoid accidental leaks
|
|
@@ -6289,7 +6233,7 @@ var require_wallet = __commonJS({
|
|
|
6289
6233
|
throw new SageSDKError(CODES.INVALID_ARGS, "secret required to import wallet");
|
|
6290
6234
|
}
|
|
6291
6235
|
const pk = secret.startsWith("0x") ? secret : "0x" + secret;
|
|
6292
|
-
const wallet = new
|
|
6236
|
+
const wallet = new ethers2.Wallet(pk);
|
|
6293
6237
|
return { address: wallet.address, _wallet: wallet };
|
|
6294
6238
|
}
|
|
6295
6239
|
function exportWallet(w) {
|
|
@@ -6324,7 +6268,7 @@ var require_wallet = __commonJS({
|
|
|
6324
6268
|
} catch (_) {
|
|
6325
6269
|
if (!opts || !opts.mnemonic || !opts.rpcUrl) throw new SageSDKError(CODES.INVALID_ARGS, "mnemonic and rpcUrl required");
|
|
6326
6270
|
const provider = getProvider({ rpcUrl: opts.rpcUrl });
|
|
6327
|
-
const wallet =
|
|
6271
|
+
const wallet = ethers2.HDNodeWallet.fromPhrase(opts.mnemonic, opts.path);
|
|
6328
6272
|
const signer = wallet.connect(provider);
|
|
6329
6273
|
return { signer, provider };
|
|
6330
6274
|
}
|
|
@@ -6336,7 +6280,7 @@ var require_wallet = __commonJS({
|
|
|
6336
6280
|
} catch (_) {
|
|
6337
6281
|
if (!opts || !opts.json || !opts.password || !opts.rpcUrl) throw new SageSDKError(CODES.INVALID_ARGS, "json, password, rpcUrl required");
|
|
6338
6282
|
const provider = getProvider({ rpcUrl: opts.rpcUrl });
|
|
6339
|
-
const signer = await
|
|
6283
|
+
const signer = await ethers2.Wallet.fromEncryptedJson(opts.json, opts.password);
|
|
6340
6284
|
return { signer: signer.connect(provider), provider };
|
|
6341
6285
|
}
|
|
6342
6286
|
},
|
|
@@ -6421,7 +6365,7 @@ var require_session = __commonJS({
|
|
|
6421
6365
|
|
|
6422
6366
|
// src/wallet/cast-manager.js
|
|
6423
6367
|
var require_cast_manager = __commonJS({
|
|
6424
|
-
"src/wallet/cast-manager.js"(
|
|
6368
|
+
"src/wallet/cast-manager.js"(exports, module) {
|
|
6425
6369
|
var { spawn } = require("child_process");
|
|
6426
6370
|
var { ethers } = require("ethers");
|
|
6427
6371
|
var fs = require("fs");
|
|
@@ -6438,6 +6382,32 @@ var require_cast_manager = __commonJS({
|
|
|
6438
6382
|
blue: (text) => `\x1B[34m${text}\x1B[0m`,
|
|
6439
6383
|
cyan: (text) => `\x1B[36m${text}\x1B[0m`
|
|
6440
6384
|
};
|
|
6385
|
+
function optionalRequire(id) {
|
|
6386
|
+
try {
|
|
6387
|
+
const req = typeof __non_webpack_require__ === "function" ? __non_webpack_require__ : eval("require");
|
|
6388
|
+
return req(id);
|
|
6389
|
+
} catch (_) {
|
|
6390
|
+
return null;
|
|
6391
|
+
}
|
|
6392
|
+
}
|
|
6393
|
+
function loadConfigBridge() {
|
|
6394
|
+
const shared = optionalRequire("@sage-protocol/shared");
|
|
6395
|
+
if (shared) {
|
|
6396
|
+
if (shared.ConfigManager) return shared.ConfigManager;
|
|
6397
|
+
if (typeof shared.getProjectDir === "function" || typeof shared.readProfiles === "function") {
|
|
6398
|
+
return shared;
|
|
6399
|
+
}
|
|
6400
|
+
}
|
|
6401
|
+
const local = optionalRequire("./config");
|
|
6402
|
+
if (local) {
|
|
6403
|
+
if (local.ConfigManager) return local.ConfigManager;
|
|
6404
|
+
return local;
|
|
6405
|
+
}
|
|
6406
|
+
return {
|
|
6407
|
+
getProjectDir: () => process.cwd(),
|
|
6408
|
+
readProfiles: () => ({ profiles: {}, activeProfile: "default" })
|
|
6409
|
+
};
|
|
6410
|
+
}
|
|
6441
6411
|
var CastSigner = class extends ethers.VoidSigner {
|
|
6442
6412
|
constructor(address, provider, castWalletManager) {
|
|
6443
6413
|
super(address, provider);
|
|
@@ -6572,13 +6542,8 @@ var require_cast_manager = __commonJS({
|
|
|
6572
6542
|
if (!address) return;
|
|
6573
6543
|
try {
|
|
6574
6544
|
const normalized = ethers.getAddress(address);
|
|
6575
|
-
|
|
6576
|
-
|
|
6577
|
-
({ ConfigManager: cfgModule } = require("@sage-protocol/shared"));
|
|
6578
|
-
} catch (_) {
|
|
6579
|
-
cfgModule = require("./config");
|
|
6580
|
-
}
|
|
6581
|
-
const projectDir = cfgModule.getProjectDir ? cfgModule.getProjectDir() : process.cwd();
|
|
6545
|
+
const cfgModule = loadConfigBridge();
|
|
6546
|
+
const projectDir = typeof cfgModule.getProjectDir === "function" ? cfgModule.getProjectDir() : process.cwd();
|
|
6582
6547
|
const cfgPath = path.join(projectDir, ".sage", "config.json");
|
|
6583
6548
|
const current = fs.existsSync(cfgPath) ? JSON.parse(fs.readFileSync(cfgPath, "utf8") || "{}") : {};
|
|
6584
6549
|
const active = current.activeProfile || "default";
|
|
@@ -6664,14 +6629,9 @@ var require_cast_manager = __commonJS({
|
|
|
6664
6629
|
console.log(colors.blue("\u{1F517} Connecting wallet using Cast keystore..."));
|
|
6665
6630
|
this.ensureKeystoreDir();
|
|
6666
6631
|
try {
|
|
6667
|
-
|
|
6668
|
-
|
|
6669
|
-
|
|
6670
|
-
} catch (_) {
|
|
6671
|
-
cliConfig = require("./config");
|
|
6672
|
-
}
|
|
6673
|
-
const profiles = cliConfig.readProfiles();
|
|
6674
|
-
const active = profiles.activeProfile || "default";
|
|
6632
|
+
const cliConfig = loadConfigBridge();
|
|
6633
|
+
const profiles = typeof cliConfig.readProfiles === "function" ? cliConfig.readProfiles() : { profiles: {}, activeProfile: "default" };
|
|
6634
|
+
const active = profiles?.activeProfile || "default";
|
|
6675
6635
|
const wanted = profiles?.profiles?.[active]?.wallet?.defaultAccount;
|
|
6676
6636
|
if (wanted && this.keystoreDir && fs.existsSync(this.keystoreDir)) {
|
|
6677
6637
|
const files = fs.readdirSync(this.keystoreDir);
|
|
@@ -6707,7 +6667,7 @@ var require_cast_manager = __commonJS({
|
|
|
6707
6667
|
this.ensureAccountSynced(walletData.address, walletData.keystorePath, { silent: true });
|
|
6708
6668
|
}
|
|
6709
6669
|
try {
|
|
6710
|
-
const { checkRpcHealth } =
|
|
6670
|
+
const { checkRpcHealth } = optionalRequire("./utils/rpc-health") || {};
|
|
6711
6671
|
const candidates = [
|
|
6712
6672
|
this.rpcUrl,
|
|
6713
6673
|
process.env.BASE_SEPOLIA_RPC,
|
|
@@ -7663,16 +7623,16 @@ ${error}` : ""}`;
|
|
|
7663
7623
|
return fullPath;
|
|
7664
7624
|
}
|
|
7665
7625
|
};
|
|
7666
|
-
|
|
7626
|
+
module.exports = CastWalletManager;
|
|
7667
7627
|
}
|
|
7668
7628
|
});
|
|
7669
7629
|
|
|
7670
7630
|
// src/wallet/cdp-manager.js
|
|
7671
7631
|
var require_cdp_manager = __commonJS({
|
|
7672
7632
|
"src/wallet/cdp-manager.js"(exports2, module2) {
|
|
7673
|
-
var
|
|
7674
|
-
var
|
|
7675
|
-
var { ethers } = require("ethers");
|
|
7633
|
+
var fs2 = require("fs");
|
|
7634
|
+
var path2 = require("path");
|
|
7635
|
+
var { ethers: ethers2 } = require("ethers");
|
|
7676
7636
|
var MinimalCdpSigner = class {
|
|
7677
7637
|
constructor(manager, provider) {
|
|
7678
7638
|
this._mgr = manager;
|
|
@@ -7701,7 +7661,7 @@ var require_cdp_manager = __commonJS({
|
|
|
7701
7661
|
this.provider = null;
|
|
7702
7662
|
this.signer = null;
|
|
7703
7663
|
this.connected = false;
|
|
7704
|
-
this._profilePath =
|
|
7664
|
+
this._profilePath = path2.join(process.cwd(), ".cdp-wallet.json");
|
|
7705
7665
|
this._client = null;
|
|
7706
7666
|
this._userId = null;
|
|
7707
7667
|
this._walletId = null;
|
|
@@ -7724,9 +7684,9 @@ var require_cdp_manager = __commonJS({
|
|
|
7724
7684
|
}
|
|
7725
7685
|
}
|
|
7726
7686
|
_loadProfile() {
|
|
7727
|
-
if (
|
|
7687
|
+
if (fs2.existsSync(this._profilePath)) {
|
|
7728
7688
|
try {
|
|
7729
|
-
const x = JSON.parse(
|
|
7689
|
+
const x = JSON.parse(fs2.readFileSync(this._profilePath, "utf8"));
|
|
7730
7690
|
this._userId = x.userId || null;
|
|
7731
7691
|
this._walletId = x.walletId || null;
|
|
7732
7692
|
this.account = x.address || null;
|
|
@@ -7736,14 +7696,14 @@ var require_cdp_manager = __commonJS({
|
|
|
7736
7696
|
}
|
|
7737
7697
|
_saveProfile() {
|
|
7738
7698
|
const payload = { userId: this._userId, walletId: this._walletId, address: this.account };
|
|
7739
|
-
|
|
7699
|
+
fs2.writeFileSync(this._profilePath, JSON.stringify(payload, null, 2));
|
|
7740
7700
|
}
|
|
7741
7701
|
async connect() {
|
|
7742
7702
|
if (!process.env.CDP_API_KEY_ID || !process.env.CDP_API_KEY_SECRET) {
|
|
7743
7703
|
throw new Error("Missing CDP_API_KEY_ID/CDP_API_KEY_SECRET in env");
|
|
7744
7704
|
}
|
|
7745
7705
|
const rpc = process.env.RPC_URL || "https://base-sepolia.publicnode.com";
|
|
7746
|
-
this.provider = new
|
|
7706
|
+
this.provider = new ethers2.JsonRpcProvider(rpc);
|
|
7747
7707
|
this._loadProfile();
|
|
7748
7708
|
let client;
|
|
7749
7709
|
try {
|
|
@@ -7755,7 +7715,7 @@ var require_cdp_manager = __commonJS({
|
|
|
7755
7715
|
const email = process.env.CDP_USER_EMAIL || await this._promptEmail();
|
|
7756
7716
|
const fakeUserId = `user_${Buffer.from(email).toString("hex").slice(0, 8)}`;
|
|
7757
7717
|
const fakeWalletId = `w_${Date.now()}`;
|
|
7758
|
-
const fakeAddress = this.account ||
|
|
7718
|
+
const fakeAddress = this.account || ethers2.Wallet.createRandom().address;
|
|
7759
7719
|
this._userId = fakeUserId;
|
|
7760
7720
|
this._walletId = fakeWalletId;
|
|
7761
7721
|
this.account = fakeAddress;
|
|
@@ -7769,7 +7729,7 @@ var require_cdp_manager = __commonJS({
|
|
|
7769
7729
|
console.log("\u{1F4CD} Address:", this.account);
|
|
7770
7730
|
try {
|
|
7771
7731
|
const bal = await this.getBalance();
|
|
7772
|
-
console.log("\u{1F4B0} Balance:",
|
|
7732
|
+
console.log("\u{1F4B0} Balance:", ethers2.formatEther(bal), "ETH");
|
|
7773
7733
|
} catch (_) {
|
|
7774
7734
|
}
|
|
7775
7735
|
}
|
|
@@ -7794,7 +7754,7 @@ var require_cdp_manager = __commonJS({
|
|
|
7794
7754
|
if (!process.env.SAGE_QUIET_JSON) {
|
|
7795
7755
|
console.log("\u{1F4DD} Transaction Details:");
|
|
7796
7756
|
console.log("To:", to);
|
|
7797
|
-
console.log("Value:",
|
|
7757
|
+
console.log("Value:", ethers2.formatEther(value));
|
|
7798
7758
|
console.log("Data:", data);
|
|
7799
7759
|
console.log("\u{1F4E8} Check your email/app to approve the transaction...");
|
|
7800
7760
|
}
|
|
@@ -7846,7 +7806,7 @@ var require_cdp_manager = __commonJS({
|
|
|
7846
7806
|
// src/wallet/typed.js
|
|
7847
7807
|
var require_typed = __commonJS({
|
|
7848
7808
|
"src/wallet/typed.js"(exports2, module2) {
|
|
7849
|
-
var { ethers } = require("ethers");
|
|
7809
|
+
var { ethers: ethers2 } = require("ethers");
|
|
7850
7810
|
function buildGovernorDomain({ name, chainId, verifyingContract }) {
|
|
7851
7811
|
if (!name || !chainId || !verifyingContract) throw new Error("name, chainId, verifyingContract required");
|
|
7852
7812
|
return { name, version: "1", chainId: Number(chainId), verifyingContract };
|
|
@@ -7963,12 +7923,40 @@ var require_doppler = __commonJS({
|
|
|
7963
7923
|
}
|
|
7964
7924
|
return { auctionAddress, note: "Lens API not available in this doppler-sdk version" };
|
|
7965
7925
|
}
|
|
7926
|
+
async function listAuctions(sdk, { limit = 10, cursor } = {}) {
|
|
7927
|
+
const lens = sdk.lens;
|
|
7928
|
+
if (lens) {
|
|
7929
|
+
if (typeof lens.listAuctions === "function") {
|
|
7930
|
+
try {
|
|
7931
|
+
return await lens.listAuctions({ limit, cursor });
|
|
7932
|
+
} catch (e) {
|
|
7933
|
+
}
|
|
7934
|
+
}
|
|
7935
|
+
if (typeof lens.getAuctions === "function") {
|
|
7936
|
+
try {
|
|
7937
|
+
return await lens.getAuctions({ limit, cursor });
|
|
7938
|
+
} catch (e) {
|
|
7939
|
+
}
|
|
7940
|
+
}
|
|
7941
|
+
}
|
|
7942
|
+
const fac = sdk.factory;
|
|
7943
|
+
if (fac && typeof fac.listAuctions === "function") {
|
|
7944
|
+
try {
|
|
7945
|
+
return await fac.listAuctions({ limit, cursor });
|
|
7946
|
+
} catch (e) {
|
|
7947
|
+
}
|
|
7948
|
+
}
|
|
7949
|
+
return { ok: false, error: "LIST_UNSUPPORTED", message: "Listing auctions not supported by this doppler-sdk version" };
|
|
7950
|
+
}
|
|
7966
7951
|
async function buyTokens(sdk, { auctionAddress, numeraireAmount }) {
|
|
7967
7952
|
const trade = sdk.trade || sdk.swap || sdk.auction;
|
|
7968
7953
|
if (trade && typeof trade.buy === "function") {
|
|
7969
|
-
|
|
7954
|
+
try {
|
|
7955
|
+
return await trade.buy({ auctionAddress, numeraireAmount });
|
|
7956
|
+
} catch (e) {
|
|
7957
|
+
}
|
|
7970
7958
|
}
|
|
7971
|
-
|
|
7959
|
+
return { ok: false, error: "BUY_UNSUPPORTED", message: "Buy not supported by this doppler-sdk version. Use executeV3BuyExactIn/urExecute helpers or upgrade doppler-sdk." };
|
|
7972
7960
|
}
|
|
7973
7961
|
async function migrate(sdk, asset) {
|
|
7974
7962
|
if (sdk.airlock && typeof sdk.airlock.migrate === "function") {
|
|
@@ -7980,6 +7968,7 @@ var require_doppler = __commonJS({
|
|
|
7980
7968
|
initDoppler,
|
|
7981
7969
|
deployDynamicAuction,
|
|
7982
7970
|
getAuctionStatus,
|
|
7971
|
+
listAuctions,
|
|
7983
7972
|
buyTokens,
|
|
7984
7973
|
migrate
|
|
7985
7974
|
};
|
|
@@ -8134,6 +8123,952 @@ var require_doppler = __commonJS({
|
|
|
8134
8123
|
}
|
|
8135
8124
|
});
|
|
8136
8125
|
|
|
8126
|
+
// src/services/utils/cache.js
|
|
8127
|
+
var require_cache = __commonJS({
|
|
8128
|
+
"src/services/utils/cache.js"(exports2, module2) {
|
|
8129
|
+
var SimpleCache = class {
|
|
8130
|
+
constructor(options = {}) {
|
|
8131
|
+
this.enabled = options.enabled !== false;
|
|
8132
|
+
this.defaultTTL = options.ttl || 3e4;
|
|
8133
|
+
this.maxSize = options.maxSize || 100;
|
|
8134
|
+
this._store = /* @__PURE__ */ new Map();
|
|
8135
|
+
}
|
|
8136
|
+
/**
|
|
8137
|
+
* Get value from cache
|
|
8138
|
+
* @param {string} key - Cache key
|
|
8139
|
+
* @returns {any|null} - Cached value or null if expired/missing
|
|
8140
|
+
*/
|
|
8141
|
+
get(key) {
|
|
8142
|
+
if (!this.enabled) return null;
|
|
8143
|
+
const entry = this._store.get(key);
|
|
8144
|
+
if (!entry) return null;
|
|
8145
|
+
if (Date.now() > entry.expires) {
|
|
8146
|
+
this._store.delete(key);
|
|
8147
|
+
return null;
|
|
8148
|
+
}
|
|
8149
|
+
return entry.data;
|
|
8150
|
+
}
|
|
8151
|
+
/**
|
|
8152
|
+
* Set value in cache with TTL
|
|
8153
|
+
* @param {string} key - Cache key
|
|
8154
|
+
* @param {any} data - Data to cache
|
|
8155
|
+
* @param {number} ttl - Time to live in milliseconds (optional)
|
|
8156
|
+
*/
|
|
8157
|
+
set(key, data, ttl) {
|
|
8158
|
+
if (!this.enabled) return;
|
|
8159
|
+
if (this._store.size >= this.maxSize && !this._store.has(key)) {
|
|
8160
|
+
const firstKey = this._store.keys().next().value;
|
|
8161
|
+
this._store.delete(firstKey);
|
|
8162
|
+
}
|
|
8163
|
+
this._store.set(key, {
|
|
8164
|
+
data,
|
|
8165
|
+
expires: Date.now() + (ttl || this.defaultTTL)
|
|
8166
|
+
});
|
|
8167
|
+
}
|
|
8168
|
+
/**
|
|
8169
|
+
* Clear all cached entries
|
|
8170
|
+
*/
|
|
8171
|
+
clear() {
|
|
8172
|
+
this._store.clear();
|
|
8173
|
+
}
|
|
8174
|
+
/**
|
|
8175
|
+
* Delete specific key
|
|
8176
|
+
* @param {string} key - Cache key to delete
|
|
8177
|
+
*/
|
|
8178
|
+
delete(key) {
|
|
8179
|
+
this._store.delete(key);
|
|
8180
|
+
}
|
|
8181
|
+
/**
|
|
8182
|
+
* Get cache statistics
|
|
8183
|
+
* @returns {object} - Cache stats (size, enabled)
|
|
8184
|
+
*/
|
|
8185
|
+
stats() {
|
|
8186
|
+
return {
|
|
8187
|
+
size: this._store.size,
|
|
8188
|
+
maxSize: this.maxSize,
|
|
8189
|
+
enabled: this.enabled
|
|
8190
|
+
};
|
|
8191
|
+
}
|
|
8192
|
+
};
|
|
8193
|
+
module2.exports = { SimpleCache };
|
|
8194
|
+
}
|
|
8195
|
+
});
|
|
8196
|
+
|
|
8197
|
+
// src/services/utils/retry.js
|
|
8198
|
+
var require_retry = __commonJS({
|
|
8199
|
+
"src/services/utils/retry.js"(exports2, module2) {
|
|
8200
|
+
async function retryWithBackoff(fn, options = {}) {
|
|
8201
|
+
const {
|
|
8202
|
+
attempts = 3,
|
|
8203
|
+
baseDelay = 1e3,
|
|
8204
|
+
maxDelay = 1e4,
|
|
8205
|
+
onRetry = null
|
|
8206
|
+
} = options;
|
|
8207
|
+
let lastError;
|
|
8208
|
+
for (let i = 0; i < attempts; i++) {
|
|
8209
|
+
try {
|
|
8210
|
+
return await fn();
|
|
8211
|
+
} catch (error) {
|
|
8212
|
+
lastError = error;
|
|
8213
|
+
if (i === attempts - 1) {
|
|
8214
|
+
break;
|
|
8215
|
+
}
|
|
8216
|
+
const delay = Math.min(baseDelay * Math.pow(2, i), maxDelay);
|
|
8217
|
+
if (onRetry) {
|
|
8218
|
+
onRetry({
|
|
8219
|
+
attempt: i + 1,
|
|
8220
|
+
totalAttempts: attempts,
|
|
8221
|
+
delay,
|
|
8222
|
+
error
|
|
8223
|
+
});
|
|
8224
|
+
}
|
|
8225
|
+
await sleep(delay);
|
|
8226
|
+
}
|
|
8227
|
+
}
|
|
8228
|
+
throw lastError;
|
|
8229
|
+
}
|
|
8230
|
+
function sleep(ms) {
|
|
8231
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
8232
|
+
}
|
|
8233
|
+
module2.exports = { retryWithBackoff, sleep };
|
|
8234
|
+
}
|
|
8235
|
+
});
|
|
8236
|
+
|
|
8237
|
+
// src/errors/index.js
|
|
8238
|
+
var require_errors2 = __commonJS({
|
|
8239
|
+
"src/errors/index.js"(exports2, module2) {
|
|
8240
|
+
var SageSDKError = class extends Error {
|
|
8241
|
+
constructor(message, code, retryable = false, originalError = null) {
|
|
8242
|
+
super(message);
|
|
8243
|
+
this.name = this.constructor.name;
|
|
8244
|
+
this.code = code;
|
|
8245
|
+
this.retryable = retryable;
|
|
8246
|
+
this.originalError = originalError;
|
|
8247
|
+
}
|
|
8248
|
+
};
|
|
8249
|
+
var SubgraphError = class extends SageSDKError {
|
|
8250
|
+
/**
|
|
8251
|
+
* @param {string} message - Error message
|
|
8252
|
+
* @param {'TIMEOUT'|'NETWORK'|'INVALID_RESPONSE'|'NOT_FOUND'|'QUERY_FAILED'} code - Error code
|
|
8253
|
+
* @param {boolean} retryable - Whether error is retryable
|
|
8254
|
+
* @param {Error} originalError - Original error (optional)
|
|
8255
|
+
*/
|
|
8256
|
+
constructor(message, code, retryable = false, originalError = null) {
|
|
8257
|
+
super(message, code, retryable, originalError);
|
|
8258
|
+
}
|
|
8259
|
+
};
|
|
8260
|
+
var IPFSError = class extends SageSDKError {
|
|
8261
|
+
/**
|
|
8262
|
+
* @param {string} message - Error message
|
|
8263
|
+
* @param {'TIMEOUT'|'PIN_FAILED'|'INVALID_CID'|'NOT_FOUND'|'GATEWAY_FAILED'|'UPLOAD_FAILED'} code - Error code
|
|
8264
|
+
* @param {boolean} retryable - Whether error is retryable
|
|
8265
|
+
* @param {Error} originalError - Original error (optional)
|
|
8266
|
+
*/
|
|
8267
|
+
constructor(message, code, retryable = false, originalError = null) {
|
|
8268
|
+
super(message, code, retryable, originalError);
|
|
8269
|
+
}
|
|
8270
|
+
};
|
|
8271
|
+
function formatErrorMessage(error) {
|
|
8272
|
+
if (!error) return "An unknown error occurred";
|
|
8273
|
+
if (error instanceof SubgraphError || error instanceof IPFSError) {
|
|
8274
|
+
switch (error.code) {
|
|
8275
|
+
case "TIMEOUT":
|
|
8276
|
+
return "Request timed out. Please try again.";
|
|
8277
|
+
case "NETWORK":
|
|
8278
|
+
return "Network error. Check your connection and try again.";
|
|
8279
|
+
case "INVALID_RESPONSE":
|
|
8280
|
+
return "Received invalid data from server.";
|
|
8281
|
+
case "NOT_FOUND":
|
|
8282
|
+
return "Content not found.";
|
|
8283
|
+
case "PIN_FAILED":
|
|
8284
|
+
return "Failed to pin content to IPFS. Please try again.";
|
|
8285
|
+
case "INVALID_CID":
|
|
8286
|
+
return "Invalid content identifier (CID).";
|
|
8287
|
+
case "GATEWAY_FAILED":
|
|
8288
|
+
return "All IPFS gateways failed. Content may be temporarily unavailable.";
|
|
8289
|
+
case "UPLOAD_FAILED":
|
|
8290
|
+
return "Failed to upload content. Please try again.";
|
|
8291
|
+
case "QUERY_FAILED":
|
|
8292
|
+
return "Failed to query data. Please try again.";
|
|
8293
|
+
default:
|
|
8294
|
+
return error.message || "An error occurred";
|
|
8295
|
+
}
|
|
8296
|
+
}
|
|
8297
|
+
return error.message || "An error occurred";
|
|
8298
|
+
}
|
|
8299
|
+
function isRetryable(error) {
|
|
8300
|
+
if (error instanceof SageSDKError) {
|
|
8301
|
+
return error.retryable;
|
|
8302
|
+
}
|
|
8303
|
+
if (error.name === "AbortError" || error.name === "TimeoutError") {
|
|
8304
|
+
return true;
|
|
8305
|
+
}
|
|
8306
|
+
const message = String(error.message || "").toLowerCase();
|
|
8307
|
+
const retryablePatterns = [
|
|
8308
|
+
"timeout",
|
|
8309
|
+
"network",
|
|
8310
|
+
"econnrefused",
|
|
8311
|
+
"econnreset",
|
|
8312
|
+
"etimedout",
|
|
8313
|
+
"fetch failed"
|
|
8314
|
+
];
|
|
8315
|
+
return retryablePatterns.some((pattern) => message.includes(pattern));
|
|
8316
|
+
}
|
|
8317
|
+
module2.exports = {
|
|
8318
|
+
SageSDKError,
|
|
8319
|
+
SubgraphError,
|
|
8320
|
+
IPFSError,
|
|
8321
|
+
formatErrorMessage,
|
|
8322
|
+
isRetryable
|
|
8323
|
+
};
|
|
8324
|
+
}
|
|
8325
|
+
});
|
|
8326
|
+
|
|
8327
|
+
// src/services/subgraph/client.js
|
|
8328
|
+
var require_client = __commonJS({
|
|
8329
|
+
"src/services/subgraph/client.js"(exports2, module2) {
|
|
8330
|
+
var subgraph = require_subgraph();
|
|
8331
|
+
var { SimpleCache } = require_cache();
|
|
8332
|
+
var { retryWithBackoff } = require_retry();
|
|
8333
|
+
var { SubgraphError } = require_errors2();
|
|
8334
|
+
var SubgraphService = class {
|
|
8335
|
+
/**
|
|
8336
|
+
* @param {object} config - Service configuration
|
|
8337
|
+
* @param {string} config.url - Subgraph GraphQL endpoint
|
|
8338
|
+
* @param {number} [config.timeout=10000] - Request timeout in ms
|
|
8339
|
+
* @param {number} [config.retries=3] - Number of retry attempts
|
|
8340
|
+
* @param {object} [config.cache] - Cache configuration
|
|
8341
|
+
* @param {boolean} [config.cache.enabled=true] - Enable caching
|
|
8342
|
+
* @param {number} [config.cache.ttl=30000] - Cache TTL in ms
|
|
8343
|
+
* @param {number} [config.cache.maxSize=100] - Max cache entries
|
|
8344
|
+
*/
|
|
8345
|
+
constructor(config) {
|
|
8346
|
+
if (!config || !config.url) {
|
|
8347
|
+
throw new Error("SubgraphService requires a url in config");
|
|
8348
|
+
}
|
|
8349
|
+
this.url = config.url;
|
|
8350
|
+
this.timeout = config.timeout || 1e4;
|
|
8351
|
+
this.retries = config.retries || 3;
|
|
8352
|
+
this._cache = new SimpleCache({
|
|
8353
|
+
enabled: config.cache?.enabled !== false,
|
|
8354
|
+
ttl: config.cache?.ttl || 3e4,
|
|
8355
|
+
maxSize: config.cache?.maxSize || 100
|
|
8356
|
+
});
|
|
8357
|
+
}
|
|
8358
|
+
/**
|
|
8359
|
+
* Get list of SubDAOs
|
|
8360
|
+
* @param {object} [options] - Query options
|
|
8361
|
+
* @param {number} [options.limit=50] - Max results
|
|
8362
|
+
* @param {number} [options.skip=0] - Results to skip
|
|
8363
|
+
* @param {boolean} [options.cache=true] - Use cache
|
|
8364
|
+
* @returns {Promise<Array>} - List of SubDAOs
|
|
8365
|
+
*/
|
|
8366
|
+
async getSubDAOs(options = {}) {
|
|
8367
|
+
const { limit = 50, skip = 0, cache = true } = options;
|
|
8368
|
+
const cacheKey = `subdaos:${limit}:${skip}`;
|
|
8369
|
+
if (cache) {
|
|
8370
|
+
const cached = this._cache.get(cacheKey);
|
|
8371
|
+
if (cached) return cached;
|
|
8372
|
+
}
|
|
8373
|
+
try {
|
|
8374
|
+
const result = await retryWithBackoff(
|
|
8375
|
+
() => this._querySubDAOs({ limit, skip }),
|
|
8376
|
+
{ attempts: this.retries }
|
|
8377
|
+
);
|
|
8378
|
+
if (cache) {
|
|
8379
|
+
this._cache.set(cacheKey, result);
|
|
8380
|
+
}
|
|
8381
|
+
return result;
|
|
8382
|
+
} catch (error) {
|
|
8383
|
+
throw new SubgraphError(
|
|
8384
|
+
`Failed to fetch SubDAOs: ${error.message}`,
|
|
8385
|
+
"QUERY_FAILED",
|
|
8386
|
+
true,
|
|
8387
|
+
error
|
|
8388
|
+
);
|
|
8389
|
+
}
|
|
8390
|
+
}
|
|
8391
|
+
/**
|
|
8392
|
+
* Get list of proposals
|
|
8393
|
+
* @param {object} [options] - Query options
|
|
8394
|
+
* @param {string} [options.governor] - Filter by governor address
|
|
8395
|
+
* @param {string} [options.subdao] - Filter by SubDAO address
|
|
8396
|
+
* @param {string[]} [options.states] - Filter by proposal states
|
|
8397
|
+
* @param {number} [options.fromTimestamp] - Filter by creation time (>=)
|
|
8398
|
+
* @param {number} [options.toTimestamp] - Filter by creation time (<=)
|
|
8399
|
+
* @param {number} [options.limit=20] - Max results
|
|
8400
|
+
* @param {number} [options.skip=0] - Results to skip
|
|
8401
|
+
* @param {boolean} [options.cache=true] - Use cache
|
|
8402
|
+
* @returns {Promise<Array>} - List of proposals
|
|
8403
|
+
*/
|
|
8404
|
+
async getProposals(options = {}) {
|
|
8405
|
+
const {
|
|
8406
|
+
governor,
|
|
8407
|
+
subdao,
|
|
8408
|
+
states,
|
|
8409
|
+
fromTimestamp,
|
|
8410
|
+
toTimestamp,
|
|
8411
|
+
limit = 20,
|
|
8412
|
+
skip = 0,
|
|
8413
|
+
cache = true
|
|
8414
|
+
} = options;
|
|
8415
|
+
const cacheKey = `proposals:${JSON.stringify({
|
|
8416
|
+
governor,
|
|
8417
|
+
subdao,
|
|
8418
|
+
states,
|
|
8419
|
+
fromTimestamp,
|
|
8420
|
+
toTimestamp,
|
|
8421
|
+
limit,
|
|
8422
|
+
skip
|
|
8423
|
+
})}`;
|
|
8424
|
+
if (cache) {
|
|
8425
|
+
const cached = this._cache.get(cacheKey);
|
|
8426
|
+
if (cached) return cached;
|
|
8427
|
+
}
|
|
8428
|
+
try {
|
|
8429
|
+
const result = await retryWithBackoff(
|
|
8430
|
+
() => this._queryProposals({
|
|
8431
|
+
governor,
|
|
8432
|
+
subdao,
|
|
8433
|
+
states,
|
|
8434
|
+
fromTimestamp,
|
|
8435
|
+
toTimestamp,
|
|
8436
|
+
limit,
|
|
8437
|
+
skip
|
|
8438
|
+
}),
|
|
8439
|
+
{ attempts: this.retries }
|
|
8440
|
+
);
|
|
8441
|
+
if (cache) {
|
|
8442
|
+
this._cache.set(cacheKey, result);
|
|
8443
|
+
}
|
|
8444
|
+
return result;
|
|
8445
|
+
} catch (error) {
|
|
8446
|
+
throw new SubgraphError(
|
|
8447
|
+
`Failed to fetch proposals: ${error.message}`,
|
|
8448
|
+
"QUERY_FAILED",
|
|
8449
|
+
true,
|
|
8450
|
+
error
|
|
8451
|
+
);
|
|
8452
|
+
}
|
|
8453
|
+
}
|
|
8454
|
+
/**
|
|
8455
|
+
* Get proposal by ID
|
|
8456
|
+
* @param {string} id - Proposal ID
|
|
8457
|
+
* @param {object} [options] - Query options
|
|
8458
|
+
* @param {boolean} [options.cache=true] - Use cache
|
|
8459
|
+
* @returns {Promise<object|null>} - Proposal or null
|
|
8460
|
+
*/
|
|
8461
|
+
async getProposalById(id2, options = {}) {
|
|
8462
|
+
const { cache = true } = options;
|
|
8463
|
+
const cacheKey = `proposal:${id2}`;
|
|
8464
|
+
if (cache) {
|
|
8465
|
+
const cached = this._cache.get(cacheKey);
|
|
8466
|
+
if (cached !== null) return cached;
|
|
8467
|
+
}
|
|
8468
|
+
try {
|
|
8469
|
+
const result = await retryWithBackoff(
|
|
8470
|
+
() => subgraph.getProposalById({ url: this.url, id: id2 }),
|
|
8471
|
+
{ attempts: this.retries }
|
|
8472
|
+
);
|
|
8473
|
+
if (cache) {
|
|
8474
|
+
this._cache.set(cacheKey, result);
|
|
8475
|
+
}
|
|
8476
|
+
return result;
|
|
8477
|
+
} catch (error) {
|
|
8478
|
+
throw new SubgraphError(
|
|
8479
|
+
`Failed to fetch proposal ${id2}: ${error.message}`,
|
|
8480
|
+
"QUERY_FAILED",
|
|
8481
|
+
true,
|
|
8482
|
+
error
|
|
8483
|
+
);
|
|
8484
|
+
}
|
|
8485
|
+
}
|
|
8486
|
+
/**
|
|
8487
|
+
* Get libraries
|
|
8488
|
+
* @param {object} [options] - Query options
|
|
8489
|
+
* @param {string} [options.subdao] - Filter by SubDAO address
|
|
8490
|
+
* @param {number} [options.limit=50] - Max results
|
|
8491
|
+
* @param {number} [options.skip=0] - Results to skip
|
|
8492
|
+
* @param {boolean} [options.cache=true] - Use cache
|
|
8493
|
+
* @returns {Promise<Array>} - List of libraries
|
|
8494
|
+
*/
|
|
8495
|
+
async getLibraries(options = {}) {
|
|
8496
|
+
const { subdao, limit = 50, skip = 0, cache = true } = options;
|
|
8497
|
+
const cacheKey = `libraries:${subdao || "all"}:${limit}:${skip}`;
|
|
8498
|
+
if (cache) {
|
|
8499
|
+
const cached = this._cache.get(cacheKey);
|
|
8500
|
+
if (cached) return cached;
|
|
8501
|
+
}
|
|
8502
|
+
try {
|
|
8503
|
+
const result = await retryWithBackoff(
|
|
8504
|
+
() => subgraph.listLibraries({ url: this.url, subdao, first: limit, skip }),
|
|
8505
|
+
{ attempts: this.retries }
|
|
8506
|
+
);
|
|
8507
|
+
if (cache) {
|
|
8508
|
+
this._cache.set(cacheKey, result);
|
|
8509
|
+
}
|
|
8510
|
+
return result;
|
|
8511
|
+
} catch (error) {
|
|
8512
|
+
throw new SubgraphError(
|
|
8513
|
+
`Failed to fetch libraries: ${error.message}`,
|
|
8514
|
+
"QUERY_FAILED",
|
|
8515
|
+
true,
|
|
8516
|
+
error
|
|
8517
|
+
);
|
|
8518
|
+
}
|
|
8519
|
+
}
|
|
8520
|
+
/**
|
|
8521
|
+
* Get prompts by tag
|
|
8522
|
+
* @param {object} options - Query options
|
|
8523
|
+
* @param {string} options.tagsHash - Tag hash to filter by
|
|
8524
|
+
* @param {string} [options.registry] - Filter by registry address
|
|
8525
|
+
* @param {number} [options.limit=50] - Max results
|
|
8526
|
+
* @param {number} [options.skip=0] - Results to skip
|
|
8527
|
+
* @param {boolean} [options.cache=true] - Use cache
|
|
8528
|
+
* @returns {Promise<Array>} - List of prompts
|
|
8529
|
+
*/
|
|
8530
|
+
async getPromptsByTag(options) {
|
|
8531
|
+
if (!options || !options.tagsHash) {
|
|
8532
|
+
throw new Error("tagsHash is required");
|
|
8533
|
+
}
|
|
8534
|
+
const { tagsHash, registry, limit = 50, skip = 0, cache = true } = options;
|
|
8535
|
+
const cacheKey = `prompts-tag:${tagsHash}:${registry || "all"}:${limit}:${skip}`;
|
|
8536
|
+
if (cache) {
|
|
8537
|
+
const cached = this._cache.get(cacheKey);
|
|
8538
|
+
if (cached) return cached;
|
|
8539
|
+
}
|
|
8540
|
+
try {
|
|
8541
|
+
const result = await retryWithBackoff(
|
|
8542
|
+
() => subgraph.listPromptsByTag({
|
|
8543
|
+
url: this.url,
|
|
8544
|
+
tagsHash,
|
|
8545
|
+
registry,
|
|
8546
|
+
first: limit,
|
|
8547
|
+
skip
|
|
8548
|
+
}),
|
|
8549
|
+
{ attempts: this.retries }
|
|
8550
|
+
);
|
|
8551
|
+
if (cache) {
|
|
8552
|
+
this._cache.set(cacheKey, result);
|
|
8553
|
+
}
|
|
8554
|
+
return result;
|
|
8555
|
+
} catch (error) {
|
|
8556
|
+
throw new SubgraphError(
|
|
8557
|
+
`Failed to fetch prompts by tag: ${error.message}`,
|
|
8558
|
+
"QUERY_FAILED",
|
|
8559
|
+
true,
|
|
8560
|
+
error
|
|
8561
|
+
);
|
|
8562
|
+
}
|
|
8563
|
+
}
|
|
8564
|
+
/**
|
|
8565
|
+
* Get registry prompts
|
|
8566
|
+
* @param {object} options - Query options
|
|
8567
|
+
* @param {string} options.registry - Registry address
|
|
8568
|
+
* @param {number} [options.limit=50] - Max results
|
|
8569
|
+
* @param {number} [options.skip=0] - Results to skip
|
|
8570
|
+
* @param {boolean} [options.cache=true] - Use cache
|
|
8571
|
+
* @returns {Promise<Array>} - List of prompts
|
|
8572
|
+
*/
|
|
8573
|
+
async getRegistryPrompts(options) {
|
|
8574
|
+
if (!options || !options.registry) {
|
|
8575
|
+
throw new Error("registry is required");
|
|
8576
|
+
}
|
|
8577
|
+
const { registry, limit = 50, skip = 0, cache = true } = options;
|
|
8578
|
+
const cacheKey = `registry-prompts:${registry}:${limit}:${skip}`;
|
|
8579
|
+
if (cache) {
|
|
8580
|
+
const cached = this._cache.get(cacheKey);
|
|
8581
|
+
if (cached) return cached;
|
|
8582
|
+
}
|
|
8583
|
+
try {
|
|
8584
|
+
const result = await retryWithBackoff(
|
|
8585
|
+
() => subgraph.listRegistryPrompts({
|
|
8586
|
+
url: this.url,
|
|
8587
|
+
registry,
|
|
8588
|
+
first: limit,
|
|
8589
|
+
skip
|
|
8590
|
+
}),
|
|
8591
|
+
{ attempts: this.retries }
|
|
8592
|
+
);
|
|
8593
|
+
if (cache) {
|
|
8594
|
+
this._cache.set(cacheKey, result);
|
|
8595
|
+
}
|
|
8596
|
+
return result;
|
|
8597
|
+
} catch (error) {
|
|
8598
|
+
throw new SubgraphError(
|
|
8599
|
+
`Failed to fetch registry prompts: ${error.message}`,
|
|
8600
|
+
"QUERY_FAILED",
|
|
8601
|
+
true,
|
|
8602
|
+
error
|
|
8603
|
+
);
|
|
8604
|
+
}
|
|
8605
|
+
}
|
|
8606
|
+
/**
|
|
8607
|
+
* Clear cache
|
|
8608
|
+
*/
|
|
8609
|
+
clearCache() {
|
|
8610
|
+
this._cache.clear();
|
|
8611
|
+
}
|
|
8612
|
+
/**
|
|
8613
|
+
* Get cache statistics
|
|
8614
|
+
* @returns {object} - Cache stats
|
|
8615
|
+
*/
|
|
8616
|
+
getCacheStats() {
|
|
8617
|
+
return this._cache.stats();
|
|
8618
|
+
}
|
|
8619
|
+
// Private methods
|
|
8620
|
+
async _querySubDAOs({ limit, skip }) {
|
|
8621
|
+
const data = await subgraph.query(
|
|
8622
|
+
this.url,
|
|
8623
|
+
`
|
|
8624
|
+
query($first: Int!, $skip: Int!) {
|
|
8625
|
+
subDAOs(first: $first, skip: $skip, orderBy: createdAt, orderDirection: desc) {
|
|
8626
|
+
id
|
|
8627
|
+
address
|
|
8628
|
+
name
|
|
8629
|
+
description
|
|
8630
|
+
governor
|
|
8631
|
+
registry
|
|
8632
|
+
token
|
|
8633
|
+
createdAt
|
|
8634
|
+
}
|
|
8635
|
+
}
|
|
8636
|
+
`,
|
|
8637
|
+
{ first: limit, skip }
|
|
8638
|
+
);
|
|
8639
|
+
return data?.subDAOs || [];
|
|
8640
|
+
}
|
|
8641
|
+
async _queryProposals({ governor, subdao, states, fromTimestamp, toTimestamp, limit, skip }) {
|
|
8642
|
+
return await subgraph.listProposalsFiltered({
|
|
8643
|
+
url: this.url,
|
|
8644
|
+
governor,
|
|
8645
|
+
states,
|
|
8646
|
+
fromTimestamp,
|
|
8647
|
+
toTimestamp,
|
|
8648
|
+
first: limit,
|
|
8649
|
+
skip
|
|
8650
|
+
});
|
|
8651
|
+
}
|
|
8652
|
+
};
|
|
8653
|
+
module2.exports = { SubgraphService };
|
|
8654
|
+
}
|
|
8655
|
+
});
|
|
8656
|
+
|
|
8657
|
+
// src/services/ipfs/client.js
|
|
8658
|
+
var require_client2 = __commonJS({
|
|
8659
|
+
"src/services/ipfs/client.js"(exports2, module2) {
|
|
8660
|
+
var ipfs = require_ipfs();
|
|
8661
|
+
var { SimpleCache } = require_cache();
|
|
8662
|
+
var { retryWithBackoff } = require_retry();
|
|
8663
|
+
var { IPFSError } = require_errors2();
|
|
8664
|
+
var IPFSService = class {
|
|
8665
|
+
/**
|
|
8666
|
+
* @param {object} config - Service configuration
|
|
8667
|
+
* @param {string} config.workerBaseUrl - IPFS worker base URL
|
|
8668
|
+
* @param {string} config.gateway - Primary IPFS gateway URL
|
|
8669
|
+
* @param {object} [config.signer] - ethers v6 signer for worker auth
|
|
8670
|
+
* @param {Function} [config.getAuth] - Function to get auth credentials
|
|
8671
|
+
* @param {string} [config.workerToken] - Bearer token for worker auth
|
|
8672
|
+
* @param {number} [config.timeout=15000] - Request timeout in ms
|
|
8673
|
+
* @param {number} [config.retries=2] - Number of retry attempts
|
|
8674
|
+
* @param {object} [config.cache] - Cache configuration
|
|
8675
|
+
* @param {boolean} [config.cache.enabled=true] - Enable caching
|
|
8676
|
+
* @param {number} [config.cache.ttl=300000] - Cache TTL in ms (default 5min for immutable CIDs)
|
|
8677
|
+
* @param {number} [config.cache.maxSize=50] - Max cache entries
|
|
8678
|
+
*/
|
|
8679
|
+
constructor(config) {
|
|
8680
|
+
if (!config) {
|
|
8681
|
+
throw new Error("IPFSService requires a config object");
|
|
8682
|
+
}
|
|
8683
|
+
this.workerBaseUrl = config.workerBaseUrl;
|
|
8684
|
+
this.gateway = config.gateway;
|
|
8685
|
+
this.timeout = config.timeout || 15e3;
|
|
8686
|
+
this.retries = config.retries || 2;
|
|
8687
|
+
this._client = ipfs.createClient({
|
|
8688
|
+
workerBaseUrl: config.workerBaseUrl,
|
|
8689
|
+
gateway: config.gateway,
|
|
8690
|
+
workerSigner: config.signer,
|
|
8691
|
+
workerGetAuth: config.getAuth,
|
|
8692
|
+
workerToken: config.workerToken,
|
|
8693
|
+
timeoutMs: this.timeout,
|
|
8694
|
+
retries: this.retries
|
|
8695
|
+
});
|
|
8696
|
+
this._cache = new SimpleCache({
|
|
8697
|
+
enabled: config.cache?.enabled !== false,
|
|
8698
|
+
ttl: config.cache?.ttl || 3e5,
|
|
8699
|
+
// 5 minutes
|
|
8700
|
+
maxSize: config.cache?.maxSize || 50
|
|
8701
|
+
});
|
|
8702
|
+
}
|
|
8703
|
+
/**
|
|
8704
|
+
* Upload content to IPFS worker
|
|
8705
|
+
* @param {any} content - Content to upload (will be JSON stringified)
|
|
8706
|
+
* @param {object} [options] - Upload options
|
|
8707
|
+
* @param {string} [options.name] - Content name
|
|
8708
|
+
* @param {boolean} [options.warm=false] - Warm gateways after upload
|
|
8709
|
+
* @returns {Promise<string>} - CID of uploaded content
|
|
8710
|
+
*/
|
|
8711
|
+
async upload(content, options = {}) {
|
|
8712
|
+
const { name = "upload", warm = false } = options;
|
|
8713
|
+
try {
|
|
8714
|
+
const result = await retryWithBackoff(
|
|
8715
|
+
() => this._client.uploadJson(content, name, {
|
|
8716
|
+
provider: "worker",
|
|
8717
|
+
warm
|
|
8718
|
+
}),
|
|
8719
|
+
{ attempts: this.retries }
|
|
8720
|
+
);
|
|
8721
|
+
return result.cid;
|
|
8722
|
+
} catch (error) {
|
|
8723
|
+
throw new IPFSError(
|
|
8724
|
+
`Failed to upload content: ${error.message}`,
|
|
8725
|
+
"UPLOAD_FAILED",
|
|
8726
|
+
true,
|
|
8727
|
+
error
|
|
8728
|
+
);
|
|
8729
|
+
}
|
|
8730
|
+
}
|
|
8731
|
+
/**
|
|
8732
|
+
* Fetch JSON content by CID with parallel gateway fetching
|
|
8733
|
+
* @param {string} cid - IPFS CID
|
|
8734
|
+
* @param {object} [options] - Fetch options
|
|
8735
|
+
* @param {boolean} [options.cache=true] - Use cache
|
|
8736
|
+
* @param {number} [options.timeout=5000] - Timeout per gateway in ms
|
|
8737
|
+
* @param {string[]} [options.extraGateways] - Additional gateways to try
|
|
8738
|
+
* @returns {Promise<any|null>} - Parsed JSON content or null
|
|
8739
|
+
*/
|
|
8740
|
+
async fetchByCID(cid, options = {}) {
|
|
8741
|
+
if (!cid) {
|
|
8742
|
+
throw new IPFSError("CID is required", "INVALID_CID", false);
|
|
8743
|
+
}
|
|
8744
|
+
const { cache = true, timeout = 5e3, extraGateways = [] } = options;
|
|
8745
|
+
if (cache) {
|
|
8746
|
+
const cached = this._cache.get(cid);
|
|
8747
|
+
if (cached) return cached;
|
|
8748
|
+
}
|
|
8749
|
+
const urls = this._client.buildGatewayUrls(cid, extraGateways);
|
|
8750
|
+
try {
|
|
8751
|
+
const result = await this._parallelFetch(urls, timeout);
|
|
8752
|
+
if (result === null) {
|
|
8753
|
+
throw new IPFSError(
|
|
8754
|
+
`All gateways failed for CID ${cid}`,
|
|
8755
|
+
"GATEWAY_FAILED",
|
|
8756
|
+
true
|
|
8757
|
+
);
|
|
8758
|
+
}
|
|
8759
|
+
if (cache) {
|
|
8760
|
+
this._cache.set(cid, result);
|
|
8761
|
+
}
|
|
8762
|
+
return result;
|
|
8763
|
+
} catch (error) {
|
|
8764
|
+
if (error instanceof IPFSError) throw error;
|
|
8765
|
+
throw new IPFSError(
|
|
8766
|
+
`Failed to fetch CID ${cid}: ${error.message}`,
|
|
8767
|
+
"GATEWAY_FAILED",
|
|
8768
|
+
true,
|
|
8769
|
+
error
|
|
8770
|
+
);
|
|
8771
|
+
}
|
|
8772
|
+
}
|
|
8773
|
+
/**
|
|
8774
|
+
* Pin CIDs to IPFS worker
|
|
8775
|
+
* @param {string|string[]} cids - CID or array of CIDs to pin
|
|
8776
|
+
* @param {object} [options] - Pin options
|
|
8777
|
+
* @param {boolean} [options.warm=false] - Warm gateways after pinning
|
|
8778
|
+
* @returns {Promise<void>}
|
|
8779
|
+
*/
|
|
8780
|
+
async pin(cids, options = {}) {
|
|
8781
|
+
const { warm = false } = options;
|
|
8782
|
+
const cidList = Array.isArray(cids) ? cids : [cids];
|
|
8783
|
+
if (cidList.length === 0) {
|
|
8784
|
+
throw new IPFSError("At least one CID is required", "INVALID_CID", false);
|
|
8785
|
+
}
|
|
8786
|
+
try {
|
|
8787
|
+
await retryWithBackoff(
|
|
8788
|
+
() => this._client.pin({ cids: cidList, warm }),
|
|
8789
|
+
{ attempts: this.retries }
|
|
8790
|
+
);
|
|
8791
|
+
} catch (error) {
|
|
8792
|
+
throw new IPFSError(
|
|
8793
|
+
`Failed to pin CIDs: ${error.message}`,
|
|
8794
|
+
"PIN_FAILED",
|
|
8795
|
+
true,
|
|
8796
|
+
error
|
|
8797
|
+
);
|
|
8798
|
+
}
|
|
8799
|
+
}
|
|
8800
|
+
/**
|
|
8801
|
+
* Warm gateways for a CID (prefetch)
|
|
8802
|
+
* @param {string} cid - CID to warm
|
|
8803
|
+
* @param {object} [options] - Warm options
|
|
8804
|
+
* @param {string[]} [options.gateways] - Specific gateways to warm
|
|
8805
|
+
* @returns {Promise<object>} - Warm result
|
|
8806
|
+
*/
|
|
8807
|
+
async warm(cid, options = {}) {
|
|
8808
|
+
const { gateways } = options;
|
|
8809
|
+
try {
|
|
8810
|
+
return await this._client.warmGateways(cid, { gateways });
|
|
8811
|
+
} catch (error) {
|
|
8812
|
+
return { warmed: [] };
|
|
8813
|
+
}
|
|
8814
|
+
}
|
|
8815
|
+
/**
|
|
8816
|
+
* Clear cache
|
|
8817
|
+
*/
|
|
8818
|
+
clearCache() {
|
|
8819
|
+
this._cache.clear();
|
|
8820
|
+
}
|
|
8821
|
+
/**
|
|
8822
|
+
* Get cache statistics
|
|
8823
|
+
* @returns {object} - Cache stats
|
|
8824
|
+
*/
|
|
8825
|
+
getCacheStats() {
|
|
8826
|
+
return this._cache.stats();
|
|
8827
|
+
}
|
|
8828
|
+
// Private methods
|
|
8829
|
+
/**
|
|
8830
|
+
* Fetch from multiple gateways in parallel
|
|
8831
|
+
* @param {string[]} urls - Gateway URLs to try
|
|
8832
|
+
* @param {number} timeout - Timeout per gateway in ms
|
|
8833
|
+
* @returns {Promise<any|null>} - First successful result or null
|
|
8834
|
+
* @private
|
|
8835
|
+
*/
|
|
8836
|
+
async _parallelFetch(urls, timeout) {
|
|
8837
|
+
if (!urls || urls.length === 0) {
|
|
8838
|
+
return null;
|
|
8839
|
+
}
|
|
8840
|
+
const fetchOne = async (url) => {
|
|
8841
|
+
const controller = new AbortController();
|
|
8842
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
8843
|
+
try {
|
|
8844
|
+
const response = await fetch(url, {
|
|
8845
|
+
signal: controller.signal,
|
|
8846
|
+
headers: { Accept: "application/json" }
|
|
8847
|
+
});
|
|
8848
|
+
clearTimeout(timeoutId);
|
|
8849
|
+
if (!response.ok) {
|
|
8850
|
+
return null;
|
|
8851
|
+
}
|
|
8852
|
+
const text = await response.text();
|
|
8853
|
+
try {
|
|
8854
|
+
return JSON.parse(text);
|
|
8855
|
+
} catch {
|
|
8856
|
+
return text;
|
|
8857
|
+
}
|
|
8858
|
+
} catch (error) {
|
|
8859
|
+
clearTimeout(timeoutId);
|
|
8860
|
+
return null;
|
|
8861
|
+
}
|
|
8862
|
+
};
|
|
8863
|
+
const results = await Promise.allSettled(urls.map((url) => fetchOne(url)));
|
|
8864
|
+
for (const result of results) {
|
|
8865
|
+
if (result.status === "fulfilled" && result.value !== null) {
|
|
8866
|
+
return result.value;
|
|
8867
|
+
}
|
|
8868
|
+
}
|
|
8869
|
+
return null;
|
|
8870
|
+
}
|
|
8871
|
+
};
|
|
8872
|
+
module2.exports = { IPFSService };
|
|
8873
|
+
}
|
|
8874
|
+
});
|
|
8875
|
+
|
|
8876
|
+
// src/hooks/useSubDAOs.js
|
|
8877
|
+
var require_useSubDAOs = __commonJS({
|
|
8878
|
+
"src/hooks/useSubDAOs.js"(exports2, module2) {
|
|
8879
|
+
var useSWR = require("swr");
|
|
8880
|
+
function useSubDAOs(subgraphService, options = {}) {
|
|
8881
|
+
const {
|
|
8882
|
+
limit = 50,
|
|
8883
|
+
skip = 0,
|
|
8884
|
+
cache = true,
|
|
8885
|
+
refreshInterval,
|
|
8886
|
+
revalidateOnFocus = true,
|
|
8887
|
+
revalidateOnReconnect = true
|
|
8888
|
+
} = options;
|
|
8889
|
+
const cacheKey = subgraphService ? ["subdaos", subgraphService.url, limit, skip] : null;
|
|
8890
|
+
const fetcher = async () => {
|
|
8891
|
+
if (!subgraphService) {
|
|
8892
|
+
throw new Error("SubgraphService is required");
|
|
8893
|
+
}
|
|
8894
|
+
return await subgraphService.getSubDAOs({ limit, skip, cache });
|
|
8895
|
+
};
|
|
8896
|
+
return useSWR(cacheKey, fetcher, {
|
|
8897
|
+
refreshInterval,
|
|
8898
|
+
revalidateOnFocus,
|
|
8899
|
+
revalidateOnReconnect,
|
|
8900
|
+
dedupingInterval: cache ? 3e4 : 0
|
|
8901
|
+
// Match service cache TTL
|
|
8902
|
+
});
|
|
8903
|
+
}
|
|
8904
|
+
module2.exports = { useSubDAOs };
|
|
8905
|
+
}
|
|
8906
|
+
});
|
|
8907
|
+
|
|
8908
|
+
// src/hooks/useProposals.js
|
|
8909
|
+
var require_useProposals = __commonJS({
|
|
8910
|
+
"src/hooks/useProposals.js"(exports2, module2) {
|
|
8911
|
+
var useSWR = require("swr");
|
|
8912
|
+
function useProposals(subgraphService, options = {}) {
|
|
8913
|
+
const {
|
|
8914
|
+
governor,
|
|
8915
|
+
subdao,
|
|
8916
|
+
states,
|
|
8917
|
+
fromTimestamp,
|
|
8918
|
+
toTimestamp,
|
|
8919
|
+
limit = 20,
|
|
8920
|
+
skip = 0,
|
|
8921
|
+
cache = true,
|
|
8922
|
+
refreshInterval,
|
|
8923
|
+
revalidateOnFocus = true,
|
|
8924
|
+
revalidateOnReconnect = true
|
|
8925
|
+
} = options;
|
|
8926
|
+
const cacheKey = subgraphService ? [
|
|
8927
|
+
"proposals",
|
|
8928
|
+
subgraphService.url,
|
|
8929
|
+
governor,
|
|
8930
|
+
subdao,
|
|
8931
|
+
states?.join(","),
|
|
8932
|
+
fromTimestamp,
|
|
8933
|
+
toTimestamp,
|
|
8934
|
+
limit,
|
|
8935
|
+
skip
|
|
8936
|
+
] : null;
|
|
8937
|
+
const fetcher = async () => {
|
|
8938
|
+
if (!subgraphService) {
|
|
8939
|
+
throw new Error("SubgraphService is required");
|
|
8940
|
+
}
|
|
8941
|
+
return await subgraphService.getProposals({
|
|
8942
|
+
governor,
|
|
8943
|
+
subdao,
|
|
8944
|
+
states,
|
|
8945
|
+
fromTimestamp,
|
|
8946
|
+
toTimestamp,
|
|
8947
|
+
limit,
|
|
8948
|
+
skip,
|
|
8949
|
+
cache
|
|
8950
|
+
});
|
|
8951
|
+
};
|
|
8952
|
+
return useSWR(cacheKey, fetcher, {
|
|
8953
|
+
refreshInterval,
|
|
8954
|
+
revalidateOnFocus,
|
|
8955
|
+
revalidateOnReconnect,
|
|
8956
|
+
dedupingInterval: cache ? 3e4 : 0
|
|
8957
|
+
// Match service cache TTL
|
|
8958
|
+
});
|
|
8959
|
+
}
|
|
8960
|
+
module2.exports = { useProposals };
|
|
8961
|
+
}
|
|
8962
|
+
});
|
|
8963
|
+
|
|
8964
|
+
// src/hooks/useFetchCID.js
|
|
8965
|
+
var require_useFetchCID = __commonJS({
|
|
8966
|
+
"src/hooks/useFetchCID.js"(exports2, module2) {
|
|
8967
|
+
var useSWR = require("swr");
|
|
8968
|
+
function useFetchCID(ipfsService, cid, options = {}) {
|
|
8969
|
+
const {
|
|
8970
|
+
cache = true,
|
|
8971
|
+
timeout = 5e3,
|
|
8972
|
+
extraGateways = [],
|
|
8973
|
+
refreshInterval,
|
|
8974
|
+
revalidateOnFocus = false,
|
|
8975
|
+
// CIDs are immutable
|
|
8976
|
+
revalidateOnReconnect = false
|
|
8977
|
+
// CIDs are immutable
|
|
8978
|
+
} = options;
|
|
8979
|
+
const cacheKey = ipfsService && cid ? ["ipfs-cid", cid] : null;
|
|
8980
|
+
const fetcher = async () => {
|
|
8981
|
+
if (!ipfsService) {
|
|
8982
|
+
throw new Error("IPFSService is required");
|
|
8983
|
+
}
|
|
8984
|
+
if (!cid) {
|
|
8985
|
+
throw new Error("CID is required");
|
|
8986
|
+
}
|
|
8987
|
+
return await ipfsService.fetchByCID(cid, {
|
|
8988
|
+
cache,
|
|
8989
|
+
timeout,
|
|
8990
|
+
extraGateways
|
|
8991
|
+
});
|
|
8992
|
+
};
|
|
8993
|
+
return useSWR(cacheKey, fetcher, {
|
|
8994
|
+
refreshInterval,
|
|
8995
|
+
revalidateOnFocus,
|
|
8996
|
+
revalidateOnReconnect,
|
|
8997
|
+
dedupingInterval: cache ? 3e5 : 0,
|
|
8998
|
+
// Match service cache TTL (5min)
|
|
8999
|
+
// CIDs are immutable, so we can cache errors too
|
|
9000
|
+
shouldRetryOnError: true,
|
|
9001
|
+
errorRetryInterval: 5e3,
|
|
9002
|
+
errorRetryCount: 3
|
|
9003
|
+
});
|
|
9004
|
+
}
|
|
9005
|
+
module2.exports = { useFetchCID };
|
|
9006
|
+
}
|
|
9007
|
+
});
|
|
9008
|
+
|
|
9009
|
+
// src/hooks/useUpload.js
|
|
9010
|
+
var require_useUpload = __commonJS({
|
|
9011
|
+
"src/hooks/useUpload.js"(exports2, module2) {
|
|
9012
|
+
var { useState, useCallback } = require("react");
|
|
9013
|
+
function useUpload(ipfsService) {
|
|
9014
|
+
const [isUploading, setIsUploading] = useState(false);
|
|
9015
|
+
const [error, setError] = useState(null);
|
|
9016
|
+
const [data, setData] = useState(null);
|
|
9017
|
+
const upload = useCallback(
|
|
9018
|
+
async (content, options = {}) => {
|
|
9019
|
+
if (!ipfsService) {
|
|
9020
|
+
const err = new Error("IPFSService is required");
|
|
9021
|
+
setError(err);
|
|
9022
|
+
throw err;
|
|
9023
|
+
}
|
|
9024
|
+
setIsUploading(true);
|
|
9025
|
+
setError(null);
|
|
9026
|
+
try {
|
|
9027
|
+
const cid = await ipfsService.upload(content, options);
|
|
9028
|
+
setData(cid);
|
|
9029
|
+
return cid;
|
|
9030
|
+
} catch (err) {
|
|
9031
|
+
setError(err);
|
|
9032
|
+
throw err;
|
|
9033
|
+
} finally {
|
|
9034
|
+
setIsUploading(false);
|
|
9035
|
+
}
|
|
9036
|
+
},
|
|
9037
|
+
[ipfsService]
|
|
9038
|
+
);
|
|
9039
|
+
const reset = useCallback(() => {
|
|
9040
|
+
setIsUploading(false);
|
|
9041
|
+
setError(null);
|
|
9042
|
+
setData(null);
|
|
9043
|
+
}, []);
|
|
9044
|
+
return {
|
|
9045
|
+
upload,
|
|
9046
|
+
isUploading,
|
|
9047
|
+
error,
|
|
9048
|
+
data,
|
|
9049
|
+
reset
|
|
9050
|
+
};
|
|
9051
|
+
}
|
|
9052
|
+
module2.exports = { useUpload };
|
|
9053
|
+
}
|
|
9054
|
+
});
|
|
9055
|
+
|
|
9056
|
+
// src/hooks/index.js
|
|
9057
|
+
var require_hooks = __commonJS({
|
|
9058
|
+
"src/hooks/index.js"(exports2, module2) {
|
|
9059
|
+
var { useSubDAOs } = require_useSubDAOs();
|
|
9060
|
+
var { useProposals } = require_useProposals();
|
|
9061
|
+
var { useFetchCID } = require_useFetchCID();
|
|
9062
|
+
var { useUpload } = require_useUpload();
|
|
9063
|
+
module2.exports = {
|
|
9064
|
+
useSubDAOs,
|
|
9065
|
+
useProposals,
|
|
9066
|
+
useFetchCID,
|
|
9067
|
+
useUpload
|
|
9068
|
+
};
|
|
9069
|
+
}
|
|
9070
|
+
});
|
|
9071
|
+
|
|
8137
9072
|
// src/index.js
|
|
8138
9073
|
var require_src = __commonJS({
|
|
8139
9074
|
"src/index.js"(exports2, module2) {
|
|
@@ -8143,6 +9078,7 @@ var require_src = __commonJS({
|
|
|
8143
9078
|
governance.intents = require_intents();
|
|
8144
9079
|
var governanceTemplates = require_templates();
|
|
8145
9080
|
governance.operations = require_operations();
|
|
9081
|
+
governance.grants = require_grants();
|
|
8146
9082
|
var subdao = require_subdao();
|
|
8147
9083
|
var timelock = require_timelock();
|
|
8148
9084
|
var factory = require_factory();
|
|
@@ -8159,7 +9095,6 @@ var require_src = __commonJS({
|
|
|
8159
9095
|
var treasury = require_treasury();
|
|
8160
9096
|
var boost = require_boost();
|
|
8161
9097
|
var bounty = require_bounty();
|
|
8162
|
-
var bond = require_bond();
|
|
8163
9098
|
var wallet = require_wallet();
|
|
8164
9099
|
wallet.session = require_session();
|
|
8165
9100
|
var walletCastManager = require_cast_manager();
|
|
@@ -8174,6 +9109,16 @@ var require_src = __commonJS({
|
|
|
8174
9109
|
openzeppelin: require_openzeppelin()
|
|
8175
9110
|
}
|
|
8176
9111
|
};
|
|
9112
|
+
var { SubgraphService } = require_client();
|
|
9113
|
+
var { IPFSService } = require_client2();
|
|
9114
|
+
var serviceErrors = require_errors2();
|
|
9115
|
+
var { SimpleCache } = require_cache();
|
|
9116
|
+
var { retryWithBackoff } = require_retry();
|
|
9117
|
+
var hooks = null;
|
|
9118
|
+
try {
|
|
9119
|
+
hooks = require_hooks();
|
|
9120
|
+
} catch (err) {
|
|
9121
|
+
}
|
|
8177
9122
|
module2.exports = {
|
|
8178
9123
|
version: pkg.version,
|
|
8179
9124
|
getProvider: utils.getProvider,
|
|
@@ -8192,7 +9137,7 @@ var require_src = __commonJS({
|
|
|
8192
9137
|
personal,
|
|
8193
9138
|
treasury,
|
|
8194
9139
|
boost,
|
|
8195
|
-
bond
|
|
9140
|
+
// bond module removed; bonds deprecated in CLI/SDK
|
|
8196
9141
|
subgraph,
|
|
8197
9142
|
utils: { ...utils, privateTx, safe },
|
|
8198
9143
|
bounty,
|
|
@@ -8204,6 +9149,18 @@ var require_src = __commonJS({
|
|
|
8204
9149
|
errors,
|
|
8205
9150
|
doppler,
|
|
8206
9151
|
adapters,
|
|
9152
|
+
// New service layer exports
|
|
9153
|
+
services: {
|
|
9154
|
+
SubgraphService,
|
|
9155
|
+
IPFSService
|
|
9156
|
+
},
|
|
9157
|
+
serviceErrors,
|
|
9158
|
+
serviceUtils: {
|
|
9159
|
+
SimpleCache,
|
|
9160
|
+
retryWithBackoff
|
|
9161
|
+
},
|
|
9162
|
+
// React hooks (optional - requires react + swr peer dependencies)
|
|
9163
|
+
hooks,
|
|
8207
9164
|
// Legacy exports (deprecated): maintain compatibility while consumers migrate
|
|
8208
9165
|
resolveGovernanceContext: async function legacyResolveGovernanceContext(args) {
|
|
8209
9166
|
console.warn("[@sage-protocol/sdk] resolveGovernanceContext is deprecated. Use governance helpers instead.");
|