@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.
Files changed (220) hide show
  1. package/README.md +201 -0
  2. package/dist/abis/DirectDemocracyVotingNew.d.ts +749 -0
  3. package/dist/abis/DirectDemocracyVotingNew.js +961 -0
  4. package/dist/abis/ERC20.d.ts +90 -0
  5. package/dist/abis/ERC20.js +125 -0
  6. package/dist/abis/EducationHubNew.d.ts +590 -0
  7. package/dist/abis/EducationHubNew.js +762 -0
  8. package/dist/abis/EligibilityModuleNew.d.ts +1615 -0
  9. package/dist/abis/EligibilityModuleNew.js +2082 -0
  10. package/dist/abis/Executor.d.ts +619 -0
  11. package/dist/abis/Executor.js +796 -0
  12. package/dist/abis/HybridVotingNew.d.ts +898 -0
  13. package/dist/abis/HybridVotingNew.js +1149 -0
  14. package/dist/abis/ImplementationRegistry.d.ts +270 -0
  15. package/dist/abis/ImplementationRegistry.js +355 -0
  16. package/dist/abis/OrgDeployerNew.d.ts +1275 -0
  17. package/dist/abis/OrgDeployerNew.js +1630 -0
  18. package/dist/abis/OrgRegistry.d.ts +670 -0
  19. package/dist/abis/OrgRegistry.js +868 -0
  20. package/dist/abis/ParticipationToken.d.ts +1086 -0
  21. package/dist/abis/ParticipationToken.js +1415 -0
  22. package/dist/abis/PasskeyAccount.d.ts +788 -0
  23. package/dist/abis/PasskeyAccount.js +1019 -0
  24. package/dist/abis/PasskeyAccountFactory.d.ts +344 -0
  25. package/dist/abis/PasskeyAccountFactory.js +449 -0
  26. package/dist/abis/PaymasterHub.d.ts +1603 -0
  27. package/dist/abis/PaymasterHub.js +2048 -0
  28. package/dist/abis/PaymentManager.d.ts +520 -0
  29. package/dist/abis/PaymentManager.js +671 -0
  30. package/dist/abis/PoaManager.d.ts +344 -0
  31. package/dist/abis/PoaManager.js +449 -0
  32. package/dist/abis/QuickJoinNew.d.ts +855 -0
  33. package/dist/abis/QuickJoinNew.js +1098 -0
  34. package/dist/abis/TaskManagerNew.d.ts +1236 -0
  35. package/dist/abis/TaskManagerNew.js +1573 -0
  36. package/dist/abis/ToggleModule.d.ts +193 -0
  37. package/dist/abis/ToggleModule.js +255 -0
  38. package/dist/abis/UniversalAccountRegistry.d.ts +577 -0
  39. package/dist/abis/UniversalAccountRegistry.js +750 -0
  40. package/dist/abis/ZkEmailInvites.d.ts +823 -0
  41. package/dist/abis/ZkEmailInvites.js +1060 -0
  42. package/dist/abis/external/AaveGovernanceV2.d.ts +128 -0
  43. package/dist/abis/external/AaveGovernanceV2.js +177 -0
  44. package/dist/abis/external/AaveGovernanceV3.d.ts +160 -0
  45. package/dist/abis/external/AaveGovernanceV3.js +220 -0
  46. package/dist/abis/external/AragonVoting.d.ts +107 -0
  47. package/dist/abis/external/AragonVoting.js +150 -0
  48. package/dist/abis/external/CurveGaugeController.d.ts +95 -0
  49. package/dist/abis/external/CurveGaugeController.js +130 -0
  50. package/dist/abis/external/CurveVotingEscrow.d.ts +86 -0
  51. package/dist/abis/external/CurveVotingEscrow.js +116 -0
  52. package/dist/abis/external/GovernorAlpha.d.ts +172 -0
  53. package/dist/abis/external/GovernorAlpha.js +228 -0
  54. package/dist/abis/external/MakerDAOChief.d.ts +92 -0
  55. package/dist/abis/external/MakerDAOChief.js +129 -0
  56. package/dist/abis/external/OZGovernor.d.ts +227 -0
  57. package/dist/abis/external/OZGovernor.js +317 -0
  58. package/dist/abis/external/SolidlyVotingEscrow.d.ts +196 -0
  59. package/dist/abis/external/SolidlyVotingEscrow.js +260 -0
  60. package/dist/abis/index.d.ts +62 -0
  61. package/dist/abis/index.js +98 -0
  62. package/dist/chains.d.ts +150 -0
  63. package/dist/chains.js +320 -0
  64. package/dist/context.d.ts +48 -0
  65. package/dist/context.js +38 -0
  66. package/dist/contracts.d.ts +24 -0
  67. package/dist/contracts.js +41 -0
  68. package/dist/encoding.d.ts +58 -0
  69. package/dist/encoding.js +243 -0
  70. package/dist/env.d.ts +10 -0
  71. package/dist/env.js +4 -0
  72. package/dist/error-catalog.d.ts +41 -0
  73. package/dist/error-catalog.js +941 -0
  74. package/dist/errors.d.ts +27 -0
  75. package/dist/errors.js +60 -0
  76. package/dist/execute/ethers.d.ts +93 -0
  77. package/dist/execute/ethers.js +323 -0
  78. package/dist/execute/index.d.ts +7 -0
  79. package/dist/execute/index.js +23 -0
  80. package/dist/execute/sponsored.d.ts +68 -0
  81. package/dist/execute/sponsored.js +277 -0
  82. package/dist/exit-codes.d.ts +18 -0
  83. package/dist/exit-codes.js +21 -0
  84. package/dist/format.d.ts +21 -0
  85. package/dist/format.js +89 -0
  86. package/dist/graph/client.d.ts +298 -0
  87. package/dist/graph/client.js +702 -0
  88. package/dist/graph/documents/activity.d.ts +9 -0
  89. package/dist/graph/documents/activity.js +164 -0
  90. package/dist/graph/documents/beacons.d.ts +172 -0
  91. package/dist/graph/documents/beacons.js +345 -0
  92. package/dist/graph/documents/index.d.ts +21 -0
  93. package/dist/graph/documents/index.js +57 -0
  94. package/dist/graph/documents/infrastructure.d.ts +30 -0
  95. package/dist/graph/documents/infrastructure.js +34 -0
  96. package/dist/graph/documents/org.d.ts +15 -0
  97. package/dist/graph/documents/org.js +249 -0
  98. package/dist/graph/documents/paymaster.d.ts +95 -0
  99. package/dist/graph/documents/paymaster.js +101 -0
  100. package/dist/graph/documents/role.d.ts +6 -0
  101. package/dist/graph/documents/role.js +41 -0
  102. package/dist/graph/documents/roles.d.ts +50 -0
  103. package/dist/graph/documents/roles.js +112 -0
  104. package/dist/graph/documents/task.d.ts +84 -0
  105. package/dist/graph/documents/task.js +236 -0
  106. package/dist/graph/documents/token.d.ts +13 -0
  107. package/dist/graph/documents/token.js +126 -0
  108. package/dist/graph/documents/treasury.d.ts +39 -0
  109. package/dist/graph/documents/treasury.js +136 -0
  110. package/dist/graph/documents/user.d.ts +120 -0
  111. package/dist/graph/documents/user.js +302 -0
  112. package/dist/graph/documents/voting-classes.d.ts +69 -0
  113. package/dist/graph/documents/voting-classes.js +149 -0
  114. package/dist/graph/documents/voting.d.ts +28 -0
  115. package/dist/graph/documents/voting.js +163 -0
  116. package/dist/graph/documents/vouch.d.ts +79 -0
  117. package/dist/graph/documents/vouch.js +171 -0
  118. package/dist/graph/documents/zkemail.d.ts +63 -0
  119. package/dist/graph/documents/zkemail.js +188 -0
  120. package/dist/graph/index.d.ts +2 -0
  121. package/dist/graph/index.js +41 -0
  122. package/dist/index.d.ts +49 -0
  123. package/dist/index.js +92 -0
  124. package/dist/ipfs.d.ts +39 -0
  125. package/dist/ipfs.js +214 -0
  126. package/dist/label-aliases.d.ts +31 -0
  127. package/dist/label-aliases.js +70 -0
  128. package/dist/metadata/education.d.ts +30 -0
  129. package/dist/metadata/education.js +31 -0
  130. package/dist/metadata/index.d.ts +12 -0
  131. package/dist/metadata/index.js +48 -0
  132. package/dist/metadata/org.d.ts +92 -0
  133. package/dist/metadata/org.js +93 -0
  134. package/dist/metadata/proposal.d.ts +44 -0
  135. package/dist/metadata/proposal.js +45 -0
  136. package/dist/metadata/role.d.ts +38 -0
  137. package/dist/metadata/role.js +35 -0
  138. package/dist/metadata/task.d.ts +108 -0
  139. package/dist/metadata/task.js +81 -0
  140. package/dist/metadata/token.d.ts +32 -0
  141. package/dist/metadata/token.js +36 -0
  142. package/dist/metadata/user.d.ts +63 -0
  143. package/dist/metadata/user.js +70 -0
  144. package/dist/multicall.d.ts +32 -0
  145. package/dist/multicall.js +96 -0
  146. package/dist/payout.d.ts +59 -0
  147. package/dist/payout.js +96 -0
  148. package/dist/perms.d.ts +47 -0
  149. package/dist/perms.js +120 -0
  150. package/dist/preflight.d.ts +72 -0
  151. package/dist/preflight.js +269 -0
  152. package/dist/reads/education.d.ts +79 -0
  153. package/dist/reads/education.js +122 -0
  154. package/dist/reads/eligibility.d.ts +377 -0
  155. package/dist/reads/eligibility.js +687 -0
  156. package/dist/reads/index.d.ts +16 -0
  157. package/dist/reads/index.js +55 -0
  158. package/dist/reads/org.d.ts +258 -0
  159. package/dist/reads/org.js +220 -0
  160. package/dist/reads/paymaster.d.ts +147 -0
  161. package/dist/reads/paymaster.js +235 -0
  162. package/dist/reads/project.d.ts +33 -0
  163. package/dist/reads/project.js +62 -0
  164. package/dist/reads/resolve.d.ts +34 -0
  165. package/dist/reads/resolve.js +64 -0
  166. package/dist/reads/task.d.ts +286 -0
  167. package/dist/reads/task.js +280 -0
  168. package/dist/reads/token.d.ts +94 -0
  169. package/dist/reads/token.js +75 -0
  170. package/dist/reads/treasury.d.ts +222 -0
  171. package/dist/reads/treasury.js +241 -0
  172. package/dist/reads/user.d.ts +229 -0
  173. package/dist/reads/user.js +155 -0
  174. package/dist/reads/vote.d.ts +296 -0
  175. package/dist/reads/vote.js +392 -0
  176. package/dist/reads/zkemail.d.ts +117 -0
  177. package/dist/reads/zkemail.js +217 -0
  178. package/dist/similarity.d.ts +36 -0
  179. package/dist/similarity.js +67 -0
  180. package/dist/sponsorship-config.d.ts +47 -0
  181. package/dist/sponsorship-config.js +41 -0
  182. package/dist/stats.d.ts +11 -0
  183. package/dist/stats.js +27 -0
  184. package/dist/task-lens.d.ts +113 -0
  185. package/dist/task-lens.js +210 -0
  186. package/dist/tx/education.d.ts +169 -0
  187. package/dist/tx/education.js +344 -0
  188. package/dist/tx/eligibility.d.ts +511 -0
  189. package/dist/tx/eligibility.js +818 -0
  190. package/dist/tx/governance.d.ts +85 -0
  191. package/dist/tx/governance.js +87 -0
  192. package/dist/tx/index.d.ts +17 -0
  193. package/dist/tx/index.js +56 -0
  194. package/dist/tx/intent.d.ts +67 -0
  195. package/dist/tx/intent.js +48 -0
  196. package/dist/tx/org.d.ts +321 -0
  197. package/dist/tx/org.js +544 -0
  198. package/dist/tx/paymaster.d.ts +140 -0
  199. package/dist/tx/paymaster.js +251 -0
  200. package/dist/tx/project.d.ts +146 -0
  201. package/dist/tx/project.js +217 -0
  202. package/dist/tx/task.d.ts +480 -0
  203. package/dist/tx/task.js +1149 -0
  204. package/dist/tx/token.d.ts +96 -0
  205. package/dist/tx/token.js +165 -0
  206. package/dist/tx/treasury.d.ts +474 -0
  207. package/dist/tx/treasury.js +911 -0
  208. package/dist/tx/user.d.ts +177 -0
  209. package/dist/tx/user.js +292 -0
  210. package/dist/tx/vote.d.ts +332 -0
  211. package/dist/tx/vote.js +762 -0
  212. package/dist/tx/zkemail.d.ts +90 -0
  213. package/dist/tx/zkemail.js +210 -0
  214. package/dist/validation.d.ts +8 -0
  215. package/dist/validation.js +39 -0
  216. package/dist/version.d.ts +142 -0
  217. package/dist/version.js +257 -0
  218. package/dist/zkemail.d.ts +161 -0
  219. package/dist/zkemail.js +299 -0
  220. package/package.json +130 -0
