@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 +97 -0
- package/dist/browser/index.mjs +198 -10
- package/dist/index.cjs +2376 -94
- package/dist/index.mjs +2372 -90
- package/dist/node/index.cjs +2372 -90
- package/dist/node/index.mjs +2372 -90
- package/package.json +1 -1
- package/types/index.d.ts +391 -1
package/dist/index.cjs
CHANGED
|
@@ -14,7 +14,7 @@ var require_package = __commonJS({
|
|
|
14
14
|
"package.json"(exports2, module2) {
|
|
15
15
|
module2.exports = {
|
|
16
16
|
name: "@sage-protocol/sdk",
|
|
17
|
-
version: "0.1.
|
|
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
|
}
|
|
@@ -672,6 +863,409 @@ var require_subgraph = __commonJS({
|
|
|
672
863
|
listLibraries,
|
|
673
864
|
getSubdaoLibraries,
|
|
674
865
|
getSubdaoPrompts,
|
|
866
|
+
/**
|
|
867
|
+
* Bounty dashboards (SimpleBountySystem)
|
|
868
|
+
*/
|
|
869
|
+
async listBounties({ url, first = 50, skip = 0, status = null, creator = null }) {
|
|
870
|
+
if (!url) throw new Error("subgraph url required");
|
|
871
|
+
const filters = [];
|
|
872
|
+
if (status != null) filters.push(`status: ${Number(status)}`);
|
|
873
|
+
if (creator) {
|
|
874
|
+
const addr = safeGetAddress(creator);
|
|
875
|
+
if (!addr) throw new Error("invalid creator address");
|
|
876
|
+
filters.push(`creator: "${addr.toLowerCase()}"`);
|
|
877
|
+
}
|
|
878
|
+
const where = filters.length ? `where:{ ${filters.join(", ")} }` : "";
|
|
879
|
+
const doc = `
|
|
880
|
+
query($first:Int!,$skip:Int!){
|
|
881
|
+
bounties(
|
|
882
|
+
${where}
|
|
883
|
+
first:$first
|
|
884
|
+
skip:$skip
|
|
885
|
+
orderBy: createdAt
|
|
886
|
+
orderDirection: desc
|
|
887
|
+
){
|
|
888
|
+
id
|
|
889
|
+
contract
|
|
890
|
+
bountyId
|
|
891
|
+
creator
|
|
892
|
+
title
|
|
893
|
+
reward
|
|
894
|
+
creatorDeposit
|
|
895
|
+
mode
|
|
896
|
+
status
|
|
897
|
+
libraryAction
|
|
898
|
+
assignee
|
|
899
|
+
winner
|
|
900
|
+
winningSubmissionId
|
|
901
|
+
libraryKey
|
|
902
|
+
deadline
|
|
903
|
+
votingEndTime
|
|
904
|
+
createdAt
|
|
905
|
+
updatedAt
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
`;
|
|
909
|
+
const data = await query(url, doc, {
|
|
910
|
+
first: Math.min(Math.max(1, Number(first || 50)), 200),
|
|
911
|
+
skip: Number(skip || 0)
|
|
912
|
+
});
|
|
913
|
+
return mapSafe(data?.bounties, (row) => {
|
|
914
|
+
const contract = safeGetAddress(row.contract);
|
|
915
|
+
const creatorAddr = safeGetAddress(row.creator);
|
|
916
|
+
const assignee = row.assignee ? safeGetAddress(row.assignee) : null;
|
|
917
|
+
const winner = row.winner ? safeGetAddress(row.winner) : null;
|
|
918
|
+
if (!contract || !creatorAddr) return null;
|
|
919
|
+
return {
|
|
920
|
+
id: String(row.id),
|
|
921
|
+
contract,
|
|
922
|
+
bountyId: BigInt(String(row.bountyId || "0")),
|
|
923
|
+
creator: creatorAddr,
|
|
924
|
+
title: String(row.title || ""),
|
|
925
|
+
reward: BigInt(String(row.reward || "0")),
|
|
926
|
+
creatorDeposit: BigInt(String(row.creatorDeposit || "0")),
|
|
927
|
+
mode: Number(row.mode || 0),
|
|
928
|
+
status: Number(row.status || 0),
|
|
929
|
+
libraryAction: row.libraryAction != null ? Number(row.libraryAction) : null,
|
|
930
|
+
assignee,
|
|
931
|
+
winner,
|
|
932
|
+
winningSubmissionId: row.winningSubmissionId != null ? BigInt(String(row.winningSubmissionId)) : null,
|
|
933
|
+
libraryKey: row.libraryKey || null,
|
|
934
|
+
deadline: row.deadline != null ? Number(row.deadline) : null,
|
|
935
|
+
votingEndTime: row.votingEndTime != null ? Number(row.votingEndTime) : null,
|
|
936
|
+
createdAt: Number(row.createdAt || 0),
|
|
937
|
+
updatedAt: Number(row.updatedAt || 0)
|
|
938
|
+
};
|
|
939
|
+
});
|
|
940
|
+
},
|
|
941
|
+
async getBounty({ url, id: id2 }) {
|
|
942
|
+
if (!url) throw new Error("subgraph url required");
|
|
943
|
+
const doc = `
|
|
944
|
+
query($id:ID!){
|
|
945
|
+
bounty(id:$id){
|
|
946
|
+
id
|
|
947
|
+
contract
|
|
948
|
+
bountyId
|
|
949
|
+
creator
|
|
950
|
+
title
|
|
951
|
+
reward
|
|
952
|
+
creatorDeposit
|
|
953
|
+
mode
|
|
954
|
+
status
|
|
955
|
+
libraryAction
|
|
956
|
+
assignee
|
|
957
|
+
winner
|
|
958
|
+
winningSubmissionId
|
|
959
|
+
libraryKey
|
|
960
|
+
deadline
|
|
961
|
+
votingEndTime
|
|
962
|
+
snapshotBlock
|
|
963
|
+
governanceProposalId
|
|
964
|
+
createdAt
|
|
965
|
+
updatedAt
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
`;
|
|
969
|
+
const data = await query(url, doc, { id: String(id2) });
|
|
970
|
+
const row = data?.bounty;
|
|
971
|
+
if (!row) return null;
|
|
972
|
+
const contract = safeGetAddress(row.contract);
|
|
973
|
+
const creatorAddr = safeGetAddress(row.creator);
|
|
974
|
+
if (!contract || !creatorAddr) return null;
|
|
975
|
+
return {
|
|
976
|
+
id: String(row.id),
|
|
977
|
+
contract,
|
|
978
|
+
bountyId: BigInt(String(row.bountyId || "0")),
|
|
979
|
+
creator: creatorAddr,
|
|
980
|
+
title: String(row.title || ""),
|
|
981
|
+
reward: BigInt(String(row.reward || "0")),
|
|
982
|
+
creatorDeposit: BigInt(String(row.creatorDeposit || "0")),
|
|
983
|
+
mode: Number(row.mode || 0),
|
|
984
|
+
status: Number(row.status || 0),
|
|
985
|
+
libraryAction: row.libraryAction != null ? Number(row.libraryAction) : null,
|
|
986
|
+
assignee: row.assignee ? safeGetAddress(row.assignee) : null,
|
|
987
|
+
winner: row.winner ? safeGetAddress(row.winner) : null,
|
|
988
|
+
winningSubmissionId: row.winningSubmissionId != null ? BigInt(String(row.winningSubmissionId)) : null,
|
|
989
|
+
libraryKey: row.libraryKey || null,
|
|
990
|
+
deadline: row.deadline != null ? Number(row.deadline) : null,
|
|
991
|
+
votingEndTime: row.votingEndTime != null ? Number(row.votingEndTime) : null,
|
|
992
|
+
snapshotBlock: row.snapshotBlock != null ? Number(row.snapshotBlock) : null,
|
|
993
|
+
governanceProposalId: row.governanceProposalId != null ? BigInt(String(row.governanceProposalId)) : null,
|
|
994
|
+
createdAt: Number(row.createdAt || 0),
|
|
995
|
+
updatedAt: Number(row.updatedAt || 0)
|
|
996
|
+
};
|
|
997
|
+
},
|
|
998
|
+
async listBountySubmissions({ url, bountyId, first = 50, skip = 0 }) {
|
|
999
|
+
if (!url) throw new Error("subgraph url required");
|
|
1000
|
+
const doc = `
|
|
1001
|
+
query($bountyId:BigInt!,$first:Int!,$skip:Int!){
|
|
1002
|
+
bountySubmissions(
|
|
1003
|
+
where:{ bountyId:$bountyId }
|
|
1004
|
+
first:$first
|
|
1005
|
+
skip:$skip
|
|
1006
|
+
orderBy: timestamp
|
|
1007
|
+
orderDirection: asc
|
|
1008
|
+
){
|
|
1009
|
+
id
|
|
1010
|
+
bountyId
|
|
1011
|
+
submissionId
|
|
1012
|
+
submitter
|
|
1013
|
+
promptIPFS
|
|
1014
|
+
deliverableIPFS
|
|
1015
|
+
timestamp
|
|
1016
|
+
voteCount
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
`;
|
|
1020
|
+
const data = await query(url, doc, {
|
|
1021
|
+
bountyId: String(bountyId),
|
|
1022
|
+
first: Math.min(Math.max(1, Number(first || 50)), 200),
|
|
1023
|
+
skip: Number(skip || 0)
|
|
1024
|
+
});
|
|
1025
|
+
return mapSafe(data?.bountySubmissions, (row) => {
|
|
1026
|
+
const submitter = safeGetAddress(row.submitter);
|
|
1027
|
+
if (!submitter) return null;
|
|
1028
|
+
return {
|
|
1029
|
+
id: String(row.id),
|
|
1030
|
+
bountyId: BigInt(String(row.bountyId || "0")),
|
|
1031
|
+
submissionId: BigInt(String(row.submissionId || "0")),
|
|
1032
|
+
submitter,
|
|
1033
|
+
promptIPFS: String(row.promptIPFS || ""),
|
|
1034
|
+
deliverableIPFS: String(row.deliverableIPFS || ""),
|
|
1035
|
+
timestamp: Number(row.timestamp || 0),
|
|
1036
|
+
voteCount: BigInt(String(row.voteCount || "0"))
|
|
1037
|
+
};
|
|
1038
|
+
});
|
|
1039
|
+
},
|
|
1040
|
+
async listBountyVotes({ url, bountyId, first = 100, skip = 0 }) {
|
|
1041
|
+
if (!url) throw new Error("subgraph url required");
|
|
1042
|
+
const doc = `
|
|
1043
|
+
query($bountyId:BigInt!,$first:Int!,$skip:Int!){
|
|
1044
|
+
bountyVotes(
|
|
1045
|
+
where:{ bountyId:$bountyId }
|
|
1046
|
+
first:$first
|
|
1047
|
+
skip:$skip
|
|
1048
|
+
orderBy: blockTimestamp
|
|
1049
|
+
orderDirection: desc
|
|
1050
|
+
){
|
|
1051
|
+
id
|
|
1052
|
+
bountyId
|
|
1053
|
+
submissionId
|
|
1054
|
+
voter
|
|
1055
|
+
weight
|
|
1056
|
+
blockNumber
|
|
1057
|
+
blockTimestamp
|
|
1058
|
+
transactionHash
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1061
|
+
`;
|
|
1062
|
+
const data = await query(url, doc, {
|
|
1063
|
+
bountyId: String(bountyId),
|
|
1064
|
+
first: Math.min(Math.max(1, Number(first || 100)), 500),
|
|
1065
|
+
skip: Number(skip || 0)
|
|
1066
|
+
});
|
|
1067
|
+
return mapSafe(data?.bountyVotes, (row) => {
|
|
1068
|
+
const voter = safeGetAddress(row.voter);
|
|
1069
|
+
if (!voter) return null;
|
|
1070
|
+
return {
|
|
1071
|
+
id: String(row.id),
|
|
1072
|
+
bountyId: BigInt(String(row.bountyId || "0")),
|
|
1073
|
+
submissionId: BigInt(String(row.submissionId || "0")),
|
|
1074
|
+
voter,
|
|
1075
|
+
weight: BigInt(String(row.weight || "0")),
|
|
1076
|
+
blockNumber: Number(row.blockNumber || 0),
|
|
1077
|
+
blockTimestamp: Number(row.blockTimestamp || 0),
|
|
1078
|
+
transactionHash: row.transactionHash || null
|
|
1079
|
+
};
|
|
1080
|
+
});
|
|
1081
|
+
},
|
|
1082
|
+
/**
|
|
1083
|
+
* Multiplier dashboards (VotingMultiplierNFT + SageAuctionHouse)
|
|
1084
|
+
*/
|
|
1085
|
+
async listMultiplierAccounts({ url, dao, first = 100, skip = 0 }) {
|
|
1086
|
+
if (!url) throw new Error("subgraph url required");
|
|
1087
|
+
const daoAddr = safeGetAddress(dao);
|
|
1088
|
+
if (!daoAddr) throw new Error("invalid dao address");
|
|
1089
|
+
const doc = `
|
|
1090
|
+
query($dao:Bytes!,$first:Int!,$skip:Int!){
|
|
1091
|
+
multiplierAccounts(
|
|
1092
|
+
where:{ dao: $dao }
|
|
1093
|
+
first:$first
|
|
1094
|
+
skip:$skip
|
|
1095
|
+
orderBy: currentMultiplierBps
|
|
1096
|
+
orderDirection: desc
|
|
1097
|
+
){
|
|
1098
|
+
id
|
|
1099
|
+
dao
|
|
1100
|
+
account
|
|
1101
|
+
currentMultiplierBps
|
|
1102
|
+
tokenCount
|
|
1103
|
+
updatedAt
|
|
1104
|
+
}
|
|
1105
|
+
}
|
|
1106
|
+
`;
|
|
1107
|
+
const data = await query(url, doc, {
|
|
1108
|
+
dao: daoAddr.toLowerCase(),
|
|
1109
|
+
first: Math.min(Math.max(1, Number(first || 100)), 500),
|
|
1110
|
+
skip: Number(skip || 0)
|
|
1111
|
+
});
|
|
1112
|
+
return mapSafe(data?.multiplierAccounts, (row) => {
|
|
1113
|
+
const daoNorm = safeGetAddress(row.dao);
|
|
1114
|
+
const account = safeGetAddress(row.account);
|
|
1115
|
+
if (!daoNorm || !account) return null;
|
|
1116
|
+
return {
|
|
1117
|
+
id: String(row.id),
|
|
1118
|
+
dao: daoNorm,
|
|
1119
|
+
account,
|
|
1120
|
+
multiplierBps: BigInt(String(row.currentMultiplierBps || "0")),
|
|
1121
|
+
tokenCount: Number(row.tokenCount || 0),
|
|
1122
|
+
updatedAt: Number(row.updatedAt || 0)
|
|
1123
|
+
};
|
|
1124
|
+
});
|
|
1125
|
+
},
|
|
1126
|
+
async listMultiplierNFTs({ url, dao, owner = null, first = 100, skip = 0 }) {
|
|
1127
|
+
if (!url) throw new Error("subgraph url required");
|
|
1128
|
+
const daoAddr = safeGetAddress(dao);
|
|
1129
|
+
if (!daoAddr) throw new Error("invalid dao address");
|
|
1130
|
+
const ownerAddr = owner ? safeGetAddress(owner) : null;
|
|
1131
|
+
const filters = [`dao: $dao`];
|
|
1132
|
+
if (ownerAddr) filters.push(`owner: $owner`);
|
|
1133
|
+
const where = `where:{ ${filters.join(", ")} }`;
|
|
1134
|
+
const doc = `
|
|
1135
|
+
query($dao:Bytes!,$owner:Bytes,$first:Int!,$skip:Int!){
|
|
1136
|
+
multiplierNFTs(
|
|
1137
|
+
${where}
|
|
1138
|
+
first:$first
|
|
1139
|
+
skip:$skip
|
|
1140
|
+
orderBy: mintedAt
|
|
1141
|
+
orderDirection: desc
|
|
1142
|
+
){
|
|
1143
|
+
id
|
|
1144
|
+
owner
|
|
1145
|
+
dao
|
|
1146
|
+
tier { id name multiplier maxSupply minted price }
|
|
1147
|
+
multiplier
|
|
1148
|
+
tokenURI
|
|
1149
|
+
mintedAt
|
|
1150
|
+
transactionHash
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
`;
|
|
1154
|
+
const variables = {
|
|
1155
|
+
dao: daoAddr.toLowerCase(),
|
|
1156
|
+
owner: ownerAddr ? ownerAddr.toLowerCase() : null,
|
|
1157
|
+
first: Math.min(Math.max(1, Number(first || 100)), 500),
|
|
1158
|
+
skip: Number(skip || 0)
|
|
1159
|
+
};
|
|
1160
|
+
const data = await query(url, doc, variables);
|
|
1161
|
+
return mapSafe(data?.multiplierNFTs, (row) => {
|
|
1162
|
+
const ownerNorm = safeGetAddress(row.owner);
|
|
1163
|
+
const daoNorm = safeGetAddress(row.dao);
|
|
1164
|
+
if (!ownerNorm || !daoNorm) return null;
|
|
1165
|
+
return {
|
|
1166
|
+
id: String(row.id),
|
|
1167
|
+
owner: ownerNorm,
|
|
1168
|
+
dao: daoNorm,
|
|
1169
|
+
tier: row.tier ? {
|
|
1170
|
+
id: String(row.tier.id),
|
|
1171
|
+
name: String(row.tier.name || ""),
|
|
1172
|
+
multiplier: Number(row.tier.multiplier || 0),
|
|
1173
|
+
maxSupply: BigInt(String(row.tier.maxSupply || "0")),
|
|
1174
|
+
minted: BigInt(String(row.tier.minted || "0")),
|
|
1175
|
+
price: BigInt(String(row.tier.price || "0"))
|
|
1176
|
+
} : null,
|
|
1177
|
+
multiplier: Number(row.multiplier || 0),
|
|
1178
|
+
tokenURI: row.tokenURI || null,
|
|
1179
|
+
mintedAt: Number(row.mintedAt || 0),
|
|
1180
|
+
transactionHash: row.transactionHash || null
|
|
1181
|
+
};
|
|
1182
|
+
});
|
|
1183
|
+
},
|
|
1184
|
+
async getCurrentAuction({ url, auctionHouse }) {
|
|
1185
|
+
if (!url) throw new Error("subgraph url required");
|
|
1186
|
+
const addr = safeGetAddress(auctionHouse);
|
|
1187
|
+
if (!addr) throw new Error("invalid auctionHouse address");
|
|
1188
|
+
const doc = `
|
|
1189
|
+
query($id:ID!){
|
|
1190
|
+
multiplierAuction(id:$id){
|
|
1191
|
+
id
|
|
1192
|
+
auctionHouse
|
|
1193
|
+
nft
|
|
1194
|
+
treasury
|
|
1195
|
+
currentNftId
|
|
1196
|
+
currentAmount
|
|
1197
|
+
currentBidder
|
|
1198
|
+
startTime
|
|
1199
|
+
endTime
|
|
1200
|
+
settled
|
|
1201
|
+
updatedAt
|
|
1202
|
+
}
|
|
1203
|
+
}
|
|
1204
|
+
`;
|
|
1205
|
+
const data = await query(url, doc, { id: addr.toLowerCase() });
|
|
1206
|
+
const row = data?.multiplierAuction;
|
|
1207
|
+
if (!row) return null;
|
|
1208
|
+
return {
|
|
1209
|
+
id: String(row.id),
|
|
1210
|
+
auctionHouse: safeGetAddress(row.auctionHouse) || addr,
|
|
1211
|
+
nft: safeGetAddress(row.nft),
|
|
1212
|
+
treasury: safeGetAddress(row.treasury),
|
|
1213
|
+
currentNftId: BigInt(String(row.currentNftId || "0")),
|
|
1214
|
+
currentAmount: BigInt(String(row.currentAmount || "0")),
|
|
1215
|
+
currentBidder: safeGetAddress(row.currentBidder || "0x0000000000000000000000000000000000000000"),
|
|
1216
|
+
startTime: Number(row.startTime || 0),
|
|
1217
|
+
endTime: Number(row.endTime || 0),
|
|
1218
|
+
settled: !!row.settled,
|
|
1219
|
+
updatedAt: Number(row.updatedAt || 0)
|
|
1220
|
+
};
|
|
1221
|
+
},
|
|
1222
|
+
async listAuctionBids({ url, auctionHouse, first = 100, skip = 0 }) {
|
|
1223
|
+
if (!url) throw new Error("subgraph url required");
|
|
1224
|
+
const addr = safeGetAddress(auctionHouse);
|
|
1225
|
+
if (!addr) throw new Error("invalid auctionHouse address");
|
|
1226
|
+
const doc = `
|
|
1227
|
+
query($auctionHouse:Bytes!,$first:Int!,$skip:Int!){
|
|
1228
|
+
multiplierAuctionBids(
|
|
1229
|
+
where:{ auctionHouse:$auctionHouse }
|
|
1230
|
+
first:$first
|
|
1231
|
+
skip:$skip
|
|
1232
|
+
orderBy: blockTimestamp
|
|
1233
|
+
orderDirection: desc
|
|
1234
|
+
){
|
|
1235
|
+
id
|
|
1236
|
+
auctionHouse
|
|
1237
|
+
nftId
|
|
1238
|
+
bidder
|
|
1239
|
+
amount
|
|
1240
|
+
extended
|
|
1241
|
+
blockNumber
|
|
1242
|
+
blockTimestamp
|
|
1243
|
+
transactionHash
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
`;
|
|
1247
|
+
const data = await query(url, doc, {
|
|
1248
|
+
auctionHouse: addr.toLowerCase(),
|
|
1249
|
+
first: Math.min(Math.max(1, Number(first || 100)), 500),
|
|
1250
|
+
skip: Number(skip || 0)
|
|
1251
|
+
});
|
|
1252
|
+
return mapSafe(data?.multiplierAuctionBids, (row) => {
|
|
1253
|
+
const bidder = safeGetAddress(row.bidder);
|
|
1254
|
+
const ah = safeGetAddress(row.auctionHouse);
|
|
1255
|
+
if (!ah || !bidder) return null;
|
|
1256
|
+
return {
|
|
1257
|
+
id: String(row.id),
|
|
1258
|
+
auctionHouse: ah,
|
|
1259
|
+
nftId: BigInt(String(row.nftId || "0")),
|
|
1260
|
+
bidder,
|
|
1261
|
+
amount: BigInt(String(row.amount || "0")),
|
|
1262
|
+
extended: !!row.extended,
|
|
1263
|
+
blockNumber: Number(row.blockNumber || 0),
|
|
1264
|
+
blockTimestamp: Number(row.blockTimestamp || 0),
|
|
1265
|
+
transactionHash: row.transactionHash || null
|
|
1266
|
+
};
|
|
1267
|
+
});
|
|
1268
|
+
},
|
|
675
1269
|
/**
|
|
676
1270
|
* Canonical proposal timeline. Tries common fields first, then event-style fallbacks.
|
|
677
1271
|
* Returns { id, createdAt, queuedAt, executedAt, canceledAt, eta, state } (numbers/strings may be null when unavailable).
|
|
@@ -1160,7 +1754,6 @@ var require_ipfs = __commonJS({
|
|
|
1160
1754
|
headers["X-Wallet-Address"] = auth.address;
|
|
1161
1755
|
headers["X-Wallet-Signature"] = auth.signature;
|
|
1162
1756
|
headers["X-Wallet-Nonce"] = auth.nonce;
|
|
1163
|
-
headers["X-Wallet-Message"] = auth.message;
|
|
1164
1757
|
}
|
|
1165
1758
|
return { headers, auth };
|
|
1166
1759
|
}
|
|
@@ -1181,8 +1774,7 @@ var require_ipfs = __commonJS({
|
|
|
1181
1774
|
...extraHeaders,
|
|
1182
1775
|
"X-Wallet-Address": auth.address,
|
|
1183
1776
|
"X-Wallet-Signature": auth.signature,
|
|
1184
|
-
"X-Wallet-Nonce": auth.nonce
|
|
1185
|
-
"X-Wallet-Message": auth.message
|
|
1777
|
+
"X-Wallet-Nonce": auth.nonce
|
|
1186
1778
|
};
|
|
1187
1779
|
return { headers, auth };
|
|
1188
1780
|
}
|
|
@@ -1203,6 +1795,13 @@ var require_ipfs = __commonJS({
|
|
|
1203
1795
|
order.push(name);
|
|
1204
1796
|
};
|
|
1205
1797
|
const normalizedPreference = Array.isArray(preference) ? preference.map((p) => toLowerSafe(p)).filter(Boolean) : preference ? [toLowerSafe(preference)].filter(Boolean) : [];
|
|
1798
|
+
if (process.env.SAGE_DEBUG_WORKER === "1") {
|
|
1799
|
+
console.log("[SDK DEBUG] resolveProviderOrder preference:", preference);
|
|
1800
|
+
console.log("[SDK DEBUG] normalizedPreference:", normalizedPreference);
|
|
1801
|
+
console.log("[SDK DEBUG] config.provider:", config.provider);
|
|
1802
|
+
console.log("[SDK DEBUG] shouldUseWorker():", shouldUseWorker());
|
|
1803
|
+
console.log("[SDK DEBUG] hasPinataCreds():", hasPinataCreds());
|
|
1804
|
+
}
|
|
1206
1805
|
normalizedPreference.forEach(append);
|
|
1207
1806
|
if (shouldUseWorker()) append("worker");
|
|
1208
1807
|
if (hasPinataCreds()) append("pinata");
|
|
@@ -1210,17 +1809,90 @@ var require_ipfs = __commonJS({
|
|
|
1210
1809
|
if (config.simulate) append("simulate");
|
|
1211
1810
|
return order;
|
|
1212
1811
|
}
|
|
1213
|
-
async function uploadViaWorker(payload, { warm, gateways } = {}) {
|
|
1812
|
+
async function uploadViaWorker(payload, { warm, gateways, pin: pin2 } = {}) {
|
|
1813
|
+
const uploadUrl = workerUrl("upload");
|
|
1814
|
+
if (process.env.SAGE_DEBUG_WORKER === "1") {
|
|
1815
|
+
console.log("[SDK DEBUG] uploadViaWorker called");
|
|
1816
|
+
console.log("[SDK DEBUG] workerBaseUrl:", workerBaseUrl());
|
|
1817
|
+
console.log("[SDK DEBUG] uploadUrl:", uploadUrl);
|
|
1818
|
+
console.log("[SDK DEBUG] workerHasAuth:", workerHasAuth());
|
|
1819
|
+
}
|
|
1214
1820
|
const { headers, auth } = await buildWorkerAuthHeaders({ "Content-Type": "application/json" });
|
|
1215
1821
|
const body = { ...payload };
|
|
1216
1822
|
if (auth) body.auth = auth;
|
|
1217
|
-
|
|
1218
|
-
|
|
1823
|
+
if (pin2) {
|
|
1824
|
+
body.pin = typeof pin2 === "string" ? { duration: pin2 } : pin2;
|
|
1825
|
+
}
|
|
1826
|
+
if (process.env.SAGE_DEBUG_WORKER === "1") {
|
|
1827
|
+
console.log("[SDK DEBUG] headers:", Object.keys(headers));
|
|
1828
|
+
console.log("[SDK DEBUG] hasAuth:", !!auth);
|
|
1829
|
+
if (pin2) console.log("[SDK DEBUG] pin:", JSON.stringify(body.pin));
|
|
1830
|
+
}
|
|
1831
|
+
let response;
|
|
1832
|
+
try {
|
|
1833
|
+
response = await axiosInstance.post(uploadUrl, body, { headers, timeout: config.timeoutMs });
|
|
1834
|
+
if (process.env.SAGE_DEBUG_WORKER === "1") {
|
|
1835
|
+
console.log("[SDK DEBUG] Upload response status:", response?.status);
|
|
1836
|
+
console.log("[SDK DEBUG] Upload response data:", JSON.stringify(response?.data || {}));
|
|
1837
|
+
}
|
|
1838
|
+
} catch (uploadErr) {
|
|
1839
|
+
if (process.env.SAGE_DEBUG_WORKER === "1") {
|
|
1840
|
+
console.log("[SDK DEBUG] Upload error:", uploadErr.message);
|
|
1841
|
+
console.log("[SDK DEBUG] Response status:", uploadErr.response?.status);
|
|
1842
|
+
console.log("[SDK DEBUG] Response data:", JSON.stringify(uploadErr.response?.data || {}));
|
|
1843
|
+
}
|
|
1844
|
+
const status = uploadErr.response?.status;
|
|
1845
|
+
const data2 = uploadErr.response?.data;
|
|
1846
|
+
if (status === 400 && data2?.error === "content_blocked") {
|
|
1847
|
+
const error = new Error("content_blocked");
|
|
1848
|
+
error.code = "CONTENT_BLOCKED";
|
|
1849
|
+
error.categories = data2.categories || [];
|
|
1850
|
+
error.reason = data2.reason;
|
|
1851
|
+
error.response = data2;
|
|
1852
|
+
throw error;
|
|
1853
|
+
}
|
|
1854
|
+
if (status === 402) {
|
|
1855
|
+
const error = new Error("payment_required");
|
|
1856
|
+
error.code = "PAYMENT_REQUIRED";
|
|
1857
|
+
error.creditsNeeded = data2?.creditsNeeded;
|
|
1858
|
+
error.balance = data2?.balance;
|
|
1859
|
+
error.duration = data2?.duration;
|
|
1860
|
+
error.accepts = data2?.accepts;
|
|
1861
|
+
error.response = data2;
|
|
1862
|
+
throw error;
|
|
1863
|
+
}
|
|
1864
|
+
throw uploadErr;
|
|
1865
|
+
}
|
|
1866
|
+
const data = response?.data || {};
|
|
1867
|
+
const cid = data.cid || data.IpfsHash;
|
|
1868
|
+
if (response?.status === 202 || data.status === "pending_review") {
|
|
1869
|
+
return {
|
|
1870
|
+
cid: cid || null,
|
|
1871
|
+
provider: "worker",
|
|
1872
|
+
status: "pending_review",
|
|
1873
|
+
categories: data.categories || [],
|
|
1874
|
+
response: data
|
|
1875
|
+
};
|
|
1876
|
+
}
|
|
1219
1877
|
if (!cid) {
|
|
1220
1878
|
throw new Error("Worker response missing cid");
|
|
1221
1879
|
}
|
|
1222
1880
|
if (warm || config.shouldWarm) await warmGateways(cid, { gateways });
|
|
1223
|
-
|
|
1881
|
+
const result = {
|
|
1882
|
+
cid,
|
|
1883
|
+
provider: "worker",
|
|
1884
|
+
response: data
|
|
1885
|
+
};
|
|
1886
|
+
if (data.moderation) {
|
|
1887
|
+
result.moderation = data.moderation;
|
|
1888
|
+
}
|
|
1889
|
+
if (data.pinned !== void 0) {
|
|
1890
|
+
result.pinned = data.pinned;
|
|
1891
|
+
result.expiresAt = data.expiresAt;
|
|
1892
|
+
result.creditsPaid = data.creditsPaid;
|
|
1893
|
+
result.urls = data.urls;
|
|
1894
|
+
}
|
|
1895
|
+
return result;
|
|
1224
1896
|
}
|
|
1225
1897
|
async function uploadToPinata(payload, { filename = "payload.json", metadata, warm, gateways } = {}) {
|
|
1226
1898
|
if (!hasPinataCreds()) {
|
|
@@ -1298,7 +1970,7 @@ var require_ipfs = __commonJS({
|
|
|
1298
1970
|
return { cid, provider: "simulate" };
|
|
1299
1971
|
}
|
|
1300
1972
|
async function uploadPayload(payload, options2 = {}) {
|
|
1301
|
-
const { providers, provider, warm, gateways, filename, metadata } = options2;
|
|
1973
|
+
const { providers, provider, warm, gateways, filename, metadata, pin: pin2 } = options2;
|
|
1302
1974
|
const order = resolveProviderOrder(providers || provider);
|
|
1303
1975
|
if (!order.length) {
|
|
1304
1976
|
throw new Error("No IPFS providers configured. Set Pinata credentials, worker upload, or enable test mode");
|
|
@@ -1307,7 +1979,7 @@ var require_ipfs = __commonJS({
|
|
|
1307
1979
|
for (const candidate of order) {
|
|
1308
1980
|
try {
|
|
1309
1981
|
if (candidate === "worker") {
|
|
1310
|
-
return await uploadViaWorker(payload, { warm, gateways });
|
|
1982
|
+
return await uploadViaWorker(payload, { warm, gateways, pin: pin2 });
|
|
1311
1983
|
}
|
|
1312
1984
|
if (candidate === "pinata") {
|
|
1313
1985
|
return await uploadToPinata(payload, { filename, metadata, warm, gateways });
|
|
@@ -1319,6 +1991,9 @@ var require_ipfs = __commonJS({
|
|
|
1319
1991
|
return await uploadSimulated(payload, { warm, gateways });
|
|
1320
1992
|
}
|
|
1321
1993
|
} catch (error2) {
|
|
1994
|
+
if (error2.code === "CONTENT_BLOCKED" || error2.code === "PAYMENT_REQUIRED") {
|
|
1995
|
+
throw error2;
|
|
1996
|
+
}
|
|
1322
1997
|
errors2.push({ provider: candidate, error: error2 });
|
|
1323
1998
|
}
|
|
1324
1999
|
}
|
|
@@ -1327,7 +2002,7 @@ var require_ipfs = __commonJS({
|
|
|
1327
2002
|
throw error;
|
|
1328
2003
|
}
|
|
1329
2004
|
async function uploadPrompt(options2 = {}) {
|
|
1330
|
-
const { prompt: prompt2, providers, provider, warm, gateways } = options2;
|
|
2005
|
+
const { prompt: prompt2, providers, provider, warm, gateways, pin: pin2 } = options2;
|
|
1331
2006
|
if (!prompt2 || typeof prompt2 !== "object") {
|
|
1332
2007
|
throw new Error("prompt payload required");
|
|
1333
2008
|
}
|
|
@@ -1353,6 +2028,7 @@ var require_ipfs = __commonJS({
|
|
|
1353
2028
|
provider,
|
|
1354
2029
|
warm,
|
|
1355
2030
|
gateways,
|
|
2031
|
+
pin: pin2,
|
|
1356
2032
|
filename: `${prompt2.name || "prompt"}.json`,
|
|
1357
2033
|
metadata
|
|
1358
2034
|
});
|
|
@@ -1587,8 +2263,7 @@ var require_ipfs = __commonJS({
|
|
|
1587
2263
|
"Content-Type": "application/json",
|
|
1588
2264
|
"X-Wallet-Address": address,
|
|
1589
2265
|
"X-Wallet-Signature": signature,
|
|
1590
|
-
"X-Wallet-Nonce": nonce
|
|
1591
|
-
"X-Wallet-Message": message
|
|
2266
|
+
"X-Wallet-Nonce": nonce
|
|
1592
2267
|
};
|
|
1593
2268
|
let verified = false;
|
|
1594
2269
|
try {
|
|
@@ -2446,13 +3121,10 @@ var require_governance = __commonJS({
|
|
|
2446
3121
|
} else {
|
|
2447
3122
|
const govAddr = normaliseGovernor(governor);
|
|
2448
3123
|
try {
|
|
2449
|
-
const
|
|
2450
|
-
|
|
2451
|
-
const ret = await provider.call({ to: govAddr, data });
|
|
2452
|
-
const [tok] = AbiCoder.defaultAbiCoder().decode(["address"], ret);
|
|
2453
|
-
addr = getAddress(tok);
|
|
3124
|
+
const chain = await resolveVotesTokenChain({ provider, governor: govAddr });
|
|
3125
|
+
addr = getAddress(chain.votingToken);
|
|
2454
3126
|
} catch (err) {
|
|
2455
|
-
throw new SageSDKError(CODES.NOT_FOUND, "failed to resolve
|
|
3127
|
+
throw new SageSDKError(CODES.NOT_FOUND, "failed to resolve votes token from governor", { cause: err });
|
|
2456
3128
|
}
|
|
2457
3129
|
}
|
|
2458
3130
|
const user = getAddress(account);
|
|
@@ -2533,6 +3205,210 @@ var require_governance = __commonJS({
|
|
|
2533
3205
|
const token2 = await g.sxxxToken();
|
|
2534
3206
|
return buildDelegateTx({ token: token2, delegatee: account });
|
|
2535
3207
|
}
|
|
3208
|
+
async function resolveVotesTokenChain({ provider, subdao: subdao2, governor }) {
|
|
3209
|
+
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
|
|
3210
|
+
if (!subdao2 && !governor) throw new SageSDKError(CODES.INVALID_ARGS, "subdao or governor required");
|
|
3211
|
+
let votingToken = null;
|
|
3212
|
+
if (governor) {
|
|
3213
|
+
const govAddr = normaliseGovernor(governor);
|
|
3214
|
+
try {
|
|
3215
|
+
const iTok = new Interface(["function token() view returns (address)"]);
|
|
3216
|
+
const data = iTok.encodeFunctionData("token", []);
|
|
3217
|
+
const ret = await provider.call({ to: govAddr, data });
|
|
3218
|
+
if (ret && ret !== "0x") {
|
|
3219
|
+
const [addr] = AbiCoder.defaultAbiCoder().decode(["address"], ret);
|
|
3220
|
+
votingToken = addr;
|
|
3221
|
+
}
|
|
3222
|
+
} catch (_) {
|
|
3223
|
+
}
|
|
3224
|
+
if (!votingToken) {
|
|
3225
|
+
try {
|
|
3226
|
+
const iGov = new Interface(["function sxxxToken() view returns (address)"]);
|
|
3227
|
+
const d2 = iGov.encodeFunctionData("sxxxToken", []);
|
|
3228
|
+
const r2 = await provider.call({ to: govAddr, data: d2 });
|
|
3229
|
+
if (r2 && r2 !== "0x") {
|
|
3230
|
+
const [addr] = AbiCoder.defaultAbiCoder().decode(["address"], r2);
|
|
3231
|
+
votingToken = addr;
|
|
3232
|
+
}
|
|
3233
|
+
} catch (_) {
|
|
3234
|
+
}
|
|
3235
|
+
}
|
|
3236
|
+
}
|
|
3237
|
+
if (!votingToken && subdao2) {
|
|
3238
|
+
try {
|
|
3239
|
+
const subAddr = getAddress(subdao2);
|
|
3240
|
+
const iSub = new Interface(["function stakeToken() view returns (address)"]);
|
|
3241
|
+
const d3 = iSub.encodeFunctionData("stakeToken", []);
|
|
3242
|
+
const r3 = await provider.call({ to: subAddr, data: d3 });
|
|
3243
|
+
if (r3 && r3 !== "0x") {
|
|
3244
|
+
const [addr] = AbiCoder.defaultAbiCoder().decode(["address"], r3);
|
|
3245
|
+
votingToken = addr;
|
|
3246
|
+
}
|
|
3247
|
+
} catch (_) {
|
|
3248
|
+
}
|
|
3249
|
+
}
|
|
3250
|
+
if (!votingToken) {
|
|
3251
|
+
throw new SageSDKError(CODES.NOT_FOUND, "failed to resolve votes token");
|
|
3252
|
+
}
|
|
3253
|
+
const votingTokenNorm = getAddress(votingToken);
|
|
3254
|
+
let baseToken = votingTokenNorm;
|
|
3255
|
+
let isWrapper = false;
|
|
3256
|
+
try {
|
|
3257
|
+
const wrapperIface = new Interface([
|
|
3258
|
+
"function baseToken() view returns (address)",
|
|
3259
|
+
"function dao() view returns (address)"
|
|
3260
|
+
]);
|
|
3261
|
+
const [rawBase, rawDao] = await Promise.all([
|
|
3262
|
+
provider.call({ to: votingTokenNorm, data: wrapperIface.encodeFunctionData("baseToken", []) }),
|
|
3263
|
+
provider.call({ to: votingTokenNorm, data: wrapperIface.encodeFunctionData("dao", []) })
|
|
3264
|
+
]);
|
|
3265
|
+
if (rawBase && rawBase !== "0x" && rawDao && rawDao !== "0x") {
|
|
3266
|
+
const [decodedBase] = AbiCoder.defaultAbiCoder().decode(["address"], rawBase);
|
|
3267
|
+
const [decodedDao] = AbiCoder.defaultAbiCoder().decode(["address"], rawDao);
|
|
3268
|
+
const baseNorm = getAddress(decodedBase);
|
|
3269
|
+
const daoNorm = getAddress(decodedDao);
|
|
3270
|
+
if (!subdao2 || daoNorm === getAddress(subdao2)) {
|
|
3271
|
+
baseToken = baseNorm;
|
|
3272
|
+
isWrapper = true;
|
|
3273
|
+
}
|
|
3274
|
+
}
|
|
3275
|
+
} catch (_) {
|
|
3276
|
+
}
|
|
3277
|
+
return { votingToken: votingTokenNorm, baseToken, isWrapper };
|
|
3278
|
+
}
|
|
3279
|
+
async function describeVotesToken({ provider, subdao: subdao2, governor }) {
|
|
3280
|
+
const { votingToken, baseToken, isWrapper } = await resolveVotesTokenChain({ provider, subdao: subdao2, governor });
|
|
3281
|
+
let multiplierNFT = null;
|
|
3282
|
+
let basis = null;
|
|
3283
|
+
if (isWrapper) {
|
|
3284
|
+
try {
|
|
3285
|
+
const wrapper = new Contract(votingToken, ABI.MultipliedVotes, provider);
|
|
3286
|
+
multiplierNFT = await wrapper.multiplierNFT().catch(() => null);
|
|
3287
|
+
basis = await wrapper.BASIS().catch(() => null);
|
|
3288
|
+
} catch (_) {
|
|
3289
|
+
}
|
|
3290
|
+
}
|
|
3291
|
+
const votingNorm = getAddress(votingToken);
|
|
3292
|
+
const baseNorm = getAddress(baseToken);
|
|
3293
|
+
const multiplierNorm = multiplierNFT && /^0x[0-9a-fA-F]{40}$/.test(String(multiplierNFT)) ? getAddress(multiplierNFT) : null;
|
|
3294
|
+
const basisBig = basis != null ? BigInt(String(basis)) : null;
|
|
3295
|
+
let description;
|
|
3296
|
+
if (!isWrapper) {
|
|
3297
|
+
description = `Voting token = ERC20Votes at ${votingNorm}`;
|
|
3298
|
+
} else {
|
|
3299
|
+
const basisStr = basisBig != null ? basisBig.toString() : "10000";
|
|
3300
|
+
description = `Voting token = MultipliedVotes(base=${baseNorm}, multiplierNFT=${multiplierNorm || "unknown"}, BASIS=${basisStr})`;
|
|
3301
|
+
if (subdao2) {
|
|
3302
|
+
description += ` for DAO ${getAddress(subdao2)}`;
|
|
3303
|
+
}
|
|
3304
|
+
}
|
|
3305
|
+
return {
|
|
3306
|
+
votingToken: votingNorm,
|
|
3307
|
+
baseToken: baseNorm,
|
|
3308
|
+
isWrapper,
|
|
3309
|
+
multiplierNFT: multiplierNorm,
|
|
3310
|
+
basis: basisBig,
|
|
3311
|
+
description
|
|
3312
|
+
};
|
|
3313
|
+
}
|
|
3314
|
+
async function getVotingStatus({ provider, subdao: subdao2, governor, account }) {
|
|
3315
|
+
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
|
|
3316
|
+
if (!governor && !subdao2) throw new SageSDKError(CODES.INVALID_ARGS, "governor or subdao required");
|
|
3317
|
+
if (!account) throw new SageSDKError(CODES.INVALID_ARGS, "account required");
|
|
3318
|
+
const acct = getAddress(account);
|
|
3319
|
+
let govAddr = null;
|
|
3320
|
+
let subdaoAddr = null;
|
|
3321
|
+
if (governor) {
|
|
3322
|
+
govAddr = normaliseGovernor(governor);
|
|
3323
|
+
}
|
|
3324
|
+
if (subdao2) {
|
|
3325
|
+
subdaoAddr = getAddress(subdao2);
|
|
3326
|
+
if (!govAddr) {
|
|
3327
|
+
try {
|
|
3328
|
+
const sub = new Contract(subdaoAddr, ["function governor() view returns (address)"], provider);
|
|
3329
|
+
govAddr = getAddress(await sub.governor());
|
|
3330
|
+
} catch (_) {
|
|
3331
|
+
}
|
|
3332
|
+
}
|
|
3333
|
+
}
|
|
3334
|
+
if (!govAddr) throw new SageSDKError(CODES.INVALID_ARGS, "could not resolve governor address");
|
|
3335
|
+
let threshold = null;
|
|
3336
|
+
try {
|
|
3337
|
+
const g = new Contract(govAddr, ABI.Governor, provider);
|
|
3338
|
+
const t = await g.proposalThreshold();
|
|
3339
|
+
threshold = BigInt(t.toString());
|
|
3340
|
+
} catch (_) {
|
|
3341
|
+
}
|
|
3342
|
+
const desc = await describeVotesToken({ provider, subdao: subdaoAddr || void 0, governor: govAddr });
|
|
3343
|
+
let stakeToken = null;
|
|
3344
|
+
if (subdaoAddr) {
|
|
3345
|
+
try {
|
|
3346
|
+
const sub = new Contract(subdaoAddr, ["function stakeToken() view returns (address)"], provider);
|
|
3347
|
+
const st = await sub.stakeToken();
|
|
3348
|
+
if (st && /^0x[0-9a-fA-F]{40}$/.test(String(st))) {
|
|
3349
|
+
stakeToken = getAddress(st);
|
|
3350
|
+
}
|
|
3351
|
+
} catch (_) {
|
|
3352
|
+
}
|
|
3353
|
+
}
|
|
3354
|
+
const VotesABI = [
|
|
3355
|
+
"function getVotes(address) view returns (uint256)",
|
|
3356
|
+
"function delegates(address) view returns (address)",
|
|
3357
|
+
"function balanceOf(address) view returns (uint256)"
|
|
3358
|
+
];
|
|
3359
|
+
let votingPower = null;
|
|
3360
|
+
let delegate = null;
|
|
3361
|
+
let tokenBalance = null;
|
|
3362
|
+
try {
|
|
3363
|
+
const votingC = new Contract(desc.votingToken, VotesABI, provider);
|
|
3364
|
+
const vp = await votingC.getVotes(acct).catch(() => null);
|
|
3365
|
+
if (vp != null) votingPower = BigInt(vp.toString());
|
|
3366
|
+
const del = await votingC.delegates(acct).catch(() => null);
|
|
3367
|
+
if (del && /^0x[0-9a-fA-F]{40}$/.test(String(del))) delegate = getAddress(del);
|
|
3368
|
+
const bal = await votingC.balanceOf(acct).catch(() => null);
|
|
3369
|
+
if (bal != null) tokenBalance = BigInt(bal.toString());
|
|
3370
|
+
} catch (_) {
|
|
3371
|
+
}
|
|
3372
|
+
const canPropose = threshold != null && votingPower != null ? votingPower >= threshold : null;
|
|
3373
|
+
let stakeTokenVotes = null;
|
|
3374
|
+
let stakeTokenDelegate = null;
|
|
3375
|
+
let stakeTokenBalance = null;
|
|
3376
|
+
const tokenMismatch = !!stakeToken && stakeToken.toLowerCase() !== desc.votingToken.toLowerCase();
|
|
3377
|
+
if (stakeToken && tokenMismatch) {
|
|
3378
|
+
try {
|
|
3379
|
+
const stakeC = new Contract(stakeToken, VotesABI, provider);
|
|
3380
|
+
const sv = await stakeC.getVotes(acct).catch(() => null);
|
|
3381
|
+
if (sv != null) stakeTokenVotes = BigInt(sv.toString());
|
|
3382
|
+
const sd = await stakeC.delegates(acct).catch(() => null);
|
|
3383
|
+
if (sd && /^0x[0-9a-fA-F]{40}$/.test(String(sd))) {
|
|
3384
|
+
stakeTokenDelegate = getAddress(sd);
|
|
3385
|
+
}
|
|
3386
|
+
const sb = await stakeC.balanceOf(acct).catch(() => null);
|
|
3387
|
+
if (sb != null) stakeTokenBalance = BigInt(sb.toString());
|
|
3388
|
+
} catch (_) {
|
|
3389
|
+
}
|
|
3390
|
+
}
|
|
3391
|
+
return {
|
|
3392
|
+
subdao: subdaoAddr,
|
|
3393
|
+
governor: govAddr,
|
|
3394
|
+
stakeToken,
|
|
3395
|
+
votingToken: desc.votingToken,
|
|
3396
|
+
baseToken: desc.baseToken,
|
|
3397
|
+
isWrapper: desc.isWrapper,
|
|
3398
|
+
multiplierNFT: desc.multiplierNFT,
|
|
3399
|
+
basis: desc.basis,
|
|
3400
|
+
threshold,
|
|
3401
|
+
votingPower,
|
|
3402
|
+
tokenBalance,
|
|
3403
|
+
delegate,
|
|
3404
|
+
canPropose,
|
|
3405
|
+
tokenMismatch,
|
|
3406
|
+
stakeTokenVotes,
|
|
3407
|
+
stakeTokenDelegate,
|
|
3408
|
+
stakeTokenBalance,
|
|
3409
|
+
description: desc.description
|
|
3410
|
+
};
|
|
3411
|
+
}
|
|
2536
3412
|
module2.exports = {
|
|
2537
3413
|
getGovernorInfo,
|
|
2538
3414
|
getProposal,
|
|
@@ -2564,52 +3440,28 @@ var require_governance = __commonJS({
|
|
|
2564
3440
|
* - SubDAO.stakeToken() (when subdao provided)
|
|
2565
3441
|
*/
|
|
2566
3442
|
resolveVotesToken: async function resolveVotesToken({ provider, subdao: subdao2, governor }) {
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
if (governor) {
|
|
2570
|
-
const govAddr = normaliseGovernor(governor);
|
|
2571
|
-
try {
|
|
2572
|
-
const iTok = new Interface(["function token() view returns (address)"]);
|
|
2573
|
-
const data = iTok.encodeFunctionData("token", []);
|
|
2574
|
-
const ret = await provider.call({ to: govAddr, data });
|
|
2575
|
-
if (ret && ret !== "0x") {
|
|
2576
|
-
const [addr] = AbiCoder.defaultAbiCoder().decode(["address"], ret);
|
|
2577
|
-
return getAddress(addr);
|
|
2578
|
-
}
|
|
2579
|
-
} catch (_) {
|
|
2580
|
-
}
|
|
2581
|
-
try {
|
|
2582
|
-
const iGov = new Interface(["function sxxxToken() view returns (address)"]);
|
|
2583
|
-
const d2 = iGov.encodeFunctionData("sxxxToken", []);
|
|
2584
|
-
const r2 = await provider.call({ to: govAddr, data: d2 });
|
|
2585
|
-
if (r2 && r2 !== "0x") {
|
|
2586
|
-
const [addr] = AbiCoder.defaultAbiCoder().decode(["address"], r2);
|
|
2587
|
-
return getAddress(addr);
|
|
2588
|
-
}
|
|
2589
|
-
} catch (_) {
|
|
2590
|
-
}
|
|
2591
|
-
}
|
|
2592
|
-
if (subdao2) {
|
|
2593
|
-
try {
|
|
2594
|
-
const subAddr = getAddress(subdao2);
|
|
2595
|
-
const iSub = new Interface(["function stakeToken() view returns (address)"]);
|
|
2596
|
-
const d3 = iSub.encodeFunctionData("stakeToken", []);
|
|
2597
|
-
const r3 = await provider.call({ to: subAddr, data: d3 });
|
|
2598
|
-
if (r3 && r3 !== "0x") {
|
|
2599
|
-
const [addr] = AbiCoder.defaultAbiCoder().decode(["address"], r3);
|
|
2600
|
-
return getAddress(addr);
|
|
2601
|
-
}
|
|
2602
|
-
} catch (_) {
|
|
2603
|
-
}
|
|
2604
|
-
}
|
|
2605
|
-
throw new SageSDKError(CODES.NOT_FOUND, "failed to resolve votes token");
|
|
3443
|
+
const { votingToken } = await resolveVotesTokenChain({ provider, subdao: subdao2, governor });
|
|
3444
|
+
return votingToken;
|
|
2606
3445
|
},
|
|
3446
|
+
/**
|
|
3447
|
+
* Resolve the IVotes token chain used for voting (wrapper + base token).
|
|
3448
|
+
* See resolveVotesTokenChain() for details.
|
|
3449
|
+
*/
|
|
3450
|
+
resolveVotesTokenChain,
|
|
3451
|
+
/**
|
|
3452
|
+
* Human-friendly description of the voting token wiring for a Governor/SubDAO.
|
|
3453
|
+
*/
|
|
3454
|
+
describeVotesToken,
|
|
3455
|
+
/**
|
|
3456
|
+
* Get voting status for an account relative to a Governor/SubDAO.
|
|
3457
|
+
*/
|
|
3458
|
+
getVotingStatus,
|
|
2607
3459
|
/** Build a delegate(self) tx using the preferred votes token resolution path. */
|
|
2608
3460
|
buildDelegateSelfPreferred: async function buildDelegateSelfPreferred({ provider, subdao: subdao2, governor, account }) {
|
|
2609
3461
|
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
|
|
2610
3462
|
if (!account) throw new SageSDKError(CODES.INVALID_ARGS, "account required");
|
|
2611
|
-
const
|
|
2612
|
-
return buildDelegateTx({ token:
|
|
3463
|
+
const { baseToken } = await resolveVotesTokenChain({ provider, subdao: subdao2, governor });
|
|
3464
|
+
return buildDelegateTx({ token: baseToken, delegatee: account });
|
|
2613
3465
|
},
|
|
2614
3466
|
/**
|
|
2615
3467
|
* Send a delegate(self) and verify votes at latest-1.
|
|
@@ -2618,15 +3470,15 @@ var require_governance = __commonJS({
|
|
|
2618
3470
|
delegateSelfAndVerify: async function delegateSelfAndVerify({ provider, subdao: subdao2, governor, account, signer = null, minVotes = null }) {
|
|
2619
3471
|
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
|
|
2620
3472
|
if (!account) throw new SageSDKError(CODES.INVALID_ARGS, "account required");
|
|
2621
|
-
const
|
|
2622
|
-
const payload = buildDelegateTx({ token:
|
|
3473
|
+
const { votingToken, baseToken } = await resolveVotesTokenChain({ provider, subdao: subdao2, governor });
|
|
3474
|
+
const payload = buildDelegateTx({ token: baseToken, delegatee: account });
|
|
2623
3475
|
let txHash = null;
|
|
2624
3476
|
if (signer && typeof signer.sendTransaction === "function") {
|
|
2625
3477
|
const tx = await signer.sendTransaction({ to: payload.to, data: payload.data, value: payload.value });
|
|
2626
3478
|
txHash = tx?.hash || null;
|
|
2627
3479
|
if (tx?.wait) await tx.wait();
|
|
2628
3480
|
}
|
|
2629
|
-
const votes = await getVotesLatestMinusOne({ provider, token:
|
|
3481
|
+
const votes = await getVotesLatestMinusOne({ provider, token: votingToken, account });
|
|
2630
3482
|
const ok = minVotes != null ? votes >= BigInt(minVotes) : votes > 0n;
|
|
2631
3483
|
return { txHash, ok, votes, payload };
|
|
2632
3484
|
},
|
|
@@ -2680,8 +3532,8 @@ var require_governance = __commonJS({
|
|
|
2680
3532
|
}
|
|
2681
3533
|
let votesOk = null;
|
|
2682
3534
|
try {
|
|
2683
|
-
const
|
|
2684
|
-
const votes = await getVotesLatestMinusOne({ provider, token:
|
|
3535
|
+
const { votingToken } = await resolveVotesTokenChain({ provider, governor });
|
|
3536
|
+
const votes = await getVotesLatestMinusOne({ provider, token: votingToken, account: user });
|
|
2685
3537
|
const th = threshold != null ? BigInt(threshold) : 0n;
|
|
2686
3538
|
votesOk = votes >= th;
|
|
2687
3539
|
} catch (_) {
|
|
@@ -3215,6 +4067,602 @@ var require_templates = __commonJS({
|
|
|
3215
4067
|
}
|
|
3216
4068
|
});
|
|
3217
4069
|
|
|
4070
|
+
// src/browser/utils.js
|
|
4071
|
+
var require_utils = __commonJS({
|
|
4072
|
+
"src/browser/utils.js"(exports2, module2) {
|
|
4073
|
+
function getAddress(address) {
|
|
4074
|
+
if (!address) return address;
|
|
4075
|
+
const addr = String(address).trim();
|
|
4076
|
+
const normalized = addr.startsWith("0x") ? addr.slice(2).toLowerCase() : addr.toLowerCase();
|
|
4077
|
+
return `0x${normalized}`;
|
|
4078
|
+
}
|
|
4079
|
+
async function keccak256Async(data) {
|
|
4080
|
+
const encoder = new TextEncoder();
|
|
4081
|
+
const dataBuffer = typeof data === "string" ? encoder.encode(data) : data;
|
|
4082
|
+
const hashBuffer = await crypto.subtle.digest("SHA-256", dataBuffer);
|
|
4083
|
+
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
4084
|
+
const hashHex = hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
4085
|
+
return `0x${hashHex}`;
|
|
4086
|
+
}
|
|
4087
|
+
function keccak256Sync(data) {
|
|
4088
|
+
const str = typeof data === "string" ? data : JSON.stringify(data);
|
|
4089
|
+
let hash = 0;
|
|
4090
|
+
for (let i = 0; i < str.length; i++) {
|
|
4091
|
+
const char = str.charCodeAt(i);
|
|
4092
|
+
hash = (hash << 5) - hash + char;
|
|
4093
|
+
hash = hash & hash;
|
|
4094
|
+
}
|
|
4095
|
+
const hex = Math.abs(hash).toString(16).padStart(8, "0");
|
|
4096
|
+
return `0x${hex.repeat(8)}`.slice(0, 66);
|
|
4097
|
+
}
|
|
4098
|
+
module2.exports = {
|
|
4099
|
+
getAddress,
|
|
4100
|
+
keccak256Async,
|
|
4101
|
+
keccak256Sync
|
|
4102
|
+
};
|
|
4103
|
+
}
|
|
4104
|
+
});
|
|
4105
|
+
|
|
4106
|
+
// src/browser/subgraph.js
|
|
4107
|
+
var require_subgraph2 = __commonJS({
|
|
4108
|
+
"src/browser/subgraph.js"(exports2, module2) {
|
|
4109
|
+
var { getAddress } = require_utils();
|
|
4110
|
+
function sanitizeOrderBy(orderBy, allowed, fallback) {
|
|
4111
|
+
const value = (orderBy || "").toString();
|
|
4112
|
+
return allowed.includes(value) ? value : fallback;
|
|
4113
|
+
}
|
|
4114
|
+
function sanitizeOrderDirection(direction, fallback = "desc") {
|
|
4115
|
+
const v = (direction || "").toString().toLowerCase();
|
|
4116
|
+
return v === "asc" ? "asc" : "desc";
|
|
4117
|
+
}
|
|
4118
|
+
function safeGetAddress(value) {
|
|
4119
|
+
try {
|
|
4120
|
+
return getAddress(value);
|
|
4121
|
+
} catch {
|
|
4122
|
+
return null;
|
|
4123
|
+
}
|
|
4124
|
+
}
|
|
4125
|
+
function mapSafe(list, mapper) {
|
|
4126
|
+
const out = [];
|
|
4127
|
+
for (const item of list || []) {
|
|
4128
|
+
try {
|
|
4129
|
+
const v = mapper(item);
|
|
4130
|
+
if (v != null) out.push(v);
|
|
4131
|
+
} catch {
|
|
4132
|
+
}
|
|
4133
|
+
}
|
|
4134
|
+
return out;
|
|
4135
|
+
}
|
|
4136
|
+
async function query(url, document, variables) {
|
|
4137
|
+
if (!url) throw new Error("subgraph url required");
|
|
4138
|
+
const controller = new AbortController();
|
|
4139
|
+
const timeoutId = setTimeout(() => controller.abort(), 1e4);
|
|
4140
|
+
try {
|
|
4141
|
+
const resp = await fetch(url, {
|
|
4142
|
+
method: "POST",
|
|
4143
|
+
headers: { "Content-Type": "application/json" },
|
|
4144
|
+
body: JSON.stringify({ query: document, variables }),
|
|
4145
|
+
signal: controller.signal
|
|
4146
|
+
});
|
|
4147
|
+
clearTimeout(timeoutId);
|
|
4148
|
+
if (!resp.ok) {
|
|
4149
|
+
throw new Error(`HTTP ${resp.status}: ${resp.statusText}`);
|
|
4150
|
+
}
|
|
4151
|
+
const data = await resp.json();
|
|
4152
|
+
if (data && data.errors) {
|
|
4153
|
+
throw new Error(data.errors.map((e) => e.message).join("; "));
|
|
4154
|
+
}
|
|
4155
|
+
return data.data;
|
|
4156
|
+
} catch (error) {
|
|
4157
|
+
clearTimeout(timeoutId);
|
|
4158
|
+
throw error;
|
|
4159
|
+
}
|
|
4160
|
+
}
|
|
4161
|
+
async function listProposals({ url, governor, first = 20, skip = 0 }) {
|
|
4162
|
+
const data = await query(url, `
|
|
4163
|
+
query($governor: Bytes!, $first: Int!, $skip: Int!) {
|
|
4164
|
+
proposals(where: { governor: $governor }, first: $first, skip: $skip, orderBy: createdAt, orderDirection: desc) {
|
|
4165
|
+
id
|
|
4166
|
+
proposer
|
|
4167
|
+
description
|
|
4168
|
+
createdAt
|
|
4169
|
+
targets
|
|
4170
|
+
values
|
|
4171
|
+
calldatas
|
|
4172
|
+
}
|
|
4173
|
+
}
|
|
4174
|
+
`, { governor: String(governor).toLowerCase(), first, skip });
|
|
4175
|
+
return mapSafe(data?.proposals, (p) => {
|
|
4176
|
+
const proposer = safeGetAddress(p.proposer);
|
|
4177
|
+
if (!proposer) return null;
|
|
4178
|
+
const targets = (p.targets || []).map((t) => safeGetAddress(t)).filter(Boolean);
|
|
4179
|
+
if (!targets.length && (p.targets || []).length) return null;
|
|
4180
|
+
return {
|
|
4181
|
+
id: BigInt(p.id),
|
|
4182
|
+
proposer,
|
|
4183
|
+
description: p.description,
|
|
4184
|
+
createdAt: Number(p.createdAt || 0),
|
|
4185
|
+
targets,
|
|
4186
|
+
values: (p.values || []).map((value) => BigInt(String(value))),
|
|
4187
|
+
calldatas: p.calldatas || []
|
|
4188
|
+
};
|
|
4189
|
+
});
|
|
4190
|
+
}
|
|
4191
|
+
var STATE_STRING_TO_NUMBER = {
|
|
4192
|
+
PENDING: 0,
|
|
4193
|
+
ACTIVE: 1,
|
|
4194
|
+
CANCELED: 2,
|
|
4195
|
+
CANCELLED: 2,
|
|
4196
|
+
// some indexes may use British spelling
|
|
4197
|
+
DEFEATED: 3,
|
|
4198
|
+
SUCCEEDED: 4,
|
|
4199
|
+
QUEUED: 5,
|
|
4200
|
+
EXPIRED: 6,
|
|
4201
|
+
EXECUTED: 7
|
|
4202
|
+
};
|
|
4203
|
+
async function listProposalsFiltered({ url, governor, states, fromTimestamp, toTimestamp, first = 20, skip = 0, orderBy = "createdAt", orderDirection = "desc" }) {
|
|
4204
|
+
const govLower = governor ? String(governor).toLowerCase() : null;
|
|
4205
|
+
const statesUpper = Array.isArray(states) && states.length ? states.map((s) => String(s).toUpperCase()) : null;
|
|
4206
|
+
const safeOrderBy = sanitizeOrderBy(orderBy, ["createdAt", "updatedAt", "eta"], "createdAt");
|
|
4207
|
+
const safeOrderDirection = sanitizeOrderDirection(orderDirection, "desc");
|
|
4208
|
+
const doc = `
|
|
4209
|
+
query($first: Int!, $skip: Int!, $governor: Bytes, $states: [String!], $from: Int, $to: Int) {
|
|
4210
|
+
proposals(
|
|
4211
|
+
where: {
|
|
4212
|
+
${governor ? "governor: $governor," : ""}
|
|
4213
|
+
${statesUpper ? "state_in: $states," : ""}
|
|
4214
|
+
${fromTimestamp !== void 0 ? "createdAt_gte: $from," : ""}
|
|
4215
|
+
${toTimestamp !== void 0 ? "createdAt_lte: $to," : ""}
|
|
4216
|
+
}
|
|
4217
|
+
first: $first
|
|
4218
|
+
skip: $skip
|
|
4219
|
+
orderBy: ${safeOrderBy}
|
|
4220
|
+
orderDirection: ${safeOrderDirection}
|
|
4221
|
+
) {
|
|
4222
|
+
id
|
|
4223
|
+
proposer
|
|
4224
|
+
description
|
|
4225
|
+
createdAt
|
|
4226
|
+
updatedAt
|
|
4227
|
+
state
|
|
4228
|
+
eta
|
|
4229
|
+
targets
|
|
4230
|
+
values
|
|
4231
|
+
calldatas
|
|
4232
|
+
}
|
|
4233
|
+
}
|
|
4234
|
+
`;
|
|
4235
|
+
const variables = { first, skip };
|
|
4236
|
+
if (govLower) variables.governor = govLower;
|
|
4237
|
+
if (statesUpper) variables.states = statesUpper;
|
|
4238
|
+
if (fromTimestamp !== void 0) variables.from = Number(fromTimestamp);
|
|
4239
|
+
if (toTimestamp !== void 0) variables.to = Number(toTimestamp);
|
|
4240
|
+
const data = await query(url, doc, variables);
|
|
4241
|
+
return mapSafe(data?.proposals, (p) => {
|
|
4242
|
+
const stateStr = String(p.state || "").toUpperCase();
|
|
4243
|
+
const stateNum = STATE_STRING_TO_NUMBER[stateStr] != null ? STATE_STRING_TO_NUMBER[stateStr] : null;
|
|
4244
|
+
const proposer = safeGetAddress(p.proposer);
|
|
4245
|
+
if (!proposer) return null;
|
|
4246
|
+
const targets = (p.targets || []).map((t) => safeGetAddress(t)).filter(Boolean);
|
|
4247
|
+
if (!targets.length && (p.targets || []).length) return null;
|
|
4248
|
+
return {
|
|
4249
|
+
id: BigInt(p.id),
|
|
4250
|
+
proposer,
|
|
4251
|
+
description: p.description || "",
|
|
4252
|
+
createdAt: Number(p.createdAt || 0),
|
|
4253
|
+
updatedAt: Number(p.updatedAt || 0),
|
|
4254
|
+
state: stateStr,
|
|
4255
|
+
stateNum,
|
|
4256
|
+
eta: p.eta ? BigInt(String(p.eta)) : null,
|
|
4257
|
+
targets,
|
|
4258
|
+
values: (p.values || []).map((value) => BigInt(String(value))),
|
|
4259
|
+
calldatas: p.calldatas || []
|
|
4260
|
+
};
|
|
4261
|
+
});
|
|
4262
|
+
}
|
|
4263
|
+
async function listLibraries({ url, subdao: subdao2, first = 50, skip = 0 }) {
|
|
4264
|
+
const where = subdao2 ? `where: { subDAO: "${String(subdao2).toLowerCase()}" }` : "";
|
|
4265
|
+
const data = await query(url, `
|
|
4266
|
+
query($first: Int!, $skip: Int!) {
|
|
4267
|
+
libraries(${where} first: $first, skip: $skip, orderBy: createdAt, orderDirection: desc) {
|
|
4268
|
+
id
|
|
4269
|
+
manifestCID
|
|
4270
|
+
subDAO
|
|
4271
|
+
proposer
|
|
4272
|
+
createdAt
|
|
4273
|
+
}
|
|
4274
|
+
}
|
|
4275
|
+
`, { first, skip });
|
|
4276
|
+
return mapSafe(data?.libraries, (lib) => {
|
|
4277
|
+
const sub = safeGetAddress(lib.subDAO);
|
|
4278
|
+
const proposer = safeGetAddress(lib.proposer);
|
|
4279
|
+
if (!sub || !proposer) return null;
|
|
4280
|
+
return {
|
|
4281
|
+
id: lib.id,
|
|
4282
|
+
manifestCID: lib.manifestCID,
|
|
4283
|
+
subdao: sub,
|
|
4284
|
+
proposer,
|
|
4285
|
+
createdAt: Number(lib.createdAt || 0)
|
|
4286
|
+
};
|
|
4287
|
+
});
|
|
4288
|
+
}
|
|
4289
|
+
async function getSubdaoLibraries({ url, subdao: subdao2, first = 20, skip = 0 }) {
|
|
4290
|
+
if (!url) throw new Error("subgraph url required");
|
|
4291
|
+
const hasFilter = !!subdao2;
|
|
4292
|
+
const whereClause = hasFilter ? "where:{ subdao:$subdao }" : "";
|
|
4293
|
+
const doc = `
|
|
4294
|
+
query($subdao:Bytes,$first:Int!,$skip:Int!){
|
|
4295
|
+
subDAOLibraryPointers(
|
|
4296
|
+
${whereClause}
|
|
4297
|
+
first:$first,
|
|
4298
|
+
skip:$skip,
|
|
4299
|
+
orderBy: updatedAt,
|
|
4300
|
+
orderDirection: desc
|
|
4301
|
+
){
|
|
4302
|
+
id
|
|
4303
|
+
subdao
|
|
4304
|
+
libraryId
|
|
4305
|
+
manifestCID
|
|
4306
|
+
previousCID
|
|
4307
|
+
promptCount
|
|
4308
|
+
updatedAt
|
|
4309
|
+
}
|
|
4310
|
+
}
|
|
4311
|
+
`;
|
|
4312
|
+
const variables = {
|
|
4313
|
+
first: Math.min(Math.max(1, Number(first || 20)), 100),
|
|
4314
|
+
skip
|
|
4315
|
+
};
|
|
4316
|
+
if (hasFilter) {
|
|
4317
|
+
const addr = safeGetAddress(subdao2);
|
|
4318
|
+
if (!addr) throw new Error("invalid subdao address");
|
|
4319
|
+
variables.subdao = addr.toLowerCase();
|
|
4320
|
+
}
|
|
4321
|
+
const data = await query(url, doc, variables);
|
|
4322
|
+
return mapSafe(data?.subDAOLibraryPointers, (row) => {
|
|
4323
|
+
const id2 = row?.id;
|
|
4324
|
+
const manifestCID = row?.manifestCID;
|
|
4325
|
+
const sub = safeGetAddress(row?.subdao);
|
|
4326
|
+
if (!id2 || !manifestCID || !sub) return null;
|
|
4327
|
+
return {
|
|
4328
|
+
id: String(id2),
|
|
4329
|
+
subdao: sub,
|
|
4330
|
+
libraryId: String(row.libraryId || "main"),
|
|
4331
|
+
manifestCID: String(manifestCID),
|
|
4332
|
+
previousCID: row.previousCID || null,
|
|
4333
|
+
promptCount: row.promptCount != null ? Number(row.promptCount) : null,
|
|
4334
|
+
updatedAt: row.updatedAt != null ? Number(row.updatedAt) : null
|
|
4335
|
+
};
|
|
4336
|
+
});
|
|
4337
|
+
}
|
|
4338
|
+
async function getSubdaoPrompts({ url, registry, first = 50, skip = 0, orderBy = "updatedAt", orderDirection = "desc" }) {
|
|
4339
|
+
if (!url) throw new Error("subgraph url required");
|
|
4340
|
+
const reg = safeGetAddress(registry);
|
|
4341
|
+
if (!reg) throw new Error("invalid registry address");
|
|
4342
|
+
const safeOrderBy = sanitizeOrderBy(orderBy, ["updatedAt"], "updatedAt");
|
|
4343
|
+
const safeOrderDirection = sanitizeOrderDirection(orderDirection, "desc");
|
|
4344
|
+
const doc = `
|
|
4345
|
+
query($registry:Bytes!,$first:Int!,$skip:Int!){
|
|
4346
|
+
prompts(
|
|
4347
|
+
where:{ registry:$registry },
|
|
4348
|
+
first:$first,
|
|
4349
|
+
skip:$skip,
|
|
4350
|
+
orderBy: ${safeOrderBy},
|
|
4351
|
+
orderDirection: ${safeOrderDirection}
|
|
4352
|
+
){
|
|
4353
|
+
id
|
|
4354
|
+
key
|
|
4355
|
+
cid
|
|
4356
|
+
version
|
|
4357
|
+
author
|
|
4358
|
+
registry
|
|
4359
|
+
updatedAt
|
|
4360
|
+
}
|
|
4361
|
+
}
|
|
4362
|
+
`;
|
|
4363
|
+
const data = await query(url, doc, {
|
|
4364
|
+
registry: reg.toLowerCase(),
|
|
4365
|
+
first: Math.min(Math.max(1, Number(first || 50)), 100),
|
|
4366
|
+
skip
|
|
4367
|
+
});
|
|
4368
|
+
return mapSafe(data?.prompts, (p) => {
|
|
4369
|
+
const author = safeGetAddress(p.author);
|
|
4370
|
+
const regAddr = safeGetAddress(p.registry);
|
|
4371
|
+
if (!author || !regAddr) return null;
|
|
4372
|
+
return {
|
|
4373
|
+
id: String(p.id),
|
|
4374
|
+
key: String(p.key),
|
|
4375
|
+
cid: String(p.cid),
|
|
4376
|
+
version: BigInt(p.version || "0"),
|
|
4377
|
+
author,
|
|
4378
|
+
registry: regAddr,
|
|
4379
|
+
updatedAt: Number(p.updatedAt || 0)
|
|
4380
|
+
};
|
|
4381
|
+
});
|
|
4382
|
+
}
|
|
4383
|
+
module2.exports = {
|
|
4384
|
+
query,
|
|
4385
|
+
listProposals,
|
|
4386
|
+
listProposalsFiltered,
|
|
4387
|
+
listLibraries,
|
|
4388
|
+
getSubdaoLibraries,
|
|
4389
|
+
getSubdaoPrompts,
|
|
4390
|
+
/**
|
|
4391
|
+
* Canonical proposal timeline. Tries common fields first, then event-style fallbacks.
|
|
4392
|
+
* Returns { id, createdAt, queuedAt, executedAt, canceledAt, eta, state } (numbers/strings may be null when unavailable).
|
|
4393
|
+
*/
|
|
4394
|
+
async getProposalTimeline({ url, id: id2 }) {
|
|
4395
|
+
if (!url) throw new Error("subgraph url required");
|
|
4396
|
+
const pid = typeof id2 === "bigint" ? id2.toString() : String(id2);
|
|
4397
|
+
try {
|
|
4398
|
+
const data = await query(url, `
|
|
4399
|
+
query($id: ID!) {
|
|
4400
|
+
proposal(id: $id) {
|
|
4401
|
+
id
|
|
4402
|
+
createdAt
|
|
4403
|
+
updatedAt
|
|
4404
|
+
state
|
|
4405
|
+
eta
|
|
4406
|
+
queuedAt
|
|
4407
|
+
executedAt
|
|
4408
|
+
canceledAt
|
|
4409
|
+
}
|
|
4410
|
+
}
|
|
4411
|
+
`, { id: pid });
|
|
4412
|
+
if (data && data.proposal) {
|
|
4413
|
+
const p = data.proposal;
|
|
4414
|
+
return {
|
|
4415
|
+
id: p.id,
|
|
4416
|
+
createdAt: Number(p.createdAt || 0),
|
|
4417
|
+
queuedAt: p.queuedAt != null ? Number(p.queuedAt) : null,
|
|
4418
|
+
executedAt: p.executedAt != null ? Number(p.executedAt) : null,
|
|
4419
|
+
canceledAt: p.canceledAt != null ? Number(p.canceledAt) : null,
|
|
4420
|
+
eta: p.eta != null ? BigInt(String(p.eta)) : null,
|
|
4421
|
+
state: String(p.state || "")
|
|
4422
|
+
};
|
|
4423
|
+
}
|
|
4424
|
+
} catch (_) {
|
|
4425
|
+
}
|
|
4426
|
+
try {
|
|
4427
|
+
const data = await query(url, `
|
|
4428
|
+
query($id: String!) {
|
|
4429
|
+
proposalEvents(where: { proposal: $id }, orderBy: timestamp, orderDirection: asc) {
|
|
4430
|
+
type
|
|
4431
|
+
timestamp
|
|
4432
|
+
}
|
|
4433
|
+
proposals(where: { id: $id }, first:1) { id createdAt state eta }
|
|
4434
|
+
}
|
|
4435
|
+
`, { id: pid });
|
|
4436
|
+
const events = (data?.proposalEvents || []).map((e) => ({ type: String(e.type || ""), timestamp: Number(e.timestamp || 0) }));
|
|
4437
|
+
const base = data?.proposals?.[0] || {};
|
|
4438
|
+
const find = (t) => events.find((e) => e.type.toLowerCase() === t)?.timestamp || null;
|
|
4439
|
+
return {
|
|
4440
|
+
id: base.id || pid,
|
|
4441
|
+
createdAt: Number(base.createdAt || 0),
|
|
4442
|
+
queuedAt: find("queued"),
|
|
4443
|
+
executedAt: find("executed"),
|
|
4444
|
+
canceledAt: find("canceled") || find("cancelled") || null,
|
|
4445
|
+
eta: base.eta != null ? BigInt(String(base.eta)) : null,
|
|
4446
|
+
state: String(base.state || "")
|
|
4447
|
+
};
|
|
4448
|
+
} catch (_) {
|
|
4449
|
+
}
|
|
4450
|
+
return { id: pid, createdAt: 0, queuedAt: null, executedAt: null, canceledAt: null, eta: null, state: "" };
|
|
4451
|
+
},
|
|
4452
|
+
async listLiquidityAddPlans({ url, subdao: subdao2 = null, first = 50, skip = 0, orderBy = "blockTimestamp", orderDirection = "desc" }) {
|
|
4453
|
+
if (!url) throw new Error("subgraph url required");
|
|
4454
|
+
const filters = [];
|
|
4455
|
+
if (subdao2) {
|
|
4456
|
+
const addr = safeGetAddress(subdao2);
|
|
4457
|
+
if (!addr) throw new Error("invalid subdao address");
|
|
4458
|
+
filters.push(`subdao: "${addr.toLowerCase()}"`);
|
|
4459
|
+
}
|
|
4460
|
+
const where = filters.length ? `where: { ${filters.join(", ")} }` : "";
|
|
4461
|
+
const safeOrderBy = sanitizeOrderBy(orderBy, ["blockTimestamp", "blockNumber"], "blockTimestamp");
|
|
4462
|
+
const safeOrderDirection = sanitizeOrderDirection(orderDirection, "desc");
|
|
4463
|
+
const doc = `
|
|
4464
|
+
query($first:Int!,$skip:Int!){
|
|
4465
|
+
liquidityAddPlans(${where} first:$first, skip:$skip, orderBy: ${safeOrderBy}, orderDirection: ${safeOrderDirection}){
|
|
4466
|
+
id subdao pool sxxxToken stableToken sxxxAmount stableAmount lpRecipient blockNumber blockTimestamp transactionHash
|
|
4467
|
+
}
|
|
4468
|
+
}
|
|
4469
|
+
`;
|
|
4470
|
+
const data = await query(url, doc, { first, skip });
|
|
4471
|
+
return mapSafe(data?.liquidityAddPlans, (e) => {
|
|
4472
|
+
const sub = safeGetAddress(e.subdao);
|
|
4473
|
+
const pool = safeGetAddress(e.pool);
|
|
4474
|
+
const sxxxToken = safeGetAddress(e.sxxxToken);
|
|
4475
|
+
const stableToken = safeGetAddress(e.stableToken);
|
|
4476
|
+
const lpRecipient = safeGetAddress(e.lpRecipient);
|
|
4477
|
+
if (!sub || !pool || !sxxxToken || !stableToken || !lpRecipient) return null;
|
|
4478
|
+
return {
|
|
4479
|
+
id: String(e.id),
|
|
4480
|
+
subdao: sub,
|
|
4481
|
+
pool,
|
|
4482
|
+
sxxxToken,
|
|
4483
|
+
stableToken,
|
|
4484
|
+
sxxxAmount: BigInt(String(e.sxxxAmount)),
|
|
4485
|
+
stableAmount: BigInt(String(e.stableAmount)),
|
|
4486
|
+
lpRecipient,
|
|
4487
|
+
blockNumber: Number(e.blockNumber || 0),
|
|
4488
|
+
blockTimestamp: Number(e.blockTimestamp || 0),
|
|
4489
|
+
transactionHash: e.transactionHash
|
|
4490
|
+
};
|
|
4491
|
+
});
|
|
4492
|
+
},
|
|
4493
|
+
async listLiquidityRemovePlans({ url, subdao: subdao2 = null, first = 50, skip = 0, orderBy = "blockTimestamp", orderDirection = "desc" }) {
|
|
4494
|
+
if (!url) throw new Error("subgraph url required");
|
|
4495
|
+
const filters = [];
|
|
4496
|
+
if (subdao2) {
|
|
4497
|
+
const addr = safeGetAddress(subdao2);
|
|
4498
|
+
if (!addr) throw new Error("invalid subdao address");
|
|
4499
|
+
filters.push(`subdao: "${addr.toLowerCase()}"`);
|
|
4500
|
+
}
|
|
4501
|
+
const where = filters.length ? `where: { ${filters.join(", ")} }` : "";
|
|
4502
|
+
const safeOrderBy = sanitizeOrderBy(orderBy, ["blockTimestamp", "blockNumber"], "blockTimestamp");
|
|
4503
|
+
const safeOrderDirection = sanitizeOrderDirection(orderDirection, "desc");
|
|
4504
|
+
const doc = `
|
|
4505
|
+
query($first:Int!,$skip:Int!){
|
|
4506
|
+
liquidityRemovePlans(${where} first:$first, skip:$skip, orderBy: ${safeOrderBy}, orderDirection: ${safeOrderDirection}){
|
|
4507
|
+
id subdao pool lpToken lpAmount recipient blockNumber blockTimestamp transactionHash
|
|
4508
|
+
}
|
|
4509
|
+
}
|
|
4510
|
+
`;
|
|
4511
|
+
const data = await query(url, doc, { first, skip });
|
|
4512
|
+
return mapSafe(data?.liquidityRemovePlans, (e) => {
|
|
4513
|
+
const sub = safeGetAddress(e.subdao);
|
|
4514
|
+
const pool = safeGetAddress(e.pool);
|
|
4515
|
+
const lpToken = safeGetAddress(e.lpToken);
|
|
4516
|
+
const recipient = safeGetAddress(e.recipient);
|
|
4517
|
+
if (!sub || !pool || !lpToken || !recipient) return null;
|
|
4518
|
+
return {
|
|
4519
|
+
id: String(e.id),
|
|
4520
|
+
subdao: sub,
|
|
4521
|
+
pool,
|
|
4522
|
+
lpToken,
|
|
4523
|
+
lpAmount: BigInt(String(e.lpAmount)),
|
|
4524
|
+
recipient,
|
|
4525
|
+
blockNumber: Number(e.blockNumber || 0),
|
|
4526
|
+
blockTimestamp: Number(e.blockTimestamp || 0),
|
|
4527
|
+
transactionHash: e.transactionHash
|
|
4528
|
+
};
|
|
4529
|
+
});
|
|
4530
|
+
},
|
|
4531
|
+
async listPromptsByTag({ url, tagsHash, registry = null, first = 50, skip = 0, orderBy = "updatedAt", orderDirection = "desc" }) {
|
|
4532
|
+
if (!url) throw new Error("subgraph url required");
|
|
4533
|
+
const clauses = [`tagsHash: "${String(tagsHash)}"`];
|
|
4534
|
+
if (registry) {
|
|
4535
|
+
const addr = safeGetAddress(registry);
|
|
4536
|
+
if (!addr) throw new Error("invalid registry address");
|
|
4537
|
+
clauses.push(`registry: "${addr.toLowerCase()}"`);
|
|
4538
|
+
}
|
|
4539
|
+
const where = `where: { ${clauses.join(", ")} }`;
|
|
4540
|
+
const safeOrderBy = sanitizeOrderBy(orderBy, ["updatedAt"], "updatedAt");
|
|
4541
|
+
const safeOrderDirection = sanitizeOrderDirection(orderDirection, "desc");
|
|
4542
|
+
const doc = `
|
|
4543
|
+
query($first:Int!,$skip:Int!) {
|
|
4544
|
+
prompts(${where} first:$first, skip:$skip, orderBy: ${safeOrderBy}, orderDirection: ${safeOrderDirection}) {
|
|
4545
|
+
id key cid version author registry updatedAt tagsHash
|
|
4546
|
+
}
|
|
4547
|
+
}
|
|
4548
|
+
`;
|
|
4549
|
+
const data = await query(url, doc, { first, skip });
|
|
4550
|
+
return mapSafe(data?.prompts, (p) => {
|
|
4551
|
+
const author = safeGetAddress(p.author);
|
|
4552
|
+
const regAddr = safeGetAddress(p.registry);
|
|
4553
|
+
if (!author || !regAddr) return null;
|
|
4554
|
+
return {
|
|
4555
|
+
id: String(p.id),
|
|
4556
|
+
key: String(p.key),
|
|
4557
|
+
cid: String(p.cid),
|
|
4558
|
+
version: BigInt(p.version || "0"),
|
|
4559
|
+
author,
|
|
4560
|
+
registry: regAddr,
|
|
4561
|
+
updatedAt: Number(p.updatedAt || 0),
|
|
4562
|
+
tagsHash: String(p.tagsHash || "")
|
|
4563
|
+
};
|
|
4564
|
+
});
|
|
4565
|
+
},
|
|
4566
|
+
// Prompt helpers (registry scoped)
|
|
4567
|
+
async listRegistryPrompts({ url, registry, first = 50, skip = 0, orderBy = "updatedAt", orderDirection = "desc" }) {
|
|
4568
|
+
if (!url) throw new Error("subgraph url required");
|
|
4569
|
+
const reg = safeGetAddress(registry);
|
|
4570
|
+
if (!reg) throw new Error("invalid registry address");
|
|
4571
|
+
const safeOrderBy = sanitizeOrderBy(orderBy, ["updatedAt"], "updatedAt");
|
|
4572
|
+
const safeOrderDirection = sanitizeOrderDirection(orderDirection, "desc");
|
|
4573
|
+
const doc = `
|
|
4574
|
+
query($first:Int!,$skip:Int!,$registry:Bytes!) {
|
|
4575
|
+
prompts(where:{ registry: $registry }, first:$first, skip:$skip, orderBy: ${safeOrderBy}, orderDirection: ${safeOrderDirection}) {
|
|
4576
|
+
id
|
|
4577
|
+
key
|
|
4578
|
+
cid
|
|
4579
|
+
version
|
|
4580
|
+
author
|
|
4581
|
+
registry
|
|
4582
|
+
updatedAt
|
|
4583
|
+
}
|
|
4584
|
+
}
|
|
4585
|
+
`;
|
|
4586
|
+
const data = await query(url, doc, { first, skip, registry: reg.toLowerCase() });
|
|
4587
|
+
return mapSafe(data?.prompts, (p) => {
|
|
4588
|
+
const author = safeGetAddress(p.author);
|
|
4589
|
+
const regAddr = safeGetAddress(p.registry);
|
|
4590
|
+
if (!author || !regAddr) return null;
|
|
4591
|
+
return {
|
|
4592
|
+
id: String(p.id),
|
|
4593
|
+
key: String(p.key),
|
|
4594
|
+
cid: String(p.cid),
|
|
4595
|
+
version: BigInt(p.version || "0"),
|
|
4596
|
+
author,
|
|
4597
|
+
registry: regAddr,
|
|
4598
|
+
updatedAt: Number(p.updatedAt || 0)
|
|
4599
|
+
};
|
|
4600
|
+
});
|
|
4601
|
+
},
|
|
4602
|
+
async getPromptByKey({ url, registry, key }) {
|
|
4603
|
+
if (!url) throw new Error("subgraph url required");
|
|
4604
|
+
const reg = safeGetAddress(registry);
|
|
4605
|
+
if (!reg) throw new Error("invalid registry address");
|
|
4606
|
+
const doc = `
|
|
4607
|
+
query($registry:Bytes!,$key:String!) {
|
|
4608
|
+
prompts(where:{ registry: $registry, key: $key }, first:1) {
|
|
4609
|
+
id
|
|
4610
|
+
key
|
|
4611
|
+
cid
|
|
4612
|
+
version
|
|
4613
|
+
author
|
|
4614
|
+
registry
|
|
4615
|
+
updatedAt
|
|
4616
|
+
}
|
|
4617
|
+
}
|
|
4618
|
+
`;
|
|
4619
|
+
const data = await query(url, doc, { registry: reg.toLowerCase(), key: String(key) });
|
|
4620
|
+
const p = (data?.prompts || [])[0];
|
|
4621
|
+
if (!p) return null;
|
|
4622
|
+
const author = safeGetAddress(p.author);
|
|
4623
|
+
const regAddr = safeGetAddress(p.registry);
|
|
4624
|
+
if (!author || !regAddr) return null;
|
|
4625
|
+
return {
|
|
4626
|
+
id: String(p.id),
|
|
4627
|
+
key: String(p.key),
|
|
4628
|
+
cid: String(p.cid),
|
|
4629
|
+
version: BigInt(p.version || "0"),
|
|
4630
|
+
author,
|
|
4631
|
+
registry: regAddr,
|
|
4632
|
+
updatedAt: Number(p.updatedAt || 0)
|
|
4633
|
+
};
|
|
4634
|
+
},
|
|
4635
|
+
async getProposalById({ url, id: id2 }) {
|
|
4636
|
+
if (!url) throw new Error("subgraph url required");
|
|
4637
|
+
const doc = `query($id: ID!){ proposal(id:$id){ id proposer description createdAt updatedAt state eta targets values calldatas } }`;
|
|
4638
|
+
const data = await query(url, doc, { id: String(id2) });
|
|
4639
|
+
const p = data?.proposal;
|
|
4640
|
+
if (!p) return null;
|
|
4641
|
+
try {
|
|
4642
|
+
const proposer = safeGetAddress(p.proposer);
|
|
4643
|
+
if (!proposer) return null;
|
|
4644
|
+
const targets = (p.targets || []).map((t) => safeGetAddress(t)).filter(Boolean);
|
|
4645
|
+
if (!targets.length && (p.targets || []).length) return null;
|
|
4646
|
+
return {
|
|
4647
|
+
id: BigInt(p.id),
|
|
4648
|
+
proposer,
|
|
4649
|
+
description: p.description || "",
|
|
4650
|
+
createdAt: Number(p.createdAt || 0),
|
|
4651
|
+
updatedAt: Number(p.updatedAt || 0),
|
|
4652
|
+
state: String(p.state || ""),
|
|
4653
|
+
eta: p.eta ? BigInt(String(p.eta)) : null,
|
|
4654
|
+
targets,
|
|
4655
|
+
values: (p.values || []).map((v) => BigInt(String(v))),
|
|
4656
|
+
calldatas: p.calldatas || []
|
|
4657
|
+
};
|
|
4658
|
+
} catch {
|
|
4659
|
+
return null;
|
|
4660
|
+
}
|
|
4661
|
+
}
|
|
4662
|
+
};
|
|
4663
|
+
}
|
|
4664
|
+
});
|
|
4665
|
+
|
|
3218
4666
|
// src/adapters/governance/openzeppelin.js
|
|
3219
4667
|
var require_openzeppelin = __commonJS({
|
|
3220
4668
|
"src/adapters/governance/openzeppelin.js"(exports2, module2) {
|
|
@@ -3569,6 +5017,7 @@ var require_operations = __commonJS({
|
|
|
3569
5017
|
cache = null,
|
|
3570
5018
|
fromBlock = 0,
|
|
3571
5019
|
helperAddress = null,
|
|
5020
|
+
subgraphUrl = null,
|
|
3572
5021
|
hints = {},
|
|
3573
5022
|
chunkSizeBlocks = 1e4,
|
|
3574
5023
|
lookBackBlocks = 2e3,
|
|
@@ -3582,6 +5031,27 @@ var require_operations = __commonJS({
|
|
|
3582
5031
|
const cached = await cacheAdapter.load(govAddr, id2);
|
|
3583
5032
|
if (cached) return cached;
|
|
3584
5033
|
}
|
|
5034
|
+
if (subgraphUrl) {
|
|
5035
|
+
try {
|
|
5036
|
+
const subgraph2 = require_subgraph2();
|
|
5037
|
+
const sgProposal = await subgraph2.getProposalById({ url: subgraphUrl, id: String(id2) });
|
|
5038
|
+
if (sgProposal && sgProposal.targets && sgProposal.targets.length > 0) {
|
|
5039
|
+
const tuple2 = {
|
|
5040
|
+
id: id2,
|
|
5041
|
+
governor: govAddr,
|
|
5042
|
+
targets: sgProposal.targets,
|
|
5043
|
+
values: sgProposal.values || [],
|
|
5044
|
+
calldatas: sgProposal.calldatas || [],
|
|
5045
|
+
description: sgProposal.description || "",
|
|
5046
|
+
descriptionHash: sgProposal.description ? keccak256(toUtf8Bytes(sgProposal.description)) : null,
|
|
5047
|
+
createdBlock: sgProposal.createdAt || null
|
|
5048
|
+
};
|
|
5049
|
+
if (cacheAdapter) await cacheAdapter.save(govAddr, id2, tuple2);
|
|
5050
|
+
return tuple2;
|
|
5051
|
+
}
|
|
5052
|
+
} catch (_) {
|
|
5053
|
+
}
|
|
5054
|
+
}
|
|
3585
5055
|
if (helperAddress) {
|
|
3586
5056
|
try {
|
|
3587
5057
|
const helperAbi = [
|
|
@@ -3795,8 +5265,14 @@ var require_operations = __commonJS({
|
|
|
3795
5265
|
]);
|
|
3796
5266
|
let resolvedSubDAO = subdao2;
|
|
3797
5267
|
if (!resolvedSubDAO) {
|
|
3798
|
-
|
|
3799
|
-
|
|
5268
|
+
try {
|
|
5269
|
+
const subDAOInterface = new Interface(["function subDAO() view returns (address)"]);
|
|
5270
|
+
const subdaoContract = new Contract(govAddr, subDAOInterface, provider);
|
|
5271
|
+
resolvedSubDAO = await subdaoContract.subDAO().catch(() => null);
|
|
5272
|
+
if (resolvedSubDAO === ZeroAddress) resolvedSubDAO = null;
|
|
5273
|
+
} catch {
|
|
5274
|
+
resolvedSubDAO = null;
|
|
5275
|
+
}
|
|
3800
5276
|
}
|
|
3801
5277
|
let mode = null;
|
|
3802
5278
|
let eligible = null;
|
|
@@ -3871,10 +5347,11 @@ var require_operations = __commonJS({
|
|
|
3871
5347
|
refresh = false,
|
|
3872
5348
|
cache = null,
|
|
3873
5349
|
includeTimeline = false,
|
|
3874
|
-
helperAddress = null
|
|
5350
|
+
helperAddress = null,
|
|
5351
|
+
subgraphUrl = null
|
|
3875
5352
|
}) {
|
|
3876
5353
|
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
|
|
3877
|
-
const tuple = await resolveProposalTuple({ provider, governor, proposalId, refresh, cache, helperAddress });
|
|
5354
|
+
const tuple = await resolveProposalTuple({ provider, governor, proposalId, refresh, cache, helperAddress, subgraphUrl });
|
|
3878
5355
|
let proposal = null;
|
|
3879
5356
|
try {
|
|
3880
5357
|
proposal = await governance2.getProposal({ provider, governor: tuple.governor, id: tuple.id });
|
|
@@ -4212,8 +5689,6 @@ var require_factory = __commonJS({
|
|
|
4212
5689
|
stableCreationFee,
|
|
4213
5690
|
feeReceiver,
|
|
4214
5691
|
allowStableFee,
|
|
4215
|
-
stablePromptForkFee,
|
|
4216
|
-
allowStablePromptForkFee,
|
|
4217
5692
|
stableForkFee,
|
|
4218
5693
|
allowStableForkFee,
|
|
4219
5694
|
timelockMinDelay,
|
|
@@ -4237,8 +5712,6 @@ var require_factory = __commonJS({
|
|
|
4237
5712
|
}
|
|
4238
5713
|
})(),
|
|
4239
5714
|
contract.allowStableFee().catch(() => null),
|
|
4240
|
-
contract.stablePromptForkFee().catch(() => null),
|
|
4241
|
-
contract.allowStablePromptForkFee().catch(() => null),
|
|
4242
5715
|
contract.stableForkFee().catch(() => null),
|
|
4243
5716
|
contract.allowStableForkFee().catch(() => null),
|
|
4244
5717
|
contract.timelockMinDelay().catch(() => null),
|
|
@@ -4254,8 +5727,6 @@ var require_factory = __commonJS({
|
|
|
4254
5727
|
stableCreationFee,
|
|
4255
5728
|
feeReceiver: feeReceiver && feeReceiver !== "0x0000000000000000000000000000000000000000" ? getAddress(feeReceiver) : null,
|
|
4256
5729
|
allowStableFee,
|
|
4257
|
-
stablePromptForkFee,
|
|
4258
|
-
allowStablePromptForkFee,
|
|
4259
5730
|
stableForkFee,
|
|
4260
5731
|
allowStableForkFee,
|
|
4261
5732
|
timelockMinDelay,
|
|
@@ -4587,6 +6058,113 @@ var require_factory = __commonJS({
|
|
|
4587
6058
|
}
|
|
4588
6059
|
});
|
|
4589
6060
|
|
|
6061
|
+
// src/lineage/index.js
|
|
6062
|
+
var require_lineage = __commonJS({
|
|
6063
|
+
"src/lineage/index.js"(exports2, module2) {
|
|
6064
|
+
var { Contract, getAddress } = require("ethers");
|
|
6065
|
+
var { SageSDKError, CODES } = require_errors();
|
|
6066
|
+
var LINEAGE_ABI = [
|
|
6067
|
+
"function libraryByDAO(address) view returns (string manifestCID, address lastUpdater, uint256 lastUpdated, string version, address forkedFromDAO, uint256 sxxxForkFee)",
|
|
6068
|
+
"function getLibraryForkFee(address) view returns (uint256)"
|
|
6069
|
+
];
|
|
6070
|
+
var ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
6071
|
+
function normalise(address, label) {
|
|
6072
|
+
if (!address) throw new SageSDKError(CODES.INVALID_ARGS, `${label} required`);
|
|
6073
|
+
try {
|
|
6074
|
+
return getAddress(address);
|
|
6075
|
+
} catch (err) {
|
|
6076
|
+
throw new SageSDKError(CODES.INVALID_ARGS, `invalid ${label}`, { cause: err });
|
|
6077
|
+
}
|
|
6078
|
+
}
|
|
6079
|
+
async function getParentLibrary({ provider, registry, subdao: subdao2 }) {
|
|
6080
|
+
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
|
|
6081
|
+
if (!registry) throw new SageSDKError(CODES.INVALID_ARGS, "registry required");
|
|
6082
|
+
if (!subdao2) throw new SageSDKError(CODES.INVALID_ARGS, "subdao required");
|
|
6083
|
+
try {
|
|
6084
|
+
const contract = new Contract(normalise(registry, "registry"), LINEAGE_ABI, provider);
|
|
6085
|
+
const info = await contract.libraryByDAO(normalise(subdao2, "subdao"));
|
|
6086
|
+
const parent = info.forkedFromDAO;
|
|
6087
|
+
if (!parent || parent === ZERO_ADDRESS) {
|
|
6088
|
+
return null;
|
|
6089
|
+
}
|
|
6090
|
+
return getAddress(parent).toLowerCase();
|
|
6091
|
+
} catch (err) {
|
|
6092
|
+
throw new SageSDKError(CODES.CONTRACT_ERROR, "Failed to fetch parent library", { cause: err });
|
|
6093
|
+
}
|
|
6094
|
+
}
|
|
6095
|
+
async function getLineageChain({ provider, registry, subdao: subdao2 }) {
|
|
6096
|
+
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
|
|
6097
|
+
if (!registry) throw new SageSDKError(CODES.INVALID_ARGS, "registry required");
|
|
6098
|
+
if (!subdao2) throw new SageSDKError(CODES.INVALID_ARGS, "subdao required");
|
|
6099
|
+
try {
|
|
6100
|
+
const contract = new Contract(normalise(registry, "registry"), LINEAGE_ABI, provider);
|
|
6101
|
+
const chain = [];
|
|
6102
|
+
let current = normalise(subdao2, "subdao");
|
|
6103
|
+
const MAX_DEPTH = 100;
|
|
6104
|
+
let iterations = 0;
|
|
6105
|
+
while (current && iterations < MAX_DEPTH) {
|
|
6106
|
+
chain.unshift(getAddress(current).toLowerCase());
|
|
6107
|
+
const info = await contract.libraryByDAO(current);
|
|
6108
|
+
const parent = info.forkedFromDAO;
|
|
6109
|
+
if (!parent || parent === ZERO_ADDRESS) {
|
|
6110
|
+
break;
|
|
6111
|
+
}
|
|
6112
|
+
current = parent;
|
|
6113
|
+
iterations++;
|
|
6114
|
+
}
|
|
6115
|
+
return {
|
|
6116
|
+
chain,
|
|
6117
|
+
depth: chain.length - 1,
|
|
6118
|
+
root: chain[0]
|
|
6119
|
+
};
|
|
6120
|
+
} catch (err) {
|
|
6121
|
+
throw new SageSDKError(CODES.CONTRACT_ERROR, "Failed to fetch lineage chain", { cause: err });
|
|
6122
|
+
}
|
|
6123
|
+
}
|
|
6124
|
+
async function isFork({ provider, registry, subdao: subdao2 }) {
|
|
6125
|
+
const parent = await getParentLibrary({ provider, registry, subdao: subdao2 });
|
|
6126
|
+
return parent !== null;
|
|
6127
|
+
}
|
|
6128
|
+
async function getLibraryForkFee({ provider, registry, subdao: subdao2 }) {
|
|
6129
|
+
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
|
|
6130
|
+
if (!registry) throw new SageSDKError(CODES.INVALID_ARGS, "registry required");
|
|
6131
|
+
if (!subdao2) throw new SageSDKError(CODES.INVALID_ARGS, "subdao required");
|
|
6132
|
+
try {
|
|
6133
|
+
const contract = new Contract(normalise(registry, "registry"), LINEAGE_ABI, provider);
|
|
6134
|
+
const fee = await contract.getLibraryForkFee(normalise(subdao2, "subdao"));
|
|
6135
|
+
return BigInt(fee.toString());
|
|
6136
|
+
} catch (err) {
|
|
6137
|
+
throw new SageSDKError(CODES.CONTRACT_ERROR, "Failed to fetch library fork fee", { cause: err });
|
|
6138
|
+
}
|
|
6139
|
+
}
|
|
6140
|
+
async function getLibraryInfo({ provider, registry, subdao: subdao2 }) {
|
|
6141
|
+
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
|
|
6142
|
+
if (!registry) throw new SageSDKError(CODES.INVALID_ARGS, "registry required");
|
|
6143
|
+
if (!subdao2) throw new SageSDKError(CODES.INVALID_ARGS, "subdao required");
|
|
6144
|
+
try {
|
|
6145
|
+
const contract = new Contract(normalise(registry, "registry"), LINEAGE_ABI, provider);
|
|
6146
|
+
const info = await contract.libraryByDAO(normalise(subdao2, "subdao"));
|
|
6147
|
+
const parent = info.forkedFromDAO;
|
|
6148
|
+
return {
|
|
6149
|
+
parentDAO: !parent || parent === ZERO_ADDRESS ? null : getAddress(parent).toLowerCase(),
|
|
6150
|
+
forkFee: BigInt(info.sxxxForkFee.toString()),
|
|
6151
|
+
manifestCID: info.manifestCID,
|
|
6152
|
+
version: info.version
|
|
6153
|
+
};
|
|
6154
|
+
} catch (err) {
|
|
6155
|
+
throw new SageSDKError(CODES.CONTRACT_ERROR, "Failed to fetch library info", { cause: err });
|
|
6156
|
+
}
|
|
6157
|
+
}
|
|
6158
|
+
module2.exports = {
|
|
6159
|
+
getParentLibrary,
|
|
6160
|
+
getLineageChain,
|
|
6161
|
+
isFork,
|
|
6162
|
+
getLibraryForkFee,
|
|
6163
|
+
getLibraryInfo
|
|
6164
|
+
};
|
|
6165
|
+
}
|
|
6166
|
+
});
|
|
6167
|
+
|
|
4590
6168
|
// src/prompt/execute.js
|
|
4591
6169
|
var require_execute = __commonJS({
|
|
4592
6170
|
"src/prompt/execute.js"(exports2, module2) {
|
|
@@ -5259,7 +6837,6 @@ var require_ipns = __commonJS({
|
|
|
5259
6837
|
headers["X-Wallet-Address"] = auth.address;
|
|
5260
6838
|
headers["X-Wallet-Signature"] = auth.signature;
|
|
5261
6839
|
headers["X-Wallet-Nonce"] = auth.nonce;
|
|
5262
|
-
headers["X-Wallet-Message"] = auth.message;
|
|
5263
6840
|
}
|
|
5264
6841
|
return { headers, auth };
|
|
5265
6842
|
}
|
|
@@ -5281,8 +6858,7 @@ var require_ipns = __commonJS({
|
|
|
5281
6858
|
...extraHeaders,
|
|
5282
6859
|
"X-Wallet-Address": auth.address,
|
|
5283
6860
|
"X-Wallet-Signature": auth.signature,
|
|
5284
|
-
"X-Wallet-Nonce": auth.nonce
|
|
5285
|
-
"X-Wallet-Message": auth.message
|
|
6861
|
+
"X-Wallet-Nonce": auth.nonce
|
|
5286
6862
|
};
|
|
5287
6863
|
return { headers, auth };
|
|
5288
6864
|
}
|
|
@@ -5919,8 +7495,34 @@ var require_time = __commonJS({
|
|
|
5919
7495
|
var require_treasury = __commonJS({
|
|
5920
7496
|
"src/treasury/index.js"(exports2, module2) {
|
|
5921
7497
|
var { Contract, Interface, getAddress } = require("ethers");
|
|
5922
|
-
var ABI = require_abi();
|
|
5923
7498
|
var { SageSDKError, CODES } = require_errors();
|
|
7499
|
+
var SAGE_TREASURY_ABI = [
|
|
7500
|
+
// Aggregated views
|
|
7501
|
+
"function totalReserves() view returns (uint256)",
|
|
7502
|
+
"function totalPOL() view returns (uint256)",
|
|
7503
|
+
"function totalDebt() view returns (uint256)",
|
|
7504
|
+
// Canonical liquidity config
|
|
7505
|
+
"function canonicalPool() view returns (address)",
|
|
7506
|
+
"function routerOrVault() view returns (address)",
|
|
7507
|
+
// Withdrawal rate limits
|
|
7508
|
+
"function maxWithdrawalRate() view returns (uint256)",
|
|
7509
|
+
"function emergencyWithdrawalLimit() view returns (uint256)",
|
|
7510
|
+
// Reserve tokens
|
|
7511
|
+
"function getReserveTokens() view returns (address[])",
|
|
7512
|
+
"function getReserve(address token) view returns (tuple(uint256 amount, uint256 value, bool isLP, bool isActive))",
|
|
7513
|
+
// Withdrawal queue
|
|
7514
|
+
"function nextWithdrawalId() view returns (uint256)",
|
|
7515
|
+
"function pendingWithdrawals(uint256 id) view returns (tuple(bool exists, address token, address recipient, uint256 amount, uint256 value, address requester, uint256 balanceBefore, uint256 recipientBalanceBefore, uint256 depositSnapshot, bool isLP, bool isEmergency))",
|
|
7516
|
+
"function withdraw(address token, uint256 amount, address recipient)",
|
|
7517
|
+
"function confirmWithdrawal(uint256 id)",
|
|
7518
|
+
"function cancelWithdrawal(uint256 id)",
|
|
7519
|
+
// Manual price overrides
|
|
7520
|
+
"function manualPrices(address token) view returns (tuple(uint256 price, uint256 expiresAt, bool active))",
|
|
7521
|
+
"function setPriceOverride(address token, uint256 price, uint256 ttlSeconds)",
|
|
7522
|
+
"function clearPriceOverride(address token)",
|
|
7523
|
+
// Events
|
|
7524
|
+
"event WithdrawalScheduled(uint256 indexed id, address indexed token, address indexed recipient, uint256 amount)"
|
|
7525
|
+
];
|
|
5924
7526
|
var LiquidityEvents = new Interface([
|
|
5925
7527
|
"event CanonicalLiquidityUpdated(address indexed pool, address indexed routerOrVault)",
|
|
5926
7528
|
"event LiquidityAddPlanned(address indexed subdao, address indexed pool, address sxxxToken, address stableToken, uint256 sxxxAmount, uint256 stableAmount, address lpRecipient)",
|
|
@@ -5965,7 +7567,7 @@ var require_treasury = __commonJS({
|
|
|
5965
7567
|
async function getTreasuryInfo({ provider, treasury: treasury2 }) {
|
|
5966
7568
|
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
|
|
5967
7569
|
const addr = normalise(treasury2, "treasury");
|
|
5968
|
-
const contract = new Contract(addr,
|
|
7570
|
+
const contract = new Contract(addr, SAGE_TREASURY_ABI, provider);
|
|
5969
7571
|
const [totalReserves, totalPOL, totalDebt, canonicalPool, routerOrVault, maxWithdrawalRate, emergencyWithdrawalLimit] = await Promise.all([
|
|
5970
7572
|
contract.totalReserves().catch(() => 0n),
|
|
5971
7573
|
contract.totalPOL().catch(() => 0n),
|
|
@@ -5989,7 +7591,7 @@ var require_treasury = __commonJS({
|
|
|
5989
7591
|
async function getPendingWithdrawals({ provider, treasury: treasury2, ids, limit = 50 }) {
|
|
5990
7592
|
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
|
|
5991
7593
|
const addr = normalise(treasury2, "treasury");
|
|
5992
|
-
const contract = new Contract(addr,
|
|
7594
|
+
const contract = new Contract(addr, SAGE_TREASURY_ABI, provider);
|
|
5993
7595
|
let idList = ids;
|
|
5994
7596
|
if (!Array.isArray(idList)) {
|
|
5995
7597
|
const nextId = await contract.nextWithdrawalId().catch(() => 0n);
|
|
@@ -6021,14 +7623,14 @@ var require_treasury = __commonJS({
|
|
|
6021
7623
|
async function getReserveTokens({ provider, treasury: treasury2 }) {
|
|
6022
7624
|
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
|
|
6023
7625
|
const addr = normalise(treasury2, "treasury");
|
|
6024
|
-
const contract = new Contract(addr,
|
|
7626
|
+
const contract = new Contract(addr, SAGE_TREASURY_ABI, provider);
|
|
6025
7627
|
const tokens = await contract.getReserveTokens().catch(() => []);
|
|
6026
7628
|
return tokens.map((token2) => getAddress(token2));
|
|
6027
7629
|
}
|
|
6028
7630
|
async function getReserves({ provider, treasury: treasury2, tokens, fetchMetadata = true }) {
|
|
6029
7631
|
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
|
|
6030
7632
|
const addr = normalise(treasury2, "treasury");
|
|
6031
|
-
const contract = new Contract(addr,
|
|
7633
|
+
const contract = new Contract(addr, SAGE_TREASURY_ABI, provider);
|
|
6032
7634
|
const tokenList = Array.isArray(tokens) && tokens.length ? tokens.map((token2) => getAddress(token2)) : await contract.getReserveTokens().catch(() => []);
|
|
6033
7635
|
const reserves = [];
|
|
6034
7636
|
for (const token2 of tokenList) {
|
|
@@ -6058,7 +7660,7 @@ var require_treasury = __commonJS({
|
|
|
6058
7660
|
async function getManualPriceOverrides({ provider, treasury: treasury2, tokens }) {
|
|
6059
7661
|
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
|
|
6060
7662
|
const addr = normalise(treasury2, "treasury");
|
|
6061
|
-
const contract = new Contract(addr,
|
|
7663
|
+
const contract = new Contract(addr, SAGE_TREASURY_ABI, provider);
|
|
6062
7664
|
const tokenList = Array.isArray(tokens) && tokens.length ? tokens.map((token2) => getAddress(token2)) : await contract.getReserveTokens().catch(() => []);
|
|
6063
7665
|
const overrides = [];
|
|
6064
7666
|
for (const token2 of tokenList) {
|
|
@@ -6163,7 +7765,7 @@ var require_treasury = __commonJS({
|
|
|
6163
7765
|
async function getLPContribution({ provider, treasury: treasury2, subdao: subdao2, token: token2 }) {
|
|
6164
7766
|
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
|
|
6165
7767
|
const addr = normalise(treasury2, "treasury");
|
|
6166
|
-
const c = new Contract(addr,
|
|
7768
|
+
const c = new Contract(addr, SAGE_TREASURY_ABI, provider);
|
|
6167
7769
|
const amount = await c.lpContributions(normalise(subdao2, "subdao"), normalise(token2, "token")).catch(() => 0n);
|
|
6168
7770
|
return amount;
|
|
6169
7771
|
}
|
|
@@ -6205,7 +7807,7 @@ var require_treasury = __commonJS({
|
|
|
6205
7807
|
function createWriteContract({ signer, treasury: treasury2 }) {
|
|
6206
7808
|
if (!signer) throw new SageSDKError(CODES.INVALID_ARGS, "signer required");
|
|
6207
7809
|
const addr = normalise(treasury2, "treasury");
|
|
6208
|
-
return new Contract(addr,
|
|
7810
|
+
return new Contract(addr, SAGE_TREASURY_ABI, signer);
|
|
6209
7811
|
}
|
|
6210
7812
|
async function waitForReceipt({ signer, tx, waitMs }) {
|
|
6211
7813
|
const provider = signer.provider;
|
|
@@ -6509,6 +8111,350 @@ var require_bounty = __commonJS({
|
|
|
6509
8111
|
}
|
|
6510
8112
|
});
|
|
6511
8113
|
|
|
8114
|
+
// src/votingMultiplier/index.js
|
|
8115
|
+
var require_votingMultiplier = __commonJS({
|
|
8116
|
+
"src/votingMultiplier/index.js"(exports2, module2) {
|
|
8117
|
+
var { Contract, Interface, getAddress } = require("ethers");
|
|
8118
|
+
var ABI = require_abi();
|
|
8119
|
+
var { SageSDKError, CODES } = require_errors();
|
|
8120
|
+
function normaliseAddress(address, label) {
|
|
8121
|
+
if (!address) throw new SageSDKError(CODES.INVALID_ARGS, `${label} required`);
|
|
8122
|
+
try {
|
|
8123
|
+
return getAddress(address);
|
|
8124
|
+
} catch (err) {
|
|
8125
|
+
throw new SageSDKError(CODES.INVALID_ARGS, `invalid ${label}`, { cause: err });
|
|
8126
|
+
}
|
|
8127
|
+
}
|
|
8128
|
+
function toBigInt(value, label) {
|
|
8129
|
+
if (value === void 0 || value === null) {
|
|
8130
|
+
throw new SageSDKError(CODES.INVALID_ARGS, `${label} required`);
|
|
8131
|
+
}
|
|
8132
|
+
try {
|
|
8133
|
+
return BigInt(value.toString());
|
|
8134
|
+
} catch (err) {
|
|
8135
|
+
throw new SageSDKError(CODES.INVALID_ARGS, `invalid ${label}`, { cause: err });
|
|
8136
|
+
}
|
|
8137
|
+
}
|
|
8138
|
+
function getNftContract(provider, nft) {
|
|
8139
|
+
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
|
|
8140
|
+
const addr = normaliseAddress(nft, "nft");
|
|
8141
|
+
return new Contract(addr, ABI.VotingMultiplierNFT, provider);
|
|
8142
|
+
}
|
|
8143
|
+
function getWrapperContract(provider, wrapper) {
|
|
8144
|
+
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
|
|
8145
|
+
const addr = normaliseAddress(wrapper, "wrapper");
|
|
8146
|
+
return new Contract(addr, ABI.MultipliedVotes, provider);
|
|
8147
|
+
}
|
|
8148
|
+
async function getTier({ provider, nft, tierId }) {
|
|
8149
|
+
const c = getNftContract(provider, nft);
|
|
8150
|
+
const id2 = toBigInt(tierId, "tierId");
|
|
8151
|
+
let tier;
|
|
8152
|
+
if (typeof c.getTier === "function") {
|
|
8153
|
+
tier = await c.getTier(id2);
|
|
8154
|
+
} else {
|
|
8155
|
+
tier = await c.tiers(id2);
|
|
8156
|
+
}
|
|
8157
|
+
const name = String(tier.name ?? tier[0]);
|
|
8158
|
+
const multiplier = BigInt((tier.multiplier ?? tier[1]).toString());
|
|
8159
|
+
const maxSupply = BigInt((tier.maxSupply ?? tier[2]).toString());
|
|
8160
|
+
const minted = BigInt((tier.minted ?? tier[3]).toString());
|
|
8161
|
+
const price = BigInt((tier.price ?? tier[4]).toString());
|
|
8162
|
+
const dao = getAddress(tier.dao ?? tier[5]);
|
|
8163
|
+
return { name, multiplier, maxSupply, minted, price, dao };
|
|
8164
|
+
}
|
|
8165
|
+
async function getTierCount({ provider, nft }) {
|
|
8166
|
+
const c = getNftContract(provider, nft);
|
|
8167
|
+
const count = await c.tierCount();
|
|
8168
|
+
return BigInt(count.toString());
|
|
8169
|
+
}
|
|
8170
|
+
function buildCreateTierTx({ nft, dao, name, multiplier, maxSupply, price }) {
|
|
8171
|
+
const addr = normaliseAddress(nft, "nft");
|
|
8172
|
+
const iface = new Interface(ABI.VotingMultiplierNFT);
|
|
8173
|
+
const data = iface.encodeFunctionData("createTier", [
|
|
8174
|
+
normaliseAddress(dao, "dao"),
|
|
8175
|
+
String(name ?? ""),
|
|
8176
|
+
toBigInt(multiplier, "multiplier"),
|
|
8177
|
+
toBigInt(maxSupply, "maxSupply"),
|
|
8178
|
+
toBigInt(price, "price")
|
|
8179
|
+
]);
|
|
8180
|
+
return { to: addr, data, value: 0n };
|
|
8181
|
+
}
|
|
8182
|
+
function buildMintTx({ nft, to, tierId, uri }) {
|
|
8183
|
+
const addr = normaliseAddress(nft, "nft");
|
|
8184
|
+
const iface = new Interface(ABI.VotingMultiplierNFT);
|
|
8185
|
+
const data = iface.encodeFunctionData("mint", [
|
|
8186
|
+
normaliseAddress(to, "to"),
|
|
8187
|
+
toBigInt(tierId, "tierId"),
|
|
8188
|
+
String(uri ?? "")
|
|
8189
|
+
]);
|
|
8190
|
+
return { to: addr, data, value: 0n };
|
|
8191
|
+
}
|
|
8192
|
+
function buildPublicMintTx({ nft, tierId, uri, value }) {
|
|
8193
|
+
const addr = normaliseAddress(nft, "nft");
|
|
8194
|
+
const iface = new Interface(ABI.VotingMultiplierNFT);
|
|
8195
|
+
const data = iface.encodeFunctionData("publicMint", [
|
|
8196
|
+
toBigInt(tierId, "tierId"),
|
|
8197
|
+
String(uri ?? "")
|
|
8198
|
+
]);
|
|
8199
|
+
return { to: addr, data, value: toBigInt(value ?? 0n, "value") };
|
|
8200
|
+
}
|
|
8201
|
+
async function getMultiplier({ provider, nft, account, dao }) {
|
|
8202
|
+
const c = getNftContract(provider, nft);
|
|
8203
|
+
const res = await c.getMultiplier(normaliseAddress(account, "account"), normaliseAddress(dao, "dao"));
|
|
8204
|
+
return BigInt(res.toString());
|
|
8205
|
+
}
|
|
8206
|
+
async function getPastMultiplier({ provider, nft, account, dao, timepoint }) {
|
|
8207
|
+
const c = getNftContract(provider, nft);
|
|
8208
|
+
const res = await c.getPastMultiplier(
|
|
8209
|
+
normaliseAddress(account, "account"),
|
|
8210
|
+
normaliseAddress(dao, "dao"),
|
|
8211
|
+
toBigInt(timepoint, "timepoint")
|
|
8212
|
+
);
|
|
8213
|
+
return BigInt(res.toString());
|
|
8214
|
+
}
|
|
8215
|
+
async function getTokenMultiplier({ provider, nft, tokenId }) {
|
|
8216
|
+
const c = getNftContract(provider, nft);
|
|
8217
|
+
const res = await c.getTokenMultiplier(toBigInt(tokenId, "tokenId"));
|
|
8218
|
+
return BigInt(res.toString());
|
|
8219
|
+
}
|
|
8220
|
+
async function getTokenDAO({ provider, nft, tokenId }) {
|
|
8221
|
+
const c = getNftContract(provider, nft);
|
|
8222
|
+
const res = await c.getTokenDAO(toBigInt(tokenId, "tokenId"));
|
|
8223
|
+
return getAddress(res);
|
|
8224
|
+
}
|
|
8225
|
+
async function getTokenInfo({ provider, nft, tokenId }) {
|
|
8226
|
+
const c = getNftContract(provider, nft);
|
|
8227
|
+
const id2 = toBigInt(tokenId, "tokenId");
|
|
8228
|
+
const info = await c.getTokenInfo(id2);
|
|
8229
|
+
const owner = getAddress(info.owner ?? info[0]);
|
|
8230
|
+
const tierId = BigInt((info.tierId ?? info[1]).toString());
|
|
8231
|
+
const multiplier = BigInt((info.multiplier ?? info[2]).toString());
|
|
8232
|
+
const uri = String(info.uri ?? info[3]);
|
|
8233
|
+
return { owner, tierId, multiplier, uri };
|
|
8234
|
+
}
|
|
8235
|
+
async function getVotes({ provider, wrapper, account }) {
|
|
8236
|
+
const c = getWrapperContract(provider, wrapper);
|
|
8237
|
+
const res = await c.getVotes(normaliseAddress(account, "account"));
|
|
8238
|
+
return BigInt(res.toString());
|
|
8239
|
+
}
|
|
8240
|
+
async function getPastVotes({ provider, wrapper, account, timepoint }) {
|
|
8241
|
+
const c = getWrapperContract(provider, wrapper);
|
|
8242
|
+
const res = await c.getPastVotes(
|
|
8243
|
+
normaliseAddress(account, "account"),
|
|
8244
|
+
toBigInt(timepoint, "timepoint")
|
|
8245
|
+
);
|
|
8246
|
+
return BigInt(res.toString());
|
|
8247
|
+
}
|
|
8248
|
+
async function getVotingBreakdown({ provider, wrapper, account }) {
|
|
8249
|
+
const c = getWrapperContract(provider, wrapper);
|
|
8250
|
+
const [baseVotes, multiplier, effectiveVotes] = await c.getVotingBreakdown(normaliseAddress(account, "account"));
|
|
8251
|
+
return {
|
|
8252
|
+
baseVotes: BigInt(baseVotes.toString()),
|
|
8253
|
+
multiplier: BigInt(multiplier.toString()),
|
|
8254
|
+
effectiveVotes: BigInt(effectiveVotes.toString())
|
|
8255
|
+
};
|
|
8256
|
+
}
|
|
8257
|
+
async function getPastVotingBreakdown({ provider, wrapper, account, timepoint }) {
|
|
8258
|
+
const c = getWrapperContract(provider, wrapper);
|
|
8259
|
+
const [baseVotes, multiplier, effectiveVotes] = await c.getPastVotingBreakdown(
|
|
8260
|
+
normaliseAddress(account, "account"),
|
|
8261
|
+
toBigInt(timepoint, "timepoint")
|
|
8262
|
+
);
|
|
8263
|
+
return {
|
|
8264
|
+
baseVotes: BigInt(baseVotes.toString()),
|
|
8265
|
+
multiplier: BigInt(multiplier.toString()),
|
|
8266
|
+
effectiveVotes: BigInt(effectiveVotes.toString())
|
|
8267
|
+
};
|
|
8268
|
+
}
|
|
8269
|
+
async function hasMultiplierBonus({ provider, wrapper, account }) {
|
|
8270
|
+
const c = getWrapperContract(provider, wrapper);
|
|
8271
|
+
const res = await c.hasMultiplierBonus(normaliseAddress(account, "account"));
|
|
8272
|
+
return !!res;
|
|
8273
|
+
}
|
|
8274
|
+
module2.exports = {
|
|
8275
|
+
// Tier management
|
|
8276
|
+
getTier,
|
|
8277
|
+
getTierCount,
|
|
8278
|
+
buildCreateTierTx,
|
|
8279
|
+
// Minting
|
|
8280
|
+
buildMintTx,
|
|
8281
|
+
buildPublicMintTx,
|
|
8282
|
+
// Multiplier queries
|
|
8283
|
+
getMultiplier,
|
|
8284
|
+
getPastMultiplier,
|
|
8285
|
+
getTokenMultiplier,
|
|
8286
|
+
getTokenDAO,
|
|
8287
|
+
getTokenInfo,
|
|
8288
|
+
// Wrapper queries
|
|
8289
|
+
getVotes,
|
|
8290
|
+
getPastVotes,
|
|
8291
|
+
getVotingBreakdown,
|
|
8292
|
+
getPastVotingBreakdown,
|
|
8293
|
+
hasMultiplierBonus
|
|
8294
|
+
};
|
|
8295
|
+
}
|
|
8296
|
+
});
|
|
8297
|
+
|
|
8298
|
+
// src/auction/index.js
|
|
8299
|
+
var require_auction = __commonJS({
|
|
8300
|
+
"src/auction/index.js"(exports2, module2) {
|
|
8301
|
+
var { Contract, Interface, getAddress } = require("ethers");
|
|
8302
|
+
var ABI = require_abi();
|
|
8303
|
+
var { SageSDKError, CODES } = require_errors();
|
|
8304
|
+
function normaliseAddress(address, label) {
|
|
8305
|
+
if (!address) throw new SageSDKError(CODES.INVALID_ARGS, `${label} required`);
|
|
8306
|
+
try {
|
|
8307
|
+
return getAddress(address);
|
|
8308
|
+
} catch (err) {
|
|
8309
|
+
throw new SageSDKError(CODES.INVALID_ARGS, `invalid ${label}`, { cause: err });
|
|
8310
|
+
}
|
|
8311
|
+
}
|
|
8312
|
+
function toBigInt(value, label) {
|
|
8313
|
+
if (value === void 0 || value === null) {
|
|
8314
|
+
throw new SageSDKError(CODES.INVALID_ARGS, `${label} required`);
|
|
8315
|
+
}
|
|
8316
|
+
try {
|
|
8317
|
+
return BigInt(value.toString());
|
|
8318
|
+
} catch (err) {
|
|
8319
|
+
throw new SageSDKError(CODES.INVALID_ARGS, `invalid ${label}`, { cause: err });
|
|
8320
|
+
}
|
|
8321
|
+
}
|
|
8322
|
+
function getAuctionContract(provider, auctionHouse) {
|
|
8323
|
+
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
|
|
8324
|
+
const addr = normaliseAddress(auctionHouse, "auctionHouse");
|
|
8325
|
+
return new Contract(addr, ABI.SageAuctionHouse, provider);
|
|
8326
|
+
}
|
|
8327
|
+
async function getAuction({ provider, auctionHouse }) {
|
|
8328
|
+
const c = getAuctionContract(provider, auctionHouse);
|
|
8329
|
+
const res = await c.auction();
|
|
8330
|
+
const nftId = BigInt(res.nftId.toString());
|
|
8331
|
+
const amount = BigInt(res.amount.toString());
|
|
8332
|
+
const startTime = BigInt(res.startTime.toString());
|
|
8333
|
+
const endTime = BigInt(res.endTime.toString());
|
|
8334
|
+
const bidder = getAddress(res.bidder);
|
|
8335
|
+
const settled = !!res.settled;
|
|
8336
|
+
return { nftId, amount, startTime, endTime, bidder, settled };
|
|
8337
|
+
}
|
|
8338
|
+
async function getConfig({ provider, auctionHouse }) {
|
|
8339
|
+
const c = getAuctionContract(provider, auctionHouse);
|
|
8340
|
+
const [nft, treasury2, weth, timeBuffer, reservePrice, minBidIncrementPercentage, duration, mintTierId, defaultTokenURI, paused, owner] = await Promise.all([
|
|
8341
|
+
c.nft(),
|
|
8342
|
+
c.treasury(),
|
|
8343
|
+
c.weth(),
|
|
8344
|
+
c.timeBuffer(),
|
|
8345
|
+
c.reservePrice(),
|
|
8346
|
+
c.minBidIncrementPercentage(),
|
|
8347
|
+
c.duration(),
|
|
8348
|
+
c.mintTierId(),
|
|
8349
|
+
c.defaultTokenURI(),
|
|
8350
|
+
c.paused(),
|
|
8351
|
+
c.owner()
|
|
8352
|
+
]);
|
|
8353
|
+
return {
|
|
8354
|
+
nft: getAddress(nft),
|
|
8355
|
+
treasury: getAddress(treasury2),
|
|
8356
|
+
weth: getAddress(weth),
|
|
8357
|
+
timeBuffer: BigInt(timeBuffer.toString()),
|
|
8358
|
+
reservePrice: BigInt(reservePrice.toString()),
|
|
8359
|
+
minBidIncrementPercentage: BigInt(minBidIncrementPercentage.toString()),
|
|
8360
|
+
duration: BigInt(duration.toString()),
|
|
8361
|
+
mintTierId: BigInt(mintTierId.toString()),
|
|
8362
|
+
defaultTokenURI: String(defaultTokenURI),
|
|
8363
|
+
paused: !!paused,
|
|
8364
|
+
owner: getAddress(owner)
|
|
8365
|
+
};
|
|
8366
|
+
}
|
|
8367
|
+
function buildCreateBidTx({ auctionHouse, nftId, value }) {
|
|
8368
|
+
const addr = normaliseAddress(auctionHouse, "auctionHouse");
|
|
8369
|
+
const iface = new Interface(ABI.SageAuctionHouse);
|
|
8370
|
+
const data = iface.encodeFunctionData("createBid", [toBigInt(nftId, "nftId")]);
|
|
8371
|
+
return { to: addr, data, value: toBigInt(value, "value") };
|
|
8372
|
+
}
|
|
8373
|
+
function buildSettleAndCreateTx({ auctionHouse }) {
|
|
8374
|
+
const addr = normaliseAddress(auctionHouse, "auctionHouse");
|
|
8375
|
+
const iface = new Interface(ABI.SageAuctionHouse);
|
|
8376
|
+
const data = iface.encodeFunctionData("settleCurrentAndCreateNewAuction", []);
|
|
8377
|
+
return { to: addr, data, value: 0n };
|
|
8378
|
+
}
|
|
8379
|
+
function buildSettleTx({ auctionHouse }) {
|
|
8380
|
+
const addr = normaliseAddress(auctionHouse, "auctionHouse");
|
|
8381
|
+
const iface = new Interface(ABI.SageAuctionHouse);
|
|
8382
|
+
const data = iface.encodeFunctionData("settleAuction", []);
|
|
8383
|
+
return { to: addr, data, value: 0n };
|
|
8384
|
+
}
|
|
8385
|
+
function buildCreateAuctionTx({ auctionHouse }) {
|
|
8386
|
+
const addr = normaliseAddress(auctionHouse, "auctionHouse");
|
|
8387
|
+
const iface = new Interface(ABI.SageAuctionHouse);
|
|
8388
|
+
const data = iface.encodeFunctionData("createAuction", []);
|
|
8389
|
+
return { to: addr, data, value: 0n };
|
|
8390
|
+
}
|
|
8391
|
+
function buildPauseTx({ auctionHouse }) {
|
|
8392
|
+
const addr = normaliseAddress(auctionHouse, "auctionHouse");
|
|
8393
|
+
const iface = new Interface(ABI.SageAuctionHouse);
|
|
8394
|
+
const data = iface.encodeFunctionData("pause", []);
|
|
8395
|
+
return { to: addr, data, value: 0n };
|
|
8396
|
+
}
|
|
8397
|
+
function buildUnpauseTx({ auctionHouse }) {
|
|
8398
|
+
const addr = normaliseAddress(auctionHouse, "auctionHouse");
|
|
8399
|
+
const iface = new Interface(ABI.SageAuctionHouse);
|
|
8400
|
+
const data = iface.encodeFunctionData("unpause", []);
|
|
8401
|
+
return { to: addr, data, value: 0n };
|
|
8402
|
+
}
|
|
8403
|
+
function buildSetTimeBufferTx({ auctionHouse, timeBuffer }) {
|
|
8404
|
+
const addr = normaliseAddress(auctionHouse, "auctionHouse");
|
|
8405
|
+
const iface = new Interface(ABI.SageAuctionHouse);
|
|
8406
|
+
const data = iface.encodeFunctionData("setTimeBuffer", [toBigInt(timeBuffer, "timeBuffer")]);
|
|
8407
|
+
return { to: addr, data, value: 0n };
|
|
8408
|
+
}
|
|
8409
|
+
function buildSetReservePriceTx({ auctionHouse, reservePrice }) {
|
|
8410
|
+
const addr = normaliseAddress(auctionHouse, "auctionHouse");
|
|
8411
|
+
const iface = new Interface(ABI.SageAuctionHouse);
|
|
8412
|
+
const data = iface.encodeFunctionData("setReservePrice", [toBigInt(reservePrice, "reservePrice")]);
|
|
8413
|
+
return { to: addr, data, value: 0n };
|
|
8414
|
+
}
|
|
8415
|
+
function buildSetMinBidIncrementTx({ auctionHouse, percentage }) {
|
|
8416
|
+
const addr = normaliseAddress(auctionHouse, "auctionHouse");
|
|
8417
|
+
const iface = new Interface(ABI.SageAuctionHouse);
|
|
8418
|
+
const data = iface.encodeFunctionData("setMinBidIncrementPercentage", [toBigInt(percentage, "percentage")]);
|
|
8419
|
+
return { to: addr, data, value: 0n };
|
|
8420
|
+
}
|
|
8421
|
+
function buildSetDurationTx({ auctionHouse, duration }) {
|
|
8422
|
+
const addr = normaliseAddress(auctionHouse, "auctionHouse");
|
|
8423
|
+
const iface = new Interface(ABI.SageAuctionHouse);
|
|
8424
|
+
const data = iface.encodeFunctionData("setDuration", [toBigInt(duration, "duration")]);
|
|
8425
|
+
return { to: addr, data, value: 0n };
|
|
8426
|
+
}
|
|
8427
|
+
function buildSetMintTierIdTx({ auctionHouse, tierId }) {
|
|
8428
|
+
const addr = normaliseAddress(auctionHouse, "auctionHouse");
|
|
8429
|
+
const iface = new Interface(ABI.SageAuctionHouse);
|
|
8430
|
+
const data = iface.encodeFunctionData("setMintTierId", [toBigInt(tierId, "tierId")]);
|
|
8431
|
+
return { to: addr, data, value: 0n };
|
|
8432
|
+
}
|
|
8433
|
+
function buildSetDefaultTokenURITx({ auctionHouse, uri }) {
|
|
8434
|
+
const addr = normaliseAddress(auctionHouse, "auctionHouse");
|
|
8435
|
+
const iface = new Interface(ABI.SageAuctionHouse);
|
|
8436
|
+
const data = iface.encodeFunctionData("setDefaultTokenURI", [String(uri ?? "")]);
|
|
8437
|
+
return { to: addr, data, value: 0n };
|
|
8438
|
+
}
|
|
8439
|
+
module2.exports = {
|
|
8440
|
+
getAuction,
|
|
8441
|
+
getConfig,
|
|
8442
|
+
buildCreateBidTx,
|
|
8443
|
+
buildSettleAndCreateTx,
|
|
8444
|
+
buildSettleTx,
|
|
8445
|
+
buildCreateAuctionTx,
|
|
8446
|
+
buildPauseTx,
|
|
8447
|
+
buildUnpauseTx,
|
|
8448
|
+
buildSetTimeBufferTx,
|
|
8449
|
+
buildSetReservePriceTx,
|
|
8450
|
+
buildSetMinBidIncrementTx,
|
|
8451
|
+
buildSetDurationTx,
|
|
8452
|
+
buildSetMintTierIdTx,
|
|
8453
|
+
buildSetDefaultTokenURITx
|
|
8454
|
+
};
|
|
8455
|
+
}
|
|
8456
|
+
});
|
|
8457
|
+
|
|
6512
8458
|
// src/utils/provider.js
|
|
6513
8459
|
var require_provider = __commonJS({
|
|
6514
8460
|
"src/utils/provider.js"(exports2, module2) {
|
|
@@ -8372,8 +10318,8 @@ var require_doppler = __commonJS({
|
|
|
8372
10318
|
return res;
|
|
8373
10319
|
};
|
|
8374
10320
|
module2.exports.getStaticPoolInfo = async function getStaticPoolInfo(sdk, poolAddress) {
|
|
8375
|
-
const
|
|
8376
|
-
return
|
|
10321
|
+
const auction2 = await sdk.getStaticAuction(poolAddress);
|
|
10322
|
+
return auction2.getPoolInfo();
|
|
8377
10323
|
};
|
|
8378
10324
|
module2.exports.quoteV3ExactIn = async function quoteV3ExactIn(sdk, { tokenIn, tokenOut, amountIn, fee, sqrtPriceLimitX96 = 0n }) {
|
|
8379
10325
|
return sdk.quoter.quoteExactInputV3({ tokenIn, tokenOut, amountIn, fee, sqrtPriceLimitX96 });
|
|
@@ -8396,8 +10342,8 @@ var require_doppler = __commonJS({
|
|
|
8396
10342
|
return { deposited: needed, hash };
|
|
8397
10343
|
};
|
|
8398
10344
|
module2.exports.getDynamicHookInfo = async function getDynamicHookInfo(sdk, hookAddress) {
|
|
8399
|
-
const
|
|
8400
|
-
return
|
|
10345
|
+
const auction2 = await sdk.getDynamicAuction(hookAddress);
|
|
10346
|
+
return auction2.getHookInfo();
|
|
8401
10347
|
};
|
|
8402
10348
|
module2.exports.quoteV4ExactIn = async function quoteV4ExactIn(sdk, { poolKey, zeroForOne, exactAmount, hookData }) {
|
|
8403
10349
|
return sdk.quoter.quoteExactInputV4({ poolKey, zeroForOne, exactAmount, hookData });
|
|
@@ -8510,6 +10456,60 @@ var require_doppler = __commonJS({
|
|
|
8510
10456
|
}
|
|
8511
10457
|
});
|
|
8512
10458
|
|
|
10459
|
+
// src/points.js
|
|
10460
|
+
var require_points = __commonJS({
|
|
10461
|
+
"src/points.js"(exports2, module2) {
|
|
10462
|
+
var axios = require("axios");
|
|
10463
|
+
function resolveBaseUrl(baseUrl) {
|
|
10464
|
+
const fromEnv = process.env.SAGE_POINTS_BASE_URL;
|
|
10465
|
+
const base = baseUrl || fromEnv;
|
|
10466
|
+
if (!base) {
|
|
10467
|
+
throw new Error(
|
|
10468
|
+
"SAGE_POINTS_BASE_URL not set and no baseUrl provided. Provide the Sage web app base URL, e.g. https://app.sage.xyz"
|
|
10469
|
+
);
|
|
10470
|
+
}
|
|
10471
|
+
return base.replace(/\/+$/, "");
|
|
10472
|
+
}
|
|
10473
|
+
async function fetchSeasonSnapshot({ baseUrl, season = "season-1" } = {}) {
|
|
10474
|
+
const base = resolveBaseUrl(baseUrl);
|
|
10475
|
+
const url = `${base}/airdrop/${season}/points.json`;
|
|
10476
|
+
const resp = await axios.get(url, { timeout: 15e3 });
|
|
10477
|
+
if (!resp || !resp.data) {
|
|
10478
|
+
throw new Error(`No data returned from ${url}`);
|
|
10479
|
+
}
|
|
10480
|
+
return resp.data;
|
|
10481
|
+
}
|
|
10482
|
+
async function getSeasonPoints({ address, season = "season-1", baseUrl } = {}) {
|
|
10483
|
+
if (!address) throw new Error("address is required");
|
|
10484
|
+
const snapshot = await fetchSeasonSnapshot({ baseUrl, season });
|
|
10485
|
+
const totals = snapshot.totals || {};
|
|
10486
|
+
const key = address.toLowerCase();
|
|
10487
|
+
const entry = totals[key] || null;
|
|
10488
|
+
return {
|
|
10489
|
+
season: snapshot.season || season,
|
|
10490
|
+
chainId: snapshot.chainId,
|
|
10491
|
+
address: key,
|
|
10492
|
+
totalPoints: entry ? entry.points || 0 : 0,
|
|
10493
|
+
breakdown: entry ? entry.breakdown || {} : {}
|
|
10494
|
+
};
|
|
10495
|
+
}
|
|
10496
|
+
async function getSeasonLeaderboard({ limit = 100, season = "season-1", baseUrl } = {}) {
|
|
10497
|
+
const snapshot = await fetchSeasonSnapshot({ baseUrl, season });
|
|
10498
|
+
const totals = snapshot.totals || {};
|
|
10499
|
+
const entries = Object.entries(totals).map(([addr, v]) => ({
|
|
10500
|
+
address: addr,
|
|
10501
|
+
points: v.points || 0
|
|
10502
|
+
})).sort((a, b) => b.points - a.points);
|
|
10503
|
+
return entries.slice(0, limit);
|
|
10504
|
+
}
|
|
10505
|
+
module2.exports = {
|
|
10506
|
+
fetchSeasonSnapshot,
|
|
10507
|
+
getSeasonPoints,
|
|
10508
|
+
getSeasonLeaderboard
|
|
10509
|
+
};
|
|
10510
|
+
}
|
|
10511
|
+
});
|
|
10512
|
+
|
|
8513
10513
|
// src/services/utils/cache.js
|
|
8514
10514
|
var require_cache = __commonJS({
|
|
8515
10515
|
"src/services/utils/cache.js"(exports2, module2) {
|
|
@@ -9260,6 +11260,273 @@ var require_client2 = __commonJS({
|
|
|
9260
11260
|
}
|
|
9261
11261
|
});
|
|
9262
11262
|
|
|
11263
|
+
// src/clients/discovery-client.js
|
|
11264
|
+
var require_discovery_client = __commonJS({
|
|
11265
|
+
"src/clients/discovery-client.js"(exports2, module2) {
|
|
11266
|
+
var DiscoveryClient2 = class {
|
|
11267
|
+
/**
|
|
11268
|
+
* @param {string} baseUrl - Base URL of the discovery API
|
|
11269
|
+
* @param {object} [options] - Client options
|
|
11270
|
+
* @param {number} [options.timeout=10000] - Request timeout in milliseconds
|
|
11271
|
+
* @param {Record<string, string>} [options.headers] - Custom headers
|
|
11272
|
+
*/
|
|
11273
|
+
constructor(baseUrl, options = {}) {
|
|
11274
|
+
this.baseUrl = baseUrl.replace(/\/$/, "");
|
|
11275
|
+
this.timeout = options.timeout || 1e4;
|
|
11276
|
+
this.headers = options.headers || {};
|
|
11277
|
+
}
|
|
11278
|
+
/**
|
|
11279
|
+
* Search prompts with keyword matching and trend ranking
|
|
11280
|
+
* @param {string} query - Search query
|
|
11281
|
+
* @param {object} [options] - Search options
|
|
11282
|
+
* @param {string} [options.category] - Filter by category
|
|
11283
|
+
* @param {string[]} [options.tags] - Filter by tags
|
|
11284
|
+
* @param {string} [options.author] - Filter by author
|
|
11285
|
+
* @param {number} [options.limit] - Max results to return
|
|
11286
|
+
* @param {number} [options.offset] - Number of results to skip
|
|
11287
|
+
* @param {boolean} [options.useVector] - Use vector search
|
|
11288
|
+
* @returns {Promise<{results: Array, total: number}>}
|
|
11289
|
+
*/
|
|
11290
|
+
async search(query, options = {}) {
|
|
11291
|
+
const params = new URLSearchParams();
|
|
11292
|
+
if (query) params.set("q", query);
|
|
11293
|
+
if (options.category) params.set("category", options.category);
|
|
11294
|
+
if (options.author) params.set("author", options.author);
|
|
11295
|
+
if (options.tags) {
|
|
11296
|
+
options.tags.forEach((tag) => params.append("tags", tag));
|
|
11297
|
+
}
|
|
11298
|
+
if (options.limit !== void 0) params.set("limit", String(options.limit));
|
|
11299
|
+
if (options.offset !== void 0) params.set("offset", String(options.offset));
|
|
11300
|
+
if (options.useVector !== void 0) params.set("useVector", String(options.useVector));
|
|
11301
|
+
return this._get(`/discover/search?${params}`);
|
|
11302
|
+
}
|
|
11303
|
+
/**
|
|
11304
|
+
* Get trending prompts by time window
|
|
11305
|
+
* @param {object} [options] - Trending options
|
|
11306
|
+
* @param {'1h'|'24h'|'7d'|'30d'|'all'} [options.window] - Time window
|
|
11307
|
+
* @param {string} [options.category] - Filter by category
|
|
11308
|
+
* @param {number} [options.limit] - Max results to return
|
|
11309
|
+
* @param {number} [options.offset] - Number of results to skip
|
|
11310
|
+
* @returns {Promise<{results: Array}>}
|
|
11311
|
+
*/
|
|
11312
|
+
async trending(options = {}) {
|
|
11313
|
+
const params = new URLSearchParams();
|
|
11314
|
+
if (options.window) params.set("window", options.window);
|
|
11315
|
+
if (options.category) params.set("category", options.category);
|
|
11316
|
+
if (options.limit !== void 0) params.set("limit", String(options.limit));
|
|
11317
|
+
if (options.offset !== void 0) params.set("offset", String(options.offset));
|
|
11318
|
+
return this._get(`/discover/trending?${params}`);
|
|
11319
|
+
}
|
|
11320
|
+
/**
|
|
11321
|
+
* Get trending prompts (alias for /trends/top endpoint)
|
|
11322
|
+
* @param {object} [options] - Trending options
|
|
11323
|
+
* @param {'1h'|'24h'|'7d'|'30d'|'all'} [options.window] - Time window
|
|
11324
|
+
* @param {number} [options.limit] - Max results to return
|
|
11325
|
+
* @param {number} [options.offset] - Number of results to skip
|
|
11326
|
+
* @returns {Promise<{results: Array}>}
|
|
11327
|
+
*/
|
|
11328
|
+
async trendingTop(options = {}) {
|
|
11329
|
+
const params = new URLSearchParams();
|
|
11330
|
+
if (options.window) params.set("window", options.window);
|
|
11331
|
+
if (options.limit !== void 0) params.set("limit", String(options.limit));
|
|
11332
|
+
if (options.offset !== void 0) params.set("offset", String(options.offset));
|
|
11333
|
+
return this._get(`/trends/top?${params}`);
|
|
11334
|
+
}
|
|
11335
|
+
/**
|
|
11336
|
+
* Find prompts matching user preferences
|
|
11337
|
+
*
|
|
11338
|
+
* Note: This endpoint is not yet implemented in the backend.
|
|
11339
|
+
* This is a placeholder for future implementation.
|
|
11340
|
+
* @param {object} preferences - User preferences
|
|
11341
|
+
* @param {string[]} [preferences.recentPrompts] - Recent prompt CIDs
|
|
11342
|
+
* @param {string[]} [preferences.preferredTags] - Preferred tags
|
|
11343
|
+
* @param {string[]} [preferences.preferredCategories] - Preferred categories
|
|
11344
|
+
* @param {string[]} [preferences.excludeAuthors] - Authors to exclude
|
|
11345
|
+
* @param {number} [preferences.limit] - Max results
|
|
11346
|
+
* @param {boolean} [preferences.diversify] - Diversify results
|
|
11347
|
+
* @returns {Promise<{results: Array, total: number}>}
|
|
11348
|
+
*/
|
|
11349
|
+
async match(preferences) {
|
|
11350
|
+
return this._post("/discover/match", preferences);
|
|
11351
|
+
}
|
|
11352
|
+
/**
|
|
11353
|
+
* Find prompts similar to a given prompt
|
|
11354
|
+
* @param {string} cid - Prompt CID to find similar prompts for
|
|
11355
|
+
* @param {object} [options] - Similar options
|
|
11356
|
+
* @param {number} [options.limit] - Max results to return
|
|
11357
|
+
* @param {'vector'|'keyword'|'hybrid'} [options.method] - Similarity method
|
|
11358
|
+
* @returns {Promise<{similar: Array}>}
|
|
11359
|
+
*/
|
|
11360
|
+
async similar(cid, options = {}) {
|
|
11361
|
+
const params = new URLSearchParams();
|
|
11362
|
+
if (options.limit !== void 0) params.set("limit", String(options.limit));
|
|
11363
|
+
if (options.method) params.set("method", options.method);
|
|
11364
|
+
return this._get(`/discover/similar/${cid}?${params}`);
|
|
11365
|
+
}
|
|
11366
|
+
/**
|
|
11367
|
+
* Get popular tags with optional clustering
|
|
11368
|
+
* @param {object} [options] - Tags options
|
|
11369
|
+
* @param {number} [options.limit] - Max tags to return
|
|
11370
|
+
* @param {string} [options.category] - Filter by category
|
|
11371
|
+
* @param {boolean} [options.clusters] - Enable tag clustering
|
|
11372
|
+
* @returns {Promise<{tags: Array}>}
|
|
11373
|
+
*/
|
|
11374
|
+
async tags(options = {}) {
|
|
11375
|
+
const params = new URLSearchParams();
|
|
11376
|
+
if (options.limit !== void 0) params.set("limit", String(options.limit));
|
|
11377
|
+
if (options.category) params.set("category", options.category);
|
|
11378
|
+
if (options.clusters !== void 0) params.set("clusters", String(options.clusters));
|
|
11379
|
+
return this._get(`/discover/tags?${params}`);
|
|
11380
|
+
}
|
|
11381
|
+
/**
|
|
11382
|
+
* Get category statistics
|
|
11383
|
+
*
|
|
11384
|
+
* Note: This endpoint is not yet implemented in the backend.
|
|
11385
|
+
* This is a placeholder for future implementation.
|
|
11386
|
+
* @returns {Promise<{categories: Array}>}
|
|
11387
|
+
*/
|
|
11388
|
+
async categories() {
|
|
11389
|
+
return this._get("/discover/categories");
|
|
11390
|
+
}
|
|
11391
|
+
/**
|
|
11392
|
+
* Get prompts by tag
|
|
11393
|
+
* @param {string} tag - Tag to search for
|
|
11394
|
+
* @param {number} [limit] - Max results to return
|
|
11395
|
+
* @returns {Promise<{results: Array}>}
|
|
11396
|
+
*/
|
|
11397
|
+
async promptsByTag(tag, limit) {
|
|
11398
|
+
const params = new URLSearchParams();
|
|
11399
|
+
if (limit !== void 0) params.set("limit", String(limit));
|
|
11400
|
+
const encodedTag = encodeURIComponent(tag);
|
|
11401
|
+
return this._get(`/discover/by-tag/${encodedTag}?${params}`);
|
|
11402
|
+
}
|
|
11403
|
+
/**
|
|
11404
|
+
* Get index statistics
|
|
11405
|
+
* @returns {Promise<{totalPrompts: number, totalTags: number, avgTrendScore: number}>}
|
|
11406
|
+
*/
|
|
11407
|
+
async stats() {
|
|
11408
|
+
return this._get("/discover/stats");
|
|
11409
|
+
}
|
|
11410
|
+
/**
|
|
11411
|
+
* Get trend signals for a specific CID
|
|
11412
|
+
* @param {string} cid - Prompt CID
|
|
11413
|
+
* @returns {Promise<{usageCount: number, forkCount: number, purchaseCount: number, uniqueBuyers: number, governanceVotes: number, lastActivityAt: number}>}
|
|
11414
|
+
*/
|
|
11415
|
+
async trendSignals(cid) {
|
|
11416
|
+
return this._get(`/trends/signals/${cid}`);
|
|
11417
|
+
}
|
|
11418
|
+
/**
|
|
11419
|
+
* Get trend history for a specific CID
|
|
11420
|
+
* @param {string} cid - Prompt CID
|
|
11421
|
+
* @param {object} [options] - History options
|
|
11422
|
+
* @param {number} [options.limit] - Max history entries
|
|
11423
|
+
* @param {number} [options.since] - Timestamp to start from
|
|
11424
|
+
* @returns {Promise<{history: Array}>}
|
|
11425
|
+
*/
|
|
11426
|
+
async trendHistory(cid, options = {}) {
|
|
11427
|
+
const params = new URLSearchParams();
|
|
11428
|
+
if (options.limit !== void 0) params.set("limit", String(options.limit));
|
|
11429
|
+
if (options.since !== void 0) params.set("since", String(options.since));
|
|
11430
|
+
return this._get(`/trends/history/${cid}?${params}`);
|
|
11431
|
+
}
|
|
11432
|
+
/**
|
|
11433
|
+
* Get trend statistics
|
|
11434
|
+
* @returns {Promise<{totalTracked: number, avgScore: number, maxScore: number, recentlyActive: number}>}
|
|
11435
|
+
*/
|
|
11436
|
+
async trendStats() {
|
|
11437
|
+
return this._get("/trends/stats");
|
|
11438
|
+
}
|
|
11439
|
+
/**
|
|
11440
|
+
* Record a usage event for a prompt (requires authentication)
|
|
11441
|
+
* @param {string} cid - Prompt CID
|
|
11442
|
+
* @returns {Promise<{ok: boolean}>}
|
|
11443
|
+
*/
|
|
11444
|
+
async recordUsage(cid) {
|
|
11445
|
+
return this._post("/trends/usage", { cid });
|
|
11446
|
+
}
|
|
11447
|
+
// Private fetch helpers
|
|
11448
|
+
/**
|
|
11449
|
+
* Perform a GET request
|
|
11450
|
+
* @private
|
|
11451
|
+
* @param {string} path - API path
|
|
11452
|
+
* @returns {Promise<any>}
|
|
11453
|
+
*/
|
|
11454
|
+
async _get(path2) {
|
|
11455
|
+
const controller = new AbortController();
|
|
11456
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
11457
|
+
try {
|
|
11458
|
+
const response = await fetch(`${this.baseUrl}${path2}`, {
|
|
11459
|
+
method: "GET",
|
|
11460
|
+
headers: {
|
|
11461
|
+
"Accept": "application/json",
|
|
11462
|
+
...this.headers
|
|
11463
|
+
},
|
|
11464
|
+
signal: controller.signal
|
|
11465
|
+
});
|
|
11466
|
+
clearTimeout(timeoutId);
|
|
11467
|
+
if (!response.ok) {
|
|
11468
|
+
const errorBody = await response.text().catch(() => "Unknown error");
|
|
11469
|
+
throw new Error(`HTTP ${response.status}: ${errorBody}`);
|
|
11470
|
+
}
|
|
11471
|
+
return await response.json();
|
|
11472
|
+
} catch (error) {
|
|
11473
|
+
clearTimeout(timeoutId);
|
|
11474
|
+
if (error.name === "AbortError") {
|
|
11475
|
+
throw new Error(`Request timeout after ${this.timeout}ms`);
|
|
11476
|
+
}
|
|
11477
|
+
throw error;
|
|
11478
|
+
}
|
|
11479
|
+
}
|
|
11480
|
+
/**
|
|
11481
|
+
* Perform a POST request
|
|
11482
|
+
* @private
|
|
11483
|
+
* @param {string} path - API path
|
|
11484
|
+
* @param {any} body - Request body
|
|
11485
|
+
* @returns {Promise<any>}
|
|
11486
|
+
*/
|
|
11487
|
+
async _post(path2, body) {
|
|
11488
|
+
const controller = new AbortController();
|
|
11489
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
11490
|
+
try {
|
|
11491
|
+
const response = await fetch(`${this.baseUrl}${path2}`, {
|
|
11492
|
+
method: "POST",
|
|
11493
|
+
headers: {
|
|
11494
|
+
"Accept": "application/json",
|
|
11495
|
+
"Content-Type": "application/json",
|
|
11496
|
+
...this.headers
|
|
11497
|
+
},
|
|
11498
|
+
body: JSON.stringify(body),
|
|
11499
|
+
signal: controller.signal
|
|
11500
|
+
});
|
|
11501
|
+
clearTimeout(timeoutId);
|
|
11502
|
+
if (!response.ok) {
|
|
11503
|
+
const errorBody = await response.text().catch(() => "Unknown error");
|
|
11504
|
+
throw new Error(`HTTP ${response.status}: ${errorBody}`);
|
|
11505
|
+
}
|
|
11506
|
+
return await response.json();
|
|
11507
|
+
} catch (error) {
|
|
11508
|
+
clearTimeout(timeoutId);
|
|
11509
|
+
if (error.name === "AbortError") {
|
|
11510
|
+
throw new Error(`Request timeout after ${this.timeout}ms`);
|
|
11511
|
+
}
|
|
11512
|
+
throw error;
|
|
11513
|
+
}
|
|
11514
|
+
}
|
|
11515
|
+
};
|
|
11516
|
+
module2.exports = { DiscoveryClient: DiscoveryClient2 };
|
|
11517
|
+
}
|
|
11518
|
+
});
|
|
11519
|
+
|
|
11520
|
+
// src/clients/index.js
|
|
11521
|
+
var require_clients = __commonJS({
|
|
11522
|
+
"src/clients/index.js"(exports2, module2) {
|
|
11523
|
+
var { DiscoveryClient: DiscoveryClient2 } = require_discovery_client();
|
|
11524
|
+
module2.exports = {
|
|
11525
|
+
DiscoveryClient: DiscoveryClient2
|
|
11526
|
+
};
|
|
11527
|
+
}
|
|
11528
|
+
});
|
|
11529
|
+
|
|
9263
11530
|
// src/hooks/useSubDAOs.js
|
|
9264
11531
|
var require_useSubDAOs = __commonJS({
|
|
9265
11532
|
"src/hooks/useSubDAOs.js"(exports2, module2) {
|
|
@@ -9468,6 +11735,7 @@ var subdao = require_subdao();
|
|
|
9468
11735
|
var timelock = require_timelock();
|
|
9469
11736
|
var factory = require_factory();
|
|
9470
11737
|
var library = require_library();
|
|
11738
|
+
var lineage = require_lineage();
|
|
9471
11739
|
var prompt = require_prompt();
|
|
9472
11740
|
var { SageEchoExecutor } = require_execute();
|
|
9473
11741
|
var ipfs = require_ipfs();
|
|
@@ -9481,6 +11749,8 @@ var time = require_time();
|
|
|
9481
11749
|
var treasury = require_treasury();
|
|
9482
11750
|
var boost = require_boost();
|
|
9483
11751
|
var bounty = require_bounty();
|
|
11752
|
+
var votingMultiplier = require_votingMultiplier();
|
|
11753
|
+
var auction = require_auction();
|
|
9484
11754
|
var wallet = require_wallet();
|
|
9485
11755
|
wallet.session = require_session();
|
|
9486
11756
|
var walletCastManager = require_cast_manager();
|
|
@@ -9495,11 +11765,13 @@ var adapters = {
|
|
|
9495
11765
|
openzeppelin: require_openzeppelin()
|
|
9496
11766
|
}
|
|
9497
11767
|
};
|
|
11768
|
+
var points = require_points();
|
|
9498
11769
|
var { SubgraphService } = require_client();
|
|
9499
11770
|
var { IPFSService } = require_client2();
|
|
9500
11771
|
var serviceErrors = require_errors2();
|
|
9501
11772
|
var { SimpleCache } = require_cache();
|
|
9502
11773
|
var { retryWithBackoff } = require_retry();
|
|
11774
|
+
var { DiscoveryClient } = require_clients();
|
|
9503
11775
|
var hooks = null;
|
|
9504
11776
|
try {
|
|
9505
11777
|
hooks = require_hooks();
|
|
@@ -9515,6 +11787,7 @@ module.exports = {
|
|
|
9515
11787
|
timelock,
|
|
9516
11788
|
factory,
|
|
9517
11789
|
library,
|
|
11790
|
+
lineage,
|
|
9518
11791
|
prompt,
|
|
9519
11792
|
ipfs,
|
|
9520
11793
|
ipns,
|
|
@@ -9527,6 +11800,8 @@ module.exports = {
|
|
|
9527
11800
|
subgraph,
|
|
9528
11801
|
utils: { ...utils, privateTx, safe, time },
|
|
9529
11802
|
bounty,
|
|
11803
|
+
votingMultiplier,
|
|
11804
|
+
auction,
|
|
9530
11805
|
wallet: Object.assign(wallet, {
|
|
9531
11806
|
cast: walletCastManager,
|
|
9532
11807
|
cdp: walletCdpManager
|
|
@@ -9535,6 +11810,8 @@ module.exports = {
|
|
|
9535
11810
|
errors,
|
|
9536
11811
|
doppler,
|
|
9537
11812
|
adapters,
|
|
11813
|
+
// Season points helpers (airdrops/testnet)
|
|
11814
|
+
points,
|
|
9538
11815
|
// New service layer exports
|
|
9539
11816
|
services: {
|
|
9540
11817
|
SubgraphService,
|
|
@@ -9545,6 +11822,11 @@ module.exports = {
|
|
|
9545
11822
|
SimpleCache,
|
|
9546
11823
|
retryWithBackoff
|
|
9547
11824
|
},
|
|
11825
|
+
// Client exports
|
|
11826
|
+
clients: {
|
|
11827
|
+
DiscoveryClient
|
|
11828
|
+
},
|
|
11829
|
+
DiscoveryClient,
|
|
9548
11830
|
// React hooks (optional - requires react + swr peer dependencies)
|
|
9549
11831
|
hooks,
|
|
9550
11832
|
// Legacy exports (deprecated): maintain compatibility while consumers migrate
|