@sage-protocol/sdk 0.1.17 → 0.1.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -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
  -----------
@@ -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.
@@ -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",
17
+ version: "0.1.21",
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",
@@ -130,7 +130,6 @@ var require_abi = __commonJS({
130
130
  "function stableCreationFee() view returns (uint256)",
131
131
  "function stableFeeReceiver() view returns (address)",
132
132
  "function stableCreationEnabled() view returns (bool)",
133
- "function stablePromptForkFee() view returns (uint256)",
134
133
  "function stableForkFee() view returns (uint256)",
135
134
  // Core factory reads
136
135
  "function timelockMinDelay() view returns (uint256)",
@@ -172,13 +171,18 @@ var require_abi = __commonJS({
172
171
  "function maxCreationBurn() view returns (uint256)"
173
172
  ];
174
173
  var LibraryRegistry = [
175
- "function libraryByDAO(address) view returns (string manifestCID, address lastUpdater, uint256 lastUpdated, string version)",
174
+ "function libraryByDAO(address) view returns (string manifestCID, address lastUpdater, uint256 lastUpdated, string version, address forkedFromDAO, uint256 sxxxForkFee)",
176
175
  "function daoTimelock(address) view returns (address)",
177
- "function getLibrary(address) view returns (tuple(string manifestCID, address lastUpdater, uint256 lastUpdated, string version))",
176
+ "function getLibrary(address) view returns (tuple(string manifestCID, address lastUpdater, uint256 lastUpdated, string version, address forkedFromDAO, uint256 sxxxForkFee))",
177
+ "function getLibraryForkFee(address dao) view returns (uint256)",
178
+ "function setLibraryForkFee(address dao, uint256 fee)",
178
179
  "function updateLibrary(address dao, string manifestCID, string version)",
179
180
  "function registerDAO(address dao, address timelock)",
181
+ "function registerForkedDAO(address childDAO, address childTimelock, address parentDAO, string manifestCID, string version)",
180
182
  "event LibraryUpdated(address indexed dao, string manifestCID, address indexed timelock, string version)",
181
- "event DAORegistered(address indexed dao, address indexed timelock)"
183
+ "event DAORegistered(address indexed dao, address indexed timelock)",
184
+ "event LibraryForked(address indexed parentDAO, address indexed childDAO)",
185
+ "event LibraryForkFeeUpdated(address indexed dao, uint256 fee)"
182
186
  ];
183
187
  var PromptRegistry = [
184
188
  "function prompts(string key) view returns (string cid, uint256 version, uint256 timestamp, address author, string forkedFromCID, address originalAuthor, bool isFork, uint256 forkDepth)",
@@ -293,6 +297,186 @@ var require_abi = __commonJS({
293
297
  "function create(uint256 proposalId, address token, uint256 perVoter, uint256 maxVoters)",
294
298
  "function fund(uint256 proposalId, uint256 amount)"
295
299
  ];
300
+ var VotingMultiplierNFT = [
301
+ // Constants
302
+ "function MINTER_ROLE() view returns (bytes32)",
303
+ "function MAX_NFTS_PER_ACCOUNT() view returns (uint256)",
304
+ // Tier Management
305
+ "function createTier(address dao, string name, uint256 multiplier, uint256 maxSupply, uint256 price) returns (uint256 tierId)",
306
+ "function getTier(uint256 tierId) view returns (tuple(string name, uint256 multiplier, uint256 maxSupply, uint256 minted, uint256 price, address dao))",
307
+ "function tierCount() view returns (uint256)",
308
+ "function tiers(uint256) view returns (string name, uint256 multiplier, uint256 maxSupply, uint256 minted, uint256 price, address dao)",
309
+ // Minting
310
+ "function mint(address to, uint256 tierId, string uri) returns (uint256 tokenId)",
311
+ "function publicMint(uint256 tierId, string uri) payable returns (uint256 tokenId)",
312
+ // Multiplier Functions
313
+ "function getMultiplier(address account, address dao) view returns (uint256)",
314
+ "function getPastMultiplier(address account, address dao, uint256 timepoint) view returns (uint256)",
315
+ "function getTokenMultiplier(uint256 tokenId) view returns (uint256)",
316
+ "function getTokenDAO(uint256 tokenId) view returns (address)",
317
+ // Token Info
318
+ "function tokenMultiplier(uint256) view returns (uint256)",
319
+ "function tokenDAO(uint256) view returns (address)",
320
+ "function tokenTier(uint256) view returns (uint256)",
321
+ "function getTokenInfo(uint256 tokenId) view returns (address owner, uint256 tierId, uint256 multiplier, string uri)",
322
+ // ERC721 Standard
323
+ "function balanceOf(address owner) view returns (uint256)",
324
+ "function ownerOf(uint256 tokenId) view returns (address)",
325
+ "function tokenOfOwnerByIndex(address owner, uint256 index) view returns (uint256)",
326
+ "function tokenURI(uint256 tokenId) view returns (string)",
327
+ "function transferFrom(address from, address to, uint256 tokenId)",
328
+ "function safeTransferFrom(address from, address to, uint256 tokenId)",
329
+ "function approve(address to, uint256 tokenId)",
330
+ "function setApprovalForAll(address operator, bool approved)",
331
+ "function getApproved(uint256 tokenId) view returns (address)",
332
+ "function isApprovedForAll(address owner, address operator) view returns (bool)",
333
+ // Admin
334
+ "function withdrawFunds(address to)",
335
+ "function grantRole(bytes32 role, address account)",
336
+ "function revokeRole(bytes32 role, address account)",
337
+ "function hasRole(bytes32 role, address account) view returns (bool)",
338
+ // Events
339
+ "event TierCreated(uint256 indexed tierId, address indexed dao, string name, uint256 multiplier, uint256 maxSupply, uint256 price)",
340
+ "event NFTMinted(address indexed to, uint256 indexed tokenId, address indexed dao, uint256 tierId, uint256 multiplier)",
341
+ "event Transfer(address indexed from, address indexed to, uint256 indexed tokenId)"
342
+ ];
343
+ var MultipliedVotes = [
344
+ // Core IVotes Interface
345
+ "function getVotes(address account) view returns (uint256)",
346
+ "function getPastVotes(address account, uint256 timepoint) view returns (uint256)",
347
+ "function getPastTotalSupply(uint256 timepoint) view returns (uint256)",
348
+ "function delegates(address account) view returns (address)",
349
+ "function delegate(address delegatee)",
350
+ "function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s)",
351
+ // IERC6372 Clock Interface
352
+ "function clock() view returns (uint48)",
353
+ "function CLOCK_MODE() view returns (string)",
354
+ // View Helpers
355
+ "function getVotingBreakdown(address account) view returns (uint256 baseVotes, uint256 multiplier, uint256 effectiveVotes)",
356
+ "function getPastVotingBreakdown(address account, uint256 timepoint) view returns (uint256 baseVotes, uint256 multiplier, uint256 effectiveVotes)",
357
+ "function hasMultiplierBonus(address account) view returns (bool)",
358
+ // Immutable Config
359
+ "function baseToken() view returns (address)",
360
+ "function multiplierNFT() view returns (address)",
361
+ "function dao() view returns (address)",
362
+ "function BASIS() view returns (uint256)"
363
+ ];
364
+ var SageAuctionHouse = [
365
+ // Core Auction Functions
366
+ "function createBid(uint256 nftId) payable",
367
+ "function settleCurrentAndCreateNewAuction()",
368
+ "function settleAuction()",
369
+ "function createAuction()",
370
+ // Current Auction State
371
+ "function auction() view returns (uint256 nftId, uint256 amount, uint256 startTime, uint256 endTime, address bidder, bool settled)",
372
+ // Configuration
373
+ "function nft() view returns (address)",
374
+ "function treasury() view returns (address)",
375
+ "function weth() view returns (address)",
376
+ "function timeBuffer() view returns (uint256)",
377
+ "function reservePrice() view returns (uint256)",
378
+ "function minBidIncrementPercentage() view returns (uint256)",
379
+ "function duration() view returns (uint256)",
380
+ "function mintTierId() view returns (uint256)",
381
+ "function defaultTokenURI() view returns (string)",
382
+ // Admin Functions
383
+ "function pause()",
384
+ "function unpause()",
385
+ "function paused() view returns (bool)",
386
+ "function setTimeBuffer(uint256 _timeBuffer)",
387
+ "function setReservePrice(uint256 _reservePrice)",
388
+ "function setMinBidIncrementPercentage(uint256 _minBidIncrementPercentage)",
389
+ "function setDuration(uint256 _duration)",
390
+ "function setMintTierId(uint256 _tierId)",
391
+ "function setDefaultTokenURI(string _uri)",
392
+ "function owner() view returns (address)",
393
+ "function transferOwnership(address newOwner)",
394
+ // Events
395
+ "event AuctionCreated(uint256 indexed nftId, uint256 startTime, uint256 endTime)",
396
+ "event AuctionBid(uint256 indexed nftId, address sender, uint256 value, bool extended)",
397
+ "event AuctionExtended(uint256 indexed nftId, uint256 endTime)",
398
+ "event AuctionSettled(uint256 indexed nftId, address winner, uint256 amount)",
399
+ "event AuctionTimeBufferUpdated(uint256 timeBuffer)",
400
+ "event AuctionReservePriceUpdated(uint256 reservePrice)",
401
+ "event AuctionMinBidIncrementPercentageUpdated(uint256 minBidIncrementPercentage)",
402
+ "event AuctionDurationUpdated(uint256 duration)"
403
+ ];
404
+ var SimpleBountySystem = [
405
+ // Constants
406
+ "function GOVERNANCE_ROLE() view returns (bytes32)",
407
+ "function MAX_SUBMISSIONS_PER_BOUNTY() view returns (uint256)",
408
+ // Bounty Creation
409
+ "function createBounty(string title, string description, string ipfsCID, uint256 reward, uint256 deadline) returns (uint256)",
410
+ "function createBountyAdvanced(string title, string description, string ipfsCID, uint256 reward, uint256 deadline, uint256 votingDuration, uint8 mode, uint8 libraryAction, address assignee, string libraryKey) returns (uint256)",
411
+ // Submission & Claiming
412
+ "function claimBounty(uint256 bountyId)",
413
+ "function submitEntry(uint256 bountyId, string promptIPFS, string deliverableIPFS) returns (uint256)",
414
+ "function completeBounty(uint256 bountyId, string deliverableIPFS)",
415
+ // Voting (COMPETITIVE mode)
416
+ "function startVoting(uint256 bountyId)",
417
+ "function vote(uint256 bountyId, uint256 submissionId)",
418
+ "function finalizeCompetitive(uint256 bountyId)",
419
+ // Approval
420
+ "function approveSubmission(uint256 bountyId, uint256 submissionId)",
421
+ "function approveBountyCompletion(uint256 bountyId, string)",
422
+ // Cancellation & Expiry
423
+ "function cancelBounty(uint256 bountyId)",
424
+ "function expireBounty(uint256 bountyId)",
425
+ // Reward Management
426
+ "function increaseReward(uint256 bountyId, uint256 additionalReward)",
427
+ "function slashCreator(uint256 bountyId, uint256 amount, address to)",
428
+ // Gate Management
429
+ "function setGates(uint256 bountyId, uint256 minTokenBalance, uint256 requiredBadgeId)",
430
+ "function addToWhitelist(uint256 bountyId, address[] addresses)",
431
+ "function removeFromWhitelist(uint256 bountyId, address[] addresses)",
432
+ "function canSubmit(uint256 bountyId, address submitter) view returns (bool)",
433
+ // View Functions
434
+ "function getBounty(uint256 bountyId) view returns (tuple(address creator, uint256 id, string title, string description, string ipfsCID, uint256 reward, uint256 creatorDeposit, uint256 minContributorLevel, uint256 minTokenBalance, uint256 requiredBadgeId, uint256 deadline, uint256 votingEndTime, uint256 snapshotBlock, uint8 mode, uint8 status, uint8 libraryAction, address assignee, address winner, uint256 winningSubmissionId, string libraryKey, uint256 governanceProposalId))",
435
+ "function getSubmission(uint256 bountyId, uint256 submissionId) view returns (tuple(uint256 id, uint256 bountyId, address submitter, string promptIPFS, string deliverableIPFS, uint256 timestamp, uint256 voteCount, bool exists))",
436
+ "function getSubmissionCount(uint256 bountyId) view returns (uint256)",
437
+ "function getLeadingSubmission(uint256 bountyId) view returns (uint256 submissionId, uint256 votes)",
438
+ "function calculateStake(uint256 reward) view returns (uint256)",
439
+ // State Mappings
440
+ "function bounties(uint256) view returns (address creator, uint256 id, string title, string description, string ipfsCID, uint256 reward, uint256 creatorDeposit, uint256 minContributorLevel, uint256 minTokenBalance, uint256 requiredBadgeId, uint256 deadline, uint256 votingEndTime, uint256 snapshotBlock, uint8 mode, uint8 status, uint8 libraryAction, address assignee, address winner, uint256 winningSubmissionId, string libraryKey, uint256 governanceProposalId)",
441
+ "function nextBountyId() view returns (uint256)",
442
+ "function submissionCount(uint256) view returns (uint256)",
443
+ "function submitterToSubmission(uint256, address) view returns (uint256)",
444
+ "function hasVotedInBounty(uint256, address) view returns (bool)",
445
+ "function voterChosenSubmission(uint256, address) view returns (uint256)",
446
+ "function whitelist(uint256, address) view returns (bool)",
447
+ "function hasWhitelist(uint256) view returns (bool)",
448
+ // External Contracts
449
+ "function sxxxToken() view returns (address)",
450
+ "function contributorSystem() view returns (address)",
451
+ "function governanceConfig() view returns (address)",
452
+ "function communityTreasury() view returns (address)",
453
+ "function governanceContract() view returns (address)",
454
+ "function libraryRegistry() view returns (address)",
455
+ "function subdao() view returns (address)",
456
+ "function soulboundBadge() view returns (address)",
457
+ // Admin
458
+ "function setGovernanceContract(address _gov)",
459
+ "function setCommunityTreasury(address _treasury)",
460
+ "function setLibraryRegistry(address _registry)",
461
+ "function setSoulboundBadge(address _sbtAddress)",
462
+ "function grantRole(bytes32 role, address account)",
463
+ "function revokeRole(bytes32 role, address account)",
464
+ "function hasRole(bytes32 role, address account) view returns (bool)",
465
+ // Events
466
+ "event BountyCreated(uint256 indexed bountyId, address indexed creator, string title, uint256 reward, uint256 deposit, uint8 mode, address assignee)",
467
+ "event SubmissionReceived(uint256 indexed bountyId, uint256 indexed submissionId, address indexed submitter, string promptIPFS)",
468
+ "event BountyClaimed(uint256 indexed bountyId, address indexed claimant)",
469
+ "event BountyUnderReview(uint256 indexed bountyId, address indexed claimant, uint256 proposalId)",
470
+ "event VoteCast(uint256 indexed bountyId, uint256 indexed submissionId, address indexed voter, uint256 weight)",
471
+ "event VotingStarted(uint256 indexed bountyId, uint256 votingEndTime)",
472
+ "event BountyCompleted(uint256 indexed bountyId, address indexed winner, uint256 reward, string deliverable)",
473
+ "event BountyAutoApproved(uint256 indexed bountyId, address indexed winner)",
474
+ "event PromptAddedToLibrary(uint256 indexed bountyId, string libraryKey, string promptIPFS)",
475
+ "event BountyCancelled(uint256 indexed bountyId, address indexed creator)",
476
+ "event BountyExpired(uint256 indexed bountyId)",
477
+ "event BountyRewardIncreased(uint256 indexed bountyId, uint256 additionalReward, uint256 newTotal)",
478
+ "event CreatorSlashed(uint256 indexed bountyId, uint256 amount, address indexed to)"
479
+ ];
296
480
  var Events = {
297
481
  ProposalCreated: "event ProposalCreated(uint256 id, address proposer, address[] targets, uint256[] values, string[] signatures, bytes[] calldatas, uint256 startBlock, uint256 endBlock, string description)"
298
482
  };
@@ -315,6 +499,13 @@ var require_abi = __commonJS({
315
499
  // Protocol treasury (replaces SageTreasury)
316
500
  GovernanceBoostMerkle,
317
501
  GovernanceBoostDirect,
502
+ // Voting Multiplier System
503
+ VotingMultiplierNFT,
504
+ MultipliedVotes,
505
+ // Auction House
506
+ SageAuctionHouse,
507
+ // Bounty System
508
+ SimpleBountySystem,
318
509
  Events
319
510
  };
320
511
  }
@@ -1196,7 +1387,6 @@ var require_ipfs = __commonJS({
1196
1387
  headers["X-Wallet-Address"] = auth.address;
1197
1388
  headers["X-Wallet-Signature"] = auth.signature;
1198
1389
  headers["X-Wallet-Nonce"] = auth.nonce;
1199
- headers["X-Wallet-Message"] = auth.message;
1200
1390
  }
1201
1391
  return { headers, auth };
1202
1392
  }
@@ -1217,8 +1407,7 @@ var require_ipfs = __commonJS({
1217
1407
  ...extraHeaders,
1218
1408
  "X-Wallet-Address": auth.address,
1219
1409
  "X-Wallet-Signature": auth.signature,
1220
- "X-Wallet-Nonce": auth.nonce,
1221
- "X-Wallet-Message": auth.message
1410
+ "X-Wallet-Nonce": auth.nonce
1222
1411
  };
1223
1412
  return { headers, auth };
1224
1413
  }
@@ -1603,8 +1792,7 @@ var require_ipfs = __commonJS({
1603
1792
  "Content-Type": "application/json",
1604
1793
  "X-Wallet-Address": address,
1605
1794
  "X-Wallet-Signature": signature,
1606
- "X-Wallet-Nonce": nonce,
1607
- "X-Wallet-Message": message
1795
+ "X-Wallet-Nonce": nonce
1608
1796
  };
1609
1797
  let verified = false;
1610
1798
  try {