@dcentralab/d402-client 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +22 -0
- package/README.md +594 -0
- package/dist/index.d.mts +859 -0
- package/dist/index.d.ts +859 -0
- package/dist/index.js +9021 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +8994 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +56 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,859 @@
|
|
|
1
|
+
import { Account } from 'viem/accounts';
|
|
2
|
+
import { Hash } from 'viem';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Type definitions for D402 payment protocol
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Supported blockchain networks
|
|
10
|
+
*/
|
|
11
|
+
type SupportedNetwork = 'mainnet' | 'sepolia' | 'base' | 'polygon';
|
|
12
|
+
/**
|
|
13
|
+
* D402 Client configuration
|
|
14
|
+
*/
|
|
15
|
+
interface D402Config {
|
|
16
|
+
/** Viem account for signing payments */
|
|
17
|
+
account: Account;
|
|
18
|
+
/** Blockchain network */
|
|
19
|
+
network: SupportedNetwork;
|
|
20
|
+
/** Maximum payment amount in wei (smallest token unit) */
|
|
21
|
+
maxPaymentAmount: bigint;
|
|
22
|
+
/** Token contract address (defaults to USDC if not provided) */
|
|
23
|
+
tokenAddress?: `0x${string}`;
|
|
24
|
+
/** Payment validity window in seconds (default: 300) */
|
|
25
|
+
validityWindowSeconds?: number;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* EIP-712 domain for signature verification
|
|
29
|
+
*/
|
|
30
|
+
interface EIP712Domain {
|
|
31
|
+
name: string;
|
|
32
|
+
version: string;
|
|
33
|
+
chainId: number;
|
|
34
|
+
verifyingContract: `0x${string}`;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Payment requirement from 402 response
|
|
38
|
+
*
|
|
39
|
+
* Matches Python: PaymentRequirements (types.py lines 97-108)
|
|
40
|
+
*/
|
|
41
|
+
interface PaymentRequirement {
|
|
42
|
+
/** D402 protocol version */
|
|
43
|
+
d402Version?: number;
|
|
44
|
+
/** Payment scheme (exact or range) */
|
|
45
|
+
scheme: 'exact' | 'range';
|
|
46
|
+
/** Network identifier */
|
|
47
|
+
network: string;
|
|
48
|
+
/** Maximum amount required (in wei/smallest unit) */
|
|
49
|
+
maxAmountRequired: string;
|
|
50
|
+
/** Recipient address */
|
|
51
|
+
payTo: `0x${string}`;
|
|
52
|
+
/** Token contract address */
|
|
53
|
+
asset: `0x${string}`;
|
|
54
|
+
/** Resource identifier (API path) */
|
|
55
|
+
resource?: string;
|
|
56
|
+
/** Description of the service */
|
|
57
|
+
description?: string;
|
|
58
|
+
/** MIME type of response */
|
|
59
|
+
mimeType?: string;
|
|
60
|
+
/** Output schema definition */
|
|
61
|
+
outputSchema?: any;
|
|
62
|
+
/** Maximum timeout in seconds */
|
|
63
|
+
maxTimeoutSeconds?: number;
|
|
64
|
+
/** Additional EIP-712 domain info */
|
|
65
|
+
extra?: {
|
|
66
|
+
name: string;
|
|
67
|
+
version: string;
|
|
68
|
+
chainId: number;
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Payment authorization details
|
|
73
|
+
*/
|
|
74
|
+
interface PaymentAuthorization {
|
|
75
|
+
/** Sender address */
|
|
76
|
+
from: `0x${string}`;
|
|
77
|
+
/** Recipient address */
|
|
78
|
+
to: `0x${string}`;
|
|
79
|
+
/** Payment amount (wei/smallest unit) */
|
|
80
|
+
value: string;
|
|
81
|
+
/** Valid after timestamp */
|
|
82
|
+
validAfter: string;
|
|
83
|
+
/** Valid before timestamp */
|
|
84
|
+
validBefore: string;
|
|
85
|
+
/** Unique nonce */
|
|
86
|
+
nonce: `0x${string}`;
|
|
87
|
+
/** Request path/resource */
|
|
88
|
+
requestPath: string;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Signed payment ready to send
|
|
92
|
+
*/
|
|
93
|
+
interface SignedPayment {
|
|
94
|
+
/** D402 protocol version */
|
|
95
|
+
d402Version: number;
|
|
96
|
+
/** Payment scheme */
|
|
97
|
+
scheme: string;
|
|
98
|
+
/** Network identifier */
|
|
99
|
+
network: string;
|
|
100
|
+
/** Payment payload */
|
|
101
|
+
payload: {
|
|
102
|
+
/** EIP-712 signature */
|
|
103
|
+
signature: `0x${string}`;
|
|
104
|
+
/** Authorization details */
|
|
105
|
+
authorization: PaymentAuthorization;
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Payment requirements selection logic
|
|
111
|
+
*/
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Options for selecting payment requirements
|
|
115
|
+
*/
|
|
116
|
+
interface PaymentSelectorOptions {
|
|
117
|
+
/** Filter by network (e.g., "base-mainnet") */
|
|
118
|
+
network?: string;
|
|
119
|
+
/** Filter by payment scheme (default: "exact") */
|
|
120
|
+
scheme?: string;
|
|
121
|
+
/** Maximum allowed payment amount in base units */
|
|
122
|
+
maxAmount?: bigint;
|
|
123
|
+
/** Preferred network (will try this first) */
|
|
124
|
+
preferredNetwork?: string;
|
|
125
|
+
/** Preferred token address */
|
|
126
|
+
preferredToken?: string;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Select payment requirement from a list based on filters and preferences
|
|
130
|
+
*
|
|
131
|
+
* This function implements the same logic as Python's default_payment_requirements_selector
|
|
132
|
+
*
|
|
133
|
+
* @param requirements - List of accepted payment requirements from 402 response
|
|
134
|
+
* @param options - Selection options and filters
|
|
135
|
+
* @returns Selected payment requirement
|
|
136
|
+
*
|
|
137
|
+
* @throws {UnsupportedSchemeError} If no matching scheme found
|
|
138
|
+
* @throws {PaymentAmountExceededError} If payment exceeds max amount
|
|
139
|
+
*
|
|
140
|
+
* @example
|
|
141
|
+
* const selected = selectPaymentRequirement(requirements, {
|
|
142
|
+
* scheme: 'exact',
|
|
143
|
+
* network: 'base-mainnet',
|
|
144
|
+
* maxAmount: 1000000n
|
|
145
|
+
* })
|
|
146
|
+
*/
|
|
147
|
+
declare function selectPaymentRequirement(requirements: PaymentRequirement[], options?: PaymentSelectorOptions): PaymentRequirement;
|
|
148
|
+
/**
|
|
149
|
+
* Custom payment selector function type
|
|
150
|
+
*/
|
|
151
|
+
type PaymentSelector = (requirements: PaymentRequirement[], options?: PaymentSelectorOptions) => PaymentRequirement;
|
|
152
|
+
/**
|
|
153
|
+
* Create a custom payment selector with default options
|
|
154
|
+
*
|
|
155
|
+
* @param defaultOptions - Default options to apply
|
|
156
|
+
* @returns Custom selector function
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* const selector = createPaymentSelector({
|
|
160
|
+
* preferredNetwork: 'base-mainnet',
|
|
161
|
+
* maxAmount: 1000000n
|
|
162
|
+
* })
|
|
163
|
+
*
|
|
164
|
+
* const selected = selector(requirements, { scheme: 'exact' })
|
|
165
|
+
*/
|
|
166
|
+
declare function createPaymentSelector(defaultOptions: PaymentSelectorOptions): PaymentSelector;
|
|
167
|
+
/**
|
|
168
|
+
* Sort payment requirements by preference
|
|
169
|
+
* Useful for UI display or debugging
|
|
170
|
+
*
|
|
171
|
+
* @param requirements - List of requirements
|
|
172
|
+
* @param preferredNetwork - Preferred network name
|
|
173
|
+
* @returns Sorted list (preferred first)
|
|
174
|
+
*/
|
|
175
|
+
declare function sortPaymentRequirements(requirements: PaymentRequirement[], preferredNetwork?: string): PaymentRequirement[];
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* D402 Client - Main client class for handling HTTP 402 payments
|
|
179
|
+
*
|
|
180
|
+
* Matches Python implementation: IATP/src/traia_iatp/d402/clients/base.py d402Client
|
|
181
|
+
*/
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* D402 Client configuration.
|
|
185
|
+
*
|
|
186
|
+
* Matches Python: d402Client.__init__ parameters (base.py lines 66-72)
|
|
187
|
+
*/
|
|
188
|
+
interface D402ClientConfig {
|
|
189
|
+
/** Operator account with private key for signing payments (EOA) */
|
|
190
|
+
operatorAccount: Account;
|
|
191
|
+
/**
|
|
192
|
+
* Consumer's IATPWallet contract address.
|
|
193
|
+
* If not provided, uses operator_account.address for testing.
|
|
194
|
+
*/
|
|
195
|
+
walletAddress?: `0x${string}`;
|
|
196
|
+
/**
|
|
197
|
+
* Optional safety limit for maximum payment amount per request in base units.
|
|
198
|
+
*
|
|
199
|
+
* WARNING: This is a simple numeric comparison and does NOT account for:
|
|
200
|
+
* - Different tokens (USDC vs TRAIA vs others) - amounts are compared directly
|
|
201
|
+
* - Token decimals - ensure maxValue uses the same decimals as expected tokens
|
|
202
|
+
* - Exchange rates - this is not a USD limit, it's a token amount limit
|
|
203
|
+
*
|
|
204
|
+
* Each endpoint can have different payment requirements (amount and token),
|
|
205
|
+
* but this limit applies to all requests. Set it based on your most expensive
|
|
206
|
+
* expected payment in the token's base units.
|
|
207
|
+
*
|
|
208
|
+
* If undefined, no limit is enforced (not recommended for production).
|
|
209
|
+
*/
|
|
210
|
+
maxValue?: bigint;
|
|
211
|
+
/**
|
|
212
|
+
* Optional custom selector for payment requirements.
|
|
213
|
+
* If not provided, uses default selector that picks first "exact" scheme.
|
|
214
|
+
*/
|
|
215
|
+
paymentRequirementsSelector?: PaymentSelector;
|
|
216
|
+
/**
|
|
217
|
+
* Optional network filter for payment selection.
|
|
218
|
+
* Only select requirements matching this network.
|
|
219
|
+
*/
|
|
220
|
+
networkFilter?: string;
|
|
221
|
+
/**
|
|
222
|
+
* Optional scheme filter for payment selection.
|
|
223
|
+
* Defaults to "exact".
|
|
224
|
+
*/
|
|
225
|
+
schemeFilter?: string;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* D402 Client for handling HTTP 402 Payment Required responses.
|
|
229
|
+
*
|
|
230
|
+
* Matches Python: d402Client class (base.py lines 63-219)
|
|
231
|
+
*
|
|
232
|
+
* This client automatically:
|
|
233
|
+
* 1. Detects HTTP 402 responses
|
|
234
|
+
* 2. Parses payment requirements
|
|
235
|
+
* 3. Selects appropriate payment option
|
|
236
|
+
* 4. Signs payment with EIP-712
|
|
237
|
+
* 5. Retries request with X-Payment header
|
|
238
|
+
*
|
|
239
|
+
* @example
|
|
240
|
+
* ```ts
|
|
241
|
+
* import { D402Client } from '@iatp/d402-client'
|
|
242
|
+
* import { privateKeyToAccount } from 'viem/accounts'
|
|
243
|
+
*
|
|
244
|
+
* const operatorAccount = privateKeyToAccount('0x...')
|
|
245
|
+
*
|
|
246
|
+
* const client = new D402Client({
|
|
247
|
+
* operatorAccount,
|
|
248
|
+
* walletAddress: '0xUserIATPWallet...',
|
|
249
|
+
* maxValue: 1000000n // 1 USDC max
|
|
250
|
+
* })
|
|
251
|
+
*
|
|
252
|
+
* const response = await client.fetch('http://api.example.com/analyze', {
|
|
253
|
+
* method: 'POST',
|
|
254
|
+
* body: JSON.stringify({ text: 'Analyze this' })
|
|
255
|
+
* })
|
|
256
|
+
*
|
|
257
|
+
* const data = await response.json()
|
|
258
|
+
* ```
|
|
259
|
+
*/
|
|
260
|
+
declare class D402Client {
|
|
261
|
+
private readonly operatorAccount;
|
|
262
|
+
private readonly walletAddress;
|
|
263
|
+
private readonly maxValue?;
|
|
264
|
+
private readonly paymentRequirementsSelector;
|
|
265
|
+
private readonly networkFilter?;
|
|
266
|
+
private readonly schemeFilter;
|
|
267
|
+
/**
|
|
268
|
+
* Create a new D402 Client.
|
|
269
|
+
*
|
|
270
|
+
* Matches Python: d402Client.__init__ (base.py lines 66-95)
|
|
271
|
+
*
|
|
272
|
+
* @param config - Client configuration
|
|
273
|
+
*/
|
|
274
|
+
constructor(config: D402ClientConfig);
|
|
275
|
+
/**
|
|
276
|
+
* Select payment requirement from list of options.
|
|
277
|
+
*
|
|
278
|
+
* Matches Python: select_payment_requirements (base.py lines 152-174)
|
|
279
|
+
*
|
|
280
|
+
* @param requirements - List of payment requirements from 402 response
|
|
281
|
+
* @returns Selected payment requirement
|
|
282
|
+
*/
|
|
283
|
+
selectPaymentRequirement(requirements: PaymentRequirement[]): PaymentRequirement;
|
|
284
|
+
/**
|
|
285
|
+
* Get the wallet address used for payments.
|
|
286
|
+
*
|
|
287
|
+
* @returns IATPWallet contract address or operator EOA address
|
|
288
|
+
*/
|
|
289
|
+
getWalletAddress(): `0x${string}`;
|
|
290
|
+
/**
|
|
291
|
+
* Get the operator account used for signing.
|
|
292
|
+
*
|
|
293
|
+
* @returns Operator account
|
|
294
|
+
*/
|
|
295
|
+
getOperatorAccount(): Account;
|
|
296
|
+
/**
|
|
297
|
+
* Get the maximum payment value limit.
|
|
298
|
+
*
|
|
299
|
+
* @returns Maximum value in base units, or undefined if no limit
|
|
300
|
+
*/
|
|
301
|
+
getMaxValue(): bigint | undefined;
|
|
302
|
+
/**
|
|
303
|
+
* Fetch with automatic 402 payment handling.
|
|
304
|
+
*
|
|
305
|
+
* Matches Python: HttpxHooks.on_response() (httpx.py lines 33-117)
|
|
306
|
+
*
|
|
307
|
+
* Flow:
|
|
308
|
+
* 1. Make request without payment
|
|
309
|
+
* 2. If 402 response, parse payment requirements
|
|
310
|
+
* 3. Select appropriate payment option
|
|
311
|
+
* 4. Sign payment with EIP-712
|
|
312
|
+
* 5. Retry request with X-Payment header
|
|
313
|
+
* 6. Return final response
|
|
314
|
+
*
|
|
315
|
+
* @param url - URL to fetch
|
|
316
|
+
* @param init - Fetch options (method, headers, body, etc.)
|
|
317
|
+
* @returns Response object (after payment if 402)
|
|
318
|
+
*
|
|
319
|
+
* @example
|
|
320
|
+
* ```ts
|
|
321
|
+
* const client = new D402Client({ operatorAccount, walletAddress })
|
|
322
|
+
*
|
|
323
|
+
* const response = await client.fetch('http://api.example.com/analyze', {
|
|
324
|
+
* method: 'POST',
|
|
325
|
+
* headers: { 'Content-Type': 'application/json' },
|
|
326
|
+
* body: JSON.stringify({ text: 'Analyze this' })
|
|
327
|
+
* })
|
|
328
|
+
*
|
|
329
|
+
* const data = await response.json()
|
|
330
|
+
* ```
|
|
331
|
+
*/
|
|
332
|
+
fetch(url: string, init?: RequestInit): Promise<Response>;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* EIP-712 payment signing utilities
|
|
337
|
+
*
|
|
338
|
+
* Matches Python implementation: IATP/src/traia_iatp/d402/payment_signing.py
|
|
339
|
+
*/
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Sign a D402 payment using EIP-712 signature.
|
|
343
|
+
*
|
|
344
|
+
* Matches Python: sign_payment_header(operator_account, payment_requirements, header, wallet_address, request_path)
|
|
345
|
+
* (payment_signing.py lines 54-155)
|
|
346
|
+
*
|
|
347
|
+
* This creates a PullFundsForSettlement signature that matches IATPWallet.sol validation.
|
|
348
|
+
*
|
|
349
|
+
* @param params - Signing parameters
|
|
350
|
+
* @param params.operatorAccount - Operator account with private key for signing (EOA)
|
|
351
|
+
* @param params.paymentRequirement - Payment requirements from 402 response
|
|
352
|
+
* @param params.walletAddress - Consumer's IATPWallet contract address (optional, uses operator address if not provided)
|
|
353
|
+
* @param params.requestPath - API request path (optional, uses payment_requirements.resource if not provided)
|
|
354
|
+
* @returns Signed payment ready to encode and send
|
|
355
|
+
*
|
|
356
|
+
* @example
|
|
357
|
+
* ```ts
|
|
358
|
+
* const requirement = await parsePaymentRequirement(response)
|
|
359
|
+
* const signedPayment = await signD402Payment({
|
|
360
|
+
* operatorAccount: account,
|
|
361
|
+
* paymentRequirement: requirement,
|
|
362
|
+
* walletAddress: '0xUserWallet...'
|
|
363
|
+
* })
|
|
364
|
+
* const encoded = encodePayment(signedPayment)
|
|
365
|
+
* ```
|
|
366
|
+
*/
|
|
367
|
+
declare function signD402Payment(params: {
|
|
368
|
+
operatorAccount: Account;
|
|
369
|
+
paymentRequirement: PaymentRequirement;
|
|
370
|
+
walletAddress?: `0x${string}`;
|
|
371
|
+
requestPath?: string;
|
|
372
|
+
d402Version?: number;
|
|
373
|
+
}): Promise<SignedPayment>;
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* Parse 402 payment requirements from HTTP responses
|
|
377
|
+
*
|
|
378
|
+
* Matches Python implementation: IATP/src/traia_iatp/d402/clients/httpx.py lines 64-66
|
|
379
|
+
* Response structure from: IATP/src/traia_iatp/d402/types.py d402PaymentRequiredResponse
|
|
380
|
+
*/
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* Parse payment requirements from HTTP 402 response.
|
|
384
|
+
*
|
|
385
|
+
* Matches Python:
|
|
386
|
+
* data = response.json()
|
|
387
|
+
* payment_response = d402PaymentRequiredResponse(**data)
|
|
388
|
+
*
|
|
389
|
+
* The 402 response body contains payment requirements in camelCase JSON format.
|
|
390
|
+
*
|
|
391
|
+
* @param response - HTTP Response object with status 402
|
|
392
|
+
* @returns First payment requirement from accepts array
|
|
393
|
+
* @throws {Invalid402ResponseError} If response is not valid 402 or malformed
|
|
394
|
+
*
|
|
395
|
+
* @example
|
|
396
|
+
* ```ts
|
|
397
|
+
* const response = await fetch('http://api.example.com')
|
|
398
|
+
* if (response.status === 402) {
|
|
399
|
+
* const requirement = await parsePaymentRequirement(response)
|
|
400
|
+
* console.log(requirement.maxAmountRequired) // "10000"
|
|
401
|
+
* }
|
|
402
|
+
* ```
|
|
403
|
+
*/
|
|
404
|
+
declare function parsePaymentRequirement(response: Response): Promise<PaymentRequirement>;
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* Base64 encoding/decoding for payment payloads
|
|
408
|
+
*
|
|
409
|
+
* Matches Python implementation: IATP/src/traia_iatp/d402/encoding.py
|
|
410
|
+
*/
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* Encode a payment object to base64 string.
|
|
414
|
+
*
|
|
415
|
+
* This combines JSON serialization with base64 encoding.
|
|
416
|
+
* Matches Python: encode_payment(payment_payload: Dict[str, Any]) -> str
|
|
417
|
+
*
|
|
418
|
+
* @param payment - Payment object to encode
|
|
419
|
+
* @returns Base64 encoded payment string suitable for X-Payment header
|
|
420
|
+
*
|
|
421
|
+
* @example
|
|
422
|
+
* ```ts
|
|
423
|
+
* const payment = { d402Version: 1, scheme: 'exact', payload: {...} }
|
|
424
|
+
* const encoded = encodePayment(payment)
|
|
425
|
+
* // Use in header: { 'X-Payment': encoded }
|
|
426
|
+
* ```
|
|
427
|
+
*/
|
|
428
|
+
declare function encodePayment(payment: SignedPayment): string;
|
|
429
|
+
/**
|
|
430
|
+
* Decode a base64 encoded payment string back to payment object.
|
|
431
|
+
*
|
|
432
|
+
* Matches Python: decode_payment(encoded_payment: str) -> Dict[str, Any]
|
|
433
|
+
*
|
|
434
|
+
* @param encodedPayment - Base64 encoded payment string
|
|
435
|
+
* @returns Decoded payment object
|
|
436
|
+
*
|
|
437
|
+
* @example
|
|
438
|
+
* ```ts
|
|
439
|
+
* const payment = decodePayment(encodedString)
|
|
440
|
+
* console.log(payment.d402Version) // 1
|
|
441
|
+
* ```
|
|
442
|
+
*/
|
|
443
|
+
declare function decodePayment(encodedPayment: string): SignedPayment;
|
|
444
|
+
|
|
445
|
+
/**
|
|
446
|
+
* Utility functions for D402 payment processing
|
|
447
|
+
*/
|
|
448
|
+
|
|
449
|
+
/**
|
|
450
|
+
* Parse a money string or number into atomic units (wei)
|
|
451
|
+
*
|
|
452
|
+
* @param amount - Amount as string (e.g., "$1.00", "1.5") or number
|
|
453
|
+
* @param decimals - Token decimals (e.g., 6 for USDC, 18 for ETH)
|
|
454
|
+
* @returns Amount in atomic units (wei)
|
|
455
|
+
*
|
|
456
|
+
* @example
|
|
457
|
+
* parseMoney("$1.00", 6) // Returns 1000000n (1 USDC in wei)
|
|
458
|
+
* parseMoney("0.5", 18) // Returns 500000000000000000n (0.5 ETH in wei)
|
|
459
|
+
*/
|
|
460
|
+
declare function parseMoney(amount: string | number | bigint, decimals: number): bigint;
|
|
461
|
+
/**
|
|
462
|
+
* Format atomic units back to human-readable format
|
|
463
|
+
*
|
|
464
|
+
* @param amount - Amount in atomic units (wei)
|
|
465
|
+
* @param decimals - Token decimals
|
|
466
|
+
* @returns Formatted string
|
|
467
|
+
*
|
|
468
|
+
* @example
|
|
469
|
+
* formatMoney(1000000n, 6) // Returns "1.000000"
|
|
470
|
+
*/
|
|
471
|
+
declare function formatMoney(amount: bigint, decimals: number): string;
|
|
472
|
+
/**
|
|
473
|
+
* Get USDC token address for a given network
|
|
474
|
+
*
|
|
475
|
+
* @param network - Network name
|
|
476
|
+
* @returns USDC token address
|
|
477
|
+
*
|
|
478
|
+
* @throws {UnsupportedNetworkError} If network is not supported
|
|
479
|
+
*/
|
|
480
|
+
declare function getUsdcAddress(network: SupportedNetwork): `0x${string}`;
|
|
481
|
+
/**
|
|
482
|
+
* Get chain ID for a given network.
|
|
483
|
+
*
|
|
484
|
+
* Matches Python: get_chain_id(network: str) -> str (chains.py lines 10-21)
|
|
485
|
+
*
|
|
486
|
+
* Supports both network names and numeric chain IDs as strings.
|
|
487
|
+
*
|
|
488
|
+
* @param network - Network name or chain ID as string
|
|
489
|
+
* @returns Chain ID as number
|
|
490
|
+
*
|
|
491
|
+
* @throws {UnsupportedNetworkError} If network is not supported
|
|
492
|
+
*
|
|
493
|
+
* @example
|
|
494
|
+
* ```ts
|
|
495
|
+
* getChainId('sepolia') // Returns 11155111
|
|
496
|
+
* getChainId('11155111') // Returns 11155111 (passthrough)
|
|
497
|
+
* getChainId('base') // Returns 8453
|
|
498
|
+
* ```
|
|
499
|
+
*/
|
|
500
|
+
declare function getChainId(network: string): number;
|
|
501
|
+
/**
|
|
502
|
+
* Find matching payment requirement from a list
|
|
503
|
+
*
|
|
504
|
+
* @param requirements - List of payment requirements
|
|
505
|
+
* @param scheme - Desired payment scheme (default: "exact")
|
|
506
|
+
* @param network - Desired network (optional)
|
|
507
|
+
* @returns Matching payment requirement or undefined
|
|
508
|
+
*/
|
|
509
|
+
declare function findMatchingPaymentRequirement(requirements: PaymentRequirement[], scheme?: string, network?: string): PaymentRequirement | undefined;
|
|
510
|
+
/**
|
|
511
|
+
* Convert USD amount to USDC atomic units
|
|
512
|
+
*
|
|
513
|
+
* @param usdAmount - Amount in USD (e.g., "1.00" or 1.5)
|
|
514
|
+
* @param decimals - USDC decimals (default: 6)
|
|
515
|
+
* @returns Amount in USDC atomic units
|
|
516
|
+
*
|
|
517
|
+
* @example
|
|
518
|
+
* usdToUsdc("1.00") // Returns 1000000n
|
|
519
|
+
* usdToUsdc(1.5) // Returns 1500000n
|
|
520
|
+
*/
|
|
521
|
+
declare function usdToUsdc(usdAmount: string | number, decimals?: number): bigint;
|
|
522
|
+
/**
|
|
523
|
+
* Generate a random nonce for payment authorization
|
|
524
|
+
*
|
|
525
|
+
* @returns Random 32-byte nonce as hex string
|
|
526
|
+
*/
|
|
527
|
+
declare function generateNonce(): `0x${string}`;
|
|
528
|
+
/**
|
|
529
|
+
* Get current timestamp in seconds
|
|
530
|
+
*
|
|
531
|
+
* @returns Unix timestamp in seconds
|
|
532
|
+
*/
|
|
533
|
+
declare function getCurrentTimestamp(): number;
|
|
534
|
+
/**
|
|
535
|
+
* Validate Ethereum address format
|
|
536
|
+
*
|
|
537
|
+
* @param address - Address to validate
|
|
538
|
+
* @returns True if valid Ethereum address
|
|
539
|
+
*/
|
|
540
|
+
declare function isValidAddress(address: string): boolean;
|
|
541
|
+
/**
|
|
542
|
+
* Normalize Ethereum address to checksummed format
|
|
543
|
+
* Note: This is a simple lowercase normalization. For full checksum validation, use viem's getAddress()
|
|
544
|
+
*
|
|
545
|
+
* @param address - Address to normalize
|
|
546
|
+
* @returns Normalized address
|
|
547
|
+
*/
|
|
548
|
+
declare function normalizeAddress(address: string): `0x${string}`;
|
|
549
|
+
/**
|
|
550
|
+
* Decode X-PAYMENT-RESPONSE header from server
|
|
551
|
+
*
|
|
552
|
+
* @param header - Base64 encoded payment response
|
|
553
|
+
* @returns Decoded payment response
|
|
554
|
+
*
|
|
555
|
+
* @example
|
|
556
|
+
* const response = decodePaymentResponse(responseHeader)
|
|
557
|
+
* console.log(response.success, response.transaction)
|
|
558
|
+
*/
|
|
559
|
+
declare function decodePaymentResponse(header: string): {
|
|
560
|
+
success: boolean;
|
|
561
|
+
transaction?: string;
|
|
562
|
+
network?: string;
|
|
563
|
+
payer?: string;
|
|
564
|
+
message?: string;
|
|
565
|
+
};
|
|
566
|
+
|
|
567
|
+
/**
|
|
568
|
+
* Error classes for D402 payment protocol
|
|
569
|
+
*/
|
|
570
|
+
/**
|
|
571
|
+
* Base error class for all payment-related errors
|
|
572
|
+
*/
|
|
573
|
+
declare class PaymentError extends Error {
|
|
574
|
+
constructor(message: string);
|
|
575
|
+
}
|
|
576
|
+
/**
|
|
577
|
+
* Thrown when payment amount exceeds the configured maximum allowed value
|
|
578
|
+
*/
|
|
579
|
+
declare class PaymentAmountExceededError extends PaymentError {
|
|
580
|
+
amount: bigint;
|
|
581
|
+
maxAmount: bigint;
|
|
582
|
+
tokenAddress?: string | undefined;
|
|
583
|
+
constructor(amount: bigint, maxAmount: bigint, tokenAddress?: string | undefined);
|
|
584
|
+
}
|
|
585
|
+
/**
|
|
586
|
+
* Thrown when request configuration is missing required fields
|
|
587
|
+
*/
|
|
588
|
+
declare class MissingRequestConfigError extends PaymentError {
|
|
589
|
+
constructor(message: string);
|
|
590
|
+
}
|
|
591
|
+
/**
|
|
592
|
+
* Thrown when payment has already been attempted for a request
|
|
593
|
+
*/
|
|
594
|
+
declare class PaymentAlreadyAttemptedError extends PaymentError {
|
|
595
|
+
constructor(message?: string);
|
|
596
|
+
}
|
|
597
|
+
/**
|
|
598
|
+
* Thrown when no supported payment scheme is found in payment requirements
|
|
599
|
+
*/
|
|
600
|
+
declare class UnsupportedSchemeError extends PaymentError {
|
|
601
|
+
availableSchemes: string[];
|
|
602
|
+
constructor(availableSchemes: string[], message?: string);
|
|
603
|
+
}
|
|
604
|
+
/**
|
|
605
|
+
* Thrown when payment verification fails
|
|
606
|
+
*/
|
|
607
|
+
declare class PaymentVerificationError extends PaymentError {
|
|
608
|
+
constructor(message: string);
|
|
609
|
+
}
|
|
610
|
+
/**
|
|
611
|
+
* Thrown when HTTP 402 response is malformed
|
|
612
|
+
*/
|
|
613
|
+
declare class Invalid402ResponseError extends PaymentError {
|
|
614
|
+
constructor(message: string);
|
|
615
|
+
}
|
|
616
|
+
/**
|
|
617
|
+
* Thrown when network is not supported
|
|
618
|
+
*/
|
|
619
|
+
declare class UnsupportedNetworkError extends PaymentError {
|
|
620
|
+
network: string;
|
|
621
|
+
constructor(network: string);
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
/**
|
|
625
|
+
* Network and token constants
|
|
626
|
+
*/
|
|
627
|
+
|
|
628
|
+
/**
|
|
629
|
+
* Chain IDs for supported networks
|
|
630
|
+
*/
|
|
631
|
+
declare const CHAIN_IDS: Record<SupportedNetwork, number>;
|
|
632
|
+
/**
|
|
633
|
+
* Network configuration
|
|
634
|
+
*/
|
|
635
|
+
declare const NETWORKS: Record<SupportedNetwork, {
|
|
636
|
+
chainId: number;
|
|
637
|
+
name: string;
|
|
638
|
+
nativeCurrency: {
|
|
639
|
+
name: string;
|
|
640
|
+
symbol: string;
|
|
641
|
+
decimals: number;
|
|
642
|
+
};
|
|
643
|
+
}>;
|
|
644
|
+
/**
|
|
645
|
+
* Default USDC token addresses per network
|
|
646
|
+
*/
|
|
647
|
+
declare const TOKEN_ADDRESSES: Record<SupportedNetwork, `0x${string}`>;
|
|
648
|
+
/**
|
|
649
|
+
* Default payment validity window (5 minutes)
|
|
650
|
+
*/
|
|
651
|
+
declare const DEFAULT_VALIDITY_WINDOW_SECONDS = 300;
|
|
652
|
+
/**
|
|
653
|
+
* EIP-712 type definitions for PullFundsForSettlement
|
|
654
|
+
*/
|
|
655
|
+
declare const EIP712_TYPES: {
|
|
656
|
+
readonly PullFundsForSettlement: readonly [{
|
|
657
|
+
readonly name: "wallet";
|
|
658
|
+
readonly type: "address";
|
|
659
|
+
}, {
|
|
660
|
+
readonly name: "provider";
|
|
661
|
+
readonly type: "address";
|
|
662
|
+
}, {
|
|
663
|
+
readonly name: "token";
|
|
664
|
+
readonly type: "address";
|
|
665
|
+
}, {
|
|
666
|
+
readonly name: "amount";
|
|
667
|
+
readonly type: "uint256";
|
|
668
|
+
}, {
|
|
669
|
+
readonly name: "deadline";
|
|
670
|
+
readonly type: "uint256";
|
|
671
|
+
}, {
|
|
672
|
+
readonly name: "requestPath";
|
|
673
|
+
readonly type: "string";
|
|
674
|
+
}];
|
|
675
|
+
};
|
|
676
|
+
|
|
677
|
+
/**
|
|
678
|
+
* Contract configuration and utilities for IATP.
|
|
679
|
+
*
|
|
680
|
+
* Matches Python implementation: IATP/src/traia_iatp/contracts/config.py
|
|
681
|
+
*
|
|
682
|
+
* Bundles contract ABIs and addresses directly in the package for reliable access.
|
|
683
|
+
*/
|
|
684
|
+
/**
|
|
685
|
+
* Supported contract names.
|
|
686
|
+
*
|
|
687
|
+
* Matches Python: ContractName enum (config.py lines 16-21)
|
|
688
|
+
*/
|
|
689
|
+
declare enum ContractName {
|
|
690
|
+
IATP_WALLET = "IATPWallet",
|
|
691
|
+
IATP_WALLET_FACTORY = "IATPWalletFactory",
|
|
692
|
+
IATP_SETTLEMENT_LAYER = "IATPSettlementLayer",
|
|
693
|
+
ROLE_MANAGER = "RoleManager"
|
|
694
|
+
}
|
|
695
|
+
/**
|
|
696
|
+
* Supported networks for contract deployments.
|
|
697
|
+
*
|
|
698
|
+
* Matches Python: SUPPORTED_NETWORKS (config.py line 25)
|
|
699
|
+
*/
|
|
700
|
+
type SupportedContractNetwork = 'sepolia' | 'localhost';
|
|
701
|
+
/**
|
|
702
|
+
* Get contract address for a given network.
|
|
703
|
+
*
|
|
704
|
+
* Matches Python: get_contract_address(contract_name: str, network: str) -> Optional[str]
|
|
705
|
+
* (config.py lines 77-118)
|
|
706
|
+
*
|
|
707
|
+
* @param contractName - Name of the contract (use ContractName enum)
|
|
708
|
+
* @param network - Network name (default: "sepolia")
|
|
709
|
+
* @param useProxy - Use proxy address if true, implementation if false (default: true)
|
|
710
|
+
* @returns Contract address as hex string, or null if not found
|
|
711
|
+
*
|
|
712
|
+
* @example
|
|
713
|
+
* ```ts
|
|
714
|
+
* const factoryAddr = getContractAddress(ContractName.IATP_WALLET_FACTORY, 'sepolia')
|
|
715
|
+
* console.log(factoryAddr) // "0x15D83638E339a0f29283f6B93dC1bb90b8339078"
|
|
716
|
+
* ```
|
|
717
|
+
*/
|
|
718
|
+
declare function getContractAddress(contractName: string | ContractName, network?: SupportedContractNetwork, useProxy?: boolean): string | null;
|
|
719
|
+
/**
|
|
720
|
+
* Get contract ABI for a given network.
|
|
721
|
+
*
|
|
722
|
+
* Matches Python: get_contract_abi(contract_name: str, network: str) -> Optional[List[dict]]
|
|
723
|
+
* (config.py lines 121-156)
|
|
724
|
+
*
|
|
725
|
+
* @param contractName - Name of the contract (use ContractName enum)
|
|
726
|
+
* @param network - Network name (default: "sepolia")
|
|
727
|
+
* @returns Contract ABI as array of objects, or null if not found
|
|
728
|
+
*
|
|
729
|
+
* @example
|
|
730
|
+
* ```ts
|
|
731
|
+
* const factoryAbi = getContractAbi(ContractName.IATP_WALLET_FACTORY, 'sepolia')
|
|
732
|
+
* console.log(factoryAbi.length) // Number of ABI entries
|
|
733
|
+
* ```
|
|
734
|
+
*/
|
|
735
|
+
declare function getContractAbi(contractName: string | ContractName, network?: SupportedContractNetwork): any[] | null;
|
|
736
|
+
/**
|
|
737
|
+
* Get contract configuration (address and ABI) for a network.
|
|
738
|
+
*
|
|
739
|
+
* Matches Python: get_contract_config(network: str) from wallet_creator.py
|
|
740
|
+
*
|
|
741
|
+
* @param contractName - Name of the contract
|
|
742
|
+
* @param network - Network name (default: "sepolia")
|
|
743
|
+
* @returns Object with address and abi, or null if not found
|
|
744
|
+
*
|
|
745
|
+
* @example
|
|
746
|
+
* ```ts
|
|
747
|
+
* const config = getContractConfig(ContractName.IATP_WALLET_FACTORY, 'sepolia')
|
|
748
|
+
* if (config) {
|
|
749
|
+
* console.log(config.address)
|
|
750
|
+
* console.log(config.abi.length)
|
|
751
|
+
* }
|
|
752
|
+
* ```
|
|
753
|
+
*/
|
|
754
|
+
declare function getContractConfig(contractName: string | ContractName, network?: SupportedContractNetwork): {
|
|
755
|
+
address: string;
|
|
756
|
+
abi: any[];
|
|
757
|
+
} | null;
|
|
758
|
+
/**
|
|
759
|
+
* Get all contract addresses for a network.
|
|
760
|
+
*
|
|
761
|
+
* @param network - Network name
|
|
762
|
+
* @returns Object with all contract addresses for the network
|
|
763
|
+
*
|
|
764
|
+
* @example
|
|
765
|
+
* ```ts
|
|
766
|
+
* const addresses = getAllContractAddresses('sepolia')
|
|
767
|
+
* console.log(addresses.IATPWalletFactory)
|
|
768
|
+
* ```
|
|
769
|
+
*/
|
|
770
|
+
declare function getAllContractAddresses(network: SupportedContractNetwork): Record<string, string>;
|
|
771
|
+
/**
|
|
772
|
+
* Check if a contract is deployed on a network.
|
|
773
|
+
*
|
|
774
|
+
* @param contractName - Name of the contract
|
|
775
|
+
* @param network - Network name
|
|
776
|
+
* @returns True if contract exists on network
|
|
777
|
+
*
|
|
778
|
+
* @example
|
|
779
|
+
* ```ts
|
|
780
|
+
* if (isContractDeployed(ContractName.IATP_WALLET_FACTORY, 'sepolia')) {
|
|
781
|
+
* // Contract is available
|
|
782
|
+
* }
|
|
783
|
+
* ```
|
|
784
|
+
*/
|
|
785
|
+
declare function isContractDeployed(contractName: string | ContractName, network: SupportedContractNetwork): boolean;
|
|
786
|
+
|
|
787
|
+
/**
|
|
788
|
+
* IATPWallet creation and management
|
|
789
|
+
*
|
|
790
|
+
* Matches Python implementation: IATP/src/traia_iatp/scripts/create_wallet.py
|
|
791
|
+
*/
|
|
792
|
+
|
|
793
|
+
/**
|
|
794
|
+
* Result of wallet creation.
|
|
795
|
+
*
|
|
796
|
+
* Matches Python: create_wallet() return type (lines 138-147)
|
|
797
|
+
*/
|
|
798
|
+
interface WalletCreationResult {
|
|
799
|
+
/** Address of the created IATPWallet contract */
|
|
800
|
+
walletAddress: `0x${string}`;
|
|
801
|
+
/** Owner address (who created it) */
|
|
802
|
+
ownerAddress: `0x${string}`;
|
|
803
|
+
/** Operator address (can sign payments) */
|
|
804
|
+
operatorAddress: `0x${string}`;
|
|
805
|
+
/** Operator private key (store securely!) */
|
|
806
|
+
operatorPrivateKey: `0x${string}`;
|
|
807
|
+
/** Transaction hash */
|
|
808
|
+
transactionHash: Hash;
|
|
809
|
+
/** Block number where wallet was created */
|
|
810
|
+
blockNumber: bigint;
|
|
811
|
+
/** Network where wallet was deployed */
|
|
812
|
+
network: string;
|
|
813
|
+
/** Chain ID */
|
|
814
|
+
chainId: number;
|
|
815
|
+
}
|
|
816
|
+
/**
|
|
817
|
+
* Create a new IATPWallet using IATPWalletFactory.
|
|
818
|
+
*
|
|
819
|
+
* Matches Python: create_wallet(owner_private_key, network, wait_confirmations)
|
|
820
|
+
* (create_wallet.py lines 37-149)
|
|
821
|
+
*
|
|
822
|
+
* This function:
|
|
823
|
+
* 1. Generates a new operator keypair
|
|
824
|
+
* 2. Calls IATPWalletFactory.createWallet(operatorAddress)
|
|
825
|
+
* 3. Waits for transaction confirmation
|
|
826
|
+
* 4. Extracts wallet address from WalletCreated event
|
|
827
|
+
* 5. Returns wallet info including operator keys
|
|
828
|
+
*
|
|
829
|
+
* @param params - Creation parameters
|
|
830
|
+
* @param params.ownerAccount - Owner's account (will own the wallet)
|
|
831
|
+
* @param params.network - Network to deploy on (default: "sepolia")
|
|
832
|
+
* @param params.rpcUrl - Custom RPC URL (optional)
|
|
833
|
+
* @param params.operatorPrivateKey - Use specific operator key instead of generating (optional)
|
|
834
|
+
* @returns Wallet creation result with addresses and keys
|
|
835
|
+
*
|
|
836
|
+
* @example
|
|
837
|
+
* ```ts
|
|
838
|
+
* import { createIATPWallet } from '@iatp/d402-client'
|
|
839
|
+
* import { privateKeyToAccount } from 'viem/accounts'
|
|
840
|
+
*
|
|
841
|
+
* const ownerAccount = privateKeyToAccount('0x...')
|
|
842
|
+
*
|
|
843
|
+
* const result = await createIATPWallet({
|
|
844
|
+
* ownerAccount,
|
|
845
|
+
* network: 'sepolia'
|
|
846
|
+
* })
|
|
847
|
+
*
|
|
848
|
+
* console.log('Wallet created:', result.walletAddress)
|
|
849
|
+
* console.log('Operator key:', result.operatorPrivateKey) // Store securely!
|
|
850
|
+
* ```
|
|
851
|
+
*/
|
|
852
|
+
declare function createIATPWallet(params: {
|
|
853
|
+
ownerAccount: Account;
|
|
854
|
+
network?: 'sepolia' | 'localhost';
|
|
855
|
+
rpcUrl?: string;
|
|
856
|
+
operatorPrivateKey?: `0x${string}`;
|
|
857
|
+
}): Promise<WalletCreationResult>;
|
|
858
|
+
|
|
859
|
+
export { CHAIN_IDS, ContractName, D402Client, type D402ClientConfig, type D402Config, DEFAULT_VALIDITY_WINDOW_SECONDS, type EIP712Domain, EIP712_TYPES, Invalid402ResponseError, MissingRequestConfigError, NETWORKS, PaymentAlreadyAttemptedError, PaymentAmountExceededError, type PaymentAuthorization, PaymentError, type PaymentRequirement, type PaymentSelector, type PaymentSelectorOptions, PaymentVerificationError, type SignedPayment, type SupportedContractNetwork, type SupportedNetwork, TOKEN_ADDRESSES, UnsupportedNetworkError, UnsupportedSchemeError, type WalletCreationResult, createIATPWallet, createPaymentSelector, decodePayment, decodePaymentResponse, encodePayment, findMatchingPaymentRequirement, formatMoney, generateNonce, getAllContractAddresses, getChainId, getContractAbi, getContractAddress, getContractConfig, getCurrentTimestamp, getUsdcAddress, isContractDeployed, isValidAddress, normalizeAddress, parseMoney, parsePaymentRequirement, selectPaymentRequirement, signD402Payment, sortPaymentRequirements, usdToUsdc };
|