@agirails/sdk 2.5.2 → 2.5.4

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 (172) hide show
  1. package/dist/ACTPClient.d.ts +18 -0
  2. package/dist/ACTPClient.d.ts.map +1 -1
  3. package/dist/ACTPClient.js +67 -22
  4. package/dist/ACTPClient.js.map +1 -1
  5. package/dist/adapters/BasicAdapter.d.ts +12 -0
  6. package/dist/adapters/BasicAdapter.d.ts.map +1 -1
  7. package/dist/adapters/BasicAdapter.js +30 -4
  8. package/dist/adapters/BasicAdapter.js.map +1 -1
  9. package/dist/adapters/StandardAdapter.d.ts +20 -3
  10. package/dist/adapters/StandardAdapter.d.ts.map +1 -1
  11. package/dist/adapters/StandardAdapter.js +45 -11
  12. package/dist/adapters/StandardAdapter.js.map +1 -1
  13. package/dist/cli/commands/publish.js +16 -4
  14. package/dist/cli/commands/publish.js.map +1 -1
  15. package/dist/cli/commands/register.js +16 -4
  16. package/dist/cli/commands/register.js.map +1 -1
  17. package/dist/cli/commands/tx.js +31 -3
  18. package/dist/cli/commands/tx.js.map +1 -1
  19. package/dist/cli/utils/client.d.ts.map +1 -1
  20. package/dist/cli/utils/client.js +1 -0
  21. package/dist/cli/utils/client.js.map +1 -1
  22. package/dist/config/networks.d.ts +2 -2
  23. package/dist/config/networks.d.ts.map +1 -1
  24. package/dist/config/networks.js +27 -22
  25. package/dist/config/networks.js.map +1 -1
  26. package/dist/level0/request.d.ts.map +1 -1
  27. package/dist/level0/request.js +2 -1
  28. package/dist/level0/request.js.map +1 -1
  29. package/dist/runtime/BlockchainRuntime.d.ts.map +1 -1
  30. package/dist/runtime/BlockchainRuntime.js +11 -5
  31. package/dist/runtime/BlockchainRuntime.js.map +1 -1
  32. package/dist/runtime/MockStateManager.d.ts.map +1 -1
  33. package/dist/runtime/MockStateManager.js +2 -1
  34. package/dist/runtime/MockStateManager.js.map +1 -1
  35. package/dist/utils/IPFSClient.d.ts +3 -1
  36. package/dist/utils/IPFSClient.d.ts.map +1 -1
  37. package/dist/utils/IPFSClient.js +27 -7
  38. package/dist/utils/IPFSClient.js.map +1 -1
  39. package/dist/wallet/AutoWalletProvider.d.ts.map +1 -1
  40. package/dist/wallet/AutoWalletProvider.js +52 -18
  41. package/dist/wallet/AutoWalletProvider.js.map +1 -1
  42. package/dist/wallet/SmartWalletRouter.d.ts +116 -0
  43. package/dist/wallet/SmartWalletRouter.d.ts.map +1 -0
  44. package/dist/wallet/SmartWalletRouter.js +212 -0
  45. package/dist/wallet/SmartWalletRouter.js.map +1 -0
  46. package/dist/wallet/aa/DualNonceManager.d.ts +19 -0
  47. package/dist/wallet/aa/DualNonceManager.d.ts.map +1 -1
  48. package/dist/wallet/aa/DualNonceManager.js +100 -5
  49. package/dist/wallet/aa/DualNonceManager.js.map +1 -1
  50. package/package.json +3 -6
  51. package/src/ACTPClient.ts +0 -1579
  52. package/src/abi/ACTPKernel.json +0 -1356
  53. package/src/abi/AgentRegistry.json +0 -915
  54. package/src/abi/ERC20.json +0 -40
  55. package/src/abi/EscrowVault.json +0 -134
  56. package/src/abi/IdentityRegistry.json +0 -316
  57. package/src/adapters/AdapterRegistry.ts +0 -173
  58. package/src/adapters/AdapterRouter.ts +0 -416
  59. package/src/adapters/BaseAdapter.ts +0 -498
  60. package/src/adapters/BasicAdapter.ts +0 -514
  61. package/src/adapters/IAdapter.ts +0 -292
  62. package/src/adapters/StandardAdapter.ts +0 -555
  63. package/src/adapters/X402Adapter.ts +0 -731
  64. package/src/adapters/index.ts +0 -60
  65. package/src/builders/DeliveryProofBuilder.ts +0 -327
  66. package/src/builders/QuoteBuilder.ts +0 -483
  67. package/src/builders/index.ts +0 -17
  68. package/src/cli/commands/balance.ts +0 -110
  69. package/src/cli/commands/batch.ts +0 -487
  70. package/src/cli/commands/config.ts +0 -231
  71. package/src/cli/commands/deploy-check.ts +0 -364
  72. package/src/cli/commands/deploy-env.ts +0 -120
  73. package/src/cli/commands/diff.ts +0 -141
  74. package/src/cli/commands/init.ts +0 -469
  75. package/src/cli/commands/mint.ts +0 -116
  76. package/src/cli/commands/pay.ts +0 -113
  77. package/src/cli/commands/publish.ts +0 -475
  78. package/src/cli/commands/pull.ts +0 -124
  79. package/src/cli/commands/register.ts +0 -247
  80. package/src/cli/commands/simulate.ts +0 -345
  81. package/src/cli/commands/time.ts +0 -302
  82. package/src/cli/commands/tx.ts +0 -448
  83. package/src/cli/commands/watch.ts +0 -211
  84. package/src/cli/index.ts +0 -134
  85. package/src/cli/utils/client.ts +0 -251
  86. package/src/cli/utils/config.ts +0 -389
  87. package/src/cli/utils/output.ts +0 -465
  88. package/src/cli/utils/wallet.ts +0 -109
  89. package/src/config/agirailsmd.ts +0 -262
  90. package/src/config/networks.ts +0 -275
  91. package/src/config/pendingPublish.ts +0 -237
  92. package/src/config/publishPipeline.ts +0 -359
  93. package/src/config/syncOperations.ts +0 -279
  94. package/src/erc8004/ERC8004Bridge.ts +0 -462
  95. package/src/erc8004/ReputationReporter.ts +0 -468
  96. package/src/erc8004/index.ts +0 -61
  97. package/src/errors/index.ts +0 -427
  98. package/src/index.ts +0 -364
  99. package/src/level0/Provider.ts +0 -117
  100. package/src/level0/ServiceDirectory.ts +0 -131
  101. package/src/level0/index.ts +0 -10
  102. package/src/level0/provide.ts +0 -132
  103. package/src/level0/request.ts +0 -432
  104. package/src/level1/Agent.ts +0 -1426
  105. package/src/level1/index.ts +0 -10
  106. package/src/level1/pricing/PriceCalculator.ts +0 -255
  107. package/src/level1/pricing/PricingStrategy.ts +0 -198
  108. package/src/level1/types/Job.ts +0 -179
  109. package/src/level1/types/Options.ts +0 -291
  110. package/src/level1/types/index.ts +0 -8
  111. package/src/protocol/ACTPKernel.ts +0 -808
  112. package/src/protocol/AgentRegistry.ts +0 -559
  113. package/src/protocol/DIDManager.ts +0 -629
  114. package/src/protocol/DIDResolver.ts +0 -554
  115. package/src/protocol/EASHelper.ts +0 -378
  116. package/src/protocol/EscrowVault.ts +0 -255
  117. package/src/protocol/EventMonitor.ts +0 -204
  118. package/src/protocol/MessageSigner.ts +0 -510
  119. package/src/protocol/ProofGenerator.ts +0 -339
  120. package/src/protocol/QuoteBuilder.ts +0 -15
  121. package/src/registry/AgentRegistryClient.ts +0 -202
  122. package/src/runtime/BlockchainRuntime.ts +0 -1015
  123. package/src/runtime/IACTPRuntime.ts +0 -306
  124. package/src/runtime/MockRuntime.ts +0 -1298
  125. package/src/runtime/MockStateManager.ts +0 -576
  126. package/src/runtime/index.ts +0 -25
  127. package/src/runtime/types/MockState.ts +0 -237
  128. package/src/storage/ArchiveBundleBuilder.ts +0 -561
  129. package/src/storage/ArweaveClient.ts +0 -946
  130. package/src/storage/FilebaseClient.ts +0 -790
  131. package/src/storage/index.ts +0 -96
  132. package/src/storage/types.ts +0 -348
  133. package/src/types/adapter.ts +0 -310
  134. package/src/types/agent.ts +0 -79
  135. package/src/types/did.ts +0 -223
  136. package/src/types/eip712.ts +0 -175
  137. package/src/types/erc8004.ts +0 -293
  138. package/src/types/escrow.ts +0 -27
  139. package/src/types/index.ts +0 -17
  140. package/src/types/message.ts +0 -145
  141. package/src/types/state.ts +0 -87
  142. package/src/types/transaction.ts +0 -69
  143. package/src/types/x402.ts +0 -251
  144. package/src/utils/ErrorRecoveryGuide.ts +0 -676
  145. package/src/utils/Helpers.ts +0 -688
  146. package/src/utils/IPFSClient.ts +0 -368
  147. package/src/utils/Logger.ts +0 -484
  148. package/src/utils/NonceManager.ts +0 -591
  149. package/src/utils/RateLimiter.ts +0 -534
  150. package/src/utils/ReceivedNonceTracker.ts +0 -567
  151. package/src/utils/SDKLifecycle.ts +0 -416
  152. package/src/utils/SecureNonce.ts +0 -78
  153. package/src/utils/Semaphore.ts +0 -276
  154. package/src/utils/UsedAttestationTracker.ts +0 -385
  155. package/src/utils/canonicalJson.ts +0 -38
  156. package/src/utils/circuitBreaker.ts +0 -324
  157. package/src/utils/computeTypeHash.ts +0 -48
  158. package/src/utils/fsSafe.ts +0 -80
  159. package/src/utils/index.ts +0 -80
  160. package/src/utils/retry.ts +0 -364
  161. package/src/utils/security.ts +0 -418
  162. package/src/utils/validation.ts +0 -540
  163. package/src/wallet/AutoWalletProvider.ts +0 -299
  164. package/src/wallet/EOAWalletProvider.ts +0 -69
  165. package/src/wallet/IWalletProvider.ts +0 -135
  166. package/src/wallet/aa/BundlerClient.ts +0 -274
  167. package/src/wallet/aa/DualNonceManager.ts +0 -173
  168. package/src/wallet/aa/PaymasterClient.ts +0 -174
  169. package/src/wallet/aa/TransactionBatcher.ts +0 -353
  170. package/src/wallet/aa/UserOpBuilder.ts +0 -246
  171. package/src/wallet/aa/constants.ts +0 -60
  172. package/src/wallet/keystore.ts +0 -240
