@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
|
@@ -1,498 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* BaseAdapter - Abstract base class for all adapter implementations
|
|
3
|
-
*
|
|
4
|
-
* Provides shared utility methods for parsing user-friendly inputs into
|
|
5
|
-
* protocol-level types. All adapters extend this class to ensure consistent
|
|
6
|
-
* behavior across the Three-Level API.
|
|
7
|
-
*
|
|
8
|
-
* Key Responsibilities:
|
|
9
|
-
* - Amount parsing (string → bigint with 6 decimals for USDC)
|
|
10
|
-
* - Address validation (0x-prefixed hex)
|
|
11
|
-
* - Deadline parsing ("+24h" → Unix timestamp)
|
|
12
|
-
* - User-friendly error messages
|
|
13
|
-
*
|
|
14
|
-
* @module adapters/BaseAdapter
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
// ============================================================================
|
|
18
|
-
// Constants
|
|
19
|
-
// ============================================================================
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Default dispute window in seconds (2 days).
|
|
23
|
-
* Used when no dispute window is specified in transaction parameters.
|
|
24
|
-
*/
|
|
25
|
-
export const DEFAULT_DISPUTE_WINDOW_SECONDS = 172800;
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Minimum dispute window in seconds (1 hour).
|
|
29
|
-
* Ensures requesters have reasonable time to dispute.
|
|
30
|
-
*
|
|
31
|
-
* SECURITY: Prevents providers from setting windows too short
|
|
32
|
-
* to avoid dispute detection.
|
|
33
|
-
*/
|
|
34
|
-
export const MIN_DISPUTE_WINDOW_SECONDS = 3600; // 1 hour
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Maximum dispute window in seconds (30 days).
|
|
38
|
-
* Prevents excessively long fund locks.
|
|
39
|
-
*
|
|
40
|
-
* SECURITY: Prevents DoS via indefinite fund locking.
|
|
41
|
-
*/
|
|
42
|
-
export const MAX_DISPUTE_WINDOW_SECONDS = 30 * 24 * 3600; // 30 days
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Default deadline offset in seconds (24 hours).
|
|
46
|
-
* Used when no deadline is specified in transaction parameters.
|
|
47
|
-
*/
|
|
48
|
-
export const DEFAULT_DEADLINE_SECONDS = 86400;
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Minimum transaction amount in USDC wei (6 decimals).
|
|
52
|
-
* $0.05 minimum per AGIRAILS protocol specification.
|
|
53
|
-
*/
|
|
54
|
-
export const MIN_AMOUNT_WEI = 50_000n; // $0.05 USDC
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Maximum deadline in hours (10 years).
|
|
58
|
-
* Prevents integer overflow in deadline calculations.
|
|
59
|
-
*/
|
|
60
|
-
export const MAX_DEADLINE_HOURS = 87600; // 10 years
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Maximum deadline in days (10 years).
|
|
64
|
-
* Prevents integer overflow in deadline calculations.
|
|
65
|
-
*/
|
|
66
|
-
export const MAX_DEADLINE_DAYS = 3650; // 10 years
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Custom error for validation failures.
|
|
70
|
-
*
|
|
71
|
-
* Thrown when user input is invalid (e.g., malformed address, negative amount).
|
|
72
|
-
* Provides descriptive error messages for end-user debugging.
|
|
73
|
-
*
|
|
74
|
-
* @example
|
|
75
|
-
* ```typescript
|
|
76
|
-
* throw new ValidationError('Invalid amount format: "abc". Expected number like "100" or "100.50"');
|
|
77
|
-
* ```
|
|
78
|
-
*/
|
|
79
|
-
export class ValidationError extends Error {
|
|
80
|
-
constructor(message: string) {
|
|
81
|
-
super(message);
|
|
82
|
-
this.name = 'ValidationError';
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Abstract base adapter with shared parsing utilities.
|
|
88
|
-
*
|
|
89
|
-
* Provides common functionality for all adapter implementations:
|
|
90
|
-
* - Amount parsing (USDC has 6 decimals)
|
|
91
|
-
* - Address validation
|
|
92
|
-
* - Deadline parsing (relative time or Unix timestamp)
|
|
93
|
-
* - Amount formatting
|
|
94
|
-
*
|
|
95
|
-
* @abstract
|
|
96
|
-
*/
|
|
97
|
-
export abstract class BaseAdapter {
|
|
98
|
-
/**
|
|
99
|
-
* Creates a new BaseAdapter instance.
|
|
100
|
-
*
|
|
101
|
-
* @param requesterAddress - The requester's Ethereum address
|
|
102
|
-
*/
|
|
103
|
-
constructor(protected requesterAddress: string) {}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Parse user-friendly amount string to bigint (USDC has 6 decimals).
|
|
107
|
-
*
|
|
108
|
-
* Accepts multiple input formats:
|
|
109
|
-
* - "100" → 100_000_000n (100.00 USDC)
|
|
110
|
-
* - "100.50" → 100_500_000n (100.50 USDC)
|
|
111
|
-
* - "100 USDC" → 100_000_000n (strips currency suffix)
|
|
112
|
-
* - "$100" → 100_000_000n (strips $ prefix)
|
|
113
|
-
* - 100 (number) → 100_000_000n
|
|
114
|
-
*
|
|
115
|
-
* Rejects:
|
|
116
|
-
* - "abc" → throws ValidationError
|
|
117
|
-
* - "" → throws ValidationError
|
|
118
|
-
* - "-100" → throws ValidationError (negative amounts)
|
|
119
|
-
* - "100.1234567" → throws ValidationError (too many decimals)
|
|
120
|
-
*
|
|
121
|
-
* @param amount - Amount as string or number
|
|
122
|
-
* @returns Amount as bigint with 6 decimals
|
|
123
|
-
* @throws {ValidationError} If amount format is invalid
|
|
124
|
-
*
|
|
125
|
-
* @example
|
|
126
|
-
* ```typescript
|
|
127
|
-
* const amount = this.parseAmount("100.50"); // 100_500_000n
|
|
128
|
-
* const amount = this.parseAmount("100 USDC"); // 100_000_000n
|
|
129
|
-
* ```
|
|
130
|
-
*/
|
|
131
|
-
protected parseAmount(amount: string | number): bigint {
|
|
132
|
-
// Issue #3 Fix: Normalize input - handle all Unicode whitespace
|
|
133
|
-
// Converts all Unicode whitespace to regular spaces, then strip currency symbols
|
|
134
|
-
let normalized = String(amount)
|
|
135
|
-
.replace(/[\s\u00A0\u2000-\u200B\uFEFF]/g, ' ') // Replace all Unicode whitespace with regular space
|
|
136
|
-
.replace(/^[$]/, '') // Strip leading $
|
|
137
|
-
.replace(/\s*(USDC|usdc)$/, '') // Strip trailing USDC
|
|
138
|
-
.replace(/,/g, '') // Strip thousands separators
|
|
139
|
-
.replace(/\s+/g, '') // Remove ALL whitespace (including normalized Unicode spaces)
|
|
140
|
-
.trim(); // Final trim for edge cases
|
|
141
|
-
|
|
142
|
-
// Check for negative
|
|
143
|
-
if (normalized.startsWith('-')) {
|
|
144
|
-
throw new ValidationError('Amount cannot be negative');
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// Validate format (integer or decimal with up to 6 decimal places)
|
|
148
|
-
if (!/^\d+(\.\d{1,6})?$/.test(normalized)) {
|
|
149
|
-
throw new ValidationError(
|
|
150
|
-
`Invalid amount format: "${amount}". Expected number like "100" or "100.50"`
|
|
151
|
-
);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
// Parse to bigint with 6 decimals
|
|
155
|
-
try {
|
|
156
|
-
const parts = normalized.split('.');
|
|
157
|
-
const wholePart = parts[0];
|
|
158
|
-
const decimalPart = (parts[1] || '').padEnd(6, '0'); // Pad to 6 decimals
|
|
159
|
-
|
|
160
|
-
const wholeAmount = BigInt(wholePart) * 1_000_000n;
|
|
161
|
-
const decimalAmount = BigInt(decimalPart);
|
|
162
|
-
|
|
163
|
-
const totalAmount = wholeAmount + decimalAmount;
|
|
164
|
-
|
|
165
|
-
// M1 Fix: Enforce minimum amount ($0.05 USDC = 50,000 wei)
|
|
166
|
-
if (totalAmount < MIN_AMOUNT_WEI) {
|
|
167
|
-
throw new ValidationError(
|
|
168
|
-
`Amount too small: "${amount}". Minimum transaction is $0.05 USDC`
|
|
169
|
-
);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
return totalAmount;
|
|
173
|
-
} catch (error) {
|
|
174
|
-
// Re-throw ValidationError as-is
|
|
175
|
-
if (error instanceof ValidationError) {
|
|
176
|
-
throw error;
|
|
177
|
-
}
|
|
178
|
-
throw new ValidationError(
|
|
179
|
-
`Failed to parse amount: "${amount}". Please use format like "100" or "100.50"`
|
|
180
|
-
);
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
* Validate Ethereum address format.
|
|
186
|
-
*
|
|
187
|
-
* Checks that address:
|
|
188
|
-
* - Is a string
|
|
189
|
-
* - Starts with "0x"
|
|
190
|
-
* - Is exactly 42 characters (0x + 40 hex chars)
|
|
191
|
-
* - Contains only valid hex characters
|
|
192
|
-
*
|
|
193
|
-
* Note: Does not validate checksum (EIP-55) in mock mode.
|
|
194
|
-
*
|
|
195
|
-
* @param address - Address to validate
|
|
196
|
-
* @param paramName - Parameter name for error message
|
|
197
|
-
* @returns Validated address (unchanged)
|
|
198
|
-
* @throws {ValidationError} If address format is invalid
|
|
199
|
-
*
|
|
200
|
-
* @example
|
|
201
|
-
* ```typescript
|
|
202
|
-
* const provider = this.validateAddress(params.to, 'to');
|
|
203
|
-
* ```
|
|
204
|
-
*/
|
|
205
|
-
protected validateAddress(address: string, paramName: string): string {
|
|
206
|
-
if (typeof address !== 'string') {
|
|
207
|
-
throw new ValidationError(
|
|
208
|
-
`Invalid ${paramName} address: expected string, got ${typeof address}`
|
|
209
|
-
);
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
// Check 0x prefix
|
|
213
|
-
if (!address.startsWith('0x')) {
|
|
214
|
-
throw new ValidationError(
|
|
215
|
-
`Invalid ${paramName} address: "${address}". Expected 0x-prefixed hex string.`
|
|
216
|
-
);
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
// Check length (0x + 40 hex chars = 42 total)
|
|
220
|
-
if (address.length !== 42) {
|
|
221
|
-
throw new ValidationError(
|
|
222
|
-
`Invalid ${paramName} address: "${address}". Expected 42 characters (0x + 40 hex).`
|
|
223
|
-
);
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
// Check hex format
|
|
227
|
-
if (!/^0x[0-9a-fA-F]{40}$/.test(address)) {
|
|
228
|
-
throw new ValidationError(
|
|
229
|
-
`Invalid ${paramName} address: "${address}". Contains invalid hex characters.`
|
|
230
|
-
);
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
// Issue #2 Fix: Normalize to lowercase for consistency
|
|
234
|
-
// This prevents case-sensitivity issues when comparing addresses
|
|
235
|
-
return address.toLowerCase();
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
/**
|
|
239
|
-
* Parse deadline from relative time expression or Unix timestamp.
|
|
240
|
-
*
|
|
241
|
-
* Accepts multiple formats:
|
|
242
|
-
* - undefined → now + 24 hours (default)
|
|
243
|
-
* - 1734076400 (number) → passed through as Unix timestamp
|
|
244
|
-
* - "+1h" → now + 1 hour
|
|
245
|
-
* - "+24h" → now + 24 hours
|
|
246
|
-
* - "+7d" → now + 7 days
|
|
247
|
-
*
|
|
248
|
-
* Rejects:
|
|
249
|
-
* - "invalid" → throws ValidationError
|
|
250
|
-
* - "-24h" → throws ValidationError (negative time)
|
|
251
|
-
*
|
|
252
|
-
* @param deadline - Deadline as relative time string, Unix timestamp, or undefined
|
|
253
|
-
* @param currentTime - Current time in seconds (defaults to Date.now() / 1000)
|
|
254
|
-
* @returns Unix timestamp in seconds
|
|
255
|
-
* @throws {ValidationError} If deadline format is invalid
|
|
256
|
-
*
|
|
257
|
-
* @example
|
|
258
|
-
* ```typescript
|
|
259
|
-
* const deadline = this.parseDeadline("+24h"); // now + 86400
|
|
260
|
-
* const deadline = this.parseDeadline(1734076400); // 1734076400
|
|
261
|
-
* const deadline = this.parseDeadline(); // now + 86400 (default)
|
|
262
|
-
* ```
|
|
263
|
-
*/
|
|
264
|
-
protected parseDeadline(deadline?: string | number, currentTime?: number): number {
|
|
265
|
-
const now = currentTime ?? Math.floor(Date.now() / 1000);
|
|
266
|
-
|
|
267
|
-
if (deadline === undefined) {
|
|
268
|
-
// Default: 24 hours from now
|
|
269
|
-
return now + DEFAULT_DEADLINE_SECONDS;
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
if (typeof deadline === 'number') {
|
|
273
|
-
return deadline;
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
// Parse relative time
|
|
277
|
-
const match = deadline.match(/^\+(\d+)(h|d)$/);
|
|
278
|
-
if (!match) {
|
|
279
|
-
throw new ValidationError(
|
|
280
|
-
`Invalid deadline format: "${deadline}". Expected Unix timestamp or relative time (e.g., "+24h", "+7d")`
|
|
281
|
-
);
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
const [, amountStr, unit] = match;
|
|
285
|
-
const amount = parseInt(amountStr, 10);
|
|
286
|
-
|
|
287
|
-
// H1 Fix: Add bounds check to prevent integer overflow
|
|
288
|
-
if (unit === 'h' && amount > MAX_DEADLINE_HOURS) {
|
|
289
|
-
throw new ValidationError(
|
|
290
|
-
`Deadline too far in future: "${deadline}". Maximum is 10 years (${MAX_DEADLINE_HOURS}h)`
|
|
291
|
-
);
|
|
292
|
-
}
|
|
293
|
-
if (unit === 'd' && amount > MAX_DEADLINE_DAYS) {
|
|
294
|
-
throw new ValidationError(
|
|
295
|
-
`Deadline too far in future: "${deadline}". Maximum is 10 years (${MAX_DEADLINE_DAYS}d)`
|
|
296
|
-
);
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
const multiplier = unit === 'h' ? 3600 : 86400;
|
|
300
|
-
|
|
301
|
-
return now + amount * multiplier;
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
/**
|
|
305
|
-
* Validate and normalize dispute window.
|
|
306
|
-
*
|
|
307
|
-
* SECURITY FIX (L-1): Enforces bounds on dispute window:
|
|
308
|
-
* - Minimum: 1 hour (prevents skipping disputes)
|
|
309
|
-
* - Maximum: 30 days (prevents indefinite fund locking)
|
|
310
|
-
*
|
|
311
|
-
* @param disputeWindow - Dispute window in seconds (undefined uses default)
|
|
312
|
-
* @returns Validated dispute window in seconds
|
|
313
|
-
* @throws {ValidationError} If window is outside allowed bounds
|
|
314
|
-
*
|
|
315
|
-
* @example
|
|
316
|
-
* ```typescript
|
|
317
|
-
* this.validateDisputeWindow(3600); // 1 hour - OK
|
|
318
|
-
* this.validateDisputeWindow(86400); // 1 day - OK
|
|
319
|
-
* this.validateDisputeWindow(100); // Too short - throws
|
|
320
|
-
* this.validateDisputeWindow(31 * 86400); // Too long - throws
|
|
321
|
-
* ```
|
|
322
|
-
*/
|
|
323
|
-
protected validateDisputeWindow(disputeWindow?: number): number {
|
|
324
|
-
if (disputeWindow === undefined) {
|
|
325
|
-
return DEFAULT_DISPUTE_WINDOW_SECONDS;
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
if (disputeWindow < MIN_DISPUTE_WINDOW_SECONDS) {
|
|
329
|
-
throw new ValidationError(
|
|
330
|
-
`Dispute window too short: ${disputeWindow} seconds. ` +
|
|
331
|
-
`Minimum is ${MIN_DISPUTE_WINDOW_SECONDS} seconds (1 hour).`
|
|
332
|
-
);
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
if (disputeWindow > MAX_DISPUTE_WINDOW_SECONDS) {
|
|
336
|
-
throw new ValidationError(
|
|
337
|
-
`Dispute window too long: ${disputeWindow} seconds. ` +
|
|
338
|
-
`Maximum is ${MAX_DISPUTE_WINDOW_SECONDS} seconds (30 days).`
|
|
339
|
-
);
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
return disputeWindow;
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
/**
|
|
346
|
-
* Validate bytes32 hex string format.
|
|
347
|
-
*
|
|
348
|
-
* SECURITY FIX (L-2): Validates that a string is a valid bytes32 hex.
|
|
349
|
-
* Used for transaction IDs, escrow IDs, attestation UIDs, etc.
|
|
350
|
-
*
|
|
351
|
-
* @param value - Value to validate
|
|
352
|
-
* @param paramName - Parameter name for error message
|
|
353
|
-
* @returns Validated bytes32 string (normalized to lowercase)
|
|
354
|
-
* @throws {ValidationError} If format is invalid
|
|
355
|
-
*
|
|
356
|
-
* @example
|
|
357
|
-
* ```typescript
|
|
358
|
-
* const txId = this.validateBytes32(id, 'transactionId');
|
|
359
|
-
* ```
|
|
360
|
-
*/
|
|
361
|
-
protected validateBytes32(value: string, paramName: string): string {
|
|
362
|
-
if (typeof value !== 'string') {
|
|
363
|
-
throw new ValidationError(
|
|
364
|
-
`Invalid ${paramName}: expected string, got ${typeof value}`
|
|
365
|
-
);
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
// Check 0x prefix
|
|
369
|
-
if (!value.startsWith('0x')) {
|
|
370
|
-
throw new ValidationError(
|
|
371
|
-
`Invalid ${paramName}: "${value}". Expected 0x-prefixed bytes32 (66 characters total).`
|
|
372
|
-
);
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
// Check length (0x + 64 hex chars = 66 total)
|
|
376
|
-
if (value.length !== 66) {
|
|
377
|
-
throw new ValidationError(
|
|
378
|
-
`Invalid ${paramName}: "${value}". Expected 66 characters (0x + 64 hex), got ${value.length}.`
|
|
379
|
-
);
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
// Check hex format
|
|
383
|
-
if (!/^0x[0-9a-fA-F]{64}$/.test(value)) {
|
|
384
|
-
throw new ValidationError(
|
|
385
|
-
`Invalid ${paramName}: "${value}". Contains invalid hex characters.`
|
|
386
|
-
);
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
// Normalize to lowercase
|
|
390
|
-
return value.toLowerCase();
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
/**
|
|
394
|
-
* Validate Unix timestamp is reasonable.
|
|
395
|
-
*
|
|
396
|
-
* SECURITY FIX (L-6): Validates timestamps to prevent overflow/underflow.
|
|
397
|
-
*
|
|
398
|
-
* @param timestamp - Unix timestamp in seconds
|
|
399
|
-
* @param paramName - Parameter name for error message
|
|
400
|
-
* @returns Validated timestamp
|
|
401
|
-
* @throws {ValidationError} If timestamp is invalid
|
|
402
|
-
*/
|
|
403
|
-
protected validateTimestamp(timestamp: number, paramName: string): number {
|
|
404
|
-
// Check it's a number
|
|
405
|
-
if (typeof timestamp !== 'number' || isNaN(timestamp)) {
|
|
406
|
-
throw new ValidationError(
|
|
407
|
-
`Invalid ${paramName}: expected number, got ${typeof timestamp}`
|
|
408
|
-
);
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
// Check it's positive
|
|
412
|
-
if (timestamp <= 0) {
|
|
413
|
-
throw new ValidationError(
|
|
414
|
-
`Invalid ${paramName}: timestamp must be positive`
|
|
415
|
-
);
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
// Check it's not in the past (with 1 minute buffer)
|
|
419
|
-
const now = Math.floor(Date.now() / 1000);
|
|
420
|
-
const _oneMinuteAgo = now - 60; // Reserved for future validation
|
|
421
|
-
|
|
422
|
-
// Only apply this check if it looks like a deadline/future timestamp
|
|
423
|
-
// (e.g., createdAt can be in the past)
|
|
424
|
-
// For now, just validate it's reasonable
|
|
425
|
-
|
|
426
|
-
// Check for overflow (year 3000 = ~32503680000)
|
|
427
|
-
const year3000 = 32503680000;
|
|
428
|
-
if (timestamp > year3000) {
|
|
429
|
-
throw new ValidationError(
|
|
430
|
-
`Invalid ${paramName}: timestamp ${timestamp} is too far in the future (overflow prevention)`
|
|
431
|
-
);
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
return timestamp;
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
/**
|
|
438
|
-
* Format bigint amount to human-readable string.
|
|
439
|
-
*
|
|
440
|
-
* Converts USDC wei (6 decimals) to formatted string with 2 decimal places.
|
|
441
|
-
* Uses proper rounding (round half up) for display purposes.
|
|
442
|
-
*
|
|
443
|
-
* @param amount - Amount as bigint (6 decimals) or string
|
|
444
|
-
* @returns Formatted string like "100.00 USDC"
|
|
445
|
-
*
|
|
446
|
-
* @example
|
|
447
|
-
* ```typescript
|
|
448
|
-
* this.formatAmount(100_000_000n); // "100.00 USDC"
|
|
449
|
-
* this.formatAmount(100_500_000n); // "100.50 USDC"
|
|
450
|
-
* this.formatAmount(100_126_000n); // "100.13 USDC" (rounded)
|
|
451
|
-
* ```
|
|
452
|
-
*/
|
|
453
|
-
protected formatAmount(amount: bigint | string): string {
|
|
454
|
-
const amountBigInt = typeof amount === 'string' ? BigInt(amount) : amount;
|
|
455
|
-
|
|
456
|
-
// Convert from 6 decimals to decimal string
|
|
457
|
-
const wholePart = amountBigInt / 1_000_000n;
|
|
458
|
-
const decimalPart = amountBigInt % 1_000_000n;
|
|
459
|
-
|
|
460
|
-
// M3 Fix: Proper rounding to 2 decimal places (round half up)
|
|
461
|
-
// decimalPart is 0-999999, we need to round to nearest 10000 (cents)
|
|
462
|
-
const decimalNum = Number(decimalPart);
|
|
463
|
-
const roundedCents = Math.round(decimalNum / 10000); // 6 decimals → 2 decimals
|
|
464
|
-
|
|
465
|
-
// Handle case where rounding causes overflow (e.g., 99.999999 → 100.00)
|
|
466
|
-
if (roundedCents >= 100) {
|
|
467
|
-
return `${wholePart + 1n}.00 USDC`;
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
const formattedDecimal = roundedCents.toString().padStart(2, '0');
|
|
471
|
-
return `${wholePart}.${formattedDecimal} USDC`;
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
/**
|
|
475
|
-
* Encode dispute window as ABI-encoded proof for DELIVERED transition.
|
|
476
|
-
*
|
|
477
|
-
* This helper centralizes proof encoding to prevent drift between
|
|
478
|
-
* adapters and ensures consistency with on-chain expectations.
|
|
479
|
-
*
|
|
480
|
-
* @param disputeWindowSeconds - Dispute window in seconds
|
|
481
|
-
* @returns ABI-encoded bytes32 proof
|
|
482
|
-
*
|
|
483
|
-
* @example
|
|
484
|
-
* ```typescript
|
|
485
|
-
* // Encode 2-hour dispute window
|
|
486
|
-
* const proof = this.encodeDisputeWindowProof(7200);
|
|
487
|
-
* await runtime.transitionState(txId, 'DELIVERED', proof);
|
|
488
|
-
* ```
|
|
489
|
-
*/
|
|
490
|
-
protected encodeDisputeWindowProof(disputeWindowSeconds: number): string {
|
|
491
|
-
// Lazy import to avoid circular dependency issues
|
|
492
|
-
const { ethers } = require('ethers');
|
|
493
|
-
return ethers.AbiCoder.defaultAbiCoder().encode(
|
|
494
|
-
['uint256'],
|
|
495
|
-
[disputeWindowSeconds]
|
|
496
|
-
);
|
|
497
|
-
}
|
|
498
|
-
}
|