@wtflabs/x402-server 0.0.1-beta.6 → 0.0.1-beta.9

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,558 @@
1
+ // src/server.ts
2
+ import { TokenDetector } from "@wtflabs/x402-detector";
3
+
4
+ // src/schemas.ts
5
+ import { z } from "zod";
6
+ var EthAddressRegex = /^0x[a-fA-F0-9]{40}$/;
7
+ var isIntegerString = (value) => {
8
+ const num = Number(value);
9
+ return Number.isInteger(num) && num >= 0;
10
+ };
11
+ var CreateRequirementsConfigSchema = z.object({
12
+ // 必填
13
+ token: z.string().regex(EthAddressRegex, "Invalid token address"),
14
+ amount: z.string().refine(isIntegerString, "Amount must be a non-negative integer string"),
15
+ // 可选 - 网络和 scheme
16
+ network: z.string().optional(),
17
+ scheme: z.string().optional(),
18
+ // 可选 - 支付类型
19
+ paymentType: z.enum(["permit", "eip3009", "permit2", "auto"]).optional(),
20
+ // 可选 - 资源描述
21
+ resource: z.string().url().optional().or(z.literal("")),
22
+ description: z.string().optional(),
23
+ mimeType: z.string().optional(),
24
+ timeout: z.number().int().positive().optional(),
25
+ // 可选 - 性能控制
26
+ autoDetect: z.boolean().optional()
27
+ });
28
+ var PaymentRequirementsSchema = z.object({
29
+ x402Version: z.literal(1),
30
+ scheme: z.string(),
31
+ network: z.string(),
32
+ maxAmountRequired: z.string().refine(isIntegerString),
33
+ payTo: z.string().regex(EthAddressRegex),
34
+ asset: z.string().regex(EthAddressRegex),
35
+ maxTimeoutSeconds: z.number().int().positive(),
36
+ resource: z.string(),
37
+ description: z.string(),
38
+ mimeType: z.string(),
39
+ paymentType: z.enum(["permit", "eip3009", "permit2"]).optional(),
40
+ extra: z.object({
41
+ relayer: z.string().regex(EthAddressRegex).optional(),
42
+ name: z.string().optional(),
43
+ version: z.string().optional()
44
+ }).passthrough().optional()
45
+ });
46
+ var PaymentPayloadSchema = z.object({
47
+ x402Version: z.number(),
48
+ scheme: z.string(),
49
+ network: z.string(),
50
+ payload: z.any()
51
+ });
52
+ var Response402Schema = z.object({
53
+ x402Version: z.literal(1),
54
+ accepts: z.array(PaymentRequirementsSchema),
55
+ error: z.string().optional()
56
+ });
57
+ var InitResultSchema = z.discriminatedUnion("success", [
58
+ z.object({ success: z.literal(true) }),
59
+ z.object({ success: z.literal(false), error: z.string() })
60
+ ]);
61
+ var ProcessResultSchema = z.discriminatedUnion("success", [
62
+ z.object({
63
+ success: z.literal(true),
64
+ status: z.literal(200),
65
+ data: z.object({
66
+ payer: z.string().regex(EthAddressRegex),
67
+ txHash: z.string()
68
+ })
69
+ }),
70
+ z.object({
71
+ success: z.literal(false),
72
+ status: z.literal(402),
73
+ response: Response402Schema
74
+ })
75
+ ]);
76
+ var ParsedPaymentSchema = z.object({
77
+ payload: PaymentPayloadSchema,
78
+ requirements: PaymentRequirementsSchema
79
+ });
80
+ var ParseResultSchema = z.discriminatedUnion("success", [
81
+ z.object({ success: z.literal(true), data: ParsedPaymentSchema }),
82
+ z.object({ success: z.literal(false), response402: Response402Schema })
83
+ ]);
84
+ var VerifyResultSchema = z.discriminatedUnion("success", [
85
+ z.object({ success: z.literal(true), payer: z.string().regex(EthAddressRegex) }),
86
+ z.object({ success: z.literal(false), error: z.string() })
87
+ ]);
88
+ var SettleResultSchema = z.discriminatedUnion("success", [
89
+ z.object({
90
+ success: z.literal(true),
91
+ txHash: z.string(),
92
+ network: z.string()
93
+ }),
94
+ z.object({
95
+ success: z.literal(false),
96
+ error: z.string()
97
+ })
98
+ ]);
99
+
100
+ // src/utils.ts
101
+ function decodeBase64(base64) {
102
+ const cleanBase64 = base64.replace(/^data:application\/json;base64,/, "");
103
+ if (typeof window !== "undefined" && window.atob) {
104
+ return window.atob(cleanBase64);
105
+ }
106
+ if (typeof Buffer !== "undefined") {
107
+ return Buffer.from(cleanBase64, "base64").toString("utf-8");
108
+ }
109
+ throw new Error("No Base64 decoder available");
110
+ }
111
+ function encodeBase64(str) {
112
+ if (typeof window !== "undefined" && window.btoa) {
113
+ return window.btoa(str);
114
+ }
115
+ if (typeof Buffer !== "undefined") {
116
+ return Buffer.from(str, "utf-8").toString("base64");
117
+ }
118
+ throw new Error("No Base64 encoder available");
119
+ }
120
+
121
+ // src/server.ts
122
+ var X402Server = class {
123
+ /**
124
+ * 构造函数
125
+ *
126
+ * @param config - Server 配置
127
+ */
128
+ constructor(config) {
129
+ this.network = null;
130
+ if (!config.client) {
131
+ throw new Error("client is required");
132
+ }
133
+ if (!config.facilitator) {
134
+ throw new Error("facilitator is required");
135
+ }
136
+ this.client = config.client;
137
+ this.facilitator = config.facilitator;
138
+ this.detector = new TokenDetector(config.client, { logger: null });
139
+ this.network = config.network || null;
140
+ }
141
+ /**
142
+ * 可选的初始化 - 预热缓存
143
+ *
144
+ * @param tokens - 要预热的 token 地址列表
145
+ * @returns 初始化结果
146
+ */
147
+ async initialize(tokens) {
148
+ try {
149
+ await this.detector.initialize(tokens);
150
+ return { success: true };
151
+ } catch (error) {
152
+ return {
153
+ success: false,
154
+ error: error instanceof Error ? error.message : "Initialization failed"
155
+ };
156
+ }
157
+ }
158
+ /**
159
+ * 创建支付要求
160
+ *
161
+ * @param config - 配置选项
162
+ * @returns 支付要求
163
+ */
164
+ async createRequirements(config) {
165
+ const validatedConfig = CreateRequirementsConfigSchema.parse(config);
166
+ const network = validatedConfig.network || this.network || await this.getNetworkName();
167
+ let paymentType;
168
+ let tokenName;
169
+ let tokenVersion;
170
+ if (validatedConfig.autoDetect !== false) {
171
+ const result = await this.detector.detect(validatedConfig.token);
172
+ if (validatedConfig.paymentType && validatedConfig.paymentType !== "auto") {
173
+ paymentType = validatedConfig.paymentType;
174
+ } else {
175
+ const recommendedMethod = await this.detector.getRecommendedMethod(validatedConfig.token);
176
+ if (!recommendedMethod) {
177
+ throw new Error(
178
+ `Token ${validatedConfig.token} does not support advanced payment methods`
179
+ );
180
+ }
181
+ paymentType = recommendedMethod;
182
+ }
183
+ tokenName = result.name;
184
+ tokenVersion = result.version;
185
+ } else {
186
+ if (!validatedConfig.paymentType || validatedConfig.paymentType === "auto") {
187
+ throw new Error("Must specify paymentType when autoDetect is false");
188
+ }
189
+ paymentType = validatedConfig.paymentType;
190
+ }
191
+ const requirements = {
192
+ x402Version: 1,
193
+ scheme: validatedConfig.scheme || "exact",
194
+ network,
195
+ maxAmountRequired: validatedConfig.amount,
196
+ payTo: this.facilitator.recipientAddress,
197
+ asset: validatedConfig.token,
198
+ maxTimeoutSeconds: validatedConfig.timeout || 300,
199
+ resource: validatedConfig.resource || "",
200
+ description: validatedConfig.description || "",
201
+ mimeType: validatedConfig.mimeType || "application/json",
202
+ paymentType,
203
+ extra: {
204
+ relayer: this.facilitator.relayer,
205
+ ...tokenName && { name: tokenName },
206
+ ...tokenVersion && { version: tokenVersion }
207
+ }
208
+ };
209
+ return PaymentRequirementsSchema.parse(requirements);
210
+ }
211
+ /**
212
+ * 完整的支付处理流程
213
+ * parse → verify → settle 一步到位
214
+ *
215
+ * @param paymentHeader - X-PAYMENT header 的值 (Base64)
216
+ * @param expectedRequirements - 期望的支付要求
217
+ * @returns 处理结果
218
+ */
219
+ async process(paymentHeader, expectedRequirements) {
220
+ const parsed = this.parse(paymentHeader, expectedRequirements);
221
+ if (!parsed.success) {
222
+ return {
223
+ success: false,
224
+ status: 402,
225
+ response: parsed.response402
226
+ };
227
+ }
228
+ const verified = await this.verify(parsed.data);
229
+ if (!verified.success) {
230
+ return {
231
+ success: false,
232
+ status: 402,
233
+ response: this.get402Response(expectedRequirements, verified.error)
234
+ };
235
+ }
236
+ const settled = await this.settle(parsed.data);
237
+ if (!settled.success) {
238
+ return {
239
+ success: false,
240
+ status: 402,
241
+ response: this.get402Response(expectedRequirements, settled.error)
242
+ };
243
+ }
244
+ return {
245
+ success: true,
246
+ status: 200,
247
+ data: {
248
+ payer: verified.payer,
249
+ txHash: settled.txHash
250
+ }
251
+ };
252
+ }
253
+ /**
254
+ * 解析支付头
255
+ *
256
+ * @param paymentHeader - X-PAYMENT header 的值
257
+ * @param expectedRequirements - 期望的支付要求
258
+ * @returns 解析结果
259
+ */
260
+ parse(paymentHeader, expectedRequirements) {
261
+ if (!paymentHeader) {
262
+ return {
263
+ success: false,
264
+ response402: this.get402Response(expectedRequirements, "missing_payment_header")
265
+ };
266
+ }
267
+ let payload;
268
+ try {
269
+ const decoded = decodeBase64(paymentHeader);
270
+ const parsed = JSON.parse(decoded);
271
+ payload = PaymentPayloadSchema.parse(parsed);
272
+ } catch (error) {
273
+ return {
274
+ success: false,
275
+ response402: this.get402Response(
276
+ expectedRequirements,
277
+ error instanceof Error ? `invalid_payment_header: ${error.message}` : "invalid_payment_header"
278
+ )
279
+ };
280
+ }
281
+ return {
282
+ success: true,
283
+ data: {
284
+ payload,
285
+ requirements: expectedRequirements
286
+ }
287
+ };
288
+ }
289
+ /**
290
+ * 验证支付签名
291
+ *
292
+ * @param parsed - 解析后的支付数据
293
+ * @returns 验证结果
294
+ */
295
+ async verify(parsed) {
296
+ try {
297
+ const facilitatorPayload = {
298
+ ...parsed.payload,
299
+ payload: parsed.payload.payload || {}
300
+ };
301
+ const result = await this.facilitator.verify(
302
+ facilitatorPayload,
303
+ parsed.requirements
304
+ );
305
+ if (!result.success) {
306
+ return {
307
+ success: false,
308
+ error: result.error || result.errorMessage || "Verification failed"
309
+ };
310
+ }
311
+ if (!result.payer) {
312
+ return {
313
+ success: false,
314
+ error: "Payer address not found in verification result"
315
+ };
316
+ }
317
+ return {
318
+ success: true,
319
+ payer: result.payer
320
+ };
321
+ } catch (error) {
322
+ return {
323
+ success: false,
324
+ error: error instanceof Error ? error.message : "Verification error"
325
+ };
326
+ }
327
+ }
328
+ /**
329
+ * 结算支付
330
+ *
331
+ * @param parsed - 解析后的支付数据
332
+ * @returns 结算结果
333
+ */
334
+ async settle(parsed) {
335
+ try {
336
+ const facilitatorPayload = {
337
+ ...parsed.payload,
338
+ payload: parsed.payload.payload || {}
339
+ };
340
+ const result = await this.facilitator.settle(
341
+ facilitatorPayload,
342
+ parsed.requirements
343
+ );
344
+ if (!result.success) {
345
+ return {
346
+ success: false,
347
+ error: result.error || result.errorMessage || "Settlement failed"
348
+ };
349
+ }
350
+ if (!result.transaction) {
351
+ return {
352
+ success: false,
353
+ error: "Transaction hash not found in settlement result"
354
+ };
355
+ }
356
+ return {
357
+ success: true,
358
+ txHash: result.transaction,
359
+ network: result.network || parsed.requirements.network
360
+ };
361
+ } catch (error) {
362
+ return {
363
+ success: false,
364
+ error: error instanceof Error ? error.message : "Settlement error"
365
+ };
366
+ }
367
+ }
368
+ /**
369
+ * 生成 402 响应
370
+ *
371
+ * @param requirements - 支付要求
372
+ * @param error - 可选的错误信息
373
+ * @returns 402 响应对象
374
+ */
375
+ get402Response(requirements, error) {
376
+ return {
377
+ x402Version: 1,
378
+ accepts: [requirements],
379
+ error
380
+ };
381
+ }
382
+ /**
383
+ * 清除缓存
384
+ *
385
+ * @param token - 可选,指定要清除的 token 地址
386
+ */
387
+ async clearCache(token) {
388
+ await this.detector.clearCache(token);
389
+ }
390
+ /**
391
+ * 获取缓存统计
392
+ *
393
+ * @returns 缓存统计信息
394
+ */
395
+ getCacheStats() {
396
+ return this.detector.getCacheStats();
397
+ }
398
+ /**
399
+ * 获取 facilitator 实例(供外部访问)
400
+ *
401
+ * @returns Facilitator 实例
402
+ */
403
+ getFacilitator() {
404
+ return this.facilitator;
405
+ }
406
+ /**
407
+ * 获取 detector 实例(供外部访问)
408
+ *
409
+ * @returns TokenDetector 实例
410
+ */
411
+ getDetector() {
412
+ return this.detector;
413
+ }
414
+ /**
415
+ * 获取 client 实例(供外部访问)
416
+ *
417
+ * @returns PublicClient 实例
418
+ */
419
+ getClient() {
420
+ return this.client;
421
+ }
422
+ /**
423
+ * 获取网络名称
424
+ *
425
+ * @returns 网络名称
426
+ */
427
+ async getNetworkName() {
428
+ if (this.network) {
429
+ return this.network;
430
+ }
431
+ const chainId = await this.client.getChainId();
432
+ const networkMap = {
433
+ 1: "ethereum-mainnet",
434
+ 5: "ethereum-goerli",
435
+ 11155111: "ethereum-sepolia",
436
+ 56: "bsc-mainnet",
437
+ 97: "bsc-testnet",
438
+ 137: "polygon-mainnet",
439
+ 80001: "polygon-mumbai",
440
+ 42161: "arbitrum-mainnet",
441
+ 421613: "arbitrum-goerli",
442
+ 10: "optimism-mainnet",
443
+ 420: "optimism-goerli",
444
+ 8453: "base-mainnet",
445
+ 84531: "base-goerli"
446
+ };
447
+ this.network = networkMap[chainId] || `chain-${chainId}`;
448
+ return this.network;
449
+ }
450
+ };
451
+
452
+ // src/middlewares/express.ts
453
+ function createExpressMiddleware(options) {
454
+ return async (req, res, next) => {
455
+ try {
456
+ const token = await options.getToken(req);
457
+ const amount = await options.getAmount(req);
458
+ const extraConfig = options.getConfig ? await options.getConfig(req) : {};
459
+ const requirements = await options.server.createRequirements({
460
+ token,
461
+ amount,
462
+ ...extraConfig
463
+ });
464
+ const paymentHeader = req.headers["x-payment"];
465
+ const result = await options.server.process(paymentHeader, requirements);
466
+ if (!result.success) {
467
+ if (options.on402) {
468
+ options.on402(req, res, result.response);
469
+ } else {
470
+ res.status(402).json(result.response);
471
+ }
472
+ return;
473
+ }
474
+ req.x402 = {
475
+ payer: result.data.payer,
476
+ txHash: result.data.txHash
477
+ };
478
+ if (options.onPaymentSuccess) {
479
+ await options.onPaymentSuccess(req, result.data.payer, result.data.txHash);
480
+ }
481
+ next();
482
+ } catch (error) {
483
+ if (options.onError) {
484
+ options.onError(error, req, res);
485
+ } else {
486
+ console.error("x402 middleware error:", error);
487
+ res.status(500).json({
488
+ error: "Payment processing error",
489
+ message: error instanceof Error ? error.message : "Unknown error"
490
+ });
491
+ }
492
+ }
493
+ };
494
+ }
495
+
496
+ // src/middlewares/hono.ts
497
+ function createHonoMiddleware(options) {
498
+ return async (c, next) => {
499
+ try {
500
+ const token = await options.getToken(c);
501
+ const amount = await options.getAmount(c);
502
+ const extraConfig = options.getConfig ? await options.getConfig(c) : {};
503
+ const requirements = await options.server.createRequirements({
504
+ token,
505
+ amount,
506
+ ...extraConfig
507
+ });
508
+ const paymentHeader = c.req.header("x-payment");
509
+ const result = await options.server.process(paymentHeader, requirements);
510
+ if (!result.success) {
511
+ if (options.on402) {
512
+ return options.on402(c, result.response);
513
+ } else {
514
+ return c.json(result.response, 402);
515
+ }
516
+ }
517
+ c.set("x402", {
518
+ payer: result.data.payer,
519
+ txHash: result.data.txHash
520
+ });
521
+ if (options.onPaymentSuccess) {
522
+ await options.onPaymentSuccess(c, result.data.payer, result.data.txHash);
523
+ }
524
+ await next();
525
+ } catch (error) {
526
+ if (options.onError) {
527
+ return options.onError(error, c);
528
+ } else {
529
+ console.error("x402 middleware error:", error);
530
+ return c.json(
531
+ {
532
+ error: "Payment processing error",
533
+ message: error instanceof Error ? error.message : "Unknown error"
534
+ },
535
+ 500
536
+ );
537
+ }
538
+ }
539
+ };
540
+ }
541
+ export {
542
+ CreateRequirementsConfigSchema,
543
+ InitResultSchema,
544
+ ParseResultSchema,
545
+ ParsedPaymentSchema,
546
+ PaymentPayloadSchema,
547
+ PaymentRequirementsSchema,
548
+ ProcessResultSchema,
549
+ Response402Schema,
550
+ SettleResultSchema,
551
+ VerifyResultSchema,
552
+ X402Server,
553
+ createExpressMiddleware,
554
+ createHonoMiddleware,
555
+ decodeBase64,
556
+ encodeBase64
557
+ };
558
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/server.ts","../../src/schemas.ts","../../src/utils.ts","../../src/middlewares/express.ts","../../src/middlewares/hono.ts"],"sourcesContent":["import type { PublicClient } from \"viem\";\nimport { TokenDetector } from \"@wtflabs/x402-detector\";\nimport { Facilitator } from \"@wtflabs/x402-facilitator\";\nimport type {\n X402ServerConfig,\n PaymentRequirements,\n PaymentPayload,\n Response402,\n InitResult,\n ProcessResult,\n ParseResult,\n VerifyResult,\n SettleResult,\n ParsedPayment,\n} from \"./types\";\nimport {\n CreateRequirementsConfigSchema,\n PaymentRequirementsSchema,\n PaymentPayloadSchema,\n} from \"./schemas\";\nimport type { CreateRequirementsConfig } from \"./schemas\";\nimport { decodeBase64 } from \"./utils\";\n\n/**\n * X402 Server\n *\n * 服务端 SDK,用于处理支付验证和结算\n *\n * @example\n * ```typescript\n * // 1. 创建 facilitator\n * const facilitator = new Facilitator({\n * recipientAddress: \"0x1234...\",\n * waitUntil: \"confirmed\",\n * });\n *\n * // 2. 创建 server\n * const server = new X402Server({\n * client: viemClient,\n * facilitator,\n * });\n *\n * // 3. 可选:预热缓存\n * await server.initialize([tokenAddress]);\n *\n * // 4. 创建支付要求\n * const requirements = await server.createRequirements({\n * token: tokenAddress,\n * amount: \"1000\",\n * });\n *\n * // 5. 处理支付\n * const result = await server.process(paymentHeader, requirements);\n * ```\n */\nexport class X402Server {\n private client: PublicClient;\n private detector: TokenDetector;\n private facilitator: Facilitator;\n private network: string | null = null;\n\n /**\n * 构造函数\n *\n * @param config - Server 配置\n */\n constructor(config: X402ServerConfig) {\n if (!config.client) {\n throw new Error(\"client is required\");\n }\n if (!config.facilitator) {\n throw new Error(\"facilitator is required\");\n }\n\n this.client = config.client;\n this.facilitator = config.facilitator;\n\n // 初始化 detector (禁用日志)\n this.detector = new TokenDetector(config.client, { logger: null });\n\n // 保存网络配置\n this.network = config.network || null;\n }\n\n /**\n * 可选的初始化 - 预热缓存\n *\n * @param tokens - 要预热的 token 地址列表\n * @returns 初始化结果\n */\n async initialize(tokens: string[]): Promise<InitResult> {\n try {\n await this.detector.initialize(tokens);\n return { success: true };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : \"Initialization failed\",\n };\n }\n }\n\n /**\n * 创建支付要求\n *\n * @param config - 配置选项\n * @returns 支付要求\n */\n async createRequirements(config: CreateRequirementsConfig): Promise<PaymentRequirements> {\n // 使用 Zod 验证输入参数\n const validatedConfig = CreateRequirementsConfigSchema.parse(config);\n\n // 获取网络名称\n const network = validatedConfig.network || this.network || (await this.getNetworkName());\n\n // 确定支付类型和 token 信息\n let paymentType: \"permit\" | \"eip3009\" | \"permit2\" | undefined;\n let tokenName: string | undefined;\n let tokenVersion: string | undefined;\n\n if (validatedConfig.autoDetect !== false) {\n // 自动检测模式(默认)\n const result = await this.detector.detect(validatedConfig.token);\n\n // 确定支付类型\n if (validatedConfig.paymentType && validatedConfig.paymentType !== \"auto\") {\n paymentType = validatedConfig.paymentType;\n } else {\n const recommendedMethod = await this.detector.getRecommendedMethod(validatedConfig.token);\n if (!recommendedMethod) {\n throw new Error(\n `Token ${validatedConfig.token} does not support advanced payment methods`,\n );\n }\n paymentType = recommendedMethod;\n }\n\n tokenName = result.name;\n tokenVersion = result.version;\n } else {\n // 快速模式,跳过检测\n if (!validatedConfig.paymentType || validatedConfig.paymentType === \"auto\") {\n throw new Error(\"Must specify paymentType when autoDetect is false\");\n }\n paymentType = validatedConfig.paymentType;\n }\n\n // 构建支付要求(未验证的对象)\n const requirements = {\n x402Version: 1 as const,\n scheme: validatedConfig.scheme || \"exact\",\n network,\n maxAmountRequired: validatedConfig.amount,\n payTo: this.facilitator.recipientAddress,\n asset: validatedConfig.token,\n maxTimeoutSeconds: validatedConfig.timeout || 300,\n resource: validatedConfig.resource || \"\",\n description: validatedConfig.description || \"\",\n mimeType: validatedConfig.mimeType || \"application/json\",\n paymentType,\n extra: {\n relayer: this.facilitator.relayer,\n ...(tokenName && { name: tokenName }),\n ...(tokenVersion && { version: tokenVersion }),\n },\n };\n\n // 使用 Zod 验证输出\n return PaymentRequirementsSchema.parse(requirements);\n }\n\n /**\n * 完整的支付处理流程\n * parse → verify → settle 一步到位\n *\n * @param paymentHeader - X-PAYMENT header 的值 (Base64)\n * @param expectedRequirements - 期望的支付要求\n * @returns 处理结果\n */\n async process(\n paymentHeader: string | undefined,\n expectedRequirements: PaymentRequirements,\n ): Promise<ProcessResult> {\n // 1. 解析\n const parsed = this.parse(paymentHeader, expectedRequirements);\n if (!parsed.success) {\n return {\n success: false,\n status: 402,\n response: parsed.response402,\n };\n }\n\n // 2. 验证\n const verified = await this.verify(parsed.data);\n if (!verified.success) {\n return {\n success: false,\n status: 402,\n response: this.get402Response(expectedRequirements, verified.error),\n };\n }\n\n // 3. 结算\n const settled = await this.settle(parsed.data);\n if (!settled.success) {\n return {\n success: false,\n status: 402,\n response: this.get402Response(expectedRequirements, settled.error),\n };\n }\n\n return {\n success: true,\n status: 200,\n data: {\n payer: verified.payer,\n txHash: settled.txHash,\n },\n };\n }\n\n /**\n * 解析支付头\n *\n * @param paymentHeader - X-PAYMENT header 的值\n * @param expectedRequirements - 期望的支付要求\n * @returns 解析结果\n */\n parse(paymentHeader: string | undefined, expectedRequirements: PaymentRequirements): ParseResult {\n // 检查是否提供了支付头\n if (!paymentHeader) {\n return {\n success: false,\n response402: this.get402Response(expectedRequirements, \"missing_payment_header\"),\n };\n }\n\n // 解析 Base64\n let payload: PaymentPayload;\n try {\n const decoded = decodeBase64(paymentHeader);\n const parsed = JSON.parse(decoded);\n\n // 使用 Zod 验证 payload\n payload = PaymentPayloadSchema.parse(parsed);\n } catch (error) {\n return {\n success: false,\n response402: this.get402Response(\n expectedRequirements,\n error instanceof Error\n ? `invalid_payment_header: ${error.message}`\n : \"invalid_payment_header\",\n ),\n };\n }\n\n return {\n success: true,\n data: {\n payload,\n requirements: expectedRequirements,\n },\n };\n }\n\n /**\n * 验证支付签名\n *\n * @param parsed - 解析后的支付数据\n * @returns 验证结果\n */\n async verify(parsed: ParsedPayment): Promise<VerifyResult> {\n try {\n // 调用 facilitator 验证\n const facilitatorPayload = {\n ...parsed.payload,\n payload: parsed.payload.payload || {},\n };\n\n const result = await this.facilitator.verify(\n facilitatorPayload as Parameters<typeof this.facilitator.verify>[0],\n parsed.requirements as Parameters<typeof this.facilitator.verify>[1],\n );\n\n if (!result.success) {\n return {\n success: false,\n error: result.error || result.errorMessage || \"Verification failed\",\n };\n }\n\n if (!result.payer) {\n return {\n success: false,\n error: \"Payer address not found in verification result\",\n };\n }\n\n return {\n success: true,\n payer: result.payer,\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : \"Verification error\",\n };\n }\n }\n\n /**\n * 结算支付\n *\n * @param parsed - 解析后的支付数据\n * @returns 结算结果\n */\n async settle(parsed: ParsedPayment): Promise<SettleResult> {\n try {\n // 调用 facilitator 结算\n const facilitatorPayload = {\n ...parsed.payload,\n payload: parsed.payload.payload || {},\n };\n\n const result = await this.facilitator.settle(\n facilitatorPayload as Parameters<typeof this.facilitator.settle>[0],\n parsed.requirements as Parameters<typeof this.facilitator.settle>[1],\n );\n\n if (!result.success) {\n return {\n success: false,\n error: result.error || result.errorMessage || \"Settlement failed\",\n };\n }\n\n if (!result.transaction) {\n return {\n success: false,\n error: \"Transaction hash not found in settlement result\",\n };\n }\n\n return {\n success: true,\n txHash: result.transaction,\n network: result.network || parsed.requirements.network,\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : \"Settlement error\",\n };\n }\n }\n\n /**\n * 生成 402 响应\n *\n * @param requirements - 支付要求\n * @param error - 可选的错误信息\n * @returns 402 响应对象\n */\n get402Response(requirements: PaymentRequirements, error?: string): Response402 {\n return {\n x402Version: 1,\n accepts: [requirements],\n error,\n };\n }\n\n /**\n * 清除缓存\n *\n * @param token - 可选,指定要清除的 token 地址\n */\n async clearCache(token?: string): Promise<void> {\n await this.detector.clearCache(token);\n }\n\n /**\n * 获取缓存统计\n *\n * @returns 缓存统计信息\n */\n getCacheStats(): { size: number; keys: string[] } {\n return this.detector.getCacheStats();\n }\n\n /**\n * 获取 facilitator 实例(供外部访问)\n *\n * @returns Facilitator 实例\n */\n getFacilitator(): Facilitator {\n return this.facilitator;\n }\n\n /**\n * 获取 detector 实例(供外部访问)\n *\n * @returns TokenDetector 实例\n */\n getDetector(): TokenDetector {\n return this.detector;\n }\n\n /**\n * 获取 client 实例(供外部访问)\n *\n * @returns PublicClient 实例\n */\n getClient(): PublicClient {\n return this.client;\n }\n\n /**\n * 获取网络名称\n *\n * @returns 网络名称\n */\n private async getNetworkName(): Promise<string> {\n if (this.network) {\n return this.network;\n }\n\n const chainId = await this.client.getChainId();\n\n // 映射常见的 chainId 到网络名称\n const networkMap: Record<number, string> = {\n 1: \"ethereum-mainnet\",\n 5: \"ethereum-goerli\",\n 11155111: \"ethereum-sepolia\",\n 56: \"bsc-mainnet\",\n 97: \"bsc-testnet\",\n 137: \"polygon-mainnet\",\n 80001: \"polygon-mumbai\",\n 42161: \"arbitrum-mainnet\",\n 421613: \"arbitrum-goerli\",\n 10: \"optimism-mainnet\",\n 420: \"optimism-goerli\",\n 8453: \"base-mainnet\",\n 84531: \"base-goerli\",\n };\n\n this.network = networkMap[chainId] || `chain-${chainId}`;\n return this.network;\n }\n}\n","import { z } from \"zod\";\n\n/**\n * 以太坊地址正则\n */\nconst EthAddressRegex = /^0x[a-fA-F0-9]{40}$/;\n\n/**\n * 整数字符串验证\n *\n * @param value - 整数字符串\n * @returns 是否为整数字符串\n */\nconst isIntegerString = (value: string) => {\n const num = Number(value);\n return Number.isInteger(num) && num >= 0;\n};\n\n/**\n * CreateRequirementsConfig Schema\n *\n * @example\n * ```typescript\n * const config = {\n * token: \"0x1234567890abcdef1234567890abcdef12345678\",\n * amount: \"1000\",\n * };\n * ```\n *\n * @returns CreateRequirementsConfigSchema\n */\nexport const CreateRequirementsConfigSchema = z.object({\n // 必填\n token: z.string().regex(EthAddressRegex, \"Invalid token address\"),\n amount: z.string().refine(isIntegerString, \"Amount must be a non-negative integer string\"),\n\n // 可选 - 网络和 scheme\n network: z.string().optional(),\n scheme: z.string().optional(),\n\n // 可选 - 支付类型\n paymentType: z.enum([\"permit\", \"eip3009\", \"permit2\", \"auto\"]).optional(),\n\n // 可选 - 资源描述\n resource: z.string().url().optional().or(z.literal(\"\")),\n description: z.string().optional(),\n mimeType: z.string().optional(),\n timeout: z.number().int().positive().optional(),\n\n // 可选 - 性能控制\n autoDetect: z.boolean().optional(),\n});\n\nexport type CreateRequirementsConfig = z.infer<typeof CreateRequirementsConfigSchema>;\n\n/**\n * PaymentRequirements Schema\n *\n * @example\n * ```typescript\n * const requirements = {\n * x402Version: 1,\n * scheme: \"exact\",\n * network: \"ethereum-mainnet\",\n * maxAmountRequired: \"1000\",\n * payTo: \"0x1234567890abcdef1234567890abcdef12345678\",\n * asset: \"0x1234567890abcdef1234567890abcdef12345678\",\n * maxTimeoutSeconds: 300,\n * resource: \"https://api.example.com/data\",\n * description: \"API access\",\n * mimeType: \"application/json\",\n * paymentType: \"permit\",\n * extra: {\n * relayer: \"0x1234567890abcdef1234567890abcdef12345678\",\n * name: \"API access\",\n * version: \"1.0.0\",\n * },\n * };\n * ```\n *\n * @returns PaymentRequirementsSchema\n */\nexport const PaymentRequirementsSchema = z.object({\n x402Version: z.literal(1),\n scheme: z.string(),\n network: z.string(),\n maxAmountRequired: z.string().refine(isIntegerString),\n payTo: z.string().regex(EthAddressRegex),\n asset: z.string().regex(EthAddressRegex),\n maxTimeoutSeconds: z.number().int().positive(),\n resource: z.string(),\n description: z.string(),\n mimeType: z.string(),\n paymentType: z.enum([\"permit\", \"eip3009\", \"permit2\"]).optional(),\n extra: z\n .object({\n relayer: z.string().regex(EthAddressRegex).optional(),\n name: z.string().optional(),\n version: z.string().optional(),\n })\n .passthrough()\n .optional(),\n});\n\nexport type PaymentRequirements = z.infer<typeof PaymentRequirementsSchema>;\n\n/**\n * PaymentPayload Schema\n *\n * @example\n * ```typescript\n * const payload = {\n * x402Version: 1,\n * scheme: \"exact\",\n * network: \"ethereum-mainnet\",\n * payload: {\n * amount: \"1000\",\n * token: \"0x1234567890abcdef1234567890abcdef12345678\",\n * recipient: \"0x1234567890abcdef1234567890abcdef12345678\",\n * nonce: \"1234567890abcdef1234567890abcdef12345678\",\n * expiration: 1715000000,\n * },\n * };\n * ```\n */\nexport const PaymentPayloadSchema = z.object({\n x402Version: z.number(),\n scheme: z.string(),\n network: z.string(),\n payload: z.any(),\n});\n\nexport type PaymentPayload = z.infer<typeof PaymentPayloadSchema>;\n\n/**\n * Response402 Schema\n */\nexport const Response402Schema = z.object({\n x402Version: z.literal(1),\n accepts: z.array(PaymentRequirementsSchema),\n error: z.string().optional(),\n});\n\nexport type Response402 = z.infer<typeof Response402Schema>;\n\n/**\n * InitResult Schema\n */\nexport const InitResultSchema = z.discriminatedUnion(\"success\", [\n z.object({ success: z.literal(true) }),\n z.object({ success: z.literal(false), error: z.string() }),\n]);\n\nexport type InitResult = z.infer<typeof InitResultSchema>;\n\n/**\n * ProcessResult Schema\n */\nexport const ProcessResultSchema = z.discriminatedUnion(\"success\", [\n z.object({\n success: z.literal(true),\n status: z.literal(200),\n data: z.object({\n payer: z.string().regex(EthAddressRegex),\n txHash: z.string(),\n }),\n }),\n z.object({\n success: z.literal(false),\n status: z.literal(402),\n response: Response402Schema,\n }),\n]);\n\nexport type ProcessResult = z.infer<typeof ProcessResultSchema>;\n\n/**\n * ParsedPayment Schema\n */\nexport const ParsedPaymentSchema = z.object({\n payload: PaymentPayloadSchema,\n requirements: PaymentRequirementsSchema,\n});\n\nexport type ParsedPayment = z.infer<typeof ParsedPaymentSchema>;\n\n/**\n * ParseResult Schema\n */\nexport const ParseResultSchema = z.discriminatedUnion(\"success\", [\n z.object({ success: z.literal(true), data: ParsedPaymentSchema }),\n z.object({ success: z.literal(false), response402: Response402Schema }),\n]);\n\nexport type ParseResult = z.infer<typeof ParseResultSchema>;\n\n/**\n * VerifyResult Schema\n */\nexport const VerifyResultSchema = z.discriminatedUnion(\"success\", [\n z.object({ success: z.literal(true), payer: z.string().regex(EthAddressRegex) }),\n z.object({ success: z.literal(false), error: z.string() }),\n]);\n\nexport type VerifyResult = z.infer<typeof VerifyResultSchema>;\n\n/**\n * SettleResult Schema\n */\nexport const SettleResultSchema = z.discriminatedUnion(\"success\", [\n z.object({\n success: z.literal(true),\n txHash: z.string(),\n network: z.string(),\n }),\n z.object({\n success: z.literal(false),\n error: z.string(),\n }),\n]);\n\nexport type SettleResult = z.infer<typeof SettleResultSchema>;\n","/**\n * 解码 Base64 字符串\n *\n * @param base64 - Base64 编码的字符串\n * @returns 解码后的字符串\n */\nexport function decodeBase64(base64: string): string {\n // 移除 data URL 前缀(如果存在)\n const cleanBase64 = base64.replace(/^data:application\\/json;base64,/, \"\");\n\n // 浏览器环境\n if (typeof window !== \"undefined\" && window.atob) {\n return window.atob(cleanBase64);\n }\n\n // Node.js 环境\n if (typeof Buffer !== \"undefined\") {\n return Buffer.from(cleanBase64, \"base64\").toString(\"utf-8\");\n }\n\n throw new Error(\"No Base64 decoder available\");\n}\n\n/**\n * 编码为 Base64 字符串\n *\n * @param str - 要编码的字符串\n * @returns Base64 编码的字符串\n */\nexport function encodeBase64(str: string): string {\n // 浏览器环境\n if (typeof window !== \"undefined\" && window.btoa) {\n return window.btoa(str);\n }\n\n // Node.js 环境\n if (typeof Buffer !== \"undefined\") {\n return Buffer.from(str, \"utf-8\").toString(\"base64\");\n }\n\n throw new Error(\"No Base64 encoder available\");\n}\n","/**\n * Express 中间件 for x402 Payment Protocol\n */\n\nimport type { X402Server } from \"../server\";\nimport type { CreateRequirementsConfig } from \"../schemas\";\n\n/**\n * Express types (避免直接导入 express,因为它是可选依赖)\n */\ntype Request = any;\ntype Response = any;\ntype NextFunction = any;\n\n/**\n * Express 中间件配置选项\n */\nexport interface ExpressMiddlewareOptions {\n /** X402Server 实例 */\n server: X402Server;\n\n /** 获取 token 地址的函数 */\n getToken: (req: Request) => string | Promise<string>;\n\n /** 获取金额的函数 */\n getAmount: (req: Request) => string | Promise<string>;\n\n /** 可选:获取额外配置的函数 */\n getConfig?: (req: Request) => Partial<CreateRequirementsConfig> | Promise<Partial<CreateRequirementsConfig>>;\n\n /** 可选:自定义错误处理 */\n onError?: (error: Error, req: Request, res: Response) => void;\n\n /** 可选:自定义 402 响应处理 */\n on402?: (req: Request, res: Response, response402: any) => void;\n\n /** 可选:支付成功后的回调 */\n onPaymentSuccess?: (req: Request, payer: string, txHash: string) => void | Promise<void>;\n}\n\n/**\n * 创建 Express 中间件\n *\n * @param options - 中间件配置\n * @returns Express 中间件函数\n *\n * @example\n * ```typescript\n * const middleware = createExpressMiddleware({\n * server,\n * getToken: (req) => req.body.token || USDC,\n * getAmount: (req) => calculatePrice(req.body),\n * });\n *\n * app.post(\"/api/resource\", middleware, (req, res) => {\n * // Payment already verified and settled\n * const { payer, txHash } = req.x402;\n * res.json({ data: \"resource\", payer, txHash });\n * });\n * ```\n */\nexport function createExpressMiddleware(options: ExpressMiddlewareOptions) {\n return async (req: Request, res: Response, next: NextFunction) => {\n try {\n // 1. 获取 token 和 amount\n const token = await options.getToken(req);\n const amount = await options.getAmount(req);\n\n // 2. 获取额外配置\n const extraConfig = options.getConfig ? await options.getConfig(req) : {};\n\n // 3. 创建支付要求\n const requirements = await options.server.createRequirements({\n token,\n amount,\n ...extraConfig,\n });\n\n // 4. 处理支付\n const paymentHeader = req.headers[\"x-payment\"] as string | undefined;\n const result = await options.server.process(paymentHeader, requirements);\n\n // 5. 处理结果\n if (!result.success) {\n // 支付失败,返回 402\n if (options.on402) {\n options.on402(req, res, result.response);\n } else {\n res.status(402).json(result.response);\n }\n return;\n }\n\n // 6. 支付成功\n // 将支付信息附加到 req 对象\n (req as any).x402 = {\n payer: result.data.payer,\n txHash: result.data.txHash,\n };\n\n // 调用成功回调\n if (options.onPaymentSuccess) {\n await options.onPaymentSuccess(req, result.data.payer, result.data.txHash);\n }\n\n // 继续到下一个中间件\n next();\n } catch (error) {\n // 错误处理\n if (options.onError) {\n options.onError(error as Error, req, res);\n } else {\n console.error(\"x402 middleware error:\", error);\n res.status(500).json({\n error: \"Payment processing error\",\n message: error instanceof Error ? error.message : \"Unknown error\",\n });\n }\n }\n };\n}\n\n/**\n * 扩展 Express Request 类型\n * 注意:这个扩展只在安装了 @types/express 时生效\n */\n/* eslint-disable @typescript-eslint/no-namespace */\ndeclare global {\n namespace Express {\n interface Request {\n x402?: {\n payer: string;\n txHash: string;\n };\n }\n }\n}\n/* eslint-enable @typescript-eslint/no-namespace */\n\n","/**\n * Hono 中间件 for x402 Payment Protocol\n */\n\nimport type { X402Server } from \"../server\";\nimport type { CreateRequirementsConfig } from \"../schemas\";\n\n/**\n * Hono types (避免直接导入 hono,因为它是可选依赖)\n */\ntype Context = any;\ntype MiddlewareHandler = any;\n\n/**\n * Hono 中间件配置选项\n */\nexport interface HonoMiddlewareOptions {\n /** X402Server 实例 */\n server: X402Server;\n\n /** 获取 token 地址的函数 */\n getToken: (c: Context) => string | Promise<string>;\n\n /** 获取金额的函数 */\n getAmount: (c: Context) => string | Promise<string>;\n\n /** 可选:获取额外配置的函数 */\n getConfig?: (c: Context) => Partial<CreateRequirementsConfig> | Promise<Partial<CreateRequirementsConfig>>;\n\n /** 可选:自定义错误处理 */\n onError?: (error: Error, c: Context) => Response | Promise<Response>;\n\n /** 可选:自定义 402 响应处理 */\n on402?: (c: Context, response402: any) => Response | Promise<Response>;\n\n /** 可选:支付成功后的回调 */\n onPaymentSuccess?: (c: Context, payer: string, txHash: string) => void | Promise<void>;\n}\n\n/**\n * 创建 Hono 中间件\n *\n * @param options - 中间件配置\n * @returns Hono 中间件函数\n *\n * @example\n * ```typescript\n * const middleware = createHonoMiddleware({\n * server,\n * getToken: (c) => c.req.query(\"token\") || USDC,\n * getAmount: async (c) => {\n * const body = await c.req.json();\n * return calculatePrice(body.complexity);\n * },\n * });\n *\n * app.post(\"/api/resource\", middleware, (c) => {\n * // Payment already verified and settled\n * const { payer, txHash } = c.get(\"x402\");\n * return c.json({ data: \"resource\", payer, txHash });\n * });\n * ```\n */\nexport function createHonoMiddleware(options: HonoMiddlewareOptions): MiddlewareHandler {\n return async (c: Context, next: any) => {\n try {\n // 1. 获取 token 和 amount\n const token = await options.getToken(c);\n const amount = await options.getAmount(c);\n\n // 2. 获取额外配置\n const extraConfig = options.getConfig ? await options.getConfig(c) : {};\n\n // 3. 创建支付要求\n const requirements = await options.server.createRequirements({\n token,\n amount,\n ...extraConfig,\n });\n\n // 4. 处理支付\n const paymentHeader = c.req.header(\"x-payment\");\n const result = await options.server.process(paymentHeader, requirements);\n\n // 5. 处理结果\n if (!result.success) {\n // 支付失败,返回 402\n if (options.on402) {\n return options.on402(c, result.response);\n } else {\n return c.json(result.response, 402);\n }\n }\n\n // 6. 支付成功\n // 将支付信息存储到 context\n c.set(\"x402\", {\n payer: result.data.payer,\n txHash: result.data.txHash,\n });\n\n // 调用成功回调\n if (options.onPaymentSuccess) {\n await options.onPaymentSuccess(c, result.data.payer, result.data.txHash);\n }\n\n // 继续到下一个中间件\n await next();\n } catch (error) {\n // 错误处理\n if (options.onError) {\n return options.onError(error as Error, c);\n } else {\n console.error(\"x402 middleware error:\", error);\n return c.json(\n {\n error: \"Payment processing error\",\n message: error instanceof Error ? error.message : \"Unknown error\",\n },\n 500,\n );\n }\n }\n };\n}\n\n/**\n * 扩展 Hono Context 类型\n * 注意:这个扩展只在安装了 hono 时生效\n */\n/* eslint-disable-next-line @typescript-eslint/no-unused-vars */\ninterface HonoContextVariableMap {\n x402?: {\n payer: string;\n txHash: string;\n };\n}\n\n"],"mappings":";AACA,SAAS,qBAAqB;;;ACD9B,SAAS,SAAS;AAKlB,IAAM,kBAAkB;AAQxB,IAAM,kBAAkB,CAAC,UAAkB;AACzC,QAAM,MAAM,OAAO,KAAK;AACxB,SAAO,OAAO,UAAU,GAAG,KAAK,OAAO;AACzC;AAeO,IAAM,iCAAiC,EAAE,OAAO;AAAA;AAAA,EAErD,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,uBAAuB;AAAA,EAChE,QAAQ,EAAE,OAAO,EAAE,OAAO,iBAAiB,8CAA8C;AAAA;AAAA,EAGzF,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,QAAQ,EAAE,OAAO,EAAE,SAAS;AAAA;AAAA,EAG5B,aAAa,EAAE,KAAK,CAAC,UAAU,WAAW,WAAW,MAAM,CAAC,EAAE,SAAS;AAAA;AAAA,EAGvE,UAAU,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC;AAAA,EACtD,aAAa,EAAE,OAAO,EAAE,SAAS;AAAA,EACjC,UAAU,EAAE,OAAO,EAAE,SAAS;AAAA,EAC9B,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS;AAAA;AAAA,EAG9C,YAAY,EAAE,QAAQ,EAAE,SAAS;AACnC,CAAC;AA+BM,IAAM,4BAA4B,EAAE,OAAO;AAAA,EAChD,aAAa,EAAE,QAAQ,CAAC;AAAA,EACxB,QAAQ,EAAE,OAAO;AAAA,EACjB,SAAS,EAAE,OAAO;AAAA,EAClB,mBAAmB,EAAE,OAAO,EAAE,OAAO,eAAe;AAAA,EACpD,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe;AAAA,EACvC,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe;AAAA,EACvC,mBAAmB,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA,EAC7C,UAAU,EAAE,OAAO;AAAA,EACnB,aAAa,EAAE,OAAO;AAAA,EACtB,UAAU,EAAE,OAAO;AAAA,EACnB,aAAa,EAAE,KAAK,CAAC,UAAU,WAAW,SAAS,CAAC,EAAE,SAAS;AAAA,EAC/D,OAAO,EACJ,OAAO;AAAA,IACN,SAAS,EAAE,OAAO,EAAE,MAAM,eAAe,EAAE,SAAS;AAAA,IACpD,MAAM,EAAE,OAAO,EAAE,SAAS;AAAA,IAC1B,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA,EAC/B,CAAC,EACA,YAAY,EACZ,SAAS;AACd,CAAC;AAuBM,IAAM,uBAAuB,EAAE,OAAO;AAAA,EAC3C,aAAa,EAAE,OAAO;AAAA,EACtB,QAAQ,EAAE,OAAO;AAAA,EACjB,SAAS,EAAE,OAAO;AAAA,EAClB,SAAS,EAAE,IAAI;AACjB,CAAC;AAOM,IAAM,oBAAoB,EAAE,OAAO;AAAA,EACxC,aAAa,EAAE,QAAQ,CAAC;AAAA,EACxB,SAAS,EAAE,MAAM,yBAAyB;AAAA,EAC1C,OAAO,EAAE,OAAO,EAAE,SAAS;AAC7B,CAAC;AAOM,IAAM,mBAAmB,EAAE,mBAAmB,WAAW;AAAA,EAC9D,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,IAAI,EAAE,CAAC;AAAA,EACrC,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,KAAK,GAAG,OAAO,EAAE,OAAO,EAAE,CAAC;AAC3D,CAAC;AAOM,IAAM,sBAAsB,EAAE,mBAAmB,WAAW;AAAA,EACjE,EAAE,OAAO;AAAA,IACP,SAAS,EAAE,QAAQ,IAAI;AAAA,IACvB,QAAQ,EAAE,QAAQ,GAAG;AAAA,IACrB,MAAM,EAAE,OAAO;AAAA,MACb,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe;AAAA,MACvC,QAAQ,EAAE,OAAO;AAAA,IACnB,CAAC;AAAA,EACH,CAAC;AAAA,EACD,EAAE,OAAO;AAAA,IACP,SAAS,EAAE,QAAQ,KAAK;AAAA,IACxB,QAAQ,EAAE,QAAQ,GAAG;AAAA,IACrB,UAAU;AAAA,EACZ,CAAC;AACH,CAAC;AAOM,IAAM,sBAAsB,EAAE,OAAO;AAAA,EAC1C,SAAS;AAAA,EACT,cAAc;AAChB,CAAC;AAOM,IAAM,oBAAoB,EAAE,mBAAmB,WAAW;AAAA,EAC/D,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,IAAI,GAAG,MAAM,oBAAoB,CAAC;AAAA,EAChE,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,KAAK,GAAG,aAAa,kBAAkB,CAAC;AACxE,CAAC;AAOM,IAAM,qBAAqB,EAAE,mBAAmB,WAAW;AAAA,EAChE,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,IAAI,GAAG,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,EAAE,CAAC;AAAA,EAC/E,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,KAAK,GAAG,OAAO,EAAE,OAAO,EAAE,CAAC;AAC3D,CAAC;AAOM,IAAM,qBAAqB,EAAE,mBAAmB,WAAW;AAAA,EAChE,EAAE,OAAO;AAAA,IACP,SAAS,EAAE,QAAQ,IAAI;AAAA,IACvB,QAAQ,EAAE,OAAO;AAAA,IACjB,SAAS,EAAE,OAAO;AAAA,EACpB,CAAC;AAAA,EACD,EAAE,OAAO;AAAA,IACP,SAAS,EAAE,QAAQ,KAAK;AAAA,IACxB,OAAO,EAAE,OAAO;AAAA,EAClB,CAAC;AACH,CAAC;;;ACrNM,SAAS,aAAa,QAAwB;AAEnD,QAAM,cAAc,OAAO,QAAQ,mCAAmC,EAAE;AAGxE,MAAI,OAAO,WAAW,eAAe,OAAO,MAAM;AAChD,WAAO,OAAO,KAAK,WAAW;AAAA,EAChC;AAGA,MAAI,OAAO,WAAW,aAAa;AACjC,WAAO,OAAO,KAAK,aAAa,QAAQ,EAAE,SAAS,OAAO;AAAA,EAC5D;AAEA,QAAM,IAAI,MAAM,6BAA6B;AAC/C;AAQO,SAAS,aAAa,KAAqB;AAEhD,MAAI,OAAO,WAAW,eAAe,OAAO,MAAM;AAChD,WAAO,OAAO,KAAK,GAAG;AAAA,EACxB;AAGA,MAAI,OAAO,WAAW,aAAa;AACjC,WAAO,OAAO,KAAK,KAAK,OAAO,EAAE,SAAS,QAAQ;AAAA,EACpD;AAEA,QAAM,IAAI,MAAM,6BAA6B;AAC/C;;;AFcO,IAAM,aAAN,MAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWtB,YAAY,QAA0B;AAPtC,SAAQ,UAAyB;AAQ/B,QAAI,CAAC,OAAO,QAAQ;AAClB,YAAM,IAAI,MAAM,oBAAoB;AAAA,IACtC;AACA,QAAI,CAAC,OAAO,aAAa;AACvB,YAAM,IAAI,MAAM,yBAAyB;AAAA,IAC3C;AAEA,SAAK,SAAS,OAAO;AACrB,SAAK,cAAc,OAAO;AAG1B,SAAK,WAAW,IAAI,cAAc,OAAO,QAAQ,EAAE,QAAQ,KAAK,CAAC;AAGjE,SAAK,UAAU,OAAO,WAAW;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,WAAW,QAAuC;AACtD,QAAI;AACF,YAAM,KAAK,SAAS,WAAW,MAAM;AACrC,aAAO,EAAE,SAAS,KAAK;AAAA,IACzB,SAAS,OAAO;AACd,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO,iBAAiB,QAAQ,MAAM,UAAU;AAAA,MAClD;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,mBAAmB,QAAgE;AAEvF,UAAM,kBAAkB,+BAA+B,MAAM,MAAM;AAGnE,UAAM,UAAU,gBAAgB,WAAW,KAAK,WAAY,MAAM,KAAK,eAAe;AAGtF,QAAI;AACJ,QAAI;AACJ,QAAI;AAEJ,QAAI,gBAAgB,eAAe,OAAO;AAExC,YAAM,SAAS,MAAM,KAAK,SAAS,OAAO,gBAAgB,KAAK;AAG/D,UAAI,gBAAgB,eAAe,gBAAgB,gBAAgB,QAAQ;AACzE,sBAAc,gBAAgB;AAAA,MAChC,OAAO;AACL,cAAM,oBAAoB,MAAM,KAAK,SAAS,qBAAqB,gBAAgB,KAAK;AACxF,YAAI,CAAC,mBAAmB;AACtB,gBAAM,IAAI;AAAA,YACR,SAAS,gBAAgB,KAAK;AAAA,UAChC;AAAA,QACF;AACA,sBAAc;AAAA,MAChB;AAEA,kBAAY,OAAO;AACnB,qBAAe,OAAO;AAAA,IACxB,OAAO;AAEL,UAAI,CAAC,gBAAgB,eAAe,gBAAgB,gBAAgB,QAAQ;AAC1E,cAAM,IAAI,MAAM,mDAAmD;AAAA,MACrE;AACA,oBAAc,gBAAgB;AAAA,IAChC;AAGA,UAAM,eAAe;AAAA,MACnB,aAAa;AAAA,MACb,QAAQ,gBAAgB,UAAU;AAAA,MAClC;AAAA,MACA,mBAAmB,gBAAgB;AAAA,MACnC,OAAO,KAAK,YAAY;AAAA,MACxB,OAAO,gBAAgB;AAAA,MACvB,mBAAmB,gBAAgB,WAAW;AAAA,MAC9C,UAAU,gBAAgB,YAAY;AAAA,MACtC,aAAa,gBAAgB,eAAe;AAAA,MAC5C,UAAU,gBAAgB,YAAY;AAAA,MACtC;AAAA,MACA,OAAO;AAAA,QACL,SAAS,KAAK,YAAY;AAAA,QAC1B,GAAI,aAAa,EAAE,MAAM,UAAU;AAAA,QACnC,GAAI,gBAAgB,EAAE,SAAS,aAAa;AAAA,MAC9C;AAAA,IACF;AAGA,WAAO,0BAA0B,MAAM,YAAY;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,QACJ,eACA,sBACwB;AAExB,UAAM,SAAS,KAAK,MAAM,eAAe,oBAAoB;AAC7D,QAAI,CAAC,OAAO,SAAS;AACnB,aAAO;AAAA,QACL,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,UAAU,OAAO;AAAA,MACnB;AAAA,IACF;AAGA,UAAM,WAAW,MAAM,KAAK,OAAO,OAAO,IAAI;AAC9C,QAAI,CAAC,SAAS,SAAS;AACrB,aAAO;AAAA,QACL,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,UAAU,KAAK,eAAe,sBAAsB,SAAS,KAAK;AAAA,MACpE;AAAA,IACF;AAGA,UAAM,UAAU,MAAM,KAAK,OAAO,OAAO,IAAI;AAC7C,QAAI,CAAC,QAAQ,SAAS;AACpB,aAAO;AAAA,QACL,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,UAAU,KAAK,eAAe,sBAAsB,QAAQ,KAAK;AAAA,MACnE;AAAA,IACF;AAEA,WAAO;AAAA,MACL,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,MAAM;AAAA,QACJ,OAAO,SAAS;AAAA,QAChB,QAAQ,QAAQ;AAAA,MAClB;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,eAAmC,sBAAwD;AAE/F,QAAI,CAAC,eAAe;AAClB,aAAO;AAAA,QACL,SAAS;AAAA,QACT,aAAa,KAAK,eAAe,sBAAsB,wBAAwB;AAAA,MACjF;AAAA,IACF;AAGA,QAAI;AACJ,QAAI;AACF,YAAM,UAAU,aAAa,aAAa;AAC1C,YAAM,SAAS,KAAK,MAAM,OAAO;AAGjC,gBAAU,qBAAqB,MAAM,MAAM;AAAA,IAC7C,SAAS,OAAO;AACd,aAAO;AAAA,QACL,SAAS;AAAA,QACT,aAAa,KAAK;AAAA,UAChB;AAAA,UACA,iBAAiB,QACb,2BAA2B,MAAM,OAAO,KACxC;AAAA,QACN;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL,SAAS;AAAA,MACT,MAAM;AAAA,QACJ;AAAA,QACA,cAAc;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,OAAO,QAA8C;AACzD,QAAI;AAEF,YAAM,qBAAqB;AAAA,QACzB,GAAG,OAAO;AAAA,QACV,SAAS,OAAO,QAAQ,WAAW,CAAC;AAAA,MACtC;AAEA,YAAM,SAAS,MAAM,KAAK,YAAY;AAAA,QACpC;AAAA,QACA,OAAO;AAAA,MACT;AAEA,UAAI,CAAC,OAAO,SAAS;AACnB,eAAO;AAAA,UACL,SAAS;AAAA,UACT,OAAO,OAAO,SAAS,OAAO,gBAAgB;AAAA,QAChD;AAAA,MACF;AAEA,UAAI,CAAC,OAAO,OAAO;AACjB,eAAO;AAAA,UACL,SAAS;AAAA,UACT,OAAO;AAAA,QACT;AAAA,MACF;AAEA,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO,OAAO;AAAA,MAChB;AAAA,IACF,SAAS,OAAO;AACd,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO,iBAAiB,QAAQ,MAAM,UAAU;AAAA,MAClD;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,OAAO,QAA8C;AACzD,QAAI;AAEF,YAAM,qBAAqB;AAAA,QACzB,GAAG,OAAO;AAAA,QACV,SAAS,OAAO,QAAQ,WAAW,CAAC;AAAA,MACtC;AAEA,YAAM,SAAS,MAAM,KAAK,YAAY;AAAA,QACpC;AAAA,QACA,OAAO;AAAA,MACT;AAEA,UAAI,CAAC,OAAO,SAAS;AACnB,eAAO;AAAA,UACL,SAAS;AAAA,UACT,OAAO,OAAO,SAAS,OAAO,gBAAgB;AAAA,QAChD;AAAA,MACF;AAEA,UAAI,CAAC,OAAO,aAAa;AACvB,eAAO;AAAA,UACL,SAAS;AAAA,UACT,OAAO;AAAA,QACT;AAAA,MACF;AAEA,aAAO;AAAA,QACL,SAAS;AAAA,QACT,QAAQ,OAAO;AAAA,QACf,SAAS,OAAO,WAAW,OAAO,aAAa;AAAA,MACjD;AAAA,IACF,SAAS,OAAO;AACd,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO,iBAAiB,QAAQ,MAAM,UAAU;AAAA,MAClD;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,eAAe,cAAmC,OAA6B;AAC7E,WAAO;AAAA,MACL,aAAa;AAAA,MACb,SAAS,CAAC,YAAY;AAAA,MACtB;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,WAAW,OAA+B;AAC9C,UAAM,KAAK,SAAS,WAAW,KAAK;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,gBAAkD;AAChD,WAAO,KAAK,SAAS,cAAc;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,iBAA8B;AAC5B,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,cAA6B;AAC3B,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,YAA0B;AACxB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAc,iBAAkC;AAC9C,QAAI,KAAK,SAAS;AAChB,aAAO,KAAK;AAAA,IACd;AAEA,UAAM,UAAU,MAAM,KAAK,OAAO,WAAW;AAG7C,UAAM,aAAqC;AAAA,MACzC,GAAG;AAAA,MACH,GAAG;AAAA,MACH,UAAU;AAAA,MACV,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,KAAK;AAAA,MACL,OAAO;AAAA,MACP,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,IAAI;AAAA,MACJ,KAAK;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,IACT;AAEA,SAAK,UAAU,WAAW,OAAO,KAAK,SAAS,OAAO;AACtD,WAAO,KAAK;AAAA,EACd;AACF;;;AGtYO,SAAS,wBAAwB,SAAmC;AACzE,SAAO,OAAO,KAAc,KAAe,SAAuB;AAChE,QAAI;AAEF,YAAM,QAAQ,MAAM,QAAQ,SAAS,GAAG;AACxC,YAAM,SAAS,MAAM,QAAQ,UAAU,GAAG;AAG1C,YAAM,cAAc,QAAQ,YAAY,MAAM,QAAQ,UAAU,GAAG,IAAI,CAAC;AAGxE,YAAM,eAAe,MAAM,QAAQ,OAAO,mBAAmB;AAAA,QAC3D;AAAA,QACA;AAAA,QACA,GAAG;AAAA,MACL,CAAC;AAGD,YAAM,gBAAgB,IAAI,QAAQ,WAAW;AAC7C,YAAM,SAAS,MAAM,QAAQ,OAAO,QAAQ,eAAe,YAAY;AAGvE,UAAI,CAAC,OAAO,SAAS;AAEnB,YAAI,QAAQ,OAAO;AACjB,kBAAQ,MAAM,KAAK,KAAK,OAAO,QAAQ;AAAA,QACzC,OAAO;AACL,cAAI,OAAO,GAAG,EAAE,KAAK,OAAO,QAAQ;AAAA,QACtC;AACA;AAAA,MACF;AAIA,MAAC,IAAY,OAAO;AAAA,QAClB,OAAO,OAAO,KAAK;AAAA,QACnB,QAAQ,OAAO,KAAK;AAAA,MACtB;AAGA,UAAI,QAAQ,kBAAkB;AAC5B,cAAM,QAAQ,iBAAiB,KAAK,OAAO,KAAK,OAAO,OAAO,KAAK,MAAM;AAAA,MAC3E;AAGA,WAAK;AAAA,IACP,SAAS,OAAO;AAEd,UAAI,QAAQ,SAAS;AACnB,gBAAQ,QAAQ,OAAgB,KAAK,GAAG;AAAA,MAC1C,OAAO;AACL,gBAAQ,MAAM,0BAA0B,KAAK;AAC7C,YAAI,OAAO,GAAG,EAAE,KAAK;AAAA,UACnB,OAAO;AAAA,UACP,SAAS,iBAAiB,QAAQ,MAAM,UAAU;AAAA,QACpD,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACF;;;ACzDO,SAAS,qBAAqB,SAAmD;AACtF,SAAO,OAAO,GAAY,SAAc;AACtC,QAAI;AAEF,YAAM,QAAQ,MAAM,QAAQ,SAAS,CAAC;AACtC,YAAM,SAAS,MAAM,QAAQ,UAAU,CAAC;AAGxC,YAAM,cAAc,QAAQ,YAAY,MAAM,QAAQ,UAAU,CAAC,IAAI,CAAC;AAGtE,YAAM,eAAe,MAAM,QAAQ,OAAO,mBAAmB;AAAA,QAC3D;AAAA,QACA;AAAA,QACA,GAAG;AAAA,MACL,CAAC;AAGD,YAAM,gBAAgB,EAAE,IAAI,OAAO,WAAW;AAC9C,YAAM,SAAS,MAAM,QAAQ,OAAO,QAAQ,eAAe,YAAY;AAGvE,UAAI,CAAC,OAAO,SAAS;AAEnB,YAAI,QAAQ,OAAO;AACjB,iBAAO,QAAQ,MAAM,GAAG,OAAO,QAAQ;AAAA,QACzC,OAAO;AACL,iBAAO,EAAE,KAAK,OAAO,UAAU,GAAG;AAAA,QACpC;AAAA,MACF;AAIA,QAAE,IAAI,QAAQ;AAAA,QACZ,OAAO,OAAO,KAAK;AAAA,QACnB,QAAQ,OAAO,KAAK;AAAA,MACtB,CAAC;AAGD,UAAI,QAAQ,kBAAkB;AAC5B,cAAM,QAAQ,iBAAiB,GAAG,OAAO,KAAK,OAAO,OAAO,KAAK,MAAM;AAAA,MACzE;AAGA,YAAM,KAAK;AAAA,IACb,SAAS,OAAO;AAEd,UAAI,QAAQ,SAAS;AACnB,eAAO,QAAQ,QAAQ,OAAgB,CAAC;AAAA,MAC1C,OAAO;AACL,gBAAQ,MAAM,0BAA0B,KAAK;AAC7C,eAAO,EAAE;AAAA,UACP;AAAA,YACE,OAAO;AAAA,YACP,SAAS,iBAAiB,QAAQ,MAAM,UAAU;AAAA,UACpD;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;","names":[]}