@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,251 @@
1
+ "use strict";
2
+ /**
3
+ * Paymaster transaction builders — ports of `pop paymaster *` write paths
4
+ * (src/commands/paymaster/).
5
+ *
6
+ * buildDepositForOrg / depositForOrgIntent — pop paymaster deposit
7
+ * (PaymasterHub.depositForOrg(bytes32) payable — permissionless)
8
+ * buildRegisterCalldata / buildAdminCallRegister / registerOrgIntent —
9
+ * pop paymaster register (PoaManager.adminCall wrapping the
10
+ * registrar-gated registerOrg / registerAndConfigureOrg)
11
+ *
12
+ * Registration gate — VERIFIED against contracts origin/main
13
+ * src/PaymasterHub.sol: registerOrg / registerAndConfigureOrg are
14
+ * registrar-gated (_onlyRegistrar: msg.sender must be the PoaManager CONTRACT
15
+ * or the orgRegistrar, i.e. the OrgDeployer). No EOA can ever call them
16
+ * directly — the after-the-fact path is the PoaManager OWNER routing the call
17
+ * through PoaManager.adminCall(target, data). adminCall is NOT payable, so an
18
+ * initial deposit is always its own, separate depositForOrg transaction.
19
+ */
20
+ Object.defineProperty(exports, "__esModule", { value: true });
21
+ exports.DEPLOY_CONFIG_TUPLE = void 0;
22
+ exports.parsePaymasterHatId = parsePaymasterHatId;
23
+ exports.parseDepositAmount = parseDepositAmount;
24
+ exports.buildRegisterCalldata = buildRegisterCalldata;
25
+ exports.buildDepositForOrg = buildDepositForOrg;
26
+ exports.buildAdminCallRegister = buildAdminCallRegister;
27
+ exports.depositForOrgIntent = depositForOrgIntent;
28
+ exports.registerOrgIntent = registerOrgIntent;
29
+ const ethers_1 = require("ethers");
30
+ const contracts_1 = require("../contracts");
31
+ const resolve_1 = require("../reads/resolve");
32
+ const paymaster_1 = require("../reads/paymaster");
33
+ const errors_1 = require("../errors");
34
+ const exit_codes_1 = require("../exit-codes");
35
+ // ---------------------------------------------------------------------------
36
+ // Encoding — identical fragments/conversions to src/commands/paymaster/register.ts
37
+ // ---------------------------------------------------------------------------
38
+ /** DeployConfig struct shape — verified against PaymasterHub.sol origin/main. */
39
+ exports.DEPLOY_CONFIG_TUPLE = 'tuple(uint256 operatorHatId, uint256 maxFeePerGas, uint256 maxPriorityFeePerGas, '
40
+ + 'uint32 maxCallGas, uint32 maxVerificationGas, uint32 maxPreVerificationGas, '
41
+ + 'address[] ruleTargets, bytes4[] ruleSelectors, bool[] ruleAllowed, uint32[] ruleMaxCallGasHints, '
42
+ + 'bytes32[] budgetSubjectKeys, uint128[] budgetCapsPerEpoch, uint32[] budgetEpochLens)';
43
+ const REGISTER_IFACE = new ethers_1.ethers.utils.Interface([
44
+ 'function registerOrg(bytes32 orgId, uint256 adminHatId, uint256 operatorHatId)',
45
+ `function registerAndConfigureOrg(bytes32 orgId, uint256 adminHatId, ${exports.DEPLOY_CONFIG_TUPLE} config) payable`,
46
+ ]);
47
+ /** Parse a hat ID flag — BigNumber, never parseInt (Hats IDs exceed 2^53). */
48
+ function parsePaymasterHatId(input, flag) {
49
+ try {
50
+ return ethers_1.ethers.BigNumber.from(String(input).trim());
51
+ }
52
+ catch {
53
+ throw new errors_1.CliError(`Invalid ${flag} "${input}".`, exit_codes_1.EXIT.USAGE, 'Pass the hat ID as a decimal or 0x-hex integer (see pop org roles).');
54
+ }
55
+ }
56
+ /** Parse an amount in ether units of the native gas token — port of parseDepositAmount in src/commands/paymaster/deposit.ts. */
57
+ function parseDepositAmount(input) {
58
+ let wei;
59
+ try {
60
+ wei = ethers_1.ethers.utils.parseEther(String(input).trim());
61
+ }
62
+ catch {
63
+ throw new errors_1.CliError(`Invalid --amount "${input}".`, exit_codes_1.EXIT.USAGE, 'Pass the amount in ether units of the native gas token, e.g. --amount 0.05');
64
+ }
65
+ if (wei.lte(0)) {
66
+ throw new errors_1.CliError('Deposit amount must be greater than zero (the contract reverts ZeroAmount).', exit_codes_1.EXIT.USAGE);
67
+ }
68
+ return wei;
69
+ }
70
+ /**
71
+ * Build the registerOrg / registerAndConfigureOrg calldata from the hat IDs +
72
+ * the optional config (gwei fee caps + ether budget caps). Pure port of
73
+ * buildRegisterCalldata in src/commands/paymaster/register.ts — byte-for-byte
74
+ * identical encoding.
75
+ */
76
+ function buildRegisterCalldata(orgId, adminHatId, operatorHatId, config) {
77
+ if (!config) {
78
+ return {
79
+ method: 'registerOrg',
80
+ data: REGISTER_IFACE.encodeFunctionData('registerOrg', [orgId, adminHatId, operatorHatId]),
81
+ };
82
+ }
83
+ const rules = config.rules ?? [];
84
+ const budgets = (config.budgets ?? []).map((b) => {
85
+ const subjectKey = b.subjectKey
86
+ ?? (b.hatId !== undefined
87
+ ? ethers_1.ethers.utils.hexZeroPad(ethers_1.ethers.BigNumber.from(String(b.hatId)).toHexString(), 32)
88
+ : undefined);
89
+ if (!subjectKey) {
90
+ throw new errors_1.CliError('Each budget entry needs "subjectKey" (bytes32) or "hatId".', exit_codes_1.EXIT.USAGE);
91
+ }
92
+ return {
93
+ subjectKey,
94
+ capPerEpoch: ethers_1.ethers.utils.parseEther(String(b.capPerEpoch)),
95
+ epochLen: b.epochLen,
96
+ };
97
+ });
98
+ const deployConfig = {
99
+ operatorHatId: config.operatorHatId !== undefined
100
+ ? ethers_1.ethers.BigNumber.from(String(config.operatorHatId))
101
+ : operatorHatId,
102
+ maxFeePerGas: config.maxFeePerGas !== undefined ? ethers_1.ethers.utils.parseUnits(String(config.maxFeePerGas), 'gwei') : 0,
103
+ maxPriorityFeePerGas: config.maxPriorityFeePerGas !== undefined
104
+ ? ethers_1.ethers.utils.parseUnits(String(config.maxPriorityFeePerGas), 'gwei')
105
+ : 0,
106
+ maxCallGas: config.maxCallGas ?? 0,
107
+ maxVerificationGas: config.maxVerificationGas ?? 0,
108
+ maxPreVerificationGas: config.maxPreVerificationGas ?? 0,
109
+ ruleTargets: rules.map(r => r.target),
110
+ ruleSelectors: rules.map(r => r.selector),
111
+ ruleAllowed: rules.map(r => Boolean(r.allowed)),
112
+ ruleMaxCallGasHints: rules.map(r => r.maxCallGasHint ?? 0),
113
+ budgetSubjectKeys: budgets.map(b => b.subjectKey),
114
+ budgetCapsPerEpoch: budgets.map(b => b.capPerEpoch),
115
+ budgetEpochLens: budgets.map(b => b.epochLen),
116
+ };
117
+ return {
118
+ method: 'registerAndConfigureOrg',
119
+ data: REGISTER_IFACE.encodeFunctionData('registerAndConfigureOrg', [orgId, adminHatId, deployConfig]),
120
+ };
121
+ }
122
+ /**
123
+ * Port of `pop paymaster deposit` — src/commands/paymaster/deposit.ts:
124
+ * PaymasterHub.depositForOrg(bytes32 orgId) payable. PERMISSIONLESS ("anyone
125
+ * can deposit to any org"); reverts ZeroAmount on msg.value == 0 and
126
+ * OrgNotRegistered when the org has no paymaster config (adminHatId == 0).
127
+ * ONE-WAY on the deployed hub: no withdraw exists (PR #185 / audit M-04 not
128
+ * shipped) — funds draw down only as sponsored UserOperations consume them.
129
+ */
130
+ function buildDepositForOrg(a) {
131
+ return {
132
+ to: a.paymasterHubAddress,
133
+ abi: (0, contracts_1.getAbi)('PaymasterHub'),
134
+ method: 'depositForOrg',
135
+ args: [a.orgId],
136
+ value: a.amountWei,
137
+ meta: {
138
+ domain: 'paymaster',
139
+ action: 'deposit',
140
+ orgId: a.orgId,
141
+ summary: { paymasterHub: a.paymasterHubAddress, amountWei: String(a.amountWei) },
142
+ },
143
+ };
144
+ }
145
+ /**
146
+ * Port of the owner path of `pop paymaster register` —
147
+ * src/commands/paymaster/register.ts: PoaManager.adminCall(paymasterHub,
148
+ * registerCalldata). Only the PoaManager OWNER can send this (adminCall is
149
+ * onlyOwner); any other signer's transaction must revert — the CLI prints the
150
+ * calldata for the owner instead of broadcasting, which hosts can reproduce
151
+ * with buildRegisterCalldata + encodeIntent.
152
+ */
153
+ function buildAdminCallRegister(a) {
154
+ const { method, data } = buildRegisterCalldata(a.orgId, a.adminHatId, a.operatorHatId, a.config);
155
+ return {
156
+ to: a.poaManagerAddress,
157
+ abi: (0, contracts_1.getAbi)('PoaManager'),
158
+ method: 'adminCall',
159
+ args: [a.paymasterHubAddress, data],
160
+ meta: {
161
+ domain: 'paymaster',
162
+ action: 'register',
163
+ orgId: a.orgId,
164
+ summary: {
165
+ method,
166
+ paymasterHub: a.paymasterHubAddress,
167
+ adminHatId: a.adminHatId.toString(),
168
+ operatorHatId: a.operatorHatId.toString(),
169
+ registerCalldata: data,
170
+ },
171
+ },
172
+ };
173
+ }
174
+ /**
175
+ * Resolved port of `pop paymaster deposit` — src/commands/paymaster/deposit.ts.
176
+ * Resolves the org id and the chain's singleton PaymasterHub proxy from the
177
+ * infrastructure subgraph (the hub is NOT in the org's module list). When
178
+ * ctx.provider is present, replicates the CLI's authoritative
179
+ * OrgNotRegistered gate (an eth_call on purpose — subgraph lag in a
180
+ * revert-predicting read means knowingly broadcasting a doomed tx).
181
+ */
182
+ async function depositForOrgIntent(ctx, params) {
183
+ const amountWei = parseDepositAmount(params.amount);
184
+ const orgId = await (0, resolve_1.resolveOrgId)(ctx.client, params.org, ctx.chainId);
185
+ const { paymasterHubAddress } = await (0, paymaster_1.resolvePaymasterInfra)(ctx.client, ctx.chainId);
186
+ if (ctx.provider) {
187
+ const orgConfig = await (0, paymaster_1.readPaymasterOrgConfig)(ctx.provider, paymasterHubAddress, orgId);
188
+ if (!orgConfig.registered) {
189
+ throw new errors_1.PreconditionError(`Org ${params.org} is not registered with the PaymasterHub — depositForOrg would revert OrgNotRegistered.`, 'Register it first: pop paymaster register --admin-hat <hatId>');
190
+ }
191
+ }
192
+ return buildDepositForOrg({ paymasterHubAddress, orgId, amountWei });
193
+ }
194
+ /**
195
+ * Resolved port of `pop paymaster register` —
196
+ * src/commands/paymaster/register.ts (the adminCall route). Resolves the org
197
+ * id + PaymasterHub + PoaManager from the infrastructure subgraph and returns
198
+ * the PoaManager.adminCall intent.
199
+ *
200
+ * Registration check is asymmetric like the CLI: a POSITIVE indexed
201
+ * "registered" answer is trusted; a negative is re-confirmed on chain when
202
+ * ctx.provider is available. An already-registered org throws
203
+ * PreconditionError (the CLI reports it as a no-op success — builder callers
204
+ * need the hard stop, since the intent would be a doomed re-registration).
205
+ *
206
+ * NOTE the on-chain gate the builder cannot check for you: adminCall is
207
+ * onlyOwner on the PoaManager, and PoaManager.owner() has no subgraph field
208
+ * in either live deployment — the CLI reads it via eth_call and prints the
209
+ * calldata instead of broadcasting when the signer is not the owner. Hosts
210
+ * should do the same before executing this intent.
211
+ */
212
+ async function registerOrgIntent(ctx, params) {
213
+ const adminHatId = parsePaymasterHatId(params.adminHat, '--admin-hat');
214
+ const operatorHatId = params.operatorHat !== undefined
215
+ ? parsePaymasterHatId(params.operatorHat, '--operator-hat')
216
+ : ethers_1.ethers.BigNumber.from(0);
217
+ if (adminHatId.isZero()) {
218
+ throw new errors_1.CliError('--admin-hat cannot be 0 (the contract treats adminHatId==0 as unregistered).', exit_codes_1.EXIT.USAGE);
219
+ }
220
+ const orgId = await (0, resolve_1.resolveOrgId)(ctx.client, params.org, ctx.chainId);
221
+ const { paymasterHubAddress, poaManagerAddress } = await (0, paymaster_1.resolvePaymasterInfra)(ctx.client, ctx.chainId);
222
+ if (!poaManagerAddress) {
223
+ throw new errors_1.PreconditionError('PoaManager not indexed for this chain — cannot route the registrar-gated call through adminCall.', 'New orgs register automatically when deployed with a paymaster config block (pop org deploy).');
224
+ }
225
+ // Already registered? Subgraph first; only a POSITIVE answer is trusted, a
226
+ // negative is re-confirmed on chain (when a provider is available) — the
227
+ // indexer can lag behind a fresh registration and never invents one.
228
+ let registered;
229
+ if (ctx.provider) {
230
+ const { config } = await (0, paymaster_1.readPaymasterOrgConfigPreferSubgraph)(ctx.client, ctx.provider, paymasterHubAddress, orgId, ctx.chainId);
231
+ registered = config.registered;
232
+ }
233
+ else {
234
+ // No provider: only the subgraph's positive answer is usable — a negative
235
+ // cannot be re-confirmed, which is exactly the direction that is safe to
236
+ // proceed on (the tx itself re-checks on-chain).
237
+ const state = await (0, paymaster_1.fetchPaymasterSubgraphState)(ctx.client, orgId, ctx.chainId);
238
+ registered = Boolean(state.orgConfig?.registered && (0, paymaster_1.subgraphMatchesHub)(state, paymasterHubAddress));
239
+ }
240
+ if (registered) {
241
+ throw new errors_1.PreconditionError('Org is already registered with the PaymasterHub.', 'Fund it with: pop paymaster deposit');
242
+ }
243
+ return buildAdminCallRegister({
244
+ poaManagerAddress,
245
+ paymasterHubAddress,
246
+ orgId,
247
+ adminHatId,
248
+ operatorHatId,
249
+ config: params.config,
250
+ });
251
+ }
@@ -0,0 +1,146 @@
1
+ /**
2
+ * Project-domain transaction builders (TaskManagerNew createProject /
3
+ * deleteProject, plus the governance-wrapped propose path).
4
+ *
5
+ * Level 1 — pure builders returning TxIntents (or an ExecutionCall for the
6
+ * governance wrap). Level 2 — resolved builders that resolve the org, pin the
7
+ * `{description}` project metadata when given, and delegate. Same rules as
8
+ * tx/task: confirmation prompts, pre-flights and receipt parsing are host UX.
9
+ */
10
+ import { ethers } from 'ethers';
11
+ import type { TxIntent } from './intent';
12
+ import { type ExecutionCall } from './governance';
13
+ import type { PopContext } from '../context';
14
+ /**
15
+ * BootstrapProjectConfig inputs. Struct field order (verified against the
16
+ * createProject components in the synced TaskManagerNew ABI, and the send
17
+ * sites in project/create.ts + project/propose.ts):
18
+ * [title, metaHash, cap, managers, createHats, claimHats, reviewHats,
19
+ * assignHats, bountyTokens, bountyCaps].
20
+ */
21
+ export interface CreateProjectArgs {
22
+ taskManagerAddress: string;
23
+ /** Project name; encoded with stringToBytes here. */
24
+ name: string;
25
+ /** CIDv0 or bytes32 of the pinned `{description}` doc; omit ⇒ HashZero. */
26
+ metadataHash?: string;
27
+ /** Human PT cap (18 decimals applied here; 0/omitted = unlimited). */
28
+ cap?: number | string;
29
+ /** Manager addresses (project propose forces this empty — hat-based). */
30
+ managers?: string[];
31
+ createHats?: ethers.BigNumberish[];
32
+ claimHats?: ethers.BigNumberish[];
33
+ reviewHats?: ethers.BigNumberish[];
34
+ assignHats?: ethers.BigNumberish[];
35
+ /** Bounty token addresses (parallel to bountyCaps). */
36
+ bountyTokens?: string[];
37
+ /** Bounty caps in RAW wei, exactly as the CLI takes --bounty-caps. */
38
+ bountyCaps?: ethers.BigNumberish[];
39
+ orgId?: string;
40
+ }
41
+ /**
42
+ * The raw BootstrapProjectConfig tuple, shared by the direct and the
43
+ * governance-wrapped paths so the two cannot drift.
44
+ */
45
+ export declare function encodeProjectStruct(a: CreateProjectArgs): unknown[];
46
+ /**
47
+ * Port of `pop project create` — src/commands/project/create.ts
48
+ * (createProject send). Direct tx: _requireCreator() gates on-chain (creator
49
+ * hat or executor); permissions are not pre-checked.
50
+ */
51
+ export declare function buildCreateProject(a: CreateProjectArgs): TxIntent;
52
+ export interface DeleteProjectArgs {
53
+ taskManagerAddress: string;
54
+ /** Resolved bytes32 project id. */
55
+ projectId: string;
56
+ orgId?: string;
57
+ }
58
+ /**
59
+ * Port of `pop project delete` — src/commands/project/delete.ts
60
+ * (deleteProject send; DESTRUCTIVE — consent is host UX).
61
+ */
62
+ export declare function buildDeleteProject(a: DeleteProjectArgs): TxIntent;
63
+ /**
64
+ * The createProject(BootstrapProjectConfig) call the executor performs when a
65
+ * `pop project propose` vote passes — src/commands/project/propose.ts:97
66
+ * (encoded via the full TaskManagerNew ABI, exactly as the CLI's loadAbi path).
67
+ */
68
+ export declare function buildCreateProjectCall(a: CreateProjectArgs): ExecutionCall;
69
+ export interface ProposeProjectArgs {
70
+ hybridVotingAddress: string;
71
+ taskManagerAddress: string;
72
+ /** Project name (used for the struct AND the proposal title/option names). */
73
+ name: string;
74
+ /** CIDv0 or bytes32 of the pinned project `{description}` doc; omit ⇒ HashZero. */
75
+ metadataHash?: string;
76
+ /** Human PT cap (0/omitted = unlimited). */
77
+ cap?: number | string;
78
+ createHats?: ethers.BigNumberish[];
79
+ claimHats?: ethers.BigNumberish[];
80
+ reviewHats?: ethers.BigNumberish[];
81
+ assignHats?: ethers.BigNumberish[];
82
+ /** Vote duration in minutes. */
83
+ durationMinutes: ethers.BigNumberish;
84
+ /** CIDv0 or bytes32 of the pinned proposal metadata. */
85
+ descriptionHash: string;
86
+ orgId?: string;
87
+ }
88
+ /**
89
+ * Port of `pop project propose` — src/commands/project/propose.ts.
90
+ * HybridVoting.createProposal(`Create project: <name>`, descriptionHash,
91
+ * duration, 2, [[createProject call], []], []). Managers, bountyTokens and
92
+ * bountyCaps are forced empty (hat-based), matching the CLI struct.
93
+ */
94
+ export declare function buildProposeProject(a: ProposeProjectArgs): TxIntent;
95
+ export interface CreateProjectParams {
96
+ org: string;
97
+ name: string;
98
+ /** Pinned as `{description}` only when given (else metaHash = HashZero). */
99
+ description?: string;
100
+ cap?: number;
101
+ managers?: string[];
102
+ createHats?: Array<string | number>;
103
+ claimHats?: Array<string | number>;
104
+ reviewHats?: Array<string | number>;
105
+ assignHats?: Array<string | number>;
106
+ bountyTokens?: string[];
107
+ /** Raw wei values, as `--bounty-caps` takes them. */
108
+ bountyCaps?: Array<string | number>;
109
+ }
110
+ /**
111
+ * Port of `pop project create` — src/commands/project/create.ts. Resolves the
112
+ * org's TaskManager, pins the `{description}` metadata when provided, and
113
+ * delegates to buildCreateProject.
114
+ */
115
+ export declare function createProjectIntent(ctx: PopContext, p: CreateProjectParams): Promise<TxIntent>;
116
+ export interface DeleteProjectParams {
117
+ org: string;
118
+ /** bytes32 hex | composite '<tm>-<hex>' | decimal counter | title. */
119
+ project: string;
120
+ }
121
+ /**
122
+ * Port of `pop project delete` — src/commands/project/delete.ts. Resolves the
123
+ * project input (bytes32 / composite / decimal → bytes32(uint) / title via
124
+ * subgraph) and builds deleteProject. The existence pre-flight (lens
125
+ * PROJECT_INFO) and destructive consent are host UX.
126
+ */
127
+ export declare function deleteProjectIntent(ctx: PopContext, p: DeleteProjectParams): Promise<TxIntent>;
128
+ export interface ProposeProjectParams {
129
+ org: string;
130
+ name: string;
131
+ description?: string;
132
+ cap?: number;
133
+ /** Vote duration in minutes (CLI default 1440 = 24h). */
134
+ duration?: number;
135
+ createHats?: Array<string | number>;
136
+ claimHats?: Array<string | number>;
137
+ reviewHats?: Array<string | number>;
138
+ assignHats?: Array<string | number>;
139
+ }
140
+ /**
141
+ * Port of `pop project propose` — src/commands/project/propose.ts. Two pins:
142
+ * the project `{description}` doc (only when given) and the proposal metadata
143
+ * {description, optionNames, createdAt} with the CLI's exact strings. Then
144
+ * wraps the createProject calldata in a HybridVoting proposal.
145
+ */
146
+ export declare function proposeProjectIntent(ctx: PopContext, p: ProposeProjectParams): Promise<TxIntent>;
@@ -0,0 +1,217 @@
1
+ "use strict";
2
+ /**
3
+ * Project-domain transaction builders (TaskManagerNew createProject /
4
+ * deleteProject, plus the governance-wrapped propose path).
5
+ *
6
+ * Level 1 — pure builders returning TxIntents (or an ExecutionCall for the
7
+ * governance wrap). Level 2 — resolved builders that resolve the org, pin the
8
+ * `{description}` project metadata when given, and delegate. Same rules as
9
+ * tx/task: confirmation prompts, pre-flights and receipt parsing are host UX.
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.encodeProjectStruct = encodeProjectStruct;
13
+ exports.buildCreateProject = buildCreateProject;
14
+ exports.buildDeleteProject = buildDeleteProject;
15
+ exports.buildCreateProjectCall = buildCreateProjectCall;
16
+ exports.buildProposeProject = buildProposeProject;
17
+ exports.createProjectIntent = createProjectIntent;
18
+ exports.deleteProjectIntent = deleteProjectIntent;
19
+ exports.proposeProjectIntent = proposeProjectIntent;
20
+ const ethers_1 = require("ethers");
21
+ const governance_1 = require("./governance");
22
+ const contracts_1 = require("../contracts");
23
+ const encoding_1 = require("../encoding");
24
+ const ipfs_1 = require("../ipfs");
25
+ const errors_1 = require("../errors");
26
+ const exit_codes_1 = require("../exit-codes");
27
+ const resolve_1 = require("../reads/resolve");
28
+ const project_1 = require("../reads/project");
29
+ const task_1 = require("../metadata/task");
30
+ const proposal_1 = require("../metadata/proposal");
31
+ /**
32
+ * The raw BootstrapProjectConfig tuple, shared by the direct and the
33
+ * governance-wrapped paths so the two cannot drift.
34
+ */
35
+ function encodeProjectStruct(a) {
36
+ const cap = a.cap ? ethers_1.ethers.utils.parseUnits(a.cap.toString(), 18) : 0;
37
+ return [
38
+ (0, encoding_1.stringToBytes)(a.name),
39
+ a.metadataHash ? (0, encoding_1.ipfsCidToBytes32)(a.metadataHash) : ethers_1.ethers.constants.HashZero,
40
+ cap,
41
+ a.managers ?? [],
42
+ (a.createHats ?? []).map((h) => ethers_1.ethers.BigNumber.from(h)),
43
+ (a.claimHats ?? []).map((h) => ethers_1.ethers.BigNumber.from(h)),
44
+ (a.reviewHats ?? []).map((h) => ethers_1.ethers.BigNumber.from(h)),
45
+ (a.assignHats ?? []).map((h) => ethers_1.ethers.BigNumber.from(h)),
46
+ a.bountyTokens ?? [],
47
+ (a.bountyCaps ?? []).map((c) => ethers_1.ethers.BigNumber.from(c)),
48
+ ];
49
+ }
50
+ /**
51
+ * Port of `pop project create` — src/commands/project/create.ts
52
+ * (createProject send). Direct tx: _requireCreator() gates on-chain (creator
53
+ * hat or executor); permissions are not pre-checked.
54
+ */
55
+ function buildCreateProject(a) {
56
+ return {
57
+ to: a.taskManagerAddress,
58
+ abi: (0, contracts_1.getAbi)('TaskManagerNew'),
59
+ method: 'createProject',
60
+ args: [encodeProjectStruct(a)],
61
+ meta: {
62
+ domain: 'project',
63
+ action: 'create',
64
+ orgId: a.orgId,
65
+ summary: { name: a.name, cap: a.cap ? String(a.cap) : 'unlimited' },
66
+ },
67
+ };
68
+ }
69
+ /**
70
+ * Port of `pop project delete` — src/commands/project/delete.ts
71
+ * (deleteProject send; DESTRUCTIVE — consent is host UX).
72
+ */
73
+ function buildDeleteProject(a) {
74
+ return {
75
+ to: a.taskManagerAddress,
76
+ abi: (0, contracts_1.getAbi)('TaskManagerNew'),
77
+ method: 'deleteProject',
78
+ args: [a.projectId],
79
+ meta: { domain: 'project', action: 'delete', orgId: a.orgId, summary: { projectId: a.projectId } },
80
+ };
81
+ }
82
+ /**
83
+ * The createProject(BootstrapProjectConfig) call the executor performs when a
84
+ * `pop project propose` vote passes — src/commands/project/propose.ts:97
85
+ * (encoded via the full TaskManagerNew ABI, exactly as the CLI's loadAbi path).
86
+ */
87
+ function buildCreateProjectCall(a) {
88
+ return (0, governance_1.encodeExecutorCall)('TaskManagerNew', a.taskManagerAddress, 'createProject', [encodeProjectStruct(a)]);
89
+ }
90
+ /**
91
+ * Port of `pop project propose` — src/commands/project/propose.ts.
92
+ * HybridVoting.createProposal(`Create project: <name>`, descriptionHash,
93
+ * duration, 2, [[createProject call], []], []). Managers, bountyTokens and
94
+ * bountyCaps are forced empty (hat-based), matching the CLI struct.
95
+ */
96
+ function buildProposeProject(a) {
97
+ const call = buildCreateProjectCall({
98
+ taskManagerAddress: a.taskManagerAddress,
99
+ name: a.name,
100
+ metadataHash: a.metadataHash,
101
+ cap: a.cap,
102
+ managers: [], // hat-based instead
103
+ createHats: a.createHats,
104
+ claimHats: a.claimHats,
105
+ reviewHats: a.reviewHats,
106
+ assignHats: a.assignHats,
107
+ bountyTokens: [],
108
+ bountyCaps: [],
109
+ });
110
+ return (0, governance_1.buildGovernanceProposal)({
111
+ votingAddress: a.hybridVotingAddress,
112
+ votingAbiName: 'HybridVotingNew',
113
+ title: `Create project: ${a.name}`,
114
+ descriptionHash: (0, encoding_1.ipfsCidToBytes32)(a.descriptionHash),
115
+ durationMinutes: a.durationMinutes,
116
+ numOptions: 2,
117
+ batches: [
118
+ [call], // option 0: create project
119
+ [], // option 1: do nothing
120
+ ],
121
+ hatIds: [],
122
+ orgId: a.orgId,
123
+ domain: 'project',
124
+ action: 'propose',
125
+ summary: { name: a.name, cap: a.cap ? String(a.cap) : 'unlimited' },
126
+ });
127
+ }
128
+ /**
129
+ * Port of `pop project create` — src/commands/project/create.ts. Resolves the
130
+ * org's TaskManager, pins the `{description}` metadata when provided, and
131
+ * delegates to buildCreateProject.
132
+ */
133
+ async function createProjectIntent(ctx, p) {
134
+ const modules = await (0, resolve_1.resolveOrgModules)(ctx.client, p.org, ctx.chainId);
135
+ const taskManagerAddress = (0, resolve_1.requireModule)(modules, 'taskManagerAddress');
136
+ let metaCid;
137
+ let metadata;
138
+ if (p.description) {
139
+ metadata = (0, task_1.buildProjectMetadata)(p.description);
140
+ metaCid = await (0, ipfs_1.pinJson)((0, task_1.serializeProjectMetadata)(metadata), ctx.ipfs);
141
+ }
142
+ const intent = buildCreateProject({
143
+ taskManagerAddress,
144
+ name: p.name,
145
+ metadataHash: metaCid,
146
+ cap: p.cap,
147
+ managers: p.managers,
148
+ createHats: p.createHats,
149
+ claimHats: p.claimHats,
150
+ reviewHats: p.reviewHats,
151
+ assignHats: p.assignHats,
152
+ bountyTokens: p.bountyTokens,
153
+ bountyCaps: p.bountyCaps,
154
+ orgId: modules.orgId,
155
+ });
156
+ if (metaCid && metadata)
157
+ intent.meta.ipfs = { cid: metaCid, metadata };
158
+ return intent;
159
+ }
160
+ /**
161
+ * Port of `pop project delete` — src/commands/project/delete.ts. Resolves the
162
+ * project input (bytes32 / composite / decimal → bytes32(uint) / title via
163
+ * subgraph) and builds deleteProject. The existence pre-flight (lens
164
+ * PROJECT_INFO) and destructive consent are host UX.
165
+ */
166
+ async function deleteProjectIntent(ctx, p) {
167
+ const modules = await (0, resolve_1.resolveOrgModules)(ctx.client, p.org, ctx.chainId);
168
+ const taskManagerAddress = (0, resolve_1.requireModule)(modules, 'taskManagerAddress');
169
+ const { pid, title } = await (0, project_1.resolveProjectInput)(ctx.client, p.project, modules.orgId, ctx.chainId);
170
+ const intent = buildDeleteProject({ taskManagerAddress, projectId: pid, orgId: modules.orgId });
171
+ if (title && intent.meta.summary)
172
+ intent.meta.summary.title = title;
173
+ return intent;
174
+ }
175
+ /**
176
+ * Port of `pop project propose` — src/commands/project/propose.ts. Two pins:
177
+ * the project `{description}` doc (only when given) and the proposal metadata
178
+ * {description, optionNames, createdAt} with the CLI's exact strings. Then
179
+ * wraps the createProject calldata in a HybridVoting proposal.
180
+ */
181
+ async function proposeProjectIntent(ctx, p) {
182
+ const modules = await (0, resolve_1.resolveOrgModules)(ctx.client, p.org, ctx.chainId);
183
+ const taskManagerAddress = (0, resolve_1.requireModule)(modules, 'taskManagerAddress');
184
+ const hybridVotingAddress = modules.hybridVotingAddress;
185
+ if (!hybridVotingAddress) {
186
+ throw new errors_1.CliError('No HybridVoting found for this org', exit_codes_1.EXIT.PRECONDITION, 'This org cannot run governance proposals.');
187
+ }
188
+ const duration = p.duration ?? 1440;
189
+ // Pin project metadata to IPFS (only when a description was given).
190
+ let metaCid;
191
+ if (p.description) {
192
+ metaCid = await (0, ipfs_1.pinJson)((0, task_1.serializeProjectMetadata)((0, task_1.buildProjectMetadata)(p.description)), ctx.ipfs);
193
+ }
194
+ // Proposal metadata — key order {description, optionNames, createdAt} is a
195
+ // protocol contract; strings match project/propose.ts verbatim.
196
+ const proposalMeta = (0, proposal_1.buildProposalMetadata)({
197
+ description: `Create project "${p.name}"${p.description ? ': ' + p.description : ''}. PT cap: ${p.cap || 'unlimited'}. If this proposal passes, the project will be created automatically via execution call.`,
198
+ optionNames: [`Create "${p.name}"`, 'Do not create'],
199
+ });
200
+ const proposalCid = await (0, ipfs_1.pinJson)((0, proposal_1.serializeProposalMetadata)(proposalMeta), ctx.ipfs);
201
+ const intent = buildProposeProject({
202
+ hybridVotingAddress,
203
+ taskManagerAddress,
204
+ name: p.name,
205
+ metadataHash: metaCid,
206
+ cap: p.cap,
207
+ createHats: p.createHats,
208
+ claimHats: p.claimHats,
209
+ reviewHats: p.reviewHats,
210
+ assignHats: p.assignHats,
211
+ durationMinutes: duration,
212
+ descriptionHash: proposalCid,
213
+ orgId: modules.orgId,
214
+ });
215
+ intent.meta.ipfs = { cid: proposalCid, metadata: proposalMeta };
216
+ return intent;
217
+ }