@@ -1,688 +0,0 @@
1
- /**
2
- * Helpers - Common utility functions for ACTP SDK
3
- *
4
- * SECURITY FIX (L-7): Convenience methods for common operations
5
- * to reduce boilerplate and prevent mistakes.
6
- *
7
- * @module utils/Helpers
8
- */
9
-
10
- /**
11
- * USDC amount utilities (6 decimal places)
12
- */
13
- export const USDC = {
14
- /**
15
- * USDC decimals
16
- */
17
- DECIMALS: 6,
18
-
19
- /**
20
- * Minimum transaction amount in USDC wei ($0.05)
21
- */
22
- MIN_AMOUNT_WEI: 50_000n,
23
-
24
- /**
25
- * Convert human-readable USDC amount to wei
26
- *
27
- * @param amount - Amount as string or number (e.g., "100.50")
28
- * @returns Amount in USDC wei (6 decimals)
29
- *
30
- * @example
31
- * ```typescript
32
- * USDC.toWei("100") // 100_000_000n
33
- * USDC.toWei("100.50") // 100_500_000n
34
- * USDC.toWei(100) // 100_000_000n
35
- * ```
36
- */
37
- toWei(amount: string | number): bigint {
38
- const amountStr = String(amount).replace(/[,$\s]/g, '');
39
- const parts = amountStr.split('.');
40
- const wholePart = parts[0] || '0';
41
- const decimalPart = (parts[1] || '').padEnd(6, '0').slice(0, 6);
42
-
43
- return BigInt(wholePart) * 1_000_000n + BigInt(decimalPart);
44
- },
45
-
46
- /**
47
- * Convert USDC wei to human-readable string
48
- *
49
- * SECURITY FIX (MEDIUM-6): Uses pure BigInt arithmetic to prevent precision loss
50
- *
51
- * @param weiAmount - Amount in USDC wei
52
- * @param decimals - Number of decimal places to show (default: 2)
53
- * @returns Formatted string (e.g., "100.50")
54
- *
55
- * @example
56
- * ```typescript
57
- * USDC.fromWei(100_500_000n) // "100.50"
58
- * USDC.fromWei(100_000_000n) // "100.00"
59
- * USDC.fromWei(100_126_000n, 4) // "100.1260"
60
- * ```
61
- */
62
- fromWei(weiAmount: bigint | string, decimals = 2): string {
63
- const amount = typeof weiAmount === 'string' ? BigInt(weiAmount) : weiAmount;
64
-
65
- // SECURITY FIX (MEDIUM-6): Use pure BigInt arithmetic for precision
66
- // Calculate divisor and multiplier using BigInt to avoid floating point
67
- const divisorExponent = 6 - decimals;
68
- const divisor = divisorExponent >= 0 ? BigInt(10 ** divisorExponent) : 1n;
69
- const maxDecimal = BigInt(10 ** decimals);
70
-
71
- // SECURITY FIX (MEDIUM-6): Round using BigInt arithmetic
72
- // Add half divisor before division for proper rounding (banker's rounding alternative)
73
- const roundedAmount = divisorExponent >= 0
74
- ? (amount + divisor / 2n) / divisor
75
- : amount * BigInt(10 ** (-divisorExponent));
76
-
77
- const wholePart = roundedAmount / maxDecimal;
78
- const decimalPart = roundedAmount % maxDecimal;
79
-
80
- // Handle overflow from rounding (e.g., 999999 rounds to 1000000)
81
- if (decimalPart < 0n) {
82
- // This shouldn't happen with positive amounts, but handle defensive
83
- return `${wholePart}.${decimalPart.toString().slice(1).padStart(decimals, '0')}`;
84
- }
85
-
86
- return `${wholePart}.${decimalPart.toString().padStart(decimals, '0')}`;
87
- },
88
-
89
- /**
90
- * Format USDC amount with currency symbol
91
- *
92
- * @param weiAmount - Amount in USDC wei
93
- * @returns Formatted string with USDC suffix (e.g., "100.50 USDC")
94
- */
95
- format(weiAmount: bigint | string): string {
96
- return `${USDC.fromWei(weiAmount)} USDC`;
97
- },
98
-
99
- /**
100
- * Check if amount meets minimum transaction requirement
101
- *
102
- * @param weiAmount - Amount in USDC wei
103
- * @returns true if amount >= $0.05
104
- */
105
- meetsMinimum(weiAmount: bigint | string): boolean {
106
- const amount = typeof weiAmount === 'string' ? BigInt(weiAmount) : weiAmount;
107
- return amount >= USDC.MIN_AMOUNT_WEI;
108
- },
109
- };
110
-
111
- /**
112
- * Deadline utilities
113
- */
114
- export const Deadline = {
115
- /**
116
- * Create deadline N hours from now
117
- *
118
- * @param hours - Number of hours from now
119
- * @returns Unix timestamp in seconds
120
- *
121
- * @example
122
- * ```typescript
123
- * Deadline.hoursFromNow(24) // timestamp 24 hours from now
124
- * ```
125
- */
126
- hoursFromNow(hours: number): number {
127
- return Math.floor(Date.now() / 1000) + hours * 3600;
128
- },
129
-
130
- /**
131
- * Create deadline N days from now
132
- *
133
- * @param days - Number of days from now
134
- * @returns Unix timestamp in seconds
135
- *
136
- * @example
137
- * ```typescript
138
- * Deadline.daysFromNow(7) // timestamp 7 days from now
139
- * ```
140
- */
141
- daysFromNow(days: number): number {
142
- return Math.floor(Date.now() / 1000) + days * 86400;
143
- },
144
-
145
- /**
146
- * Create deadline at specific date
147
- *
148
- * @param date - Date object or ISO string
149
- * @returns Unix timestamp in seconds
150
- *
151
- * @example
152
- * ```typescript
153
- * Deadline.at(new Date('2025-01-01'))
154
- * Deadline.at('2025-01-01T00:00:00Z')
155
- * ```
156
- */
157
- at(date: Date | string): number {
158
- const d = typeof date === 'string' ? new Date(date) : date;
159
- return Math.floor(d.getTime() / 1000);
160
- },
161
-
162
- /**
163
- * Check if deadline has passed
164
- *
165
- * @param deadline - Unix timestamp in seconds
166
- * @returns true if deadline is in the past
167
- */
168
- isPast(deadline: number): boolean {
169
- return deadline <= Math.floor(Date.now() / 1000);
170
- },
171
-
172
- /**
173
- * Get time remaining until deadline
174
- *
175
- * @param deadline - Unix timestamp in seconds
176
- * @returns Time remaining in seconds (negative if past)
177
- */
178
- timeRemaining(deadline: number): number {
179
- return deadline - Math.floor(Date.now() / 1000);
180
- },
181
-
182
- /**
183
- * Format deadline as human-readable string
184
- *
185
- * @param deadline - Unix timestamp in seconds
186
- * @returns Human-readable string (e.g., "in 2 hours", "expired 1 day ago")
187
- */
188
- format(deadline: number): string {
189
- const remaining = Deadline.timeRemaining(deadline);
190
-
191
- if (remaining <= 0) {
192
- const ago = Math.abs(remaining);
193
- if (ago < 60) return `expired ${ago} seconds ago`;
194
- if (ago < 3600) return `expired ${Math.floor(ago / 60)} minutes ago`;
195
- if (ago < 86400) return `expired ${Math.floor(ago / 3600)} hours ago`;
196
- return `expired ${Math.floor(ago / 86400)} days ago`;
197
- }
198
-
199
- if (remaining < 60) return `in ${remaining} seconds`;
200
- if (remaining < 3600) return `in ${Math.floor(remaining / 60)} minutes`;
201
- if (remaining < 86400) return `in ${Math.floor(remaining / 3600)} hours`;
202
- return `in ${Math.floor(remaining / 86400)} days`;
203
- },
204
- };
205
-
206
- /**
207
- * Address utilities
208
- */
209
- export const Address = {
210
- /**
211
- * Normalize address to lowercase with 0x prefix
212
- *
213
- * @param address - Ethereum address
214
- * @returns Normalized address
215
- */
216
- normalize(address: string): string {
217
- return address.toLowerCase();
218
- },
219
-
220
- /**
221
- * Check if two addresses are the same (case-insensitive)
222
- *
223
- * @param a - First address
224
- * @param b - Second address
225
- * @returns true if addresses match
226
- */
227
- equals(a: string, b: string): boolean {
228
- return a.toLowerCase() === b.toLowerCase();
229
- },
230
-
231
- /**
232
- * Truncate address for display
233
- *
234
- * @param address - Ethereum address
235
- * @param chars - Characters to show on each side (default: 4)
236
- * @returns Truncated address (e.g., "0x1234...5678")
237
- */
238
- truncate(address: string, chars = 4): string {
239
- if (address.length <= 2 + chars * 2) {
240
- return address;
241
- }
242
- return `${address.slice(0, 2 + chars)}...${address.slice(-chars)}`;
243
- },
244
-
245
- /**
246
- * Check if string is valid Ethereum address format
247
- *
248
- * @param address - String to check
249
- * @returns true if valid address format
250
- */
251
- isValid(address: string): boolean {
252
- return /^0x[0-9a-fA-F]{40}$/.test(address);
253
- },
254
-
255
- /**
256
- * Check if address is zero address
257
- *
258
- * @param address - Ethereum address
259
- * @returns true if zero address
260
- */
261
- isZero(address: string): boolean {
262
- return address.toLowerCase() === '0x0000000000000000000000000000000000000000';
263
- },
264
- };
265
-
266
- /**
267
- * Bytes32 utilities
268
- */
269
- export const Bytes32 = {
270
- /**
271
- * Check if string is valid bytes32 format
272
- *
273
- * @param value - String to check
274
- * @returns true if valid bytes32 format
275
- */
276
- isValid(value: string): boolean {
277
- return /^0x[0-9a-fA-F]{64}$/.test(value);
278
- },
279
-
280
- /**
281
- * Normalize bytes32 to lowercase
282
- *
283
- * @param value - Bytes32 string
284
- * @returns Normalized lowercase string
285
- */
286
- normalize(value: string): string {
287
- return value.toLowerCase();
288
- },
289
-
290
- /**
291
- * Check if two bytes32 values are equal
292
- *
293
- * @param a - First value
294
- * @param b - Second value
295
- * @returns true if equal
296
- */
297
- equals(a: string, b: string): boolean {
298
- return a.toLowerCase() === b.toLowerCase();
299
- },
300
-
301
- /**
302
- * Check if bytes32 is zero
303
- *
304
- * @param value - Bytes32 string
305
- * @returns true if zero
306
- */
307
- isZero(value: string): boolean {
308
- return value.toLowerCase() === '0x' + '0'.repeat(64);
309
- },
310
-
311
- /**
312
- * Create zero bytes32
313
- *
314
- * @returns Zero bytes32 string
315
- */
316
- zero(): string {
317
- return '0x' + '0'.repeat(64);
318
- },
319
-
320
- /**
321
- * Truncate bytes32 for display
322
- *
323
- * @param value - Bytes32 string
324
- * @param chars - Characters to show on each side (default: 6)
325
- * @returns Truncated string (e.g., "0x123456...abcdef")
326
- */
327
- truncate(value: string, chars = 6): string {
328
- if (value.length <= 2 + chars * 2) {
329
- return value;
330
- }
331
- return `${value.slice(0, 2 + chars)}...${value.slice(-chars)}`;
332
- },
333
- };
334
-
335
- /**
336
- * State machine utilities
337
- */
338
- export const State = {
339
- /**
340
- * Valid ACTP states
341
- */
342
- STATES: [
343
- 'INITIATED',
344
- 'QUOTED',
345
- 'COMMITTED',
346
- 'IN_PROGRESS',
347
- 'DELIVERED',
348
- 'SETTLED',
349
- 'DISPUTED',
350
- 'CANCELLED',
351
- ] as const,
352
-
353
- /**
354
- * Terminal states (no further transitions)
355
- */
356
- TERMINAL: ['SETTLED', 'CANCELLED'] as const,
357
-
358
- /**
359
- * Check if state is terminal
360
- *
361
- * @param state - State to check
362
- * @returns true if terminal state
363
- */
364
- isTerminal(state: string): boolean {
365
- return State.TERMINAL.includes(state as any);
366
- },
367
-
368
- /**
369
- * Check if state is valid
370
- *
371
- * @param state - State to check
372
- * @returns true if valid state
373
- */
374
- isValid(state: string): boolean {
375
- return State.STATES.includes(state as any);
376
- },
377
-
378
- /**
379
- * Get valid next states from current state
380
- *
381
- * SECURITY FIX (CRITICAL-1): Must match ACTPKernel contract state machine exactly
382
- * Per CLAUDE.md §Architecture Overview - ACTP Protocol State Machine
383
- *
384
- * @param currentState - Current state
385
- * @returns Array of valid next states
386
- */
387
- validTransitions(currentState: string): string[] {
388
- const transitions: Record<string, string[]> = {
389
- INITIATED: ['QUOTED', 'COMMITTED', 'CANCELLED'],
390
- QUOTED: ['COMMITTED', 'CANCELLED'],
391
- // Can skip IN_PROGRESS and go directly to DELIVERED
392
- COMMITTED: ['IN_PROGRESS', 'DELIVERED', 'CANCELLED'],
393
- // No DISPUTED from IN_PROGRESS - only after DELIVERED
394
- IN_PROGRESS: ['DELIVERED', 'CANCELLED'],
395
- DELIVERED: ['SETTLED', 'DISPUTED'],
396
- // Disputes can only resolve to SETTLED (no CANCELLED)
397
- DISPUTED: ['SETTLED'],
398
- SETTLED: [],
399
- CANCELLED: [],
400
- };
401
-
402
- return transitions[currentState] || [];
403
- },
404
-
405
- /**
406
- * Check if transition is valid
407
- *
408
- * @param from - Current state
409
- * @param to - Target state
410
- * @returns true if transition is valid
411
- */
412
- canTransition(from: string, to: string): boolean {
413
- return State.validTransitions(from).includes(to);
414
- },
415
- };
416
-
417
- /**
418
- * Dispute window utilities
419
- */
420
- export const DisputeWindow = {
421
- /**
422
- * Default dispute window in seconds (2 days)
423
- */
424
- DEFAULT: 172800,
425
-
426
- /**
427
- * Minimum dispute window in seconds (1 hour)
428
- */
429
- MIN: 3600,
430
-
431
- /**
432
- * Maximum dispute window in seconds (30 days)
433
- */
434
- MAX: 30 * 24 * 3600,
435
-
436
- /**
437
- * Convert hours to seconds
438
- */
439
- hours(h: number): number {
440
- return h * 3600;
441
- },
442
-
443
- /**
444
- * Convert days to seconds
445
- */
446
- days(d: number): number {
447
- return d * 86400;
448
- },
449
-
450
- /**
451
- * Check if dispute window is still active
452
- *
453
- * @param completedAt - Completion timestamp
454
- * @param windowSeconds - Dispute window in seconds
455
- * @returns true if window is still active
456
- */
457
- isActive(completedAt: number, windowSeconds: number): boolean {
458
- const expiresAt = completedAt + windowSeconds;
459
- return Math.floor(Date.now() / 1000) < expiresAt;
460
- },
461
-
462
- /**
463
- * Get time remaining in dispute window
464
- *
465
- * @param completedAt - Completion timestamp
466
- * @param windowSeconds - Dispute window in seconds
467
- * @returns Seconds remaining (0 if expired)
468
- */
469
- remaining(completedAt: number, windowSeconds: number): number {
470
- const expiresAt = completedAt + windowSeconds;
471
- const now = Math.floor(Date.now() / 1000);
472
- return Math.max(0, expiresAt - now);
473
- },
474
- };
475
-
476
- /**
477
- * ============================================================================
478
- * Convenience Wrappers for Common Operations
479
- * ============================================================================
480
- */
481
-
482
- /**
483
- * Parse USDC amount string to wei (6 decimals)
484
- *
485
- * Convenience wrapper for USDC.toWei()
486
- *
487
- * @param amount - Amount in USDC (e.g., "100" or "0.50")
488
- * @returns BigInt in wei (e.g., 100000000n for $100)
489
- *
490
- * @example
491
- * ```typescript
492
- * parseUSDC("100") // 100_000_000n
493
- * parseUSDC("0.50") // 500_000n
494
- * parseUSDC(100) // 100_000_000n
495
- * ```
496
- */
497
- export function parseUSDC(amount: string | number): bigint {
498
- return USDC.toWei(amount);
499
- }
500
-
501
- /**
502
- * Format USDC wei to human-readable string
503
- *
504
- * Convenience wrapper for USDC.fromWei()
505
- *
506
- * @param wei - Amount in wei (BigInt or string)
507
- * @returns Formatted string (e.g., "100.00")
508
- *
509
- * @example
510
- * ```typescript
511
- * formatUSDC(100_000_000n) // "100.00"
512
- * formatUSDC("100000000") // "100.00"
513
- * formatUSDC(500_000n) // "0.50"
514
- * ```
515
- */
516
- export function formatUSDC(wei: bigint | string): string {
517
- return USDC.fromWei(wei);
518
- }
519
-
520
- /**
521
- * Shorten Ethereum address for display
522
- *
523
- * Convenience wrapper for Address.truncate()
524
- *
525
- * @param address - Full Ethereum address
526
- * @param chars - Characters to show on each side (default: 4)
527
- * @returns Shortened address (e.g., "0x1234...abcd")
528
- *
529
- * @example
530
- * ```typescript
531
- * shortenAddress("0x1234567890123456789012345678901234567890") // "0x1234...7890"
532
- * shortenAddress("0x1234567890123456789012345678901234567890", 6) // "0x123456...567890"
533
- * ```
534
- */
535
- export function shortenAddress(address: string, chars: number = 4): string {
536
- return Address.truncate(address, chars);
537
- }
538
-
539
- /**
540
- * ============================================================================
541
- * Service Metadata Utilities
542
- *
543
- * SECURITY FIX (CRITICAL): ACTPKernel expects bytes32 serviceHash, not raw strings.
544
- * These utilities handle proper hashing and encoding of service metadata.
545
- * ============================================================================
546
- */
547
-
548
- /**
549
- * Service metadata structure
550
- */
551
- export interface ServiceMetadata {
552
- service: string;
553
- input?: unknown;
554
- version?: string;
555
- timestamp?: number;
556
- }
557
-
558
- /**
559
- * Service metadata utilities for ACTP transactions
560
- *
561
- * SECURITY FIX (CRITICAL): The ACTPKernel contract expects a bytes32 serviceHash,
562
- * not a raw JSON string. This utility properly hashes metadata before on-chain calls.
563
- */
564
- export const ServiceHash = {
565
- /**
566
- * Create canonical JSON from service metadata
567
- *
568
- * SECURITY: Uses deterministic key ordering to ensure consistent hashes
569
- *
570
- * @param metadata - Service metadata object
571
- * @returns Canonical JSON string
572
- */
573
- toCanonical(metadata: ServiceMetadata): string {
574
- // Sort keys for deterministic output
575
- const canonical = {
576
- service: metadata.service,
577
- ...(metadata.input !== undefined && { input: metadata.input }),
578
- ...(metadata.version !== undefined && { version: metadata.version }),
579
- ...(metadata.timestamp !== undefined && { timestamp: metadata.timestamp }),
580
- };
581
- return JSON.stringify(canonical);
582
- },
583
-
584
- /**
585
- * Hash service metadata to bytes32 using keccak256
586
- *
587
- * SECURITY FIX (CRITICAL): This is what should be passed to ACTPKernel.createTransaction()
588
- *
589
- * @param metadata - Service metadata (string or object)
590
- * @returns bytes32 hash string (0x-prefixed, 64 hex chars)
591
- *
592
- * @example
593
- * ```typescript
594
- * const hash = ServiceHash.hash({ service: 'echo', input: 'hello' });
595
- * // Returns: 0x1234...abcd (bytes32)
596
- * ```
597
- */
598
- hash(metadata: ServiceMetadata | string): string {
599
- // Dynamic import to avoid circular dependencies
600
- const { keccak256, toUtf8Bytes } = require('ethers');
601
-
602
- const canonical = typeof metadata === 'string'
603
- ? metadata
604
- : ServiceHash.toCanonical(metadata);
605
-
606
- return keccak256(toUtf8Bytes(canonical));
607
- },
608
-
609
- /**
610
- * Create service metadata from legacy format
611
- *
612
- * Parses the old "service:X;input:Y" format into structured metadata
613
- *
614
- * @param legacyFormat - Legacy service description string
615
- * @returns Parsed ServiceMetadata or null if invalid
616
- */
617
- fromLegacy(legacyFormat: string): ServiceMetadata | null {
618
- // Parse "service:NAME;input:JSON" format
619
- const serviceMatch = legacyFormat.match(/^service:([^;]+)/);
620
- if (!serviceMatch) return null;
621
-
622
- const service = serviceMatch[1];
623
-
624
- const inputMatch = legacyFormat.match(/;input:(.+)$/);
625
- let input: unknown = undefined;
626
-
627
- if (inputMatch) {
628
- try {
629
- input = JSON.parse(inputMatch[1]);
630
- } catch {
631
- // If not valid JSON, use as string
632
- input = inputMatch[1];
633
- }
634
- }
635
-
636
- return { service, input };
637
- },
638
-
639
- /**
640
- * Extract service name from metadata hash (requires off-chain lookup)
641
- *
642
- * NOTE: The hash cannot be reversed. This is a helper for when you have
643
- * both the hash and the original metadata stored off-chain.
644
- *
645
- * @param metadata - Original metadata
646
- * @returns Service name
647
- */
648
- getServiceName(metadata: ServiceMetadata | string): string {
649
- if (typeof metadata === 'string') {
650
- const parsed = ServiceHash.fromLegacy(metadata);
651
- return parsed?.service || 'unknown';
652
- }
653
- return metadata.service;
654
- },
655
-
656
- /**
657
- * Validate bytes32 format
658
- *
659
- * @param value - Value to check
660
- * @returns true if valid bytes32 format
661
- */
662
- isValidHash(value: string): boolean {
663
- return /^0x[0-9a-fA-F]{64}$/.test(value);
664
- },
665
-
666
- /**
667
- * Zero hash (empty service metadata)
668
- */
669
- ZERO: '0x0000000000000000000000000000000000000000000000000000000000000000',
670
- };
671
-
672
- /**
673
- * Hash service description for on-chain storage
674
- *
675
- * Convenience function for ServiceHash.hash()
676
- *
677
- * @param service - Service name
678
- * @param input - Input data (optional)
679
- * @returns bytes32 hash
680
- *
681
- * @example
682
- * ```typescript
683
- * const hash = hashServiceMetadata('echo', { text: 'hello' });
684
- * ```
685
- */
686
- export function hashServiceMetadata(service: string, input?: unknown): string {
687
- return ServiceHash.hash({ service, input });
688
- }