@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.
- package/dist/ACTPClient.d.ts +18 -0
- package/dist/ACTPClient.d.ts.map +1 -1
- package/dist/ACTPClient.js +72 -23
- package/dist/ACTPClient.js.map +1 -1
- package/dist/adapters/BasicAdapter.d.ts +15 -0
- package/dist/adapters/BasicAdapter.d.ts.map +1 -1
- package/dist/adapters/BasicAdapter.js +33 -4
- package/dist/adapters/BasicAdapter.js.map +1 -1
- package/dist/adapters/StandardAdapter.d.ts +20 -3
- package/dist/adapters/StandardAdapter.d.ts.map +1 -1
- package/dist/adapters/StandardAdapter.js +90 -12
- package/dist/adapters/StandardAdapter.js.map +1 -1
- package/dist/cli/commands/publish.js +16 -4
- package/dist/cli/commands/publish.js.map +1 -1
- package/dist/cli/commands/register.js +16 -4
- package/dist/cli/commands/register.js.map +1 -1
- package/dist/cli/commands/tx.js +31 -3
- package/dist/cli/commands/tx.js.map +1 -1
- package/dist/config/networks.d.ts +10 -2
- package/dist/config/networks.d.ts.map +1 -1
- package/dist/config/networks.js +31 -22
- package/dist/config/networks.js.map +1 -1
- package/dist/level0/request.d.ts.map +1 -1
- package/dist/level0/request.js +2 -1
- package/dist/level0/request.js.map +1 -1
- package/dist/runtime/BlockchainRuntime.d.ts.map +1 -1
- package/dist/runtime/BlockchainRuntime.js +11 -5
- package/dist/runtime/BlockchainRuntime.js.map +1 -1
- package/dist/utils/IPFSClient.d.ts +3 -1
- package/dist/utils/IPFSClient.d.ts.map +1 -1
- package/dist/utils/IPFSClient.js +27 -7
- package/dist/utils/IPFSClient.js.map +1 -1
- package/dist/wallet/AutoWalletProvider.d.ts +11 -1
- package/dist/wallet/AutoWalletProvider.d.ts.map +1 -1
- package/dist/wallet/AutoWalletProvider.js +84 -19
- package/dist/wallet/AutoWalletProvider.js.map +1 -1
- package/dist/wallet/IWalletProvider.d.ts +34 -0
- package/dist/wallet/IWalletProvider.d.ts.map +1 -1
- package/dist/wallet/SmartWalletRouter.d.ts +128 -0
- package/dist/wallet/SmartWalletRouter.d.ts.map +1 -0
- package/dist/wallet/SmartWalletRouter.js +248 -0
- package/dist/wallet/SmartWalletRouter.js.map +1 -0
- package/dist/wallet/aa/DualNonceManager.d.ts +26 -1
- package/dist/wallet/aa/DualNonceManager.d.ts.map +1 -1
- package/dist/wallet/aa/DualNonceManager.js +140 -6
- package/dist/wallet/aa/DualNonceManager.js.map +1 -1
- package/package.json +3 -6
- package/src/ACTPClient.ts +0 -1579
- package/src/abi/ACTPKernel.json +0 -1356
- package/src/abi/AgentRegistry.json +0 -915
- package/src/abi/ERC20.json +0 -40
- package/src/abi/EscrowVault.json +0 -134
- package/src/abi/IdentityRegistry.json +0 -316
- package/src/adapters/AdapterRegistry.ts +0 -173
- package/src/adapters/AdapterRouter.ts +0 -416
- package/src/adapters/BaseAdapter.ts +0 -498
- package/src/adapters/BasicAdapter.ts +0 -514
- package/src/adapters/IAdapter.ts +0 -292
- package/src/adapters/StandardAdapter.ts +0 -555
- package/src/adapters/X402Adapter.ts +0 -731
- package/src/adapters/index.ts +0 -60
- package/src/builders/DeliveryProofBuilder.ts +0 -327
- package/src/builders/QuoteBuilder.ts +0 -483
- package/src/builders/index.ts +0 -17
- package/src/cli/commands/balance.ts +0 -110
- package/src/cli/commands/batch.ts +0 -487
- package/src/cli/commands/config.ts +0 -231
- package/src/cli/commands/deploy-check.ts +0 -364
- package/src/cli/commands/deploy-env.ts +0 -120
- package/src/cli/commands/diff.ts +0 -141
- package/src/cli/commands/init.ts +0 -469
- package/src/cli/commands/mint.ts +0 -116
- package/src/cli/commands/pay.ts +0 -113
- package/src/cli/commands/publish.ts +0 -475
- package/src/cli/commands/pull.ts +0 -124
- package/src/cli/commands/register.ts +0 -247
- package/src/cli/commands/simulate.ts +0 -345
- package/src/cli/commands/time.ts +0 -302
- package/src/cli/commands/tx.ts +0 -448
- package/src/cli/commands/watch.ts +0 -211
- package/src/cli/index.ts +0 -134
- package/src/cli/utils/client.ts +0 -252
- package/src/cli/utils/config.ts +0 -389
- package/src/cli/utils/output.ts +0 -465
- package/src/cli/utils/wallet.ts +0 -109
- package/src/config/agirailsmd.ts +0 -262
- package/src/config/networks.ts +0 -275
- package/src/config/pendingPublish.ts +0 -237
- package/src/config/publishPipeline.ts +0 -359
- package/src/config/syncOperations.ts +0 -279
- package/src/erc8004/ERC8004Bridge.ts +0 -462
- package/src/erc8004/ReputationReporter.ts +0 -468
- package/src/erc8004/index.ts +0 -61
- package/src/errors/index.ts +0 -427
- package/src/index.ts +0 -364
- package/src/level0/Provider.ts +0 -117
- package/src/level0/ServiceDirectory.ts +0 -131
- package/src/level0/index.ts +0 -10
- package/src/level0/provide.ts +0 -132
- package/src/level0/request.ts +0 -432
- package/src/level1/Agent.ts +0 -1426
- package/src/level1/index.ts +0 -10
- package/src/level1/pricing/PriceCalculator.ts +0 -255
- package/src/level1/pricing/PricingStrategy.ts +0 -198
- package/src/level1/types/Job.ts +0 -179
- package/src/level1/types/Options.ts +0 -291
- package/src/level1/types/index.ts +0 -8
- package/src/protocol/ACTPKernel.ts +0 -808
- package/src/protocol/AgentRegistry.ts +0 -559
- package/src/protocol/DIDManager.ts +0 -629
- package/src/protocol/DIDResolver.ts +0 -554
- package/src/protocol/EASHelper.ts +0 -378
- package/src/protocol/EscrowVault.ts +0 -255
- package/src/protocol/EventMonitor.ts +0 -204
- package/src/protocol/MessageSigner.ts +0 -510
- package/src/protocol/ProofGenerator.ts +0 -339
- package/src/protocol/QuoteBuilder.ts +0 -15
- package/src/registry/AgentRegistryClient.ts +0 -202
- package/src/runtime/BlockchainRuntime.ts +0 -1015
- package/src/runtime/IACTPRuntime.ts +0 -306
- package/src/runtime/MockRuntime.ts +0 -1298
- package/src/runtime/MockStateManager.ts +0 -577
- package/src/runtime/index.ts +0 -25
- package/src/runtime/types/MockState.ts +0 -237
- package/src/storage/ArchiveBundleBuilder.ts +0 -561
- package/src/storage/ArweaveClient.ts +0 -946
- package/src/storage/FilebaseClient.ts +0 -790
- package/src/storage/index.ts +0 -96
- package/src/storage/types.ts +0 -348
- package/src/types/adapter.ts +0 -310
- package/src/types/agent.ts +0 -79
- package/src/types/did.ts +0 -223
- package/src/types/eip712.ts +0 -175
- package/src/types/erc8004.ts +0 -293
- package/src/types/escrow.ts +0 -27
- package/src/types/index.ts +0 -17
- package/src/types/message.ts +0 -145
- package/src/types/state.ts +0 -87
- package/src/types/transaction.ts +0 -69
- package/src/types/x402.ts +0 -251
- package/src/utils/ErrorRecoveryGuide.ts +0 -676
- package/src/utils/Helpers.ts +0 -688
- package/src/utils/IPFSClient.ts +0 -368
- package/src/utils/Logger.ts +0 -484
- package/src/utils/NonceManager.ts +0 -591
- package/src/utils/RateLimiter.ts +0 -534
- package/src/utils/ReceivedNonceTracker.ts +0 -567
- package/src/utils/SDKLifecycle.ts +0 -416
- package/src/utils/SecureNonce.ts +0 -78
- package/src/utils/Semaphore.ts +0 -276
- package/src/utils/UsedAttestationTracker.ts +0 -385
- package/src/utils/canonicalJson.ts +0 -38
- package/src/utils/circuitBreaker.ts +0 -324
- package/src/utils/computeTypeHash.ts +0 -48
- package/src/utils/fsSafe.ts +0 -80
- package/src/utils/index.ts +0 -80
- package/src/utils/retry.ts +0 -364
- package/src/utils/security.ts +0 -418
- package/src/utils/validation.ts +0 -540
- package/src/wallet/AutoWalletProvider.ts +0 -299
- package/src/wallet/EOAWalletProvider.ts +0 -69
- package/src/wallet/IWalletProvider.ts +0 -135
- package/src/wallet/aa/BundlerClient.ts +0 -274
- package/src/wallet/aa/DualNonceManager.ts +0 -173
- package/src/wallet/aa/PaymasterClient.ts +0 -174
- package/src/wallet/aa/TransactionBatcher.ts +0 -353
- package/src/wallet/aa/UserOpBuilder.ts +0 -246
- package/src/wallet/aa/constants.ts +0 -60
- package/src/wallet/keystore.ts +0 -240
package/src/utils/Helpers.ts
DELETED
|
@@ -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
|
-
}
|