@poa-box/core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +201 -0
- package/dist/abis/DirectDemocracyVotingNew.d.ts +749 -0
- package/dist/abis/DirectDemocracyVotingNew.js +961 -0
- package/dist/abis/ERC20.d.ts +90 -0
- package/dist/abis/ERC20.js +125 -0
- package/dist/abis/EducationHubNew.d.ts +590 -0
- package/dist/abis/EducationHubNew.js +762 -0
- package/dist/abis/EligibilityModuleNew.d.ts +1615 -0
- package/dist/abis/EligibilityModuleNew.js +2082 -0
- package/dist/abis/Executor.d.ts +619 -0
- package/dist/abis/Executor.js +796 -0
- package/dist/abis/HybridVotingNew.d.ts +898 -0
- package/dist/abis/HybridVotingNew.js +1149 -0
- package/dist/abis/ImplementationRegistry.d.ts +270 -0
- package/dist/abis/ImplementationRegistry.js +355 -0
- package/dist/abis/OrgDeployerNew.d.ts +1275 -0
- package/dist/abis/OrgDeployerNew.js +1630 -0
- package/dist/abis/OrgRegistry.d.ts +670 -0
- package/dist/abis/OrgRegistry.js +868 -0
- package/dist/abis/ParticipationToken.d.ts +1086 -0
- package/dist/abis/ParticipationToken.js +1415 -0
- package/dist/abis/PasskeyAccount.d.ts +788 -0
- package/dist/abis/PasskeyAccount.js +1019 -0
- package/dist/abis/PasskeyAccountFactory.d.ts +344 -0
- package/dist/abis/PasskeyAccountFactory.js +449 -0
- package/dist/abis/PaymasterHub.d.ts +1603 -0
- package/dist/abis/PaymasterHub.js +2048 -0
- package/dist/abis/PaymentManager.d.ts +520 -0
- package/dist/abis/PaymentManager.js +671 -0
- package/dist/abis/PoaManager.d.ts +344 -0
- package/dist/abis/PoaManager.js +449 -0
- package/dist/abis/QuickJoinNew.d.ts +855 -0
- package/dist/abis/QuickJoinNew.js +1098 -0
- package/dist/abis/TaskManagerNew.d.ts +1236 -0
- package/dist/abis/TaskManagerNew.js +1573 -0
- package/dist/abis/ToggleModule.d.ts +193 -0
- package/dist/abis/ToggleModule.js +255 -0
- package/dist/abis/UniversalAccountRegistry.d.ts +577 -0
- package/dist/abis/UniversalAccountRegistry.js +750 -0
- package/dist/abis/ZkEmailInvites.d.ts +823 -0
- package/dist/abis/ZkEmailInvites.js +1060 -0
- package/dist/abis/external/AaveGovernanceV2.d.ts +128 -0
- package/dist/abis/external/AaveGovernanceV2.js +177 -0
- package/dist/abis/external/AaveGovernanceV3.d.ts +160 -0
- package/dist/abis/external/AaveGovernanceV3.js +220 -0
- package/dist/abis/external/AragonVoting.d.ts +107 -0
- package/dist/abis/external/AragonVoting.js +150 -0
- package/dist/abis/external/CurveGaugeController.d.ts +95 -0
- package/dist/abis/external/CurveGaugeController.js +130 -0
- package/dist/abis/external/CurveVotingEscrow.d.ts +86 -0
- package/dist/abis/external/CurveVotingEscrow.js +116 -0
- package/dist/abis/external/GovernorAlpha.d.ts +172 -0
- package/dist/abis/external/GovernorAlpha.js +228 -0
- package/dist/abis/external/MakerDAOChief.d.ts +92 -0
- package/dist/abis/external/MakerDAOChief.js +129 -0
- package/dist/abis/external/OZGovernor.d.ts +227 -0
- package/dist/abis/external/OZGovernor.js +317 -0
- package/dist/abis/external/SolidlyVotingEscrow.d.ts +196 -0
- package/dist/abis/external/SolidlyVotingEscrow.js +260 -0
- package/dist/abis/index.d.ts +62 -0
- package/dist/abis/index.js +98 -0
- package/dist/chains.d.ts +150 -0
- package/dist/chains.js +320 -0
- package/dist/context.d.ts +48 -0
- package/dist/context.js +38 -0
- package/dist/contracts.d.ts +24 -0
- package/dist/contracts.js +41 -0
- package/dist/encoding.d.ts +58 -0
- package/dist/encoding.js +243 -0
- package/dist/env.d.ts +10 -0
- package/dist/env.js +4 -0
- package/dist/error-catalog.d.ts +41 -0
- package/dist/error-catalog.js +941 -0
- package/dist/errors.d.ts +27 -0
- package/dist/errors.js +60 -0
- package/dist/execute/ethers.d.ts +93 -0
- package/dist/execute/ethers.js +323 -0
- package/dist/execute/index.d.ts +7 -0
- package/dist/execute/index.js +23 -0
- package/dist/execute/sponsored.d.ts +68 -0
- package/dist/execute/sponsored.js +277 -0
- package/dist/exit-codes.d.ts +18 -0
- package/dist/exit-codes.js +21 -0
- package/dist/format.d.ts +21 -0
- package/dist/format.js +89 -0
- package/dist/graph/client.d.ts +298 -0
- package/dist/graph/client.js +702 -0
- package/dist/graph/documents/activity.d.ts +9 -0
- package/dist/graph/documents/activity.js +164 -0
- package/dist/graph/documents/beacons.d.ts +172 -0
- package/dist/graph/documents/beacons.js +345 -0
- package/dist/graph/documents/index.d.ts +21 -0
- package/dist/graph/documents/index.js +57 -0
- package/dist/graph/documents/infrastructure.d.ts +30 -0
- package/dist/graph/documents/infrastructure.js +34 -0
- package/dist/graph/documents/org.d.ts +15 -0
- package/dist/graph/documents/org.js +249 -0
- package/dist/graph/documents/paymaster.d.ts +95 -0
- package/dist/graph/documents/paymaster.js +101 -0
- package/dist/graph/documents/role.d.ts +6 -0
- package/dist/graph/documents/role.js +41 -0
- package/dist/graph/documents/roles.d.ts +50 -0
- package/dist/graph/documents/roles.js +112 -0
- package/dist/graph/documents/task.d.ts +84 -0
- package/dist/graph/documents/task.js +236 -0
- package/dist/graph/documents/token.d.ts +13 -0
- package/dist/graph/documents/token.js +126 -0
- package/dist/graph/documents/treasury.d.ts +39 -0
- package/dist/graph/documents/treasury.js +136 -0
- package/dist/graph/documents/user.d.ts +120 -0
- package/dist/graph/documents/user.js +302 -0
- package/dist/graph/documents/voting-classes.d.ts +69 -0
- package/dist/graph/documents/voting-classes.js +149 -0
- package/dist/graph/documents/voting.d.ts +28 -0
- package/dist/graph/documents/voting.js +163 -0
- package/dist/graph/documents/vouch.d.ts +79 -0
- package/dist/graph/documents/vouch.js +171 -0
- package/dist/graph/documents/zkemail.d.ts +63 -0
- package/dist/graph/documents/zkemail.js +188 -0
- package/dist/graph/index.d.ts +2 -0
- package/dist/graph/index.js +41 -0
- package/dist/index.d.ts +49 -0
- package/dist/index.js +92 -0
- package/dist/ipfs.d.ts +39 -0
- package/dist/ipfs.js +214 -0
- package/dist/label-aliases.d.ts +31 -0
- package/dist/label-aliases.js +70 -0
- package/dist/metadata/education.d.ts +30 -0
- package/dist/metadata/education.js +31 -0
- package/dist/metadata/index.d.ts +12 -0
- package/dist/metadata/index.js +48 -0
- package/dist/metadata/org.d.ts +92 -0
- package/dist/metadata/org.js +93 -0
- package/dist/metadata/proposal.d.ts +44 -0
- package/dist/metadata/proposal.js +45 -0
- package/dist/metadata/role.d.ts +38 -0
- package/dist/metadata/role.js +35 -0
- package/dist/metadata/task.d.ts +108 -0
- package/dist/metadata/task.js +81 -0
- package/dist/metadata/token.d.ts +32 -0
- package/dist/metadata/token.js +36 -0
- package/dist/metadata/user.d.ts +63 -0
- package/dist/metadata/user.js +70 -0
- package/dist/multicall.d.ts +32 -0
- package/dist/multicall.js +96 -0
- package/dist/payout.d.ts +59 -0
- package/dist/payout.js +96 -0
- package/dist/perms.d.ts +47 -0
- package/dist/perms.js +120 -0
- package/dist/preflight.d.ts +72 -0
- package/dist/preflight.js +269 -0
- package/dist/reads/education.d.ts +79 -0
- package/dist/reads/education.js +122 -0
- package/dist/reads/eligibility.d.ts +377 -0
- package/dist/reads/eligibility.js +687 -0
- package/dist/reads/index.d.ts +16 -0
- package/dist/reads/index.js +55 -0
- package/dist/reads/org.d.ts +258 -0
- package/dist/reads/org.js +220 -0
- package/dist/reads/paymaster.d.ts +147 -0
- package/dist/reads/paymaster.js +235 -0
- package/dist/reads/project.d.ts +33 -0
- package/dist/reads/project.js +62 -0
- package/dist/reads/resolve.d.ts +34 -0
- package/dist/reads/resolve.js +64 -0
- package/dist/reads/task.d.ts +286 -0
- package/dist/reads/task.js +280 -0
- package/dist/reads/token.d.ts +94 -0
- package/dist/reads/token.js +75 -0
- package/dist/reads/treasury.d.ts +222 -0
- package/dist/reads/treasury.js +241 -0
- package/dist/reads/user.d.ts +229 -0
- package/dist/reads/user.js +155 -0
- package/dist/reads/vote.d.ts +296 -0
- package/dist/reads/vote.js +392 -0
- package/dist/reads/zkemail.d.ts +117 -0
- package/dist/reads/zkemail.js +217 -0
- package/dist/similarity.d.ts +36 -0
- package/dist/similarity.js +67 -0
- package/dist/sponsorship-config.d.ts +47 -0
- package/dist/sponsorship-config.js +41 -0
- package/dist/stats.d.ts +11 -0
- package/dist/stats.js +27 -0
- package/dist/task-lens.d.ts +113 -0
- package/dist/task-lens.js +210 -0
- package/dist/tx/education.d.ts +169 -0
- package/dist/tx/education.js +344 -0
- package/dist/tx/eligibility.d.ts +511 -0
- package/dist/tx/eligibility.js +818 -0
- package/dist/tx/governance.d.ts +85 -0
- package/dist/tx/governance.js +87 -0
- package/dist/tx/index.d.ts +17 -0
- package/dist/tx/index.js +56 -0
- package/dist/tx/intent.d.ts +67 -0
- package/dist/tx/intent.js +48 -0
- package/dist/tx/org.d.ts +321 -0
- package/dist/tx/org.js +544 -0
- package/dist/tx/paymaster.d.ts +140 -0
- package/dist/tx/paymaster.js +251 -0
- package/dist/tx/project.d.ts +146 -0
- package/dist/tx/project.js +217 -0
- package/dist/tx/task.d.ts +480 -0
- package/dist/tx/task.js +1149 -0
- package/dist/tx/token.d.ts +96 -0
- package/dist/tx/token.js +165 -0
- package/dist/tx/treasury.d.ts +474 -0
- package/dist/tx/treasury.js +911 -0
- package/dist/tx/user.d.ts +177 -0
- package/dist/tx/user.js +292 -0
- package/dist/tx/vote.d.ts +332 -0
- package/dist/tx/vote.js +762 -0
- package/dist/tx/zkemail.d.ts +90 -0
- package/dist/tx/zkemail.js +210 -0
- package/dist/validation.d.ts +8 -0
- package/dist/validation.js +39 -0
- package/dist/version.d.ts +142 -0
- package/dist/version.js +257 -0
- package/dist/zkemail.d.ts +161 -0
- package/dist/zkemail.js +299 -0
- package/package.json +130 -0
|
@@ -0,0 +1,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
|
+
}
|