@poa-box/core 0.1.0 → 1.0.0
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 +2 -0
- package/dist/abis/AuthorityRouter.d.ts +448 -0
- package/dist/abis/AuthorityRouter.js +584 -0
- package/dist/abis/CutoverVerifier.d.ts +194 -0
- package/dist/abis/CutoverVerifier.js +259 -0
- package/dist/abis/DirectDemocracyVotingNew.d.ts +168 -30
- package/dist/abis/DirectDemocracyVotingNew.js +214 -35
- package/dist/abis/EducationHubNew.d.ts +32 -75
- package/dist/abis/EducationHubNew.js +38 -94
- package/dist/abis/Executor.d.ts +56 -86
- package/dist/abis/Executor.js +68 -104
- package/dist/abis/HybridVotingNew.d.ts +279 -35
- package/dist/abis/HybridVotingNew.js +357 -40
- package/dist/abis/{EligibilityModuleNew.d.ts → MembershipAuthority.d.ts} +1437 -718
- package/dist/abis/{EligibilityModuleNew.js → MembershipAuthority.js} +1821 -899
- package/dist/abis/OrgDeployerNew.d.ts +193 -127
- package/dist/abis/OrgDeployerNew.js +244 -160
- package/dist/abis/OrgRegistry.d.ts +40 -0
- package/dist/abis/OrgRegistry.js +51 -0
- package/dist/abis/ParticipationToken.d.ts +32 -75
- package/dist/abis/ParticipationToken.js +38 -94
- package/dist/abis/PasskeyAccount.d.ts +28 -0
- package/dist/abis/PasskeyAccount.js +35 -0
- package/dist/abis/PaymasterHub.d.ts +527 -47
- package/dist/abis/PaymasterHub.js +750 -135
- package/dist/abis/QuickJoinNew.d.ts +59 -170
- package/dist/abis/QuickJoinNew.js +71 -215
- package/dist/abis/TaskManagerNew.d.ts +27 -44
- package/dist/abis/TaskManagerNew.js +31 -52
- package/dist/abis/UniversalAccountRegistry.d.ts +24 -0
- package/dist/abis/UniversalAccountRegistry.js +30 -0
- package/dist/abis/ZkEmailInvites.d.ts +44 -0
- package/dist/abis/ZkEmailInvites.js +55 -0
- package/dist/abis/index.d.ts +6 -4
- package/dist/abis/index.js +10 -7
- package/dist/chains.js +3 -3
- package/dist/error-catalog.js +125 -7
- package/dist/graph/documents/activity.d.ts +3 -1
- package/dist/graph/documents/activity.js +19 -14
- package/dist/graph/documents/org.d.ts +4 -4
- package/dist/graph/documents/org.js +10 -4
- package/dist/graph/documents/task.d.ts +10 -1
- package/dist/graph/documents/task.js +157 -3
- package/dist/graph/documents/user.d.ts +5 -30
- package/dist/graph/documents/user.js +2 -42
- package/dist/graph/documents/voting-classes.d.ts +23 -2
- package/dist/graph/documents/voting-classes.js +119 -10
- package/dist/metadata/index.d.ts +0 -1
- package/dist/metadata/index.js +1 -2
- package/dist/perms.d.ts +0 -15
- package/dist/perms.js +1 -21
- package/dist/preflight.d.ts +2 -2
- package/dist/preflight.js +14 -22
- package/dist/reads/authority.d.ts +33 -0
- package/dist/reads/authority.js +196 -0
- package/dist/reads/index.d.ts +1 -1
- package/dist/reads/index.js +2 -2
- package/dist/reads/org.d.ts +20 -20
- package/dist/reads/org.js +94 -28
- package/dist/reads/project.js +3 -3
- package/dist/reads/resolve.d.ts +1 -1
- package/dist/reads/resolve.js +12 -3
- package/dist/reads/task.d.ts +44 -22
- package/dist/reads/task.js +126 -67
- package/dist/reads/user.d.ts +8 -43
- package/dist/reads/user.js +27 -44
- package/dist/reads/vote.d.ts +26 -2
- package/dist/reads/vote.js +104 -23
- package/dist/tx/authority.d.ts +33 -0
- package/dist/tx/authority.js +62 -0
- package/dist/tx/governance.d.ts +6 -0
- package/dist/tx/governance.js +20 -2
- package/dist/tx/index.d.ts +1 -1
- package/dist/tx/index.js +2 -2
- package/dist/tx/org.d.ts +23 -18
- package/dist/tx/org.js +203 -67
- package/dist/tx/project.d.ts +3 -2
- package/dist/tx/project.js +28 -10
- package/dist/tx/task.d.ts +13 -24
- package/dist/tx/task.js +45 -85
- package/dist/tx/user.d.ts +2 -40
- package/dist/tx/user.js +2 -76
- package/dist/tx/vote.d.ts +5 -0
- package/dist/tx/vote.js +54 -43
- package/dist/version.d.ts +0 -5
- package/dist/version.js +1 -13
- package/package.json +1 -1
- package/dist/abis/ToggleModule.d.ts +0 -193
- package/dist/abis/ToggleModule.js +0 -255
- package/dist/metadata/role.d.ts +0 -38
- package/dist/metadata/role.js +0 -35
- package/dist/reads/eligibility.d.ts +0 -377
- package/dist/reads/eligibility.js +0 -687
- package/dist/tx/eligibility.d.ts +0 -511
- package/dist/tx/eligibility.js +0 -818
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Ported from frontend queries.js
|
|
4
4
|
*/
|
|
5
5
|
import type { FieldFallbackTier } from '../client';
|
|
6
|
-
export declare const FETCH_PROJECTS_DATA = "\n query FetchProjectsDataNew($orgId: Bytes
|
|
6
|
+
export declare const FETCH_PROJECTS_DATA = "\n query FetchProjectsDataNew($orgId: Bytes!, $projectCursor: String = \"\") {\n organization(id: $orgId) {\n id\n taskManager {\n id\n creatorHatIds\n projects(where: { deleted: false, id_gt: $projectCursor }, first: 50, orderBy: id, orderDirection: asc) {\n id\n title\n metadataHash\n metadata {\n id\n description\n }\n cap\n bountyCaps {\n token\n cap\n }\n createdAt\n tasks(first: 1000, orderBy: taskId, orderDirection: desc) {\n id\n taskId\n title\n metadataHash\n submissionHash\n rejectionHash\n rejectionCount\n metadata {\n id\n name\n description\n location\n difficulty\n estimatedHours\n dueDate\n submission\n rejection\n }\n rejections(orderBy: rejectedAt, orderDirection: desc, first: 10) {\n rejectorUsername\n rejectedAt\n metadata {\n rejection\n }\n }\n payout\n bountyToken\n bountyPayout\n completionWindow\n absoluteDeadline\n claimDeadline\n reclaimCount\n status\n assignee\n assigneeUsername\n completer\n completerUsername\n requiresApplication\n createdAt\n assignedAt\n submittedAt\n completedAt\n applications {\n applicant\n applicantUsername\n applicationHash\n metadata {\n notes\n experience\n }\n approved\n approver\n approverUsername\n appliedAt\n }\n }\n }\n }\n }\n }\n";
|
|
7
7
|
/**
|
|
8
8
|
* FETCH_PROJECTS_DATA without the TaskManager v6 deadline fields (subgraph #192).
|
|
9
9
|
*
|
|
@@ -82,3 +82,12 @@ export declare const FETCH_TASK_RELEASE_HISTORY_LEGACY = "\n query FetchTaskRel
|
|
|
82
82
|
* checksummed address returns `[]` silently rather than erroring.
|
|
83
83
|
*/
|
|
84
84
|
export declare const FETCH_ORG_TASK_RELEASES = "\n query FetchOrgTaskReleases($taskManager: Bytes!, $first: Int!, $skip: Int!) {\n taskReleases(\n where: { task_: { taskManager: $taskManager } }\n orderBy: releasedAt\n orderDirection: desc\n first: $first\n skip: $skip\n ) {\n id\n previousClaimer\n previousClaimerUsername\n caller\n callerUsername\n selfRelease\n releasedAt\n transactionHash\n task {\n id\n taskId\n title\n status\n releaseCount\n }\n }\n }\n";
|
|
85
|
+
/** A direct task lookup avoids the org tree's project/task page limits. */
|
|
86
|
+
export declare const FETCH_TASK_DATA = "\n query FetchTaskData($taskId: ID!) {\n task(id: $taskId) {\n id\n taskId\n title\n metadataHash\n submissionHash\n rejectionHash\n rejectionCount\n metadata {\n id\n name\n description\n location\n difficulty\n estimatedHours\n dueDate\n submission\n rejection\n }\n rejections(orderBy: rejectedAt, orderDirection: desc, first: 10) {\n rejectorUsername\n rejectedAt\n metadata {\n rejection\n }\n }\n payout\n bountyToken\n bountyPayout\n completionWindow\n absoluteDeadline\n claimDeadline\n reclaimCount\n status\n assignee\n assigneeUsername\n completer\n completerUsername\n requiresApplication\n createdAt\n assignedAt\n submittedAt\n completedAt\n applications {\n applicant\n applicantUsername\n applicationHash\n metadata {\n notes\n experience\n }\n approved\n approver\n approverUsername\n appliedAt\n }\n project { id title }\n }\n }\n";
|
|
87
|
+
export declare const FETCH_TASK_DATA_WITH_RELEASES: string;
|
|
88
|
+
export declare const FETCH_TASK_DATA_LEGACY: string;
|
|
89
|
+
/** Follow-up page for a single project's tasks. taskId is unique within its TaskManager. */
|
|
90
|
+
export declare const FETCH_PROJECT_TASK_PAGE = "\n query FetchProjectTaskPage($projectId: ID!, $taskCursor: BigInt!) {\n project(id: $projectId) {\n id\n tasks(first: 1000, orderBy: taskId, orderDirection: desc, where: { taskId_lt: $taskCursor }) {\n id\n taskId\n title\n metadataHash\n submissionHash\n rejectionHash\n rejectionCount\n metadata {\n id\n name\n description\n location\n difficulty\n estimatedHours\n dueDate\n submission\n rejection\n }\n rejections(orderBy: rejectedAt, orderDirection: desc, first: 10) {\n rejectorUsername\n rejectedAt\n metadata {\n rejection\n }\n }\n payout\n bountyToken\n bountyPayout\n completionWindow\n absoluteDeadline\n claimDeadline\n reclaimCount\n status\n assignee\n assigneeUsername\n completer\n completerUsername\n requiresApplication\n createdAt\n assignedAt\n submittedAt\n completedAt\n applications {\n applicant\n applicantUsername\n applicationHash\n metadata {\n notes\n experience\n }\n approved\n approver\n approverUsername\n appliedAt\n }\n }\n }\n }\n";
|
|
91
|
+
export declare const PROJECT_TASK_PAGE_TIERS: string[];
|
|
92
|
+
/** PR213 immutable work/review history. ID cursors retain same-timestamp events. */
|
|
93
|
+
export declare const FETCH_TASK_SUBMISSION_HISTORY = "\n query FetchTaskSubmissionHistory($taskId: ID!, $submissionCursor: Bytes!, $rejectionCursor: Bytes!) {\n task(id: $taskId) {\n id\n latestSubmission { id submissionHash submittedAt submittedAtBlock transactionHash metadata { submission } }\n latestRejection { id }\n submissions(first: 1000, orderBy: id, orderDirection: asc, where: { id_gt: $submissionCursor }) {\n id submissionHash submittedAt submittedAtBlock transactionHash metadata { submission }\n }\n rejections(first: 1000, orderBy: id, orderDirection: asc, where: { id_gt: $rejectionCursor }) {\n id rejector rejectorUsername rejectionHash rejectedAt rejectedAtBlock transactionHash\n metadata { rejection }\n submission { id submissionHash submittedAt submittedAtBlock transactionHash metadata { submission } }\n }\n }\n }\n";
|
|
@@ -4,17 +4,17 @@
|
|
|
4
4
|
* Ported from frontend queries.js
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.FETCH_ORG_TASK_RELEASES = exports.FETCH_TASK_RELEASE_HISTORY_LEGACY = exports.FETCH_TASK_RELEASE_HISTORY = exports.TASK_RELEASE_INDEXING_CHAIN_IDS = exports.PROJECTS_DATA_TIERS = exports.FETCH_PROJECTS_DATA_WITH_RELEASES = exports.FETCH_PROJECTS_DATA_LEGACY = exports.FETCH_PROJECTS_DATA = void 0;
|
|
7
|
+
exports.FETCH_TASK_SUBMISSION_HISTORY = exports.PROJECT_TASK_PAGE_TIERS = exports.FETCH_PROJECT_TASK_PAGE = exports.FETCH_TASK_DATA_LEGACY = exports.FETCH_TASK_DATA_WITH_RELEASES = exports.FETCH_TASK_DATA = exports.FETCH_ORG_TASK_RELEASES = exports.FETCH_TASK_RELEASE_HISTORY_LEGACY = exports.FETCH_TASK_RELEASE_HISTORY = exports.TASK_RELEASE_INDEXING_CHAIN_IDS = exports.PROJECTS_DATA_TIERS = exports.FETCH_PROJECTS_DATA_WITH_RELEASES = exports.FETCH_PROJECTS_DATA_LEGACY = exports.FETCH_PROJECTS_DATA = void 0;
|
|
8
8
|
exports.projectsDataTiers = projectsDataTiers;
|
|
9
9
|
exports.chainIndexesTaskReleases = chainIndexesTaskReleases;
|
|
10
10
|
exports.FETCH_PROJECTS_DATA = `
|
|
11
|
-
query FetchProjectsDataNew($orgId: Bytes
|
|
11
|
+
query FetchProjectsDataNew($orgId: Bytes!, $projectCursor: String = "") {
|
|
12
12
|
organization(id: $orgId) {
|
|
13
13
|
id
|
|
14
14
|
taskManager {
|
|
15
15
|
id
|
|
16
16
|
creatorHatIds
|
|
17
|
-
projects(where: { deleted: false }, first: 50) {
|
|
17
|
+
projects(where: { deleted: false, id_gt: $projectCursor }, first: 50, orderBy: id, orderDirection: asc) {
|
|
18
18
|
id
|
|
19
19
|
title
|
|
20
20
|
metadataHash
|
|
@@ -234,3 +234,157 @@ exports.FETCH_ORG_TASK_RELEASES = `
|
|
|
234
234
|
}
|
|
235
235
|
}
|
|
236
236
|
`;
|
|
237
|
+
/** A direct task lookup avoids the org tree's project/task page limits. */
|
|
238
|
+
exports.FETCH_TASK_DATA = `
|
|
239
|
+
query FetchTaskData($taskId: ID!) {
|
|
240
|
+
task(id: $taskId) {
|
|
241
|
+
id
|
|
242
|
+
taskId
|
|
243
|
+
title
|
|
244
|
+
metadataHash
|
|
245
|
+
submissionHash
|
|
246
|
+
rejectionHash
|
|
247
|
+
rejectionCount
|
|
248
|
+
metadata {
|
|
249
|
+
id
|
|
250
|
+
name
|
|
251
|
+
description
|
|
252
|
+
location
|
|
253
|
+
difficulty
|
|
254
|
+
estimatedHours
|
|
255
|
+
dueDate
|
|
256
|
+
submission
|
|
257
|
+
rejection
|
|
258
|
+
}
|
|
259
|
+
rejections(orderBy: rejectedAt, orderDirection: desc, first: 10) {
|
|
260
|
+
rejectorUsername
|
|
261
|
+
rejectedAt
|
|
262
|
+
metadata {
|
|
263
|
+
rejection
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
payout
|
|
267
|
+
bountyToken
|
|
268
|
+
bountyPayout
|
|
269
|
+
completionWindow
|
|
270
|
+
absoluteDeadline
|
|
271
|
+
claimDeadline
|
|
272
|
+
reclaimCount
|
|
273
|
+
status
|
|
274
|
+
assignee
|
|
275
|
+
assigneeUsername
|
|
276
|
+
completer
|
|
277
|
+
completerUsername
|
|
278
|
+
requiresApplication
|
|
279
|
+
createdAt
|
|
280
|
+
assignedAt
|
|
281
|
+
submittedAt
|
|
282
|
+
completedAt
|
|
283
|
+
applications {
|
|
284
|
+
applicant
|
|
285
|
+
applicantUsername
|
|
286
|
+
applicationHash
|
|
287
|
+
metadata {
|
|
288
|
+
notes
|
|
289
|
+
experience
|
|
290
|
+
}
|
|
291
|
+
approved
|
|
292
|
+
approver
|
|
293
|
+
approverUsername
|
|
294
|
+
appliedAt
|
|
295
|
+
}
|
|
296
|
+
project { id title }
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
`;
|
|
300
|
+
exports.FETCH_TASK_DATA_WITH_RELEASES = exports.FETCH_TASK_DATA.replace(/^(\s*)reclaimCount$/m, '$1reclaimCount\n$1releaseCount\n$1lastReleasedAt');
|
|
301
|
+
exports.FETCH_TASK_DATA_LEGACY = exports.FETCH_TASK_DATA.split('\n')
|
|
302
|
+
.filter(line => !/^\s*(completionWindow|absoluteDeadline|claimDeadline|reclaimCount)\s*$/.test(line)).join('\n');
|
|
303
|
+
/** Follow-up page for a single project's tasks. taskId is unique within its TaskManager. */
|
|
304
|
+
exports.FETCH_PROJECT_TASK_PAGE = `
|
|
305
|
+
query FetchProjectTaskPage($projectId: ID!, $taskCursor: BigInt!) {
|
|
306
|
+
project(id: $projectId) {
|
|
307
|
+
id
|
|
308
|
+
tasks(first: 1000, orderBy: taskId, orderDirection: desc, where: { taskId_lt: $taskCursor }) {
|
|
309
|
+
id
|
|
310
|
+
taskId
|
|
311
|
+
title
|
|
312
|
+
metadataHash
|
|
313
|
+
submissionHash
|
|
314
|
+
rejectionHash
|
|
315
|
+
rejectionCount
|
|
316
|
+
metadata {
|
|
317
|
+
id
|
|
318
|
+
name
|
|
319
|
+
description
|
|
320
|
+
location
|
|
321
|
+
difficulty
|
|
322
|
+
estimatedHours
|
|
323
|
+
dueDate
|
|
324
|
+
submission
|
|
325
|
+
rejection
|
|
326
|
+
}
|
|
327
|
+
rejections(orderBy: rejectedAt, orderDirection: desc, first: 10) {
|
|
328
|
+
rejectorUsername
|
|
329
|
+
rejectedAt
|
|
330
|
+
metadata {
|
|
331
|
+
rejection
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
payout
|
|
335
|
+
bountyToken
|
|
336
|
+
bountyPayout
|
|
337
|
+
completionWindow
|
|
338
|
+
absoluteDeadline
|
|
339
|
+
claimDeadline
|
|
340
|
+
reclaimCount
|
|
341
|
+
status
|
|
342
|
+
assignee
|
|
343
|
+
assigneeUsername
|
|
344
|
+
completer
|
|
345
|
+
completerUsername
|
|
346
|
+
requiresApplication
|
|
347
|
+
createdAt
|
|
348
|
+
assignedAt
|
|
349
|
+
submittedAt
|
|
350
|
+
completedAt
|
|
351
|
+
applications {
|
|
352
|
+
applicant
|
|
353
|
+
applicantUsername
|
|
354
|
+
applicationHash
|
|
355
|
+
metadata {
|
|
356
|
+
notes
|
|
357
|
+
experience
|
|
358
|
+
}
|
|
359
|
+
approved
|
|
360
|
+
approver
|
|
361
|
+
approverUsername
|
|
362
|
+
appliedAt
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
`;
|
|
368
|
+
exports.PROJECT_TASK_PAGE_TIERS = [
|
|
369
|
+
exports.FETCH_PROJECT_TASK_PAGE.replace(/^(\s*)reclaimCount$/m, '$1reclaimCount\n$1releaseCount\n$1lastReleasedAt'),
|
|
370
|
+
exports.FETCH_PROJECT_TASK_PAGE,
|
|
371
|
+
exports.FETCH_PROJECT_TASK_PAGE.split('\n').filter(line => !/^\s*(completionWindow|absoluteDeadline|claimDeadline|reclaimCount)\s*$/.test(line)).join('\n'),
|
|
372
|
+
];
|
|
373
|
+
/** PR213 immutable work/review history. ID cursors retain same-timestamp events. */
|
|
374
|
+
exports.FETCH_TASK_SUBMISSION_HISTORY = `
|
|
375
|
+
query FetchTaskSubmissionHistory($taskId: ID!, $submissionCursor: Bytes!, $rejectionCursor: Bytes!) {
|
|
376
|
+
task(id: $taskId) {
|
|
377
|
+
id
|
|
378
|
+
latestSubmission { id submissionHash submittedAt submittedAtBlock transactionHash metadata { submission } }
|
|
379
|
+
latestRejection { id }
|
|
380
|
+
submissions(first: 1000, orderBy: id, orderDirection: asc, where: { id_gt: $submissionCursor }) {
|
|
381
|
+
id submissionHash submittedAt submittedAtBlock transactionHash metadata { submission }
|
|
382
|
+
}
|
|
383
|
+
rejections(first: 1000, orderBy: id, orderDirection: asc, where: { id_gt: $rejectionCursor }) {
|
|
384
|
+
id rejector rejectorUsername rejectionHash rejectedAt rejectedAtBlock transactionHash
|
|
385
|
+
metadata { rejection }
|
|
386
|
+
submission { id submissionHash submittedAt submittedAtBlock transactionHash metadata { submission } }
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
`;
|
|
@@ -5,28 +5,8 @@
|
|
|
5
5
|
import type { FieldFallbackTier } from '../client';
|
|
6
6
|
export declare const FETCH_USERNAME = "\n query FetchUsernameNew($id: Bytes!) {\n account(id: $id) {\n id\n username\n profileMetadataHash\n metadata {\n id\n bio\n avatar\n github\n twitter\n website\n }\n }\n }\n";
|
|
7
7
|
export declare const GET_ACCOUNT_BY_USERNAME = "\n query GetAccountByUsername($username: String!) {\n accounts(where: { username: $username }, first: 1) {\n id\n user\n username\n }\n }\n";
|
|
8
|
-
/**
|
|
9
|
-
|
|
10
|
-
* names, the org's QuickJoin module pointers, the caller's account
|
|
11
|
-
* (username + which registry it lives on), their ERC-20 participation-token
|
|
12
|
-
* balance, their org-user entity (membership, PT balance, hats worn), and
|
|
13
|
-
* their pending participation-token requests. The `status: Pending`
|
|
14
|
-
* filter is inlined (enum literal) to match FETCH_PENDING_TOKEN_REQUESTS
|
|
15
|
-
* in queries/token.ts.
|
|
16
|
-
*
|
|
17
|
-
* Every field here was verified NON-NULL against the live Gnosis
|
|
18
|
-
* (poa-gnosis-v-1) AND Arbitrum (poa-arb-v-1) deployments, and
|
|
19
|
-
* quickJoinContract.{accountRegistry,hatsContract,memberHatIds} were
|
|
20
|
-
* byte-compared against the matching eth_calls on both chains — including
|
|
21
|
-
* the empty-array memberHatIds case, which is genuinely empty on-chain and
|
|
22
|
-
* not an indexing gap.
|
|
23
|
-
*
|
|
24
|
-
* `account.registry` is carried so callers can prove the indexed account
|
|
25
|
-
* belongs to the SAME registry the org's QuickJoin consults before trusting
|
|
26
|
-
* the indexed username (a legacy org can point at a registry this subgraph
|
|
27
|
-
* does not index).
|
|
28
|
-
*/
|
|
29
|
-
export declare const FETCH_WHOAMI_ORG_DATA = "\n query WhoamiOrgData(\n $orgId: Bytes!\n $orgUserID: String!\n $tokenAddress: String!\n $userAddress: Bytes!\n $quickJoinAddress: ID!\n $accountID: ID!\n $tokenBalanceID: ID!\n ) {\n organization(id: $orgId) {\n id\n name\n roles(where: { isUserRole: true }) {\n hatId\n name\n # Hats Protocol's toggle flag. When it is false, Hats.isWearerOfHat returns\n # false for EVERY wearer regardless of token balance, and the tokens are NOT\n # burned \u2014 so User.currentHatIds still lists the hat. A membership answer\n # derived from currentHatIds alone must AND it with this flag.\n hat {\n active\n }\n }\n }\n quickJoinContract(id: $quickJoinAddress) {\n id\n accountRegistry\n hatsContract\n memberHatIds\n }\n account(id: $accountID) {\n id\n username\n isDeleted\n registry {\n id\n }\n }\n tokenBalance(id: $tokenBalanceID) {\n id\n balance\n }\n user(id: $orgUserID) {\n id\n membershipStatus\n participationTokenBalance\n currentHatIds\n }\n tokenRequests(\n where: { participationToken: $tokenAddress, requester: $userAddress, status: Pending }\n first: 100\n ) {\n id\n }\n }\n";
|
|
8
|
+
/** Historical account and token snapshot; current membership is projected from the authority index. */
|
|
9
|
+
export declare const FETCH_WHOAMI_ORG_DATA = "\n query WhoamiOrgData(\n $orgId: Bytes!\n $orgUserID: String!\n $tokenAddress: String!\n $userAddress: Bytes!\n $quickJoinAddress: ID!\n $accountID: ID!\n $tokenBalanceID: ID!\n ) {\n organization(id: $orgId) {\n id\n name\n }\n quickJoinContract(id: $quickJoinAddress) {\n id\n accountRegistry\n }\n account(id: $accountID) {\n id\n username\n isDeleted\n registry {\n id\n }\n }\n tokenBalance(id: $tokenBalanceID) {\n id\n balance\n }\n user(id: $orgUserID) {\n id\n membershipStatus\n participationTokenBalance\n currentHatIds\n }\n tokenRequests(\n where: { participationToken: $tokenAddress, requester: $userAddress, status: Pending }\n first: 100\n ) {\n id\n }\n }\n";
|
|
30
10
|
/**
|
|
31
11
|
* Standalone account lookup (no org): the username + registry for one
|
|
32
12
|
* address. Account.id is the LOWERCASED address. Used by `pop user whoami`
|
|
@@ -45,12 +25,9 @@ export declare const FETCH_ACCOUNT_USERNAME = "\n query AccountUsername($accoun
|
|
|
45
25
|
* `account.registry.id === quickJoinContract.accountRegistry` — see the
|
|
46
26
|
* guard in commands/user/join.ts.
|
|
47
27
|
*/
|
|
48
|
-
export declare const FETCH_QUICKJOIN_ACCOUNT = "\n query QuickJoinAccount($quickJoinAddress: ID!, $accountID: ID!) {\n quickJoinContract(id: $quickJoinAddress) {\n id\n accountRegistry\n
|
|
49
|
-
/**
|
|
50
|
-
|
|
51
|
-
* needs before running its (deliberately on-chain) pre-flight probes.
|
|
52
|
-
*/
|
|
53
|
-
export declare const FETCH_QUICKJOIN_MODULES = "\n query QuickJoinModules($quickJoinAddress: ID!) {\n quickJoinContract(id: $quickJoinAddress) {\n id\n accountRegistry\n hatsContract\n memberHatIds\n }\n }\n";
|
|
28
|
+
export declare const FETCH_QUICKJOIN_ACCOUNT = "\n query QuickJoinAccount($quickJoinAddress: ID!, $accountID: ID!) {\n quickJoinContract(id: $quickJoinAddress) {\n id\n accountRegistry\n }\n account(id: $accountID) {\n id\n username\n isDeleted\n registry {\n id\n }\n }\n }\n";
|
|
29
|
+
/** Indexed QuickJoin account registry pointer. */
|
|
30
|
+
export declare const FETCH_QUICKJOIN_MODULES = "\n query QuickJoinModules($quickJoinAddress: ID!) {\n quickJoinContract(id: $quickJoinAddress) {\n id\n accountRegistry\n }\n }\n";
|
|
54
31
|
/**
|
|
55
32
|
* The indexed account registry plus one account's username and profile
|
|
56
33
|
* metadata, in one round-trip — everything `pop user update-profile` needs
|
|
@@ -71,8 +48,6 @@ export interface IndexedAccount {
|
|
|
71
48
|
export interface IndexedQuickJoin {
|
|
72
49
|
id: string;
|
|
73
50
|
accountRegistry: string;
|
|
74
|
-
hatsContract: string;
|
|
75
|
-
memberHatIds: string[];
|
|
76
51
|
}
|
|
77
52
|
/**
|
|
78
53
|
* True when an indexed account can stand in for a live
|
|
@@ -33,27 +33,7 @@ exports.GET_ACCOUNT_BY_USERNAME = `
|
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
35
|
`;
|
|
36
|
-
/**
|
|
37
|
-
* One-round-trip org snapshot for `pop user whoami`: org name + role-hat
|
|
38
|
-
* names, the org's QuickJoin module pointers, the caller's account
|
|
39
|
-
* (username + which registry it lives on), their ERC-20 participation-token
|
|
40
|
-
* balance, their org-user entity (membership, PT balance, hats worn), and
|
|
41
|
-
* their pending participation-token requests. The `status: Pending`
|
|
42
|
-
* filter is inlined (enum literal) to match FETCH_PENDING_TOKEN_REQUESTS
|
|
43
|
-
* in queries/token.ts.
|
|
44
|
-
*
|
|
45
|
-
* Every field here was verified NON-NULL against the live Gnosis
|
|
46
|
-
* (poa-gnosis-v-1) AND Arbitrum (poa-arb-v-1) deployments, and
|
|
47
|
-
* quickJoinContract.{accountRegistry,hatsContract,memberHatIds} were
|
|
48
|
-
* byte-compared against the matching eth_calls on both chains — including
|
|
49
|
-
* the empty-array memberHatIds case, which is genuinely empty on-chain and
|
|
50
|
-
* not an indexing gap.
|
|
51
|
-
*
|
|
52
|
-
* `account.registry` is carried so callers can prove the indexed account
|
|
53
|
-
* belongs to the SAME registry the org's QuickJoin consults before trusting
|
|
54
|
-
* the indexed username (a legacy org can point at a registry this subgraph
|
|
55
|
-
* does not index).
|
|
56
|
-
*/
|
|
36
|
+
/** Historical account and token snapshot; current membership is projected from the authority index. */
|
|
57
37
|
exports.FETCH_WHOAMI_ORG_DATA = `
|
|
58
38
|
query WhoamiOrgData(
|
|
59
39
|
$orgId: Bytes!
|
|
@@ -67,23 +47,10 @@ exports.FETCH_WHOAMI_ORG_DATA = `
|
|
|
67
47
|
organization(id: $orgId) {
|
|
68
48
|
id
|
|
69
49
|
name
|
|
70
|
-
roles(where: { isUserRole: true }) {
|
|
71
|
-
hatId
|
|
72
|
-
name
|
|
73
|
-
# Hats Protocol's toggle flag. When it is false, Hats.isWearerOfHat returns
|
|
74
|
-
# false for EVERY wearer regardless of token balance, and the tokens are NOT
|
|
75
|
-
# burned — so User.currentHatIds still lists the hat. A membership answer
|
|
76
|
-
# derived from currentHatIds alone must AND it with this flag.
|
|
77
|
-
hat {
|
|
78
|
-
active
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
50
|
}
|
|
82
51
|
quickJoinContract(id: $quickJoinAddress) {
|
|
83
52
|
id
|
|
84
53
|
accountRegistry
|
|
85
|
-
hatsContract
|
|
86
|
-
memberHatIds
|
|
87
54
|
}
|
|
88
55
|
account(id: $accountID) {
|
|
89
56
|
id
|
|
@@ -145,8 +112,6 @@ exports.FETCH_QUICKJOIN_ACCOUNT = `
|
|
|
145
112
|
quickJoinContract(id: $quickJoinAddress) {
|
|
146
113
|
id
|
|
147
114
|
accountRegistry
|
|
148
|
-
hatsContract
|
|
149
|
-
memberHatIds
|
|
150
115
|
}
|
|
151
116
|
account(id: $accountID) {
|
|
152
117
|
id
|
|
@@ -158,17 +123,12 @@ exports.FETCH_QUICKJOIN_ACCOUNT = `
|
|
|
158
123
|
}
|
|
159
124
|
}
|
|
160
125
|
`;
|
|
161
|
-
/**
|
|
162
|
-
* Just the QuickJoin module pointers — the addresses `pop user claim-hats`
|
|
163
|
-
* needs before running its (deliberately on-chain) pre-flight probes.
|
|
164
|
-
*/
|
|
126
|
+
/** Indexed QuickJoin account registry pointer. */
|
|
165
127
|
exports.FETCH_QUICKJOIN_MODULES = `
|
|
166
128
|
query QuickJoinModules($quickJoinAddress: ID!) {
|
|
167
129
|
quickJoinContract(id: $quickJoinAddress) {
|
|
168
130
|
id
|
|
169
131
|
accountRegistry
|
|
170
|
-
hatsContract
|
|
171
|
-
memberHatIds
|
|
172
132
|
}
|
|
173
133
|
}
|
|
174
134
|
`;
|
|
@@ -34,14 +34,22 @@ export declare const FETCH_VOTING_CLASS_CONFIG = "\n query FetchVotingClassConf
|
|
|
34
34
|
*/
|
|
35
35
|
export declare const FETCH_VOTING_CLASS_CONFIG_LEGACY = "\n query FetchVotingClassConfigLegacy($hybridVoting: ID!) {\n hybridVotingContract(id: $hybridVoting) {\n id\n thresholdPct\n quorum\n votingClasses(first: 1000) {\n version\n classIndex\n strategy\n slicePct\n quadratic\n minBalance\n asset\n hatIds\n isActive\n }\n }\n }\n";
|
|
36
36
|
/** Class snapshot frozen for one proposal + threshold/quorum. Single tier. */
|
|
37
|
-
export declare const FETCH_PROPOSAL_VOTING_CLASSES = "\n query FetchProposalVotingClasses($hybridVoting: ID!, $proposalId: BigInt!) {\n hybridVotingContract(id: $hybridVoting) {\n id\n thresholdPct\n quorum\n proposals(where: { proposalId: $proposalId }) {\n proposalId\n classesVersion\n }\n votingClasses(first: 1000) {\n version\n classIndex\n strategy\n slicePct\n quadratic\n minBalance\n asset\n hatIds\n isActive\n }\n }\n }\n";
|
|
37
|
+
export declare const FETCH_PROPOSAL_VOTING_CLASSES = "\n query FetchProposalVotingClasses($hybridVoting: ID!, $proposalId: BigInt!) {\n hybridVotingContract(id: $hybridVoting) {\n id\n thresholdPct\n quorum\n proposals(where: { proposalId: $proposalId }) {\n proposalId\n classesVersion\n isHatRestricted\n }\n votingClasses(first: 1000) {\n version\n classIndex\n strategy\n slicePct\n quadratic\n minBalance\n asset\n hatIds\n isActive\n }\n }\n }\n";
|
|
38
38
|
/**
|
|
39
39
|
* Everything `pop vote analyze` needs in ONE round-trip: the frozen class
|
|
40
40
|
* snapshot, every ballot with its per-class raw power (Vote.classRawPowers is
|
|
41
41
|
* the exact quantity the command used to reconstruct from VoteCast logs), and
|
|
42
42
|
* the org's username map for display names.
|
|
43
43
|
*/
|
|
44
|
-
export declare const FETCH_PROPOSAL_VOTE_ANALYSIS = "\n query FetchProposalVoteAnalysis($hybridVoting: ID!, $proposalId: BigInt
|
|
44
|
+
export declare const FETCH_PROPOSAL_VOTE_ANALYSIS = "\n query FetchProposalVoteAnalysis($hybridVoting: ID!, $proposalId: BigInt!, $after: String = \"\") {\n hybridVotingContract(id: $hybridVoting) {\n id\n organization {\n id\n users(first: 100) {\n address\n account { username }\n }\n }\n proposals(where: { proposalId: $proposalId }) {\n proposalId\n numOptions\n classesVersion\n isHatRestricted\n votes(first: 1000, orderBy: id, orderDirection: asc, where: { id_gt: $after }) {\n id\n voter\n voterUsername\n optionIndexes\n optionWeights\n classRawPowers\n }\n }\n votingClasses(first: 1000) {\n version\n classIndex\n strategy\n slicePct\n quadratic\n minBalance\n asset\n hatIds\n isActive\n }\n }\n }\n";
|
|
45
|
+
export declare const FETCH_VOTING_CLASS_CONFIG_EXACT = "\n query FetchVotingClassConfigExact($hybridVoting: ID!) {\n hybridVotingContract(id: $hybridVoting) {\n id thresholdPct quorum classVersion classesChange {\n id numClasses\n votingClasses(first: 8, orderBy: classIndex, orderDirection: asc) {\n version\n classIndex\n strategy\n slicePct\n quadratic\n minBalance\n asset\n hatIds\n isActive\n }\n}\n }\n }\n";
|
|
46
|
+
export declare const FETCH_PROPOSAL_VOTING_CLASSES_EXACT = "\n query FetchProposalVotingClassesExact($hybridVoting: ID!, $proposalId: BigInt!) {\n hybridVotingContract(id: $hybridVoting) {\n id thresholdPct quorum\n proposals(where: { proposalId: $proposalId }, first: 1) {\n proposalId classesVersion isHatRestricted classesChange {\n id numClasses\n votingClasses(first: 8, orderBy: classIndex, orderDirection: asc) {\n version\n classIndex\n strategy\n slicePct\n quadratic\n minBalance\n asset\n hatIds\n isActive\n }\n}\n }\n }\n }\n";
|
|
47
|
+
export declare const FETCH_PROPOSAL_VOTE_ANALYSIS_EXACT: string;
|
|
48
|
+
/**
|
|
49
|
+
* Select one complete, unambiguous class emission. Restricted polls can use a
|
|
50
|
+
* synthetic V2 class which is still absent from the index; refuse that guess.
|
|
51
|
+
*/
|
|
52
|
+
export declare function selectIndexedClassSnapshot(contract: any, proposalId?: number): SubgraphVotingClass[];
|
|
45
53
|
/** One VotingClass row as returned by the subgraph (all scalars are strings/numbers). */
|
|
46
54
|
export interface SubgraphVotingClass {
|
|
47
55
|
version: string;
|
|
@@ -63,6 +71,19 @@ export interface SubgraphVotingClass {
|
|
|
63
71
|
* version wins, which reproduces getClasses() but must NEVER be used to
|
|
64
72
|
* reconstruct an old proposal's frozen snapshot.
|
|
65
73
|
*
|
|
74
|
+
* `isActive` deliberately does NOT filter the version-pinned path. It means
|
|
75
|
+
* "belongs to the config that is live right now", so a proposal created under
|
|
76
|
+
* a since-replaced config has an entirely inactive snapshot — filtering on it
|
|
77
|
+
* first would drop every row and report "no answer" for exactly the proposals
|
|
78
|
+
* the snapshot machinery exists to serve. It is only used to pick a version
|
|
79
|
+
* when the caller has none, and to break the ambiguity below.
|
|
80
|
+
*
|
|
81
|
+
* `version` is the contract's `block.number`, not a per-setClasses id, so it is
|
|
82
|
+
* not unique: two setClasses share it in one block on Gnosis, and on Arbitrum
|
|
83
|
+
* `block.number` is the L1 block, which spans ~48 indexed L2 blocks. When two
|
|
84
|
+
* emissions share a version their classIndex values repeat; summing them would
|
|
85
|
+
* yield slice percentages over 100.
|
|
86
|
+
*
|
|
66
87
|
* Returns [] when nothing matches, which callers treat as "subgraph can't
|
|
67
88
|
* answer this" and fall back to the contract.
|
|
68
89
|
*/
|
|
@@ -26,7 +26,8 @@
|
|
|
26
26
|
* falling back to the on-chain getProposalClasses call.
|
|
27
27
|
*/
|
|
28
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
-
exports.FETCH_PROPOSAL_VOTE_ANALYSIS = exports.FETCH_PROPOSAL_VOTING_CLASSES = exports.FETCH_VOTING_CLASS_CONFIG_LEGACY = exports.FETCH_VOTING_CLASS_CONFIG = void 0;
|
|
29
|
+
exports.FETCH_PROPOSAL_VOTE_ANALYSIS_EXACT = exports.FETCH_PROPOSAL_VOTING_CLASSES_EXACT = exports.FETCH_VOTING_CLASS_CONFIG_EXACT = exports.FETCH_PROPOSAL_VOTE_ANALYSIS = exports.FETCH_PROPOSAL_VOTING_CLASSES = exports.FETCH_VOTING_CLASS_CONFIG_LEGACY = exports.FETCH_VOTING_CLASS_CONFIG = void 0;
|
|
30
|
+
exports.selectIndexedClassSnapshot = selectIndexedClassSnapshot;
|
|
30
31
|
exports.selectClassSnapshot = selectClassSnapshot;
|
|
31
32
|
/** Field set shared by every VotingClass selection. */
|
|
32
33
|
const VOTING_CLASS_FIELDS = `
|
|
@@ -79,6 +80,7 @@ exports.FETCH_PROPOSAL_VOTING_CLASSES = `
|
|
|
79
80
|
proposals(where: { proposalId: $proposalId }) {
|
|
80
81
|
proposalId
|
|
81
82
|
classesVersion
|
|
83
|
+
isHatRestricted
|
|
82
84
|
}
|
|
83
85
|
votingClasses(first: 1000) {${VOTING_CLASS_FIELDS}
|
|
84
86
|
}
|
|
@@ -92,7 +94,7 @@ exports.FETCH_PROPOSAL_VOTING_CLASSES = `
|
|
|
92
94
|
* the org's username map for display names.
|
|
93
95
|
*/
|
|
94
96
|
exports.FETCH_PROPOSAL_VOTE_ANALYSIS = `
|
|
95
|
-
query FetchProposalVoteAnalysis($hybridVoting: ID!, $proposalId: BigInt
|
|
97
|
+
query FetchProposalVoteAnalysis($hybridVoting: ID!, $proposalId: BigInt!, $after: String = "") {
|
|
96
98
|
hybridVotingContract(id: $hybridVoting) {
|
|
97
99
|
id
|
|
98
100
|
organization {
|
|
@@ -104,8 +106,11 @@ exports.FETCH_PROPOSAL_VOTE_ANALYSIS = `
|
|
|
104
106
|
}
|
|
105
107
|
proposals(where: { proposalId: $proposalId }) {
|
|
106
108
|
proposalId
|
|
109
|
+
numOptions
|
|
107
110
|
classesVersion
|
|
108
|
-
|
|
111
|
+
isHatRestricted
|
|
112
|
+
votes(first: 1000, orderBy: id, orderDirection: asc, where: { id_gt: $after }) {
|
|
113
|
+
id
|
|
109
114
|
voter
|
|
110
115
|
voterUsername
|
|
111
116
|
optionIndexes
|
|
@@ -118,6 +123,75 @@ exports.FETCH_PROPOSAL_VOTE_ANALYSIS = `
|
|
|
118
123
|
}
|
|
119
124
|
}
|
|
120
125
|
`;
|
|
126
|
+
/** Exact per-emission joins are populated by current subgraphs on both supported chains. */
|
|
127
|
+
const CLASS_CHANGE_FIELDS = `classesChange {
|
|
128
|
+
id numClasses
|
|
129
|
+
votingClasses(first: 8, orderBy: classIndex, orderDirection: asc) {${VOTING_CLASS_FIELDS}
|
|
130
|
+
}
|
|
131
|
+
}`;
|
|
132
|
+
exports.FETCH_VOTING_CLASS_CONFIG_EXACT = `
|
|
133
|
+
query FetchVotingClassConfigExact($hybridVoting: ID!) {
|
|
134
|
+
hybridVotingContract(id: $hybridVoting) {
|
|
135
|
+
id thresholdPct quorum classVersion ${CLASS_CHANGE_FIELDS}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
`;
|
|
139
|
+
exports.FETCH_PROPOSAL_VOTING_CLASSES_EXACT = `
|
|
140
|
+
query FetchProposalVotingClassesExact($hybridVoting: ID!, $proposalId: BigInt!) {
|
|
141
|
+
hybridVotingContract(id: $hybridVoting) {
|
|
142
|
+
id thresholdPct quorum
|
|
143
|
+
proposals(where: { proposalId: $proposalId }, first: 1) {
|
|
144
|
+
proposalId classesVersion isHatRestricted ${CLASS_CHANGE_FIELDS}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
`;
|
|
149
|
+
exports.FETCH_PROPOSAL_VOTE_ANALYSIS_EXACT = exports.FETCH_PROPOSAL_VOTE_ANALYSIS
|
|
150
|
+
.replace('classesVersion', `classesVersion ${CLASS_CHANGE_FIELDS}`)
|
|
151
|
+
.replace(`votingClasses(first: 1000) {${VOTING_CLASS_FIELDS}
|
|
152
|
+
}`, '');
|
|
153
|
+
/**
|
|
154
|
+
* Select one complete, unambiguous class emission. Restricted polls can use a
|
|
155
|
+
* synthetic V2 class which is still absent from the index; refuse that guess.
|
|
156
|
+
*/
|
|
157
|
+
function selectIndexedClassSnapshot(contract, proposalId) {
|
|
158
|
+
const holder = proposalId === undefined ? contract : contract?.proposals?.[0];
|
|
159
|
+
if (!holder)
|
|
160
|
+
return [];
|
|
161
|
+
if (proposalId !== undefined && holder.isHatRestricted !== false)
|
|
162
|
+
return [];
|
|
163
|
+
if (holder.classesChange !== undefined) {
|
|
164
|
+
const change = holder.classesChange;
|
|
165
|
+
const rows = change?.votingClasses ?? [];
|
|
166
|
+
if (!change || rows.length !== Number(change.numClasses) || rows.length === 0 || rows.length > 8)
|
|
167
|
+
return [];
|
|
168
|
+
const sorted = [...rows].sort((a, b) => Number(a.classIndex) - Number(b.classIndex));
|
|
169
|
+
if (sorted.some((r, i) => Number(r.classIndex) !== i))
|
|
170
|
+
return [];
|
|
171
|
+
return sorted;
|
|
172
|
+
}
|
|
173
|
+
const version = proposalId === undefined ? contract.classVersion : holder.classesVersion;
|
|
174
|
+
if (proposalId !== undefined && version == null)
|
|
175
|
+
return [];
|
|
176
|
+
// A full legacy history page could omit any requested emission or some of
|
|
177
|
+
// its classes. Never infer a complete snapshot from a truncated history.
|
|
178
|
+
if ((contract.votingClasses?.length ?? 0) >= 1000)
|
|
179
|
+
return [];
|
|
180
|
+
const rows = selectClassSnapshot(contract.votingClasses, version);
|
|
181
|
+
return rows.length > 0 && rows.length <= 8 && rows.every((r, i) => Number(r.classIndex) === i)
|
|
182
|
+
&& rows.reduce((total, r) => total + Number(r.slicePct), 0) === 100 ? rows : [];
|
|
183
|
+
}
|
|
184
|
+
/** True when two rows claim the same classIndex, i.e. two configs are mixed together. */
|
|
185
|
+
function hasRepeatedClassIndex(rows) {
|
|
186
|
+
const seen = new Set();
|
|
187
|
+
for (const r of rows) {
|
|
188
|
+
const i = Number(r.classIndex);
|
|
189
|
+
if (seen.has(i))
|
|
190
|
+
return true;
|
|
191
|
+
seen.add(i);
|
|
192
|
+
}
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
121
195
|
/**
|
|
122
196
|
* Pick the class rows belonging to one config version and order them by
|
|
123
197
|
* classIndex (the on-chain array order the whole slice/quorum math assumes).
|
|
@@ -127,23 +201,58 @@ exports.FETCH_PROPOSAL_VOTE_ANALYSIS = `
|
|
|
127
201
|
* version wins, which reproduces getClasses() but must NEVER be used to
|
|
128
202
|
* reconstruct an old proposal's frozen snapshot.
|
|
129
203
|
*
|
|
204
|
+
* `isActive` deliberately does NOT filter the version-pinned path. It means
|
|
205
|
+
* "belongs to the config that is live right now", so a proposal created under
|
|
206
|
+
* a since-replaced config has an entirely inactive snapshot — filtering on it
|
|
207
|
+
* first would drop every row and report "no answer" for exactly the proposals
|
|
208
|
+
* the snapshot machinery exists to serve. It is only used to pick a version
|
|
209
|
+
* when the caller has none, and to break the ambiguity below.
|
|
210
|
+
*
|
|
211
|
+
* `version` is the contract's `block.number`, not a per-setClasses id, so it is
|
|
212
|
+
* not unique: two setClasses share it in one block on Gnosis, and on Arbitrum
|
|
213
|
+
* `block.number` is the L1 block, which spans ~48 indexed L2 blocks. When two
|
|
214
|
+
* emissions share a version their classIndex values repeat; summing them would
|
|
215
|
+
* yield slice percentages over 100.
|
|
216
|
+
*
|
|
130
217
|
* Returns [] when nothing matches, which callers treat as "subgraph can't
|
|
131
218
|
* answer this" and fall back to the contract.
|
|
132
219
|
*/
|
|
133
220
|
function selectClassSnapshot(rows, version) {
|
|
134
|
-
const
|
|
135
|
-
if (active.length === 0)
|
|
136
|
-
return [];
|
|
221
|
+
const all = (rows ?? []).filter(r => !!r);
|
|
137
222
|
let target = version === null || version === undefined ? null : String(version);
|
|
138
223
|
if (target === null) {
|
|
139
|
-
|
|
224
|
+
// Nothing pins the version, so the live rows are the only ones that identify
|
|
225
|
+
// the current config. Versions are block numbers and exceed 2^53 on some
|
|
226
|
+
// chains, so this comparison must not go through Number.
|
|
227
|
+
target = all
|
|
228
|
+
.filter(r => r.isActive !== false)
|
|
229
|
+
.reduce((max, r) => {
|
|
140
230
|
const v = String(r.version);
|
|
141
231
|
if (max === null)
|
|
142
232
|
return v;
|
|
143
233
|
return BigInt(v) > BigInt(max) ? v : max;
|
|
144
234
|
}, null);
|
|
235
|
+
if (target === null)
|
|
236
|
+
return [];
|
|
237
|
+
}
|
|
238
|
+
let matched = all.filter(r => String(r.version) === target);
|
|
239
|
+
if (hasRepeatedClassIndex(matched)) {
|
|
240
|
+
// Two emissions share this version. The live one is still identifiable; a
|
|
241
|
+
// superseded one is not, without the per-emission pointer newer subgraphs
|
|
242
|
+
// expose. Blending them would report slices summing past 100, so say
|
|
243
|
+
// nothing and leave it to the caller's contract fallback. That fallback is
|
|
244
|
+
// not always free — `vote analyze` re-derives voters from a ~200k-block
|
|
245
|
+
// VoteCast window and throws for older proposals — but a wrong tally is
|
|
246
|
+
// worse than a loud one, and this path is unreachable until two setClasses
|
|
247
|
+
// land on one version.
|
|
248
|
+
// With a pinned version the live emission may be newer than the proposal.
|
|
249
|
+
// Only the exact classesChange pointer can disambiguate it.
|
|
250
|
+
if (version !== null && version !== undefined)
|
|
251
|
+
return [];
|
|
252
|
+
const live = matched.filter(r => r.isActive !== false);
|
|
253
|
+
if (live.length === 0 || hasRepeatedClassIndex(live))
|
|
254
|
+
return [];
|
|
255
|
+
matched = live;
|
|
145
256
|
}
|
|
146
|
-
return
|
|
147
|
-
.filter(r => String(r.version) === target)
|
|
148
|
-
.sort((a, b) => Number(a.classIndex) - Number(b.classIndex));
|
|
257
|
+
return matched.sort((a, b) => Number(a.classIndex) - Number(b.classIndex));
|
|
149
258
|
}
|
package/dist/metadata/index.d.ts
CHANGED
package/dist/metadata/index.js
CHANGED
|
@@ -38,11 +38,10 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
38
38
|
};
|
|
39
39
|
})();
|
|
40
40
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
|
-
exports.user = exports.token = exports.task = exports.
|
|
41
|
+
exports.user = exports.token = exports.task = exports.proposal = exports.org = exports.education = void 0;
|
|
42
42
|
exports.education = __importStar(require("./education"));
|
|
43
43
|
exports.org = __importStar(require("./org"));
|
|
44
44
|
exports.proposal = __importStar(require("./proposal"));
|
|
45
|
-
exports.role = __importStar(require("./role"));
|
|
46
45
|
exports.task = __importStar(require("./task"));
|
|
47
46
|
exports.token = __importStar(require("./token"));
|
|
48
47
|
exports.user = __importStar(require("./user"));
|
package/dist/perms.d.ts
CHANGED
|
@@ -30,18 +30,3 @@ export declare function formatMask(mask: number): string;
|
|
|
30
30
|
* Unknown bits render as 'unknown permission (bitN)'.
|
|
31
31
|
*/
|
|
32
32
|
export declare function describeMask(mask: number): string[];
|
|
33
|
-
/**
|
|
34
|
-
* EligibilityModule vouch-config flag bits (EligibilityModule.sol:156-157).
|
|
35
|
-
* Packed into the `flags` byte of the VouchConfig tuple returned by getVouchConfig.
|
|
36
|
-
*/
|
|
37
|
-
export declare const VOUCH_FLAG_ENABLED = 1;
|
|
38
|
-
export declare const VOUCH_FLAG_COMBINE_HIERARCHY = 2;
|
|
39
|
-
/**
|
|
40
|
-
* Would enabling vouching and default-eligibility on the same hat conflict?
|
|
41
|
-
*
|
|
42
|
-
* Audit M-03 made these mutually exclusive in BOTH directions: a hat that everyone is eligible
|
|
43
|
-
* for by default makes a vouch quorum a no-op, so the contract reverts
|
|
44
|
-
* DefaultEligibilityConflictsWithVouch. The guard only fires when vouching is enabled AND
|
|
45
|
-
* combineWithHierarchy is set — vouching alone, or without combine, is fine.
|
|
46
|
-
*/
|
|
47
|
-
export declare function vouchConflictsWithDefaultEligibility(vouchFlags: number, vouchQuorum: number, defaultEligible: boolean): boolean;
|