@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,277 @@
1
+ "use strict";
2
+ /**
3
+ * EIP-7702 Gas Sponsorship
4
+ *
5
+ * Uses the org PaymasterHub to sponsor agent transaction gas.
6
+ * Flow: Agent EOA → EIP-7702 delegation → UserOp via Pimlico bundler → PaymasterHub pays gas.
7
+ *
8
+ * Based on the poa-frontend EOA7702TransactionManager + userOpBuilder implementation.
9
+ *
10
+ * Prerequisites:
11
+ * - Agent registered in UniversalAccountRegistry
12
+ * - Agent wears a hat in the org
13
+ * - `pimlicoApiKey` or `bundlerUrl` provided via SponsoredSendOptions
14
+ * (the CLI passes PIMLICO_API_KEY / POP_BUNDLER_URL from env)
15
+ */
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.ENTRY_POINT = exports.PAYMASTER_HUB = exports.EOA_DELEGATION = void 0;
18
+ exports.encodePaymasterData = encodePaymasterData;
19
+ exports.isDelegated = isDelegated;
20
+ exports.delegateEOA = delegateEOA;
21
+ exports.getUserOpHash = getUserOpHash;
22
+ exports.sendSponsored = sendSponsored;
23
+ exports.encodeCall = encodeCall;
24
+ const viem_1 = require("viem");
25
+ const chains_1 = require("viem/chains");
26
+ const accounts_1 = require("viem/accounts");
27
+ const pimlico_1 = require("permissionless/clients/pimlico");
28
+ const account_abstraction_1 = require("viem/account-abstraction");
29
+ // Contract addresses (Gnosis)
30
+ exports.EOA_DELEGATION = '0x776ec88A88E86e38d54a985983377f1A2A25ef8b';
31
+ exports.PAYMASTER_HUB = '0xdEf1038C297493c0b5f82F0CDB49e929B53B4108';
32
+ exports.ENTRY_POINT = account_abstraction_1.entryPoint07Address;
33
+ const GAS_BUFFER_PERCENT = 10n;
34
+ const DUMMY_ECDSA_SIGNATURE = ('0x' + 'ff'.repeat(65));
35
+ /**
36
+ * Encode paymaster data for the PaymasterHub.
37
+ * Format: version(1) | orgId(32) | subjectType=0x01(1) | hatId(32) | ruleId(4) | mailboxCommit(8)
38
+ * Total: 78 bytes (must match frontend encoding exactly)
39
+ */
40
+ function encodePaymasterData(orgId, hatId) {
41
+ const version = (0, viem_1.toHex)(0x01, { size: 1 });
42
+ const paddedOrgId = (0, viem_1.pad)(orgId, { size: 32 });
43
+ const subjectType = (0, viem_1.toHex)(0x01, { size: 1 }); // HAT
44
+ const paddedHatId = (0, viem_1.toHex)(hatId, { size: 32 });
45
+ const ruleId = (0, viem_1.toHex)(0, { size: 4 });
46
+ const mailboxCommit = (0, viem_1.toHex)(0n, { size: 8 });
47
+ return (0, viem_1.concat)([version, paddedOrgId, subjectType, paddedHatId, ruleId, mailboxCommit]);
48
+ }
49
+ /**
50
+ * Check if an EOA has already delegated to EOADelegation.
51
+ */
52
+ async function isDelegated(address, rpcUrl) {
53
+ const client = (0, viem_1.createPublicClient)({
54
+ chain: chains_1.gnosis,
55
+ transport: (0, viem_1.http)(rpcUrl || 'https://rpc.gnosischain.com'),
56
+ });
57
+ const code = await client.getCode({ address });
58
+ return code !== undefined && code !== '0x' && code.startsWith('0xef0100');
59
+ }
60
+ /**
61
+ * Sign EIP-7702 authorization to delegate EOA to EOADelegation contract.
62
+ * This is a one-time setup — after delegation, the EOA can receive UserOps.
63
+ */
64
+ async function delegateEOA(privateKey, rpcUrl) {
65
+ const account = (0, accounts_1.privateKeyToAccount)(privateKey);
66
+ const walletClient = (0, viem_1.createWalletClient)({
67
+ account,
68
+ chain: chains_1.gnosis,
69
+ transport: (0, viem_1.http)(rpcUrl || 'https://rpc.gnosischain.com'),
70
+ });
71
+ const authorization = await walletClient.signAuthorization({
72
+ contractAddress: exports.EOA_DELEGATION,
73
+ executor: 'self',
74
+ });
75
+ const hash = await walletClient.sendTransaction({
76
+ authorizationList: [authorization],
77
+ to: account.address,
78
+ data: '0x',
79
+ });
80
+ return hash;
81
+ }
82
+ /**
83
+ * Pack two uint128 values into a single bytes32.
84
+ * high128 || low128
85
+ */
86
+ function packUint128Pair(high, low) {
87
+ return (0, viem_1.pad)((0, viem_1.toHex)((BigInt(high) << 128n) | BigInt(low)), { size: 32 });
88
+ }
89
+ function applyBuffer(value) {
90
+ return (BigInt(value) * (100n + GAS_BUFFER_PERCENT)) / 100n;
91
+ }
92
+ /**
93
+ * Compute the UserOp hash per EIP-4337 v0.7 (PackedUserOperation) spec.
94
+ * Ported from poa-frontend userOpBuilder.js getUserOpHash().
95
+ */
96
+ function getUserOpHash(userOp, entryPoint, chainId) {
97
+ // Reconstruct paymasterAndData
98
+ let paymasterAndData = '0x';
99
+ if (userOp.paymaster) {
100
+ const pmVerGas = (0, viem_1.pad)((0, viem_1.toHex)(userOp.paymasterVerificationGasLimit || 0n), { size: 16 });
101
+ const pmPostGas = (0, viem_1.pad)((0, viem_1.toHex)(userOp.paymasterPostOpGasLimit || 0n), { size: 16 });
102
+ if (userOp.paymasterData && userOp.paymasterData !== '0x') {
103
+ paymasterAndData = (0, viem_1.concat)([userOp.paymaster, pmVerGas, pmPostGas, userOp.paymasterData]);
104
+ }
105
+ else {
106
+ paymasterAndData = (0, viem_1.concat)([userOp.paymaster, pmVerGas, pmPostGas]);
107
+ }
108
+ }
109
+ const accountGasLimits = packUint128Pair(userOp.verificationGasLimit, userOp.callGasLimit);
110
+ const gasFees = packUint128Pair(userOp.maxPriorityFeePerGas, userOp.maxFeePerGas);
111
+ const packed = (0, viem_1.encodeAbiParameters)((0, viem_1.parseAbiParameters)('address, uint256, bytes32, bytes32, bytes32, uint256, bytes32, bytes32'), [
112
+ userOp.sender,
113
+ userOp.nonce,
114
+ (0, viem_1.keccak256)('0x'), // no initCode for already-deployed EOA
115
+ (0, viem_1.keccak256)(userOp.callData),
116
+ accountGasLimits,
117
+ userOp.preVerificationGas,
118
+ gasFees,
119
+ (0, viem_1.keccak256)(paymasterAndData),
120
+ ]);
121
+ const userOpPacked = (0, viem_1.keccak256)(packed);
122
+ return (0, viem_1.keccak256)((0, viem_1.encodeAbiParameters)((0, viem_1.parseAbiParameters)('bytes32, address, uint256'), [userOpPacked, entryPoint, BigInt(chainId)]));
123
+ }
124
+ /**
125
+ * Send a sponsored transaction via Pimlico bundler.
126
+ * The PaymasterHub pays for gas — agent pays nothing.
127
+ *
128
+ * Follows the same flow as poa-frontend EOA7702TransactionManager:
129
+ * 1. Encode call in EOADelegation.execute() wrapper
130
+ * 2. Build UserOp with paymaster data and dummy signature
131
+ * 3. Estimate gas via bundler
132
+ * 4. Compute UserOp hash (EIP-4337 v0.7 packed format)
133
+ * 5. Sign with wallet (ECDSA via signMessage — EIP-191 prefix)
134
+ * 6. Submit to bundler and wait for receipt
135
+ */
136
+ async function sendSponsored(privateKey, to, data, orgId, hatId, options) {
137
+ // Task #425: bundlerUrl (CLI: POP_BUNDLER_URL) for self-hosted bundler support.
138
+ // When set, uses the local bundler (e.g. Skandha at localhost:14337).
139
+ // When unset, falls back to Pimlico. Zero-downtime migration path.
140
+ const bundlerOverride = options?.bundlerUrl;
141
+ const apiKey = bundlerOverride ? null : options?.pimlicoApiKey;
142
+ if (!bundlerOverride && !apiKey) {
143
+ throw new Error('Set bundlerUrl (env: POP_BUNDLER_URL) for self-hosted bundler or pimlicoApiKey (env: PIMLICO_API_KEY) for Pimlico. See reports/research/self-hosted-bundler-research.md.');
144
+ }
145
+ const rpcUrl = options?.rpcUrl || 'https://rpc.gnosischain.com';
146
+ const account = (0, accounts_1.privateKeyToAccount)(privateKey);
147
+ const pimlicoUrl = bundlerOverride || `https://api.pimlico.io/v2/${chains_1.gnosis.id}/rpc?apikey=${apiKey}`;
148
+ // Check delegation
149
+ const delegated = await isDelegated(account.address, rpcUrl);
150
+ if (!delegated) {
151
+ throw new Error(`EOA ${account.address} not delegated to EOADelegation. ` +
152
+ `Run 'pop agent delegate' first to set up EIP-7702 delegation.`);
153
+ }
154
+ const walletClient = (0, viem_1.createWalletClient)({
155
+ account,
156
+ chain: chains_1.gnosis,
157
+ transport: (0, viem_1.http)(rpcUrl),
158
+ });
159
+ const publicClient = (0, viem_1.createPublicClient)({
160
+ chain: chains_1.gnosis,
161
+ transport: (0, viem_1.http)(rpcUrl),
162
+ });
163
+ const pimlicoClient = (0, pimlico_1.createPimlicoClient)({
164
+ chain: chains_1.gnosis,
165
+ transport: (0, viem_1.http)(pimlicoUrl),
166
+ entryPoint: {
167
+ address: exports.ENTRY_POINT,
168
+ version: '0.7',
169
+ },
170
+ });
171
+ // Encode paymaster data
172
+ const paymasterData = encodePaymasterData(orgId, hatId);
173
+ // EOADelegation.execute(target, value, data) — same ABI as PasskeyAccount.execute
174
+ const executeAbi = [{
175
+ name: 'execute',
176
+ type: 'function',
177
+ inputs: [
178
+ { name: 'target', type: 'address' },
179
+ { name: 'value', type: 'uint256' },
180
+ { name: 'data', type: 'bytes' },
181
+ ],
182
+ outputs: [],
183
+ stateMutability: 'nonpayable',
184
+ }];
185
+ const callData = (0, viem_1.encodeFunctionData)({
186
+ abi: executeAbi,
187
+ functionName: 'execute',
188
+ args: [to, options?.value || 0n, data],
189
+ });
190
+ // Fetch nonce and gas prices in parallel
191
+ const [nonce, gasPrices] = await Promise.all([
192
+ publicClient.readContract({
193
+ address: exports.ENTRY_POINT,
194
+ abi: account_abstraction_1.entryPoint07Abi,
195
+ functionName: 'getNonce',
196
+ args: [account.address, 0n],
197
+ }),
198
+ pimlicoClient.getUserOperationGasPrice(),
199
+ ]);
200
+ // Sign 7702 authorization (bundler includes it in the type-4 tx)
201
+ const authorization = await walletClient.signAuthorization({
202
+ contractAddress: exports.EOA_DELEGATION,
203
+ });
204
+ // Build UserOp with dummy signature for gas estimation
205
+ // Gas limits must stay within PaymasterHub fee caps (maxCallGas, maxVerificationGas, maxPreVerificationGas)
206
+ const userOp = {
207
+ sender: account.address,
208
+ nonce,
209
+ callData,
210
+ callGasLimit: 300000n,
211
+ verificationGasLimit: 300000n,
212
+ preVerificationGas: 80000n,
213
+ maxFeePerGas: gasPrices.fast.maxFeePerGas,
214
+ maxPriorityFeePerGas: gasPrices.fast.maxPriorityFeePerGas,
215
+ paymaster: exports.PAYMASTER_HUB,
216
+ paymasterVerificationGasLimit: 200000n,
217
+ paymasterPostOpGasLimit: 200000n,
218
+ paymasterData,
219
+ authorization,
220
+ signature: DUMMY_ECDSA_SIGNATURE,
221
+ };
222
+ // Estimate gas via bundler — catch validateUserOp errors from dummy signature
223
+ try {
224
+ const gasEstimate = await pimlicoClient.estimateUserOperationGas({
225
+ ...userOp,
226
+ entryPointAddress: exports.ENTRY_POINT,
227
+ });
228
+ // Apply gas estimates with buffer
229
+ userOp.callGasLimit = applyBuffer(gasEstimate.callGasLimit);
230
+ userOp.preVerificationGas = applyBuffer(gasEstimate.preVerificationGas);
231
+ // ECDSA verification is cheap (~3k gas), but enforce a minimum
232
+ const estimatedVerification = applyBuffer(gasEstimate.verificationGasLimit);
233
+ userOp.verificationGasLimit = estimatedVerification < 100000n ? 100000n : estimatedVerification;
234
+ if (gasEstimate.paymasterVerificationGasLimit) {
235
+ userOp.paymasterVerificationGasLimit = applyBuffer(gasEstimate.paymasterVerificationGasLimit);
236
+ }
237
+ if (gasEstimate.paymasterPostOpGasLimit) {
238
+ userOp.paymasterPostOpGasLimit = applyBuffer(gasEstimate.paymasterPostOpGasLimit);
239
+ }
240
+ }
241
+ catch (estimateError) {
242
+ const msg = estimateError.message || '';
243
+ // Paymaster rejections should propagate — caller needs to know
244
+ if (msg.includes('AA31') || msg.includes('AA32') || msg.includes('AA33')) {
245
+ throw estimateError;
246
+ }
247
+ // validateUserOp fails with dummy sig — use generous defaults
248
+ // (same pattern as poa-frontend estimateGas() fallback)
249
+ }
250
+ // Compute UserOp hash (EIP-4337 v0.7 packed format)
251
+ const computedHash = getUserOpHash(userOp, exports.ENTRY_POINT, chains_1.gnosis.id);
252
+ // Sign with wallet — EOADelegation validates via toEthSignedMessageHash(userOpHash)
253
+ const signature = await walletClient.signMessage({
254
+ message: { raw: computedHash },
255
+ });
256
+ userOp.signature = signature;
257
+ // Submit to bundler
258
+ const submittedHash = await pimlicoClient.sendUserOperation({
259
+ ...userOp,
260
+ entryPointAddress: exports.ENTRY_POINT,
261
+ });
262
+ // Wait for receipt
263
+ const receipt = await pimlicoClient.waitForUserOperationReceipt({
264
+ hash: submittedHash,
265
+ timeout: 120_000,
266
+ });
267
+ return {
268
+ txHash: receipt.receipt.transactionHash,
269
+ userOpHash: submittedHash,
270
+ };
271
+ }
272
+ /**
273
+ * Helper: encode a contract function call for use with sendSponsored.
274
+ */
275
+ function encodeCall(abi, functionName, args) {
276
+ return (0, viem_1.encodeFunctionData)({ abi, functionName, args });
277
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Exit Codes
3
+ * Single source of truth for process exit codes across the CLI.
4
+ */
5
+ export declare const EXIT: {
6
+ /** Success */
7
+ readonly OK: 0;
8
+ /** Bad or missing input, unknown entity, generic usage error */
9
+ readonly USAGE: 1;
10
+ /** Transaction reverted or gas estimation revealed a revert (existing convention) */
11
+ readonly TX_FAILED: 2;
12
+ /** Infrastructure unavailable: RPC, subgraph, or IPFS (matches NetworkError/SubgraphError/IpfsError code 3) */
13
+ readonly INFRA: 3;
14
+ /** Pre-flight check failed: wrong status, not a member, duplicate suspected */
15
+ readonly PRECONDITION: 4;
16
+ /** User declined confirmation, or non-TTY destructive write without --yes */
17
+ readonly ABORTED: 5;
18
+ };
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ /**
3
+ * Exit Codes
4
+ * Single source of truth for process exit codes across the CLI.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.EXIT = void 0;
8
+ exports.EXIT = {
9
+ /** Success */
10
+ OK: 0,
11
+ /** Bad or missing input, unknown entity, generic usage error */
12
+ USAGE: 1,
13
+ /** Transaction reverted or gas estimation revealed a revert (existing convention) */
14
+ TX_FAILED: 2,
15
+ /** Infrastructure unavailable: RPC, subgraph, or IPFS (matches NetworkError/SubgraphError/IpfsError code 3) */
16
+ INFRA: 3,
17
+ /** Pre-flight check failed: wrong status, not a member, duplicate suspected */
18
+ PRECONDITION: 4,
19
+ /** User declined confirmation, or non-TTY destructive write without --yes */
20
+ ABORTED: 5,
21
+ };
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Display Formatting Helpers
3
+ * Pure functions for tokens, times, and USD amounts.
4
+ * Time functions accept an injectable `now` (unix seconds) for testability.
5
+ *
6
+ * NOTE: statusColor (chalk-based) did NOT move here — it stays CLI-side.
7
+ */
8
+ import { ethers } from 'ethers';
9
+ /**
10
+ * Format a wei-denominated amount as a human string, e.g. "12.5 PT".
11
+ * Trims trailing zeros, adds thousands separators to the integer part,
12
+ * shows at most 4 decimal places — unless the value is nonzero and
13
+ * < 0.0001, in which case full precision is kept.
14
+ */
15
+ export declare function formatToken(wei: ethers.BigNumberish, decimals?: number, symbol?: string): string;
16
+ /** "3h ago" for past timestamps, "in 2d" for future ones. */
17
+ export declare function formatRelativeTime(unixSecs: number | string, now?: number): string;
18
+ /** "2d 4h left" | "expired 3h ago" | "none" for a zero deadline. */
19
+ export declare function formatCountdown(deadlineUnixSecs: number, now?: number): string;
20
+ /** "$1,234.50" */
21
+ export declare function formatUsd(n: number): string;
package/dist/format.js ADDED
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ /**
3
+ * Display Formatting Helpers
4
+ * Pure functions for tokens, times, and USD amounts.
5
+ * Time functions accept an injectable `now` (unix seconds) for testability.
6
+ *
7
+ * NOTE: statusColor (chalk-based) did NOT move here — it stays CLI-side.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.formatToken = formatToken;
11
+ exports.formatRelativeTime = formatRelativeTime;
12
+ exports.formatCountdown = formatCountdown;
13
+ exports.formatUsd = formatUsd;
14
+ const ethers_1 = require("ethers");
15
+ function nowSecs() {
16
+ return Math.floor(Date.now() / 1000);
17
+ }
18
+ function addThousandsSeparators(intPart) {
19
+ return intPart.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
20
+ }
21
+ /**
22
+ * Format a wei-denominated amount as a human string, e.g. "12.5 PT".
23
+ * Trims trailing zeros, adds thousands separators to the integer part,
24
+ * shows at most 4 decimal places — unless the value is nonzero and
25
+ * < 0.0001, in which case full precision is kept.
26
+ */
27
+ function formatToken(wei, decimals = 18, symbol) {
28
+ const raw = ethers_1.ethers.utils.formatUnits(wei, decimals);
29
+ let [intPart, fracPart = ''] = raw.split('.');
30
+ const negative = intPart.startsWith('-');
31
+ if (negative)
32
+ intPart = intPart.slice(1);
33
+ fracPart = fracPart.replace(/0+$/, '');
34
+ let frac = fracPart;
35
+ if (fracPart.length > 4) {
36
+ const isSubDust = /^0+$/.test(intPart) && /^0{4}/.test(fracPart);
37
+ if (!isSubDust) {
38
+ frac = fracPart.slice(0, 4).replace(/0+$/, '');
39
+ }
40
+ }
41
+ let result = addThousandsSeparators(intPart) + (frac ? '.' + frac : '');
42
+ if (negative && !/^0(\.0*)?$/.test(result))
43
+ result = '-' + result;
44
+ return symbol ? `${result} ${symbol}` : result;
45
+ }
46
+ /** Bucket a positive elapsed/remaining span in seconds: s/m/h/d/mo. */
47
+ function bucket(seconds) {
48
+ const abs = Math.abs(Math.round(seconds));
49
+ if (abs < 60)
50
+ return `${abs}s`;
51
+ if (abs < 3600)
52
+ return `${Math.floor(abs / 60)}m`;
53
+ if (abs < 86400)
54
+ return `${Math.floor(abs / 3600)}h`;
55
+ if (abs < 30 * 86400)
56
+ return `${Math.floor(abs / 86400)}d`;
57
+ return `${Math.floor(abs / (30 * 86400))}mo`;
58
+ }
59
+ /** "3h ago" for past timestamps, "in 2d" for future ones. */
60
+ function formatRelativeTime(unixSecs, now = nowSecs()) {
61
+ const ts = Number(unixSecs);
62
+ const diff = now - ts;
63
+ if (diff >= 0)
64
+ return `${bucket(diff)} ago`;
65
+ return `in ${bucket(-diff)}`;
66
+ }
67
+ /** "2d 4h left" | "expired 3h ago" | "none" for a zero deadline. */
68
+ function formatCountdown(deadlineUnixSecs, now = nowSecs()) {
69
+ if (deadlineUnixSecs === 0)
70
+ return 'none';
71
+ const remaining = deadlineUnixSecs - now;
72
+ if (remaining <= 0)
73
+ return `expired ${bucket(-remaining)} ago`;
74
+ const d = Math.floor(remaining / 86400);
75
+ const h = Math.floor((remaining % 86400) / 3600);
76
+ const m = Math.floor((remaining % 3600) / 60);
77
+ const s = remaining % 60;
78
+ if (d > 0)
79
+ return `${d}d ${h}h left`;
80
+ if (h > 0)
81
+ return `${h}h ${m}m left`;
82
+ if (m > 0)
83
+ return `${m}m left`;
84
+ return `${s}s left`;
85
+ }
86
+ /** "$1,234.50" */
87
+ function formatUsd(n) {
88
+ return n.toLocaleString('en-US', { style: 'currency', currency: 'USD' });
89
+ }