@agirails/sdk 2.5.3 → 2.5.5

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 (169) hide show
  1. package/dist/ACTPClient.d.ts +18 -0
  2. package/dist/ACTPClient.d.ts.map +1 -1
  3. package/dist/ACTPClient.js +72 -23
  4. package/dist/ACTPClient.js.map +1 -1
  5. package/dist/adapters/BasicAdapter.d.ts +15 -0
  6. package/dist/adapters/BasicAdapter.d.ts.map +1 -1
  7. package/dist/adapters/BasicAdapter.js +33 -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 +90 -12
  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/config/networks.d.ts +10 -2
  20. package/dist/config/networks.d.ts.map +1 -1
  21. package/dist/config/networks.js +31 -22
  22. package/dist/config/networks.js.map +1 -1
  23. package/dist/level0/request.d.ts.map +1 -1
  24. package/dist/level0/request.js +2 -1
  25. package/dist/level0/request.js.map +1 -1
  26. package/dist/runtime/BlockchainRuntime.d.ts.map +1 -1
  27. package/dist/runtime/BlockchainRuntime.js +11 -5
  28. package/dist/runtime/BlockchainRuntime.js.map +1 -1
  29. package/dist/utils/IPFSClient.d.ts +3 -1
  30. package/dist/utils/IPFSClient.d.ts.map +1 -1
  31. package/dist/utils/IPFSClient.js +27 -7
  32. package/dist/utils/IPFSClient.js.map +1 -1
  33. package/dist/wallet/AutoWalletProvider.d.ts +11 -1
  34. package/dist/wallet/AutoWalletProvider.d.ts.map +1 -1
  35. package/dist/wallet/AutoWalletProvider.js +84 -19
  36. package/dist/wallet/AutoWalletProvider.js.map +1 -1
  37. package/dist/wallet/IWalletProvider.d.ts +34 -0
  38. package/dist/wallet/IWalletProvider.d.ts.map +1 -1
  39. package/dist/wallet/SmartWalletRouter.d.ts +128 -0
  40. package/dist/wallet/SmartWalletRouter.d.ts.map +1 -0
  41. package/dist/wallet/SmartWalletRouter.js +248 -0
  42. package/dist/wallet/SmartWalletRouter.js.map +1 -0
  43. package/dist/wallet/aa/DualNonceManager.d.ts +26 -1
  44. package/dist/wallet/aa/DualNonceManager.d.ts.map +1 -1
  45. package/dist/wallet/aa/DualNonceManager.js +140 -6
  46. package/dist/wallet/aa/DualNonceManager.js.map +1 -1
  47. package/package.json +3 -6
  48. package/src/ACTPClient.ts +0 -1579
  49. package/src/abi/ACTPKernel.json +0 -1356
  50. package/src/abi/AgentRegistry.json +0 -915
  51. package/src/abi/ERC20.json +0 -40
  52. package/src/abi/EscrowVault.json +0 -134
  53. package/src/abi/IdentityRegistry.json +0 -316
  54. package/src/adapters/AdapterRegistry.ts +0 -173
  55. package/src/adapters/AdapterRouter.ts +0 -416
  56. package/src/adapters/BaseAdapter.ts +0 -498
  57. package/src/adapters/BasicAdapter.ts +0 -514
  58. package/src/adapters/IAdapter.ts +0 -292
  59. package/src/adapters/StandardAdapter.ts +0 -555
  60. package/src/adapters/X402Adapter.ts +0 -731
  61. package/src/adapters/index.ts +0 -60
  62. package/src/builders/DeliveryProofBuilder.ts +0 -327
  63. package/src/builders/QuoteBuilder.ts +0 -483
  64. package/src/builders/index.ts +0 -17
  65. package/src/cli/commands/balance.ts +0 -110
  66. package/src/cli/commands/batch.ts +0 -487
  67. package/src/cli/commands/config.ts +0 -231
  68. package/src/cli/commands/deploy-check.ts +0 -364
  69. package/src/cli/commands/deploy-env.ts +0 -120
  70. package/src/cli/commands/diff.ts +0 -141
  71. package/src/cli/commands/init.ts +0 -469
  72. package/src/cli/commands/mint.ts +0 -116
  73. package/src/cli/commands/pay.ts +0 -113
  74. package/src/cli/commands/publish.ts +0 -475
  75. package/src/cli/commands/pull.ts +0 -124
  76. package/src/cli/commands/register.ts +0 -247
  77. package/src/cli/commands/simulate.ts +0 -345
  78. package/src/cli/commands/time.ts +0 -302
  79. package/src/cli/commands/tx.ts +0 -448
  80. package/src/cli/commands/watch.ts +0 -211
  81. package/src/cli/index.ts +0 -134
  82. package/src/cli/utils/client.ts +0 -252
  83. package/src/cli/utils/config.ts +0 -389
  84. package/src/cli/utils/output.ts +0 -465
  85. package/src/cli/utils/wallet.ts +0 -109
  86. package/src/config/agirailsmd.ts +0 -262
  87. package/src/config/networks.ts +0 -275
  88. package/src/config/pendingPublish.ts +0 -237
  89. package/src/config/publishPipeline.ts +0 -359
  90. package/src/config/syncOperations.ts +0 -279
  91. package/src/erc8004/ERC8004Bridge.ts +0 -462
  92. package/src/erc8004/ReputationReporter.ts +0 -468
  93. package/src/erc8004/index.ts +0 -61
  94. package/src/errors/index.ts +0 -427
  95. package/src/index.ts +0 -364
  96. package/src/level0/Provider.ts +0 -117
  97. package/src/level0/ServiceDirectory.ts +0 -131
  98. package/src/level0/index.ts +0 -10
  99. package/src/level0/provide.ts +0 -132
  100. package/src/level0/request.ts +0 -432
  101. package/src/level1/Agent.ts +0 -1426
  102. package/src/level1/index.ts +0 -10
  103. package/src/level1/pricing/PriceCalculator.ts +0 -255
  104. package/src/level1/pricing/PricingStrategy.ts +0 -198
  105. package/src/level1/types/Job.ts +0 -179
  106. package/src/level1/types/Options.ts +0 -291
  107. package/src/level1/types/index.ts +0 -8
  108. package/src/protocol/ACTPKernel.ts +0 -808
  109. package/src/protocol/AgentRegistry.ts +0 -559
  110. package/src/protocol/DIDManager.ts +0 -629
  111. package/src/protocol/DIDResolver.ts +0 -554
  112. package/src/protocol/EASHelper.ts +0 -378
  113. package/src/protocol/EscrowVault.ts +0 -255
  114. package/src/protocol/EventMonitor.ts +0 -204
  115. package/src/protocol/MessageSigner.ts +0 -510
  116. package/src/protocol/ProofGenerator.ts +0 -339
  117. package/src/protocol/QuoteBuilder.ts +0 -15
  118. package/src/registry/AgentRegistryClient.ts +0 -202
  119. package/src/runtime/BlockchainRuntime.ts +0 -1015
  120. package/src/runtime/IACTPRuntime.ts +0 -306
  121. package/src/runtime/MockRuntime.ts +0 -1298
  122. package/src/runtime/MockStateManager.ts +0 -577
  123. package/src/runtime/index.ts +0 -25
  124. package/src/runtime/types/MockState.ts +0 -237
  125. package/src/storage/ArchiveBundleBuilder.ts +0 -561
  126. package/src/storage/ArweaveClient.ts +0 -946
  127. package/src/storage/FilebaseClient.ts +0 -790
  128. package/src/storage/index.ts +0 -96
  129. package/src/storage/types.ts +0 -348
  130. package/src/types/adapter.ts +0 -310
  131. package/src/types/agent.ts +0 -79
  132. package/src/types/did.ts +0 -223
  133. package/src/types/eip712.ts +0 -175
  134. package/src/types/erc8004.ts +0 -293
  135. package/src/types/escrow.ts +0 -27
  136. package/src/types/index.ts +0 -17
  137. package/src/types/message.ts +0 -145
  138. package/src/types/state.ts +0 -87
  139. package/src/types/transaction.ts +0 -69
  140. package/src/types/x402.ts +0 -251
  141. package/src/utils/ErrorRecoveryGuide.ts +0 -676
  142. package/src/utils/Helpers.ts +0 -688
  143. package/src/utils/IPFSClient.ts +0 -368
  144. package/src/utils/Logger.ts +0 -484
  145. package/src/utils/NonceManager.ts +0 -591
  146. package/src/utils/RateLimiter.ts +0 -534
  147. package/src/utils/ReceivedNonceTracker.ts +0 -567
  148. package/src/utils/SDKLifecycle.ts +0 -416
  149. package/src/utils/SecureNonce.ts +0 -78
  150. package/src/utils/Semaphore.ts +0 -276
  151. package/src/utils/UsedAttestationTracker.ts +0 -385
  152. package/src/utils/canonicalJson.ts +0 -38
  153. package/src/utils/circuitBreaker.ts +0 -324
  154. package/src/utils/computeTypeHash.ts +0 -48
  155. package/src/utils/fsSafe.ts +0 -80
  156. package/src/utils/index.ts +0 -80
  157. package/src/utils/retry.ts +0 -364
  158. package/src/utils/security.ts +0 -418
  159. package/src/utils/validation.ts +0 -540
  160. package/src/wallet/AutoWalletProvider.ts +0 -299
  161. package/src/wallet/EOAWalletProvider.ts +0 -69
  162. package/src/wallet/IWalletProvider.ts +0 -135
  163. package/src/wallet/aa/BundlerClient.ts +0 -274
  164. package/src/wallet/aa/DualNonceManager.ts +0 -173
  165. package/src/wallet/aa/PaymasterClient.ts +0 -174
  166. package/src/wallet/aa/TransactionBatcher.ts +0 -353
  167. package/src/wallet/aa/UserOpBuilder.ts +0 -246
  168. package/src/wallet/aa/constants.ts +0 -60
  169. 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
- }