@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.
@@ -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"}
@@ -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"}