@sage-protocol/sdk 0.1.24 → 0.1.25
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 +1 -1
- package/dist/browser/index.mjs +1 -1
- package/dist/index.cjs +332 -1
- package/dist/index.mjs +332 -1
- package/dist/node/index.cjs +332 -1
- package/dist/node/index.mjs +332 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -28,7 +28,7 @@ const provider = sdk.getProvider({ rpcUrl: 'https://base-sepolia.publicnode.com'
|
|
|
28
28
|
// Discover SubDAOs deployed by the latest factory
|
|
29
29
|
const subdaos = await sdk.subdao.discoverSubDAOs({
|
|
30
30
|
provider,
|
|
31
|
-
factoryAddress: '
|
|
31
|
+
factoryAddress: '0x89Fd9FfD04503A62c52E6769401AB928abbeD5cA',
|
|
32
32
|
fromBlock: 0,
|
|
33
33
|
});
|
|
34
34
|
|
package/dist/browser/index.mjs
CHANGED
|
@@ -14,7 +14,7 @@ var require_package = __commonJS({
|
|
|
14
14
|
"package.json"(exports, module) {
|
|
15
15
|
module.exports = {
|
|
16
16
|
name: "@sage-protocol/sdk",
|
|
17
|
-
version: "0.1.
|
|
17
|
+
version: "0.1.25",
|
|
18
18
|
description: "Backend-agnostic SDK for interacting with the Sage Protocol (governance, SubDAOs, tokens).",
|
|
19
19
|
main: "dist/index.cjs",
|
|
20
20
|
module: "dist/index.mjs",
|
package/dist/index.cjs
CHANGED
|
@@ -14,7 +14,7 @@ var require_package = __commonJS({
|
|
|
14
14
|
"package.json"(exports2, module2) {
|
|
15
15
|
module2.exports = {
|
|
16
16
|
name: "@sage-protocol/sdk",
|
|
17
|
-
version: "0.1.
|
|
17
|
+
version: "0.1.25",
|
|
18
18
|
description: "Backend-agnostic SDK for interacting with the Sage Protocol (governance, SubDAOs, tokens).",
|
|
19
19
|
main: "dist/index.cjs",
|
|
20
20
|
module: "dist/index.mjs",
|
|
@@ -9789,6 +9789,335 @@ var require_contributions = __commonJS({
|
|
|
9789
9789
|
}
|
|
9790
9790
|
});
|
|
9791
9791
|
|
|
9792
|
+
// src/browser/reputation.js
|
|
9793
|
+
var require_reputation = __commonJS({
|
|
9794
|
+
"src/browser/reputation.js"(exports2, module2) {
|
|
9795
|
+
var { getAddress } = require_utils();
|
|
9796
|
+
var subgraph2 = require_subgraph2();
|
|
9797
|
+
function safeGetAddress(value) {
|
|
9798
|
+
try {
|
|
9799
|
+
return getAddress(value);
|
|
9800
|
+
} catch {
|
|
9801
|
+
return null;
|
|
9802
|
+
}
|
|
9803
|
+
}
|
|
9804
|
+
function clampInt(value, { min = 1, max = 100, fallback = 100 } = {}) {
|
|
9805
|
+
const n = Number(value);
|
|
9806
|
+
if (!Number.isFinite(n)) return fallback;
|
|
9807
|
+
return Math.min(max, Math.max(min, Math.trunc(n)));
|
|
9808
|
+
}
|
|
9809
|
+
function toBigIntString(value, fallback = "0") {
|
|
9810
|
+
try {
|
|
9811
|
+
if (typeof value === "bigint") return value.toString();
|
|
9812
|
+
if (typeof value === "number") return String(Math.trunc(value));
|
|
9813
|
+
const str = String(value).trim();
|
|
9814
|
+
if (!str) return fallback;
|
|
9815
|
+
if (!/^-?\d+$/.test(str)) return fallback;
|
|
9816
|
+
return str;
|
|
9817
|
+
} catch {
|
|
9818
|
+
return fallback;
|
|
9819
|
+
}
|
|
9820
|
+
}
|
|
9821
|
+
function mapSafe(list, mapper) {
|
|
9822
|
+
const out = [];
|
|
9823
|
+
for (const item of list || []) {
|
|
9824
|
+
try {
|
|
9825
|
+
const v = mapper(item);
|
|
9826
|
+
if (v != null) out.push(v);
|
|
9827
|
+
} catch {
|
|
9828
|
+
}
|
|
9829
|
+
}
|
|
9830
|
+
return out;
|
|
9831
|
+
}
|
|
9832
|
+
async function getBadgesByRecipient({ url, recipient, first = 50 }) {
|
|
9833
|
+
if (!url) throw new Error("subgraph url required");
|
|
9834
|
+
if (!recipient) throw new Error("recipient required");
|
|
9835
|
+
const addr = safeGetAddress(recipient);
|
|
9836
|
+
if (!addr) throw new Error("invalid recipient address");
|
|
9837
|
+
const doc = `
|
|
9838
|
+
query($recipient: Bytes!, $first: Int!) {
|
|
9839
|
+
soulboundBadges(
|
|
9840
|
+
where: { recipient: $recipient }
|
|
9841
|
+
first: $first
|
|
9842
|
+
orderBy: blockTimestamp
|
|
9843
|
+
orderDirection: desc
|
|
9844
|
+
) {
|
|
9845
|
+
id
|
|
9846
|
+
contract
|
|
9847
|
+
badgeId
|
|
9848
|
+
recipient
|
|
9849
|
+
evidenceURI
|
|
9850
|
+
blockNumber
|
|
9851
|
+
blockTimestamp
|
|
9852
|
+
transactionHash
|
|
9853
|
+
}
|
|
9854
|
+
}
|
|
9855
|
+
`;
|
|
9856
|
+
const data = await subgraph2.query(url, doc, {
|
|
9857
|
+
recipient: addr.toLowerCase(),
|
|
9858
|
+
first: clampInt(first, { min: 1, max: 100, fallback: 50 })
|
|
9859
|
+
});
|
|
9860
|
+
return mapSafe(data?.soulboundBadges, (row) => {
|
|
9861
|
+
const contract = safeGetAddress(row.contract);
|
|
9862
|
+
const recipientAddr = safeGetAddress(row.recipient);
|
|
9863
|
+
if (!contract || !recipientAddr) return null;
|
|
9864
|
+
return {
|
|
9865
|
+
id: String(row.id),
|
|
9866
|
+
contract,
|
|
9867
|
+
badgeId: toBigIntString(row.badgeId, "0"),
|
|
9868
|
+
recipient: recipientAddr,
|
|
9869
|
+
evidenceURI: row.evidenceURI || null,
|
|
9870
|
+
blockNumber: Number(row.blockNumber || 0),
|
|
9871
|
+
blockTimestamp: Number(row.blockTimestamp || 0),
|
|
9872
|
+
transactionHash: row.transactionHash || null
|
|
9873
|
+
};
|
|
9874
|
+
});
|
|
9875
|
+
}
|
|
9876
|
+
async function listContributions({ url, contributor, subdao: subdao2, first = 50, orderBy = "updatedAt", orderDirection = "desc" }) {
|
|
9877
|
+
if (!url) throw new Error("subgraph url required");
|
|
9878
|
+
const filters = [];
|
|
9879
|
+
if (contributor) {
|
|
9880
|
+
const addr = safeGetAddress(contributor);
|
|
9881
|
+
if (!addr) throw new Error("invalid contributor address");
|
|
9882
|
+
filters.push(`contributor: "${addr.toLowerCase()}"`);
|
|
9883
|
+
}
|
|
9884
|
+
if (subdao2) {
|
|
9885
|
+
const addr = safeGetAddress(subdao2);
|
|
9886
|
+
if (!addr) throw new Error("invalid subdao address");
|
|
9887
|
+
filters.push(`dao: "${addr.toLowerCase()}"`);
|
|
9888
|
+
}
|
|
9889
|
+
const where = filters.length ? `where: { ${filters.join(", ")} }` : "";
|
|
9890
|
+
const safeOrderBy = ["updatedAt", "createdAt"].includes(orderBy) ? orderBy : "updatedAt";
|
|
9891
|
+
const safeOrderDirection = orderDirection === "asc" ? "asc" : "desc";
|
|
9892
|
+
const doc = `
|
|
9893
|
+
query($first: Int!) {
|
|
9894
|
+
promptContributions(
|
|
9895
|
+
${where}
|
|
9896
|
+
first: $first
|
|
9897
|
+
orderBy: ${safeOrderBy}
|
|
9898
|
+
orderDirection: ${safeOrderDirection}
|
|
9899
|
+
) {
|
|
9900
|
+
id
|
|
9901
|
+
dao
|
|
9902
|
+
promptKey
|
|
9903
|
+
contributor
|
|
9904
|
+
cid
|
|
9905
|
+
proposalId
|
|
9906
|
+
forVotes
|
|
9907
|
+
againstVotes
|
|
9908
|
+
abstainVotes
|
|
9909
|
+
uniqueVoters
|
|
9910
|
+
quorum
|
|
9911
|
+
fromBounty
|
|
9912
|
+
bountyId
|
|
9913
|
+
badgeId
|
|
9914
|
+
badgeEvidenceURI
|
|
9915
|
+
createdAt
|
|
9916
|
+
updatedAt
|
|
9917
|
+
transactionHash
|
|
9918
|
+
}
|
|
9919
|
+
}
|
|
9920
|
+
`;
|
|
9921
|
+
const data = await subgraph2.query(url, doc, {
|
|
9922
|
+
first: clampInt(first, { min: 1, max: 100, fallback: 50 })
|
|
9923
|
+
});
|
|
9924
|
+
return mapSafe(data?.promptContributions, (row) => {
|
|
9925
|
+
const dao = safeGetAddress(row.dao);
|
|
9926
|
+
const contributorAddr = safeGetAddress(row.contributor);
|
|
9927
|
+
if (!dao) return null;
|
|
9928
|
+
return {
|
|
9929
|
+
id: String(row.id),
|
|
9930
|
+
dao,
|
|
9931
|
+
promptKey: String(row.promptKey),
|
|
9932
|
+
contributor: contributorAddr || "0x0000000000000000000000000000000000000000",
|
|
9933
|
+
cid: String(row.cid),
|
|
9934
|
+
timestamp: Number(row.updatedAt || 0),
|
|
9935
|
+
createdAt: Number(row.createdAt || 0),
|
|
9936
|
+
updatedAt: Number(row.updatedAt || 0),
|
|
9937
|
+
transactionHash: row.transactionHash || null,
|
|
9938
|
+
proposalId: row.proposalId != null ? toBigIntString(row.proposalId) : null,
|
|
9939
|
+
forVotes: row.forVotes != null ? toBigIntString(row.forVotes) : null,
|
|
9940
|
+
againstVotes: row.againstVotes != null ? toBigIntString(row.againstVotes) : null,
|
|
9941
|
+
abstainVotes: row.abstainVotes != null ? toBigIntString(row.abstainVotes) : null,
|
|
9942
|
+
uniqueVoters: row.uniqueVoters != null ? Number(row.uniqueVoters) : null,
|
|
9943
|
+
quorum: row.quorum != null ? toBigIntString(row.quorum) : null,
|
|
9944
|
+
fromBounty: Boolean(row.fromBounty),
|
|
9945
|
+
bountyId: row.bountyId != null ? toBigIntString(row.bountyId) : null,
|
|
9946
|
+
badgeId: row.badgeId != null ? toBigIntString(row.badgeId) : null,
|
|
9947
|
+
badgeEvidenceURI: row.badgeEvidenceURI || null
|
|
9948
|
+
};
|
|
9949
|
+
});
|
|
9950
|
+
}
|
|
9951
|
+
function computeAggregates(contributions2) {
|
|
9952
|
+
if (!contributions2 || contributions2.length === 0) {
|
|
9953
|
+
return {
|
|
9954
|
+
totalContributions: 0,
|
|
9955
|
+
uniqueContributors: 0,
|
|
9956
|
+
bountyOriginated: 0,
|
|
9957
|
+
governanceOriginated: 0,
|
|
9958
|
+
totalForVotes: "0",
|
|
9959
|
+
totalAgainstVotes: "0",
|
|
9960
|
+
averageVoterCount: 0,
|
|
9961
|
+
badgeCount: 0
|
|
9962
|
+
};
|
|
9963
|
+
}
|
|
9964
|
+
const contributorSet = /* @__PURE__ */ new Set();
|
|
9965
|
+
let bountyOriginated = 0;
|
|
9966
|
+
let governanceOriginated = 0;
|
|
9967
|
+
let totalForVotes = 0n;
|
|
9968
|
+
let totalAgainstVotes = 0n;
|
|
9969
|
+
let voterCountSum = 0;
|
|
9970
|
+
let voterCountN = 0;
|
|
9971
|
+
let badgeCount = 0;
|
|
9972
|
+
for (const c of contributions2) {
|
|
9973
|
+
if (c.contributor) contributorSet.add(c.contributor.toLowerCase());
|
|
9974
|
+
if (c.fromBounty) {
|
|
9975
|
+
bountyOriginated++;
|
|
9976
|
+
} else {
|
|
9977
|
+
governanceOriginated++;
|
|
9978
|
+
}
|
|
9979
|
+
if (c.forVotes != null) {
|
|
9980
|
+
try {
|
|
9981
|
+
totalForVotes += BigInt(c.forVotes);
|
|
9982
|
+
} catch {
|
|
9983
|
+
}
|
|
9984
|
+
}
|
|
9985
|
+
if (c.againstVotes != null) {
|
|
9986
|
+
try {
|
|
9987
|
+
totalAgainstVotes += BigInt(c.againstVotes);
|
|
9988
|
+
} catch {
|
|
9989
|
+
}
|
|
9990
|
+
}
|
|
9991
|
+
if (c.uniqueVoters != null) {
|
|
9992
|
+
voterCountSum += c.uniqueVoters;
|
|
9993
|
+
voterCountN++;
|
|
9994
|
+
}
|
|
9995
|
+
if (c.badgeId != null) badgeCount++;
|
|
9996
|
+
}
|
|
9997
|
+
return {
|
|
9998
|
+
totalContributions: contributions2.length,
|
|
9999
|
+
uniqueContributors: contributorSet.size,
|
|
10000
|
+
bountyOriginated,
|
|
10001
|
+
governanceOriginated,
|
|
10002
|
+
totalForVotes: totalForVotes.toString(),
|
|
10003
|
+
totalAgainstVotes: totalAgainstVotes.toString(),
|
|
10004
|
+
averageVoterCount: voterCountN > 0 ? Math.round(voterCountSum / voterCountN) : 0,
|
|
10005
|
+
badgeCount
|
|
10006
|
+
};
|
|
10007
|
+
}
|
|
10008
|
+
async function getByAddress({
|
|
10009
|
+
url,
|
|
10010
|
+
address,
|
|
10011
|
+
subdao: subdao2,
|
|
10012
|
+
includeBadges = true,
|
|
10013
|
+
includeContributions = true,
|
|
10014
|
+
first = 100
|
|
10015
|
+
} = {}) {
|
|
10016
|
+
if (!url) throw new Error("subgraph url required");
|
|
10017
|
+
if (!address) throw new Error("address required");
|
|
10018
|
+
const addr = safeGetAddress(address);
|
|
10019
|
+
if (!addr) throw new Error("invalid address");
|
|
10020
|
+
const subdaoAddr = subdao2 ? safeGetAddress(subdao2) : null;
|
|
10021
|
+
if (subdao2 && !subdaoAddr) throw new Error("invalid subdao address");
|
|
10022
|
+
const limit = clampInt(first, { min: 1, max: 200, fallback: 100 });
|
|
10023
|
+
let badges = void 0;
|
|
10024
|
+
if (includeBadges) {
|
|
10025
|
+
badges = await getBadgesByRecipient({ url, recipient: addr, first: limit });
|
|
10026
|
+
}
|
|
10027
|
+
let contributionAggregates = void 0;
|
|
10028
|
+
let lastContributionAt = null;
|
|
10029
|
+
if (includeContributions) {
|
|
10030
|
+
const rows = await listContributions({
|
|
10031
|
+
url,
|
|
10032
|
+
contributor: addr,
|
|
10033
|
+
subdao: subdaoAddr || void 0,
|
|
10034
|
+
first: limit,
|
|
10035
|
+
orderBy: "updatedAt",
|
|
10036
|
+
orderDirection: "desc"
|
|
10037
|
+
});
|
|
10038
|
+
if (rows && rows.length) {
|
|
10039
|
+
const updatedAt = rows[0]?.updatedAt ?? rows[0]?.timestamp ?? null;
|
|
10040
|
+
lastContributionAt = updatedAt != null ? Number(updatedAt) : null;
|
|
10041
|
+
if (!Number.isFinite(lastContributionAt)) lastContributionAt = null;
|
|
10042
|
+
}
|
|
10043
|
+
contributionAggregates = computeAggregates(rows || []);
|
|
10044
|
+
}
|
|
10045
|
+
const signals = {
|
|
10046
|
+
badgeCount: includeBadges ? badges ? badges.length : 0 : null,
|
|
10047
|
+
totalContributions: includeContributions ? contributionAggregates ? contributionAggregates.totalContributions : 0 : null,
|
|
10048
|
+
governanceOriginated: includeContributions ? contributionAggregates ? contributionAggregates.governanceOriginated : 0 : null,
|
|
10049
|
+
bountyOriginated: includeContributions ? contributionAggregates ? contributionAggregates.bountyOriginated : 0 : null,
|
|
10050
|
+
lastContributionAt: includeContributions ? lastContributionAt : null
|
|
10051
|
+
};
|
|
10052
|
+
const out = {
|
|
10053
|
+
address: addr,
|
|
10054
|
+
subdao: subdaoAddr || null,
|
|
10055
|
+
signals
|
|
10056
|
+
};
|
|
10057
|
+
if (includeBadges) out.badges = badges;
|
|
10058
|
+
if (includeContributions) {
|
|
10059
|
+
out.contributionAggregates = contributionAggregates;
|
|
10060
|
+
out.lastContributionAt = lastContributionAt;
|
|
10061
|
+
}
|
|
10062
|
+
return out;
|
|
10063
|
+
}
|
|
10064
|
+
function normalizeGateInt(value, name) {
|
|
10065
|
+
if (value === void 0 || value === null) return null;
|
|
10066
|
+
const n = Number(value);
|
|
10067
|
+
if (!Number.isFinite(n) || n < 0) {
|
|
10068
|
+
throw new Error(`invalid gate: ${name}`);
|
|
10069
|
+
}
|
|
10070
|
+
return Math.trunc(n);
|
|
10071
|
+
}
|
|
10072
|
+
function normalizeRequiredBadgeIds(value) {
|
|
10073
|
+
const list = Array.isArray(value) ? value : value != null ? [value] : [];
|
|
10074
|
+
const out = [];
|
|
10075
|
+
for (const item of list) {
|
|
10076
|
+
const id2 = toBigIntString(item, "");
|
|
10077
|
+
if (id2) out.push(id2);
|
|
10078
|
+
}
|
|
10079
|
+
return out;
|
|
10080
|
+
}
|
|
10081
|
+
function evaluate(result, gates = {}) {
|
|
10082
|
+
const reasons = [];
|
|
10083
|
+
const minBadges = normalizeGateInt(gates.minBadges, "minBadges");
|
|
10084
|
+
const minContributions = normalizeGateInt(gates.minContributions, "minContributions");
|
|
10085
|
+
const requiredBadges = normalizeRequiredBadgeIds(gates.requireBadges ?? gates.requireBadge);
|
|
10086
|
+
const badgeCount = Number(result?.signals?.badgeCount ?? (result?.badges?.length ?? 0));
|
|
10087
|
+
const totalContributions = Number(result?.signals?.totalContributions ?? (result?.contributionAggregates?.totalContributions ?? 0));
|
|
10088
|
+
if (minBadges != null) {
|
|
10089
|
+
if (!Number.isFinite(badgeCount)) {
|
|
10090
|
+
reasons.push("badges_unavailable");
|
|
10091
|
+
} else if (badgeCount < minBadges) {
|
|
10092
|
+
reasons.push(`minBadges:${badgeCount}<${minBadges}`);
|
|
10093
|
+
}
|
|
10094
|
+
}
|
|
10095
|
+
if (minContributions != null) {
|
|
10096
|
+
if (!Number.isFinite(totalContributions)) {
|
|
10097
|
+
reasons.push("contributions_unavailable");
|
|
10098
|
+
} else if (totalContributions < minContributions) {
|
|
10099
|
+
reasons.push(`minContributions:${totalContributions}<${minContributions}`);
|
|
10100
|
+
}
|
|
10101
|
+
}
|
|
10102
|
+
if (requiredBadges.length) {
|
|
10103
|
+
const have = new Set((result?.badges || []).map((b) => toBigIntString(b?.badgeId, "")).filter(Boolean));
|
|
10104
|
+
for (const req2 of requiredBadges) {
|
|
10105
|
+
if (!have.has(req2)) reasons.push(`missingBadge:${req2}`);
|
|
10106
|
+
}
|
|
10107
|
+
}
|
|
10108
|
+
return { ok: reasons.length === 0, reasons };
|
|
10109
|
+
}
|
|
10110
|
+
module2.exports = {
|
|
10111
|
+
getByAddress,
|
|
10112
|
+
evaluate,
|
|
10113
|
+
// Expose lower-level functions for advanced usage
|
|
10114
|
+
getBadgesByRecipient,
|
|
10115
|
+
listContributions,
|
|
10116
|
+
computeAggregates
|
|
10117
|
+
};
|
|
10118
|
+
}
|
|
10119
|
+
});
|
|
10120
|
+
|
|
9792
10121
|
// src/votingMultiplier/index.js
|
|
9793
10122
|
var require_votingMultiplier = __commonJS({
|
|
9794
10123
|
"src/votingMultiplier/index.js"(exports2, module2) {
|
|
@@ -14041,6 +14370,7 @@ var treasury = require_treasury();
|
|
|
14041
14370
|
var boost = require_boost();
|
|
14042
14371
|
var bounty = require_bounty();
|
|
14043
14372
|
var contributions = require_contributions();
|
|
14373
|
+
var reputation = require_reputation();
|
|
14044
14374
|
var votingMultiplier = require_votingMultiplier();
|
|
14045
14375
|
var auction = require_auction();
|
|
14046
14376
|
var wallet = require_wallet();
|
|
@@ -14094,6 +14424,7 @@ module.exports = {
|
|
|
14094
14424
|
utils: { ...utils, privateTx, safe, time },
|
|
14095
14425
|
bounty,
|
|
14096
14426
|
contributions,
|
|
14427
|
+
reputation,
|
|
14097
14428
|
votingMultiplier,
|
|
14098
14429
|
auction,
|
|
14099
14430
|
wallet: Object.assign(wallet, {
|