@peac/adapter-x402 0.10.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/README.md +116 -0
- package/dist/errors.d.ts +36 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +62 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +35 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +49 -0
- package/dist/index.js.map +1 -0
- package/dist/map.d.ts +56 -0
- package/dist/map.d.ts.map +1 -0
- package/dist/map.js +111 -0
- package/dist/map.js.map +1 -0
- package/dist/types.d.ts +392 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +58 -0
- package/dist/types.js.map +1 -0
- package/dist/verify.d.ts +80 -0
- package/dist/verify.d.ts.map +1 -0
- package/dist/verify.js +919 -0
- package/dist/verify.js.map +1 -0
- package/package.json +37 -0
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* x402 Offer/Receipt extension types
|
|
3
|
+
*
|
|
4
|
+
* Models the x402 offer/receipt flow:
|
|
5
|
+
* - SignedOffer: EIP-712 or JWS signed payment terms
|
|
6
|
+
* - SignedReceipt: Settlement proof binding offer to on-chain transaction
|
|
7
|
+
* - AcceptEntry: Terms an offer can match against
|
|
8
|
+
* - acceptIndex: Unsigned envelope field (hint only, not binding)
|
|
9
|
+
*
|
|
10
|
+
* Key design choices:
|
|
11
|
+
* - validUntil: epoch seconds in signed payload
|
|
12
|
+
* - version: in signed payload
|
|
13
|
+
* - acceptIndex: unsigned envelope field (outside signature)
|
|
14
|
+
* - metadata: deferred to v2
|
|
15
|
+
*
|
|
16
|
+
* NOTE: This adapter targets the x402 Offer/Receipt EXTENSION,
|
|
17
|
+
* NOT the baseline x402 header flow. The profile identifier reflects this:
|
|
18
|
+
* `peac-x402-offer-receipt/0.1` (extension) vs `peac-x402/0.1` (baseline, reserved).
|
|
19
|
+
*/
|
|
20
|
+
import type { JsonObject } from '@peac/kernel';
|
|
21
|
+
export type { Result, AdapterError, AdapterErrorCode, JsonObject } from '@peac/adapter-core';
|
|
22
|
+
/**
|
|
23
|
+
* Profile identifier for x402 Offer/Receipt extension records
|
|
24
|
+
*
|
|
25
|
+
* This profile targets the EXTENSION flow (signed offers + signed receipts),
|
|
26
|
+
* NOT the baseline x402 header flow (PAYMENT-REQUIRED, etc.).
|
|
27
|
+
*
|
|
28
|
+
* `peac-x402/0.1` is RESERVED for future baseline header flow support.
|
|
29
|
+
*/
|
|
30
|
+
export declare const X402_OFFER_RECEIPT_PROFILE: "peac-x402-offer-receipt/0.1";
|
|
31
|
+
/**
|
|
32
|
+
* Maximum number of accept entries allowed (DoS protection)
|
|
33
|
+
*
|
|
34
|
+
* Prevents CPU exhaustion from maliciously large accepts arrays.
|
|
35
|
+
* O(n) scan becomes O(128) worst case.
|
|
36
|
+
*/
|
|
37
|
+
export declare const MAX_ACCEPT_ENTRIES = 128;
|
|
38
|
+
/**
|
|
39
|
+
* Maximum total bytes for accepts array JSON (DoS protection)
|
|
40
|
+
*
|
|
41
|
+
* Prevents memory exhaustion from large accept payloads.
|
|
42
|
+
* 256 KiB is generous for legitimate use cases.
|
|
43
|
+
*/
|
|
44
|
+
export declare const MAX_TOTAL_ACCEPTS_BYTES: number;
|
|
45
|
+
/**
|
|
46
|
+
* Maximum length for amount string (prevents arbitrary-precision DoS)
|
|
47
|
+
*
|
|
48
|
+
* 78 chars supports uint256 (Ethereum's max) without truncation.
|
|
49
|
+
*/
|
|
50
|
+
export declare const MAX_AMOUNT_LENGTH = 78;
|
|
51
|
+
/**
|
|
52
|
+
* Signature format for x402 artifacts
|
|
53
|
+
*
|
|
54
|
+
* - eip712: EIP-712 typed structured data signature (Ethereum)
|
|
55
|
+
* - jws: JWS compact serialization (RFC 7515)
|
|
56
|
+
*/
|
|
57
|
+
export type SignatureFormat = 'eip712' | 'jws';
|
|
58
|
+
/**
|
|
59
|
+
* x402 Offer payload (inside the signed envelope)
|
|
60
|
+
*
|
|
61
|
+
* These fields are cryptographically bound by the signature.
|
|
62
|
+
* Any modification invalidates the signature.
|
|
63
|
+
*/
|
|
64
|
+
export interface OfferPayload {
|
|
65
|
+
/** Schema version (in signed payload) */
|
|
66
|
+
version: string;
|
|
67
|
+
/** Offer expiry as epoch seconds (in signed payload) */
|
|
68
|
+
validUntil: number;
|
|
69
|
+
/** CAIP-2 network identifier (e.g., "eip155:8453") */
|
|
70
|
+
network: string;
|
|
71
|
+
/** Payment asset identifier (e.g., "USDC", "ETH") */
|
|
72
|
+
asset: string;
|
|
73
|
+
/** Payment amount in minor units */
|
|
74
|
+
amount: string;
|
|
75
|
+
/** Payment recipient address */
|
|
76
|
+
payTo: string;
|
|
77
|
+
/** Settlement scheme (e.g., "exact", "flexible") */
|
|
78
|
+
scheme?: string;
|
|
79
|
+
/** Settlement parameters (scheme-specific) */
|
|
80
|
+
settlement?: JsonObject;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* x402 Signed Offer (envelope)
|
|
84
|
+
*
|
|
85
|
+
* The offer envelope contains:
|
|
86
|
+
* - payload: signed content (cryptographically bound)
|
|
87
|
+
* - signature: EIP-712 or JWS signature over the payload
|
|
88
|
+
* - format: which signature scheme was used
|
|
89
|
+
*/
|
|
90
|
+
export interface SignedOffer {
|
|
91
|
+
/** The signed payload */
|
|
92
|
+
payload: OfferPayload;
|
|
93
|
+
/** Signature over the payload */
|
|
94
|
+
signature: string;
|
|
95
|
+
/** Signature format */
|
|
96
|
+
format: SignatureFormat;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* x402 Receipt payload (inside the signed envelope)
|
|
100
|
+
*/
|
|
101
|
+
export interface ReceiptPayload {
|
|
102
|
+
/** Schema version */
|
|
103
|
+
version: string;
|
|
104
|
+
/** CAIP-2 network identifier */
|
|
105
|
+
network: string;
|
|
106
|
+
/** On-chain transaction hash */
|
|
107
|
+
txHash: string;
|
|
108
|
+
/** Payment asset */
|
|
109
|
+
asset?: string;
|
|
110
|
+
/** Payment amount in minor units */
|
|
111
|
+
amount?: string;
|
|
112
|
+
/** Payment recipient */
|
|
113
|
+
payTo?: string;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* x402 Signed Receipt (envelope)
|
|
117
|
+
*/
|
|
118
|
+
export interface SignedReceipt {
|
|
119
|
+
/** The signed payload */
|
|
120
|
+
payload: ReceiptPayload;
|
|
121
|
+
/** Signature over the payload */
|
|
122
|
+
signature: string;
|
|
123
|
+
/** Signature format */
|
|
124
|
+
format: SignatureFormat;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* A single accept entry: the terms under which a facilitator accepts payment
|
|
128
|
+
*
|
|
129
|
+
* These are the terms that offers are matched against during verification.
|
|
130
|
+
* Term-matching is the binding mechanism (not acceptIndex).
|
|
131
|
+
*/
|
|
132
|
+
export interface AcceptEntry {
|
|
133
|
+
/** CAIP-2 network identifier */
|
|
134
|
+
network: string;
|
|
135
|
+
/** Payment asset */
|
|
136
|
+
asset: string;
|
|
137
|
+
/** Payment recipient address */
|
|
138
|
+
payTo: string;
|
|
139
|
+
/** Maximum amount in minor units */
|
|
140
|
+
amount: string;
|
|
141
|
+
/** Settlement scheme */
|
|
142
|
+
scheme?: string;
|
|
143
|
+
/** Settlement parameters */
|
|
144
|
+
settlement?: JsonObject;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* x402 PaymentRequired response with offer/receipt extension
|
|
148
|
+
*
|
|
149
|
+
* This is the 402 response sent by the resource server.
|
|
150
|
+
* The extension data lives under extensions["offer-receipt"].
|
|
151
|
+
*/
|
|
152
|
+
export interface X402PaymentRequired {
|
|
153
|
+
/** List of acceptable payment terms */
|
|
154
|
+
accepts: AcceptEntry[];
|
|
155
|
+
/**
|
|
156
|
+
* Index into accepts[] that the offer targets.
|
|
157
|
+
*
|
|
158
|
+
* IMPORTANT: This field is OUTSIDE the signed payload (unsigned envelope).
|
|
159
|
+
* Verifiers MUST NOT rely on it as binding.
|
|
160
|
+
* Treat as advisory hint only; always verify via term-matching.
|
|
161
|
+
*/
|
|
162
|
+
acceptIndex?: number;
|
|
163
|
+
/** Signed offer */
|
|
164
|
+
offer: SignedOffer;
|
|
165
|
+
/** Resource URL being accessed */
|
|
166
|
+
resourceUrl?: string;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* x402 Settlement response with receipt extension
|
|
170
|
+
*/
|
|
171
|
+
export interface X402SettlementResponse {
|
|
172
|
+
/** Signed receipt proving settlement */
|
|
173
|
+
receipt: SignedReceipt;
|
|
174
|
+
/** Resource URL that was accessed */
|
|
175
|
+
resourceUrl?: string;
|
|
176
|
+
/** Reference back to the offer */
|
|
177
|
+
offerRef?: string;
|
|
178
|
+
/**
|
|
179
|
+
* Forward-compatibility: unknown extension fields from x402 evolution
|
|
180
|
+
*
|
|
181
|
+
* This allows the adapter to tolerate additions from upstream PRs
|
|
182
|
+
* (e.g., #1004 TXID, #1015 fee extensions) without breaking.
|
|
183
|
+
* Unknown fields are preserved in proofs but NOT copied to evidence.
|
|
184
|
+
*/
|
|
185
|
+
extensions?: Record<string, unknown>;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Result of offer verification
|
|
189
|
+
*/
|
|
190
|
+
export interface OfferVerification {
|
|
191
|
+
/** Whether the offer is valid */
|
|
192
|
+
valid: boolean;
|
|
193
|
+
/** The matched accept entry (if valid) */
|
|
194
|
+
matchedAccept?: AcceptEntry;
|
|
195
|
+
/** Index of the matched accept entry */
|
|
196
|
+
matchedIndex?: number;
|
|
197
|
+
/** Whether acceptIndex was used as hint (vs full scan) */
|
|
198
|
+
usedHint: boolean;
|
|
199
|
+
/** Verification errors (if invalid) */
|
|
200
|
+
errors: VerificationError[];
|
|
201
|
+
/**
|
|
202
|
+
* Term-matching details (always populated for deterministic output)
|
|
203
|
+
*
|
|
204
|
+
* This makes mismatchDetected first-class in the verification output,
|
|
205
|
+
* rather than requiring callers to pass it externally.
|
|
206
|
+
*
|
|
207
|
+
* All fields are required booleans for predictable downstream processing.
|
|
208
|
+
*/
|
|
209
|
+
termMatching: {
|
|
210
|
+
/** Method used: 'hint' (acceptIndex) or 'scan' (full array scan) */
|
|
211
|
+
method: 'hint' | 'scan';
|
|
212
|
+
/** Whether the acceptIndex hint was provided */
|
|
213
|
+
hintProvided: boolean;
|
|
214
|
+
/** Whether the hint pointed to a non-matching entry */
|
|
215
|
+
hintMismatchDetected: boolean;
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Result of receipt verification
|
|
220
|
+
*/
|
|
221
|
+
export interface ReceiptVerification {
|
|
222
|
+
/** Whether the receipt is valid */
|
|
223
|
+
valid: boolean;
|
|
224
|
+
/** Verification errors (if invalid) */
|
|
225
|
+
errors: VerificationError[];
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Structured verification error
|
|
229
|
+
*/
|
|
230
|
+
export interface VerificationError {
|
|
231
|
+
/** Error code (from X402ErrorCode) */
|
|
232
|
+
code: string;
|
|
233
|
+
/** Human-readable message */
|
|
234
|
+
message: string;
|
|
235
|
+
/** Field that caused the error */
|
|
236
|
+
field?: string;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Verification status metadata
|
|
240
|
+
*
|
|
241
|
+
* Records what verification was performed and how.
|
|
242
|
+
* CRITICAL: `valid: true` from verifyOffer/verifyReceipt does NOT imply
|
|
243
|
+
* cryptographic signature validity unless a crypto verifier was supplied.
|
|
244
|
+
*/
|
|
245
|
+
export interface VerificationStatus {
|
|
246
|
+
/** Structural validation always performed by this adapter */
|
|
247
|
+
structural: true;
|
|
248
|
+
/** Cryptographic signature verification status */
|
|
249
|
+
cryptographic: {
|
|
250
|
+
/** Whether crypto verification was performed */
|
|
251
|
+
verified: boolean;
|
|
252
|
+
/** Why crypto wasn't verified (if not verified) */
|
|
253
|
+
reason?: 'not_checked' | 'verifier_not_supplied' | 'verifier_failed';
|
|
254
|
+
/** Signature format */
|
|
255
|
+
format?: 'eip712' | 'jws';
|
|
256
|
+
/** Signer identity (if verified and available) */
|
|
257
|
+
signer?: string;
|
|
258
|
+
};
|
|
259
|
+
/** Term-matching verification status */
|
|
260
|
+
termMatching: {
|
|
261
|
+
/** Whether a matching accept entry was found */
|
|
262
|
+
matched: boolean;
|
|
263
|
+
/** Method used: 'hint' (acceptIndex) or 'scan' (full scan) */
|
|
264
|
+
method: 'hint' | 'scan';
|
|
265
|
+
/** Index of matched accept entry */
|
|
266
|
+
matchedIndex?: number;
|
|
267
|
+
/** Why term-matching wasn't performed (if matched is false and no verification was done) */
|
|
268
|
+
reason?: 'not_verified';
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* PEAC interaction record for an x402 Offer/Receipt extension flow
|
|
273
|
+
*
|
|
274
|
+
* This is the canonical record produced by mapping x402 proofs
|
|
275
|
+
* into the PEAC evidence layer.
|
|
276
|
+
*
|
|
277
|
+
* NOTE: This profile targets the x402 Offer/Receipt EXTENSION,
|
|
278
|
+
* NOT the baseline x402 header flow.
|
|
279
|
+
*/
|
|
280
|
+
export interface X402PeacRecord {
|
|
281
|
+
/** Record format version (extension profile, not baseline) */
|
|
282
|
+
version: typeof X402_OFFER_RECEIPT_PROFILE;
|
|
283
|
+
/** Raw x402 proofs (preserved for audit) */
|
|
284
|
+
proofs: {
|
|
285
|
+
x402: {
|
|
286
|
+
offer: SignedOffer;
|
|
287
|
+
receipt: SignedReceipt;
|
|
288
|
+
};
|
|
289
|
+
};
|
|
290
|
+
/** Normalized evidence fields (extracted from signed payloads) */
|
|
291
|
+
evidence: {
|
|
292
|
+
/** Offer expiry (epoch seconds, from signed payload) */
|
|
293
|
+
validUntil: number;
|
|
294
|
+
/** CAIP-2 network */
|
|
295
|
+
network: string;
|
|
296
|
+
/** Payment recipient (neutral naming; x402 calls this "payTo") */
|
|
297
|
+
payee: string;
|
|
298
|
+
/** Payment asset */
|
|
299
|
+
asset: string;
|
|
300
|
+
/** Payment amount in minor units */
|
|
301
|
+
amount: string;
|
|
302
|
+
/** On-chain transaction hash (from receipt) */
|
|
303
|
+
txHash: string;
|
|
304
|
+
/** Schema version (from offer) */
|
|
305
|
+
offerVersion: string;
|
|
306
|
+
/** Schema version (from receipt, if present) */
|
|
307
|
+
receiptVersion?: string;
|
|
308
|
+
};
|
|
309
|
+
/** Unsigned metadata and verification status */
|
|
310
|
+
hints: {
|
|
311
|
+
acceptIndex?: {
|
|
312
|
+
/** The acceptIndex value from the envelope */
|
|
313
|
+
value: number;
|
|
314
|
+
/** Always true -- acceptIndex is outside the signature */
|
|
315
|
+
untrusted: true;
|
|
316
|
+
/** True if acceptIndex pointed to a non-matching entry (when mismatchPolicy != 'fail') */
|
|
317
|
+
mismatchDetected?: boolean;
|
|
318
|
+
};
|
|
319
|
+
resourceUrl?: string;
|
|
320
|
+
/**
|
|
321
|
+
* Verification status metadata
|
|
322
|
+
*
|
|
323
|
+
* IMPORTANT: `valid: true` does NOT imply cryptographic signature validity
|
|
324
|
+
* unless verification.cryptographic.verified is true.
|
|
325
|
+
*/
|
|
326
|
+
verification?: VerificationStatus;
|
|
327
|
+
};
|
|
328
|
+
/** RFC 8785 JCS + SHA-256 digest of this record */
|
|
329
|
+
digest?: string;
|
|
330
|
+
/** ISO 8601 timestamp of record creation */
|
|
331
|
+
createdAt: string;
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Mismatch policy for acceptIndex hint verification
|
|
335
|
+
*
|
|
336
|
+
* Controls behavior when acceptIndex points to an entry that doesn't match
|
|
337
|
+
* the signed offer payload.
|
|
338
|
+
*
|
|
339
|
+
* - 'fail': Reject with accept_term_mismatch error (default, recommended)
|
|
340
|
+
* - 'warn_and_scan': Log warning, continue with scan, record in hints
|
|
341
|
+
* - 'ignore_and_scan': Skip hint check entirely, always scan
|
|
342
|
+
*/
|
|
343
|
+
export type MismatchPolicy = 'fail' | 'warn_and_scan' | 'ignore_and_scan';
|
|
344
|
+
/**
|
|
345
|
+
* Adapter configuration
|
|
346
|
+
*
|
|
347
|
+
* This adapter implements the PaymentProofAdapter interface from @peac/adapter-core.
|
|
348
|
+
* See docs/specs/X402-PROFILE.md for the normative specification.
|
|
349
|
+
*/
|
|
350
|
+
export interface X402AdapterConfig {
|
|
351
|
+
/** Supported offer versions (default: ["1"]) */
|
|
352
|
+
supportedVersions?: string[];
|
|
353
|
+
/** Clock skew tolerance in seconds for validUntil (default: 60) */
|
|
354
|
+
clockSkewSeconds?: number;
|
|
355
|
+
/** Current time override for testing (epoch seconds) */
|
|
356
|
+
nowSeconds?: number;
|
|
357
|
+
/**
|
|
358
|
+
* How to handle acceptIndex mismatch (default: "fail")
|
|
359
|
+
*
|
|
360
|
+
* When "warn_and_scan" or "ignore_and_scan", the adapter will:
|
|
361
|
+
* 1. Record the mismatch in hints.acceptIndex.mismatchDetected
|
|
362
|
+
* 2. Continue verification via full scan
|
|
363
|
+
* 3. Succeed if scan finds a unique match
|
|
364
|
+
*/
|
|
365
|
+
mismatchPolicy?: MismatchPolicy;
|
|
366
|
+
/**
|
|
367
|
+
* Maximum number of accept entries allowed (default: 128)
|
|
368
|
+
*
|
|
369
|
+
* DoS protection: prevents CPU exhaustion from large accepts arrays.
|
|
370
|
+
*/
|
|
371
|
+
maxAcceptEntries?: number;
|
|
372
|
+
/**
|
|
373
|
+
* Maximum total bytes for accepts array JSON (default: 256 KiB)
|
|
374
|
+
*
|
|
375
|
+
* DoS protection: prevents memory exhaustion from large payloads.
|
|
376
|
+
* Note: This requires caller to pass raw JSON size if available.
|
|
377
|
+
*/
|
|
378
|
+
maxTotalAcceptsBytes?: number;
|
|
379
|
+
/**
|
|
380
|
+
* Enable strict CAIP-2 network format validation (default: true)
|
|
381
|
+
*
|
|
382
|
+
* When enabled, validates network strings match CAIP-2 format (namespace:reference).
|
|
383
|
+
*/
|
|
384
|
+
strictNetworkValidation?: boolean;
|
|
385
|
+
/**
|
|
386
|
+
* Enable strict amount validation (default: true)
|
|
387
|
+
*
|
|
388
|
+
* When enabled, validates amount is a non-negative integer string.
|
|
389
|
+
*/
|
|
390
|
+
strictAmountValidation?: boolean;
|
|
391
|
+
}
|
|
392
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* x402 Offer/Receipt extension types
|
|
4
|
+
*
|
|
5
|
+
* Models the x402 offer/receipt flow:
|
|
6
|
+
* - SignedOffer: EIP-712 or JWS signed payment terms
|
|
7
|
+
* - SignedReceipt: Settlement proof binding offer to on-chain transaction
|
|
8
|
+
* - AcceptEntry: Terms an offer can match against
|
|
9
|
+
* - acceptIndex: Unsigned envelope field (hint only, not binding)
|
|
10
|
+
*
|
|
11
|
+
* Key design choices:
|
|
12
|
+
* - validUntil: epoch seconds in signed payload
|
|
13
|
+
* - version: in signed payload
|
|
14
|
+
* - acceptIndex: unsigned envelope field (outside signature)
|
|
15
|
+
* - metadata: deferred to v2
|
|
16
|
+
*
|
|
17
|
+
* NOTE: This adapter targets the x402 Offer/Receipt EXTENSION,
|
|
18
|
+
* NOT the baseline x402 header flow. The profile identifier reflects this:
|
|
19
|
+
* `peac-x402-offer-receipt/0.1` (extension) vs `peac-x402/0.1` (baseline, reserved).
|
|
20
|
+
*/
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
exports.MAX_AMOUNT_LENGTH = exports.MAX_TOTAL_ACCEPTS_BYTES = exports.MAX_ACCEPT_ENTRIES = exports.X402_OFFER_RECEIPT_PROFILE = void 0;
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
// Profile Identifier
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
/**
|
|
27
|
+
* Profile identifier for x402 Offer/Receipt extension records
|
|
28
|
+
*
|
|
29
|
+
* This profile targets the EXTENSION flow (signed offers + signed receipts),
|
|
30
|
+
* NOT the baseline x402 header flow (PAYMENT-REQUIRED, etc.).
|
|
31
|
+
*
|
|
32
|
+
* `peac-x402/0.1` is RESERVED for future baseline header flow support.
|
|
33
|
+
*/
|
|
34
|
+
exports.X402_OFFER_RECEIPT_PROFILE = 'peac-x402-offer-receipt/0.1';
|
|
35
|
+
// ---------------------------------------------------------------------------
|
|
36
|
+
// DoS Protection Limits
|
|
37
|
+
// ---------------------------------------------------------------------------
|
|
38
|
+
/**
|
|
39
|
+
* Maximum number of accept entries allowed (DoS protection)
|
|
40
|
+
*
|
|
41
|
+
* Prevents CPU exhaustion from maliciously large accepts arrays.
|
|
42
|
+
* O(n) scan becomes O(128) worst case.
|
|
43
|
+
*/
|
|
44
|
+
exports.MAX_ACCEPT_ENTRIES = 128;
|
|
45
|
+
/**
|
|
46
|
+
* Maximum total bytes for accepts array JSON (DoS protection)
|
|
47
|
+
*
|
|
48
|
+
* Prevents memory exhaustion from large accept payloads.
|
|
49
|
+
* 256 KiB is generous for legitimate use cases.
|
|
50
|
+
*/
|
|
51
|
+
exports.MAX_TOTAL_ACCEPTS_BYTES = 256 * 1024; // 256 KiB
|
|
52
|
+
/**
|
|
53
|
+
* Maximum length for amount string (prevents arbitrary-precision DoS)
|
|
54
|
+
*
|
|
55
|
+
* 78 chars supports uint256 (Ethereum's max) without truncation.
|
|
56
|
+
*/
|
|
57
|
+
exports.MAX_AMOUNT_LENGTH = 78;
|
|
58
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;GAkBG;;;AAOH,8EAA8E;AAC9E,qBAAqB;AACrB,8EAA8E;AAE9E;;;;;;;GAOG;AACU,QAAA,0BAA0B,GAAG,6BAAsC,CAAC;AAEjF,8EAA8E;AAC9E,wBAAwB;AACxB,8EAA8E;AAE9E;;;;;GAKG;AACU,QAAA,kBAAkB,GAAG,GAAG,CAAC;AAEtC;;;;;GAKG;AACU,QAAA,uBAAuB,GAAG,GAAG,GAAG,IAAI,CAAC,CAAC,UAAU;AAE7D;;;;GAIG;AACU,QAAA,iBAAiB,GAAG,EAAE,CAAC"}
|
package/dist/verify.d.ts
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* x402 Offer/Receipt verification
|
|
3
|
+
*
|
|
4
|
+
* Verification rules (PEAC-first):
|
|
5
|
+
* 1. Structural validation (format, required fields)
|
|
6
|
+
* 2. DoS guards (accepts array limits)
|
|
7
|
+
* 3. Amount validation (non-negative integer string)
|
|
8
|
+
* 4. Network validation (CAIP-2 format)
|
|
9
|
+
* 5. Expiry check (validUntil vs current time)
|
|
10
|
+
* 6. Version check (supported versions)
|
|
11
|
+
* 7. Signature format validation (EIP-712 or JWS structure)
|
|
12
|
+
* 8. Term-matching (offer payload vs accept entry)
|
|
13
|
+
*
|
|
14
|
+
* IMPORTANT: Cryptographic signature verification (EIP-712 recovery, JWS validation)
|
|
15
|
+
* is NOT performed here. That requires a crypto provider (viem, ethers, etc.)
|
|
16
|
+
* and should be done by the caller before passing artifacts to this adapter.
|
|
17
|
+
*
|
|
18
|
+
* `valid: true` does NOT imply cryptographic signature validity unless a
|
|
19
|
+
* CryptoVerifier is supplied and `verification.cryptographic.verified` is true.
|
|
20
|
+
*
|
|
21
|
+
* The focus of this module is TERM-MATCHING: ensuring the signed payload
|
|
22
|
+
* fields match the declared accept terms. This is the binding mechanism
|
|
23
|
+
* that makes unsigned acceptIndex irrelevant for security.
|
|
24
|
+
*/
|
|
25
|
+
import type { OfferPayload, SignedOffer, SignedReceipt, AcceptEntry, OfferVerification, ReceiptVerification, X402AdapterConfig } from './types.js';
|
|
26
|
+
/**
|
|
27
|
+
* Verify an x402 signed offer against accept terms
|
|
28
|
+
*
|
|
29
|
+
* This performs structural validation, expiry/version checks, and
|
|
30
|
+
* term-matching against the provided accept entries. It does NOT verify
|
|
31
|
+
* the cryptographic signature (that is the caller's responsibility).
|
|
32
|
+
*
|
|
33
|
+
* @param offer - The signed offer to verify
|
|
34
|
+
* @param accepts - The list of acceptable payment terms
|
|
35
|
+
* @param acceptIndex - Optional hint index (unsigned, treat as advisory)
|
|
36
|
+
* @param config - Optional adapter configuration
|
|
37
|
+
* @returns Verification result with matched accept entry or errors
|
|
38
|
+
*/
|
|
39
|
+
export declare function verifyOffer(offer: SignedOffer, accepts: AcceptEntry[], acceptIndex?: number, config?: X402AdapterConfig): OfferVerification;
|
|
40
|
+
/**
|
|
41
|
+
* Verify an x402 signed receipt
|
|
42
|
+
*
|
|
43
|
+
* Performs structural validation on the receipt. Does NOT verify
|
|
44
|
+
* the cryptographic signature.
|
|
45
|
+
*
|
|
46
|
+
* @param receipt - The signed receipt to verify
|
|
47
|
+
* @param config - Optional adapter configuration
|
|
48
|
+
* @returns Verification result with errors if invalid
|
|
49
|
+
*/
|
|
50
|
+
export declare function verifyReceipt(receipt: SignedReceipt, config?: X402AdapterConfig): ReceiptVerification;
|
|
51
|
+
/**
|
|
52
|
+
* Match offer payload fields against a single accept entry
|
|
53
|
+
*
|
|
54
|
+
* Compares: network, asset, payTo, amount, scheme, settlement
|
|
55
|
+
* All present fields must match exactly. Amount comparison is string-based
|
|
56
|
+
* (minor units) to avoid floating-point issues.
|
|
57
|
+
*
|
|
58
|
+
* @returns Array of mismatched field names (empty = match)
|
|
59
|
+
*/
|
|
60
|
+
export declare function matchAcceptTerms(payload: OfferPayload, accept: AcceptEntry): string[];
|
|
61
|
+
/**
|
|
62
|
+
* Select the matching accept entry from the list
|
|
63
|
+
*
|
|
64
|
+
* Selection logic:
|
|
65
|
+
* - If acceptIndex provided: bounds-check, then term-match that entry
|
|
66
|
+
* - If absent: scan all entries for a unique match
|
|
67
|
+
* - If multiple matches: fail closed (ambiguous)
|
|
68
|
+
* - If no matches: fail closed
|
|
69
|
+
*
|
|
70
|
+
* @param payload - Offer payload to match
|
|
71
|
+
* @param accepts - List of accept entries
|
|
72
|
+
* @param acceptIndex - Optional hint (unsigned, untrusted)
|
|
73
|
+
* @returns The matched entry and its index, or throws X402Error
|
|
74
|
+
*/
|
|
75
|
+
export declare function selectAccept(payload: OfferPayload, accepts: AcceptEntry[], acceptIndex?: number): {
|
|
76
|
+
entry: AcceptEntry;
|
|
77
|
+
index: number;
|
|
78
|
+
usedHint: boolean;
|
|
79
|
+
};
|
|
80
|
+
//# sourceMappingURL=verify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../src/verify.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAGH,OAAO,KAAK,EACV,YAAY,EACZ,WAAW,EACX,aAAa,EACb,WAAW,EACX,iBAAiB,EACjB,mBAAmB,EAEnB,iBAAiB,EAElB,MAAM,YAAY,CAAC;AA+PpB;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,WAAW,EAClB,OAAO,EAAE,WAAW,EAAE,EACtB,WAAW,CAAC,EAAE,MAAM,EACpB,MAAM,CAAC,EAAE,iBAAiB,GACzB,iBAAiB,CAuInB;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,aAAa,EACtB,MAAM,CAAC,EAAE,iBAAiB,GACzB,mBAAmB,CAgDrB;AAMD;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,WAAW,GAAG,MAAM,EAAE,CAwBrF;AAMD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,YAAY,EACrB,OAAO,EAAE,WAAW,EAAE,EACtB,WAAW,CAAC,EAAE,MAAM,GACnB;IAAE,KAAK,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CA4D1D"}
|