@sage-protocol/sdk 0.1.18 → 0.1.23
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 +98 -1
- package/dist/browser/index.mjs +43 -18
- package/dist/index.cjs +2972 -183
- package/dist/index.mjs +2968 -179
- package/dist/node/index.cjs +2968 -179
- package/dist/node/index.mjs +2968 -179
- package/package.json +1 -1
- package/types/index.d.ts +540 -6
package/README.md
CHANGED
|
@@ -62,6 +62,7 @@ Module Overview
|
|
|
62
62
|
| `timelock` | Min delay, queued operation inspection, schedule/cancel builders | Safe workflows, monitoring |
|
|
63
63
|
| `factory` | Config reads, template enumeration, SubDAO create/fork builders | Launch tooling, analytics |
|
|
64
64
|
| `library` | Manifest listings & scoped ownership checks | Prompt library browsers |
|
|
65
|
+
| `lineage` | Library fork ancestry, per-library fork fees | Fork tracking, royalty analytics |
|
|
65
66
|
| `prompt` | Prompt metadata, fork counts, usage counters | UI prompt catalogues, agent prompt selection |
|
|
66
67
|
| `ipfs` | Upload helpers + discovery/governance worker APIs | CLI sandbox, dashboards, worker automation |
|
|
67
68
|
| `subdao` | Discovery, staking helpers, per-user stats | SubDAO directories, onboarding |
|
|
@@ -371,6 +372,8 @@ Important
|
|
|
371
372
|
Deprecations
|
|
372
373
|
------------
|
|
373
374
|
- `resolveGovernanceContext` is still exported for compatibility but now logs a deprecation warning. Use the richer `governance` + `subdao` helpers instead.
|
|
375
|
+
- **Prompt-level forking** is deprecated. On-chain prompt forking via `SubDAO.forkPrompt()` and `SubDAO.forkPromptWithStable()` is no longer supported. Use `forked_from` metadata in prompt frontmatter instead. Library-level forks (entire SubDAOs) remain fully supported via the factory.
|
|
376
|
+
- **Prompt fork fees** (stable fee configuration for prompt forks) have been removed. Per-library SXXX fork fees are now the standard model for monetizing library forks. See the `lineage` module documentation above.
|
|
374
377
|
|
|
375
378
|
Next Phases
|
|
376
379
|
-----------
|
|
@@ -402,7 +405,7 @@ const mapped = await sdk.factory.getSubDAORegistry({ provider, factory, subdao }
|
|
|
402
405
|
|
|
403
406
|
Registry preflight as timelock
|
|
404
407
|
```js
|
|
405
|
-
const { to, data } = sdk.library.
|
|
408
|
+
const { to, data } = sdk.library.buildUpdateLibraryTx({ registry, subdao, manifestCID, version: '1.0.0' });
|
|
406
409
|
const sim = await sdk.library.simulateAsTimelock({ provider, registry, to, data, timelock });
|
|
407
410
|
if (!sim.ok) throw new Error(`registry preflight failed: ${sim.error?.message}`);
|
|
408
411
|
```
|
|
@@ -649,6 +652,100 @@ const profileCid = 'bafy...'; // CID of dao-profile.json on IPFS
|
|
|
649
652
|
const { to, data, value } = sdk.subdao.buildSetProfileCidTx({ subdao: res.subdao, profileCid });
|
|
650
653
|
// Example: schedule via timelock or propose via Governor, depending on your governance mode
|
|
651
654
|
```
|
|
655
|
+
|
|
656
|
+
# Library Lineage and Fork Fees
|
|
657
|
+
|
|
658
|
+
The `lineage` module provides helpers for tracking library fork relationships and per-library SXXX fork fees.
|
|
659
|
+
|
|
660
|
+
## Fork Ancestry
|
|
661
|
+
|
|
662
|
+
Libraries can be forked from other libraries. The `lineage` module tracks this ancestry:
|
|
663
|
+
|
|
664
|
+
```js
|
|
665
|
+
import sdk from '@sage-protocol/sdk';
|
|
666
|
+
|
|
667
|
+
const provider = sdk.getProvider({ rpcUrl: process.env.RPC_URL });
|
|
668
|
+
const registry = '0xLibraryRegistry';
|
|
669
|
+
const subdao = '0xSubDAO';
|
|
670
|
+
|
|
671
|
+
// Check if a library was forked from another
|
|
672
|
+
const isFork = await sdk.lineage.isFork({ provider, registry, subdao });
|
|
673
|
+
// → true if this library has a parent
|
|
674
|
+
|
|
675
|
+
// Get the parent library (null if original)
|
|
676
|
+
const parent = await sdk.lineage.getParentLibrary({ provider, registry, subdao });
|
|
677
|
+
// → '0xParentSubDAO' or null
|
|
678
|
+
|
|
679
|
+
// Get full ancestry chain from root to current
|
|
680
|
+
const chain = await sdk.lineage.getLineageChain({ provider, registry, subdao });
|
|
681
|
+
// → { chain: ['0xRoot', '0xChild', '0xGrandchild'], depth: 2, root: '0xRoot' }
|
|
682
|
+
```
|
|
683
|
+
|
|
684
|
+
## Per-Library Fork Fees
|
|
685
|
+
|
|
686
|
+
Library owners can set an SXXX fee for forking their library. This fee is paid by the forker to the parent library's treasury when creating a forked SubDAO.
|
|
687
|
+
|
|
688
|
+
```js
|
|
689
|
+
// Get the SXXX fork fee for a library (0n = free fork)
|
|
690
|
+
const fee = await sdk.lineage.getLibraryForkFee({ provider, registry, subdao });
|
|
691
|
+
// → 1000000000000000000n (1 SXXX in wei)
|
|
692
|
+
|
|
693
|
+
// Get comprehensive library info including fork fee
|
|
694
|
+
const info = await sdk.lineage.getLibraryInfo({ provider, registry, subdao });
|
|
695
|
+
// → {
|
|
696
|
+
// parentDAO: '0xParent' | null,
|
|
697
|
+
// forkFee: 1000000000000000000n,
|
|
698
|
+
// manifestCID: 'Qm...',
|
|
699
|
+
// version: '1.0.0'
|
|
700
|
+
// }
|
|
701
|
+
```
|
|
702
|
+
|
|
703
|
+
## Setting Fork Fees (via Governance)
|
|
704
|
+
|
|
705
|
+
Fork fees can only be set by the library's timelock. This is typically done through a governance proposal:
|
|
706
|
+
|
|
707
|
+
```js
|
|
708
|
+
import { ethers } from 'ethers';
|
|
709
|
+
|
|
710
|
+
// Build the setLibraryForkFee transaction (for use in a proposal)
|
|
711
|
+
const registryIface = new ethers.Interface([
|
|
712
|
+
'function setLibraryForkFee(address dao, uint256 fee)'
|
|
713
|
+
]);
|
|
714
|
+
|
|
715
|
+
const feeInWei = ethers.parseUnits('10', 18); // 10 SXXX
|
|
716
|
+
const calldata = registryIface.encodeFunctionData('setLibraryForkFee', [subdao, feeInWei]);
|
|
717
|
+
|
|
718
|
+
// Include in a governance proposal
|
|
719
|
+
const proposeTx = sdk.governance.buildProposeTx({
|
|
720
|
+
governor,
|
|
721
|
+
targets: [registry],
|
|
722
|
+
values: [0n],
|
|
723
|
+
calldatas: [calldata],
|
|
724
|
+
descriptionOrHash: 'Set library fork fee to 10 SXXX'
|
|
725
|
+
});
|
|
726
|
+
```
|
|
727
|
+
|
|
728
|
+
## Fork Fee Flow
|
|
729
|
+
|
|
730
|
+
When a SubDAO is forked via the factory:
|
|
731
|
+
|
|
732
|
+
1. Factory reads the parent library's fork fee from LibraryRegistry
|
|
733
|
+
2. If fee > 0, SXXX is transferred from forker to parent's treasury
|
|
734
|
+
3. `LibraryForkFeePaid(parentDAO, forker, amount)` event is emitted
|
|
735
|
+
4. Fork proceeds with standard SubDAO creation
|
|
736
|
+
|
|
737
|
+
Note: Forkers must approve SXXX to the factory before forking a library with a fee set.
|
|
738
|
+
|
|
739
|
+
## Deprecation: Prompt-Level Forks
|
|
740
|
+
|
|
741
|
+
On-chain prompt forking is deprecated. Prompt forks are now tracked via metadata only:
|
|
742
|
+
|
|
743
|
+
1. Add `forked_from: <original-cid>` to your prompt frontmatter
|
|
744
|
+
2. Upload the new prompt to IPFS
|
|
745
|
+
3. Register via governance proposal
|
|
746
|
+
|
|
747
|
+
Library-level forks (entire SubDAOs) continue to work and are tracked via `LibraryRegistry.registerForkedDAO()`.
|
|
748
|
+
|
|
652
749
|
# Governance Adapter (OpenZeppelin)
|
|
653
750
|
|
|
654
751
|
Normalize proposals/timelines across OZ governors with a compact adapter, inspired by Boardroom’s pattern.
|
package/dist/browser/index.mjs
CHANGED
|
@@ -14,7 +14,7 @@ var require_package = __commonJS({
|
|
|
14
14
|
"package.json"(exports, module) {
|
|
15
15
|
module.exports = {
|
|
16
16
|
name: "@sage-protocol/sdk",
|
|
17
|
-
version: "0.1.
|
|
17
|
+
version: "0.1.23",
|
|
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",
|
|
@@ -119,7 +119,12 @@ var require_abi = __commonJS({
|
|
|
119
119
|
"function userForkCount(address) view returns (uint256)",
|
|
120
120
|
"function forkCount(string) view returns (uint256)",
|
|
121
121
|
"function stake(uint256)",
|
|
122
|
-
"function unstake(uint256)"
|
|
122
|
+
"function unstake(uint256)",
|
|
123
|
+
// Fork functions
|
|
124
|
+
"function forkSubDAO(string,string)",
|
|
125
|
+
"function forkSubDAO(string,string,bool)",
|
|
126
|
+
"function forkSubDAOWithStable(string,string,(uint256,uint256,uint8,bytes32,bytes32))",
|
|
127
|
+
"function forkSubDAOWithStable(string,string,(uint256,uint256,uint8,bytes32,bytes32),bool)"
|
|
123
128
|
];
|
|
124
129
|
var Factory = [
|
|
125
130
|
"event SubDAOGovernanceDeployed(address indexed subDAO, address indexed governor, address timelock, address treasury)"
|
|
@@ -130,7 +135,6 @@ var require_abi = __commonJS({
|
|
|
130
135
|
"function stableCreationFee() view returns (uint256)",
|
|
131
136
|
"function stableFeeReceiver() view returns (address)",
|
|
132
137
|
"function stableCreationEnabled() view returns (bool)",
|
|
133
|
-
"function stablePromptForkFee() view returns (uint256)",
|
|
134
138
|
"function stableForkFee() view returns (uint256)",
|
|
135
139
|
// Core factory reads
|
|
136
140
|
"function timelockMinDelay() view returns (uint256)",
|
|
@@ -160,8 +164,8 @@ var require_abi = __commonJS({
|
|
|
160
164
|
"function createSubDAOOperatorWithStableAdvanced(string name, string description, uint8 accessModel, uint256 minStakeAmount, address operatorExecutor, address operatorAdmin, bool anyoneExec, bool governorProposer, (uint256 value,uint256 deadline,uint8 v,bytes32 r,bytes32 s) permit) returns (address subDAO, address registry)",
|
|
161
165
|
"function createSubDAOOperator(string name, string description, uint8 accessModel, uint256 minStakeAmount, uint256 burnAmount, address operatorExecutor, address operatorAdmin) returns (address subDAO, address registry)",
|
|
162
166
|
"function createSubDAOOperatorAdvanced(string name, string description, uint8 accessModel, uint256 minStakeAmount, uint256 burnAmount, address operatorExecutor, address operatorAdmin, bool anyoneExec, bool governorProposer) returns (address subDAO, address registry)",
|
|
163
|
-
"function createForkedSubDAO(string newName, string newDescription, string originalName, address originalSubDAO, address forker) returns (address subDAO, address registry)",
|
|
164
|
-
"function createForkedSubDAOWithStable(string newName, string newDescription, string originalName, address originalSubDAO, address forker, uint64 authorizationNonce, (uint256 value,uint256 deadline,uint8 v,bytes32 r,bytes32 s) permit) returns (address subDAO, address registry)"
|
|
167
|
+
"function createForkedSubDAO(string newName, string newDescription, string originalName, address originalSubDAO, address forker, bool copyLibrary) returns (address subDAO, address registry)",
|
|
168
|
+
"function createForkedSubDAOWithStable(string newName, string newDescription, string originalName, address originalSubDAO, address forker, uint64 authorizationNonce, (uint256 value,uint256 deadline,uint8 v,bytes32 r,bytes32 s) permit, bool copyLibrary) returns (address subDAO, address registry)"
|
|
165
169
|
];
|
|
166
170
|
var TemplateModule = [
|
|
167
171
|
"function getActiveTemplates() view returns (uint256[])",
|
|
@@ -172,13 +176,19 @@ var require_abi = __commonJS({
|
|
|
172
176
|
"function maxCreationBurn() view returns (uint256)"
|
|
173
177
|
];
|
|
174
178
|
var LibraryRegistry = [
|
|
175
|
-
"function libraryByDAO(address) view returns (string manifestCID, address lastUpdater, uint256 lastUpdated, string version)",
|
|
179
|
+
"function libraryByDAO(address) view returns (string manifestCID, address lastUpdater, uint256 lastUpdated, string version, address forkedFromDAO, uint256 sxxxForkFee)",
|
|
176
180
|
"function daoTimelock(address) view returns (address)",
|
|
177
|
-
"function getLibrary(address) view returns (tuple(string manifestCID, address lastUpdater, uint256 lastUpdated, string version))",
|
|
181
|
+
"function getLibrary(address) view returns (tuple(string manifestCID, address lastUpdater, uint256 lastUpdated, string version, address forkedFromDAO, uint256 sxxxForkFee))",
|
|
182
|
+
"function getLibraryForkFee(address dao) view returns (uint256)",
|
|
183
|
+
"function setLibraryForkFee(address dao, uint256 fee)",
|
|
178
184
|
"function updateLibrary(address dao, string manifestCID, string version)",
|
|
179
185
|
"function registerDAO(address dao, address timelock)",
|
|
186
|
+
"function registerForkedDAO(address childDAO, address childTimelock, address parentDAO, string manifestCID, string version)",
|
|
187
|
+
"function initializeLibraryFromFork(address sourceDao, address forkedDao)",
|
|
180
188
|
"event LibraryUpdated(address indexed dao, string manifestCID, address indexed timelock, string version)",
|
|
181
|
-
"event DAORegistered(address indexed dao, address indexed timelock)"
|
|
189
|
+
"event DAORegistered(address indexed dao, address indexed timelock)",
|
|
190
|
+
"event LibraryForked(address indexed sourceDao, address indexed forkedDao, string manifestCID)",
|
|
191
|
+
"event LibraryForkFeeUpdated(address indexed dao, uint256 fee)"
|
|
182
192
|
];
|
|
183
193
|
var PromptRegistry = [
|
|
184
194
|
"function prompts(string key) view returns (string cid, uint256 version, uint256 timestamp, address author, string forkedFromCID, address originalAuthor, bool isFork, uint256 forkDepth)",
|
|
@@ -1103,19 +1113,37 @@ var require_subgraph = __commonJS({
|
|
|
1103
1113
|
updatedAt: Number(p.updatedAt || 0)
|
|
1104
1114
|
};
|
|
1105
1115
|
},
|
|
1106
|
-
async getProposalById({ url, id }) {
|
|
1116
|
+
async getProposalById({ url, id, governor }) {
|
|
1107
1117
|
if (!url) throw new Error("subgraph url required");
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1118
|
+
let p = null;
|
|
1119
|
+
if (governor) {
|
|
1120
|
+
const govLower = String(governor).toLowerCase();
|
|
1121
|
+
const compositeId = `${govLower}-${String(id)}`;
|
|
1122
|
+
const doc = `query($id: ID!){ proposal(id:$id){ id proposer description createdAt updatedAt state eta targets values calldatas } }`;
|
|
1123
|
+
const data = await query(url, doc, { id: compositeId });
|
|
1124
|
+
p = data?.proposal;
|
|
1125
|
+
}
|
|
1126
|
+
if (!p && governor) {
|
|
1127
|
+
const govLower = String(governor).toLowerCase();
|
|
1128
|
+
const doc = `query($gov: Bytes!, $first: Int!){ proposals(where:{governor:$gov}, first:$first, orderBy:createdAt, orderDirection:desc){ id proposer description createdAt updatedAt state eta targets values calldatas } }`;
|
|
1129
|
+
const data = await query(url, doc, { gov: govLower, first: 100 });
|
|
1130
|
+
const proposals = data?.proposals || [];
|
|
1131
|
+
p = proposals.find((prop) => {
|
|
1132
|
+
const parts = String(prop.id || "").split("-");
|
|
1133
|
+
const propId = parts.length > 1 ? parts[parts.length - 1] : prop.id;
|
|
1134
|
+
return String(propId) === String(id) || propId && String(BigInt(propId)) === String(BigInt(id));
|
|
1135
|
+
});
|
|
1136
|
+
}
|
|
1111
1137
|
if (!p) return null;
|
|
1112
1138
|
try {
|
|
1113
1139
|
const proposer = safeGetAddress(p.proposer);
|
|
1114
1140
|
if (!proposer) return null;
|
|
1115
1141
|
const targets = (p.targets || []).map((t) => safeGetAddress(t)).filter(Boolean);
|
|
1116
1142
|
if (!targets.length && (p.targets || []).length) return null;
|
|
1143
|
+
const idParts = String(p.id || "").split("-");
|
|
1144
|
+
const actualId = idParts.length > 1 ? idParts[idParts.length - 1] : p.id;
|
|
1117
1145
|
return {
|
|
1118
|
-
id: BigInt(
|
|
1146
|
+
id: BigInt(actualId),
|
|
1119
1147
|
proposer,
|
|
1120
1148
|
description: p.description || "",
|
|
1121
1149
|
createdAt: Number(p.createdAt || 0),
|
|
@@ -1383,7 +1411,6 @@ var require_ipfs = __commonJS({
|
|
|
1383
1411
|
headers["X-Wallet-Address"] = auth.address;
|
|
1384
1412
|
headers["X-Wallet-Signature"] = auth.signature;
|
|
1385
1413
|
headers["X-Wallet-Nonce"] = auth.nonce;
|
|
1386
|
-
headers["X-Wallet-Message"] = auth.message;
|
|
1387
1414
|
}
|
|
1388
1415
|
return { headers, auth };
|
|
1389
1416
|
}
|
|
@@ -1404,8 +1431,7 @@ var require_ipfs = __commonJS({
|
|
|
1404
1431
|
...extraHeaders,
|
|
1405
1432
|
"X-Wallet-Address": auth.address,
|
|
1406
1433
|
"X-Wallet-Signature": auth.signature,
|
|
1407
|
-
"X-Wallet-Nonce": auth.nonce
|
|
1408
|
-
"X-Wallet-Message": auth.message
|
|
1434
|
+
"X-Wallet-Nonce": auth.nonce
|
|
1409
1435
|
};
|
|
1410
1436
|
return { headers, auth };
|
|
1411
1437
|
}
|
|
@@ -1790,8 +1816,7 @@ var require_ipfs = __commonJS({
|
|
|
1790
1816
|
"Content-Type": "application/json",
|
|
1791
1817
|
"X-Wallet-Address": address,
|
|
1792
1818
|
"X-Wallet-Signature": signature,
|
|
1793
|
-
"X-Wallet-Nonce": nonce
|
|
1794
|
-
"X-Wallet-Message": message
|
|
1819
|
+
"X-Wallet-Nonce": nonce
|
|
1795
1820
|
};
|
|
1796
1821
|
let verified = false;
|
|
1797
1822
|
try {
|