@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.mjs
CHANGED
|
@@ -20,7 +20,7 @@ var require_package = __commonJS({
|
|
|
20
20
|
"package.json"(exports2, module2) {
|
|
21
21
|
module2.exports = {
|
|
22
22
|
name: "@sage-protocol/sdk",
|
|
23
|
-
version: "0.1.
|
|
23
|
+
version: "0.1.21",
|
|
24
24
|
description: "Backend-agnostic SDK for interacting with the Sage Protocol (governance, SubDAOs, tokens).",
|
|
25
25
|
main: "dist/index.cjs",
|
|
26
26
|
module: "dist/index.mjs",
|
|
@@ -136,7 +136,6 @@ var require_abi = __commonJS({
|
|
|
136
136
|
"function stableCreationFee() view returns (uint256)",
|
|
137
137
|
"function stableFeeReceiver() view returns (address)",
|
|
138
138
|
"function stableCreationEnabled() view returns (bool)",
|
|
139
|
-
"function stablePromptForkFee() view returns (uint256)",
|
|
140
139
|
"function stableForkFee() view returns (uint256)",
|
|
141
140
|
// Core factory reads
|
|
142
141
|
"function timelockMinDelay() view returns (uint256)",
|
|
@@ -178,13 +177,18 @@ var require_abi = __commonJS({
|
|
|
178
177
|
"function maxCreationBurn() view returns (uint256)"
|
|
179
178
|
];
|
|
180
179
|
var LibraryRegistry = [
|
|
181
|
-
"function libraryByDAO(address) view returns (string manifestCID, address lastUpdater, uint256 lastUpdated, string version)",
|
|
180
|
+
"function libraryByDAO(address) view returns (string manifestCID, address lastUpdater, uint256 lastUpdated, string version, address forkedFromDAO, uint256 sxxxForkFee)",
|
|
182
181
|
"function daoTimelock(address) view returns (address)",
|
|
183
|
-
"function getLibrary(address) view returns (tuple(string manifestCID, address lastUpdater, uint256 lastUpdated, string version))",
|
|
182
|
+
"function getLibrary(address) view returns (tuple(string manifestCID, address lastUpdater, uint256 lastUpdated, string version, address forkedFromDAO, uint256 sxxxForkFee))",
|
|
183
|
+
"function getLibraryForkFee(address dao) view returns (uint256)",
|
|
184
|
+
"function setLibraryForkFee(address dao, uint256 fee)",
|
|
184
185
|
"function updateLibrary(address dao, string manifestCID, string version)",
|
|
185
186
|
"function registerDAO(address dao, address timelock)",
|
|
187
|
+
"function registerForkedDAO(address childDAO, address childTimelock, address parentDAO, string manifestCID, string version)",
|
|
186
188
|
"event LibraryUpdated(address indexed dao, string manifestCID, address indexed timelock, string version)",
|
|
187
|
-
"event DAORegistered(address indexed dao, address indexed timelock)"
|
|
189
|
+
"event DAORegistered(address indexed dao, address indexed timelock)",
|
|
190
|
+
"event LibraryForked(address indexed parentDAO, address indexed childDAO)",
|
|
191
|
+
"event LibraryForkFeeUpdated(address indexed dao, uint256 fee)"
|
|
188
192
|
];
|
|
189
193
|
var PromptRegistry = [
|
|
190
194
|
"function prompts(string key) view returns (string cid, uint256 version, uint256 timestamp, address author, string forkedFromCID, address originalAuthor, bool isFork, uint256 forkDepth)",
|
|
@@ -299,6 +303,186 @@ var require_abi = __commonJS({
|
|
|
299
303
|
"function create(uint256 proposalId, address token, uint256 perVoter, uint256 maxVoters)",
|
|
300
304
|
"function fund(uint256 proposalId, uint256 amount)"
|
|
301
305
|
];
|
|
306
|
+
var VotingMultiplierNFT = [
|
|
307
|
+
// Constants
|
|
308
|
+
"function MINTER_ROLE() view returns (bytes32)",
|
|
309
|
+
"function MAX_NFTS_PER_ACCOUNT() view returns (uint256)",
|
|
310
|
+
// Tier Management
|
|
311
|
+
"function createTier(address dao, string name, uint256 multiplier, uint256 maxSupply, uint256 price) returns (uint256 tierId)",
|
|
312
|
+
"function getTier(uint256 tierId) view returns (tuple(string name, uint256 multiplier, uint256 maxSupply, uint256 minted, uint256 price, address dao))",
|
|
313
|
+
"function tierCount() view returns (uint256)",
|
|
314
|
+
"function tiers(uint256) view returns (string name, uint256 multiplier, uint256 maxSupply, uint256 minted, uint256 price, address dao)",
|
|
315
|
+
// Minting
|
|
316
|
+
"function mint(address to, uint256 tierId, string uri) returns (uint256 tokenId)",
|
|
317
|
+
"function publicMint(uint256 tierId, string uri) payable returns (uint256 tokenId)",
|
|
318
|
+
// Multiplier Functions
|
|
319
|
+
"function getMultiplier(address account, address dao) view returns (uint256)",
|
|
320
|
+
"function getPastMultiplier(address account, address dao, uint256 timepoint) view returns (uint256)",
|
|
321
|
+
"function getTokenMultiplier(uint256 tokenId) view returns (uint256)",
|
|
322
|
+
"function getTokenDAO(uint256 tokenId) view returns (address)",
|
|
323
|
+
// Token Info
|
|
324
|
+
"function tokenMultiplier(uint256) view returns (uint256)",
|
|
325
|
+
"function tokenDAO(uint256) view returns (address)",
|
|
326
|
+
"function tokenTier(uint256) view returns (uint256)",
|
|
327
|
+
"function getTokenInfo(uint256 tokenId) view returns (address owner, uint256 tierId, uint256 multiplier, string uri)",
|
|
328
|
+
// ERC721 Standard
|
|
329
|
+
"function balanceOf(address owner) view returns (uint256)",
|
|
330
|
+
"function ownerOf(uint256 tokenId) view returns (address)",
|
|
331
|
+
"function tokenOfOwnerByIndex(address owner, uint256 index) view returns (uint256)",
|
|
332
|
+
"function tokenURI(uint256 tokenId) view returns (string)",
|
|
333
|
+
"function transferFrom(address from, address to, uint256 tokenId)",
|
|
334
|
+
"function safeTransferFrom(address from, address to, uint256 tokenId)",
|
|
335
|
+
"function approve(address to, uint256 tokenId)",
|
|
336
|
+
"function setApprovalForAll(address operator, bool approved)",
|
|
337
|
+
"function getApproved(uint256 tokenId) view returns (address)",
|
|
338
|
+
"function isApprovedForAll(address owner, address operator) view returns (bool)",
|
|
339
|
+
// Admin
|
|
340
|
+
"function withdrawFunds(address to)",
|
|
341
|
+
"function grantRole(bytes32 role, address account)",
|
|
342
|
+
"function revokeRole(bytes32 role, address account)",
|
|
343
|
+
"function hasRole(bytes32 role, address account) view returns (bool)",
|
|
344
|
+
// Events
|
|
345
|
+
"event TierCreated(uint256 indexed tierId, address indexed dao, string name, uint256 multiplier, uint256 maxSupply, uint256 price)",
|
|
346
|
+
"event NFTMinted(address indexed to, uint256 indexed tokenId, address indexed dao, uint256 tierId, uint256 multiplier)",
|
|
347
|
+
"event Transfer(address indexed from, address indexed to, uint256 indexed tokenId)"
|
|
348
|
+
];
|
|
349
|
+
var MultipliedVotes = [
|
|
350
|
+
// Core IVotes Interface
|
|
351
|
+
"function getVotes(address account) view returns (uint256)",
|
|
352
|
+
"function getPastVotes(address account, uint256 timepoint) view returns (uint256)",
|
|
353
|
+
"function getPastTotalSupply(uint256 timepoint) view returns (uint256)",
|
|
354
|
+
"function delegates(address account) view returns (address)",
|
|
355
|
+
"function delegate(address delegatee)",
|
|
356
|
+
"function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s)",
|
|
357
|
+
// IERC6372 Clock Interface
|
|
358
|
+
"function clock() view returns (uint48)",
|
|
359
|
+
"function CLOCK_MODE() view returns (string)",
|
|
360
|
+
// View Helpers
|
|
361
|
+
"function getVotingBreakdown(address account) view returns (uint256 baseVotes, uint256 multiplier, uint256 effectiveVotes)",
|
|
362
|
+
"function getPastVotingBreakdown(address account, uint256 timepoint) view returns (uint256 baseVotes, uint256 multiplier, uint256 effectiveVotes)",
|
|
363
|
+
"function hasMultiplierBonus(address account) view returns (bool)",
|
|
364
|
+
// Immutable Config
|
|
365
|
+
"function baseToken() view returns (address)",
|
|
366
|
+
"function multiplierNFT() view returns (address)",
|
|
367
|
+
"function dao() view returns (address)",
|
|
368
|
+
"function BASIS() view returns (uint256)"
|
|
369
|
+
];
|
|
370
|
+
var SageAuctionHouse = [
|
|
371
|
+
// Core Auction Functions
|
|
372
|
+
"function createBid(uint256 nftId) payable",
|
|
373
|
+
"function settleCurrentAndCreateNewAuction()",
|
|
374
|
+
"function settleAuction()",
|
|
375
|
+
"function createAuction()",
|
|
376
|
+
// Current Auction State
|
|
377
|
+
"function auction() view returns (uint256 nftId, uint256 amount, uint256 startTime, uint256 endTime, address bidder, bool settled)",
|
|
378
|
+
// Configuration
|
|
379
|
+
"function nft() view returns (address)",
|
|
380
|
+
"function treasury() view returns (address)",
|
|
381
|
+
"function weth() view returns (address)",
|
|
382
|
+
"function timeBuffer() view returns (uint256)",
|
|
383
|
+
"function reservePrice() view returns (uint256)",
|
|
384
|
+
"function minBidIncrementPercentage() view returns (uint256)",
|
|
385
|
+
"function duration() view returns (uint256)",
|
|
386
|
+
"function mintTierId() view returns (uint256)",
|
|
387
|
+
"function defaultTokenURI() view returns (string)",
|
|
388
|
+
// Admin Functions
|
|
389
|
+
"function pause()",
|
|
390
|
+
"function unpause()",
|
|
391
|
+
"function paused() view returns (bool)",
|
|
392
|
+
"function setTimeBuffer(uint256 _timeBuffer)",
|
|
393
|
+
"function setReservePrice(uint256 _reservePrice)",
|
|
394
|
+
"function setMinBidIncrementPercentage(uint256 _minBidIncrementPercentage)",
|
|
395
|
+
"function setDuration(uint256 _duration)",
|
|
396
|
+
"function setMintTierId(uint256 _tierId)",
|
|
397
|
+
"function setDefaultTokenURI(string _uri)",
|
|
398
|
+
"function owner() view returns (address)",
|
|
399
|
+
"function transferOwnership(address newOwner)",
|
|
400
|
+
// Events
|
|
401
|
+
"event AuctionCreated(uint256 indexed nftId, uint256 startTime, uint256 endTime)",
|
|
402
|
+
"event AuctionBid(uint256 indexed nftId, address sender, uint256 value, bool extended)",
|
|
403
|
+
"event AuctionExtended(uint256 indexed nftId, uint256 endTime)",
|
|
404
|
+
"event AuctionSettled(uint256 indexed nftId, address winner, uint256 amount)",
|
|
405
|
+
"event AuctionTimeBufferUpdated(uint256 timeBuffer)",
|
|
406
|
+
"event AuctionReservePriceUpdated(uint256 reservePrice)",
|
|
407
|
+
"event AuctionMinBidIncrementPercentageUpdated(uint256 minBidIncrementPercentage)",
|
|
408
|
+
"event AuctionDurationUpdated(uint256 duration)"
|
|
409
|
+
];
|
|
410
|
+
var SimpleBountySystem = [
|
|
411
|
+
// Constants
|
|
412
|
+
"function GOVERNANCE_ROLE() view returns (bytes32)",
|
|
413
|
+
"function MAX_SUBMISSIONS_PER_BOUNTY() view returns (uint256)",
|
|
414
|
+
// Bounty Creation
|
|
415
|
+
"function createBounty(string title, string description, string ipfsCID, uint256 reward, uint256 deadline) returns (uint256)",
|
|
416
|
+
"function createBountyAdvanced(string title, string description, string ipfsCID, uint256 reward, uint256 deadline, uint256 votingDuration, uint8 mode, uint8 libraryAction, address assignee, string libraryKey) returns (uint256)",
|
|
417
|
+
// Submission & Claiming
|
|
418
|
+
"function claimBounty(uint256 bountyId)",
|
|
419
|
+
"function submitEntry(uint256 bountyId, string promptIPFS, string deliverableIPFS) returns (uint256)",
|
|
420
|
+
"function completeBounty(uint256 bountyId, string deliverableIPFS)",
|
|
421
|
+
// Voting (COMPETITIVE mode)
|
|
422
|
+
"function startVoting(uint256 bountyId)",
|
|
423
|
+
"function vote(uint256 bountyId, uint256 submissionId)",
|
|
424
|
+
"function finalizeCompetitive(uint256 bountyId)",
|
|
425
|
+
// Approval
|
|
426
|
+
"function approveSubmission(uint256 bountyId, uint256 submissionId)",
|
|
427
|
+
"function approveBountyCompletion(uint256 bountyId, string)",
|
|
428
|
+
// Cancellation & Expiry
|
|
429
|
+
"function cancelBounty(uint256 bountyId)",
|
|
430
|
+
"function expireBounty(uint256 bountyId)",
|
|
431
|
+
// Reward Management
|
|
432
|
+
"function increaseReward(uint256 bountyId, uint256 additionalReward)",
|
|
433
|
+
"function slashCreator(uint256 bountyId, uint256 amount, address to)",
|
|
434
|
+
// Gate Management
|
|
435
|
+
"function setGates(uint256 bountyId, uint256 minTokenBalance, uint256 requiredBadgeId)",
|
|
436
|
+
"function addToWhitelist(uint256 bountyId, address[] addresses)",
|
|
437
|
+
"function removeFromWhitelist(uint256 bountyId, address[] addresses)",
|
|
438
|
+
"function canSubmit(uint256 bountyId, address submitter) view returns (bool)",
|
|
439
|
+
// View Functions
|
|
440
|
+
"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))",
|
|
441
|
+
"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))",
|
|
442
|
+
"function getSubmissionCount(uint256 bountyId) view returns (uint256)",
|
|
443
|
+
"function getLeadingSubmission(uint256 bountyId) view returns (uint256 submissionId, uint256 votes)",
|
|
444
|
+
"function calculateStake(uint256 reward) view returns (uint256)",
|
|
445
|
+
// State Mappings
|
|
446
|
+
"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)",
|
|
447
|
+
"function nextBountyId() view returns (uint256)",
|
|
448
|
+
"function submissionCount(uint256) view returns (uint256)",
|
|
449
|
+
"function submitterToSubmission(uint256, address) view returns (uint256)",
|
|
450
|
+
"function hasVotedInBounty(uint256, address) view returns (bool)",
|
|
451
|
+
"function voterChosenSubmission(uint256, address) view returns (uint256)",
|
|
452
|
+
"function whitelist(uint256, address) view returns (bool)",
|
|
453
|
+
"function hasWhitelist(uint256) view returns (bool)",
|
|
454
|
+
// External Contracts
|
|
455
|
+
"function sxxxToken() view returns (address)",
|
|
456
|
+
"function contributorSystem() view returns (address)",
|
|
457
|
+
"function governanceConfig() view returns (address)",
|
|
458
|
+
"function communityTreasury() view returns (address)",
|
|
459
|
+
"function governanceContract() view returns (address)",
|
|
460
|
+
"function libraryRegistry() view returns (address)",
|
|
461
|
+
"function subdao() view returns (address)",
|
|
462
|
+
"function soulboundBadge() view returns (address)",
|
|
463
|
+
// Admin
|
|
464
|
+
"function setGovernanceContract(address _gov)",
|
|
465
|
+
"function setCommunityTreasury(address _treasury)",
|
|
466
|
+
"function setLibraryRegistry(address _registry)",
|
|
467
|
+
"function setSoulboundBadge(address _sbtAddress)",
|
|
468
|
+
"function grantRole(bytes32 role, address account)",
|
|
469
|
+
"function revokeRole(bytes32 role, address account)",
|
|
470
|
+
"function hasRole(bytes32 role, address account) view returns (bool)",
|
|
471
|
+
// Events
|
|
472
|
+
"event BountyCreated(uint256 indexed bountyId, address indexed creator, string title, uint256 reward, uint256 deposit, uint8 mode, address assignee)",
|
|
473
|
+
"event SubmissionReceived(uint256 indexed bountyId, uint256 indexed submissionId, address indexed submitter, string promptIPFS)",
|
|
474
|
+
"event BountyClaimed(uint256 indexed bountyId, address indexed claimant)",
|
|
475
|
+
"event BountyUnderReview(uint256 indexed bountyId, address indexed claimant, uint256 proposalId)",
|
|
476
|
+
"event VoteCast(uint256 indexed bountyId, uint256 indexed submissionId, address indexed voter, uint256 weight)",
|
|
477
|
+
"event VotingStarted(uint256 indexed bountyId, uint256 votingEndTime)",
|
|
478
|
+
"event BountyCompleted(uint256 indexed bountyId, address indexed winner, uint256 reward, string deliverable)",
|
|
479
|
+
"event BountyAutoApproved(uint256 indexed bountyId, address indexed winner)",
|
|
480
|
+
"event PromptAddedToLibrary(uint256 indexed bountyId, string libraryKey, string promptIPFS)",
|
|
481
|
+
"event BountyCancelled(uint256 indexed bountyId, address indexed creator)",
|
|
482
|
+
"event BountyExpired(uint256 indexed bountyId)",
|
|
483
|
+
"event BountyRewardIncreased(uint256 indexed bountyId, uint256 additionalReward, uint256 newTotal)",
|
|
484
|
+
"event CreatorSlashed(uint256 indexed bountyId, uint256 amount, address indexed to)"
|
|
485
|
+
];
|
|
302
486
|
var Events = {
|
|
303
487
|
ProposalCreated: "event ProposalCreated(uint256 id, address proposer, address[] targets, uint256[] values, string[] signatures, bytes[] calldatas, uint256 startBlock, uint256 endBlock, string description)"
|
|
304
488
|
};
|
|
@@ -321,6 +505,13 @@ var require_abi = __commonJS({
|
|
|
321
505
|
// Protocol treasury (replaces SageTreasury)
|
|
322
506
|
GovernanceBoostMerkle,
|
|
323
507
|
GovernanceBoostDirect,
|
|
508
|
+
// Voting Multiplier System
|
|
509
|
+
VotingMultiplierNFT,
|
|
510
|
+
MultipliedVotes,
|
|
511
|
+
// Auction House
|
|
512
|
+
SageAuctionHouse,
|
|
513
|
+
// Bounty System
|
|
514
|
+
SimpleBountySystem,
|
|
324
515
|
Events
|
|
325
516
|
};
|
|
326
517
|
}
|
|
@@ -678,6 +869,409 @@ var require_subgraph = __commonJS({
|
|
|
678
869
|
listLibraries,
|
|
679
870
|
getSubdaoLibraries,
|
|
680
871
|
getSubdaoPrompts,
|
|
872
|
+
/**
|
|
873
|
+
* Bounty dashboards (SimpleBountySystem)
|
|
874
|
+
*/
|
|
875
|
+
async listBounties({ url, first = 50, skip = 0, status = null, creator = null }) {
|
|
876
|
+
if (!url) throw new Error("subgraph url required");
|
|
877
|
+
const filters = [];
|
|
878
|
+
if (status != null) filters.push(`status: ${Number(status)}`);
|
|
879
|
+
if (creator) {
|
|
880
|
+
const addr = safeGetAddress(creator);
|
|
881
|
+
if (!addr) throw new Error("invalid creator address");
|
|
882
|
+
filters.push(`creator: "${addr.toLowerCase()}"`);
|
|
883
|
+
}
|
|
884
|
+
const where = filters.length ? `where:{ ${filters.join(", ")} }` : "";
|
|
885
|
+
const doc = `
|
|
886
|
+
query($first:Int!,$skip:Int!){
|
|
887
|
+
bounties(
|
|
888
|
+
${where}
|
|
889
|
+
first:$first
|
|
890
|
+
skip:$skip
|
|
891
|
+
orderBy: createdAt
|
|
892
|
+
orderDirection: desc
|
|
893
|
+
){
|
|
894
|
+
id
|
|
895
|
+
contract
|
|
896
|
+
bountyId
|
|
897
|
+
creator
|
|
898
|
+
title
|
|
899
|
+
reward
|
|
900
|
+
creatorDeposit
|
|
901
|
+
mode
|
|
902
|
+
status
|
|
903
|
+
libraryAction
|
|
904
|
+
assignee
|
|
905
|
+
winner
|
|
906
|
+
winningSubmissionId
|
|
907
|
+
libraryKey
|
|
908
|
+
deadline
|
|
909
|
+
votingEndTime
|
|
910
|
+
createdAt
|
|
911
|
+
updatedAt
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
`;
|
|
915
|
+
const data = await query(url, doc, {
|
|
916
|
+
first: Math.min(Math.max(1, Number(first || 50)), 200),
|
|
917
|
+
skip: Number(skip || 0)
|
|
918
|
+
});
|
|
919
|
+
return mapSafe(data?.bounties, (row) => {
|
|
920
|
+
const contract = safeGetAddress(row.contract);
|
|
921
|
+
const creatorAddr = safeGetAddress(row.creator);
|
|
922
|
+
const assignee = row.assignee ? safeGetAddress(row.assignee) : null;
|
|
923
|
+
const winner = row.winner ? safeGetAddress(row.winner) : null;
|
|
924
|
+
if (!contract || !creatorAddr) return null;
|
|
925
|
+
return {
|
|
926
|
+
id: String(row.id),
|
|
927
|
+
contract,
|
|
928
|
+
bountyId: BigInt(String(row.bountyId || "0")),
|
|
929
|
+
creator: creatorAddr,
|
|
930
|
+
title: String(row.title || ""),
|
|
931
|
+
reward: BigInt(String(row.reward || "0")),
|
|
932
|
+
creatorDeposit: BigInt(String(row.creatorDeposit || "0")),
|
|
933
|
+
mode: Number(row.mode || 0),
|
|
934
|
+
status: Number(row.status || 0),
|
|
935
|
+
libraryAction: row.libraryAction != null ? Number(row.libraryAction) : null,
|
|
936
|
+
assignee,
|
|
937
|
+
winner,
|
|
938
|
+
winningSubmissionId: row.winningSubmissionId != null ? BigInt(String(row.winningSubmissionId)) : null,
|
|
939
|
+
libraryKey: row.libraryKey || null,
|
|
940
|
+
deadline: row.deadline != null ? Number(row.deadline) : null,
|
|
941
|
+
votingEndTime: row.votingEndTime != null ? Number(row.votingEndTime) : null,
|
|
942
|
+
createdAt: Number(row.createdAt || 0),
|
|
943
|
+
updatedAt: Number(row.updatedAt || 0)
|
|
944
|
+
};
|
|
945
|
+
});
|
|
946
|
+
},
|
|
947
|
+
async getBounty({ url, id: id2 }) {
|
|
948
|
+
if (!url) throw new Error("subgraph url required");
|
|
949
|
+
const doc = `
|
|
950
|
+
query($id:ID!){
|
|
951
|
+
bounty(id:$id){
|
|
952
|
+
id
|
|
953
|
+
contract
|
|
954
|
+
bountyId
|
|
955
|
+
creator
|
|
956
|
+
title
|
|
957
|
+
reward
|
|
958
|
+
creatorDeposit
|
|
959
|
+
mode
|
|
960
|
+
status
|
|
961
|
+
libraryAction
|
|
962
|
+
assignee
|
|
963
|
+
winner
|
|
964
|
+
winningSubmissionId
|
|
965
|
+
libraryKey
|
|
966
|
+
deadline
|
|
967
|
+
votingEndTime
|
|
968
|
+
snapshotBlock
|
|
969
|
+
governanceProposalId
|
|
970
|
+
createdAt
|
|
971
|
+
updatedAt
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
`;
|
|
975
|
+
const data = await query(url, doc, { id: String(id2) });
|
|
976
|
+
const row = data?.bounty;
|
|
977
|
+
if (!row) return null;
|
|
978
|
+
const contract = safeGetAddress(row.contract);
|
|
979
|
+
const creatorAddr = safeGetAddress(row.creator);
|
|
980
|
+
if (!contract || !creatorAddr) return null;
|
|
981
|
+
return {
|
|
982
|
+
id: String(row.id),
|
|
983
|
+
contract,
|
|
984
|
+
bountyId: BigInt(String(row.bountyId || "0")),
|
|
985
|
+
creator: creatorAddr,
|
|
986
|
+
title: String(row.title || ""),
|
|
987
|
+
reward: BigInt(String(row.reward || "0")),
|
|
988
|
+
creatorDeposit: BigInt(String(row.creatorDeposit || "0")),
|
|
989
|
+
mode: Number(row.mode || 0),
|
|
990
|
+
status: Number(row.status || 0),
|
|
991
|
+
libraryAction: row.libraryAction != null ? Number(row.libraryAction) : null,
|
|
992
|
+
assignee: row.assignee ? safeGetAddress(row.assignee) : null,
|
|
993
|
+
winner: row.winner ? safeGetAddress(row.winner) : null,
|
|
994
|
+
winningSubmissionId: row.winningSubmissionId != null ? BigInt(String(row.winningSubmissionId)) : null,
|
|
995
|
+
libraryKey: row.libraryKey || null,
|
|
996
|
+
deadline: row.deadline != null ? Number(row.deadline) : null,
|
|
997
|
+
votingEndTime: row.votingEndTime != null ? Number(row.votingEndTime) : null,
|
|
998
|
+
snapshotBlock: row.snapshotBlock != null ? Number(row.snapshotBlock) : null,
|
|
999
|
+
governanceProposalId: row.governanceProposalId != null ? BigInt(String(row.governanceProposalId)) : null,
|
|
1000
|
+
createdAt: Number(row.createdAt || 0),
|
|
1001
|
+
updatedAt: Number(row.updatedAt || 0)
|
|
1002
|
+
};
|
|
1003
|
+
},
|
|
1004
|
+
async listBountySubmissions({ url, bountyId, first = 50, skip = 0 }) {
|
|
1005
|
+
if (!url) throw new Error("subgraph url required");
|
|
1006
|
+
const doc = `
|
|
1007
|
+
query($bountyId:BigInt!,$first:Int!,$skip:Int!){
|
|
1008
|
+
bountySubmissions(
|
|
1009
|
+
where:{ bountyId:$bountyId }
|
|
1010
|
+
first:$first
|
|
1011
|
+
skip:$skip
|
|
1012
|
+
orderBy: timestamp
|
|
1013
|
+
orderDirection: asc
|
|
1014
|
+
){
|
|
1015
|
+
id
|
|
1016
|
+
bountyId
|
|
1017
|
+
submissionId
|
|
1018
|
+
submitter
|
|
1019
|
+
promptIPFS
|
|
1020
|
+
deliverableIPFS
|
|
1021
|
+
timestamp
|
|
1022
|
+
voteCount
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
`;
|
|
1026
|
+
const data = await query(url, doc, {
|
|
1027
|
+
bountyId: String(bountyId),
|
|
1028
|
+
first: Math.min(Math.max(1, Number(first || 50)), 200),
|
|
1029
|
+
skip: Number(skip || 0)
|
|
1030
|
+
});
|
|
1031
|
+
return mapSafe(data?.bountySubmissions, (row) => {
|
|
1032
|
+
const submitter = safeGetAddress(row.submitter);
|
|
1033
|
+
if (!submitter) return null;
|
|
1034
|
+
return {
|
|
1035
|
+
id: String(row.id),
|
|
1036
|
+
bountyId: BigInt(String(row.bountyId || "0")),
|
|
1037
|
+
submissionId: BigInt(String(row.submissionId || "0")),
|
|
1038
|
+
submitter,
|
|
1039
|
+
promptIPFS: String(row.promptIPFS || ""),
|
|
1040
|
+
deliverableIPFS: String(row.deliverableIPFS || ""),
|
|
1041
|
+
timestamp: Number(row.timestamp || 0),
|
|
1042
|
+
voteCount: BigInt(String(row.voteCount || "0"))
|
|
1043
|
+
};
|
|
1044
|
+
});
|
|
1045
|
+
},
|
|
1046
|
+
async listBountyVotes({ url, bountyId, first = 100, skip = 0 }) {
|
|
1047
|
+
if (!url) throw new Error("subgraph url required");
|
|
1048
|
+
const doc = `
|
|
1049
|
+
query($bountyId:BigInt!,$first:Int!,$skip:Int!){
|
|
1050
|
+
bountyVotes(
|
|
1051
|
+
where:{ bountyId:$bountyId }
|
|
1052
|
+
first:$first
|
|
1053
|
+
skip:$skip
|
|
1054
|
+
orderBy: blockTimestamp
|
|
1055
|
+
orderDirection: desc
|
|
1056
|
+
){
|
|
1057
|
+
id
|
|
1058
|
+
bountyId
|
|
1059
|
+
submissionId
|
|
1060
|
+
voter
|
|
1061
|
+
weight
|
|
1062
|
+
blockNumber
|
|
1063
|
+
blockTimestamp
|
|
1064
|
+
transactionHash
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
`;
|
|
1068
|
+
const data = await query(url, doc, {
|
|
1069
|
+
bountyId: String(bountyId),
|
|
1070
|
+
first: Math.min(Math.max(1, Number(first || 100)), 500),
|
|
1071
|
+
skip: Number(skip || 0)
|
|
1072
|
+
});
|
|
1073
|
+
return mapSafe(data?.bountyVotes, (row) => {
|
|
1074
|
+
const voter = safeGetAddress(row.voter);
|
|
1075
|
+
if (!voter) return null;
|
|
1076
|
+
return {
|
|
1077
|
+
id: String(row.id),
|
|
1078
|
+
bountyId: BigInt(String(row.bountyId || "0")),
|
|
1079
|
+
submissionId: BigInt(String(row.submissionId || "0")),
|
|
1080
|
+
voter,
|
|
1081
|
+
weight: BigInt(String(row.weight || "0")),
|
|
1082
|
+
blockNumber: Number(row.blockNumber || 0),
|
|
1083
|
+
blockTimestamp: Number(row.blockTimestamp || 0),
|
|
1084
|
+
transactionHash: row.transactionHash || null
|
|
1085
|
+
};
|
|
1086
|
+
});
|
|
1087
|
+
},
|
|
1088
|
+
/**
|
|
1089
|
+
* Multiplier dashboards (VotingMultiplierNFT + SageAuctionHouse)
|
|
1090
|
+
*/
|
|
1091
|
+
async listMultiplierAccounts({ url, dao, first = 100, skip = 0 }) {
|
|
1092
|
+
if (!url) throw new Error("subgraph url required");
|
|
1093
|
+
const daoAddr = safeGetAddress(dao);
|
|
1094
|
+
if (!daoAddr) throw new Error("invalid dao address");
|
|
1095
|
+
const doc = `
|
|
1096
|
+
query($dao:Bytes!,$first:Int!,$skip:Int!){
|
|
1097
|
+
multiplierAccounts(
|
|
1098
|
+
where:{ dao: $dao }
|
|
1099
|
+
first:$first
|
|
1100
|
+
skip:$skip
|
|
1101
|
+
orderBy: currentMultiplierBps
|
|
1102
|
+
orderDirection: desc
|
|
1103
|
+
){
|
|
1104
|
+
id
|
|
1105
|
+
dao
|
|
1106
|
+
account
|
|
1107
|
+
currentMultiplierBps
|
|
1108
|
+
tokenCount
|
|
1109
|
+
updatedAt
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
`;
|
|
1113
|
+
const data = await query(url, doc, {
|
|
1114
|
+
dao: daoAddr.toLowerCase(),
|
|
1115
|
+
first: Math.min(Math.max(1, Number(first || 100)), 500),
|
|
1116
|
+
skip: Number(skip || 0)
|
|
1117
|
+
});
|
|
1118
|
+
return mapSafe(data?.multiplierAccounts, (row) => {
|
|
1119
|
+
const daoNorm = safeGetAddress(row.dao);
|
|
1120
|
+
const account = safeGetAddress(row.account);
|
|
1121
|
+
if (!daoNorm || !account) return null;
|
|
1122
|
+
return {
|
|
1123
|
+
id: String(row.id),
|
|
1124
|
+
dao: daoNorm,
|
|
1125
|
+
account,
|
|
1126
|
+
multiplierBps: BigInt(String(row.currentMultiplierBps || "0")),
|
|
1127
|
+
tokenCount: Number(row.tokenCount || 0),
|
|
1128
|
+
updatedAt: Number(row.updatedAt || 0)
|
|
1129
|
+
};
|
|
1130
|
+
});
|
|
1131
|
+
},
|
|
1132
|
+
async listMultiplierNFTs({ url, dao, owner = null, first = 100, skip = 0 }) {
|
|
1133
|
+
if (!url) throw new Error("subgraph url required");
|
|
1134
|
+
const daoAddr = safeGetAddress(dao);
|
|
1135
|
+
if (!daoAddr) throw new Error("invalid dao address");
|
|
1136
|
+
const ownerAddr = owner ? safeGetAddress(owner) : null;
|
|
1137
|
+
const filters = [`dao: $dao`];
|
|
1138
|
+
if (ownerAddr) filters.push(`owner: $owner`);
|
|
1139
|
+
const where = `where:{ ${filters.join(", ")} }`;
|
|
1140
|
+
const doc = `
|
|
1141
|
+
query($dao:Bytes!,$owner:Bytes,$first:Int!,$skip:Int!){
|
|
1142
|
+
multiplierNFTs(
|
|
1143
|
+
${where}
|
|
1144
|
+
first:$first
|
|
1145
|
+
skip:$skip
|
|
1146
|
+
orderBy: mintedAt
|
|
1147
|
+
orderDirection: desc
|
|
1148
|
+
){
|
|
1149
|
+
id
|
|
1150
|
+
owner
|
|
1151
|
+
dao
|
|
1152
|
+
tier { id name multiplier maxSupply minted price }
|
|
1153
|
+
multiplier
|
|
1154
|
+
tokenURI
|
|
1155
|
+
mintedAt
|
|
1156
|
+
transactionHash
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
`;
|
|
1160
|
+
const variables = {
|
|
1161
|
+
dao: daoAddr.toLowerCase(),
|
|
1162
|
+
owner: ownerAddr ? ownerAddr.toLowerCase() : null,
|
|
1163
|
+
first: Math.min(Math.max(1, Number(first || 100)), 500),
|
|
1164
|
+
skip: Number(skip || 0)
|
|
1165
|
+
};
|
|
1166
|
+
const data = await query(url, doc, variables);
|
|
1167
|
+
return mapSafe(data?.multiplierNFTs, (row) => {
|
|
1168
|
+
const ownerNorm = safeGetAddress(row.owner);
|
|
1169
|
+
const daoNorm = safeGetAddress(row.dao);
|
|
1170
|
+
if (!ownerNorm || !daoNorm) return null;
|
|
1171
|
+
return {
|
|
1172
|
+
id: String(row.id),
|
|
1173
|
+
owner: ownerNorm,
|
|
1174
|
+
dao: daoNorm,
|
|
1175
|
+
tier: row.tier ? {
|
|
1176
|
+
id: String(row.tier.id),
|
|
1177
|
+
name: String(row.tier.name || ""),
|
|
1178
|
+
multiplier: Number(row.tier.multiplier || 0),
|
|
1179
|
+
maxSupply: BigInt(String(row.tier.maxSupply || "0")),
|
|
1180
|
+
minted: BigInt(String(row.tier.minted || "0")),
|
|
1181
|
+
price: BigInt(String(row.tier.price || "0"))
|
|
1182
|
+
} : null,
|
|
1183
|
+
multiplier: Number(row.multiplier || 0),
|
|
1184
|
+
tokenURI: row.tokenURI || null,
|
|
1185
|
+
mintedAt: Number(row.mintedAt || 0),
|
|
1186
|
+
transactionHash: row.transactionHash || null
|
|
1187
|
+
};
|
|
1188
|
+
});
|
|
1189
|
+
},
|
|
1190
|
+
async getCurrentAuction({ url, auctionHouse }) {
|
|
1191
|
+
if (!url) throw new Error("subgraph url required");
|
|
1192
|
+
const addr = safeGetAddress(auctionHouse);
|
|
1193
|
+
if (!addr) throw new Error("invalid auctionHouse address");
|
|
1194
|
+
const doc = `
|
|
1195
|
+
query($id:ID!){
|
|
1196
|
+
multiplierAuction(id:$id){
|
|
1197
|
+
id
|
|
1198
|
+
auctionHouse
|
|
1199
|
+
nft
|
|
1200
|
+
treasury
|
|
1201
|
+
currentNftId
|
|
1202
|
+
currentAmount
|
|
1203
|
+
currentBidder
|
|
1204
|
+
startTime
|
|
1205
|
+
endTime
|
|
1206
|
+
settled
|
|
1207
|
+
updatedAt
|
|
1208
|
+
}
|
|
1209
|
+
}
|
|
1210
|
+
`;
|
|
1211
|
+
const data = await query(url, doc, { id: addr.toLowerCase() });
|
|
1212
|
+
const row = data?.multiplierAuction;
|
|
1213
|
+
if (!row) return null;
|
|
1214
|
+
return {
|
|
1215
|
+
id: String(row.id),
|
|
1216
|
+
auctionHouse: safeGetAddress(row.auctionHouse) || addr,
|
|
1217
|
+
nft: safeGetAddress(row.nft),
|
|
1218
|
+
treasury: safeGetAddress(row.treasury),
|
|
1219
|
+
currentNftId: BigInt(String(row.currentNftId || "0")),
|
|
1220
|
+
currentAmount: BigInt(String(row.currentAmount || "0")),
|
|
1221
|
+
currentBidder: safeGetAddress(row.currentBidder || "0x0000000000000000000000000000000000000000"),
|
|
1222
|
+
startTime: Number(row.startTime || 0),
|
|
1223
|
+
endTime: Number(row.endTime || 0),
|
|
1224
|
+
settled: !!row.settled,
|
|
1225
|
+
updatedAt: Number(row.updatedAt || 0)
|
|
1226
|
+
};
|
|
1227
|
+
},
|
|
1228
|
+
async listAuctionBids({ url, auctionHouse, first = 100, skip = 0 }) {
|
|
1229
|
+
if (!url) throw new Error("subgraph url required");
|
|
1230
|
+
const addr = safeGetAddress(auctionHouse);
|
|
1231
|
+
if (!addr) throw new Error("invalid auctionHouse address");
|
|
1232
|
+
const doc = `
|
|
1233
|
+
query($auctionHouse:Bytes!,$first:Int!,$skip:Int!){
|
|
1234
|
+
multiplierAuctionBids(
|
|
1235
|
+
where:{ auctionHouse:$auctionHouse }
|
|
1236
|
+
first:$first
|
|
1237
|
+
skip:$skip
|
|
1238
|
+
orderBy: blockTimestamp
|
|
1239
|
+
orderDirection: desc
|
|
1240
|
+
){
|
|
1241
|
+
id
|
|
1242
|
+
auctionHouse
|
|
1243
|
+
nftId
|
|
1244
|
+
bidder
|
|
1245
|
+
amount
|
|
1246
|
+
extended
|
|
1247
|
+
blockNumber
|
|
1248
|
+
blockTimestamp
|
|
1249
|
+
transactionHash
|
|
1250
|
+
}
|
|
1251
|
+
}
|
|
1252
|
+
`;
|
|
1253
|
+
const data = await query(url, doc, {
|
|
1254
|
+
auctionHouse: addr.toLowerCase(),
|
|
1255
|
+
first: Math.min(Math.max(1, Number(first || 100)), 500),
|
|
1256
|
+
skip: Number(skip || 0)
|
|
1257
|
+
});
|
|
1258
|
+
return mapSafe(data?.multiplierAuctionBids, (row) => {
|
|
1259
|
+
const bidder = safeGetAddress(row.bidder);
|
|
1260
|
+
const ah = safeGetAddress(row.auctionHouse);
|
|
1261
|
+
if (!ah || !bidder) return null;
|
|
1262
|
+
return {
|
|
1263
|
+
id: String(row.id),
|
|
1264
|
+
auctionHouse: ah,
|
|
1265
|
+
nftId: BigInt(String(row.nftId || "0")),
|
|
1266
|
+
bidder,
|
|
1267
|
+
amount: BigInt(String(row.amount || "0")),
|
|
1268
|
+
extended: !!row.extended,
|
|
1269
|
+
blockNumber: Number(row.blockNumber || 0),
|
|
1270
|
+
blockTimestamp: Number(row.blockTimestamp || 0),
|
|
1271
|
+
transactionHash: row.transactionHash || null
|
|
1272
|
+
};
|
|
1273
|
+
});
|
|
1274
|
+
},
|
|
681
1275
|
/**
|
|
682
1276
|
* Canonical proposal timeline. Tries common fields first, then event-style fallbacks.
|
|
683
1277
|
* Returns { id, createdAt, queuedAt, executedAt, canceledAt, eta, state } (numbers/strings may be null when unavailable).
|
|
@@ -1166,7 +1760,6 @@ var require_ipfs = __commonJS({
|
|
|
1166
1760
|
headers["X-Wallet-Address"] = auth.address;
|
|
1167
1761
|
headers["X-Wallet-Signature"] = auth.signature;
|
|
1168
1762
|
headers["X-Wallet-Nonce"] = auth.nonce;
|
|
1169
|
-
headers["X-Wallet-Message"] = auth.message;
|
|
1170
1763
|
}
|
|
1171
1764
|
return { headers, auth };
|
|
1172
1765
|
}
|
|
@@ -1187,8 +1780,7 @@ var require_ipfs = __commonJS({
|
|
|
1187
1780
|
...extraHeaders,
|
|
1188
1781
|
"X-Wallet-Address": auth.address,
|
|
1189
1782
|
"X-Wallet-Signature": auth.signature,
|
|
1190
|
-
"X-Wallet-Nonce": auth.nonce
|
|
1191
|
-
"X-Wallet-Message": auth.message
|
|
1783
|
+
"X-Wallet-Nonce": auth.nonce
|
|
1192
1784
|
};
|
|
1193
1785
|
return { headers, auth };
|
|
1194
1786
|
}
|
|
@@ -1209,6 +1801,13 @@ var require_ipfs = __commonJS({
|
|
|
1209
1801
|
order.push(name);
|
|
1210
1802
|
};
|
|
1211
1803
|
const normalizedPreference = Array.isArray(preference) ? preference.map((p) => toLowerSafe(p)).filter(Boolean) : preference ? [toLowerSafe(preference)].filter(Boolean) : [];
|
|
1804
|
+
if (process.env.SAGE_DEBUG_WORKER === "1") {
|
|
1805
|
+
console.log("[SDK DEBUG] resolveProviderOrder preference:", preference);
|
|
1806
|
+
console.log("[SDK DEBUG] normalizedPreference:", normalizedPreference);
|
|
1807
|
+
console.log("[SDK DEBUG] config.provider:", config.provider);
|
|
1808
|
+
console.log("[SDK DEBUG] shouldUseWorker():", shouldUseWorker());
|
|
1809
|
+
console.log("[SDK DEBUG] hasPinataCreds():", hasPinataCreds());
|
|
1810
|
+
}
|
|
1212
1811
|
normalizedPreference.forEach(append);
|
|
1213
1812
|
if (shouldUseWorker()) append("worker");
|
|
1214
1813
|
if (hasPinataCreds()) append("pinata");
|
|
@@ -1216,17 +1815,90 @@ var require_ipfs = __commonJS({
|
|
|
1216
1815
|
if (config.simulate) append("simulate");
|
|
1217
1816
|
return order;
|
|
1218
1817
|
}
|
|
1219
|
-
async function uploadViaWorker(payload, { warm, gateways } = {}) {
|
|
1818
|
+
async function uploadViaWorker(payload, { warm, gateways, pin: pin2 } = {}) {
|
|
1819
|
+
const uploadUrl = workerUrl("upload");
|
|
1820
|
+
if (process.env.SAGE_DEBUG_WORKER === "1") {
|
|
1821
|
+
console.log("[SDK DEBUG] uploadViaWorker called");
|
|
1822
|
+
console.log("[SDK DEBUG] workerBaseUrl:", workerBaseUrl());
|
|
1823
|
+
console.log("[SDK DEBUG] uploadUrl:", uploadUrl);
|
|
1824
|
+
console.log("[SDK DEBUG] workerHasAuth:", workerHasAuth());
|
|
1825
|
+
}
|
|
1220
1826
|
const { headers, auth } = await buildWorkerAuthHeaders({ "Content-Type": "application/json" });
|
|
1221
1827
|
const body = { ...payload };
|
|
1222
1828
|
if (auth) body.auth = auth;
|
|
1223
|
-
|
|
1224
|
-
|
|
1829
|
+
if (pin2) {
|
|
1830
|
+
body.pin = typeof pin2 === "string" ? { duration: pin2 } : pin2;
|
|
1831
|
+
}
|
|
1832
|
+
if (process.env.SAGE_DEBUG_WORKER === "1") {
|
|
1833
|
+
console.log("[SDK DEBUG] headers:", Object.keys(headers));
|
|
1834
|
+
console.log("[SDK DEBUG] hasAuth:", !!auth);
|
|
1835
|
+
if (pin2) console.log("[SDK DEBUG] pin:", JSON.stringify(body.pin));
|
|
1836
|
+
}
|
|
1837
|
+
let response;
|
|
1838
|
+
try {
|
|
1839
|
+
response = await axiosInstance.post(uploadUrl, body, { headers, timeout: config.timeoutMs });
|
|
1840
|
+
if (process.env.SAGE_DEBUG_WORKER === "1") {
|
|
1841
|
+
console.log("[SDK DEBUG] Upload response status:", response?.status);
|
|
1842
|
+
console.log("[SDK DEBUG] Upload response data:", JSON.stringify(response?.data || {}));
|
|
1843
|
+
}
|
|
1844
|
+
} catch (uploadErr) {
|
|
1845
|
+
if (process.env.SAGE_DEBUG_WORKER === "1") {
|
|
1846
|
+
console.log("[SDK DEBUG] Upload error:", uploadErr.message);
|
|
1847
|
+
console.log("[SDK DEBUG] Response status:", uploadErr.response?.status);
|
|
1848
|
+
console.log("[SDK DEBUG] Response data:", JSON.stringify(uploadErr.response?.data || {}));
|
|
1849
|
+
}
|
|
1850
|
+
const status = uploadErr.response?.status;
|
|
1851
|
+
const data2 = uploadErr.response?.data;
|
|
1852
|
+
if (status === 400 && data2?.error === "content_blocked") {
|
|
1853
|
+
const error = new Error("content_blocked");
|
|
1854
|
+
error.code = "CONTENT_BLOCKED";
|
|
1855
|
+
error.categories = data2.categories || [];
|
|
1856
|
+
error.reason = data2.reason;
|
|
1857
|
+
error.response = data2;
|
|
1858
|
+
throw error;
|
|
1859
|
+
}
|
|
1860
|
+
if (status === 402) {
|
|
1861
|
+
const error = new Error("payment_required");
|
|
1862
|
+
error.code = "PAYMENT_REQUIRED";
|
|
1863
|
+
error.creditsNeeded = data2?.creditsNeeded;
|
|
1864
|
+
error.balance = data2?.balance;
|
|
1865
|
+
error.duration = data2?.duration;
|
|
1866
|
+
error.accepts = data2?.accepts;
|
|
1867
|
+
error.response = data2;
|
|
1868
|
+
throw error;
|
|
1869
|
+
}
|
|
1870
|
+
throw uploadErr;
|
|
1871
|
+
}
|
|
1872
|
+
const data = response?.data || {};
|
|
1873
|
+
const cid = data.cid || data.IpfsHash;
|
|
1874
|
+
if (response?.status === 202 || data.status === "pending_review") {
|
|
1875
|
+
return {
|
|
1876
|
+
cid: cid || null,
|
|
1877
|
+
provider: "worker",
|
|
1878
|
+
status: "pending_review",
|
|
1879
|
+
categories: data.categories || [],
|
|
1880
|
+
response: data
|
|
1881
|
+
};
|
|
1882
|
+
}
|
|
1225
1883
|
if (!cid) {
|
|
1226
1884
|
throw new Error("Worker response missing cid");
|
|
1227
1885
|
}
|
|
1228
1886
|
if (warm || config.shouldWarm) await warmGateways(cid, { gateways });
|
|
1229
|
-
|
|
1887
|
+
const result = {
|
|
1888
|
+
cid,
|
|
1889
|
+
provider: "worker",
|
|
1890
|
+
response: data
|
|
1891
|
+
};
|
|
1892
|
+
if (data.moderation) {
|
|
1893
|
+
result.moderation = data.moderation;
|
|
1894
|
+
}
|
|
1895
|
+
if (data.pinned !== void 0) {
|
|
1896
|
+
result.pinned = data.pinned;
|
|
1897
|
+
result.expiresAt = data.expiresAt;
|
|
1898
|
+
result.creditsPaid = data.creditsPaid;
|
|
1899
|
+
result.urls = data.urls;
|
|
1900
|
+
}
|
|
1901
|
+
return result;
|
|
1230
1902
|
}
|
|
1231
1903
|
async function uploadToPinata(payload, { filename = "payload.json", metadata, warm, gateways } = {}) {
|
|
1232
1904
|
if (!hasPinataCreds()) {
|
|
@@ -1304,7 +1976,7 @@ var require_ipfs = __commonJS({
|
|
|
1304
1976
|
return { cid, provider: "simulate" };
|
|
1305
1977
|
}
|
|
1306
1978
|
async function uploadPayload(payload, options2 = {}) {
|
|
1307
|
-
const { providers, provider, warm, gateways, filename, metadata } = options2;
|
|
1979
|
+
const { providers, provider, warm, gateways, filename, metadata, pin: pin2 } = options2;
|
|
1308
1980
|
const order = resolveProviderOrder(providers || provider);
|
|
1309
1981
|
if (!order.length) {
|
|
1310
1982
|
throw new Error("No IPFS providers configured. Set Pinata credentials, worker upload, or enable test mode");
|
|
@@ -1313,7 +1985,7 @@ var require_ipfs = __commonJS({
|
|
|
1313
1985
|
for (const candidate of order) {
|
|
1314
1986
|
try {
|
|
1315
1987
|
if (candidate === "worker") {
|
|
1316
|
-
return await uploadViaWorker(payload, { warm, gateways });
|
|
1988
|
+
return await uploadViaWorker(payload, { warm, gateways, pin: pin2 });
|
|
1317
1989
|
}
|
|
1318
1990
|
if (candidate === "pinata") {
|
|
1319
1991
|
return await uploadToPinata(payload, { filename, metadata, warm, gateways });
|
|
@@ -1325,6 +1997,9 @@ var require_ipfs = __commonJS({
|
|
|
1325
1997
|
return await uploadSimulated(payload, { warm, gateways });
|
|
1326
1998
|
}
|
|
1327
1999
|
} catch (error2) {
|
|
2000
|
+
if (error2.code === "CONTENT_BLOCKED" || error2.code === "PAYMENT_REQUIRED") {
|
|
2001
|
+
throw error2;
|
|
2002
|
+
}
|
|
1328
2003
|
errors.push({ provider: candidate, error: error2 });
|
|
1329
2004
|
}
|
|
1330
2005
|
}
|
|
@@ -1333,7 +2008,7 @@ var require_ipfs = __commonJS({
|
|
|
1333
2008
|
throw error;
|
|
1334
2009
|
}
|
|
1335
2010
|
async function uploadPrompt(options2 = {}) {
|
|
1336
|
-
const { prompt, providers, provider, warm, gateways } = options2;
|
|
2011
|
+
const { prompt, providers, provider, warm, gateways, pin: pin2 } = options2;
|
|
1337
2012
|
if (!prompt || typeof prompt !== "object") {
|
|
1338
2013
|
throw new Error("prompt payload required");
|
|
1339
2014
|
}
|
|
@@ -1359,6 +2034,7 @@ var require_ipfs = __commonJS({
|
|
|
1359
2034
|
provider,
|
|
1360
2035
|
warm,
|
|
1361
2036
|
gateways,
|
|
2037
|
+
pin: pin2,
|
|
1362
2038
|
filename: `${prompt.name || "prompt"}.json`,
|
|
1363
2039
|
metadata
|
|
1364
2040
|
});
|
|
@@ -1593,8 +2269,7 @@ var require_ipfs = __commonJS({
|
|
|
1593
2269
|
"Content-Type": "application/json",
|
|
1594
2270
|
"X-Wallet-Address": address,
|
|
1595
2271
|
"X-Wallet-Signature": signature,
|
|
1596
|
-
"X-Wallet-Nonce": nonce
|
|
1597
|
-
"X-Wallet-Message": message
|
|
2272
|
+
"X-Wallet-Nonce": nonce
|
|
1598
2273
|
};
|
|
1599
2274
|
let verified = false;
|
|
1600
2275
|
try {
|
|
@@ -2452,13 +3127,10 @@ var require_governance = __commonJS({
|
|
|
2452
3127
|
} else {
|
|
2453
3128
|
const govAddr = normaliseGovernor(governor);
|
|
2454
3129
|
try {
|
|
2455
|
-
const
|
|
2456
|
-
|
|
2457
|
-
const ret = await provider.call({ to: govAddr, data });
|
|
2458
|
-
const [tok] = AbiCoder.defaultAbiCoder().decode(["address"], ret);
|
|
2459
|
-
addr = getAddress(tok);
|
|
3130
|
+
const chain = await resolveVotesTokenChain({ provider, governor: govAddr });
|
|
3131
|
+
addr = getAddress(chain.votingToken);
|
|
2460
3132
|
} catch (err) {
|
|
2461
|
-
throw new SageSDKError(CODES.NOT_FOUND, "failed to resolve
|
|
3133
|
+
throw new SageSDKError(CODES.NOT_FOUND, "failed to resolve votes token from governor", { cause: err });
|
|
2462
3134
|
}
|
|
2463
3135
|
}
|
|
2464
3136
|
const user = getAddress(account);
|
|
@@ -2539,6 +3211,210 @@ var require_governance = __commonJS({
|
|
|
2539
3211
|
const token = await g.sxxxToken();
|
|
2540
3212
|
return buildDelegateTx({ token, delegatee: account });
|
|
2541
3213
|
}
|
|
3214
|
+
async function resolveVotesTokenChain({ provider, subdao, governor }) {
|
|
3215
|
+
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
|
|
3216
|
+
if (!subdao && !governor) throw new SageSDKError(CODES.INVALID_ARGS, "subdao or governor required");
|
|
3217
|
+
let votingToken = null;
|
|
3218
|
+
if (governor) {
|
|
3219
|
+
const govAddr = normaliseGovernor(governor);
|
|
3220
|
+
try {
|
|
3221
|
+
const iTok = new Interface(["function token() view returns (address)"]);
|
|
3222
|
+
const data = iTok.encodeFunctionData("token", []);
|
|
3223
|
+
const ret = await provider.call({ to: govAddr, data });
|
|
3224
|
+
if (ret && ret !== "0x") {
|
|
3225
|
+
const [addr] = AbiCoder.defaultAbiCoder().decode(["address"], ret);
|
|
3226
|
+
votingToken = addr;
|
|
3227
|
+
}
|
|
3228
|
+
} catch (_) {
|
|
3229
|
+
}
|
|
3230
|
+
if (!votingToken) {
|
|
3231
|
+
try {
|
|
3232
|
+
const iGov = new Interface(["function sxxxToken() view returns (address)"]);
|
|
3233
|
+
const d2 = iGov.encodeFunctionData("sxxxToken", []);
|
|
3234
|
+
const r2 = await provider.call({ to: govAddr, data: d2 });
|
|
3235
|
+
if (r2 && r2 !== "0x") {
|
|
3236
|
+
const [addr] = AbiCoder.defaultAbiCoder().decode(["address"], r2);
|
|
3237
|
+
votingToken = addr;
|
|
3238
|
+
}
|
|
3239
|
+
} catch (_) {
|
|
3240
|
+
}
|
|
3241
|
+
}
|
|
3242
|
+
}
|
|
3243
|
+
if (!votingToken && subdao) {
|
|
3244
|
+
try {
|
|
3245
|
+
const subAddr = getAddress(subdao);
|
|
3246
|
+
const iSub = new Interface(["function stakeToken() view returns (address)"]);
|
|
3247
|
+
const d3 = iSub.encodeFunctionData("stakeToken", []);
|
|
3248
|
+
const r3 = await provider.call({ to: subAddr, data: d3 });
|
|
3249
|
+
if (r3 && r3 !== "0x") {
|
|
3250
|
+
const [addr] = AbiCoder.defaultAbiCoder().decode(["address"], r3);
|
|
3251
|
+
votingToken = addr;
|
|
3252
|
+
}
|
|
3253
|
+
} catch (_) {
|
|
3254
|
+
}
|
|
3255
|
+
}
|
|
3256
|
+
if (!votingToken) {
|
|
3257
|
+
throw new SageSDKError(CODES.NOT_FOUND, "failed to resolve votes token");
|
|
3258
|
+
}
|
|
3259
|
+
const votingTokenNorm = getAddress(votingToken);
|
|
3260
|
+
let baseToken = votingTokenNorm;
|
|
3261
|
+
let isWrapper = false;
|
|
3262
|
+
try {
|
|
3263
|
+
const wrapperIface = new Interface([
|
|
3264
|
+
"function baseToken() view returns (address)",
|
|
3265
|
+
"function dao() view returns (address)"
|
|
3266
|
+
]);
|
|
3267
|
+
const [rawBase, rawDao] = await Promise.all([
|
|
3268
|
+
provider.call({ to: votingTokenNorm, data: wrapperIface.encodeFunctionData("baseToken", []) }),
|
|
3269
|
+
provider.call({ to: votingTokenNorm, data: wrapperIface.encodeFunctionData("dao", []) })
|
|
3270
|
+
]);
|
|
3271
|
+
if (rawBase && rawBase !== "0x" && rawDao && rawDao !== "0x") {
|
|
3272
|
+
const [decodedBase] = AbiCoder.defaultAbiCoder().decode(["address"], rawBase);
|
|
3273
|
+
const [decodedDao] = AbiCoder.defaultAbiCoder().decode(["address"], rawDao);
|
|
3274
|
+
const baseNorm = getAddress(decodedBase);
|
|
3275
|
+
const daoNorm = getAddress(decodedDao);
|
|
3276
|
+
if (!subdao || daoNorm === getAddress(subdao)) {
|
|
3277
|
+
baseToken = baseNorm;
|
|
3278
|
+
isWrapper = true;
|
|
3279
|
+
}
|
|
3280
|
+
}
|
|
3281
|
+
} catch (_) {
|
|
3282
|
+
}
|
|
3283
|
+
return { votingToken: votingTokenNorm, baseToken, isWrapper };
|
|
3284
|
+
}
|
|
3285
|
+
async function describeVotesToken({ provider, subdao, governor }) {
|
|
3286
|
+
const { votingToken, baseToken, isWrapper } = await resolveVotesTokenChain({ provider, subdao, governor });
|
|
3287
|
+
let multiplierNFT = null;
|
|
3288
|
+
let basis = null;
|
|
3289
|
+
if (isWrapper) {
|
|
3290
|
+
try {
|
|
3291
|
+
const wrapper = new Contract(votingToken, ABI.MultipliedVotes, provider);
|
|
3292
|
+
multiplierNFT = await wrapper.multiplierNFT().catch(() => null);
|
|
3293
|
+
basis = await wrapper.BASIS().catch(() => null);
|
|
3294
|
+
} catch (_) {
|
|
3295
|
+
}
|
|
3296
|
+
}
|
|
3297
|
+
const votingNorm = getAddress(votingToken);
|
|
3298
|
+
const baseNorm = getAddress(baseToken);
|
|
3299
|
+
const multiplierNorm = multiplierNFT && /^0x[0-9a-fA-F]{40}$/.test(String(multiplierNFT)) ? getAddress(multiplierNFT) : null;
|
|
3300
|
+
const basisBig = basis != null ? BigInt(String(basis)) : null;
|
|
3301
|
+
let description;
|
|
3302
|
+
if (!isWrapper) {
|
|
3303
|
+
description = `Voting token = ERC20Votes at ${votingNorm}`;
|
|
3304
|
+
} else {
|
|
3305
|
+
const basisStr = basisBig != null ? basisBig.toString() : "10000";
|
|
3306
|
+
description = `Voting token = MultipliedVotes(base=${baseNorm}, multiplierNFT=${multiplierNorm || "unknown"}, BASIS=${basisStr})`;
|
|
3307
|
+
if (subdao) {
|
|
3308
|
+
description += ` for DAO ${getAddress(subdao)}`;
|
|
3309
|
+
}
|
|
3310
|
+
}
|
|
3311
|
+
return {
|
|
3312
|
+
votingToken: votingNorm,
|
|
3313
|
+
baseToken: baseNorm,
|
|
3314
|
+
isWrapper,
|
|
3315
|
+
multiplierNFT: multiplierNorm,
|
|
3316
|
+
basis: basisBig,
|
|
3317
|
+
description
|
|
3318
|
+
};
|
|
3319
|
+
}
|
|
3320
|
+
async function getVotingStatus({ provider, subdao, governor, account }) {
|
|
3321
|
+
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
|
|
3322
|
+
if (!governor && !subdao) throw new SageSDKError(CODES.INVALID_ARGS, "governor or subdao required");
|
|
3323
|
+
if (!account) throw new SageSDKError(CODES.INVALID_ARGS, "account required");
|
|
3324
|
+
const acct = getAddress(account);
|
|
3325
|
+
let govAddr = null;
|
|
3326
|
+
let subdaoAddr = null;
|
|
3327
|
+
if (governor) {
|
|
3328
|
+
govAddr = normaliseGovernor(governor);
|
|
3329
|
+
}
|
|
3330
|
+
if (subdao) {
|
|
3331
|
+
subdaoAddr = getAddress(subdao);
|
|
3332
|
+
if (!govAddr) {
|
|
3333
|
+
try {
|
|
3334
|
+
const sub = new Contract(subdaoAddr, ["function governor() view returns (address)"], provider);
|
|
3335
|
+
govAddr = getAddress(await sub.governor());
|
|
3336
|
+
} catch (_) {
|
|
3337
|
+
}
|
|
3338
|
+
}
|
|
3339
|
+
}
|
|
3340
|
+
if (!govAddr) throw new SageSDKError(CODES.INVALID_ARGS, "could not resolve governor address");
|
|
3341
|
+
let threshold = null;
|
|
3342
|
+
try {
|
|
3343
|
+
const g = new Contract(govAddr, ABI.Governor, provider);
|
|
3344
|
+
const t = await g.proposalThreshold();
|
|
3345
|
+
threshold = BigInt(t.toString());
|
|
3346
|
+
} catch (_) {
|
|
3347
|
+
}
|
|
3348
|
+
const desc = await describeVotesToken({ provider, subdao: subdaoAddr || void 0, governor: govAddr });
|
|
3349
|
+
let stakeToken = null;
|
|
3350
|
+
if (subdaoAddr) {
|
|
3351
|
+
try {
|
|
3352
|
+
const sub = new Contract(subdaoAddr, ["function stakeToken() view returns (address)"], provider);
|
|
3353
|
+
const st = await sub.stakeToken();
|
|
3354
|
+
if (st && /^0x[0-9a-fA-F]{40}$/.test(String(st))) {
|
|
3355
|
+
stakeToken = getAddress(st);
|
|
3356
|
+
}
|
|
3357
|
+
} catch (_) {
|
|
3358
|
+
}
|
|
3359
|
+
}
|
|
3360
|
+
const VotesABI = [
|
|
3361
|
+
"function getVotes(address) view returns (uint256)",
|
|
3362
|
+
"function delegates(address) view returns (address)",
|
|
3363
|
+
"function balanceOf(address) view returns (uint256)"
|
|
3364
|
+
];
|
|
3365
|
+
let votingPower = null;
|
|
3366
|
+
let delegate = null;
|
|
3367
|
+
let tokenBalance = null;
|
|
3368
|
+
try {
|
|
3369
|
+
const votingC = new Contract(desc.votingToken, VotesABI, provider);
|
|
3370
|
+
const vp = await votingC.getVotes(acct).catch(() => null);
|
|
3371
|
+
if (vp != null) votingPower = BigInt(vp.toString());
|
|
3372
|
+
const del = await votingC.delegates(acct).catch(() => null);
|
|
3373
|
+
if (del && /^0x[0-9a-fA-F]{40}$/.test(String(del))) delegate = getAddress(del);
|
|
3374
|
+
const bal = await votingC.balanceOf(acct).catch(() => null);
|
|
3375
|
+
if (bal != null) tokenBalance = BigInt(bal.toString());
|
|
3376
|
+
} catch (_) {
|
|
3377
|
+
}
|
|
3378
|
+
const canPropose = threshold != null && votingPower != null ? votingPower >= threshold : null;
|
|
3379
|
+
let stakeTokenVotes = null;
|
|
3380
|
+
let stakeTokenDelegate = null;
|
|
3381
|
+
let stakeTokenBalance = null;
|
|
3382
|
+
const tokenMismatch = !!stakeToken && stakeToken.toLowerCase() !== desc.votingToken.toLowerCase();
|
|
3383
|
+
if (stakeToken && tokenMismatch) {
|
|
3384
|
+
try {
|
|
3385
|
+
const stakeC = new Contract(stakeToken, VotesABI, provider);
|
|
3386
|
+
const sv = await stakeC.getVotes(acct).catch(() => null);
|
|
3387
|
+
if (sv != null) stakeTokenVotes = BigInt(sv.toString());
|
|
3388
|
+
const sd = await stakeC.delegates(acct).catch(() => null);
|
|
3389
|
+
if (sd && /^0x[0-9a-fA-F]{40}$/.test(String(sd))) {
|
|
3390
|
+
stakeTokenDelegate = getAddress(sd);
|
|
3391
|
+
}
|
|
3392
|
+
const sb = await stakeC.balanceOf(acct).catch(() => null);
|
|
3393
|
+
if (sb != null) stakeTokenBalance = BigInt(sb.toString());
|
|
3394
|
+
} catch (_) {
|
|
3395
|
+
}
|
|
3396
|
+
}
|
|
3397
|
+
return {
|
|
3398
|
+
subdao: subdaoAddr,
|
|
3399
|
+
governor: govAddr,
|
|
3400
|
+
stakeToken,
|
|
3401
|
+
votingToken: desc.votingToken,
|
|
3402
|
+
baseToken: desc.baseToken,
|
|
3403
|
+
isWrapper: desc.isWrapper,
|
|
3404
|
+
multiplierNFT: desc.multiplierNFT,
|
|
3405
|
+
basis: desc.basis,
|
|
3406
|
+
threshold,
|
|
3407
|
+
votingPower,
|
|
3408
|
+
tokenBalance,
|
|
3409
|
+
delegate,
|
|
3410
|
+
canPropose,
|
|
3411
|
+
tokenMismatch,
|
|
3412
|
+
stakeTokenVotes,
|
|
3413
|
+
stakeTokenDelegate,
|
|
3414
|
+
stakeTokenBalance,
|
|
3415
|
+
description: desc.description
|
|
3416
|
+
};
|
|
3417
|
+
}
|
|
2542
3418
|
module2.exports = {
|
|
2543
3419
|
getGovernorInfo,
|
|
2544
3420
|
getProposal,
|
|
@@ -2570,52 +3446,28 @@ var require_governance = __commonJS({
|
|
|
2570
3446
|
* - SubDAO.stakeToken() (when subdao provided)
|
|
2571
3447
|
*/
|
|
2572
3448
|
resolveVotesToken: async function resolveVotesToken({ provider, subdao, governor }) {
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
if (governor) {
|
|
2576
|
-
const govAddr = normaliseGovernor(governor);
|
|
2577
|
-
try {
|
|
2578
|
-
const iTok = new Interface(["function token() view returns (address)"]);
|
|
2579
|
-
const data = iTok.encodeFunctionData("token", []);
|
|
2580
|
-
const ret = await provider.call({ to: govAddr, data });
|
|
2581
|
-
if (ret && ret !== "0x") {
|
|
2582
|
-
const [addr] = AbiCoder.defaultAbiCoder().decode(["address"], ret);
|
|
2583
|
-
return getAddress(addr);
|
|
2584
|
-
}
|
|
2585
|
-
} catch (_) {
|
|
2586
|
-
}
|
|
2587
|
-
try {
|
|
2588
|
-
const iGov = new Interface(["function sxxxToken() view returns (address)"]);
|
|
2589
|
-
const d2 = iGov.encodeFunctionData("sxxxToken", []);
|
|
2590
|
-
const r2 = await provider.call({ to: govAddr, data: d2 });
|
|
2591
|
-
if (r2 && r2 !== "0x") {
|
|
2592
|
-
const [addr] = AbiCoder.defaultAbiCoder().decode(["address"], r2);
|
|
2593
|
-
return getAddress(addr);
|
|
2594
|
-
}
|
|
2595
|
-
} catch (_) {
|
|
2596
|
-
}
|
|
2597
|
-
}
|
|
2598
|
-
if (subdao) {
|
|
2599
|
-
try {
|
|
2600
|
-
const subAddr = getAddress(subdao);
|
|
2601
|
-
const iSub = new Interface(["function stakeToken() view returns (address)"]);
|
|
2602
|
-
const d3 = iSub.encodeFunctionData("stakeToken", []);
|
|
2603
|
-
const r3 = await provider.call({ to: subAddr, data: d3 });
|
|
2604
|
-
if (r3 && r3 !== "0x") {
|
|
2605
|
-
const [addr] = AbiCoder.defaultAbiCoder().decode(["address"], r3);
|
|
2606
|
-
return getAddress(addr);
|
|
2607
|
-
}
|
|
2608
|
-
} catch (_) {
|
|
2609
|
-
}
|
|
2610
|
-
}
|
|
2611
|
-
throw new SageSDKError(CODES.NOT_FOUND, "failed to resolve votes token");
|
|
3449
|
+
const { votingToken } = await resolveVotesTokenChain({ provider, subdao, governor });
|
|
3450
|
+
return votingToken;
|
|
2612
3451
|
},
|
|
3452
|
+
/**
|
|
3453
|
+
* Resolve the IVotes token chain used for voting (wrapper + base token).
|
|
3454
|
+
* See resolveVotesTokenChain() for details.
|
|
3455
|
+
*/
|
|
3456
|
+
resolveVotesTokenChain,
|
|
3457
|
+
/**
|
|
3458
|
+
* Human-friendly description of the voting token wiring for a Governor/SubDAO.
|
|
3459
|
+
*/
|
|
3460
|
+
describeVotesToken,
|
|
3461
|
+
/**
|
|
3462
|
+
* Get voting status for an account relative to a Governor/SubDAO.
|
|
3463
|
+
*/
|
|
3464
|
+
getVotingStatus,
|
|
2613
3465
|
/** Build a delegate(self) tx using the preferred votes token resolution path. */
|
|
2614
3466
|
buildDelegateSelfPreferred: async function buildDelegateSelfPreferred({ provider, subdao, governor, account }) {
|
|
2615
3467
|
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
|
|
2616
3468
|
if (!account) throw new SageSDKError(CODES.INVALID_ARGS, "account required");
|
|
2617
|
-
const
|
|
2618
|
-
return buildDelegateTx({ token, delegatee: account });
|
|
3469
|
+
const { baseToken } = await resolveVotesTokenChain({ provider, subdao, governor });
|
|
3470
|
+
return buildDelegateTx({ token: baseToken, delegatee: account });
|
|
2619
3471
|
},
|
|
2620
3472
|
/**
|
|
2621
3473
|
* Send a delegate(self) and verify votes at latest-1.
|
|
@@ -2624,15 +3476,15 @@ var require_governance = __commonJS({
|
|
|
2624
3476
|
delegateSelfAndVerify: async function delegateSelfAndVerify({ provider, subdao, governor, account, signer = null, minVotes = null }) {
|
|
2625
3477
|
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
|
|
2626
3478
|
if (!account) throw new SageSDKError(CODES.INVALID_ARGS, "account required");
|
|
2627
|
-
const
|
|
2628
|
-
const payload = buildDelegateTx({ token, delegatee: account });
|
|
3479
|
+
const { votingToken, baseToken } = await resolveVotesTokenChain({ provider, subdao, governor });
|
|
3480
|
+
const payload = buildDelegateTx({ token: baseToken, delegatee: account });
|
|
2629
3481
|
let txHash = null;
|
|
2630
3482
|
if (signer && typeof signer.sendTransaction === "function") {
|
|
2631
3483
|
const tx = await signer.sendTransaction({ to: payload.to, data: payload.data, value: payload.value });
|
|
2632
3484
|
txHash = tx?.hash || null;
|
|
2633
3485
|
if (tx?.wait) await tx.wait();
|
|
2634
3486
|
}
|
|
2635
|
-
const votes = await getVotesLatestMinusOne({ provider, token, account });
|
|
3487
|
+
const votes = await getVotesLatestMinusOne({ provider, token: votingToken, account });
|
|
2636
3488
|
const ok = minVotes != null ? votes >= BigInt(minVotes) : votes > 0n;
|
|
2637
3489
|
return { txHash, ok, votes, payload };
|
|
2638
3490
|
},
|
|
@@ -2686,8 +3538,8 @@ var require_governance = __commonJS({
|
|
|
2686
3538
|
}
|
|
2687
3539
|
let votesOk = null;
|
|
2688
3540
|
try {
|
|
2689
|
-
const
|
|
2690
|
-
const votes = await getVotesLatestMinusOne({ provider, token, account: user });
|
|
3541
|
+
const { votingToken } = await resolveVotesTokenChain({ provider, governor });
|
|
3542
|
+
const votes = await getVotesLatestMinusOne({ provider, token: votingToken, account: user });
|
|
2691
3543
|
const th = threshold != null ? BigInt(threshold) : 0n;
|
|
2692
3544
|
votesOk = votes >= th;
|
|
2693
3545
|
} catch (_) {
|
|
@@ -3221,6 +4073,602 @@ var require_templates = __commonJS({
|
|
|
3221
4073
|
}
|
|
3222
4074
|
});
|
|
3223
4075
|
|
|
4076
|
+
// src/browser/utils.js
|
|
4077
|
+
var require_utils = __commonJS({
|
|
4078
|
+
"src/browser/utils.js"(exports2, module2) {
|
|
4079
|
+
function getAddress(address) {
|
|
4080
|
+
if (!address) return address;
|
|
4081
|
+
const addr = String(address).trim();
|
|
4082
|
+
const normalized = addr.startsWith("0x") ? addr.slice(2).toLowerCase() : addr.toLowerCase();
|
|
4083
|
+
return `0x${normalized}`;
|
|
4084
|
+
}
|
|
4085
|
+
async function keccak256Async(data) {
|
|
4086
|
+
const encoder = new TextEncoder();
|
|
4087
|
+
const dataBuffer = typeof data === "string" ? encoder.encode(data) : data;
|
|
4088
|
+
const hashBuffer = await crypto.subtle.digest("SHA-256", dataBuffer);
|
|
4089
|
+
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
4090
|
+
const hashHex = hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
4091
|
+
return `0x${hashHex}`;
|
|
4092
|
+
}
|
|
4093
|
+
function keccak256Sync(data) {
|
|
4094
|
+
const str = typeof data === "string" ? data : JSON.stringify(data);
|
|
4095
|
+
let hash = 0;
|
|
4096
|
+
for (let i = 0; i < str.length; i++) {
|
|
4097
|
+
const char = str.charCodeAt(i);
|
|
4098
|
+
hash = (hash << 5) - hash + char;
|
|
4099
|
+
hash = hash & hash;
|
|
4100
|
+
}
|
|
4101
|
+
const hex = Math.abs(hash).toString(16).padStart(8, "0");
|
|
4102
|
+
return `0x${hex.repeat(8)}`.slice(0, 66);
|
|
4103
|
+
}
|
|
4104
|
+
module2.exports = {
|
|
4105
|
+
getAddress,
|
|
4106
|
+
keccak256Async,
|
|
4107
|
+
keccak256Sync
|
|
4108
|
+
};
|
|
4109
|
+
}
|
|
4110
|
+
});
|
|
4111
|
+
|
|
4112
|
+
// src/browser/subgraph.js
|
|
4113
|
+
var require_subgraph2 = __commonJS({
|
|
4114
|
+
"src/browser/subgraph.js"(exports2, module2) {
|
|
4115
|
+
var { getAddress } = require_utils();
|
|
4116
|
+
function sanitizeOrderBy(orderBy, allowed, fallback) {
|
|
4117
|
+
const value = (orderBy || "").toString();
|
|
4118
|
+
return allowed.includes(value) ? value : fallback;
|
|
4119
|
+
}
|
|
4120
|
+
function sanitizeOrderDirection(direction, fallback = "desc") {
|
|
4121
|
+
const v = (direction || "").toString().toLowerCase();
|
|
4122
|
+
return v === "asc" ? "asc" : "desc";
|
|
4123
|
+
}
|
|
4124
|
+
function safeGetAddress(value) {
|
|
4125
|
+
try {
|
|
4126
|
+
return getAddress(value);
|
|
4127
|
+
} catch {
|
|
4128
|
+
return null;
|
|
4129
|
+
}
|
|
4130
|
+
}
|
|
4131
|
+
function mapSafe(list, mapper) {
|
|
4132
|
+
const out = [];
|
|
4133
|
+
for (const item of list || []) {
|
|
4134
|
+
try {
|
|
4135
|
+
const v = mapper(item);
|
|
4136
|
+
if (v != null) out.push(v);
|
|
4137
|
+
} catch {
|
|
4138
|
+
}
|
|
4139
|
+
}
|
|
4140
|
+
return out;
|
|
4141
|
+
}
|
|
4142
|
+
async function query(url, document, variables) {
|
|
4143
|
+
if (!url) throw new Error("subgraph url required");
|
|
4144
|
+
const controller = new AbortController();
|
|
4145
|
+
const timeoutId = setTimeout(() => controller.abort(), 1e4);
|
|
4146
|
+
try {
|
|
4147
|
+
const resp = await fetch(url, {
|
|
4148
|
+
method: "POST",
|
|
4149
|
+
headers: { "Content-Type": "application/json" },
|
|
4150
|
+
body: JSON.stringify({ query: document, variables }),
|
|
4151
|
+
signal: controller.signal
|
|
4152
|
+
});
|
|
4153
|
+
clearTimeout(timeoutId);
|
|
4154
|
+
if (!resp.ok) {
|
|
4155
|
+
throw new Error(`HTTP ${resp.status}: ${resp.statusText}`);
|
|
4156
|
+
}
|
|
4157
|
+
const data = await resp.json();
|
|
4158
|
+
if (data && data.errors) {
|
|
4159
|
+
throw new Error(data.errors.map((e) => e.message).join("; "));
|
|
4160
|
+
}
|
|
4161
|
+
return data.data;
|
|
4162
|
+
} catch (error) {
|
|
4163
|
+
clearTimeout(timeoutId);
|
|
4164
|
+
throw error;
|
|
4165
|
+
}
|
|
4166
|
+
}
|
|
4167
|
+
async function listProposals({ url, governor, first = 20, skip = 0 }) {
|
|
4168
|
+
const data = await query(url, `
|
|
4169
|
+
query($governor: Bytes!, $first: Int!, $skip: Int!) {
|
|
4170
|
+
proposals(where: { governor: $governor }, first: $first, skip: $skip, orderBy: createdAt, orderDirection: desc) {
|
|
4171
|
+
id
|
|
4172
|
+
proposer
|
|
4173
|
+
description
|
|
4174
|
+
createdAt
|
|
4175
|
+
targets
|
|
4176
|
+
values
|
|
4177
|
+
calldatas
|
|
4178
|
+
}
|
|
4179
|
+
}
|
|
4180
|
+
`, { governor: String(governor).toLowerCase(), first, skip });
|
|
4181
|
+
return mapSafe(data?.proposals, (p) => {
|
|
4182
|
+
const proposer = safeGetAddress(p.proposer);
|
|
4183
|
+
if (!proposer) return null;
|
|
4184
|
+
const targets = (p.targets || []).map((t) => safeGetAddress(t)).filter(Boolean);
|
|
4185
|
+
if (!targets.length && (p.targets || []).length) return null;
|
|
4186
|
+
return {
|
|
4187
|
+
id: BigInt(p.id),
|
|
4188
|
+
proposer,
|
|
4189
|
+
description: p.description,
|
|
4190
|
+
createdAt: Number(p.createdAt || 0),
|
|
4191
|
+
targets,
|
|
4192
|
+
values: (p.values || []).map((value) => BigInt(String(value))),
|
|
4193
|
+
calldatas: p.calldatas || []
|
|
4194
|
+
};
|
|
4195
|
+
});
|
|
4196
|
+
}
|
|
4197
|
+
var STATE_STRING_TO_NUMBER = {
|
|
4198
|
+
PENDING: 0,
|
|
4199
|
+
ACTIVE: 1,
|
|
4200
|
+
CANCELED: 2,
|
|
4201
|
+
CANCELLED: 2,
|
|
4202
|
+
// some indexes may use British spelling
|
|
4203
|
+
DEFEATED: 3,
|
|
4204
|
+
SUCCEEDED: 4,
|
|
4205
|
+
QUEUED: 5,
|
|
4206
|
+
EXPIRED: 6,
|
|
4207
|
+
EXECUTED: 7
|
|
4208
|
+
};
|
|
4209
|
+
async function listProposalsFiltered({ url, governor, states, fromTimestamp, toTimestamp, first = 20, skip = 0, orderBy = "createdAt", orderDirection = "desc" }) {
|
|
4210
|
+
const govLower = governor ? String(governor).toLowerCase() : null;
|
|
4211
|
+
const statesUpper = Array.isArray(states) && states.length ? states.map((s) => String(s).toUpperCase()) : null;
|
|
4212
|
+
const safeOrderBy = sanitizeOrderBy(orderBy, ["createdAt", "updatedAt", "eta"], "createdAt");
|
|
4213
|
+
const safeOrderDirection = sanitizeOrderDirection(orderDirection, "desc");
|
|
4214
|
+
const doc = `
|
|
4215
|
+
query($first: Int!, $skip: Int!, $governor: Bytes, $states: [String!], $from: Int, $to: Int) {
|
|
4216
|
+
proposals(
|
|
4217
|
+
where: {
|
|
4218
|
+
${governor ? "governor: $governor," : ""}
|
|
4219
|
+
${statesUpper ? "state_in: $states," : ""}
|
|
4220
|
+
${fromTimestamp !== void 0 ? "createdAt_gte: $from," : ""}
|
|
4221
|
+
${toTimestamp !== void 0 ? "createdAt_lte: $to," : ""}
|
|
4222
|
+
}
|
|
4223
|
+
first: $first
|
|
4224
|
+
skip: $skip
|
|
4225
|
+
orderBy: ${safeOrderBy}
|
|
4226
|
+
orderDirection: ${safeOrderDirection}
|
|
4227
|
+
) {
|
|
4228
|
+
id
|
|
4229
|
+
proposer
|
|
4230
|
+
description
|
|
4231
|
+
createdAt
|
|
4232
|
+
updatedAt
|
|
4233
|
+
state
|
|
4234
|
+
eta
|
|
4235
|
+
targets
|
|
4236
|
+
values
|
|
4237
|
+
calldatas
|
|
4238
|
+
}
|
|
4239
|
+
}
|
|
4240
|
+
`;
|
|
4241
|
+
const variables = { first, skip };
|
|
4242
|
+
if (govLower) variables.governor = govLower;
|
|
4243
|
+
if (statesUpper) variables.states = statesUpper;
|
|
4244
|
+
if (fromTimestamp !== void 0) variables.from = Number(fromTimestamp);
|
|
4245
|
+
if (toTimestamp !== void 0) variables.to = Number(toTimestamp);
|
|
4246
|
+
const data = await query(url, doc, variables);
|
|
4247
|
+
return mapSafe(data?.proposals, (p) => {
|
|
4248
|
+
const stateStr = String(p.state || "").toUpperCase();
|
|
4249
|
+
const stateNum = STATE_STRING_TO_NUMBER[stateStr] != null ? STATE_STRING_TO_NUMBER[stateStr] : null;
|
|
4250
|
+
const proposer = safeGetAddress(p.proposer);
|
|
4251
|
+
if (!proposer) return null;
|
|
4252
|
+
const targets = (p.targets || []).map((t) => safeGetAddress(t)).filter(Boolean);
|
|
4253
|
+
if (!targets.length && (p.targets || []).length) return null;
|
|
4254
|
+
return {
|
|
4255
|
+
id: BigInt(p.id),
|
|
4256
|
+
proposer,
|
|
4257
|
+
description: p.description || "",
|
|
4258
|
+
createdAt: Number(p.createdAt || 0),
|
|
4259
|
+
updatedAt: Number(p.updatedAt || 0),
|
|
4260
|
+
state: stateStr,
|
|
4261
|
+
stateNum,
|
|
4262
|
+
eta: p.eta ? BigInt(String(p.eta)) : null,
|
|
4263
|
+
targets,
|
|
4264
|
+
values: (p.values || []).map((value) => BigInt(String(value))),
|
|
4265
|
+
calldatas: p.calldatas || []
|
|
4266
|
+
};
|
|
4267
|
+
});
|
|
4268
|
+
}
|
|
4269
|
+
async function listLibraries({ url, subdao, first = 50, skip = 0 }) {
|
|
4270
|
+
const where = subdao ? `where: { subDAO: "${String(subdao).toLowerCase()}" }` : "";
|
|
4271
|
+
const data = await query(url, `
|
|
4272
|
+
query($first: Int!, $skip: Int!) {
|
|
4273
|
+
libraries(${where} first: $first, skip: $skip, orderBy: createdAt, orderDirection: desc) {
|
|
4274
|
+
id
|
|
4275
|
+
manifestCID
|
|
4276
|
+
subDAO
|
|
4277
|
+
proposer
|
|
4278
|
+
createdAt
|
|
4279
|
+
}
|
|
4280
|
+
}
|
|
4281
|
+
`, { first, skip });
|
|
4282
|
+
return mapSafe(data?.libraries, (lib) => {
|
|
4283
|
+
const sub = safeGetAddress(lib.subDAO);
|
|
4284
|
+
const proposer = safeGetAddress(lib.proposer);
|
|
4285
|
+
if (!sub || !proposer) return null;
|
|
4286
|
+
return {
|
|
4287
|
+
id: lib.id,
|
|
4288
|
+
manifestCID: lib.manifestCID,
|
|
4289
|
+
subdao: sub,
|
|
4290
|
+
proposer,
|
|
4291
|
+
createdAt: Number(lib.createdAt || 0)
|
|
4292
|
+
};
|
|
4293
|
+
});
|
|
4294
|
+
}
|
|
4295
|
+
async function getSubdaoLibraries({ url, subdao, first = 20, skip = 0 }) {
|
|
4296
|
+
if (!url) throw new Error("subgraph url required");
|
|
4297
|
+
const hasFilter = !!subdao;
|
|
4298
|
+
const whereClause = hasFilter ? "where:{ subdao:$subdao }" : "";
|
|
4299
|
+
const doc = `
|
|
4300
|
+
query($subdao:Bytes,$first:Int!,$skip:Int!){
|
|
4301
|
+
subDAOLibraryPointers(
|
|
4302
|
+
${whereClause}
|
|
4303
|
+
first:$first,
|
|
4304
|
+
skip:$skip,
|
|
4305
|
+
orderBy: updatedAt,
|
|
4306
|
+
orderDirection: desc
|
|
4307
|
+
){
|
|
4308
|
+
id
|
|
4309
|
+
subdao
|
|
4310
|
+
libraryId
|
|
4311
|
+
manifestCID
|
|
4312
|
+
previousCID
|
|
4313
|
+
promptCount
|
|
4314
|
+
updatedAt
|
|
4315
|
+
}
|
|
4316
|
+
}
|
|
4317
|
+
`;
|
|
4318
|
+
const variables = {
|
|
4319
|
+
first: Math.min(Math.max(1, Number(first || 20)), 100),
|
|
4320
|
+
skip
|
|
4321
|
+
};
|
|
4322
|
+
if (hasFilter) {
|
|
4323
|
+
const addr = safeGetAddress(subdao);
|
|
4324
|
+
if (!addr) throw new Error("invalid subdao address");
|
|
4325
|
+
variables.subdao = addr.toLowerCase();
|
|
4326
|
+
}
|
|
4327
|
+
const data = await query(url, doc, variables);
|
|
4328
|
+
return mapSafe(data?.subDAOLibraryPointers, (row) => {
|
|
4329
|
+
const id2 = row?.id;
|
|
4330
|
+
const manifestCID = row?.manifestCID;
|
|
4331
|
+
const sub = safeGetAddress(row?.subdao);
|
|
4332
|
+
if (!id2 || !manifestCID || !sub) return null;
|
|
4333
|
+
return {
|
|
4334
|
+
id: String(id2),
|
|
4335
|
+
subdao: sub,
|
|
4336
|
+
libraryId: String(row.libraryId || "main"),
|
|
4337
|
+
manifestCID: String(manifestCID),
|
|
4338
|
+
previousCID: row.previousCID || null,
|
|
4339
|
+
promptCount: row.promptCount != null ? Number(row.promptCount) : null,
|
|
4340
|
+
updatedAt: row.updatedAt != null ? Number(row.updatedAt) : null
|
|
4341
|
+
};
|
|
4342
|
+
});
|
|
4343
|
+
}
|
|
4344
|
+
async function getSubdaoPrompts({ url, registry, first = 50, skip = 0, orderBy = "updatedAt", orderDirection = "desc" }) {
|
|
4345
|
+
if (!url) throw new Error("subgraph url required");
|
|
4346
|
+
const reg = safeGetAddress(registry);
|
|
4347
|
+
if (!reg) throw new Error("invalid registry address");
|
|
4348
|
+
const safeOrderBy = sanitizeOrderBy(orderBy, ["updatedAt"], "updatedAt");
|
|
4349
|
+
const safeOrderDirection = sanitizeOrderDirection(orderDirection, "desc");
|
|
4350
|
+
const doc = `
|
|
4351
|
+
query($registry:Bytes!,$first:Int!,$skip:Int!){
|
|
4352
|
+
prompts(
|
|
4353
|
+
where:{ registry:$registry },
|
|
4354
|
+
first:$first,
|
|
4355
|
+
skip:$skip,
|
|
4356
|
+
orderBy: ${safeOrderBy},
|
|
4357
|
+
orderDirection: ${safeOrderDirection}
|
|
4358
|
+
){
|
|
4359
|
+
id
|
|
4360
|
+
key
|
|
4361
|
+
cid
|
|
4362
|
+
version
|
|
4363
|
+
author
|
|
4364
|
+
registry
|
|
4365
|
+
updatedAt
|
|
4366
|
+
}
|
|
4367
|
+
}
|
|
4368
|
+
`;
|
|
4369
|
+
const data = await query(url, doc, {
|
|
4370
|
+
registry: reg.toLowerCase(),
|
|
4371
|
+
first: Math.min(Math.max(1, Number(first || 50)), 100),
|
|
4372
|
+
skip
|
|
4373
|
+
});
|
|
4374
|
+
return mapSafe(data?.prompts, (p) => {
|
|
4375
|
+
const author = safeGetAddress(p.author);
|
|
4376
|
+
const regAddr = safeGetAddress(p.registry);
|
|
4377
|
+
if (!author || !regAddr) return null;
|
|
4378
|
+
return {
|
|
4379
|
+
id: String(p.id),
|
|
4380
|
+
key: String(p.key),
|
|
4381
|
+
cid: String(p.cid),
|
|
4382
|
+
version: BigInt(p.version || "0"),
|
|
4383
|
+
author,
|
|
4384
|
+
registry: regAddr,
|
|
4385
|
+
updatedAt: Number(p.updatedAt || 0)
|
|
4386
|
+
};
|
|
4387
|
+
});
|
|
4388
|
+
}
|
|
4389
|
+
module2.exports = {
|
|
4390
|
+
query,
|
|
4391
|
+
listProposals,
|
|
4392
|
+
listProposalsFiltered,
|
|
4393
|
+
listLibraries,
|
|
4394
|
+
getSubdaoLibraries,
|
|
4395
|
+
getSubdaoPrompts,
|
|
4396
|
+
/**
|
|
4397
|
+
* Canonical proposal timeline. Tries common fields first, then event-style fallbacks.
|
|
4398
|
+
* Returns { id, createdAt, queuedAt, executedAt, canceledAt, eta, state } (numbers/strings may be null when unavailable).
|
|
4399
|
+
*/
|
|
4400
|
+
async getProposalTimeline({ url, id: id2 }) {
|
|
4401
|
+
if (!url) throw new Error("subgraph url required");
|
|
4402
|
+
const pid = typeof id2 === "bigint" ? id2.toString() : String(id2);
|
|
4403
|
+
try {
|
|
4404
|
+
const data = await query(url, `
|
|
4405
|
+
query($id: ID!) {
|
|
4406
|
+
proposal(id: $id) {
|
|
4407
|
+
id
|
|
4408
|
+
createdAt
|
|
4409
|
+
updatedAt
|
|
4410
|
+
state
|
|
4411
|
+
eta
|
|
4412
|
+
queuedAt
|
|
4413
|
+
executedAt
|
|
4414
|
+
canceledAt
|
|
4415
|
+
}
|
|
4416
|
+
}
|
|
4417
|
+
`, { id: pid });
|
|
4418
|
+
if (data && data.proposal) {
|
|
4419
|
+
const p = data.proposal;
|
|
4420
|
+
return {
|
|
4421
|
+
id: p.id,
|
|
4422
|
+
createdAt: Number(p.createdAt || 0),
|
|
4423
|
+
queuedAt: p.queuedAt != null ? Number(p.queuedAt) : null,
|
|
4424
|
+
executedAt: p.executedAt != null ? Number(p.executedAt) : null,
|
|
4425
|
+
canceledAt: p.canceledAt != null ? Number(p.canceledAt) : null,
|
|
4426
|
+
eta: p.eta != null ? BigInt(String(p.eta)) : null,
|
|
4427
|
+
state: String(p.state || "")
|
|
4428
|
+
};
|
|
4429
|
+
}
|
|
4430
|
+
} catch (_) {
|
|
4431
|
+
}
|
|
4432
|
+
try {
|
|
4433
|
+
const data = await query(url, `
|
|
4434
|
+
query($id: String!) {
|
|
4435
|
+
proposalEvents(where: { proposal: $id }, orderBy: timestamp, orderDirection: asc) {
|
|
4436
|
+
type
|
|
4437
|
+
timestamp
|
|
4438
|
+
}
|
|
4439
|
+
proposals(where: { id: $id }, first:1) { id createdAt state eta }
|
|
4440
|
+
}
|
|
4441
|
+
`, { id: pid });
|
|
4442
|
+
const events = (data?.proposalEvents || []).map((e) => ({ type: String(e.type || ""), timestamp: Number(e.timestamp || 0) }));
|
|
4443
|
+
const base = data?.proposals?.[0] || {};
|
|
4444
|
+
const find = (t) => events.find((e) => e.type.toLowerCase() === t)?.timestamp || null;
|
|
4445
|
+
return {
|
|
4446
|
+
id: base.id || pid,
|
|
4447
|
+
createdAt: Number(base.createdAt || 0),
|
|
4448
|
+
queuedAt: find("queued"),
|
|
4449
|
+
executedAt: find("executed"),
|
|
4450
|
+
canceledAt: find("canceled") || find("cancelled") || null,
|
|
4451
|
+
eta: base.eta != null ? BigInt(String(base.eta)) : null,
|
|
4452
|
+
state: String(base.state || "")
|
|
4453
|
+
};
|
|
4454
|
+
} catch (_) {
|
|
4455
|
+
}
|
|
4456
|
+
return { id: pid, createdAt: 0, queuedAt: null, executedAt: null, canceledAt: null, eta: null, state: "" };
|
|
4457
|
+
},
|
|
4458
|
+
async listLiquidityAddPlans({ url, subdao = null, first = 50, skip = 0, orderBy = "blockTimestamp", orderDirection = "desc" }) {
|
|
4459
|
+
if (!url) throw new Error("subgraph url required");
|
|
4460
|
+
const filters = [];
|
|
4461
|
+
if (subdao) {
|
|
4462
|
+
const addr = safeGetAddress(subdao);
|
|
4463
|
+
if (!addr) throw new Error("invalid subdao address");
|
|
4464
|
+
filters.push(`subdao: "${addr.toLowerCase()}"`);
|
|
4465
|
+
}
|
|
4466
|
+
const where = filters.length ? `where: { ${filters.join(", ")} }` : "";
|
|
4467
|
+
const safeOrderBy = sanitizeOrderBy(orderBy, ["blockTimestamp", "blockNumber"], "blockTimestamp");
|
|
4468
|
+
const safeOrderDirection = sanitizeOrderDirection(orderDirection, "desc");
|
|
4469
|
+
const doc = `
|
|
4470
|
+
query($first:Int!,$skip:Int!){
|
|
4471
|
+
liquidityAddPlans(${where} first:$first, skip:$skip, orderBy: ${safeOrderBy}, orderDirection: ${safeOrderDirection}){
|
|
4472
|
+
id subdao pool sxxxToken stableToken sxxxAmount stableAmount lpRecipient blockNumber blockTimestamp transactionHash
|
|
4473
|
+
}
|
|
4474
|
+
}
|
|
4475
|
+
`;
|
|
4476
|
+
const data = await query(url, doc, { first, skip });
|
|
4477
|
+
return mapSafe(data?.liquidityAddPlans, (e) => {
|
|
4478
|
+
const sub = safeGetAddress(e.subdao);
|
|
4479
|
+
const pool = safeGetAddress(e.pool);
|
|
4480
|
+
const sxxxToken = safeGetAddress(e.sxxxToken);
|
|
4481
|
+
const stableToken = safeGetAddress(e.stableToken);
|
|
4482
|
+
const lpRecipient = safeGetAddress(e.lpRecipient);
|
|
4483
|
+
if (!sub || !pool || !sxxxToken || !stableToken || !lpRecipient) return null;
|
|
4484
|
+
return {
|
|
4485
|
+
id: String(e.id),
|
|
4486
|
+
subdao: sub,
|
|
4487
|
+
pool,
|
|
4488
|
+
sxxxToken,
|
|
4489
|
+
stableToken,
|
|
4490
|
+
sxxxAmount: BigInt(String(e.sxxxAmount)),
|
|
4491
|
+
stableAmount: BigInt(String(e.stableAmount)),
|
|
4492
|
+
lpRecipient,
|
|
4493
|
+
blockNumber: Number(e.blockNumber || 0),
|
|
4494
|
+
blockTimestamp: Number(e.blockTimestamp || 0),
|
|
4495
|
+
transactionHash: e.transactionHash
|
|
4496
|
+
};
|
|
4497
|
+
});
|
|
4498
|
+
},
|
|
4499
|
+
async listLiquidityRemovePlans({ url, subdao = null, first = 50, skip = 0, orderBy = "blockTimestamp", orderDirection = "desc" }) {
|
|
4500
|
+
if (!url) throw new Error("subgraph url required");
|
|
4501
|
+
const filters = [];
|
|
4502
|
+
if (subdao) {
|
|
4503
|
+
const addr = safeGetAddress(subdao);
|
|
4504
|
+
if (!addr) throw new Error("invalid subdao address");
|
|
4505
|
+
filters.push(`subdao: "${addr.toLowerCase()}"`);
|
|
4506
|
+
}
|
|
4507
|
+
const where = filters.length ? `where: { ${filters.join(", ")} }` : "";
|
|
4508
|
+
const safeOrderBy = sanitizeOrderBy(orderBy, ["blockTimestamp", "blockNumber"], "blockTimestamp");
|
|
4509
|
+
const safeOrderDirection = sanitizeOrderDirection(orderDirection, "desc");
|
|
4510
|
+
const doc = `
|
|
4511
|
+
query($first:Int!,$skip:Int!){
|
|
4512
|
+
liquidityRemovePlans(${where} first:$first, skip:$skip, orderBy: ${safeOrderBy}, orderDirection: ${safeOrderDirection}){
|
|
4513
|
+
id subdao pool lpToken lpAmount recipient blockNumber blockTimestamp transactionHash
|
|
4514
|
+
}
|
|
4515
|
+
}
|
|
4516
|
+
`;
|
|
4517
|
+
const data = await query(url, doc, { first, skip });
|
|
4518
|
+
return mapSafe(data?.liquidityRemovePlans, (e) => {
|
|
4519
|
+
const sub = safeGetAddress(e.subdao);
|
|
4520
|
+
const pool = safeGetAddress(e.pool);
|
|
4521
|
+
const lpToken = safeGetAddress(e.lpToken);
|
|
4522
|
+
const recipient = safeGetAddress(e.recipient);
|
|
4523
|
+
if (!sub || !pool || !lpToken || !recipient) return null;
|
|
4524
|
+
return {
|
|
4525
|
+
id: String(e.id),
|
|
4526
|
+
subdao: sub,
|
|
4527
|
+
pool,
|
|
4528
|
+
lpToken,
|
|
4529
|
+
lpAmount: BigInt(String(e.lpAmount)),
|
|
4530
|
+
recipient,
|
|
4531
|
+
blockNumber: Number(e.blockNumber || 0),
|
|
4532
|
+
blockTimestamp: Number(e.blockTimestamp || 0),
|
|
4533
|
+
transactionHash: e.transactionHash
|
|
4534
|
+
};
|
|
4535
|
+
});
|
|
4536
|
+
},
|
|
4537
|
+
async listPromptsByTag({ url, tagsHash, registry = null, first = 50, skip = 0, orderBy = "updatedAt", orderDirection = "desc" }) {
|
|
4538
|
+
if (!url) throw new Error("subgraph url required");
|
|
4539
|
+
const clauses = [`tagsHash: "${String(tagsHash)}"`];
|
|
4540
|
+
if (registry) {
|
|
4541
|
+
const addr = safeGetAddress(registry);
|
|
4542
|
+
if (!addr) throw new Error("invalid registry address");
|
|
4543
|
+
clauses.push(`registry: "${addr.toLowerCase()}"`);
|
|
4544
|
+
}
|
|
4545
|
+
const where = `where: { ${clauses.join(", ")} }`;
|
|
4546
|
+
const safeOrderBy = sanitizeOrderBy(orderBy, ["updatedAt"], "updatedAt");
|
|
4547
|
+
const safeOrderDirection = sanitizeOrderDirection(orderDirection, "desc");
|
|
4548
|
+
const doc = `
|
|
4549
|
+
query($first:Int!,$skip:Int!) {
|
|
4550
|
+
prompts(${where} first:$first, skip:$skip, orderBy: ${safeOrderBy}, orderDirection: ${safeOrderDirection}) {
|
|
4551
|
+
id key cid version author registry updatedAt tagsHash
|
|
4552
|
+
}
|
|
4553
|
+
}
|
|
4554
|
+
`;
|
|
4555
|
+
const data = await query(url, doc, { first, skip });
|
|
4556
|
+
return mapSafe(data?.prompts, (p) => {
|
|
4557
|
+
const author = safeGetAddress(p.author);
|
|
4558
|
+
const regAddr = safeGetAddress(p.registry);
|
|
4559
|
+
if (!author || !regAddr) return null;
|
|
4560
|
+
return {
|
|
4561
|
+
id: String(p.id),
|
|
4562
|
+
key: String(p.key),
|
|
4563
|
+
cid: String(p.cid),
|
|
4564
|
+
version: BigInt(p.version || "0"),
|
|
4565
|
+
author,
|
|
4566
|
+
registry: regAddr,
|
|
4567
|
+
updatedAt: Number(p.updatedAt || 0),
|
|
4568
|
+
tagsHash: String(p.tagsHash || "")
|
|
4569
|
+
};
|
|
4570
|
+
});
|
|
4571
|
+
},
|
|
4572
|
+
// Prompt helpers (registry scoped)
|
|
4573
|
+
async listRegistryPrompts({ url, registry, first = 50, skip = 0, orderBy = "updatedAt", orderDirection = "desc" }) {
|
|
4574
|
+
if (!url) throw new Error("subgraph url required");
|
|
4575
|
+
const reg = safeGetAddress(registry);
|
|
4576
|
+
if (!reg) throw new Error("invalid registry address");
|
|
4577
|
+
const safeOrderBy = sanitizeOrderBy(orderBy, ["updatedAt"], "updatedAt");
|
|
4578
|
+
const safeOrderDirection = sanitizeOrderDirection(orderDirection, "desc");
|
|
4579
|
+
const doc = `
|
|
4580
|
+
query($first:Int!,$skip:Int!,$registry:Bytes!) {
|
|
4581
|
+
prompts(where:{ registry: $registry }, first:$first, skip:$skip, orderBy: ${safeOrderBy}, orderDirection: ${safeOrderDirection}) {
|
|
4582
|
+
id
|
|
4583
|
+
key
|
|
4584
|
+
cid
|
|
4585
|
+
version
|
|
4586
|
+
author
|
|
4587
|
+
registry
|
|
4588
|
+
updatedAt
|
|
4589
|
+
}
|
|
4590
|
+
}
|
|
4591
|
+
`;
|
|
4592
|
+
const data = await query(url, doc, { first, skip, registry: reg.toLowerCase() });
|
|
4593
|
+
return mapSafe(data?.prompts, (p) => {
|
|
4594
|
+
const author = safeGetAddress(p.author);
|
|
4595
|
+
const regAddr = safeGetAddress(p.registry);
|
|
4596
|
+
if (!author || !regAddr) return null;
|
|
4597
|
+
return {
|
|
4598
|
+
id: String(p.id),
|
|
4599
|
+
key: String(p.key),
|
|
4600
|
+
cid: String(p.cid),
|
|
4601
|
+
version: BigInt(p.version || "0"),
|
|
4602
|
+
author,
|
|
4603
|
+
registry: regAddr,
|
|
4604
|
+
updatedAt: Number(p.updatedAt || 0)
|
|
4605
|
+
};
|
|
4606
|
+
});
|
|
4607
|
+
},
|
|
4608
|
+
async getPromptByKey({ url, registry, key }) {
|
|
4609
|
+
if (!url) throw new Error("subgraph url required");
|
|
4610
|
+
const reg = safeGetAddress(registry);
|
|
4611
|
+
if (!reg) throw new Error("invalid registry address");
|
|
4612
|
+
const doc = `
|
|
4613
|
+
query($registry:Bytes!,$key:String!) {
|
|
4614
|
+
prompts(where:{ registry: $registry, key: $key }, first:1) {
|
|
4615
|
+
id
|
|
4616
|
+
key
|
|
4617
|
+
cid
|
|
4618
|
+
version
|
|
4619
|
+
author
|
|
4620
|
+
registry
|
|
4621
|
+
updatedAt
|
|
4622
|
+
}
|
|
4623
|
+
}
|
|
4624
|
+
`;
|
|
4625
|
+
const data = await query(url, doc, { registry: reg.toLowerCase(), key: String(key) });
|
|
4626
|
+
const p = (data?.prompts || [])[0];
|
|
4627
|
+
if (!p) return null;
|
|
4628
|
+
const author = safeGetAddress(p.author);
|
|
4629
|
+
const regAddr = safeGetAddress(p.registry);
|
|
4630
|
+
if (!author || !regAddr) return null;
|
|
4631
|
+
return {
|
|
4632
|
+
id: String(p.id),
|
|
4633
|
+
key: String(p.key),
|
|
4634
|
+
cid: String(p.cid),
|
|
4635
|
+
version: BigInt(p.version || "0"),
|
|
4636
|
+
author,
|
|
4637
|
+
registry: regAddr,
|
|
4638
|
+
updatedAt: Number(p.updatedAt || 0)
|
|
4639
|
+
};
|
|
4640
|
+
},
|
|
4641
|
+
async getProposalById({ url, id: id2 }) {
|
|
4642
|
+
if (!url) throw new Error("subgraph url required");
|
|
4643
|
+
const doc = `query($id: ID!){ proposal(id:$id){ id proposer description createdAt updatedAt state eta targets values calldatas } }`;
|
|
4644
|
+
const data = await query(url, doc, { id: String(id2) });
|
|
4645
|
+
const p = data?.proposal;
|
|
4646
|
+
if (!p) return null;
|
|
4647
|
+
try {
|
|
4648
|
+
const proposer = safeGetAddress(p.proposer);
|
|
4649
|
+
if (!proposer) return null;
|
|
4650
|
+
const targets = (p.targets || []).map((t) => safeGetAddress(t)).filter(Boolean);
|
|
4651
|
+
if (!targets.length && (p.targets || []).length) return null;
|
|
4652
|
+
return {
|
|
4653
|
+
id: BigInt(p.id),
|
|
4654
|
+
proposer,
|
|
4655
|
+
description: p.description || "",
|
|
4656
|
+
createdAt: Number(p.createdAt || 0),
|
|
4657
|
+
updatedAt: Number(p.updatedAt || 0),
|
|
4658
|
+
state: String(p.state || ""),
|
|
4659
|
+
eta: p.eta ? BigInt(String(p.eta)) : null,
|
|
4660
|
+
targets,
|
|
4661
|
+
values: (p.values || []).map((v) => BigInt(String(v))),
|
|
4662
|
+
calldatas: p.calldatas || []
|
|
4663
|
+
};
|
|
4664
|
+
} catch {
|
|
4665
|
+
return null;
|
|
4666
|
+
}
|
|
4667
|
+
}
|
|
4668
|
+
};
|
|
4669
|
+
}
|
|
4670
|
+
});
|
|
4671
|
+
|
|
3224
4672
|
// src/adapters/governance/openzeppelin.js
|
|
3225
4673
|
var require_openzeppelin = __commonJS({
|
|
3226
4674
|
"src/adapters/governance/openzeppelin.js"(exports2, module2) {
|
|
@@ -3575,6 +5023,7 @@ var require_operations = __commonJS({
|
|
|
3575
5023
|
cache = null,
|
|
3576
5024
|
fromBlock = 0,
|
|
3577
5025
|
helperAddress = null,
|
|
5026
|
+
subgraphUrl = null,
|
|
3578
5027
|
hints = {},
|
|
3579
5028
|
chunkSizeBlocks = 1e4,
|
|
3580
5029
|
lookBackBlocks = 2e3,
|
|
@@ -3588,6 +5037,27 @@ var require_operations = __commonJS({
|
|
|
3588
5037
|
const cached = await cacheAdapter.load(govAddr, id2);
|
|
3589
5038
|
if (cached) return cached;
|
|
3590
5039
|
}
|
|
5040
|
+
if (subgraphUrl) {
|
|
5041
|
+
try {
|
|
5042
|
+
const subgraph = require_subgraph2();
|
|
5043
|
+
const sgProposal = await subgraph.getProposalById({ url: subgraphUrl, id: String(id2) });
|
|
5044
|
+
if (sgProposal && sgProposal.targets && sgProposal.targets.length > 0) {
|
|
5045
|
+
const tuple2 = {
|
|
5046
|
+
id: id2,
|
|
5047
|
+
governor: govAddr,
|
|
5048
|
+
targets: sgProposal.targets,
|
|
5049
|
+
values: sgProposal.values || [],
|
|
5050
|
+
calldatas: sgProposal.calldatas || [],
|
|
5051
|
+
description: sgProposal.description || "",
|
|
5052
|
+
descriptionHash: sgProposal.description ? keccak256(toUtf8Bytes(sgProposal.description)) : null,
|
|
5053
|
+
createdBlock: sgProposal.createdAt || null
|
|
5054
|
+
};
|
|
5055
|
+
if (cacheAdapter) await cacheAdapter.save(govAddr, id2, tuple2);
|
|
5056
|
+
return tuple2;
|
|
5057
|
+
}
|
|
5058
|
+
} catch (_) {
|
|
5059
|
+
}
|
|
5060
|
+
}
|
|
3591
5061
|
if (helperAddress) {
|
|
3592
5062
|
try {
|
|
3593
5063
|
const helperAbi = [
|
|
@@ -3801,8 +5271,14 @@ var require_operations = __commonJS({
|
|
|
3801
5271
|
]);
|
|
3802
5272
|
let resolvedSubDAO = subdao;
|
|
3803
5273
|
if (!resolvedSubDAO) {
|
|
3804
|
-
|
|
3805
|
-
|
|
5274
|
+
try {
|
|
5275
|
+
const subDAOInterface = new Interface(["function subDAO() view returns (address)"]);
|
|
5276
|
+
const subdaoContract = new Contract(govAddr, subDAOInterface, provider);
|
|
5277
|
+
resolvedSubDAO = await subdaoContract.subDAO().catch(() => null);
|
|
5278
|
+
if (resolvedSubDAO === ZeroAddress) resolvedSubDAO = null;
|
|
5279
|
+
} catch {
|
|
5280
|
+
resolvedSubDAO = null;
|
|
5281
|
+
}
|
|
3806
5282
|
}
|
|
3807
5283
|
let mode = null;
|
|
3808
5284
|
let eligible = null;
|
|
@@ -3877,10 +5353,11 @@ var require_operations = __commonJS({
|
|
|
3877
5353
|
refresh = false,
|
|
3878
5354
|
cache = null,
|
|
3879
5355
|
includeTimeline = false,
|
|
3880
|
-
helperAddress = null
|
|
5356
|
+
helperAddress = null,
|
|
5357
|
+
subgraphUrl = null
|
|
3881
5358
|
}) {
|
|
3882
5359
|
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
|
|
3883
|
-
const tuple = await resolveProposalTuple({ provider, governor, proposalId, refresh, cache, helperAddress });
|
|
5360
|
+
const tuple = await resolveProposalTuple({ provider, governor, proposalId, refresh, cache, helperAddress, subgraphUrl });
|
|
3884
5361
|
let proposal = null;
|
|
3885
5362
|
try {
|
|
3886
5363
|
proposal = await governance.getProposal({ provider, governor: tuple.governor, id: tuple.id });
|
|
@@ -4218,8 +5695,6 @@ var require_factory = __commonJS({
|
|
|
4218
5695
|
stableCreationFee,
|
|
4219
5696
|
feeReceiver,
|
|
4220
5697
|
allowStableFee,
|
|
4221
|
-
stablePromptForkFee,
|
|
4222
|
-
allowStablePromptForkFee,
|
|
4223
5698
|
stableForkFee,
|
|
4224
5699
|
allowStableForkFee,
|
|
4225
5700
|
timelockMinDelay,
|
|
@@ -4243,8 +5718,6 @@ var require_factory = __commonJS({
|
|
|
4243
5718
|
}
|
|
4244
5719
|
})(),
|
|
4245
5720
|
contract.allowStableFee().catch(() => null),
|
|
4246
|
-
contract.stablePromptForkFee().catch(() => null),
|
|
4247
|
-
contract.allowStablePromptForkFee().catch(() => null),
|
|
4248
5721
|
contract.stableForkFee().catch(() => null),
|
|
4249
5722
|
contract.allowStableForkFee().catch(() => null),
|
|
4250
5723
|
contract.timelockMinDelay().catch(() => null),
|
|
@@ -4260,8 +5733,6 @@ var require_factory = __commonJS({
|
|
|
4260
5733
|
stableCreationFee,
|
|
4261
5734
|
feeReceiver: feeReceiver && feeReceiver !== "0x0000000000000000000000000000000000000000" ? getAddress(feeReceiver) : null,
|
|
4262
5735
|
allowStableFee,
|
|
4263
|
-
stablePromptForkFee,
|
|
4264
|
-
allowStablePromptForkFee,
|
|
4265
5736
|
stableForkFee,
|
|
4266
5737
|
allowStableForkFee,
|
|
4267
5738
|
timelockMinDelay,
|
|
@@ -4593,6 +6064,113 @@ var require_factory = __commonJS({
|
|
|
4593
6064
|
}
|
|
4594
6065
|
});
|
|
4595
6066
|
|
|
6067
|
+
// src/lineage/index.js
|
|
6068
|
+
var require_lineage = __commonJS({
|
|
6069
|
+
"src/lineage/index.js"(exports2, module2) {
|
|
6070
|
+
var { Contract, getAddress } = __require("ethers");
|
|
6071
|
+
var { SageSDKError, CODES } = require_errors();
|
|
6072
|
+
var LINEAGE_ABI = [
|
|
6073
|
+
"function libraryByDAO(address) view returns (string manifestCID, address lastUpdater, uint256 lastUpdated, string version, address forkedFromDAO, uint256 sxxxForkFee)",
|
|
6074
|
+
"function getLibraryForkFee(address) view returns (uint256)"
|
|
6075
|
+
];
|
|
6076
|
+
var ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
6077
|
+
function normalise(address, label) {
|
|
6078
|
+
if (!address) throw new SageSDKError(CODES.INVALID_ARGS, `${label} required`);
|
|
6079
|
+
try {
|
|
6080
|
+
return getAddress(address);
|
|
6081
|
+
} catch (err) {
|
|
6082
|
+
throw new SageSDKError(CODES.INVALID_ARGS, `invalid ${label}`, { cause: err });
|
|
6083
|
+
}
|
|
6084
|
+
}
|
|
6085
|
+
async function getParentLibrary({ provider, registry, subdao }) {
|
|
6086
|
+
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
|
|
6087
|
+
if (!registry) throw new SageSDKError(CODES.INVALID_ARGS, "registry required");
|
|
6088
|
+
if (!subdao) throw new SageSDKError(CODES.INVALID_ARGS, "subdao required");
|
|
6089
|
+
try {
|
|
6090
|
+
const contract = new Contract(normalise(registry, "registry"), LINEAGE_ABI, provider);
|
|
6091
|
+
const info = await contract.libraryByDAO(normalise(subdao, "subdao"));
|
|
6092
|
+
const parent = info.forkedFromDAO;
|
|
6093
|
+
if (!parent || parent === ZERO_ADDRESS) {
|
|
6094
|
+
return null;
|
|
6095
|
+
}
|
|
6096
|
+
return getAddress(parent).toLowerCase();
|
|
6097
|
+
} catch (err) {
|
|
6098
|
+
throw new SageSDKError(CODES.CONTRACT_ERROR, "Failed to fetch parent library", { cause: err });
|
|
6099
|
+
}
|
|
6100
|
+
}
|
|
6101
|
+
async function getLineageChain({ provider, registry, subdao }) {
|
|
6102
|
+
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
|
|
6103
|
+
if (!registry) throw new SageSDKError(CODES.INVALID_ARGS, "registry required");
|
|
6104
|
+
if (!subdao) throw new SageSDKError(CODES.INVALID_ARGS, "subdao required");
|
|
6105
|
+
try {
|
|
6106
|
+
const contract = new Contract(normalise(registry, "registry"), LINEAGE_ABI, provider);
|
|
6107
|
+
const chain = [];
|
|
6108
|
+
let current = normalise(subdao, "subdao");
|
|
6109
|
+
const MAX_DEPTH = 100;
|
|
6110
|
+
let iterations = 0;
|
|
6111
|
+
while (current && iterations < MAX_DEPTH) {
|
|
6112
|
+
chain.unshift(getAddress(current).toLowerCase());
|
|
6113
|
+
const info = await contract.libraryByDAO(current);
|
|
6114
|
+
const parent = info.forkedFromDAO;
|
|
6115
|
+
if (!parent || parent === ZERO_ADDRESS) {
|
|
6116
|
+
break;
|
|
6117
|
+
}
|
|
6118
|
+
current = parent;
|
|
6119
|
+
iterations++;
|
|
6120
|
+
}
|
|
6121
|
+
return {
|
|
6122
|
+
chain,
|
|
6123
|
+
depth: chain.length - 1,
|
|
6124
|
+
root: chain[0]
|
|
6125
|
+
};
|
|
6126
|
+
} catch (err) {
|
|
6127
|
+
throw new SageSDKError(CODES.CONTRACT_ERROR, "Failed to fetch lineage chain", { cause: err });
|
|
6128
|
+
}
|
|
6129
|
+
}
|
|
6130
|
+
async function isFork({ provider, registry, subdao }) {
|
|
6131
|
+
const parent = await getParentLibrary({ provider, registry, subdao });
|
|
6132
|
+
return parent !== null;
|
|
6133
|
+
}
|
|
6134
|
+
async function getLibraryForkFee({ provider, registry, subdao }) {
|
|
6135
|
+
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
|
|
6136
|
+
if (!registry) throw new SageSDKError(CODES.INVALID_ARGS, "registry required");
|
|
6137
|
+
if (!subdao) throw new SageSDKError(CODES.INVALID_ARGS, "subdao required");
|
|
6138
|
+
try {
|
|
6139
|
+
const contract = new Contract(normalise(registry, "registry"), LINEAGE_ABI, provider);
|
|
6140
|
+
const fee = await contract.getLibraryForkFee(normalise(subdao, "subdao"));
|
|
6141
|
+
return BigInt(fee.toString());
|
|
6142
|
+
} catch (err) {
|
|
6143
|
+
throw new SageSDKError(CODES.CONTRACT_ERROR, "Failed to fetch library fork fee", { cause: err });
|
|
6144
|
+
}
|
|
6145
|
+
}
|
|
6146
|
+
async function getLibraryInfo({ provider, registry, subdao }) {
|
|
6147
|
+
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
|
|
6148
|
+
if (!registry) throw new SageSDKError(CODES.INVALID_ARGS, "registry required");
|
|
6149
|
+
if (!subdao) throw new SageSDKError(CODES.INVALID_ARGS, "subdao required");
|
|
6150
|
+
try {
|
|
6151
|
+
const contract = new Contract(normalise(registry, "registry"), LINEAGE_ABI, provider);
|
|
6152
|
+
const info = await contract.libraryByDAO(normalise(subdao, "subdao"));
|
|
6153
|
+
const parent = info.forkedFromDAO;
|
|
6154
|
+
return {
|
|
6155
|
+
parentDAO: !parent || parent === ZERO_ADDRESS ? null : getAddress(parent).toLowerCase(),
|
|
6156
|
+
forkFee: BigInt(info.sxxxForkFee.toString()),
|
|
6157
|
+
manifestCID: info.manifestCID,
|
|
6158
|
+
version: info.version
|
|
6159
|
+
};
|
|
6160
|
+
} catch (err) {
|
|
6161
|
+
throw new SageSDKError(CODES.CONTRACT_ERROR, "Failed to fetch library info", { cause: err });
|
|
6162
|
+
}
|
|
6163
|
+
}
|
|
6164
|
+
module2.exports = {
|
|
6165
|
+
getParentLibrary,
|
|
6166
|
+
getLineageChain,
|
|
6167
|
+
isFork,
|
|
6168
|
+
getLibraryForkFee,
|
|
6169
|
+
getLibraryInfo
|
|
6170
|
+
};
|
|
6171
|
+
}
|
|
6172
|
+
});
|
|
6173
|
+
|
|
4596
6174
|
// src/prompt/execute.js
|
|
4597
6175
|
var require_execute = __commonJS({
|
|
4598
6176
|
"src/prompt/execute.js"(exports2, module2) {
|
|
@@ -5265,7 +6843,6 @@ var require_ipns = __commonJS({
|
|
|
5265
6843
|
headers["X-Wallet-Address"] = auth.address;
|
|
5266
6844
|
headers["X-Wallet-Signature"] = auth.signature;
|
|
5267
6845
|
headers["X-Wallet-Nonce"] = auth.nonce;
|
|
5268
|
-
headers["X-Wallet-Message"] = auth.message;
|
|
5269
6846
|
}
|
|
5270
6847
|
return { headers, auth };
|
|
5271
6848
|
}
|
|
@@ -5287,8 +6864,7 @@ var require_ipns = __commonJS({
|
|
|
5287
6864
|
...extraHeaders,
|
|
5288
6865
|
"X-Wallet-Address": auth.address,
|
|
5289
6866
|
"X-Wallet-Signature": auth.signature,
|
|
5290
|
-
"X-Wallet-Nonce": auth.nonce
|
|
5291
|
-
"X-Wallet-Message": auth.message
|
|
6867
|
+
"X-Wallet-Nonce": auth.nonce
|
|
5292
6868
|
};
|
|
5293
6869
|
return { headers, auth };
|
|
5294
6870
|
}
|
|
@@ -5925,8 +7501,34 @@ var require_time = __commonJS({
|
|
|
5925
7501
|
var require_treasury = __commonJS({
|
|
5926
7502
|
"src/treasury/index.js"(exports2, module2) {
|
|
5927
7503
|
var { Contract, Interface, getAddress } = __require("ethers");
|
|
5928
|
-
var ABI = require_abi();
|
|
5929
7504
|
var { SageSDKError, CODES } = require_errors();
|
|
7505
|
+
var SAGE_TREASURY_ABI = [
|
|
7506
|
+
// Aggregated views
|
|
7507
|
+
"function totalReserves() view returns (uint256)",
|
|
7508
|
+
"function totalPOL() view returns (uint256)",
|
|
7509
|
+
"function totalDebt() view returns (uint256)",
|
|
7510
|
+
// Canonical liquidity config
|
|
7511
|
+
"function canonicalPool() view returns (address)",
|
|
7512
|
+
"function routerOrVault() view returns (address)",
|
|
7513
|
+
// Withdrawal rate limits
|
|
7514
|
+
"function maxWithdrawalRate() view returns (uint256)",
|
|
7515
|
+
"function emergencyWithdrawalLimit() view returns (uint256)",
|
|
7516
|
+
// Reserve tokens
|
|
7517
|
+
"function getReserveTokens() view returns (address[])",
|
|
7518
|
+
"function getReserve(address token) view returns (tuple(uint256 amount, uint256 value, bool isLP, bool isActive))",
|
|
7519
|
+
// Withdrawal queue
|
|
7520
|
+
"function nextWithdrawalId() view returns (uint256)",
|
|
7521
|
+
"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))",
|
|
7522
|
+
"function withdraw(address token, uint256 amount, address recipient)",
|
|
7523
|
+
"function confirmWithdrawal(uint256 id)",
|
|
7524
|
+
"function cancelWithdrawal(uint256 id)",
|
|
7525
|
+
// Manual price overrides
|
|
7526
|
+
"function manualPrices(address token) view returns (tuple(uint256 price, uint256 expiresAt, bool active))",
|
|
7527
|
+
"function setPriceOverride(address token, uint256 price, uint256 ttlSeconds)",
|
|
7528
|
+
"function clearPriceOverride(address token)",
|
|
7529
|
+
// Events
|
|
7530
|
+
"event WithdrawalScheduled(uint256 indexed id, address indexed token, address indexed recipient, uint256 amount)"
|
|
7531
|
+
];
|
|
5930
7532
|
var LiquidityEvents = new Interface([
|
|
5931
7533
|
"event CanonicalLiquidityUpdated(address indexed pool, address indexed routerOrVault)",
|
|
5932
7534
|
"event LiquidityAddPlanned(address indexed subdao, address indexed pool, address sxxxToken, address stableToken, uint256 sxxxAmount, uint256 stableAmount, address lpRecipient)",
|
|
@@ -5971,7 +7573,7 @@ var require_treasury = __commonJS({
|
|
|
5971
7573
|
async function getTreasuryInfo({ provider, treasury }) {
|
|
5972
7574
|
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
|
|
5973
7575
|
const addr = normalise(treasury, "treasury");
|
|
5974
|
-
const contract = new Contract(addr,
|
|
7576
|
+
const contract = new Contract(addr, SAGE_TREASURY_ABI, provider);
|
|
5975
7577
|
const [totalReserves, totalPOL, totalDebt, canonicalPool, routerOrVault, maxWithdrawalRate, emergencyWithdrawalLimit] = await Promise.all([
|
|
5976
7578
|
contract.totalReserves().catch(() => 0n),
|
|
5977
7579
|
contract.totalPOL().catch(() => 0n),
|
|
@@ -5995,7 +7597,7 @@ var require_treasury = __commonJS({
|
|
|
5995
7597
|
async function getPendingWithdrawals({ provider, treasury, ids, limit = 50 }) {
|
|
5996
7598
|
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
|
|
5997
7599
|
const addr = normalise(treasury, "treasury");
|
|
5998
|
-
const contract = new Contract(addr,
|
|
7600
|
+
const contract = new Contract(addr, SAGE_TREASURY_ABI, provider);
|
|
5999
7601
|
let idList = ids;
|
|
6000
7602
|
if (!Array.isArray(idList)) {
|
|
6001
7603
|
const nextId = await contract.nextWithdrawalId().catch(() => 0n);
|
|
@@ -6027,14 +7629,14 @@ var require_treasury = __commonJS({
|
|
|
6027
7629
|
async function getReserveTokens({ provider, treasury }) {
|
|
6028
7630
|
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
|
|
6029
7631
|
const addr = normalise(treasury, "treasury");
|
|
6030
|
-
const contract = new Contract(addr,
|
|
7632
|
+
const contract = new Contract(addr, SAGE_TREASURY_ABI, provider);
|
|
6031
7633
|
const tokens = await contract.getReserveTokens().catch(() => []);
|
|
6032
7634
|
return tokens.map((token) => getAddress(token));
|
|
6033
7635
|
}
|
|
6034
7636
|
async function getReserves({ provider, treasury, tokens, fetchMetadata = true }) {
|
|
6035
7637
|
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
|
|
6036
7638
|
const addr = normalise(treasury, "treasury");
|
|
6037
|
-
const contract = new Contract(addr,
|
|
7639
|
+
const contract = new Contract(addr, SAGE_TREASURY_ABI, provider);
|
|
6038
7640
|
const tokenList = Array.isArray(tokens) && tokens.length ? tokens.map((token) => getAddress(token)) : await contract.getReserveTokens().catch(() => []);
|
|
6039
7641
|
const reserves = [];
|
|
6040
7642
|
for (const token of tokenList) {
|
|
@@ -6064,7 +7666,7 @@ var require_treasury = __commonJS({
|
|
|
6064
7666
|
async function getManualPriceOverrides({ provider, treasury, tokens }) {
|
|
6065
7667
|
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
|
|
6066
7668
|
const addr = normalise(treasury, "treasury");
|
|
6067
|
-
const contract = new Contract(addr,
|
|
7669
|
+
const contract = new Contract(addr, SAGE_TREASURY_ABI, provider);
|
|
6068
7670
|
const tokenList = Array.isArray(tokens) && tokens.length ? tokens.map((token) => getAddress(token)) : await contract.getReserveTokens().catch(() => []);
|
|
6069
7671
|
const overrides = [];
|
|
6070
7672
|
for (const token of tokenList) {
|
|
@@ -6169,7 +7771,7 @@ var require_treasury = __commonJS({
|
|
|
6169
7771
|
async function getLPContribution({ provider, treasury, subdao, token }) {
|
|
6170
7772
|
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
|
|
6171
7773
|
const addr = normalise(treasury, "treasury");
|
|
6172
|
-
const c = new Contract(addr,
|
|
7774
|
+
const c = new Contract(addr, SAGE_TREASURY_ABI, provider);
|
|
6173
7775
|
const amount = await c.lpContributions(normalise(subdao, "subdao"), normalise(token, "token")).catch(() => 0n);
|
|
6174
7776
|
return amount;
|
|
6175
7777
|
}
|
|
@@ -6211,7 +7813,7 @@ var require_treasury = __commonJS({
|
|
|
6211
7813
|
function createWriteContract({ signer, treasury }) {
|
|
6212
7814
|
if (!signer) throw new SageSDKError(CODES.INVALID_ARGS, "signer required");
|
|
6213
7815
|
const addr = normalise(treasury, "treasury");
|
|
6214
|
-
return new Contract(addr,
|
|
7816
|
+
return new Contract(addr, SAGE_TREASURY_ABI, signer);
|
|
6215
7817
|
}
|
|
6216
7818
|
async function waitForReceipt({ signer, tx, waitMs }) {
|
|
6217
7819
|
const provider = signer.provider;
|
|
@@ -6515,6 +8117,350 @@ var require_bounty = __commonJS({
|
|
|
6515
8117
|
}
|
|
6516
8118
|
});
|
|
6517
8119
|
|
|
8120
|
+
// src/votingMultiplier/index.js
|
|
8121
|
+
var require_votingMultiplier = __commonJS({
|
|
8122
|
+
"src/votingMultiplier/index.js"(exports2, module2) {
|
|
8123
|
+
var { Contract, Interface, getAddress } = __require("ethers");
|
|
8124
|
+
var ABI = require_abi();
|
|
8125
|
+
var { SageSDKError, CODES } = require_errors();
|
|
8126
|
+
function normaliseAddress(address, label) {
|
|
8127
|
+
if (!address) throw new SageSDKError(CODES.INVALID_ARGS, `${label} required`);
|
|
8128
|
+
try {
|
|
8129
|
+
return getAddress(address);
|
|
8130
|
+
} catch (err) {
|
|
8131
|
+
throw new SageSDKError(CODES.INVALID_ARGS, `invalid ${label}`, { cause: err });
|
|
8132
|
+
}
|
|
8133
|
+
}
|
|
8134
|
+
function toBigInt(value, label) {
|
|
8135
|
+
if (value === void 0 || value === null) {
|
|
8136
|
+
throw new SageSDKError(CODES.INVALID_ARGS, `${label} required`);
|
|
8137
|
+
}
|
|
8138
|
+
try {
|
|
8139
|
+
return BigInt(value.toString());
|
|
8140
|
+
} catch (err) {
|
|
8141
|
+
throw new SageSDKError(CODES.INVALID_ARGS, `invalid ${label}`, { cause: err });
|
|
8142
|
+
}
|
|
8143
|
+
}
|
|
8144
|
+
function getNftContract(provider, nft) {
|
|
8145
|
+
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
|
|
8146
|
+
const addr = normaliseAddress(nft, "nft");
|
|
8147
|
+
return new Contract(addr, ABI.VotingMultiplierNFT, provider);
|
|
8148
|
+
}
|
|
8149
|
+
function getWrapperContract(provider, wrapper) {
|
|
8150
|
+
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
|
|
8151
|
+
const addr = normaliseAddress(wrapper, "wrapper");
|
|
8152
|
+
return new Contract(addr, ABI.MultipliedVotes, provider);
|
|
8153
|
+
}
|
|
8154
|
+
async function getTier({ provider, nft, tierId }) {
|
|
8155
|
+
const c = getNftContract(provider, nft);
|
|
8156
|
+
const id2 = toBigInt(tierId, "tierId");
|
|
8157
|
+
let tier;
|
|
8158
|
+
if (typeof c.getTier === "function") {
|
|
8159
|
+
tier = await c.getTier(id2);
|
|
8160
|
+
} else {
|
|
8161
|
+
tier = await c.tiers(id2);
|
|
8162
|
+
}
|
|
8163
|
+
const name = String(tier.name ?? tier[0]);
|
|
8164
|
+
const multiplier = BigInt((tier.multiplier ?? tier[1]).toString());
|
|
8165
|
+
const maxSupply = BigInt((tier.maxSupply ?? tier[2]).toString());
|
|
8166
|
+
const minted = BigInt((tier.minted ?? tier[3]).toString());
|
|
8167
|
+
const price = BigInt((tier.price ?? tier[4]).toString());
|
|
8168
|
+
const dao = getAddress(tier.dao ?? tier[5]);
|
|
8169
|
+
return { name, multiplier, maxSupply, minted, price, dao };
|
|
8170
|
+
}
|
|
8171
|
+
async function getTierCount({ provider, nft }) {
|
|
8172
|
+
const c = getNftContract(provider, nft);
|
|
8173
|
+
const count = await c.tierCount();
|
|
8174
|
+
return BigInt(count.toString());
|
|
8175
|
+
}
|
|
8176
|
+
function buildCreateTierTx({ nft, dao, name, multiplier, maxSupply, price }) {
|
|
8177
|
+
const addr = normaliseAddress(nft, "nft");
|
|
8178
|
+
const iface = new Interface(ABI.VotingMultiplierNFT);
|
|
8179
|
+
const data = iface.encodeFunctionData("createTier", [
|
|
8180
|
+
normaliseAddress(dao, "dao"),
|
|
8181
|
+
String(name ?? ""),
|
|
8182
|
+
toBigInt(multiplier, "multiplier"),
|
|
8183
|
+
toBigInt(maxSupply, "maxSupply"),
|
|
8184
|
+
toBigInt(price, "price")
|
|
8185
|
+
]);
|
|
8186
|
+
return { to: addr, data, value: 0n };
|
|
8187
|
+
}
|
|
8188
|
+
function buildMintTx({ nft, to, tierId, uri }) {
|
|
8189
|
+
const addr = normaliseAddress(nft, "nft");
|
|
8190
|
+
const iface = new Interface(ABI.VotingMultiplierNFT);
|
|
8191
|
+
const data = iface.encodeFunctionData("mint", [
|
|
8192
|
+
normaliseAddress(to, "to"),
|
|
8193
|
+
toBigInt(tierId, "tierId"),
|
|
8194
|
+
String(uri ?? "")
|
|
8195
|
+
]);
|
|
8196
|
+
return { to: addr, data, value: 0n };
|
|
8197
|
+
}
|
|
8198
|
+
function buildPublicMintTx({ nft, tierId, uri, value }) {
|
|
8199
|
+
const addr = normaliseAddress(nft, "nft");
|
|
8200
|
+
const iface = new Interface(ABI.VotingMultiplierNFT);
|
|
8201
|
+
const data = iface.encodeFunctionData("publicMint", [
|
|
8202
|
+
toBigInt(tierId, "tierId"),
|
|
8203
|
+
String(uri ?? "")
|
|
8204
|
+
]);
|
|
8205
|
+
return { to: addr, data, value: toBigInt(value ?? 0n, "value") };
|
|
8206
|
+
}
|
|
8207
|
+
async function getMultiplier({ provider, nft, account, dao }) {
|
|
8208
|
+
const c = getNftContract(provider, nft);
|
|
8209
|
+
const res = await c.getMultiplier(normaliseAddress(account, "account"), normaliseAddress(dao, "dao"));
|
|
8210
|
+
return BigInt(res.toString());
|
|
8211
|
+
}
|
|
8212
|
+
async function getPastMultiplier({ provider, nft, account, dao, timepoint }) {
|
|
8213
|
+
const c = getNftContract(provider, nft);
|
|
8214
|
+
const res = await c.getPastMultiplier(
|
|
8215
|
+
normaliseAddress(account, "account"),
|
|
8216
|
+
normaliseAddress(dao, "dao"),
|
|
8217
|
+
toBigInt(timepoint, "timepoint")
|
|
8218
|
+
);
|
|
8219
|
+
return BigInt(res.toString());
|
|
8220
|
+
}
|
|
8221
|
+
async function getTokenMultiplier({ provider, nft, tokenId }) {
|
|
8222
|
+
const c = getNftContract(provider, nft);
|
|
8223
|
+
const res = await c.getTokenMultiplier(toBigInt(tokenId, "tokenId"));
|
|
8224
|
+
return BigInt(res.toString());
|
|
8225
|
+
}
|
|
8226
|
+
async function getTokenDAO({ provider, nft, tokenId }) {
|
|
8227
|
+
const c = getNftContract(provider, nft);
|
|
8228
|
+
const res = await c.getTokenDAO(toBigInt(tokenId, "tokenId"));
|
|
8229
|
+
return getAddress(res);
|
|
8230
|
+
}
|
|
8231
|
+
async function getTokenInfo({ provider, nft, tokenId }) {
|
|
8232
|
+
const c = getNftContract(provider, nft);
|
|
8233
|
+
const id2 = toBigInt(tokenId, "tokenId");
|
|
8234
|
+
const info = await c.getTokenInfo(id2);
|
|
8235
|
+
const owner = getAddress(info.owner ?? info[0]);
|
|
8236
|
+
const tierId = BigInt((info.tierId ?? info[1]).toString());
|
|
8237
|
+
const multiplier = BigInt((info.multiplier ?? info[2]).toString());
|
|
8238
|
+
const uri = String(info.uri ?? info[3]);
|
|
8239
|
+
return { owner, tierId, multiplier, uri };
|
|
8240
|
+
}
|
|
8241
|
+
async function getVotes({ provider, wrapper, account }) {
|
|
8242
|
+
const c = getWrapperContract(provider, wrapper);
|
|
8243
|
+
const res = await c.getVotes(normaliseAddress(account, "account"));
|
|
8244
|
+
return BigInt(res.toString());
|
|
8245
|
+
}
|
|
8246
|
+
async function getPastVotes({ provider, wrapper, account, timepoint }) {
|
|
8247
|
+
const c = getWrapperContract(provider, wrapper);
|
|
8248
|
+
const res = await c.getPastVotes(
|
|
8249
|
+
normaliseAddress(account, "account"),
|
|
8250
|
+
toBigInt(timepoint, "timepoint")
|
|
8251
|
+
);
|
|
8252
|
+
return BigInt(res.toString());
|
|
8253
|
+
}
|
|
8254
|
+
async function getVotingBreakdown({ provider, wrapper, account }) {
|
|
8255
|
+
const c = getWrapperContract(provider, wrapper);
|
|
8256
|
+
const [baseVotes, multiplier, effectiveVotes] = await c.getVotingBreakdown(normaliseAddress(account, "account"));
|
|
8257
|
+
return {
|
|
8258
|
+
baseVotes: BigInt(baseVotes.toString()),
|
|
8259
|
+
multiplier: BigInt(multiplier.toString()),
|
|
8260
|
+
effectiveVotes: BigInt(effectiveVotes.toString())
|
|
8261
|
+
};
|
|
8262
|
+
}
|
|
8263
|
+
async function getPastVotingBreakdown({ provider, wrapper, account, timepoint }) {
|
|
8264
|
+
const c = getWrapperContract(provider, wrapper);
|
|
8265
|
+
const [baseVotes, multiplier, effectiveVotes] = await c.getPastVotingBreakdown(
|
|
8266
|
+
normaliseAddress(account, "account"),
|
|
8267
|
+
toBigInt(timepoint, "timepoint")
|
|
8268
|
+
);
|
|
8269
|
+
return {
|
|
8270
|
+
baseVotes: BigInt(baseVotes.toString()),
|
|
8271
|
+
multiplier: BigInt(multiplier.toString()),
|
|
8272
|
+
effectiveVotes: BigInt(effectiveVotes.toString())
|
|
8273
|
+
};
|
|
8274
|
+
}
|
|
8275
|
+
async function hasMultiplierBonus({ provider, wrapper, account }) {
|
|
8276
|
+
const c = getWrapperContract(provider, wrapper);
|
|
8277
|
+
const res = await c.hasMultiplierBonus(normaliseAddress(account, "account"));
|
|
8278
|
+
return !!res;
|
|
8279
|
+
}
|
|
8280
|
+
module2.exports = {
|
|
8281
|
+
// Tier management
|
|
8282
|
+
getTier,
|
|
8283
|
+
getTierCount,
|
|
8284
|
+
buildCreateTierTx,
|
|
8285
|
+
// Minting
|
|
8286
|
+
buildMintTx,
|
|
8287
|
+
buildPublicMintTx,
|
|
8288
|
+
// Multiplier queries
|
|
8289
|
+
getMultiplier,
|
|
8290
|
+
getPastMultiplier,
|
|
8291
|
+
getTokenMultiplier,
|
|
8292
|
+
getTokenDAO,
|
|
8293
|
+
getTokenInfo,
|
|
8294
|
+
// Wrapper queries
|
|
8295
|
+
getVotes,
|
|
8296
|
+
getPastVotes,
|
|
8297
|
+
getVotingBreakdown,
|
|
8298
|
+
getPastVotingBreakdown,
|
|
8299
|
+
hasMultiplierBonus
|
|
8300
|
+
};
|
|
8301
|
+
}
|
|
8302
|
+
});
|
|
8303
|
+
|
|
8304
|
+
// src/auction/index.js
|
|
8305
|
+
var require_auction = __commonJS({
|
|
8306
|
+
"src/auction/index.js"(exports2, module2) {
|
|
8307
|
+
var { Contract, Interface, getAddress } = __require("ethers");
|
|
8308
|
+
var ABI = require_abi();
|
|
8309
|
+
var { SageSDKError, CODES } = require_errors();
|
|
8310
|
+
function normaliseAddress(address, label) {
|
|
8311
|
+
if (!address) throw new SageSDKError(CODES.INVALID_ARGS, `${label} required`);
|
|
8312
|
+
try {
|
|
8313
|
+
return getAddress(address);
|
|
8314
|
+
} catch (err) {
|
|
8315
|
+
throw new SageSDKError(CODES.INVALID_ARGS, `invalid ${label}`, { cause: err });
|
|
8316
|
+
}
|
|
8317
|
+
}
|
|
8318
|
+
function toBigInt(value, label) {
|
|
8319
|
+
if (value === void 0 || value === null) {
|
|
8320
|
+
throw new SageSDKError(CODES.INVALID_ARGS, `${label} required`);
|
|
8321
|
+
}
|
|
8322
|
+
try {
|
|
8323
|
+
return BigInt(value.toString());
|
|
8324
|
+
} catch (err) {
|
|
8325
|
+
throw new SageSDKError(CODES.INVALID_ARGS, `invalid ${label}`, { cause: err });
|
|
8326
|
+
}
|
|
8327
|
+
}
|
|
8328
|
+
function getAuctionContract(provider, auctionHouse) {
|
|
8329
|
+
if (!provider) throw new SageSDKError(CODES.INVALID_ARGS, "provider required");
|
|
8330
|
+
const addr = normaliseAddress(auctionHouse, "auctionHouse");
|
|
8331
|
+
return new Contract(addr, ABI.SageAuctionHouse, provider);
|
|
8332
|
+
}
|
|
8333
|
+
async function getAuction({ provider, auctionHouse }) {
|
|
8334
|
+
const c = getAuctionContract(provider, auctionHouse);
|
|
8335
|
+
const res = await c.auction();
|
|
8336
|
+
const nftId = BigInt(res.nftId.toString());
|
|
8337
|
+
const amount = BigInt(res.amount.toString());
|
|
8338
|
+
const startTime = BigInt(res.startTime.toString());
|
|
8339
|
+
const endTime = BigInt(res.endTime.toString());
|
|
8340
|
+
const bidder = getAddress(res.bidder);
|
|
8341
|
+
const settled = !!res.settled;
|
|
8342
|
+
return { nftId, amount, startTime, endTime, bidder, settled };
|
|
8343
|
+
}
|
|
8344
|
+
async function getConfig({ provider, auctionHouse }) {
|
|
8345
|
+
const c = getAuctionContract(provider, auctionHouse);
|
|
8346
|
+
const [nft, treasury, weth, timeBuffer, reservePrice, minBidIncrementPercentage, duration, mintTierId, defaultTokenURI, paused, owner] = await Promise.all([
|
|
8347
|
+
c.nft(),
|
|
8348
|
+
c.treasury(),
|
|
8349
|
+
c.weth(),
|
|
8350
|
+
c.timeBuffer(),
|
|
8351
|
+
c.reservePrice(),
|
|
8352
|
+
c.minBidIncrementPercentage(),
|
|
8353
|
+
c.duration(),
|
|
8354
|
+
c.mintTierId(),
|
|
8355
|
+
c.defaultTokenURI(),
|
|
8356
|
+
c.paused(),
|
|
8357
|
+
c.owner()
|
|
8358
|
+
]);
|
|
8359
|
+
return {
|
|
8360
|
+
nft: getAddress(nft),
|
|
8361
|
+
treasury: getAddress(treasury),
|
|
8362
|
+
weth: getAddress(weth),
|
|
8363
|
+
timeBuffer: BigInt(timeBuffer.toString()),
|
|
8364
|
+
reservePrice: BigInt(reservePrice.toString()),
|
|
8365
|
+
minBidIncrementPercentage: BigInt(minBidIncrementPercentage.toString()),
|
|
8366
|
+
duration: BigInt(duration.toString()),
|
|
8367
|
+
mintTierId: BigInt(mintTierId.toString()),
|
|
8368
|
+
defaultTokenURI: String(defaultTokenURI),
|
|
8369
|
+
paused: !!paused,
|
|
8370
|
+
owner: getAddress(owner)
|
|
8371
|
+
};
|
|
8372
|
+
}
|
|
8373
|
+
function buildCreateBidTx({ auctionHouse, nftId, value }) {
|
|
8374
|
+
const addr = normaliseAddress(auctionHouse, "auctionHouse");
|
|
8375
|
+
const iface = new Interface(ABI.SageAuctionHouse);
|
|
8376
|
+
const data = iface.encodeFunctionData("createBid", [toBigInt(nftId, "nftId")]);
|
|
8377
|
+
return { to: addr, data, value: toBigInt(value, "value") };
|
|
8378
|
+
}
|
|
8379
|
+
function buildSettleAndCreateTx({ auctionHouse }) {
|
|
8380
|
+
const addr = normaliseAddress(auctionHouse, "auctionHouse");
|
|
8381
|
+
const iface = new Interface(ABI.SageAuctionHouse);
|
|
8382
|
+
const data = iface.encodeFunctionData("settleCurrentAndCreateNewAuction", []);
|
|
8383
|
+
return { to: addr, data, value: 0n };
|
|
8384
|
+
}
|
|
8385
|
+
function buildSettleTx({ auctionHouse }) {
|
|
8386
|
+
const addr = normaliseAddress(auctionHouse, "auctionHouse");
|
|
8387
|
+
const iface = new Interface(ABI.SageAuctionHouse);
|
|
8388
|
+
const data = iface.encodeFunctionData("settleAuction", []);
|
|
8389
|
+
return { to: addr, data, value: 0n };
|
|
8390
|
+
}
|
|
8391
|
+
function buildCreateAuctionTx({ auctionHouse }) {
|
|
8392
|
+
const addr = normaliseAddress(auctionHouse, "auctionHouse");
|
|
8393
|
+
const iface = new Interface(ABI.SageAuctionHouse);
|
|
8394
|
+
const data = iface.encodeFunctionData("createAuction", []);
|
|
8395
|
+
return { to: addr, data, value: 0n };
|
|
8396
|
+
}
|
|
8397
|
+
function buildPauseTx({ auctionHouse }) {
|
|
8398
|
+
const addr = normaliseAddress(auctionHouse, "auctionHouse");
|
|
8399
|
+
const iface = new Interface(ABI.SageAuctionHouse);
|
|
8400
|
+
const data = iface.encodeFunctionData("pause", []);
|
|
8401
|
+
return { to: addr, data, value: 0n };
|
|
8402
|
+
}
|
|
8403
|
+
function buildUnpauseTx({ auctionHouse }) {
|
|
8404
|
+
const addr = normaliseAddress(auctionHouse, "auctionHouse");
|
|
8405
|
+
const iface = new Interface(ABI.SageAuctionHouse);
|
|
8406
|
+
const data = iface.encodeFunctionData("unpause", []);
|
|
8407
|
+
return { to: addr, data, value: 0n };
|
|
8408
|
+
}
|
|
8409
|
+
function buildSetTimeBufferTx({ auctionHouse, timeBuffer }) {
|
|
8410
|
+
const addr = normaliseAddress(auctionHouse, "auctionHouse");
|
|
8411
|
+
const iface = new Interface(ABI.SageAuctionHouse);
|
|
8412
|
+
const data = iface.encodeFunctionData("setTimeBuffer", [toBigInt(timeBuffer, "timeBuffer")]);
|
|
8413
|
+
return { to: addr, data, value: 0n };
|
|
8414
|
+
}
|
|
8415
|
+
function buildSetReservePriceTx({ auctionHouse, reservePrice }) {
|
|
8416
|
+
const addr = normaliseAddress(auctionHouse, "auctionHouse");
|
|
8417
|
+
const iface = new Interface(ABI.SageAuctionHouse);
|
|
8418
|
+
const data = iface.encodeFunctionData("setReservePrice", [toBigInt(reservePrice, "reservePrice")]);
|
|
8419
|
+
return { to: addr, data, value: 0n };
|
|
8420
|
+
}
|
|
8421
|
+
function buildSetMinBidIncrementTx({ auctionHouse, percentage }) {
|
|
8422
|
+
const addr = normaliseAddress(auctionHouse, "auctionHouse");
|
|
8423
|
+
const iface = new Interface(ABI.SageAuctionHouse);
|
|
8424
|
+
const data = iface.encodeFunctionData("setMinBidIncrementPercentage", [toBigInt(percentage, "percentage")]);
|
|
8425
|
+
return { to: addr, data, value: 0n };
|
|
8426
|
+
}
|
|
8427
|
+
function buildSetDurationTx({ auctionHouse, duration }) {
|
|
8428
|
+
const addr = normaliseAddress(auctionHouse, "auctionHouse");
|
|
8429
|
+
const iface = new Interface(ABI.SageAuctionHouse);
|
|
8430
|
+
const data = iface.encodeFunctionData("setDuration", [toBigInt(duration, "duration")]);
|
|
8431
|
+
return { to: addr, data, value: 0n };
|
|
8432
|
+
}
|
|
8433
|
+
function buildSetMintTierIdTx({ auctionHouse, tierId }) {
|
|
8434
|
+
const addr = normaliseAddress(auctionHouse, "auctionHouse");
|
|
8435
|
+
const iface = new Interface(ABI.SageAuctionHouse);
|
|
8436
|
+
const data = iface.encodeFunctionData("setMintTierId", [toBigInt(tierId, "tierId")]);
|
|
8437
|
+
return { to: addr, data, value: 0n };
|
|
8438
|
+
}
|
|
8439
|
+
function buildSetDefaultTokenURITx({ auctionHouse, uri }) {
|
|
8440
|
+
const addr = normaliseAddress(auctionHouse, "auctionHouse");
|
|
8441
|
+
const iface = new Interface(ABI.SageAuctionHouse);
|
|
8442
|
+
const data = iface.encodeFunctionData("setDefaultTokenURI", [String(uri ?? "")]);
|
|
8443
|
+
return { to: addr, data, value: 0n };
|
|
8444
|
+
}
|
|
8445
|
+
module2.exports = {
|
|
8446
|
+
getAuction,
|
|
8447
|
+
getConfig,
|
|
8448
|
+
buildCreateBidTx,
|
|
8449
|
+
buildSettleAndCreateTx,
|
|
8450
|
+
buildSettleTx,
|
|
8451
|
+
buildCreateAuctionTx,
|
|
8452
|
+
buildPauseTx,
|
|
8453
|
+
buildUnpauseTx,
|
|
8454
|
+
buildSetTimeBufferTx,
|
|
8455
|
+
buildSetReservePriceTx,
|
|
8456
|
+
buildSetMinBidIncrementTx,
|
|
8457
|
+
buildSetDurationTx,
|
|
8458
|
+
buildSetMintTierIdTx,
|
|
8459
|
+
buildSetDefaultTokenURITx
|
|
8460
|
+
};
|
|
8461
|
+
}
|
|
8462
|
+
});
|
|
8463
|
+
|
|
6518
8464
|
// src/utils/provider.js
|
|
6519
8465
|
var require_provider = __commonJS({
|
|
6520
8466
|
"src/utils/provider.js"(exports2, module2) {
|
|
@@ -8516,6 +10462,60 @@ var require_doppler = __commonJS({
|
|
|
8516
10462
|
}
|
|
8517
10463
|
});
|
|
8518
10464
|
|
|
10465
|
+
// src/points.js
|
|
10466
|
+
var require_points = __commonJS({
|
|
10467
|
+
"src/points.js"(exports2, module2) {
|
|
10468
|
+
var axios = __require("axios");
|
|
10469
|
+
function resolveBaseUrl(baseUrl) {
|
|
10470
|
+
const fromEnv = process.env.SAGE_POINTS_BASE_URL;
|
|
10471
|
+
const base = baseUrl || fromEnv;
|
|
10472
|
+
if (!base) {
|
|
10473
|
+
throw new Error(
|
|
10474
|
+
"SAGE_POINTS_BASE_URL not set and no baseUrl provided. Provide the Sage web app base URL, e.g. https://app.sage.xyz"
|
|
10475
|
+
);
|
|
10476
|
+
}
|
|
10477
|
+
return base.replace(/\/+$/, "");
|
|
10478
|
+
}
|
|
10479
|
+
async function fetchSeasonSnapshot({ baseUrl, season = "season-1" } = {}) {
|
|
10480
|
+
const base = resolveBaseUrl(baseUrl);
|
|
10481
|
+
const url = `${base}/airdrop/${season}/points.json`;
|
|
10482
|
+
const resp = await axios.get(url, { timeout: 15e3 });
|
|
10483
|
+
if (!resp || !resp.data) {
|
|
10484
|
+
throw new Error(`No data returned from ${url}`);
|
|
10485
|
+
}
|
|
10486
|
+
return resp.data;
|
|
10487
|
+
}
|
|
10488
|
+
async function getSeasonPoints({ address, season = "season-1", baseUrl } = {}) {
|
|
10489
|
+
if (!address) throw new Error("address is required");
|
|
10490
|
+
const snapshot = await fetchSeasonSnapshot({ baseUrl, season });
|
|
10491
|
+
const totals = snapshot.totals || {};
|
|
10492
|
+
const key = address.toLowerCase();
|
|
10493
|
+
const entry = totals[key] || null;
|
|
10494
|
+
return {
|
|
10495
|
+
season: snapshot.season || season,
|
|
10496
|
+
chainId: snapshot.chainId,
|
|
10497
|
+
address: key,
|
|
10498
|
+
totalPoints: entry ? entry.points || 0 : 0,
|
|
10499
|
+
breakdown: entry ? entry.breakdown || {} : {}
|
|
10500
|
+
};
|
|
10501
|
+
}
|
|
10502
|
+
async function getSeasonLeaderboard({ limit = 100, season = "season-1", baseUrl } = {}) {
|
|
10503
|
+
const snapshot = await fetchSeasonSnapshot({ baseUrl, season });
|
|
10504
|
+
const totals = snapshot.totals || {};
|
|
10505
|
+
const entries = Object.entries(totals).map(([addr, v]) => ({
|
|
10506
|
+
address: addr,
|
|
10507
|
+
points: v.points || 0
|
|
10508
|
+
})).sort((a, b) => b.points - a.points);
|
|
10509
|
+
return entries.slice(0, limit);
|
|
10510
|
+
}
|
|
10511
|
+
module2.exports = {
|
|
10512
|
+
fetchSeasonSnapshot,
|
|
10513
|
+
getSeasonPoints,
|
|
10514
|
+
getSeasonLeaderboard
|
|
10515
|
+
};
|
|
10516
|
+
}
|
|
10517
|
+
});
|
|
10518
|
+
|
|
8519
10519
|
// src/services/utils/cache.js
|
|
8520
10520
|
var require_cache = __commonJS({
|
|
8521
10521
|
"src/services/utils/cache.js"(exports2, module2) {
|
|
@@ -9266,6 +11266,273 @@ var require_client2 = __commonJS({
|
|
|
9266
11266
|
}
|
|
9267
11267
|
});
|
|
9268
11268
|
|
|
11269
|
+
// src/clients/discovery-client.js
|
|
11270
|
+
var require_discovery_client = __commonJS({
|
|
11271
|
+
"src/clients/discovery-client.js"(exports2, module2) {
|
|
11272
|
+
var DiscoveryClient = class {
|
|
11273
|
+
/**
|
|
11274
|
+
* @param {string} baseUrl - Base URL of the discovery API
|
|
11275
|
+
* @param {object} [options] - Client options
|
|
11276
|
+
* @param {number} [options.timeout=10000] - Request timeout in milliseconds
|
|
11277
|
+
* @param {Record<string, string>} [options.headers] - Custom headers
|
|
11278
|
+
*/
|
|
11279
|
+
constructor(baseUrl, options = {}) {
|
|
11280
|
+
this.baseUrl = baseUrl.replace(/\/$/, "");
|
|
11281
|
+
this.timeout = options.timeout || 1e4;
|
|
11282
|
+
this.headers = options.headers || {};
|
|
11283
|
+
}
|
|
11284
|
+
/**
|
|
11285
|
+
* Search prompts with keyword matching and trend ranking
|
|
11286
|
+
* @param {string} query - Search query
|
|
11287
|
+
* @param {object} [options] - Search options
|
|
11288
|
+
* @param {string} [options.category] - Filter by category
|
|
11289
|
+
* @param {string[]} [options.tags] - Filter by tags
|
|
11290
|
+
* @param {string} [options.author] - Filter by author
|
|
11291
|
+
* @param {number} [options.limit] - Max results to return
|
|
11292
|
+
* @param {number} [options.offset] - Number of results to skip
|
|
11293
|
+
* @param {boolean} [options.useVector] - Use vector search
|
|
11294
|
+
* @returns {Promise<{results: Array, total: number}>}
|
|
11295
|
+
*/
|
|
11296
|
+
async search(query, options = {}) {
|
|
11297
|
+
const params = new URLSearchParams();
|
|
11298
|
+
if (query) params.set("q", query);
|
|
11299
|
+
if (options.category) params.set("category", options.category);
|
|
11300
|
+
if (options.author) params.set("author", options.author);
|
|
11301
|
+
if (options.tags) {
|
|
11302
|
+
options.tags.forEach((tag) => params.append("tags", tag));
|
|
11303
|
+
}
|
|
11304
|
+
if (options.limit !== void 0) params.set("limit", String(options.limit));
|
|
11305
|
+
if (options.offset !== void 0) params.set("offset", String(options.offset));
|
|
11306
|
+
if (options.useVector !== void 0) params.set("useVector", String(options.useVector));
|
|
11307
|
+
return this._get(`/discover/search?${params}`);
|
|
11308
|
+
}
|
|
11309
|
+
/**
|
|
11310
|
+
* Get trending prompts by time window
|
|
11311
|
+
* @param {object} [options] - Trending options
|
|
11312
|
+
* @param {'1h'|'24h'|'7d'|'30d'|'all'} [options.window] - Time window
|
|
11313
|
+
* @param {string} [options.category] - Filter by category
|
|
11314
|
+
* @param {number} [options.limit] - Max results to return
|
|
11315
|
+
* @param {number} [options.offset] - Number of results to skip
|
|
11316
|
+
* @returns {Promise<{results: Array}>}
|
|
11317
|
+
*/
|
|
11318
|
+
async trending(options = {}) {
|
|
11319
|
+
const params = new URLSearchParams();
|
|
11320
|
+
if (options.window) params.set("window", options.window);
|
|
11321
|
+
if (options.category) params.set("category", options.category);
|
|
11322
|
+
if (options.limit !== void 0) params.set("limit", String(options.limit));
|
|
11323
|
+
if (options.offset !== void 0) params.set("offset", String(options.offset));
|
|
11324
|
+
return this._get(`/discover/trending?${params}`);
|
|
11325
|
+
}
|
|
11326
|
+
/**
|
|
11327
|
+
* Get trending prompts (alias for /trends/top endpoint)
|
|
11328
|
+
* @param {object} [options] - Trending options
|
|
11329
|
+
* @param {'1h'|'24h'|'7d'|'30d'|'all'} [options.window] - Time window
|
|
11330
|
+
* @param {number} [options.limit] - Max results to return
|
|
11331
|
+
* @param {number} [options.offset] - Number of results to skip
|
|
11332
|
+
* @returns {Promise<{results: Array}>}
|
|
11333
|
+
*/
|
|
11334
|
+
async trendingTop(options = {}) {
|
|
11335
|
+
const params = new URLSearchParams();
|
|
11336
|
+
if (options.window) params.set("window", options.window);
|
|
11337
|
+
if (options.limit !== void 0) params.set("limit", String(options.limit));
|
|
11338
|
+
if (options.offset !== void 0) params.set("offset", String(options.offset));
|
|
11339
|
+
return this._get(`/trends/top?${params}`);
|
|
11340
|
+
}
|
|
11341
|
+
/**
|
|
11342
|
+
* Find prompts matching user preferences
|
|
11343
|
+
*
|
|
11344
|
+
* Note: This endpoint is not yet implemented in the backend.
|
|
11345
|
+
* This is a placeholder for future implementation.
|
|
11346
|
+
* @param {object} preferences - User preferences
|
|
11347
|
+
* @param {string[]} [preferences.recentPrompts] - Recent prompt CIDs
|
|
11348
|
+
* @param {string[]} [preferences.preferredTags] - Preferred tags
|
|
11349
|
+
* @param {string[]} [preferences.preferredCategories] - Preferred categories
|
|
11350
|
+
* @param {string[]} [preferences.excludeAuthors] - Authors to exclude
|
|
11351
|
+
* @param {number} [preferences.limit] - Max results
|
|
11352
|
+
* @param {boolean} [preferences.diversify] - Diversify results
|
|
11353
|
+
* @returns {Promise<{results: Array, total: number}>}
|
|
11354
|
+
*/
|
|
11355
|
+
async match(preferences) {
|
|
11356
|
+
return this._post("/discover/match", preferences);
|
|
11357
|
+
}
|
|
11358
|
+
/**
|
|
11359
|
+
* Find prompts similar to a given prompt
|
|
11360
|
+
* @param {string} cid - Prompt CID to find similar prompts for
|
|
11361
|
+
* @param {object} [options] - Similar options
|
|
11362
|
+
* @param {number} [options.limit] - Max results to return
|
|
11363
|
+
* @param {'vector'|'keyword'|'hybrid'} [options.method] - Similarity method
|
|
11364
|
+
* @returns {Promise<{similar: Array}>}
|
|
11365
|
+
*/
|
|
11366
|
+
async similar(cid, options = {}) {
|
|
11367
|
+
const params = new URLSearchParams();
|
|
11368
|
+
if (options.limit !== void 0) params.set("limit", String(options.limit));
|
|
11369
|
+
if (options.method) params.set("method", options.method);
|
|
11370
|
+
return this._get(`/discover/similar/${cid}?${params}`);
|
|
11371
|
+
}
|
|
11372
|
+
/**
|
|
11373
|
+
* Get popular tags with optional clustering
|
|
11374
|
+
* @param {object} [options] - Tags options
|
|
11375
|
+
* @param {number} [options.limit] - Max tags to return
|
|
11376
|
+
* @param {string} [options.category] - Filter by category
|
|
11377
|
+
* @param {boolean} [options.clusters] - Enable tag clustering
|
|
11378
|
+
* @returns {Promise<{tags: Array}>}
|
|
11379
|
+
*/
|
|
11380
|
+
async tags(options = {}) {
|
|
11381
|
+
const params = new URLSearchParams();
|
|
11382
|
+
if (options.limit !== void 0) params.set("limit", String(options.limit));
|
|
11383
|
+
if (options.category) params.set("category", options.category);
|
|
11384
|
+
if (options.clusters !== void 0) params.set("clusters", String(options.clusters));
|
|
11385
|
+
return this._get(`/discover/tags?${params}`);
|
|
11386
|
+
}
|
|
11387
|
+
/**
|
|
11388
|
+
* Get category statistics
|
|
11389
|
+
*
|
|
11390
|
+
* Note: This endpoint is not yet implemented in the backend.
|
|
11391
|
+
* This is a placeholder for future implementation.
|
|
11392
|
+
* @returns {Promise<{categories: Array}>}
|
|
11393
|
+
*/
|
|
11394
|
+
async categories() {
|
|
11395
|
+
return this._get("/discover/categories");
|
|
11396
|
+
}
|
|
11397
|
+
/**
|
|
11398
|
+
* Get prompts by tag
|
|
11399
|
+
* @param {string} tag - Tag to search for
|
|
11400
|
+
* @param {number} [limit] - Max results to return
|
|
11401
|
+
* @returns {Promise<{results: Array}>}
|
|
11402
|
+
*/
|
|
11403
|
+
async promptsByTag(tag, limit) {
|
|
11404
|
+
const params = new URLSearchParams();
|
|
11405
|
+
if (limit !== void 0) params.set("limit", String(limit));
|
|
11406
|
+
const encodedTag = encodeURIComponent(tag);
|
|
11407
|
+
return this._get(`/discover/by-tag/${encodedTag}?${params}`);
|
|
11408
|
+
}
|
|
11409
|
+
/**
|
|
11410
|
+
* Get index statistics
|
|
11411
|
+
* @returns {Promise<{totalPrompts: number, totalTags: number, avgTrendScore: number}>}
|
|
11412
|
+
*/
|
|
11413
|
+
async stats() {
|
|
11414
|
+
return this._get("/discover/stats");
|
|
11415
|
+
}
|
|
11416
|
+
/**
|
|
11417
|
+
* Get trend signals for a specific CID
|
|
11418
|
+
* @param {string} cid - Prompt CID
|
|
11419
|
+
* @returns {Promise<{usageCount: number, forkCount: number, purchaseCount: number, uniqueBuyers: number, governanceVotes: number, lastActivityAt: number}>}
|
|
11420
|
+
*/
|
|
11421
|
+
async trendSignals(cid) {
|
|
11422
|
+
return this._get(`/trends/signals/${cid}`);
|
|
11423
|
+
}
|
|
11424
|
+
/**
|
|
11425
|
+
* Get trend history for a specific CID
|
|
11426
|
+
* @param {string} cid - Prompt CID
|
|
11427
|
+
* @param {object} [options] - History options
|
|
11428
|
+
* @param {number} [options.limit] - Max history entries
|
|
11429
|
+
* @param {number} [options.since] - Timestamp to start from
|
|
11430
|
+
* @returns {Promise<{history: Array}>}
|
|
11431
|
+
*/
|
|
11432
|
+
async trendHistory(cid, options = {}) {
|
|
11433
|
+
const params = new URLSearchParams();
|
|
11434
|
+
if (options.limit !== void 0) params.set("limit", String(options.limit));
|
|
11435
|
+
if (options.since !== void 0) params.set("since", String(options.since));
|
|
11436
|
+
return this._get(`/trends/history/${cid}?${params}`);
|
|
11437
|
+
}
|
|
11438
|
+
/**
|
|
11439
|
+
* Get trend statistics
|
|
11440
|
+
* @returns {Promise<{totalTracked: number, avgScore: number, maxScore: number, recentlyActive: number}>}
|
|
11441
|
+
*/
|
|
11442
|
+
async trendStats() {
|
|
11443
|
+
return this._get("/trends/stats");
|
|
11444
|
+
}
|
|
11445
|
+
/**
|
|
11446
|
+
* Record a usage event for a prompt (requires authentication)
|
|
11447
|
+
* @param {string} cid - Prompt CID
|
|
11448
|
+
* @returns {Promise<{ok: boolean}>}
|
|
11449
|
+
*/
|
|
11450
|
+
async recordUsage(cid) {
|
|
11451
|
+
return this._post("/trends/usage", { cid });
|
|
11452
|
+
}
|
|
11453
|
+
// Private fetch helpers
|
|
11454
|
+
/**
|
|
11455
|
+
* Perform a GET request
|
|
11456
|
+
* @private
|
|
11457
|
+
* @param {string} path - API path
|
|
11458
|
+
* @returns {Promise<any>}
|
|
11459
|
+
*/
|
|
11460
|
+
async _get(path2) {
|
|
11461
|
+
const controller = new AbortController();
|
|
11462
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
11463
|
+
try {
|
|
11464
|
+
const response = await fetch(`${this.baseUrl}${path2}`, {
|
|
11465
|
+
method: "GET",
|
|
11466
|
+
headers: {
|
|
11467
|
+
"Accept": "application/json",
|
|
11468
|
+
...this.headers
|
|
11469
|
+
},
|
|
11470
|
+
signal: controller.signal
|
|
11471
|
+
});
|
|
11472
|
+
clearTimeout(timeoutId);
|
|
11473
|
+
if (!response.ok) {
|
|
11474
|
+
const errorBody = await response.text().catch(() => "Unknown error");
|
|
11475
|
+
throw new Error(`HTTP ${response.status}: ${errorBody}`);
|
|
11476
|
+
}
|
|
11477
|
+
return await response.json();
|
|
11478
|
+
} catch (error) {
|
|
11479
|
+
clearTimeout(timeoutId);
|
|
11480
|
+
if (error.name === "AbortError") {
|
|
11481
|
+
throw new Error(`Request timeout after ${this.timeout}ms`);
|
|
11482
|
+
}
|
|
11483
|
+
throw error;
|
|
11484
|
+
}
|
|
11485
|
+
}
|
|
11486
|
+
/**
|
|
11487
|
+
* Perform a POST request
|
|
11488
|
+
* @private
|
|
11489
|
+
* @param {string} path - API path
|
|
11490
|
+
* @param {any} body - Request body
|
|
11491
|
+
* @returns {Promise<any>}
|
|
11492
|
+
*/
|
|
11493
|
+
async _post(path2, body) {
|
|
11494
|
+
const controller = new AbortController();
|
|
11495
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
11496
|
+
try {
|
|
11497
|
+
const response = await fetch(`${this.baseUrl}${path2}`, {
|
|
11498
|
+
method: "POST",
|
|
11499
|
+
headers: {
|
|
11500
|
+
"Accept": "application/json",
|
|
11501
|
+
"Content-Type": "application/json",
|
|
11502
|
+
...this.headers
|
|
11503
|
+
},
|
|
11504
|
+
body: JSON.stringify(body),
|
|
11505
|
+
signal: controller.signal
|
|
11506
|
+
});
|
|
11507
|
+
clearTimeout(timeoutId);
|
|
11508
|
+
if (!response.ok) {
|
|
11509
|
+
const errorBody = await response.text().catch(() => "Unknown error");
|
|
11510
|
+
throw new Error(`HTTP ${response.status}: ${errorBody}`);
|
|
11511
|
+
}
|
|
11512
|
+
return await response.json();
|
|
11513
|
+
} catch (error) {
|
|
11514
|
+
clearTimeout(timeoutId);
|
|
11515
|
+
if (error.name === "AbortError") {
|
|
11516
|
+
throw new Error(`Request timeout after ${this.timeout}ms`);
|
|
11517
|
+
}
|
|
11518
|
+
throw error;
|
|
11519
|
+
}
|
|
11520
|
+
}
|
|
11521
|
+
};
|
|
11522
|
+
module2.exports = { DiscoveryClient };
|
|
11523
|
+
}
|
|
11524
|
+
});
|
|
11525
|
+
|
|
11526
|
+
// src/clients/index.js
|
|
11527
|
+
var require_clients = __commonJS({
|
|
11528
|
+
"src/clients/index.js"(exports2, module2) {
|
|
11529
|
+
var { DiscoveryClient } = require_discovery_client();
|
|
11530
|
+
module2.exports = {
|
|
11531
|
+
DiscoveryClient
|
|
11532
|
+
};
|
|
11533
|
+
}
|
|
11534
|
+
});
|
|
11535
|
+
|
|
9269
11536
|
// src/hooks/useSubDAOs.js
|
|
9270
11537
|
var require_useSubDAOs = __commonJS({
|
|
9271
11538
|
"src/hooks/useSubDAOs.js"(exports2, module2) {
|
|
@@ -9476,6 +11743,7 @@ var require_src = __commonJS({
|
|
|
9476
11743
|
var timelock = require_timelock();
|
|
9477
11744
|
var factory = require_factory();
|
|
9478
11745
|
var library = require_library();
|
|
11746
|
+
var lineage = require_lineage();
|
|
9479
11747
|
var prompt = require_prompt();
|
|
9480
11748
|
var { SageEchoExecutor } = require_execute();
|
|
9481
11749
|
var ipfs = require_ipfs();
|
|
@@ -9489,6 +11757,8 @@ var require_src = __commonJS({
|
|
|
9489
11757
|
var treasury = require_treasury();
|
|
9490
11758
|
var boost = require_boost();
|
|
9491
11759
|
var bounty = require_bounty();
|
|
11760
|
+
var votingMultiplier = require_votingMultiplier();
|
|
11761
|
+
var auction = require_auction();
|
|
9492
11762
|
var wallet = require_wallet();
|
|
9493
11763
|
wallet.session = require_session();
|
|
9494
11764
|
var walletCastManager = require_cast_manager();
|
|
@@ -9503,11 +11773,13 @@ var require_src = __commonJS({
|
|
|
9503
11773
|
openzeppelin: require_openzeppelin()
|
|
9504
11774
|
}
|
|
9505
11775
|
};
|
|
11776
|
+
var points = require_points();
|
|
9506
11777
|
var { SubgraphService } = require_client();
|
|
9507
11778
|
var { IPFSService } = require_client2();
|
|
9508
11779
|
var serviceErrors = require_errors2();
|
|
9509
11780
|
var { SimpleCache } = require_cache();
|
|
9510
11781
|
var { retryWithBackoff } = require_retry();
|
|
11782
|
+
var { DiscoveryClient } = require_clients();
|
|
9511
11783
|
var hooks = null;
|
|
9512
11784
|
try {
|
|
9513
11785
|
hooks = require_hooks();
|
|
@@ -9523,6 +11795,7 @@ var require_src = __commonJS({
|
|
|
9523
11795
|
timelock,
|
|
9524
11796
|
factory,
|
|
9525
11797
|
library,
|
|
11798
|
+
lineage,
|
|
9526
11799
|
prompt,
|
|
9527
11800
|
ipfs,
|
|
9528
11801
|
ipns,
|
|
@@ -9535,6 +11808,8 @@ var require_src = __commonJS({
|
|
|
9535
11808
|
subgraph,
|
|
9536
11809
|
utils: { ...utils, privateTx, safe, time },
|
|
9537
11810
|
bounty,
|
|
11811
|
+
votingMultiplier,
|
|
11812
|
+
auction,
|
|
9538
11813
|
wallet: Object.assign(wallet, {
|
|
9539
11814
|
cast: walletCastManager,
|
|
9540
11815
|
cdp: walletCdpManager
|
|
@@ -9543,6 +11818,8 @@ var require_src = __commonJS({
|
|
|
9543
11818
|
errors,
|
|
9544
11819
|
doppler,
|
|
9545
11820
|
adapters,
|
|
11821
|
+
// Season points helpers (airdrops/testnet)
|
|
11822
|
+
points,
|
|
9546
11823
|
// New service layer exports
|
|
9547
11824
|
services: {
|
|
9548
11825
|
SubgraphService,
|
|
@@ -9553,6 +11830,11 @@ var require_src = __commonJS({
|
|
|
9553
11830
|
SimpleCache,
|
|
9554
11831
|
retryWithBackoff
|
|
9555
11832
|
},
|
|
11833
|
+
// Client exports
|
|
11834
|
+
clients: {
|
|
11835
|
+
DiscoveryClient
|
|
11836
|
+
},
|
|
11837
|
+
DiscoveryClient,
|
|
9556
11838
|
// React hooks (optional - requires react + swr peer dependencies)
|
|
9557
11839
|
hooks,
|
|
9558
11840
|
// Legacy exports (deprecated): maintain compatibility while consumers migrate
|