@peac/adapter-x402 0.12.0 → 0.12.2

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/raw.js ADDED
@@ -0,0 +1,246 @@
1
+ "use strict";
2
+ /**
3
+ * x402 raw wire types and extraction (Layer A)
4
+ *
5
+ * Exact mirror of upstream coinbase/x402 TypeScript types and field shapes
6
+ * after PR #935 (Offer/Receipt Extension) merged at commit f2bbb5c.
7
+ *
8
+ * This layer exists to:
9
+ * 1. Match upstream encoded wire shapes exactly (no renames, no approximations)
10
+ * 2. Provide extraction helpers for both JWS and EIP-712 formats
11
+ * 3. Serve as the single source of truth for wire-level types
12
+ *
13
+ * Upstream TypeScript keeps `validUntil` and `transaction` as always-present
14
+ * fields because EIP-712 requires fixed schemas. Unused values are encoded as
15
+ * `0` (validUntil) and `""` (transaction). This layer preserves that encoding;
16
+ * semantic normalization to `undefined` happens in Layer B (normalize.ts).
17
+ *
18
+ * IMPORTANT: Types in this file MUST match upstream exactly.
19
+ * Do NOT rename fields, add PEAC-specific fields, or change types.
20
+ */
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.X402_RECEIPT_HEADERS = exports.MAX_COMPACT_JWS_BYTES = exports.OFFER_RECEIPT = void 0;
23
+ exports.parseCompactJWS = parseCompactJWS;
24
+ exports.extractOfferPayload = extractOfferPayload;
25
+ exports.extractReceiptPayload = extractReceiptPayload;
26
+ exports.extractExtensionInfo = extractExtensionInfo;
27
+ exports.extractReceiptFromHeaders = extractReceiptFromHeaders;
28
+ const crypto_1 = require("@peac/crypto");
29
+ const errors_js_1 = require("./errors.js");
30
+ // ---------------------------------------------------------------------------
31
+ // Upstream Extension Constant
32
+ // ---------------------------------------------------------------------------
33
+ /**
34
+ * Upstream extension key for offer/receipt extension
35
+ *
36
+ * Matches upstream `OFFER_RECEIPT = "offer-receipt"`.
37
+ * Used in `extensions["offer-receipt"].info`.
38
+ */
39
+ exports.OFFER_RECEIPT = 'offer-receipt';
40
+ // ---------------------------------------------------------------------------
41
+ // JWS Parsing Contract (Hardened)
42
+ // ---------------------------------------------------------------------------
43
+ /**
44
+ * Default maximum compact JWS byte length (64 KB)
45
+ *
46
+ * Enforced BEFORE base64url decoding to prevent memory amplification.
47
+ */
48
+ exports.MAX_COMPACT_JWS_BYTES = 64 * 1024;
49
+ /**
50
+ * Parse a compact JWS string with hardened validation
51
+ *
52
+ * Contract:
53
+ * 1. Exactly 3 segments (split on `.`)
54
+ * 2. No padding characters (`=`) in any segment
55
+ * 3. Size limit enforced BEFORE decoding
56
+ * 4. Payload MUST be a plain JSON object (not array, primitive, or null)
57
+ * 5. Never reconstruct: the compact JWS is the signed artifact
58
+ * 6. Fail-closed on any anomaly
59
+ *
60
+ * @param compact - The compact JWS string
61
+ * @param maxBytes - Maximum byte length (default: MAX_COMPACT_JWS_BYTES)
62
+ * @returns Parsed components
63
+ * @throws X402Error with specific error code on any parsing failure
64
+ */
65
+ function parseCompactJWS(compact, maxBytes = exports.MAX_COMPACT_JWS_BYTES) {
66
+ // 1. Size limit before any processing
67
+ if (compact.length > maxBytes) {
68
+ throw new errors_js_1.X402Error('jws_too_large', `Compact JWS exceeds ${maxBytes} byte limit`);
69
+ }
70
+ // 2. Split into exactly 3 segments
71
+ const segments = compact.split('.');
72
+ if (segments.length !== 3) {
73
+ throw new errors_js_1.X402Error('jws_malformed', `Expected 3 segments in compact JWS, got ${segments.length}`);
74
+ }
75
+ // 3. Reject padded base64url (per RFC 7515, base64url has no padding)
76
+ for (const seg of segments) {
77
+ if (seg.includes('=')) {
78
+ throw new errors_js_1.X402Error('jws_padded_base64url', 'Padded base64url is not valid in compact JWS (RFC 7515)');
79
+ }
80
+ }
81
+ // 4. Decode header
82
+ let header;
83
+ try {
84
+ const headerJson = (0, crypto_1.base64urlDecodeString)(segments[0]);
85
+ header = JSON.parse(headerJson);
86
+ }
87
+ catch (e) {
88
+ throw new errors_js_1.X402Error('jws_malformed', `Failed to decode JWS header: ${e instanceof Error ? e.message : String(e)}`);
89
+ }
90
+ if (typeof header !== 'object' || header === null || Array.isArray(header)) {
91
+ throw new errors_js_1.X402Error('jws_malformed', 'JWS header must be a JSON object');
92
+ }
93
+ // 5. Decode payload
94
+ let payload;
95
+ try {
96
+ const payloadJson = (0, crypto_1.base64urlDecodeString)(segments[1]);
97
+ payload = JSON.parse(payloadJson);
98
+ }
99
+ catch (e) {
100
+ throw new errors_js_1.X402Error('jws_malformed', `Failed to decode JWS payload: ${e instanceof Error ? e.message : String(e)}`);
101
+ }
102
+ // 6. Payload must be a plain object (not array, primitive, or null)
103
+ if (typeof payload !== 'object' || payload === null || Array.isArray(payload)) {
104
+ throw new errors_js_1.X402Error('jws_payload_not_object', 'JWS payload must be a JSON object');
105
+ }
106
+ return {
107
+ header: header,
108
+ payload: payload,
109
+ signatureSegment: segments[2],
110
+ };
111
+ }
112
+ // ---------------------------------------------------------------------------
113
+ // Payload Extraction Helpers
114
+ // ---------------------------------------------------------------------------
115
+ /**
116
+ * Extract offer payload from a signed offer
117
+ *
118
+ * For EIP-712: returns the `payload` field directly.
119
+ * For JWS: decodes the compact JWS and returns the decoded payload.
120
+ *
121
+ * @param offer - The signed offer (discriminated union)
122
+ * @param maxJwsBytes - Maximum JWS byte length for JWS format
123
+ * @returns The raw offer payload
124
+ * @throws X402Error if extraction fails
125
+ */
126
+ function extractOfferPayload(offer, maxJwsBytes) {
127
+ if (offer.format === 'eip712') {
128
+ return offer.payload;
129
+ }
130
+ // JWS format: decode from compact serialization
131
+ const parsed = parseCompactJWS(offer.signature, maxJwsBytes);
132
+ return parsed.payload;
133
+ }
134
+ /**
135
+ * Extract receipt payload from a signed receipt
136
+ *
137
+ * For EIP-712: returns the `payload` field directly.
138
+ * For JWS: decodes the compact JWS and returns the decoded payload.
139
+ *
140
+ * @param receipt - The signed receipt (discriminated union)
141
+ * @param maxJwsBytes - Maximum JWS byte length for JWS format
142
+ * @returns The raw receipt payload
143
+ * @throws X402Error if extraction fails
144
+ */
145
+ function extractReceiptPayload(receipt, maxJwsBytes) {
146
+ if (receipt.format === 'eip712') {
147
+ return receipt.payload;
148
+ }
149
+ // JWS format: decode from compact serialization
150
+ const parsed = parseCompactJWS(receipt.signature, maxJwsBytes);
151
+ return parsed.payload;
152
+ }
153
+ /**
154
+ * Extract x402 extension info from an upstream response body
155
+ *
156
+ * Equivalent to upstream's `extractOffersFromPaymentRequired()` but operates
157
+ * on the raw response body rather than the upstream `PaymentRequired` type.
158
+ * Looks for `extensions["offer-receipt"].info` in the body.
159
+ *
160
+ * This is the entry point for converting raw upstream wire data into
161
+ * PEAC's `X402OfferReceiptChallenge` convenience type.
162
+ *
163
+ * @param body - The upstream response body (unknown shape)
164
+ * @returns The extension info, or null if absent/malformed
165
+ */
166
+ function extractExtensionInfo(body) {
167
+ if (typeof body !== 'object' || body === null || Array.isArray(body)) {
168
+ return null;
169
+ }
170
+ const typed = body;
171
+ const extensions = typed.extensions;
172
+ if (typeof extensions !== 'object' || extensions === null || Array.isArray(extensions)) {
173
+ return null;
174
+ }
175
+ const ext = extensions;
176
+ const offerReceipt = ext['offer-receipt'];
177
+ if (typeof offerReceipt !== 'object' || offerReceipt === null || Array.isArray(offerReceipt)) {
178
+ return null;
179
+ }
180
+ const orTyped = offerReceipt;
181
+ const info = orTyped.info;
182
+ if (typeof info !== 'object' || info === null || Array.isArray(info)) {
183
+ return null;
184
+ }
185
+ const infoTyped = info;
186
+ // Validate offers is an array
187
+ if (!Array.isArray(infoTyped.offers)) {
188
+ return null;
189
+ }
190
+ return {
191
+ offers: infoTyped.offers,
192
+ ...(infoTyped.receipt !== undefined && {
193
+ receipt: infoTyped.receipt,
194
+ }),
195
+ };
196
+ }
197
+ // ---------------------------------------------------------------------------
198
+ // Upstream Message Shape Extractors
199
+ // ---------------------------------------------------------------------------
200
+ /**
201
+ * Standard x402 response header names for payment receipts
202
+ *
203
+ * Upstream uses `X-PAYMENT-RESPONSE` (primary) and `PAYMENT-RESPONSE` (alias).
204
+ */
205
+ exports.X402_RECEIPT_HEADERS = ['x-payment-response', 'payment-response'];
206
+ /**
207
+ * Extract signed receipt from x402 settlement response headers
208
+ *
209
+ * Equivalent to upstream's `extractReceiptFromResponse()` but operates
210
+ * on raw headers rather than a `Response` object. Upstream sends the
211
+ * signed receipt as JSON in `X-PAYMENT-RESPONSE` or `PAYMENT-RESPONSE`.
212
+ *
213
+ * @param headers - Response headers (case-insensitive lookup)
214
+ * @returns The signed receipt, or null if absent/malformed
215
+ */
216
+ function extractReceiptFromHeaders(headers) {
217
+ // Case-insensitive header lookup
218
+ const lowerHeaders = {};
219
+ for (const [key, value] of Object.entries(headers)) {
220
+ if (value !== undefined) {
221
+ lowerHeaders[key.toLowerCase()] = Array.isArray(value) ? value[0] : value;
222
+ }
223
+ }
224
+ let raw;
225
+ for (const name of exports.X402_RECEIPT_HEADERS) {
226
+ raw = lowerHeaders[name];
227
+ if (raw)
228
+ break;
229
+ }
230
+ if (!raw)
231
+ return null;
232
+ try {
233
+ const parsed = JSON.parse(raw);
234
+ if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed))
235
+ return null;
236
+ if (parsed.format !== 'eip712' && parsed.format !== 'jws')
237
+ return null;
238
+ if (typeof parsed.signature !== 'string')
239
+ return null;
240
+ return parsed;
241
+ }
242
+ catch {
243
+ return null;
244
+ }
245
+ }
246
+ //# sourceMappingURL=raw.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"raw.js","sourceRoot":"","sources":["../src/raw.ts"],"names":[],"mappings":"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"}