@@ -0,0 +1,217 @@
1
+ "use strict";
2
+ /**
3
+ * ZK Email reads — module resolution + state for `pop zkemail status` /
4
+ * `pop zkemail claims`. Port of src/commands/zkemail/helpers.ts (client- and
5
+ * provider-injected) plus the claim-history read from
6
+ * src/commands/zkemail/claims.ts.
7
+ *
8
+ * The ZkEmailInvites module is OPTIONAL per org — `organization.zkEmailInvites`
9
+ * is null for orgs deployed without it — and a deployed module with
10
+ * `merkleRoot == 0` is DORMANT (every claim reverts until governance publishes
11
+ * an allowlist). Both states get a named error rather than a confusing revert.
12
+ */
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.resolveZkEmailModule = resolveZkEmailModule;
15
+ exports.readModuleState = readModuleState;
16
+ exports.fetchIndexedActiveRoot = fetchIndexedActiveRoot;
17
+ exports.fetchZkEmailClaims = fetchZkEmailClaims;
18
+ exports.fetchRoleNames = fetchRoleNames;
19
+ exports.labelHat = labelHat;
20
+ exports.normalizeEntries = normalizeEntries;
21
+ const ethers_1 = require("ethers");
22
+ const zkemail_1 = require("../graph/documents/zkemail");
23
+ const resolve_1 = require("./resolve");
24
+ const contracts_1 = require("../contracts");
25
+ const chains_1 = require("../chains");
26
+ const encoding_1 = require("../encoding");
27
+ const errors_1 = require("../errors");
28
+ const exit_codes_1 = require("../exit-codes");
29
+ /**
30
+ * Resolve the org's ZkEmailInvites proxy from the subgraph. Port of
31
+ * resolveZkEmailModule in src/commands/zkemail/helpers.ts.
32
+ * Throws a named error when the org has no module rather than letting a null
33
+ * address turn into an opaque call failure.
34
+ */
35
+ async function resolveZkEmailModule(client, orgArg, chainId) {
36
+ const orgId = await (0, resolve_1.resolveOrgId)(client, orgArg, chainId);
37
+ // Modern tier carries the wiring + DKIM keys (subgraph-pop #197); the legacy tier is the
38
+ // allowlist-only shape served before it. tierIndex tells callers whether they still have to
39
+ // fall back to RPC for the rest.
40
+ const { data: res, tierIndex } = await client.queryWithFieldFallback(zkemail_1.FETCH_ZKEMAIL_MODULE_TIERS.map((q) => ({ query: q, variables: { orgId } })), { chainId });
41
+ const indexedWiring = tierIndex === 0;
42
+ const org = res.organization;
43
+ if (!org) {
44
+ throw new errors_1.CliError(`Organization ${orgId} not found on this chain.`, exit_codes_1.EXIT.USAGE);
45
+ }
46
+ const mod = org.zkEmailInvites;
47
+ if (!mod?.id) {
48
+ throw new errors_1.CliError(`Org "${org.name || orgId}" has no ZkEmailInvites module.`, exit_codes_1.EXIT.PRECONDITION, 'ZK Email invites are opt-in per org — the module is wired at deploy time via '
49
+ + 'OrgDeployer.deployFullOrgWithZkEmail. Existing orgs need a governance-approved module install.');
50
+ }
51
+ return { orgId, orgName: org.name ?? null, address: mod.id, subgraph: mod, indexedWiring };
52
+ }
53
+ /**
54
+ * Read the module's state, preferring the subgraph. Port of readModuleState in
55
+ * src/commands/zkemail/helpers.ts (the read behind `pop zkemail status`).
56
+ *
57
+ * `activeRoot` and `activeAllowlistCid` are indexed on the ZkEmailInvites entity, so the
58
+ * allowlist half needs no RPC at all — `resolveZkEmailModule` has already fetched it. Only the
59
+ * wiring addresses (executor + the four verifier/registry pointers) are unindexed pre-#197, so
60
+ * they are fetched on demand: pass `withWiring` when the caller actually renders them.
61
+ *
62
+ * Pass an existing `provider` to avoid opening a second connection; when omitted and an RPC
63
+ * read is needed, a JsonRpcProvider is built from resolveNetworkConfig(chainId, env).
64
+ */
65
+ async function readModuleState(address, orgId, orgName, chainId, provider, opts) {
66
+ const indexed = opts?.subgraph;
67
+ // The subgraph stores the CID as a decoded CIDv0 string and the root as Bytes. It is the
68
+ // authority for both; on-chain reads are only needed when the module is not indexed yet.
69
+ //
70
+ // In practice this is always true for the in-repo callers: BOTH tiers of
71
+ // FETCH_ZKEMAIL_MODULE_TIERS select `activeRoot` (it exists on the Arbitrum pre-#197 schema
72
+ // too), and resolveZkEmailModule throws before returning a module-less org — so the
73
+ // merkleRoot()/allowlistCid() pair below never fires today. It is kept because `opts` is
74
+ // optional on this exported helper: a caller that omits `subgraph` must still get a correct
75
+ // answer rather than an undefined root.
76
+ const haveIndexed = indexed != null && indexed.activeRoot !== undefined;
77
+ let merkleRoot;
78
+ let allowlistCid;
79
+ let cidDigest;
80
+ // Post-#197 the module entity carries the wiring, so `withWiring` needs no RPC either.
81
+ const indexedHasWiring = indexed != null && indexed.executor !== undefined;
82
+ const wantsWiring = opts?.withWiring === true || opts?.withDkimRegistry === true;
83
+ const needsRpc = !haveIndexed || (wantsWiring && !indexedHasWiring);
84
+ const p = needsRpc
85
+ ? (provider ?? new ethers_1.ethers.providers.JsonRpcProvider((0, chains_1.resolveNetworkConfig)(chainId, opts?.env).resolvedRpc))
86
+ : null;
87
+ const c = p ? (0, contracts_1.createReadContract)(address, 'ZkEmailInvites', p) : null;
88
+ if (haveIndexed) {
89
+ merkleRoot = indexed.activeRoot ?? ethers_1.ethers.constants.HashZero;
90
+ allowlistCid = indexed.activeAllowlistCid ?? null;
91
+ cidDigest = allowlistCid ? (0, encoding_1.ipfsCidToBytes32)(allowlistCid) : ethers_1.ethers.constants.HashZero;
92
+ }
93
+ else {
94
+ const [root, digest] = await Promise.all([c.merkleRoot(), c.allowlistCid()]);
95
+ merkleRoot = root;
96
+ cidDigest = digest;
97
+ allowlistCid = (0, encoding_1.bytes32ToIpfsCid)(digest);
98
+ }
99
+ // Wiring: indexed since subgraph-pop #197, so the six eth_calls below only run against a
100
+ // deployment that predates it. `dkimRegistry` is an entity reference there, hence the `.id`.
101
+ //
102
+ // NOT dead code. Gnosis serves #197, but ARBITRUM (chain 42161) still runs the older
103
+ // deployment QmYGCS4pXoaqXX7WjaPEhA56kiwgC14z7jsstZzEQgxgUp, whose ZkEmailInvites type is
104
+ // only {id, organization, activeRoot, activeAllowlistCid, activeAllowlist, createdAt,
105
+ // lastUpdatedAt} — no executor, no dkimRegistry — so the LEGACY tier is what wins there and
106
+ // `indexedHasWiring` is false. Verified by introspection 2026-07. Deleting this branch would
107
+ // break `pop zkemail status --chain 42161` the moment an Arbitrum org installs the module.
108
+ let executor;
109
+ let domainVerifier;
110
+ let emailVerifier;
111
+ let dkimRegistry;
112
+ let accountRegistry;
113
+ let universalFactory;
114
+ if (indexedHasWiring) {
115
+ executor = indexed.executor ?? undefined;
116
+ domainVerifier = indexed.domainVerifier ?? undefined;
117
+ emailVerifier = indexed.emailVerifier ?? undefined;
118
+ dkimRegistry = indexed.dkimRegistry?.id ?? undefined;
119
+ accountRegistry = indexed.accountRegistry ?? undefined;
120
+ universalFactory = indexed.universalFactory ?? undefined;
121
+ }
122
+ else if (opts?.withWiring && c) {
123
+ [executor, domainVerifier, emailVerifier, dkimRegistry, accountRegistry, universalFactory] =
124
+ await Promise.all([
125
+ c.executor(), c.domainVerifier(), c.emailVerifier(),
126
+ c.dkimRegistry(), c.accountRegistry(), c.universalFactory(),
127
+ ]);
128
+ }
129
+ else if (opts?.withDkimRegistry && c) {
130
+ // `zkemail check` needs only this one pointer; pulling all six would be five wasted calls.
131
+ dkimRegistry = await c.dkimRegistry();
132
+ }
133
+ return {
134
+ orgId,
135
+ orgName,
136
+ address,
137
+ merkleRoot,
138
+ allowlistCidDigest: cidDigest,
139
+ allowlistCid,
140
+ dormant: merkleRoot === ethers_1.ethers.constants.HashZero,
141
+ executor,
142
+ domainVerifier,
143
+ emailVerifier,
144
+ dkimRegistry,
145
+ accountRegistry,
146
+ universalFactory,
147
+ indexedWiring: indexedHasWiring,
148
+ };
149
+ }
150
+ /**
151
+ * The indexed active root for an org's module, identity-guarded — the display
152
+ * read used by `pop zkemail propose-allowlist`
153
+ * (src/commands/zkemail/propose-allowlist.ts).
154
+ *
155
+ * Returns:
156
+ * - a root string (HashZero for a dormant module whose row EXISTS), or
157
+ * - null when the row is missing / the indexed module id does not match
158
+ * `moduleAddress` (a stale org->module pointer must not describe a
159
+ * different contract than the one a proposal targets). Callers fall back
160
+ * to merkleRoot() on-chain for the null case.
161
+ */
162
+ async function fetchIndexedActiveRoot(client, orgId, moduleAddress, chainId) {
163
+ try {
164
+ const res = await client.query(zkemail_1.FETCH_ZKEMAIL_ACTIVE_ROOT, { orgId }, chainId);
165
+ const mod = res.organization?.zkEmailInvites;
166
+ if (!mod?.id || String(mod.id).toLowerCase() !== moduleAddress.toLowerCase())
167
+ return null;
168
+ return mod.activeRoot ?? ethers_1.ethers.constants.HashZero;
169
+ }
170
+ catch {
171
+ return null;
172
+ }
173
+ }
174
+ /**
175
+ * Claim history for a module, most recent first — the read behind
176
+ * `pop zkemail claims` (src/commands/zkemail/claims.ts). Indexed since
177
+ * subgraph-pop #197; on a chain still serving the legacy tier the claim events
178
+ * were seen but every parameter was discarded, so there is nothing to read —
179
+ * callers should gate on `indexedWiring` from resolveZkEmailModule like the
180
+ * CLI does.
181
+ */
182
+ async function fetchZkEmailClaims(client, moduleAddress, chainId, limit = 50) {
183
+ const res = await client.query(zkemail_1.FETCH_ZKEMAIL_CLAIMS, { module: moduleAddress.toLowerCase(), first: Math.max(1, Math.min(1000, limit)) }, chainId);
184
+ return res.zkEmailClaims ?? [];
185
+ }
186
+ /** Map hatId -> role name so allowlists render as "gmail.com -> Member". */
187
+ async function fetchRoleNames(client, orgId, chainId) {
188
+ const map = new Map();
189
+ try {
190
+ const res = await client.query(zkemail_1.FETCH_ORG_ROLE_NAMES, { orgId }, chainId);
191
+ for (const r of res.organization?.roles ?? []) {
192
+ if (r.hatId && r.name)
193
+ map.set(ethers_1.ethers.BigNumber.from(r.hatId).toString(), r.name);
194
+ }
195
+ }
196
+ catch {
197
+ // Role names are cosmetic — a subgraph hiccup must not fail an allowlist read.
198
+ }
199
+ return map;
200
+ }
201
+ /** Render a hat ID as "Member (0x2a)" when the name is known, else the raw id. */
202
+ function labelHat(hatId, names) {
203
+ const dec = ethers_1.ethers.BigNumber.from(hatId).toString();
204
+ const name = names.get(dec);
205
+ return name ? `${name} (${dec})` : dec;
206
+ }
207
+ /** Normalize the subgraph's allowlist entries into a stable shape. */
208
+ function normalizeEntries(allowlist) {
209
+ return (allowlist?.entries ?? []).map((e) => ({
210
+ index: Number(e.index),
211
+ entryType: e.entryType,
212
+ identifier: e.identifier ?? null,
213
+ identifierHash: e.identifierHash ?? null,
214
+ hatIds: (e.hatIds ?? []).map((h) => ethers_1.ethers.BigNumber.from(h).toString()),
215
+ roleIndexes: (e.roleIndexes ?? []).map((r) => Number(r)),
216
+ }));
217
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Text Similarity Utilities
3
+ * Tokenization + Jaccard similarity used for duplicate detection
4
+ * (e.g. `pop task create` warns when a similar task title exists).
5
+ */
6
+ /**
7
+ * Default stopwords: English filler + common CLI/governance scaffolding words
8
+ * that carry no signal when comparing task titles.
9
+ */
10
+ export declare const STOPWORDS: Set<string>;
11
+ /**
12
+ * Tokenize a string into a set of meaningful lowercase words.
13
+ * Splits on non-alphanumerics, drops words shorter than `minLen`
14
+ * (default 4), and filters out stopwords (default STOPWORDS).
15
+ */
16
+ export declare function tokenize(s: string, opts?: {
17
+ minLen?: number;
18
+ stopwords?: Set<string>;
19
+ }): Set<string>;
20
+ /**
21
+ * Jaccard similarity between two token sets: |intersection| / |union|.
22
+ * Returns 0 when the union is empty.
23
+ */
24
+ export declare function jaccard(a: Set<string>, b: Set<string>): number;
25
+ /**
26
+ * Rank `items` by Jaccard similarity of their text against `queryText`.
27
+ * Returns matches with score >= threshold (default 0, exclusive of
28
+ * zero-score items), sorted descending, capped at topN (default all).
29
+ */
30
+ export declare function bestMatches<T>(queryText: string, items: T[], getText: (t: T) => string, opts?: {
31
+ threshold?: number;
32
+ topN?: number;
33
+ }): Array<{
34
+ item: T;
35
+ score: number;
36
+ }>;
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ /**
3
+ * Text Similarity Utilities
4
+ * Tokenization + Jaccard similarity used for duplicate detection
5
+ * (e.g. `pop task create` warns when a similar task title exists).
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.STOPWORDS = void 0;
9
+ exports.tokenize = tokenize;
10
+ exports.jaccard = jaccard;
11
+ exports.bestMatches = bestMatches;
12
+ /**
13
+ * Default stopwords: English filler + common CLI/governance scaffolding words
14
+ * that carry no signal when comparing task titles.
15
+ */
16
+ exports.STOPWORDS = new Set([
17
+ 'the', 'and', 'for', 'with', 'from', 'into', 'onto', 'that', 'this',
18
+ 'task', 'tasks', 'create', 'build', 'make', 'add', 'new', 'fix',
19
+ 'command', 'commands', 'update', 'updates', 'support', 'test',
20
+ 'cli', 'pop', 'org', 'orgs', 'run', 'use', 'using', 'via', 'like',
21
+ 'proposal', 'proposals', 'vote', 'votes', 'write', 'generate',
22
+ ]);
23
+ /**
24
+ * Tokenize a string into a set of meaningful lowercase words.
25
+ * Splits on non-alphanumerics, drops words shorter than `minLen`
26
+ * (default 4), and filters out stopwords (default STOPWORDS).
27
+ */
28
+ function tokenize(s, opts) {
29
+ const minLen = opts?.minLen ?? 4;
30
+ const stopwords = opts?.stopwords ?? exports.STOPWORDS;
31
+ const words = (s || '').toLowerCase().split(/[^a-z0-9]+/).filter(w => w.length >= minLen);
32
+ return new Set(words.filter(w => !stopwords.has(w)));
33
+ }
34
+ /**
35
+ * Jaccard similarity between two token sets: |intersection| / |union|.
36
+ * Returns 0 when the union is empty.
37
+ */
38
+ function jaccard(a, b) {
39
+ const union = new Set([...a, ...b]);
40
+ if (union.size === 0)
41
+ return 0;
42
+ let shared = 0;
43
+ for (const w of a) {
44
+ if (b.has(w))
45
+ shared++;
46
+ }
47
+ return shared / union.size;
48
+ }
49
+ /**
50
+ * Rank `items` by Jaccard similarity of their text against `queryText`.
51
+ * Returns matches with score >= threshold (default 0, exclusive of
52
+ * zero-score items), sorted descending, capped at topN (default all).
53
+ */
54
+ function bestMatches(queryText, items, getText, opts) {
55
+ const threshold = opts?.threshold ?? 0;
56
+ const topN = opts?.topN ?? items.length;
57
+ const queryTokens = tokenize(queryText);
58
+ const scored = [];
59
+ for (const item of items) {
60
+ const score = jaccard(queryTokens, tokenize(getText(item)));
61
+ if (score > 0 && score >= threshold) {
62
+ scored.push({ item, score });
63
+ }
64
+ }
65
+ scored.sort((a, b) => b.score - a.score);
66
+ return scored.slice(0, topN);
67
+ }
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Sponsorship config resolution (pure, env-injected).
3
+ *
4
+ * Kept in its own tiny module — with no viem/permissionless/network deps — so
5
+ * both the tx layer (which sends sponsored transactions) and preflight logic
6
+ * (which skips the gas-balance check for sponsored wallets) can import it
7
+ * without a circular dependency, and so mocking the tx module in a test never
8
+ * removes this function from preflight's reach.
9
+ */
10
+ import { EnvSource } from './env';
11
+ /**
12
+ * Structurally identical to viem's Hex. Declared locally so this module — and
13
+ * everything that re-exports SponsoredConfig (the root barrel, preflight, the
14
+ * plain-EOA executor) — never references viem's declarations: viem is an
15
+ * OPTIONAL peer, and a skipLibCheck:false consumer without it must still
16
+ * typecheck. Values flow to/from viem's Hex without casts.
17
+ */
18
+ export type Hex = `0x${string}`;
19
+ export interface SponsoredConfig {
20
+ privateKey: Hex;
21
+ orgId: Hex;
22
+ hatId: bigint;
23
+ }
24
+ /**
25
+ * Bundler/RPC routing for the sponsored (4337/7702) send path. Lives here —
26
+ * not in execute/sponsored — for the same optional-peer reason: TxOptions on
27
+ * the plain-EOA executor references this type, and that executor must not
28
+ * pull viem-typed declarations into its closure. execute/sponsored re-exports
29
+ * it, so its historical import path keeps working.
30
+ */
31
+ export interface SponsoredSendOptions {
32
+ rpcUrl?: string;
33
+ value?: bigint;
34
+ pimlicoApiKey?: string;
35
+ bundlerUrl?: string;
36
+ }
37
+ /**
38
+ * Resolve sponsored config from the injected environment. Returns undefined
39
+ * when any required piece is missing.
40
+ *
41
+ * A signing key + org + hat identify the subject; the bundler can be EITHER a
42
+ * self-hosted endpoint (POP_BUNDLER_URL) OR Pimlico (PIMLICO_API_KEY) — mirror
43
+ * of sendSponsored(), so a bundler URL alone is a complete setup. Requiring a
44
+ * Pimlico key here would silently drop self-hosted-bundler users to direct EOA
45
+ * transactions.
46
+ */
47
+ export declare function resolveSponsoredConfig(env?: EnvSource): SponsoredConfig | undefined;
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveSponsoredConfig = resolveSponsoredConfig;
4
+ /**
5
+ * Sponsorship config resolution (pure, env-injected).
6
+ *
7
+ * Kept in its own tiny module — with no viem/permissionless/network deps — so
8
+ * both the tx layer (which sends sponsored transactions) and preflight logic
9
+ * (which skips the gas-balance check for sponsored wallets) can import it
10
+ * without a circular dependency, and so mocking the tx module in a test never
11
+ * removes this function from preflight's reach.
12
+ */
13
+ const env_1 = require("./env");
14
+ /**
15
+ * Resolve sponsored config from the injected environment. Returns undefined
16
+ * when any required piece is missing.
17
+ *
18
+ * A signing key + org + hat identify the subject; the bundler can be EITHER a
19
+ * self-hosted endpoint (POP_BUNDLER_URL) OR Pimlico (PIMLICO_API_KEY) — mirror
20
+ * of sendSponsored(), so a bundler URL alone is a complete setup. Requiring a
21
+ * Pimlico key here would silently drop self-hosted-bundler users to direct EOA
22
+ * transactions.
23
+ */
24
+ function resolveSponsoredConfig(env = env_1.EMPTY_ENV) {
25
+ // Read-only mode: sponsorship is a signing capability (userops are signed
26
+ // with the key) — report "not configured" so no 4337 path ever activates.
27
+ if (env.POP_READONLY === '1')
28
+ return undefined;
29
+ const privateKey = env.POP_PRIVATE_KEY;
30
+ const orgId = env.POP_ORG_ID;
31
+ const hatId = env.POP_HAT_ID;
32
+ const hasBundler = Boolean(env.PIMLICO_API_KEY || env.POP_BUNDLER_URL);
33
+ if (!privateKey || !orgId || !hatId || !hasBundler) {
34
+ return undefined;
35
+ }
36
+ return {
37
+ privateKey: (privateKey.startsWith('0x') ? privateKey : `0x${privateKey}`),
38
+ orgId: orgId,
39
+ hatId: BigInt(hatId),
40
+ };
41
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Statistics Utilities
3
+ * Shared numeric helpers for org analytics commands (audit, health-score).
4
+ */
5
+ /**
6
+ * Gini coefficient of a distribution (0 = perfect equality, → 1 = one
7
+ * holder owns everything). Uses the sorted mean-difference formula:
8
+ * G = Σ (2i - n - 1) * x_i / (n * Σ x_i) with 1-based i over sorted x.
9
+ * Returns 0 for empty input or when all values sum to 0.
10
+ */
11
+ export declare function computeGini(values: number[]): number;
package/dist/stats.js ADDED
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ /**
3
+ * Statistics Utilities
4
+ * Shared numeric helpers for org analytics commands (audit, health-score).
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.computeGini = computeGini;
8
+ /**
9
+ * Gini coefficient of a distribution (0 = perfect equality, → 1 = one
10
+ * holder owns everything). Uses the sorted mean-difference formula:
11
+ * G = Σ (2i - n - 1) * x_i / (n * Σ x_i) with 1-based i over sorted x.
12
+ * Returns 0 for empty input or when all values sum to 0.
13
+ */
14
+ function computeGini(values) {
15
+ if (values.length === 0)
16
+ return 0;
17
+ const sorted = [...values].sort((a, b) => a - b);
18
+ const n = sorted.length;
19
+ const total = sorted.reduce((s, v) => s + v, 0);
20
+ if (total === 0)
21
+ return 0;
22
+ let numerator = 0;
23
+ for (let i = 0; i < n; i++) {
24
+ numerator += (2 * (i + 1) - n - 1) * sorted[i];
25
+ }
26
+ return numerator / (n * total);
27
+ }
@@ -0,0 +1,113 @@
1
+ /**
2
+ * TaskManager Lens Reader
3
+ * Authoritative on-chain task state via TaskManager.getLensData(uint8,bytes),
4
+ * bypassing subgraph lag. Key numbering and tuple shapes verified against
5
+ * contracts repo origin/main src/TaskManager.sol (getLensData dispatcher) and
6
+ * src/lens/TaskManagerLens.sol (whose getStorage routes through the same
7
+ * variants).
8
+ */
9
+ import { ethers } from 'ethers';
10
+ /**
11
+ * TaskManager.getLensData variant selectors, verified against contracts repo
12
+ * origin/main src/TaskManager.sol. NOTE: these are NOT the TaskManagerLens.sol
13
+ * StorageKey enum indexes — that enum keys the lens contract's own
14
+ * getStorage(); the CLI calls the TaskManager dispatcher directly with the
15
+ * variant numbers below (TaskManagerLens.sol itself forwards to these).
16
+ */
17
+ export declare const STORAGE_KEYS: {
18
+ /** abi.encode(uint256 id) → task tuple (see decodeTaskInfo) */
19
+ readonly TASK_INFO: 1;
20
+ /** abi.encode(bytes32 pid) → (uint128 cap, uint128 spent, bool exists) */
21
+ readonly PROJECT_INFO: 2;
22
+ /** '' → (address hats) */
23
+ readonly HATS: 3;
24
+ /** '' → (address executor) */
25
+ readonly EXECUTOR: 4;
26
+ /** '' → (uint256[] hatIds) */
27
+ readonly CREATOR_HATS: 5;
28
+ /** '' → (uint256[] hatIds) */
29
+ readonly PERMISSION_HATS: 6;
30
+ /** abi.encode(uint256 id) → (address[] applicants) */
31
+ readonly TASK_APPLICANTS: 7;
32
+ /** abi.encode(uint256 id, address applicant) → (bytes32 hash) */
33
+ readonly TASK_APPLICATION: 8;
34
+ /** abi.encode(bytes32 pid, address token) → (uint128 cap, uint128 spent) */
35
+ readonly BOUNTY_BUDGET: 9;
36
+ /** '' → (bytes32 foldersRoot) */
37
+ readonly FOLDERS_ROOT: 10;
38
+ /** '' → (uint256[] hatIds) */
39
+ readonly ORGANIZER_HATS: 11;
40
+ };
41
+ /** Task Status enum (TaskManager.sol). */
42
+ export declare const TASK_STATUS: {
43
+ readonly UNCLAIMED: 0;
44
+ readonly CLAIMED: 1;
45
+ readonly SUBMITTED: 2;
46
+ readonly COMPLETED: 3;
47
+ readonly CANCELLED: 4;
48
+ };
49
+ export declare const TASK_STATUS_NAMES: string[];
50
+ export declare function taskStatusName(status: number): string;
51
+ export interface TaskOnChain {
52
+ projectId: string;
53
+ payout: ethers.BigNumber;
54
+ claimer: string;
55
+ bountyPayout: ethers.BigNumber;
56
+ requiresApplication: boolean;
57
+ status: number;
58
+ bountyToken: string;
59
+ /** Unix cutoff for any claim (0 = none). Undefined on pre-v6 implementations. */
60
+ absoluteDeadline?: number;
61
+ /** Per-claim submission window in seconds (0 = none). Undefined pre-v6. */
62
+ completionWindow?: number;
63
+ /** Current claim's deadline, set on claim/assign (0 = none). Undefined pre-v6. */
64
+ claimDeadline?: number;
65
+ }
66
+ /** Encode a raw eth_call payload for TaskManager.getLensData. */
67
+ export declare function encodeLensCall(key: number, params?: string): string;
68
+ /** Unwrap the `bytes` payload from a raw getLensData return. */
69
+ export declare function decodeLensResult(returnData: string): string;
70
+ /**
71
+ * Decode the task payload from getLensData variant 1. Tries the v6 10-field
72
+ * tuple first; pre-v6 payloads are only 7 words, so the v6 decode throws
73
+ * (out-of-bounds) — fall back to the legacy tuple and leave the deadline
74
+ * fields undefined.
75
+ */
76
+ export declare function decodeTaskInfo(data: string): TaskOnChain;
77
+ /**
78
+ * Read a single task's on-chain state. Accepts plain numeric IDs or
79
+ * subgraph-format IDs ("contractAddress-taskId").
80
+ */
81
+ export declare function getTaskOnChain(provider: ethers.providers.Provider, taskManagerAddr: string, taskId: string | number): Promise<TaskOnChain>;
82
+ export interface TaskEnrichmentResult {
83
+ /** Keyed by the original ID string passed in `ids`. */
84
+ tasks: Map<string, TaskOnChain>;
85
+ errors: Array<{
86
+ id: string;
87
+ message: string;
88
+ }>;
89
+ }
90
+ /**
91
+ * Fetch on-chain state for many tasks with bounded concurrency (default 5,
92
+ * capped at 50 tasks). Per-task failures are collected, never thrown, so
93
+ * callers can render partial data.
94
+ */
95
+ export declare function enrichTasksWithDeadlines(provider: ethers.providers.Provider, taskManagerAddr: string, ids: Array<string | number>, opts?: {
96
+ concurrency?: number;
97
+ cap?: number;
98
+ }): Promise<TaskEnrichmentResult>;
99
+ export type ClaimState = 'expired-claimable' | 'expiring-soon' | 'on-track' | 'none';
100
+ /**
101
+ * Classify a CLAIMED task's deadline state. `claimDeadline` takes precedence
102
+ * over `absoluteDeadline`; zero/undefined deadlines mean "no deadline".
103
+ * A deadline strictly in the past means the claim is forfeitable.
104
+ */
105
+ export declare function deriveClaimState(task: Pick<TaskOnChain, 'status' | 'claimDeadline' | 'absoluteDeadline'>, now?: number): ClaimState;
106
+ /** Read the org's task folders merkle root (getLensData variant 10). */
107
+ export declare function getFoldersRoot(provider: ethers.providers.Provider, taskManagerAddr: string): Promise<string>;
108
+ /** Read organizer hat IDs (getLensData variant 11). */
109
+ export declare function getOrganizerHats(provider: ethers.providers.Provider, taskManagerAddr: string): Promise<ethers.BigNumber[]>;
110
+ /** Read permission hat IDs (getLensData variant 6). */
111
+ export declare function getPermissionHats(provider: ethers.providers.Provider, taskManagerAddr: string): Promise<ethers.BigNumber[]>;
112
+ /** Read a task's applicant addresses (getLensData variant 7). */
113
+ export declare function getTaskApplicants(provider: ethers.providers.Provider, taskManagerAddr: string, taskId: string | number): Promise<string[]>;