@poa-box/core 0.1.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 +201 -0
- package/dist/abis/DirectDemocracyVotingNew.d.ts +749 -0
- package/dist/abis/DirectDemocracyVotingNew.js +961 -0
- package/dist/abis/ERC20.d.ts +90 -0
- package/dist/abis/ERC20.js +125 -0
- package/dist/abis/EducationHubNew.d.ts +590 -0
- package/dist/abis/EducationHubNew.js +762 -0
- package/dist/abis/EligibilityModuleNew.d.ts +1615 -0
- package/dist/abis/EligibilityModuleNew.js +2082 -0
- package/dist/abis/Executor.d.ts +619 -0
- package/dist/abis/Executor.js +796 -0
- package/dist/abis/HybridVotingNew.d.ts +898 -0
- package/dist/abis/HybridVotingNew.js +1149 -0
- package/dist/abis/ImplementationRegistry.d.ts +270 -0
- package/dist/abis/ImplementationRegistry.js +355 -0
- package/dist/abis/OrgDeployerNew.d.ts +1275 -0
- package/dist/abis/OrgDeployerNew.js +1630 -0
- package/dist/abis/OrgRegistry.d.ts +670 -0
- package/dist/abis/OrgRegistry.js +868 -0
- package/dist/abis/ParticipationToken.d.ts +1086 -0
- package/dist/abis/ParticipationToken.js +1415 -0
- package/dist/abis/PasskeyAccount.d.ts +788 -0
- package/dist/abis/PasskeyAccount.js +1019 -0
- package/dist/abis/PasskeyAccountFactory.d.ts +344 -0
- package/dist/abis/PasskeyAccountFactory.js +449 -0
- package/dist/abis/PaymasterHub.d.ts +1603 -0
- package/dist/abis/PaymasterHub.js +2048 -0
- package/dist/abis/PaymentManager.d.ts +520 -0
- package/dist/abis/PaymentManager.js +671 -0
- package/dist/abis/PoaManager.d.ts +344 -0
- package/dist/abis/PoaManager.js +449 -0
- package/dist/abis/QuickJoinNew.d.ts +855 -0
- package/dist/abis/QuickJoinNew.js +1098 -0
- package/dist/abis/TaskManagerNew.d.ts +1236 -0
- package/dist/abis/TaskManagerNew.js +1573 -0
- package/dist/abis/ToggleModule.d.ts +193 -0
- package/dist/abis/ToggleModule.js +255 -0
- package/dist/abis/UniversalAccountRegistry.d.ts +577 -0
- package/dist/abis/UniversalAccountRegistry.js +750 -0
- package/dist/abis/ZkEmailInvites.d.ts +823 -0
- package/dist/abis/ZkEmailInvites.js +1060 -0
- package/dist/abis/external/AaveGovernanceV2.d.ts +128 -0
- package/dist/abis/external/AaveGovernanceV2.js +177 -0
- package/dist/abis/external/AaveGovernanceV3.d.ts +160 -0
- package/dist/abis/external/AaveGovernanceV3.js +220 -0
- package/dist/abis/external/AragonVoting.d.ts +107 -0
- package/dist/abis/external/AragonVoting.js +150 -0
- package/dist/abis/external/CurveGaugeController.d.ts +95 -0
- package/dist/abis/external/CurveGaugeController.js +130 -0
- package/dist/abis/external/CurveVotingEscrow.d.ts +86 -0
- package/dist/abis/external/CurveVotingEscrow.js +116 -0
- package/dist/abis/external/GovernorAlpha.d.ts +172 -0
- package/dist/abis/external/GovernorAlpha.js +228 -0
- package/dist/abis/external/MakerDAOChief.d.ts +92 -0
- package/dist/abis/external/MakerDAOChief.js +129 -0
- package/dist/abis/external/OZGovernor.d.ts +227 -0
- package/dist/abis/external/OZGovernor.js +317 -0
- package/dist/abis/external/SolidlyVotingEscrow.d.ts +196 -0
- package/dist/abis/external/SolidlyVotingEscrow.js +260 -0
- package/dist/abis/index.d.ts +62 -0
- package/dist/abis/index.js +98 -0
- package/dist/chains.d.ts +150 -0
- package/dist/chains.js +320 -0
- package/dist/context.d.ts +48 -0
- package/dist/context.js +38 -0
- package/dist/contracts.d.ts +24 -0
- package/dist/contracts.js +41 -0
- package/dist/encoding.d.ts +58 -0
- package/dist/encoding.js +243 -0
- package/dist/env.d.ts +10 -0
- package/dist/env.js +4 -0
- package/dist/error-catalog.d.ts +41 -0
- package/dist/error-catalog.js +941 -0
- package/dist/errors.d.ts +27 -0
- package/dist/errors.js +60 -0
- package/dist/execute/ethers.d.ts +93 -0
- package/dist/execute/ethers.js +323 -0
- package/dist/execute/index.d.ts +7 -0
- package/dist/execute/index.js +23 -0
- package/dist/execute/sponsored.d.ts +68 -0
- package/dist/execute/sponsored.js +277 -0
- package/dist/exit-codes.d.ts +18 -0
- package/dist/exit-codes.js +21 -0
- package/dist/format.d.ts +21 -0
- package/dist/format.js +89 -0
- package/dist/graph/client.d.ts +298 -0
- package/dist/graph/client.js +702 -0
- package/dist/graph/documents/activity.d.ts +9 -0
- package/dist/graph/documents/activity.js +164 -0
- package/dist/graph/documents/beacons.d.ts +172 -0
- package/dist/graph/documents/beacons.js +345 -0
- package/dist/graph/documents/index.d.ts +21 -0
- package/dist/graph/documents/index.js +57 -0
- package/dist/graph/documents/infrastructure.d.ts +30 -0
- package/dist/graph/documents/infrastructure.js +34 -0
- package/dist/graph/documents/org.d.ts +15 -0
- package/dist/graph/documents/org.js +249 -0
- package/dist/graph/documents/paymaster.d.ts +95 -0
- package/dist/graph/documents/paymaster.js +101 -0
- package/dist/graph/documents/role.d.ts +6 -0
- package/dist/graph/documents/role.js +41 -0
- package/dist/graph/documents/roles.d.ts +50 -0
- package/dist/graph/documents/roles.js +112 -0
- package/dist/graph/documents/task.d.ts +84 -0
- package/dist/graph/documents/task.js +236 -0
- package/dist/graph/documents/token.d.ts +13 -0
- package/dist/graph/documents/token.js +126 -0
- package/dist/graph/documents/treasury.d.ts +39 -0
- package/dist/graph/documents/treasury.js +136 -0
- package/dist/graph/documents/user.d.ts +120 -0
- package/dist/graph/documents/user.js +302 -0
- package/dist/graph/documents/voting-classes.d.ts +69 -0
- package/dist/graph/documents/voting-classes.js +149 -0
- package/dist/graph/documents/voting.d.ts +28 -0
- package/dist/graph/documents/voting.js +163 -0
- package/dist/graph/documents/vouch.d.ts +79 -0
- package/dist/graph/documents/vouch.js +171 -0
- package/dist/graph/documents/zkemail.d.ts +63 -0
- package/dist/graph/documents/zkemail.js +188 -0
- package/dist/graph/index.d.ts +2 -0
- package/dist/graph/index.js +41 -0
- package/dist/index.d.ts +49 -0
- package/dist/index.js +92 -0
- package/dist/ipfs.d.ts +39 -0
- package/dist/ipfs.js +214 -0
- package/dist/label-aliases.d.ts +31 -0
- package/dist/label-aliases.js +70 -0
- package/dist/metadata/education.d.ts +30 -0
- package/dist/metadata/education.js +31 -0
- package/dist/metadata/index.d.ts +12 -0
- package/dist/metadata/index.js +48 -0
- package/dist/metadata/org.d.ts +92 -0
- package/dist/metadata/org.js +93 -0
- package/dist/metadata/proposal.d.ts +44 -0
- package/dist/metadata/proposal.js +45 -0
- package/dist/metadata/role.d.ts +38 -0
- package/dist/metadata/role.js +35 -0
- package/dist/metadata/task.d.ts +108 -0
- package/dist/metadata/task.js +81 -0
- package/dist/metadata/token.d.ts +32 -0
- package/dist/metadata/token.js +36 -0
- package/dist/metadata/user.d.ts +63 -0
- package/dist/metadata/user.js +70 -0
- package/dist/multicall.d.ts +32 -0
- package/dist/multicall.js +96 -0
- package/dist/payout.d.ts +59 -0
- package/dist/payout.js +96 -0
- package/dist/perms.d.ts +47 -0
- package/dist/perms.js +120 -0
- package/dist/preflight.d.ts +72 -0
- package/dist/preflight.js +269 -0
- package/dist/reads/education.d.ts +79 -0
- package/dist/reads/education.js +122 -0
- package/dist/reads/eligibility.d.ts +377 -0
- package/dist/reads/eligibility.js +687 -0
- package/dist/reads/index.d.ts +16 -0
- package/dist/reads/index.js +55 -0
- package/dist/reads/org.d.ts +258 -0
- package/dist/reads/org.js +220 -0
- package/dist/reads/paymaster.d.ts +147 -0
- package/dist/reads/paymaster.js +235 -0
- package/dist/reads/project.d.ts +33 -0
- package/dist/reads/project.js +62 -0
- package/dist/reads/resolve.d.ts +34 -0
- package/dist/reads/resolve.js +64 -0
- package/dist/reads/task.d.ts +286 -0
- package/dist/reads/task.js +280 -0
- package/dist/reads/token.d.ts +94 -0
- package/dist/reads/token.js +75 -0
- package/dist/reads/treasury.d.ts +222 -0
- package/dist/reads/treasury.js +241 -0
- package/dist/reads/user.d.ts +229 -0
- package/dist/reads/user.js +155 -0
- package/dist/reads/vote.d.ts +296 -0
- package/dist/reads/vote.js +392 -0
- package/dist/reads/zkemail.d.ts +117 -0
- package/dist/reads/zkemail.js +217 -0
- package/dist/similarity.d.ts +36 -0
- package/dist/similarity.js +67 -0
- package/dist/sponsorship-config.d.ts +47 -0
- package/dist/sponsorship-config.js +41 -0
- package/dist/stats.d.ts +11 -0
- package/dist/stats.js +27 -0
- package/dist/task-lens.d.ts +113 -0
- package/dist/task-lens.js +210 -0
- package/dist/tx/education.d.ts +169 -0
- package/dist/tx/education.js +344 -0
- package/dist/tx/eligibility.d.ts +511 -0
- package/dist/tx/eligibility.js +818 -0
- package/dist/tx/governance.d.ts +85 -0
- package/dist/tx/governance.js +87 -0
- package/dist/tx/index.d.ts +17 -0
- package/dist/tx/index.js +56 -0
- package/dist/tx/intent.d.ts +67 -0
- package/dist/tx/intent.js +48 -0
- package/dist/tx/org.d.ts +321 -0
- package/dist/tx/org.js +544 -0
- package/dist/tx/paymaster.d.ts +140 -0
- package/dist/tx/paymaster.js +251 -0
- package/dist/tx/project.d.ts +146 -0
- package/dist/tx/project.js +217 -0
- package/dist/tx/task.d.ts +480 -0
- package/dist/tx/task.js +1149 -0
- package/dist/tx/token.d.ts +96 -0
- package/dist/tx/token.js +165 -0
- package/dist/tx/treasury.d.ts +474 -0
- package/dist/tx/treasury.js +911 -0
- package/dist/tx/user.d.ts +177 -0
- package/dist/tx/user.js +292 -0
- package/dist/tx/vote.d.ts +332 -0
- package/dist/tx/vote.js +762 -0
- package/dist/tx/zkemail.d.ts +90 -0
- package/dist/tx/zkemail.js +210 -0
- package/dist/validation.d.ts +8 -0
- package/dist/validation.js +39 -0
- package/dist/version.d.ts +142 -0
- package/dist/version.js +257 -0
- package/dist/zkemail.d.ts +161 -0
- package/dist/zkemail.js +299 -0
- package/package.json +130 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* User & Account Queries
|
|
3
|
+
* Ported from frontend queries.js
|
|
4
|
+
*/
|
|
5
|
+
import type { FieldFallbackTier } from '../client';
|
|
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
|
+
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
|
+
* One-round-trip org snapshot for `pop user whoami`: org name + role-hat
|
|
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";
|
|
30
|
+
/**
|
|
31
|
+
* Standalone account lookup (no org): the username + registry for one
|
|
32
|
+
* address. Account.id is the LOWERCASED address. Used by `pop user whoami`
|
|
33
|
+
* when no org is configured — the username is home-chain account-registry
|
|
34
|
+
* state, so this runs against the home-chain subgraph instead of building a
|
|
35
|
+
* second JsonRpcProvider just to call getUsername.
|
|
36
|
+
*/
|
|
37
|
+
export declare const FETCH_ACCOUNT_USERNAME = "\n query AccountUsername($accountID: ID!) {\n account(id: $accountID) {\n id\n username\n isDeleted\n registry {\n id\n }\n }\n }\n";
|
|
38
|
+
/**
|
|
39
|
+
* The org QuickJoin's module pointers plus the caller's account, in one
|
|
40
|
+
* round-trip. `pop user join` needs both: the registry QuickJoin consults
|
|
41
|
+
* (registering anywhere else leaves quickJoinWithUser reverting NoUsername)
|
|
42
|
+
* and whether a username already exists (1-tx vs 2-tx flow).
|
|
43
|
+
*
|
|
44
|
+
* The account is only trustworthy for that decision when
|
|
45
|
+
* `account.registry.id === quickJoinContract.accountRegistry` — see the
|
|
46
|
+
* guard in commands/user/join.ts.
|
|
47
|
+
*/
|
|
48
|
+
export declare const FETCH_QUICKJOIN_ACCOUNT = "\n query QuickJoinAccount($quickJoinAddress: ID!, $accountID: ID!) {\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 }\n";
|
|
49
|
+
/**
|
|
50
|
+
* Just the QuickJoin module pointers — the addresses `pop user claim-hats`
|
|
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";
|
|
54
|
+
/**
|
|
55
|
+
* The indexed account registry plus one account's username and profile
|
|
56
|
+
* metadata, in one round-trip — everything `pop user update-profile` needs
|
|
57
|
+
* before it writes. Replaces two separate subgraph queries plus a
|
|
58
|
+
* getUsername eth_call.
|
|
59
|
+
*/
|
|
60
|
+
export declare const FETCH_REGISTRY_AND_ACCOUNT = "\n query RegistryAndAccount($accountID: ID!) {\n universalAccountRegistries(first: 1) {\n id\n }\n account(id: $accountID) {\n id\n username\n isDeleted\n metadata {\n bio\n avatar\n github\n twitter\n website\n }\n }\n }\n";
|
|
61
|
+
/** Shape of the `account` selection shared by the queries above. */
|
|
62
|
+
export interface IndexedAccount {
|
|
63
|
+
id: string;
|
|
64
|
+
username: string;
|
|
65
|
+
isDeleted: boolean;
|
|
66
|
+
registry?: {
|
|
67
|
+
id: string;
|
|
68
|
+
} | null;
|
|
69
|
+
}
|
|
70
|
+
/** Shape of the `quickJoinContract` selection shared by the queries above. */
|
|
71
|
+
export interface IndexedQuickJoin {
|
|
72
|
+
id: string;
|
|
73
|
+
accountRegistry: string;
|
|
74
|
+
hatsContract: string;
|
|
75
|
+
memberHatIds: string[];
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* True when an indexed account can stand in for a live
|
|
79
|
+
* `registry.getUsername(addr)` read.
|
|
80
|
+
*
|
|
81
|
+
* Two ways it cannot:
|
|
82
|
+
* - the account was deleted on-chain (the indexed username is a tombstone);
|
|
83
|
+
* - it lives on a DIFFERENT registry than the one the caller is about to
|
|
84
|
+
* transact against. Exactly one UniversalAccountRegistry is indexed per
|
|
85
|
+
* deployment, but a legacy org's QuickJoin can point at another address
|
|
86
|
+
* (verified: Gnosis org "Test5" points at 0x01a1…8513, which has no code
|
|
87
|
+
* on Gnosis), and Account.id is the bare address — not registry-scoped —
|
|
88
|
+
* so a username from the indexed registry would be the wrong answer.
|
|
89
|
+
*
|
|
90
|
+
* `expectedRegistry` omitted means "no registry constraint" (the caller is
|
|
91
|
+
* reading the subgraph's own registry).
|
|
92
|
+
*/
|
|
93
|
+
export declare function isAccountAuthoritative(account: IndexedAccount | null | undefined, expectedRegistry?: string | null): account is IndexedAccount;
|
|
94
|
+
export declare const FETCH_USER_DATA = "\n query FetchUserDataNew($orgUserID: String!, $userAddress: Bytes!) {\n user(id: $orgUserID) {\n id\n address\n participationTokenBalance\n membershipStatus\n currentHatIds\n joinMethod\n totalTasksCompleted\n totalVotes\n totalModulesCompleted\n firstSeenAt\n lastActiveAt\n assignedTasks(first: 20) {\n id\n taskId\n title\n payout\n status\n }\n completedTasks(first: 20) {\n id\n taskId\n title\n payout\n }\n hybridProposalsCreated(first: 20) {\n id\n proposalId\n title\n status\n startTimestamp\n endTimestamp\n }\n modulesCompleted(first: 20) {\n moduleId\n completedAt\n }\n }\n account(id: $userAddress) {\n id\n username\n }\n }\n";
|
|
95
|
+
/**
|
|
96
|
+
* FETCH_USER_DATA plus the per-user claim-churn counters (subgraph #201,
|
|
97
|
+
* TaskManager v7): how many claims this member released themselves, and how
|
|
98
|
+
* many were force-released out from under them after their claim expired.
|
|
99
|
+
*
|
|
100
|
+
* GNOSIS ONLY as of 2026-08-02. `totalTasksLostToExpiry` exists on BOTH
|
|
101
|
+
* deployments and only rides along here because a GraphQL document validates
|
|
102
|
+
* as a whole — there is no way to ask for it next to `totalTasksReleased`
|
|
103
|
+
* without the pair standing or falling together. Verified live that
|
|
104
|
+
* poa-arb-v-1 rejects this document with ``Type `User` has no field
|
|
105
|
+
* `totalTasksReleased``` (`isUnknownFieldError` matches /has no field/i, so
|
|
106
|
+
* the tier drops cleanly to FETCH_USER_DATA), while poa-gnosis-v-1 serves it.
|
|
107
|
+
*
|
|
108
|
+
* Both counters are zero on every live row on both chains today, so callers
|
|
109
|
+
* must gate rendering on the SERVED TIER: `0` ("indexed, never churned") has
|
|
110
|
+
* to stay distinguishable from absent ("not indexed here").
|
|
111
|
+
*
|
|
112
|
+
* Built by INSERTION so the two documents cannot drift apart, and so a
|
|
113
|
+
* reflow that broke the anchor would produce a visibly identical tier rather
|
|
114
|
+
* than a silently degraded one.
|
|
115
|
+
*/
|
|
116
|
+
export declare const FETCH_USER_DATA_WITH_CHURN: string;
|
|
117
|
+
/** Tier order for `pop user profile`. Tier 1 is the untouched original. */
|
|
118
|
+
export declare const USER_DATA_TIERS: string[];
|
|
119
|
+
/** Build the tier array for `queryWithFieldFallback`. */
|
|
120
|
+
export declare function userDataTiers(orgUserID: string, userAddress: string): FieldFallbackTier[];
|
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* User & Account Queries
|
|
4
|
+
* Ported from frontend queries.js
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.USER_DATA_TIERS = exports.FETCH_USER_DATA_WITH_CHURN = exports.FETCH_USER_DATA = exports.FETCH_REGISTRY_AND_ACCOUNT = exports.FETCH_QUICKJOIN_MODULES = exports.FETCH_QUICKJOIN_ACCOUNT = exports.FETCH_ACCOUNT_USERNAME = exports.FETCH_WHOAMI_ORG_DATA = exports.GET_ACCOUNT_BY_USERNAME = exports.FETCH_USERNAME = void 0;
|
|
8
|
+
exports.isAccountAuthoritative = isAccountAuthoritative;
|
|
9
|
+
exports.userDataTiers = userDataTiers;
|
|
10
|
+
exports.FETCH_USERNAME = `
|
|
11
|
+
query FetchUsernameNew($id: Bytes!) {
|
|
12
|
+
account(id: $id) {
|
|
13
|
+
id
|
|
14
|
+
username
|
|
15
|
+
profileMetadataHash
|
|
16
|
+
metadata {
|
|
17
|
+
id
|
|
18
|
+
bio
|
|
19
|
+
avatar
|
|
20
|
+
github
|
|
21
|
+
twitter
|
|
22
|
+
website
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
`;
|
|
27
|
+
exports.GET_ACCOUNT_BY_USERNAME = `
|
|
28
|
+
query GetAccountByUsername($username: String!) {
|
|
29
|
+
accounts(where: { username: $username }, first: 1) {
|
|
30
|
+
id
|
|
31
|
+
user
|
|
32
|
+
username
|
|
33
|
+
}
|
|
34
|
+
}
|
|
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
|
+
*/
|
|
57
|
+
exports.FETCH_WHOAMI_ORG_DATA = `
|
|
58
|
+
query WhoamiOrgData(
|
|
59
|
+
$orgId: Bytes!
|
|
60
|
+
$orgUserID: String!
|
|
61
|
+
$tokenAddress: String!
|
|
62
|
+
$userAddress: Bytes!
|
|
63
|
+
$quickJoinAddress: ID!
|
|
64
|
+
$accountID: ID!
|
|
65
|
+
$tokenBalanceID: ID!
|
|
66
|
+
) {
|
|
67
|
+
organization(id: $orgId) {
|
|
68
|
+
id
|
|
69
|
+
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
|
+
}
|
|
82
|
+
quickJoinContract(id: $quickJoinAddress) {
|
|
83
|
+
id
|
|
84
|
+
accountRegistry
|
|
85
|
+
hatsContract
|
|
86
|
+
memberHatIds
|
|
87
|
+
}
|
|
88
|
+
account(id: $accountID) {
|
|
89
|
+
id
|
|
90
|
+
username
|
|
91
|
+
isDeleted
|
|
92
|
+
registry {
|
|
93
|
+
id
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
tokenBalance(id: $tokenBalanceID) {
|
|
97
|
+
id
|
|
98
|
+
balance
|
|
99
|
+
}
|
|
100
|
+
user(id: $orgUserID) {
|
|
101
|
+
id
|
|
102
|
+
membershipStatus
|
|
103
|
+
participationTokenBalance
|
|
104
|
+
currentHatIds
|
|
105
|
+
}
|
|
106
|
+
tokenRequests(
|
|
107
|
+
where: { participationToken: $tokenAddress, requester: $userAddress, status: Pending }
|
|
108
|
+
first: 100
|
|
109
|
+
) {
|
|
110
|
+
id
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
`;
|
|
114
|
+
/**
|
|
115
|
+
* Standalone account lookup (no org): the username + registry for one
|
|
116
|
+
* address. Account.id is the LOWERCASED address. Used by `pop user whoami`
|
|
117
|
+
* when no org is configured — the username is home-chain account-registry
|
|
118
|
+
* state, so this runs against the home-chain subgraph instead of building a
|
|
119
|
+
* second JsonRpcProvider just to call getUsername.
|
|
120
|
+
*/
|
|
121
|
+
exports.FETCH_ACCOUNT_USERNAME = `
|
|
122
|
+
query AccountUsername($accountID: ID!) {
|
|
123
|
+
account(id: $accountID) {
|
|
124
|
+
id
|
|
125
|
+
username
|
|
126
|
+
isDeleted
|
|
127
|
+
registry {
|
|
128
|
+
id
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
`;
|
|
133
|
+
/**
|
|
134
|
+
* The org QuickJoin's module pointers plus the caller's account, in one
|
|
135
|
+
* round-trip. `pop user join` needs both: the registry QuickJoin consults
|
|
136
|
+
* (registering anywhere else leaves quickJoinWithUser reverting NoUsername)
|
|
137
|
+
* and whether a username already exists (1-tx vs 2-tx flow).
|
|
138
|
+
*
|
|
139
|
+
* The account is only trustworthy for that decision when
|
|
140
|
+
* `account.registry.id === quickJoinContract.accountRegistry` — see the
|
|
141
|
+
* guard in commands/user/join.ts.
|
|
142
|
+
*/
|
|
143
|
+
exports.FETCH_QUICKJOIN_ACCOUNT = `
|
|
144
|
+
query QuickJoinAccount($quickJoinAddress: ID!, $accountID: ID!) {
|
|
145
|
+
quickJoinContract(id: $quickJoinAddress) {
|
|
146
|
+
id
|
|
147
|
+
accountRegistry
|
|
148
|
+
hatsContract
|
|
149
|
+
memberHatIds
|
|
150
|
+
}
|
|
151
|
+
account(id: $accountID) {
|
|
152
|
+
id
|
|
153
|
+
username
|
|
154
|
+
isDeleted
|
|
155
|
+
registry {
|
|
156
|
+
id
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
`;
|
|
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
|
+
*/
|
|
165
|
+
exports.FETCH_QUICKJOIN_MODULES = `
|
|
166
|
+
query QuickJoinModules($quickJoinAddress: ID!) {
|
|
167
|
+
quickJoinContract(id: $quickJoinAddress) {
|
|
168
|
+
id
|
|
169
|
+
accountRegistry
|
|
170
|
+
hatsContract
|
|
171
|
+
memberHatIds
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
`;
|
|
175
|
+
/**
|
|
176
|
+
* The indexed account registry plus one account's username and profile
|
|
177
|
+
* metadata, in one round-trip — everything `pop user update-profile` needs
|
|
178
|
+
* before it writes. Replaces two separate subgraph queries plus a
|
|
179
|
+
* getUsername eth_call.
|
|
180
|
+
*/
|
|
181
|
+
exports.FETCH_REGISTRY_AND_ACCOUNT = `
|
|
182
|
+
query RegistryAndAccount($accountID: ID!) {
|
|
183
|
+
universalAccountRegistries(first: 1) {
|
|
184
|
+
id
|
|
185
|
+
}
|
|
186
|
+
account(id: $accountID) {
|
|
187
|
+
id
|
|
188
|
+
username
|
|
189
|
+
isDeleted
|
|
190
|
+
metadata {
|
|
191
|
+
bio
|
|
192
|
+
avatar
|
|
193
|
+
github
|
|
194
|
+
twitter
|
|
195
|
+
website
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
`;
|
|
200
|
+
/**
|
|
201
|
+
* True when an indexed account can stand in for a live
|
|
202
|
+
* `registry.getUsername(addr)` read.
|
|
203
|
+
*
|
|
204
|
+
* Two ways it cannot:
|
|
205
|
+
* - the account was deleted on-chain (the indexed username is a tombstone);
|
|
206
|
+
* - it lives on a DIFFERENT registry than the one the caller is about to
|
|
207
|
+
* transact against. Exactly one UniversalAccountRegistry is indexed per
|
|
208
|
+
* deployment, but a legacy org's QuickJoin can point at another address
|
|
209
|
+
* (verified: Gnosis org "Test5" points at 0x01a1…8513, which has no code
|
|
210
|
+
* on Gnosis), and Account.id is the bare address — not registry-scoped —
|
|
211
|
+
* so a username from the indexed registry would be the wrong answer.
|
|
212
|
+
*
|
|
213
|
+
* `expectedRegistry` omitted means "no registry constraint" (the caller is
|
|
214
|
+
* reading the subgraph's own registry).
|
|
215
|
+
*/
|
|
216
|
+
function isAccountAuthoritative(account, expectedRegistry) {
|
|
217
|
+
if (!account || account.isDeleted)
|
|
218
|
+
return false;
|
|
219
|
+
if (!expectedRegistry)
|
|
220
|
+
return true;
|
|
221
|
+
const indexed = account.registry?.id;
|
|
222
|
+
if (!indexed)
|
|
223
|
+
return false;
|
|
224
|
+
return indexed.toLowerCase() === expectedRegistry.toLowerCase();
|
|
225
|
+
}
|
|
226
|
+
exports.FETCH_USER_DATA = `
|
|
227
|
+
query FetchUserDataNew($orgUserID: String!, $userAddress: Bytes!) {
|
|
228
|
+
user(id: $orgUserID) {
|
|
229
|
+
id
|
|
230
|
+
address
|
|
231
|
+
participationTokenBalance
|
|
232
|
+
membershipStatus
|
|
233
|
+
currentHatIds
|
|
234
|
+
joinMethod
|
|
235
|
+
totalTasksCompleted
|
|
236
|
+
totalVotes
|
|
237
|
+
totalModulesCompleted
|
|
238
|
+
firstSeenAt
|
|
239
|
+
lastActiveAt
|
|
240
|
+
assignedTasks(first: 20) {
|
|
241
|
+
id
|
|
242
|
+
taskId
|
|
243
|
+
title
|
|
244
|
+
payout
|
|
245
|
+
status
|
|
246
|
+
}
|
|
247
|
+
completedTasks(first: 20) {
|
|
248
|
+
id
|
|
249
|
+
taskId
|
|
250
|
+
title
|
|
251
|
+
payout
|
|
252
|
+
}
|
|
253
|
+
hybridProposalsCreated(first: 20) {
|
|
254
|
+
id
|
|
255
|
+
proposalId
|
|
256
|
+
title
|
|
257
|
+
status
|
|
258
|
+
startTimestamp
|
|
259
|
+
endTimestamp
|
|
260
|
+
}
|
|
261
|
+
modulesCompleted(first: 20) {
|
|
262
|
+
moduleId
|
|
263
|
+
completedAt
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
account(id: $userAddress) {
|
|
267
|
+
id
|
|
268
|
+
username
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
`;
|
|
272
|
+
/**
|
|
273
|
+
* FETCH_USER_DATA plus the per-user claim-churn counters (subgraph #201,
|
|
274
|
+
* TaskManager v7): how many claims this member released themselves, and how
|
|
275
|
+
* many were force-released out from under them after their claim expired.
|
|
276
|
+
*
|
|
277
|
+
* GNOSIS ONLY as of 2026-08-02. `totalTasksLostToExpiry` exists on BOTH
|
|
278
|
+
* deployments and only rides along here because a GraphQL document validates
|
|
279
|
+
* as a whole — there is no way to ask for it next to `totalTasksReleased`
|
|
280
|
+
* without the pair standing or falling together. Verified live that
|
|
281
|
+
* poa-arb-v-1 rejects this document with ``Type `User` has no field
|
|
282
|
+
* `totalTasksReleased``` (`isUnknownFieldError` matches /has no field/i, so
|
|
283
|
+
* the tier drops cleanly to FETCH_USER_DATA), while poa-gnosis-v-1 serves it.
|
|
284
|
+
*
|
|
285
|
+
* Both counters are zero on every live row on both chains today, so callers
|
|
286
|
+
* must gate rendering on the SERVED TIER: `0` ("indexed, never churned") has
|
|
287
|
+
* to stay distinguishable from absent ("not indexed here").
|
|
288
|
+
*
|
|
289
|
+
* Built by INSERTION so the two documents cannot drift apart, and so a
|
|
290
|
+
* reflow that broke the anchor would produce a visibly identical tier rather
|
|
291
|
+
* than a silently degraded one.
|
|
292
|
+
*/
|
|
293
|
+
exports.FETCH_USER_DATA_WITH_CHURN = exports.FETCH_USER_DATA.replace(/^(\s*)totalTasksCompleted$/m, '$1totalTasksCompleted\n$1totalTasksReleased\n$1totalTasksLostToExpiry');
|
|
294
|
+
/** Tier order for `pop user profile`. Tier 1 is the untouched original. */
|
|
295
|
+
exports.USER_DATA_TIERS = [
|
|
296
|
+
exports.FETCH_USER_DATA_WITH_CHURN, // 0: Gnosis — v7 claim-churn counters
|
|
297
|
+
exports.FETCH_USER_DATA, // 1: Arbitrum today — no releases indexed
|
|
298
|
+
];
|
|
299
|
+
/** Build the tier array for `queryWithFieldFallback`. */
|
|
300
|
+
function userDataTiers(orgUserID, userAddress) {
|
|
301
|
+
return exports.USER_DATA_TIERS.map((query) => ({ query, variables: { orgUserID, userAddress } }));
|
|
302
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Voting-class queries — the subgraph mirror of HybridVoting.getClasses() /
|
|
3
|
+
* getProposalClasses(id) plus the two DISTINCT validity parameters
|
|
4
|
+
* (thresholdPct = % of weighted power, quorum = raw voter count).
|
|
5
|
+
*
|
|
6
|
+
* Model (verified live against poa-gnosis-v-1 and poa-arb-v-1):
|
|
7
|
+
* HybridVotingContract { thresholdPct, quorum, classVersion, votingClasses }
|
|
8
|
+
* VotingClass { version, classIndex, strategy, slicePct, quadratic,
|
|
9
|
+
* minBalance, asset, hatIds, isActive }
|
|
10
|
+
* Proposal { classesVersion } ← the frozen snapshot pointer
|
|
11
|
+
*
|
|
12
|
+
* A VotingClass row is NOT unique per contract — every setClasses() writes a
|
|
13
|
+
* fresh `version` (the block number) and keeps the old rows around, which is
|
|
14
|
+
* exactly what makes the per-proposal snapshot reconstructable. So every read
|
|
15
|
+
* here is "fetch the contract's class rows, then pick one version":
|
|
16
|
+
* live config → version == HybridVotingContract.classVersion
|
|
17
|
+
* proposal snapshot→ version == Proposal.classesVersion
|
|
18
|
+
*
|
|
19
|
+
* Deployment tiering (src/lib/subgraph.ts queryWithFieldFallback): GraphQL
|
|
20
|
+
* validates a document as a whole, so `classVersion` — absent on subgraph
|
|
21
|
+
* deployments older than the class-versioning release — has to live in its own
|
|
22
|
+
* tier. The proposal-snapshot query deliberately has NO legacy tier: without
|
|
23
|
+
* `classesVersion` there is no way to identify the frozen snapshot, and
|
|
24
|
+
* silently showing the CURRENT classes for an old proposal would be worse than
|
|
25
|
+
* falling back to the on-chain getProposalClasses call.
|
|
26
|
+
*/
|
|
27
|
+
/** Live class config + threshold/quorum. Tier 0 — has classVersion. */
|
|
28
|
+
export declare const FETCH_VOTING_CLASS_CONFIG = "\n query FetchVotingClassConfig($hybridVoting: ID!) {\n hybridVotingContract(id: $hybridVoting) {\n id\n thresholdPct\n quorum\n classVersion\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";
|
|
29
|
+
/**
|
|
30
|
+
* Live class config, tier 1 — for deployments that predate `classVersion`.
|
|
31
|
+
* Without it the current version is recovered as max(version), which is
|
|
32
|
+
* correct as long as setClasses versions increase monotonically (they are
|
|
33
|
+
* block numbers, so they do).
|
|
34
|
+
*/
|
|
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
|
+
/** 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";
|
|
38
|
+
/**
|
|
39
|
+
* Everything `pop vote analyze` needs in ONE round-trip: the frozen class
|
|
40
|
+
* snapshot, every ballot with its per-class raw power (Vote.classRawPowers is
|
|
41
|
+
* the exact quantity the command used to reconstruct from VoteCast logs), and
|
|
42
|
+
* the org's username map for display names.
|
|
43
|
+
*/
|
|
44
|
+
export declare const FETCH_PROPOSAL_VOTE_ANALYSIS = "\n query FetchProposalVoteAnalysis($hybridVoting: ID!, $proposalId: BigInt!) {\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 classesVersion\n votes(first: 1000, orderBy: votedAt, orderDirection: asc) {\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
|
+
/** One VotingClass row as returned by the subgraph (all scalars are strings/numbers). */
|
|
46
|
+
export interface SubgraphVotingClass {
|
|
47
|
+
version: string;
|
|
48
|
+
classIndex: number;
|
|
49
|
+
strategy: string;
|
|
50
|
+
slicePct: number;
|
|
51
|
+
quadratic: boolean;
|
|
52
|
+
minBalance: string;
|
|
53
|
+
asset: string;
|
|
54
|
+
hatIds: string[];
|
|
55
|
+
isActive: boolean;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Pick the class rows belonging to one config version and order them by
|
|
59
|
+
* classIndex (the on-chain array order the whole slice/quorum math assumes).
|
|
60
|
+
*
|
|
61
|
+
* `version` null/undefined means the caller could not learn which version to
|
|
62
|
+
* use (legacy deployment without classVersion) — then the newest indexed
|
|
63
|
+
* version wins, which reproduces getClasses() but must NEVER be used to
|
|
64
|
+
* reconstruct an old proposal's frozen snapshot.
|
|
65
|
+
*
|
|
66
|
+
* Returns [] when nothing matches, which callers treat as "subgraph can't
|
|
67
|
+
* answer this" and fall back to the contract.
|
|
68
|
+
*/
|
|
69
|
+
export declare function selectClassSnapshot(rows: SubgraphVotingClass[] | undefined | null, version: string | number | null | undefined): SubgraphVotingClass[];
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Voting-class queries — the subgraph mirror of HybridVoting.getClasses() /
|
|
4
|
+
* getProposalClasses(id) plus the two DISTINCT validity parameters
|
|
5
|
+
* (thresholdPct = % of weighted power, quorum = raw voter count).
|
|
6
|
+
*
|
|
7
|
+
* Model (verified live against poa-gnosis-v-1 and poa-arb-v-1):
|
|
8
|
+
* HybridVotingContract { thresholdPct, quorum, classVersion, votingClasses }
|
|
9
|
+
* VotingClass { version, classIndex, strategy, slicePct, quadratic,
|
|
10
|
+
* minBalance, asset, hatIds, isActive }
|
|
11
|
+
* Proposal { classesVersion } ← the frozen snapshot pointer
|
|
12
|
+
*
|
|
13
|
+
* A VotingClass row is NOT unique per contract — every setClasses() writes a
|
|
14
|
+
* fresh `version` (the block number) and keeps the old rows around, which is
|
|
15
|
+
* exactly what makes the per-proposal snapshot reconstructable. So every read
|
|
16
|
+
* here is "fetch the contract's class rows, then pick one version":
|
|
17
|
+
* live config → version == HybridVotingContract.classVersion
|
|
18
|
+
* proposal snapshot→ version == Proposal.classesVersion
|
|
19
|
+
*
|
|
20
|
+
* Deployment tiering (src/lib/subgraph.ts queryWithFieldFallback): GraphQL
|
|
21
|
+
* validates a document as a whole, so `classVersion` — absent on subgraph
|
|
22
|
+
* deployments older than the class-versioning release — has to live in its own
|
|
23
|
+
* tier. The proposal-snapshot query deliberately has NO legacy tier: without
|
|
24
|
+
* `classesVersion` there is no way to identify the frozen snapshot, and
|
|
25
|
+
* silently showing the CURRENT classes for an old proposal would be worse than
|
|
26
|
+
* falling back to the on-chain getProposalClasses call.
|
|
27
|
+
*/
|
|
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;
|
|
30
|
+
exports.selectClassSnapshot = selectClassSnapshot;
|
|
31
|
+
/** Field set shared by every VotingClass selection. */
|
|
32
|
+
const VOTING_CLASS_FIELDS = `
|
|
33
|
+
version
|
|
34
|
+
classIndex
|
|
35
|
+
strategy
|
|
36
|
+
slicePct
|
|
37
|
+
quadratic
|
|
38
|
+
minBalance
|
|
39
|
+
asset
|
|
40
|
+
hatIds
|
|
41
|
+
isActive`;
|
|
42
|
+
/** Live class config + threshold/quorum. Tier 0 — has classVersion. */
|
|
43
|
+
exports.FETCH_VOTING_CLASS_CONFIG = `
|
|
44
|
+
query FetchVotingClassConfig($hybridVoting: ID!) {
|
|
45
|
+
hybridVotingContract(id: $hybridVoting) {
|
|
46
|
+
id
|
|
47
|
+
thresholdPct
|
|
48
|
+
quorum
|
|
49
|
+
classVersion
|
|
50
|
+
votingClasses(first: 1000) {${VOTING_CLASS_FIELDS}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
`;
|
|
55
|
+
/**
|
|
56
|
+
* Live class config, tier 1 — for deployments that predate `classVersion`.
|
|
57
|
+
* Without it the current version is recovered as max(version), which is
|
|
58
|
+
* correct as long as setClasses versions increase monotonically (they are
|
|
59
|
+
* block numbers, so they do).
|
|
60
|
+
*/
|
|
61
|
+
exports.FETCH_VOTING_CLASS_CONFIG_LEGACY = `
|
|
62
|
+
query FetchVotingClassConfigLegacy($hybridVoting: ID!) {
|
|
63
|
+
hybridVotingContract(id: $hybridVoting) {
|
|
64
|
+
id
|
|
65
|
+
thresholdPct
|
|
66
|
+
quorum
|
|
67
|
+
votingClasses(first: 1000) {${VOTING_CLASS_FIELDS}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
`;
|
|
72
|
+
/** Class snapshot frozen for one proposal + threshold/quorum. Single tier. */
|
|
73
|
+
exports.FETCH_PROPOSAL_VOTING_CLASSES = `
|
|
74
|
+
query FetchProposalVotingClasses($hybridVoting: ID!, $proposalId: BigInt!) {
|
|
75
|
+
hybridVotingContract(id: $hybridVoting) {
|
|
76
|
+
id
|
|
77
|
+
thresholdPct
|
|
78
|
+
quorum
|
|
79
|
+
proposals(where: { proposalId: $proposalId }) {
|
|
80
|
+
proposalId
|
|
81
|
+
classesVersion
|
|
82
|
+
}
|
|
83
|
+
votingClasses(first: 1000) {${VOTING_CLASS_FIELDS}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
`;
|
|
88
|
+
/**
|
|
89
|
+
* Everything `pop vote analyze` needs in ONE round-trip: the frozen class
|
|
90
|
+
* snapshot, every ballot with its per-class raw power (Vote.classRawPowers is
|
|
91
|
+
* the exact quantity the command used to reconstruct from VoteCast logs), and
|
|
92
|
+
* the org's username map for display names.
|
|
93
|
+
*/
|
|
94
|
+
exports.FETCH_PROPOSAL_VOTE_ANALYSIS = `
|
|
95
|
+
query FetchProposalVoteAnalysis($hybridVoting: ID!, $proposalId: BigInt!) {
|
|
96
|
+
hybridVotingContract(id: $hybridVoting) {
|
|
97
|
+
id
|
|
98
|
+
organization {
|
|
99
|
+
id
|
|
100
|
+
users(first: 100) {
|
|
101
|
+
address
|
|
102
|
+
account { username }
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
proposals(where: { proposalId: $proposalId }) {
|
|
106
|
+
proposalId
|
|
107
|
+
classesVersion
|
|
108
|
+
votes(first: 1000, orderBy: votedAt, orderDirection: asc) {
|
|
109
|
+
voter
|
|
110
|
+
voterUsername
|
|
111
|
+
optionIndexes
|
|
112
|
+
optionWeights
|
|
113
|
+
classRawPowers
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
votingClasses(first: 1000) {${VOTING_CLASS_FIELDS}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
`;
|
|
121
|
+
/**
|
|
122
|
+
* Pick the class rows belonging to one config version and order them by
|
|
123
|
+
* classIndex (the on-chain array order the whole slice/quorum math assumes).
|
|
124
|
+
*
|
|
125
|
+
* `version` null/undefined means the caller could not learn which version to
|
|
126
|
+
* use (legacy deployment without classVersion) — then the newest indexed
|
|
127
|
+
* version wins, which reproduces getClasses() but must NEVER be used to
|
|
128
|
+
* reconstruct an old proposal's frozen snapshot.
|
|
129
|
+
*
|
|
130
|
+
* Returns [] when nothing matches, which callers treat as "subgraph can't
|
|
131
|
+
* answer this" and fall back to the contract.
|
|
132
|
+
*/
|
|
133
|
+
function selectClassSnapshot(rows, version) {
|
|
134
|
+
const active = (rows ?? []).filter(r => r && r.isActive !== false);
|
|
135
|
+
if (active.length === 0)
|
|
136
|
+
return [];
|
|
137
|
+
let target = version === null || version === undefined ? null : String(version);
|
|
138
|
+
if (target === null) {
|
|
139
|
+
target = active.reduce((max, r) => {
|
|
140
|
+
const v = String(r.version);
|
|
141
|
+
if (max === null)
|
|
142
|
+
return v;
|
|
143
|
+
return BigInt(v) > BigInt(max) ? v : max;
|
|
144
|
+
}, null);
|
|
145
|
+
}
|
|
146
|
+
return active
|
|
147
|
+
.filter(r => String(r.version) === target)
|
|
148
|
+
.sort((a, b) => Number(a.classIndex) - Number(b.classIndex));
|
|
149
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Voting Queries
|
|
3
|
+
* Ported from frontend queries.js
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Fuzzy --proposal resolution: recent proposals for ONE voting contract,
|
|
7
|
+
* addressed directly by contract address (works for HybridVoting and
|
|
8
|
+
* DirectDemocracyVoting — whichever entity matches the address answers,
|
|
9
|
+
* the other root field returns null). Titles are stored decoded by the
|
|
10
|
+
* subgraph, so they can be scored with bestMatches directly.
|
|
11
|
+
*/
|
|
12
|
+
export declare const RECENT_PROPOSALS_FOR_RESOLVE = "\n query RecentProposalsForResolve($votingId: ID!, $first: Int!) {\n hybridVotingContract(id: $votingId) {\n id\n proposals(orderBy: startTimestamp, orderDirection: desc, first: $first) {\n proposalId\n title\n status\n endTimestamp\n }\n }\n directDemocracyVotingContract(id: $votingId) {\n id\n ddvProposals(orderBy: startTimestamp, orderDirection: desc, first: $first) {\n proposalId\n title\n status\n endTimestamp\n }\n }\n }\n";
|
|
13
|
+
/**
|
|
14
|
+
* One proposal's voting-window state for the cast pre-flight
|
|
15
|
+
* ("not obviously ended"). Same dual-entity addressing as above.
|
|
16
|
+
*/
|
|
17
|
+
export declare const PROPOSAL_STATE_FOR_PREFLIGHT = "\n query ProposalStateForPreflight($votingId: ID!, $proposalId: BigInt!) {\n hybridVotingContract(id: $votingId) {\n proposals(where: { proposalId: $proposalId }, first: 1) {\n proposalId\n status\n endTimestamp\n }\n }\n directDemocracyVotingContract(id: $votingId) {\n ddvProposals(where: { proposalId: $proposalId }, first: 1) {\n proposalId\n status\n endTimestamp\n }\n }\n }\n";
|
|
18
|
+
export declare const FETCH_VOTING_DATA = "\n query FetchVotingDataNew($orgId: Bytes!) {\n organization(id: $orgId) {\n id\n hybridVoting {\n id\n thresholdPct\n quorum\n classVersion\n votingClasses(where: { isActive: true }, orderBy: classIndex, orderDirection: asc) {\n id\n classIndex\n version\n strategy\n slicePct\n quadratic\n minBalance\n asset\n hatIds\n isActive\n }\n proposals(orderBy: startTimestamp, orderDirection: desc, first: 50) {\n id\n proposalId\n title\n descriptionHash\n metadata {\n id\n description\n optionNames\n }\n numOptions\n startTimestamp\n endTimestamp\n status\n winningOption\n isValid\n wasExecuted\n executionFailed\n executionError\n isHatRestricted\n restrictedHatIds\n proposer\n proposerUsername\n creatorUsername\n classesVersion\n votes {\n voter\n voterUsername\n optionIndexes\n optionWeights\n classRawPowers\n votedAt\n }\n }\n }\n directDemocracyVoting {\n id\n thresholdPct\n quorum\n ddvProposals(orderBy: startTimestamp, orderDirection: desc, first: 50) {\n id\n proposalId\n title\n descriptionHash\n metadata {\n id\n description\n optionNames\n }\n numOptions\n startTimestamp\n endTimestamp\n status\n winningOption\n isValid\n executionFailed\n executionError\n isHatRestricted\n restrictedHatIds\n proposer\n proposerUsername\n votes {\n voter\n optionIndexes\n optionWeights\n }\n }\n }\n }\n }\n";
|
|
19
|
+
/**
|
|
20
|
+
* FETCH_VOTING_DATA without the subgraph #195 attribution fields.
|
|
21
|
+
*
|
|
22
|
+
* A GraphQL document is validated as a whole, so a single unknown field fails the entire
|
|
23
|
+
* query — not just that selection. `pop vote announce-all` (a WRITE that announces winners)
|
|
24
|
+
* shares this document, so against a subgraph pinned before #195 the org would lose the
|
|
25
|
+
* ability to announce ANY proposal. Derived from the full query by deletion so the two
|
|
26
|
+
* cannot drift apart.
|
|
27
|
+
*/
|
|
28
|
+
export declare const FETCH_VOTING_DATA_LEGACY: string;
|