@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,147 @@
1
+ /**
2
+ * Paymaster reads — PaymasterHub infrastructure resolution + org sponsorship
3
+ * state. Port of src/commands/paymaster/helpers.ts (client-injected) plus the
4
+ * pure epoch helper from src/commands/paymaster/status.ts.
5
+ *
6
+ * The PaymasterHub is a singleton shared across all orgs (one proxy per
7
+ * chain), so its address comes from the infrastructure query, not the org's
8
+ * module list.
9
+ *
10
+ * ── Where the numbers come from (KEEP — verified field-by-field) ────────────
11
+ * ENTRY_POINT, the OrgConfig, the fee caps and EVERY budget come from the
12
+ * subgraph (see graph/documents/paymaster.ts for the field-by-field
13
+ * verification against both live deployments). Three things deliberately
14
+ * STAY ON RPC — the schema has fields for some of them, but the VALUES are
15
+ * wrong on live rows:
16
+ * • getOrgFinancials — PaymasterOrgConfig.totalSpent/.depositBalance are
17
+ * indexed WITHOUT the 1.01x solidarity fee the hub also debits, so they
18
+ * sit at exactly 1/1.01 of the contract's `spent` on both live chains
19
+ * (proven to the wei on Gnosis and Arbitrum). `available` decides whether
20
+ * sponsorship still works, so it must be the chain's number. The call also
21
+ * carries solidarityUsedThisPeriod + periodStart, which have no subgraph
22
+ * field at all.
23
+ * • getSolidarityFund — numActiveOrgs and feePercentageBps have no field,
24
+ * the indexed solidarityBalance is stale on Gnosis (6376552300000000 wei
25
+ * high), and solidarityDistributionPaused reads `false` on Arbitrum while
26
+ * the contract reports `true`.
27
+ * • EntryPoint.balanceOf — the ERC-4337 singleton is not a subgraph data
28
+ * source.
29
+ *
30
+ * Two ways to read an org's paymaster config, and the difference matters:
31
+ *
32
+ * readPaymasterOrgConfig() — authoritative eth_call. Use it
33
+ * wherever the answer decides whether a transaction gets broadcast
34
+ * (deposit's OrgNotRegistered gate). Subgraph lag there means knowingly
35
+ * sending a doomed tx.
36
+ * readPaymasterOrgConfigPreferSubgraph() — subgraph first, but ONLY trusts a
37
+ * POSITIVE "registered" answer; a negative one is always re-confirmed on
38
+ * chain before anything is written. The subgraph can lag behind a fresh
39
+ * registration, it can never invent one, so a positive is safe to trust and
40
+ * a negative is not.
41
+ */
42
+ import { ethers } from 'ethers';
43
+ import type { GraphClient } from '../graph/client';
44
+ export interface PaymasterInfra {
45
+ paymasterHubAddress: string;
46
+ poaManagerAddress: string | null;
47
+ }
48
+ /** Resolve the chain's PaymasterHub proxy (+ PoaManager) from the subgraph. */
49
+ export declare function resolvePaymasterInfra(client: GraphClient, chainId?: number): Promise<PaymasterInfra>;
50
+ export interface PaymasterOrgConfig {
51
+ adminHatId: ethers.BigNumber;
52
+ operatorHatId: ethers.BigNumber;
53
+ paused: boolean;
54
+ registeredAt: number;
55
+ bannedFromSolidarity: boolean;
56
+ registered: boolean;
57
+ }
58
+ /** Fee caps in raw contract units (wei per gas / gas units). */
59
+ export interface PaymasterFeeCaps {
60
+ maxFeePerGas: ethers.BigNumber;
61
+ maxPriorityFeePerGas: ethers.BigNumber;
62
+ maxCallGas: number;
63
+ maxVerificationGas: number;
64
+ maxPreVerificationGas: number;
65
+ }
66
+ /** One budget row as the subgraph has it. `totalUsed` is null on the legacy tier. */
67
+ export interface PaymasterBudgetRecord {
68
+ subjectKey: string;
69
+ capPerEpoch: ethers.BigNumber;
70
+ usedInEpoch: ethers.BigNumber;
71
+ epochLen: number;
72
+ epochStart: number;
73
+ totalUsed: ethers.BigNumber | null;
74
+ }
75
+ export interface PaymasterSubgraphState {
76
+ /** Hub address the indexer knows about — cross-check before trusting the rest. */
77
+ hubAddress: string | null;
78
+ /** Checksummed to match what ENTRY_POINT() would have returned. */
79
+ entryPoint: string | null;
80
+ orgConfig: PaymasterOrgConfig | null;
81
+ /**
82
+ * All-zero when the org row exists but has no PaymasterFeeCaps edge — that is
83
+ * the contract's "never configured" default, verified against getFeeCaps() on
84
+ * five orgs across both live deployments. Null only when the org row itself is
85
+ * missing, in which case the caller must fall back to RPC.
86
+ */
87
+ feeCaps: PaymasterFeeCaps | null;
88
+ /** Null (not empty) when the org row is missing, so "no budgets" stays distinguishable. */
89
+ budgets: PaymasterBudgetRecord[] | null;
90
+ }
91
+ /**
92
+ * Read the hub state the subgraph can serve accurately: the immutable
93
+ * ENTRY_POINT, the org's OrgConfig, its fee caps and ALL of its budgets.
94
+ * Subgraph half of `pop paymaster status` (src/commands/paymaster/status.ts).
95
+ *
96
+ * Never throws — every failure (unreachable subgraph, chain with no deployment,
97
+ * unindexed org) degrades to nulls so the caller falls back to eth_calls.
98
+ *
99
+ * Financials and the solidarity fund are deliberately NOT here; see the module
100
+ * header for the measurements that disqualified them.
101
+ */
102
+ export declare function fetchPaymasterSubgraphState(client: GraphClient, orgId: string, chainId?: number): Promise<PaymasterSubgraphState>;
103
+ /**
104
+ * True when the indexed hub is the hub we independently resolved. A mismatch
105
+ * (redeployed hub the indexer has not caught up with, a hand-set
106
+ * POP_*_SUBGRAPH pointing at another network) means the org row describes a
107
+ * different contract, so the caller must ignore the whole state object.
108
+ */
109
+ export declare function subgraphMatchesHub(state: PaymasterSubgraphState, hubAddress: string): boolean;
110
+ /**
111
+ * Read the hub's OrgConfig for an org. `registered` is derived the same way
112
+ * the contract does it (adminHatId != 0 — see PaymasterHub._registerOrg).
113
+ *
114
+ * Authoritative eth_call. Keep using this one for revert-predicting gates.
115
+ */
116
+ export declare function readPaymasterOrgConfig(provider: ethers.providers.Provider, hubAddress: string, orgId: string): Promise<PaymasterOrgConfig>;
117
+ /**
118
+ * Registration read for callers that may go on to WRITE.
119
+ *
120
+ * Asymmetric on purpose: an indexed registration is trusted (saves the eth_call
121
+ * on the common "already registered" path), an absent one is re-read on chain
122
+ * before any decision is made. The subgraph only ever lags reality, so a
123
+ * false-negative is possible and a false-positive is not — re-confirming just
124
+ * the negative keeps revert prediction exactly as strong as pure RPC.
125
+ */
126
+ export declare function readPaymasterOrgConfigPreferSubgraph(client: GraphClient, provider: ethers.providers.Provider, hubAddress: string, orgId: string, chainId?: number): Promise<{
127
+ config: PaymasterOrgConfig;
128
+ source: 'subgraph' | 'rpc';
129
+ }>;
130
+ /** Subject key for a hat-scoped paymaster budget: the hat ID as bytes32. */
131
+ export declare function hatSubjectKey(hatId: ethers.BigNumberish): string;
132
+ /**
133
+ * Has this budget's epoch elapsed? Pure port of budgetEpochState from
134
+ * src/commands/paymaster/status.ts.
135
+ *
136
+ * PaymasterHub resets `usedInEpoch` LAZILY, on the next sponsored
137
+ * UserOperation, so a budget whose epoch elapsed months ago still reports the
138
+ * old spend — and getBudget() returns exactly the same stale figure the
139
+ * subgraph does (verified: both return 7993482525000000 for a Gnosis epoch
140
+ * that ended in May). Rather than present a stale number as current spend,
141
+ * check each row against epochStart + epochLen and report it as lapsed, with
142
+ * the effective (post-reset) spend of zero alongside the raw counter.
143
+ */
144
+ export declare function budgetEpochState(epochStart: number, epochLen: number, now: number): {
145
+ epochEnd: number | null;
146
+ expired: boolean;
147
+ };
@@ -0,0 +1,235 @@
1
+ "use strict";
2
+ /**
3
+ * Paymaster reads — PaymasterHub infrastructure resolution + org sponsorship
4
+ * state. Port of src/commands/paymaster/helpers.ts (client-injected) plus the
5
+ * pure epoch helper from src/commands/paymaster/status.ts.
6
+ *
7
+ * The PaymasterHub is a singleton shared across all orgs (one proxy per
8
+ * chain), so its address comes from the infrastructure query, not the org's
9
+ * module list.
10
+ *
11
+ * ── Where the numbers come from (KEEP — verified field-by-field) ────────────
12
+ * ENTRY_POINT, the OrgConfig, the fee caps and EVERY budget come from the
13
+ * subgraph (see graph/documents/paymaster.ts for the field-by-field
14
+ * verification against both live deployments). Three things deliberately
15
+ * STAY ON RPC — the schema has fields for some of them, but the VALUES are
16
+ * wrong on live rows:
17
+ * • getOrgFinancials — PaymasterOrgConfig.totalSpent/.depositBalance are
18
+ * indexed WITHOUT the 1.01x solidarity fee the hub also debits, so they
19
+ * sit at exactly 1/1.01 of the contract's `spent` on both live chains
20
+ * (proven to the wei on Gnosis and Arbitrum). `available` decides whether
21
+ * sponsorship still works, so it must be the chain's number. The call also
22
+ * carries solidarityUsedThisPeriod + periodStart, which have no subgraph
23
+ * field at all.
24
+ * • getSolidarityFund — numActiveOrgs and feePercentageBps have no field,
25
+ * the indexed solidarityBalance is stale on Gnosis (6376552300000000 wei
26
+ * high), and solidarityDistributionPaused reads `false` on Arbitrum while
27
+ * the contract reports `true`.
28
+ * • EntryPoint.balanceOf — the ERC-4337 singleton is not a subgraph data
29
+ * source.
30
+ *
31
+ * Two ways to read an org's paymaster config, and the difference matters:
32
+ *
33
+ * readPaymasterOrgConfig() — authoritative eth_call. Use it
34
+ * wherever the answer decides whether a transaction gets broadcast
35
+ * (deposit's OrgNotRegistered gate). Subgraph lag there means knowingly
36
+ * sending a doomed tx.
37
+ * readPaymasterOrgConfigPreferSubgraph() — subgraph first, but ONLY trusts a
38
+ * POSITIVE "registered" answer; a negative one is always re-confirmed on
39
+ * chain before anything is written. The subgraph can lag behind a fresh
40
+ * registration, it can never invent one, so a positive is safe to trust and
41
+ * a negative is not.
42
+ */
43
+ Object.defineProperty(exports, "__esModule", { value: true });
44
+ exports.resolvePaymasterInfra = resolvePaymasterInfra;
45
+ exports.fetchPaymasterSubgraphState = fetchPaymasterSubgraphState;
46
+ exports.subgraphMatchesHub = subgraphMatchesHub;
47
+ exports.readPaymasterOrgConfig = readPaymasterOrgConfig;
48
+ exports.readPaymasterOrgConfigPreferSubgraph = readPaymasterOrgConfigPreferSubgraph;
49
+ exports.hatSubjectKey = hatSubjectKey;
50
+ exports.budgetEpochState = budgetEpochState;
51
+ const ethers_1 = require("ethers");
52
+ const infrastructure_1 = require("../graph/documents/infrastructure");
53
+ const paymaster_1 = require("../graph/documents/paymaster");
54
+ const contracts_1 = require("../contracts");
55
+ const errors_1 = require("../errors");
56
+ /** Resolve the chain's PaymasterHub proxy (+ PoaManager) from the subgraph. */
57
+ async function resolvePaymasterInfra(client, chainId) {
58
+ const infra = await client.query(infrastructure_1.FETCH_INFRASTRUCTURE_ADDRESSES, {}, chainId);
59
+ const record = infra.poaManagerContracts?.[0];
60
+ const paymasterHubAddress = record?.paymasterHubProxy;
61
+ if (!paymasterHubAddress) {
62
+ throw new errors_1.PreconditionError('PaymasterHub not indexed for this chain.', 'The subgraph may still be syncing, or gas sponsorship is not deployed on this chain.');
63
+ }
64
+ return { paymasterHubAddress, poaManagerAddress: record?.id ?? null };
65
+ }
66
+ const EMPTY_STATE = {
67
+ hubAddress: null,
68
+ entryPoint: null,
69
+ orgConfig: null,
70
+ feeCaps: null,
71
+ budgets: null,
72
+ };
73
+ const ZERO_FEE_CAPS = {
74
+ maxFeePerGas: ethers_1.ethers.BigNumber.from(0),
75
+ maxPriorityFeePerGas: ethers_1.ethers.BigNumber.from(0),
76
+ maxCallGas: 0,
77
+ maxVerificationGas: 0,
78
+ maxPreVerificationGas: 0,
79
+ };
80
+ /**
81
+ * Read the hub state the subgraph can serve accurately: the immutable
82
+ * ENTRY_POINT, the org's OrgConfig, its fee caps and ALL of its budgets.
83
+ * Subgraph half of `pop paymaster status` (src/commands/paymaster/status.ts).
84
+ *
85
+ * Never throws — every failure (unreachable subgraph, chain with no deployment,
86
+ * unindexed org) degrades to nulls so the caller falls back to eth_calls.
87
+ *
88
+ * Financials and the solidarity fund are deliberately NOT here; see the module
89
+ * header for the measurements that disqualified them.
90
+ */
91
+ async function fetchPaymasterSubgraphState(client, orgId, chainId) {
92
+ let data;
93
+ try {
94
+ const result = await client.queryWithFieldFallback(paymaster_1.FETCH_PAYMASTER_STATE_TIERS.map(q => ({ query: q, variables: { orgId: orgId.toLowerCase() } })), { chainId });
95
+ data = result.data;
96
+ }
97
+ catch {
98
+ return EMPTY_STATE;
99
+ }
100
+ const hub = data?.paymasterHubContracts?.[0];
101
+ const row = data?.paymasterOrgConfigs?.[0];
102
+ let entryPoint = null;
103
+ if (hub?.entryPoint) {
104
+ // The subgraph stores Bytes lowercased; ENTRY_POINT() returns a checksummed
105
+ // address. Re-checksum so output is byte-identical either way.
106
+ try {
107
+ const checksummed = ethers_1.ethers.utils.getAddress(hub.entryPoint);
108
+ // The zero address is a documented PLACEHOLDER, not an answer. The mapping
109
+ // seeds hub.entryPoint = Address.zero() in getOrCreateHub, and the deploy
110
+ // path only fills it via a try_ENTRY_POINT() call that falls back to zero
111
+ // (PaymasterInitialized fires before InfrastructureDeployed, so
112
+ // handlePaymasterInitialized never runs for the initial deploy).
113
+ //
114
+ // getAddress() happily accepts it, so without this guard a placeholder
115
+ // becomes a non-null `entryPoint` that callers then use as an eth_call
116
+ // TARGET: balanceOf against address(0) returns '0x' and decoding throws
117
+ // CALL_EXCEPTION. null makes callers fall back to the ENTRY_POINT() read.
118
+ entryPoint = checksummed === ethers_1.ethers.constants.AddressZero ? null : checksummed;
119
+ }
120
+ catch {
121
+ entryPoint = null;
122
+ }
123
+ }
124
+ if (!row) {
125
+ return { ...EMPTY_STATE, hubAddress: hub?.id ?? null, entryPoint };
126
+ }
127
+ let orgConfig = null;
128
+ try {
129
+ const adminHatId = ethers_1.ethers.BigNumber.from(row.adminHatId);
130
+ orgConfig = {
131
+ adminHatId,
132
+ operatorHatId: ethers_1.ethers.BigNumber.from(row.operatorHatId),
133
+ paused: Boolean(row.isPaused),
134
+ registeredAt: Number(row.registeredAt ?? 0) || 0,
135
+ bannedFromSolidarity: Boolean(row.isBannedFromSolidarity),
136
+ // Derived exactly like PaymasterHub._registerOrg does it.
137
+ registered: !adminHatId.isZero(),
138
+ };
139
+ }
140
+ catch {
141
+ return { ...EMPTY_STATE, hubAddress: hub?.id ?? null, entryPoint };
142
+ }
143
+ const feeCaps = row.feeCaps
144
+ ? {
145
+ maxFeePerGas: ethers_1.ethers.BigNumber.from(row.feeCaps.maxFeePerGas),
146
+ maxPriorityFeePerGas: ethers_1.ethers.BigNumber.from(row.feeCaps.maxPriorityFeePerGas),
147
+ maxCallGas: Number(row.feeCaps.maxCallGas ?? 0),
148
+ maxVerificationGas: Number(row.feeCaps.maxVerificationGas ?? 0),
149
+ maxPreVerificationGas: Number(row.feeCaps.maxPreVerificationGas ?? 0),
150
+ }
151
+ : ZERO_FEE_CAPS;
152
+ const budgets = (row.budgets ?? []).map(b => ({
153
+ subjectKey: b.subjectKey,
154
+ capPerEpoch: ethers_1.ethers.BigNumber.from(b.capPerEpoch),
155
+ usedInEpoch: ethers_1.ethers.BigNumber.from(b.usedInEpoch),
156
+ epochLen: Number(b.epochLen ?? 0),
157
+ epochStart: Number(b.epochStart ?? 0),
158
+ totalUsed: b.totalUsed !== undefined && b.totalUsed !== null
159
+ ? ethers_1.ethers.BigNumber.from(b.totalUsed)
160
+ : null,
161
+ }));
162
+ return {
163
+ hubAddress: row.paymasterHub?.id ?? hub?.id ?? null,
164
+ entryPoint,
165
+ orgConfig,
166
+ feeCaps,
167
+ budgets,
168
+ };
169
+ }
170
+ /**
171
+ * True when the indexed hub is the hub we independently resolved. A mismatch
172
+ * (redeployed hub the indexer has not caught up with, a hand-set
173
+ * POP_*_SUBGRAPH pointing at another network) means the org row describes a
174
+ * different contract, so the caller must ignore the whole state object.
175
+ */
176
+ function subgraphMatchesHub(state, hubAddress) {
177
+ return !!state.hubAddress && state.hubAddress.toLowerCase() === hubAddress.toLowerCase();
178
+ }
179
+ /**
180
+ * Read the hub's OrgConfig for an org. `registered` is derived the same way
181
+ * the contract does it (adminHatId != 0 — see PaymasterHub._registerOrg).
182
+ *
183
+ * Authoritative eth_call. Keep using this one for revert-predicting gates.
184
+ */
185
+ async function readPaymasterOrgConfig(provider, hubAddress, orgId) {
186
+ const hub = (0, contracts_1.createReadContract)(hubAddress, 'PaymasterHub', provider);
187
+ const cfg = await hub.getOrgConfig(orgId);
188
+ const adminHatId = ethers_1.ethers.BigNumber.from(cfg.adminHatId);
189
+ return {
190
+ adminHatId,
191
+ operatorHatId: ethers_1.ethers.BigNumber.from(cfg.operatorHatId),
192
+ paused: Boolean(cfg.paused),
193
+ registeredAt: Number(cfg.registeredAt ?? 0),
194
+ bannedFromSolidarity: Boolean(cfg.bannedFromSolidarity),
195
+ registered: !adminHatId.isZero(),
196
+ };
197
+ }
198
+ /**
199
+ * Registration read for callers that may go on to WRITE.
200
+ *
201
+ * Asymmetric on purpose: an indexed registration is trusted (saves the eth_call
202
+ * on the common "already registered" path), an absent one is re-read on chain
203
+ * before any decision is made. The subgraph only ever lags reality, so a
204
+ * false-negative is possible and a false-positive is not — re-confirming just
205
+ * the negative keeps revert prediction exactly as strong as pure RPC.
206
+ */
207
+ async function readPaymasterOrgConfigPreferSubgraph(client, provider, hubAddress, orgId, chainId) {
208
+ const state = await fetchPaymasterSubgraphState(client, orgId, chainId);
209
+ if (state.orgConfig?.registered && subgraphMatchesHub(state, hubAddress)) {
210
+ return { config: state.orgConfig, source: 'subgraph' };
211
+ }
212
+ return { config: await readPaymasterOrgConfig(provider, hubAddress, orgId), source: 'rpc' };
213
+ }
214
+ /** Subject key for a hat-scoped paymaster budget: the hat ID as bytes32. */
215
+ function hatSubjectKey(hatId) {
216
+ return ethers_1.ethers.utils.hexZeroPad(ethers_1.ethers.BigNumber.from(hatId).toHexString(), 32);
217
+ }
218
+ /**
219
+ * Has this budget's epoch elapsed? Pure port of budgetEpochState from
220
+ * src/commands/paymaster/status.ts.
221
+ *
222
+ * PaymasterHub resets `usedInEpoch` LAZILY, on the next sponsored
223
+ * UserOperation, so a budget whose epoch elapsed months ago still reports the
224
+ * old spend — and getBudget() returns exactly the same stale figure the
225
+ * subgraph does (verified: both return 7993482525000000 for a Gnosis epoch
226
+ * that ended in May). Rather than present a stale number as current spend,
227
+ * check each row against epochStart + epochLen and report it as lapsed, with
228
+ * the effective (post-reset) spend of zero alongside the raw counter.
229
+ */
230
+ function budgetEpochState(epochStart, epochLen, now) {
231
+ if (!epochLen || !epochStart)
232
+ return { epochEnd: null, expired: false };
233
+ const epochEnd = epochStart + epochLen;
234
+ return { epochEnd, expired: now >= epochEnd };
235
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Project-domain subgraph reads and project-id resolution.
3
+ *
4
+ * Ports the read path of `pop project list` (src/commands/project/list.ts) and
5
+ * the project-input resolver shared by `pop project delete`
6
+ * (src/commands/project/delete.ts resolveProjectInput) onto the injected
7
+ * GraphClient. Projects live under the task domain's FETCH_PROJECTS_DATA
8
+ * document — there is no separate projects query.
9
+ */
10
+ import type { GraphClient } from '../graph/client';
11
+ import type { SubgraphProject } from './task';
12
+ /**
13
+ * List an org's (non-deleted) projects, tasks included.
14
+ * Port of the read at src/commands/project/list.ts:37 — a bare
15
+ * FETCH_PROJECTS_DATA query (no tier fallback; `pop project list` never used
16
+ * the deadline/release fields, so the base document always validates).
17
+ */
18
+ export declare function listProjects(client: GraphClient, orgId: string, chainId?: number): Promise<SubgraphProject[]>;
19
+ /**
20
+ * Resolve project input to the on-chain bytes32 pid:
21
+ * bytes32 hex and subgraph composite IDs resolve locally; a plain decimal
22
+ * maps to bytes32(uint) (on-chain pids are counters — verified against
23
+ * _createProjectCore in TaskManager.sol); anything else is treated as a
24
+ * project title and matched via the subgraph.
25
+ *
26
+ * Port of src/commands/project/delete.ts resolveProjectInput (same messages,
27
+ * same resolution order — note decimal beats title here, unlike task create's
28
+ * resolver which tries the title first).
29
+ */
30
+ export declare function resolveProjectInput(client: GraphClient, input: string, orgId: string, chainId?: number): Promise<{
31
+ pid: string;
32
+ title?: string;
33
+ }>;
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ /**
3
+ * Project-domain subgraph reads and project-id resolution.
4
+ *
5
+ * Ports the read path of `pop project list` (src/commands/project/list.ts) and
6
+ * the project-input resolver shared by `pop project delete`
7
+ * (src/commands/project/delete.ts resolveProjectInput) onto the injected
8
+ * GraphClient. Projects live under the task domain's FETCH_PROJECTS_DATA
9
+ * document — there is no separate projects query.
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.listProjects = listProjects;
13
+ exports.resolveProjectInput = resolveProjectInput;
14
+ const ethers_1 = require("ethers");
15
+ const task_1 = require("../graph/documents/task");
16
+ const encoding_1 = require("../encoding");
17
+ const errors_1 = require("../errors");
18
+ const exit_codes_1 = require("../exit-codes");
19
+ /**
20
+ * List an org's (non-deleted) projects, tasks included.
21
+ * Port of the read at src/commands/project/list.ts:37 — a bare
22
+ * FETCH_PROJECTS_DATA query (no tier fallback; `pop project list` never used
23
+ * the deadline/release fields, so the base document always validates).
24
+ */
25
+ async function listProjects(client, orgId, chainId) {
26
+ const result = await client.query(task_1.FETCH_PROJECTS_DATA, { orgId }, chainId);
27
+ return result.organization?.taskManager?.projects || [];
28
+ }
29
+ /**
30
+ * Resolve project input to the on-chain bytes32 pid:
31
+ * bytes32 hex and subgraph composite IDs resolve locally; a plain decimal
32
+ * maps to bytes32(uint) (on-chain pids are counters — verified against
33
+ * _createProjectCore in TaskManager.sol); anything else is treated as a
34
+ * project title and matched via the subgraph.
35
+ *
36
+ * Port of src/commands/project/delete.ts resolveProjectInput (same messages,
37
+ * same resolution order — note decimal beats title here, unlike task create's
38
+ * resolver which tries the title first).
39
+ */
40
+ async function resolveProjectInput(client, input, orgId, chainId) {
41
+ if (input.startsWith('0x') && input.length === 66)
42
+ return { pid: input };
43
+ if (/^0x[a-fA-F0-9]{40}-/.test(input))
44
+ return { pid: (0, encoding_1.parseProjectId)(input) };
45
+ if (/^\d+$/.test(input)) {
46
+ return { pid: ethers_1.ethers.utils.hexZeroPad(ethers_1.ethers.BigNumber.from(input).toHexString(), 32) };
47
+ }
48
+ // Title lookup via the subgraph (case-insensitive).
49
+ let projects = [];
50
+ try {
51
+ const result = await client.query(task_1.FETCH_PROJECTS_DATA, { orgId }, chainId);
52
+ projects = result.organization?.taskManager?.projects || [];
53
+ }
54
+ catch {
55
+ throw new errors_1.CliError(`Could not resolve project "${input}" — the subgraph is unavailable for title lookup.`, exit_codes_1.EXIT.INFRA, 'Pass the 0x-prefixed bytes32 project ID instead (pop project list --json).');
56
+ }
57
+ const match = projects.find((p) => (p.title || '').toLowerCase() === input.toLowerCase());
58
+ if (match)
59
+ return { pid: (0, encoding_1.parseProjectId)(match.id), title: match.title ?? undefined };
60
+ const available = projects.map((p) => p.title).filter(Boolean).join(', ');
61
+ throw new errors_1.CliError(`Project "${input}" not found.`, exit_codes_1.EXIT.USAGE, `Available projects: ${available || 'none'} (or pass the 0x-prefixed bytes32 project ID).`);
62
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Shared org/contract resolution helpers.
3
+ * Single source of truth for resolving org names to IDs and fetching contract
4
+ * addresses. Port of src/lib/resolve.ts: functions take the GraphClient
5
+ * explicitly instead of importing a process-global one.
6
+ */
7
+ import type { GraphClient } from '../graph/client';
8
+ /**
9
+ * Resolve an org identifier (name or hex ID) to its bytes32 ID.
10
+ * Throws a helpful error if org is not provided.
11
+ */
12
+ export declare function resolveOrgId(client: GraphClient, orgIdOrName: string | undefined, chainId?: number): Promise<string>;
13
+ export interface OrgModules {
14
+ orgId: string;
15
+ taskManagerAddress: string | null;
16
+ hybridVotingAddress: string | null;
17
+ ddVotingAddress: string | null;
18
+ participationTokenAddress: string | null;
19
+ educationHubAddress: string | null;
20
+ executorAddress: string | null;
21
+ quickJoinAddress: string | null;
22
+ eligibilityModuleAddress: string | null;
23
+ paymentManagerAddress: string | null;
24
+ /** ZkEmailInvites proxy — null for orgs deployed without the optional ZK Email module. */
25
+ zkEmailInvitesAddress: string | null;
26
+ }
27
+ /**
28
+ * Resolve an org's deployed module addresses via subgraph.
29
+ */
30
+ export declare function resolveOrgModules(client: GraphClient, orgIdOrName: string | undefined, chainId?: number): Promise<OrgModules>;
31
+ /**
32
+ * Require a specific module address, throwing a helpful error if not deployed.
33
+ */
34
+ export declare function requireModule(modules: OrgModules, moduleName: keyof OrgModules): string;
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ /**
3
+ * Shared org/contract resolution helpers.
4
+ * Single source of truth for resolving org names to IDs and fetching contract
5
+ * addresses. Port of src/lib/resolve.ts: functions take the GraphClient
6
+ * explicitly instead of importing a process-global one.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.resolveOrgId = resolveOrgId;
10
+ exports.resolveOrgModules = resolveOrgModules;
11
+ exports.requireModule = requireModule;
12
+ const org_1 = require("../graph/documents/org");
13
+ /**
14
+ * Resolve an org identifier (name or hex ID) to its bytes32 ID.
15
+ * Throws a helpful error if org is not provided.
16
+ */
17
+ async function resolveOrgId(client, orgIdOrName, chainId) {
18
+ if (!orgIdOrName) {
19
+ throw new Error('Missing --org flag. Provide --org or set POP_DEFAULT_ORG in .env');
20
+ }
21
+ if (orgIdOrName.startsWith('0x')) {
22
+ return orgIdOrName;
23
+ }
24
+ const result = await client.query(org_1.GET_ORG_BY_NAME, { name: orgIdOrName }, chainId);
25
+ if (!result.organizations?.length) {
26
+ throw new Error(`Organization "${orgIdOrName}" not found. Use the hex ID or check the org name.`);
27
+ }
28
+ return result.organizations[0].id;
29
+ }
30
+ /**
31
+ * Resolve an org's deployed module addresses via subgraph.
32
+ */
33
+ async function resolveOrgModules(client, orgIdOrName, chainId) {
34
+ const orgId = await resolveOrgId(client, orgIdOrName, chainId);
35
+ const result = await client.query(org_1.FETCH_ORG_BY_ID, { id: orgId }, chainId);
36
+ if (!result.organization) {
37
+ throw new Error(`Organization ${orgId} not found on this chain`);
38
+ }
39
+ const org = result.organization;
40
+ return {
41
+ orgId: org.id,
42
+ taskManagerAddress: org.taskManager?.id || null,
43
+ hybridVotingAddress: org.hybridVoting?.id || null,
44
+ ddVotingAddress: org.directDemocracyVoting?.id || null,
45
+ participationTokenAddress: org.participationToken?.id || null,
46
+ educationHubAddress: org.educationHub?.id || null,
47
+ executorAddress: org.executorContract?.id || null,
48
+ quickJoinAddress: org.quickJoin?.id || null,
49
+ eligibilityModuleAddress: org.eligibilityModule?.id || null,
50
+ paymentManagerAddress: org.paymentManager?.id || null,
51
+ zkEmailInvitesAddress: org.zkEmailInvites?.id || null,
52
+ };
53
+ }
54
+ /**
55
+ * Require a specific module address, throwing a helpful error if not deployed.
56
+ */
57
+ function requireModule(modules, moduleName) {
58
+ const addr = modules[moduleName];
59
+ if (!addr || typeof addr !== 'string') {
60
+ const friendlyName = moduleName.replace('Address', '').replace(/([A-Z])/g, ' $1').trim();
61
+ throw new Error(`Organization has no ${friendlyName} deployed`);
62
+ }
63
+ return addr;
64
+ }