@bankofai/x402-extensions 1.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/README.md +28 -0
  2. package/dist/cjs/bazaar/index.d.ts +4 -0
  3. package/dist/cjs/bazaar/index.js +1048 -0
  4. package/dist/cjs/bazaar/index.js.map +1 -0
  5. package/dist/cjs/builder-code/index.d.ts +225 -0
  6. package/dist/cjs/builder-code/index.js +369 -0
  7. package/dist/cjs/builder-code/index.js.map +1 -0
  8. package/dist/cjs/index-B8S563vv.d.ts +929 -0
  9. package/dist/cjs/index-BUV9B9f8.d.ts +929 -0
  10. package/dist/cjs/index.d.ts +373 -0
  11. package/dist/cjs/index.js +3536 -0
  12. package/dist/cjs/index.js.map +1 -0
  13. package/dist/cjs/offer-receipt/index.d.ts +702 -0
  14. package/dist/cjs/offer-receipt/index.js +909 -0
  15. package/dist/cjs/offer-receipt/index.js.map +1 -0
  16. package/dist/cjs/payment-identifier/index.d.ts +345 -0
  17. package/dist/cjs/payment-identifier/index.js +285 -0
  18. package/dist/cjs/payment-identifier/index.js.map +1 -0
  19. package/dist/cjs/sign-in-with-x/index.d.ts +1117 -0
  20. package/dist/cjs/sign-in-with-x/index.js +876 -0
  21. package/dist/cjs/sign-in-with-x/index.js.map +1 -0
  22. package/dist/esm/bazaar/index.d.mts +4 -0
  23. package/dist/esm/bazaar/index.mjs +51 -0
  24. package/dist/esm/bazaar/index.mjs.map +1 -0
  25. package/dist/esm/builder-code/index.d.mts +225 -0
  26. package/dist/esm/builder-code/index.mjs +27 -0
  27. package/dist/esm/builder-code/index.mjs.map +1 -0
  28. package/dist/esm/chunk-4IPDE3NS.mjs +990 -0
  29. package/dist/esm/chunk-4IPDE3NS.mjs.map +1 -0
  30. package/dist/esm/chunk-N74HQTNO.mjs +807 -0
  31. package/dist/esm/chunk-N74HQTNO.mjs.map +1 -0
  32. package/dist/esm/chunk-OWZP4CUR.mjs +333 -0
  33. package/dist/esm/chunk-OWZP4CUR.mjs.map +1 -0
  34. package/dist/esm/chunk-RERA4OZZ.mjs +233 -0
  35. package/dist/esm/chunk-RERA4OZZ.mjs.map +1 -0
  36. package/dist/esm/chunk-TIVMC3ZS.mjs +828 -0
  37. package/dist/esm/chunk-TIVMC3ZS.mjs.map +1 -0
  38. package/dist/esm/index-B8S563vv.d.mts +929 -0
  39. package/dist/esm/index-BUV9B9f8.d.mts +929 -0
  40. package/dist/esm/index.d.mts +373 -0
  41. package/dist/esm/index.mjs +455 -0
  42. package/dist/esm/index.mjs.map +1 -0
  43. package/dist/esm/offer-receipt/index.d.mts +702 -0
  44. package/dist/esm/offer-receipt/index.mjs +97 -0
  45. package/dist/esm/offer-receipt/index.mjs.map +1 -0
  46. package/dist/esm/payment-identifier/index.d.mts +345 -0
  47. package/dist/esm/payment-identifier/index.mjs +39 -0
  48. package/dist/esm/payment-identifier/index.mjs.map +1 -0
  49. package/dist/esm/sign-in-with-x/index.d.mts +1117 -0
  50. package/dist/esm/sign-in-with-x/index.mjs +73 -0
  51. package/dist/esm/sign-in-with-x/index.mjs.map +1 -0
  52. package/package.json +124 -0
@@ -0,0 +1,929 @@
1
+ import { FacilitatorExtension, ResourceServerExtension, ResourceInfo, PaymentPayload, PaymentRequirements, PaymentRequirementsV1 } from '@bankofai/x402-core/types';
2
+ import { QueryParamMethods, BodyMethods, HTTPFacilitatorClient } from '@bankofai/x402-core/http';
3
+ import { RoutesConfig } from '@bankofai/x402-core/server';
4
+
5
+ /**
6
+ * Shared type utilities for x402 extensions
7
+ */
8
+ /**
9
+ * Type utility to merge extensions properly when chaining.
10
+ * If T already has extensions, merge them; otherwise add new extensions.
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * // Chaining multiple extensions preserves all types:
15
+ * const client = withBazaar(withOtherExtension(new HTTPFacilitatorClient()));
16
+ * // Type: HTTPFacilitatorClient & { extensions: OtherExtension & BazaarExtension }
17
+ * ```
18
+ */
19
+ type WithExtensions<T, E> = T extends {
20
+ extensions: infer Existing;
21
+ } ? Omit<T, "extensions"> & {
22
+ extensions: Existing & E;
23
+ } : T & {
24
+ extensions: E;
25
+ };
26
+
27
+ /**
28
+ * HTTP-specific type definitions for the Bazaar Discovery Extension
29
+ */
30
+
31
+ /** Shared schema definition for an object-typed parameter map (queryParams, pathParams, etc.) */
32
+ interface ParamMapSchemaProperty {
33
+ type: "object";
34
+ properties?: Record<string, unknown>;
35
+ additionalProperties?: boolean;
36
+ }
37
+ /**
38
+ * Discovery info for query parameter methods (GET, HEAD, DELETE)
39
+ */
40
+ interface QueryDiscoveryInfo {
41
+ input: {
42
+ type: "http";
43
+ /** Absent at declaration time; set by bazaarResourceServerExtension.enrichDeclaration */
44
+ method?: QueryParamMethods;
45
+ queryParams?: Record<string, unknown>;
46
+ pathParams?: Record<string, unknown>;
47
+ headers?: Record<string, string>;
48
+ };
49
+ output?: {
50
+ type?: string;
51
+ format?: string;
52
+ example?: unknown;
53
+ };
54
+ }
55
+ /**
56
+ * Discovery info for body methods (POST, PUT, PATCH)
57
+ */
58
+ interface BodyDiscoveryInfo {
59
+ input: {
60
+ type: "http";
61
+ /** Absent at declaration time; set by bazaarResourceServerExtension.enrichDeclaration */
62
+ method?: BodyMethods;
63
+ bodyType: "json" | "form-data" | "text";
64
+ body: Record<string, unknown>;
65
+ queryParams?: Record<string, unknown>;
66
+ pathParams?: Record<string, unknown>;
67
+ headers?: Record<string, string>;
68
+ };
69
+ output?: {
70
+ type?: string;
71
+ format?: string;
72
+ example?: unknown;
73
+ };
74
+ }
75
+ /**
76
+ * Discovery extension for query parameter methods (GET, HEAD, DELETE)
77
+ */
78
+ interface QueryDiscoveryExtension {
79
+ info: QueryDiscoveryInfo;
80
+ routeTemplate?: string;
81
+ schema: {
82
+ $schema: "https://json-schema.org/draft/2020-12/schema";
83
+ type: "object";
84
+ properties: {
85
+ input: {
86
+ type: "object";
87
+ properties: {
88
+ type: {
89
+ type: "string";
90
+ const: "http";
91
+ };
92
+ method: {
93
+ type: "string";
94
+ enum: QueryParamMethods[];
95
+ };
96
+ queryParams?: ParamMapSchemaProperty & {
97
+ required?: string[];
98
+ };
99
+ pathParams?: ParamMapSchemaProperty;
100
+ headers?: {
101
+ type: "object";
102
+ additionalProperties: {
103
+ type: "string";
104
+ };
105
+ };
106
+ };
107
+ required: ("type" | "method")[];
108
+ additionalProperties?: boolean;
109
+ };
110
+ output?: {
111
+ type: "object";
112
+ properties?: Record<string, unknown>;
113
+ required?: readonly string[];
114
+ additionalProperties?: boolean;
115
+ };
116
+ };
117
+ required: ["input"];
118
+ };
119
+ }
120
+ /**
121
+ * Discovery extension for body methods (POST, PUT, PATCH)
122
+ */
123
+ interface BodyDiscoveryExtension {
124
+ info: BodyDiscoveryInfo;
125
+ routeTemplate?: string;
126
+ schema: {
127
+ $schema: "https://json-schema.org/draft/2020-12/schema";
128
+ type: "object";
129
+ properties: {
130
+ input: {
131
+ type: "object";
132
+ properties: {
133
+ type: {
134
+ type: "string";
135
+ const: "http";
136
+ };
137
+ method: {
138
+ type: "string";
139
+ enum: BodyMethods[];
140
+ };
141
+ bodyType: {
142
+ type: "string";
143
+ enum: ["json", "form-data", "text"];
144
+ };
145
+ body: Record<string, unknown>;
146
+ queryParams?: ParamMapSchemaProperty & {
147
+ required?: string[];
148
+ };
149
+ pathParams?: ParamMapSchemaProperty;
150
+ headers?: {
151
+ type: "object";
152
+ additionalProperties: {
153
+ type: "string";
154
+ };
155
+ };
156
+ };
157
+ required: ("type" | "method" | "bodyType" | "body")[];
158
+ additionalProperties?: boolean;
159
+ };
160
+ output?: {
161
+ type: "object";
162
+ properties?: Record<string, unknown>;
163
+ required?: readonly string[];
164
+ additionalProperties?: boolean;
165
+ };
166
+ };
167
+ required: ["input"];
168
+ };
169
+ }
170
+ interface DeclareQueryDiscoveryExtensionConfig {
171
+ method?: QueryParamMethods;
172
+ input?: Record<string, unknown>;
173
+ inputSchema?: Record<string, unknown>;
174
+ pathParams?: Record<string, unknown>;
175
+ pathParamsSchema?: Record<string, unknown>;
176
+ output?: {
177
+ example?: unknown;
178
+ schema?: Record<string, unknown>;
179
+ };
180
+ }
181
+ interface DeclareBodyDiscoveryExtensionConfig {
182
+ method?: BodyMethods;
183
+ input?: Record<string, unknown>;
184
+ inputSchema?: Record<string, unknown>;
185
+ pathParams?: Record<string, unknown>;
186
+ pathParamsSchema?: Record<string, unknown>;
187
+ bodyType: "json" | "form-data" | "text";
188
+ output?: {
189
+ example?: unknown;
190
+ schema?: Record<string, unknown>;
191
+ };
192
+ }
193
+ interface DiscoveredHTTPResource {
194
+ resourceUrl: string;
195
+ description?: string;
196
+ mimeType?: string;
197
+ /** Sanitized service metadata. See `sanitizeResourceServiceMetadata` for rules. */
198
+ serviceName?: string;
199
+ tags?: string[];
200
+ iconUrl?: string;
201
+ /** Present after server extension enrichment; may be absent for pre-enrichment data */
202
+ method?: string;
203
+ routeTemplate?: string;
204
+ x402Version: number;
205
+ discoveryInfo: DiscoveryInfo;
206
+ /** Extension payloads for catalog echo (v2: payload.extensions; v1: synthesized extensions.bazaar) */
207
+ extensions?: Record<string, unknown>;
208
+ }
209
+ declare const isQueryExtensionConfig: (config: DeclareQueryDiscoveryExtensionConfig | DeclareBodyDiscoveryExtensionConfig) => config is DeclareQueryDiscoveryExtensionConfig;
210
+ declare const isBodyExtensionConfig: (config: DeclareQueryDiscoveryExtensionConfig | DeclareBodyDiscoveryExtensionConfig) => config is DeclareBodyDiscoveryExtensionConfig;
211
+
212
+ /**
213
+ * MCP-specific type definitions for the Bazaar Discovery Extension
214
+ */
215
+
216
+ /**
217
+ * Discovery info for MCP tools
218
+ */
219
+ interface McpDiscoveryInfo {
220
+ input: {
221
+ type: "mcp";
222
+ toolName: string;
223
+ description?: string;
224
+ transport?: string;
225
+ inputSchema: Record<string, unknown>;
226
+ example?: Record<string, unknown>;
227
+ };
228
+ output?: {
229
+ type?: string;
230
+ format?: string;
231
+ example?: unknown;
232
+ };
233
+ }
234
+ /**
235
+ * Discovery extension for MCP tools
236
+ */
237
+ interface McpDiscoveryExtension {
238
+ info: McpDiscoveryInfo;
239
+ schema: {
240
+ $schema: "https://json-schema.org/draft/2020-12/schema";
241
+ type: "object";
242
+ properties: {
243
+ input: {
244
+ type: "object";
245
+ properties: {
246
+ type: {
247
+ type: "string";
248
+ const: "mcp";
249
+ };
250
+ toolName: {
251
+ type: "string";
252
+ };
253
+ description?: {
254
+ type: "string";
255
+ };
256
+ transport?: {
257
+ type: "string";
258
+ enum?: string[];
259
+ };
260
+ inputSchema: Record<string, unknown>;
261
+ example?: Record<string, unknown>;
262
+ };
263
+ required: ("type" | "toolName" | "inputSchema")[];
264
+ additionalProperties?: boolean;
265
+ };
266
+ output?: {
267
+ type: "object";
268
+ properties?: Record<string, unknown>;
269
+ required?: readonly string[];
270
+ additionalProperties?: boolean;
271
+ };
272
+ };
273
+ required: ["input"];
274
+ };
275
+ }
276
+ interface DeclareMcpDiscoveryExtensionConfig {
277
+ toolName: string;
278
+ description?: string;
279
+ transport?: string;
280
+ inputSchema: Record<string, unknown>;
281
+ example?: Record<string, unknown>;
282
+ output?: {
283
+ example?: unknown;
284
+ schema?: Record<string, unknown>;
285
+ };
286
+ }
287
+ interface DiscoveredMCPResource {
288
+ resourceUrl: string;
289
+ description?: string;
290
+ mimeType?: string;
291
+ /** Sanitized service metadata. See `sanitizeResourceServiceMetadata` for rules. */
292
+ serviceName?: string;
293
+ tags?: string[];
294
+ iconUrl?: string;
295
+ toolName: string;
296
+ x402Version: number;
297
+ discoveryInfo: DiscoveryInfo;
298
+ /** Extension payloads for catalog echo (v2: payload.extensions; v1: synthesized extensions.bazaar) */
299
+ extensions?: Record<string, unknown>;
300
+ }
301
+ declare const isMcpExtensionConfig: (config: DeclareMcpDiscoveryExtensionConfig | Record<string, unknown>) => config is DeclareMcpDiscoveryExtensionConfig;
302
+
303
+ /**
304
+ * Shared type definitions for the Bazaar Discovery Extension
305
+ *
306
+ * Protocol-specific types live in their own directories (http/, mcp/).
307
+ * This file defines the shared unions, constants, and utility types,
308
+ * and re-exports all protocol-specific types for backwards compatibility.
309
+ */
310
+
311
+ /**
312
+ * Extension identifier for the Bazaar discovery extension.
313
+ */
314
+ declare const BAZAAR: FacilitatorExtension;
315
+ /**
316
+ * Combined discovery info type
317
+ */
318
+ type DiscoveryInfo = QueryDiscoveryInfo | BodyDiscoveryInfo | McpDiscoveryInfo;
319
+ /**
320
+ * Combined discovery extension type
321
+ */
322
+ type DiscoveryExtension = QueryDiscoveryExtension | BodyDiscoveryExtension | McpDiscoveryExtension;
323
+ type DeclareDiscoveryExtensionConfig = DeclareQueryDiscoveryExtensionConfig | DeclareBodyDiscoveryExtensionConfig | DeclareMcpDiscoveryExtensionConfig;
324
+ /**
325
+ * Distributive Omit - properly distributes Omit over union types.
326
+ *
327
+ * Standard `Omit<A | B, K>` collapses to common properties only,
328
+ * losing discriminant properties like `bodyType`.
329
+ *
330
+ * This type uses conditional type distribution to preserve the union:
331
+ * `DistributiveOmit<A | B, K>` = `Omit<A, K> | Omit<B, K>`
332
+ */
333
+ type DistributiveOmit<T, K extends keyof T> = T extends T ? Omit<T, K> : never;
334
+ /**
335
+ * Config type for declareDiscoveryExtension function.
336
+ * Uses DistributiveOmit to preserve bodyType discriminant in the union for HTTP configs.
337
+ * MCP config has no `method` field so it's included directly.
338
+ */
339
+ type DeclareDiscoveryExtensionInput = DistributiveOmit<DeclareQueryDiscoveryExtensionConfig, "method"> | DistributiveOmit<DeclareBodyDiscoveryExtensionConfig, "method"> | DeclareMcpDiscoveryExtensionConfig;
340
+
341
+ /**
342
+ * Resource Service entry point for creating Bazaar discovery extensions
343
+ *
344
+ * This module provides the unified `declareDiscoveryExtension` function that
345
+ * routes to protocol-specific builders in http/ and mcp/.
346
+ */
347
+
348
+ /**
349
+ * Create a discovery extension for any HTTP method or MCP tool
350
+ *
351
+ * This function helps servers declare how their endpoint should be called,
352
+ * including the expected input parameters/body and output format.
353
+ *
354
+ * @param config - Configuration object for the discovery extension
355
+ * @returns A discovery extension object with both info and schema
356
+ *
357
+ * @example
358
+ * ```typescript
359
+ * // For a GET endpoint with no input
360
+ * const getExtension = declareDiscoveryExtension({
361
+ * method: "GET",
362
+ * output: {
363
+ * example: { message: "Success", timestamp: "2024-01-01T00:00:00Z" }
364
+ * }
365
+ * });
366
+ *
367
+ * // For a GET endpoint with query params
368
+ * const getWithParams = declareDiscoveryExtension({
369
+ * method: "GET",
370
+ * input: { query: "example" },
371
+ * inputSchema: {
372
+ * properties: {
373
+ * query: { type: "string" }
374
+ * },
375
+ * required: ["query"]
376
+ * }
377
+ * });
378
+ *
379
+ * // For a POST endpoint with JSON body
380
+ * const postExtension = declareDiscoveryExtension({
381
+ * method: "POST",
382
+ * input: { name: "John", age: 30 },
383
+ * inputSchema: {
384
+ * properties: {
385
+ * name: { type: "string" },
386
+ * age: { type: "number" }
387
+ * },
388
+ * required: ["name"]
389
+ * },
390
+ * bodyType: "json",
391
+ * output: {
392
+ * example: { success: true, id: "123" }
393
+ * }
394
+ * });
395
+ *
396
+ * // For an MCP tool
397
+ * const mcpExtension = declareDiscoveryExtension({
398
+ * toolName: "financial_analysis",
399
+ * description: "Analyze financial data for a given ticker",
400
+ * inputSchema: {
401
+ * type: "object",
402
+ * properties: {
403
+ * ticker: { type: "string" },
404
+ * },
405
+ * required: ["ticker"],
406
+ * },
407
+ * output: {
408
+ * example: { pe_ratio: 28.5, recommendation: "hold" }
409
+ * }
410
+ * });
411
+ * ```
412
+ */
413
+ declare function declareDiscoveryExtension(config: DeclareDiscoveryExtensionInput): Record<string, DiscoveryExtension>;
414
+
415
+ declare const bazaarResourceServerExtension: ResourceServerExtension;
416
+
417
+ /**
418
+ * Facilitator functions for validating and extracting Bazaar discovery extensions
419
+ *
420
+ * These functions help facilitators validate extension data against schemas
421
+ * and extract the discovery information for cataloging in the Bazaar.
422
+ *
423
+ * Supports both v2 (extensions in PaymentRequired) and v1 (outputSchema in PaymentRequirements).
424
+ */
425
+
426
+ /**
427
+ * Checks whether a routeTemplate value is structurally valid.
428
+ *
429
+ * Expected format: "/:param" segments using colon-prefixed identifiers
430
+ * (e.g. "/users/:userId", "/weather/:country/:city").
431
+ *
432
+ * The facilitator is a trust boundary: clients control the payment payload and
433
+ * can modify routeTemplate before submission. A malicious value could cause the
434
+ * facilitator to catalog the payment under an arbitrary URL (catalog poisoning).
435
+ * This function enforces minimal structural requirements:
436
+ * - Must be a non-empty string starting with "/"
437
+ * - Must match the safe URL path character set (alphanumeric, _, :, /, ., -, ~, %)
438
+ * - Must not contain ".." (path traversal)
439
+ * - Must not contain "://" (URL injection)
440
+ *
441
+ * @param value - The raw routeTemplate string from the client payload
442
+ * @returns true if the value is a valid routeTemplate, false otherwise
443
+ *
444
+ * @internal Exported for facilitator use.
445
+ */
446
+ declare function isValidRouteTemplate(value: string | undefined): value is string;
447
+ /**
448
+ * Validates a routeTemplate and returns it if valid, undefined otherwise.
449
+ *
450
+ * @param value - The raw routeTemplate string to validate
451
+ * @returns The validated value, or undefined if invalid
452
+ * @deprecated Use `isValidRouteTemplate` instead.
453
+ */
454
+ declare function validateRouteTemplate(value: string | undefined): string | undefined;
455
+ /**
456
+ * Checks whether a serviceName value is structurally valid for the bazaar
457
+ * `resource.serviceName` field. Non-empty string of printable ASCII
458
+ * (U+0020–U+007E), length ≤ 32.
459
+ *
460
+ * The ASCII restriction matches the `paymentidentifier.id` convention and
461
+ * keeps `len()` semantics identical across TS / Python / Go.
462
+ *
463
+ * Mirrors `_is_valid_service_name` (Python) and `isValidServiceName` (Go).
464
+ * All three implementations must stay in sync.
465
+ *
466
+ * @param value - The raw serviceName string from the resource object
467
+ * @returns true if the value is a valid serviceName, false otherwise
468
+ *
469
+ * @internal Exported for facilitator use.
470
+ */
471
+ declare function isValidServiceName(value: string | undefined): value is string;
472
+ /**
473
+ * Sanitizes a tags array for the bazaar `resource.tags` field. Drops entries
474
+ * that are not non-empty printable-ASCII strings of at most 32 characters,
475
+ * then truncates to the first 5 valid entries. Returns undefined when no
476
+ * entries survive (so the field can be omitted from the catalog).
477
+ *
478
+ * The ASCII restriction matches the `paymentidentifier.id` convention and
479
+ * keeps `len()` semantics identical across TS / Python / Go.
480
+ *
481
+ * Mirrors `_sanitize_tags` (Python) and `sanitizeTags` (Go).
482
+ * All three implementations must stay in sync.
483
+ *
484
+ * @param value - The raw tags value from the resource object (typed as unknown
485
+ * because callers pass it directly from a parsed JSON payload)
486
+ * @returns The sanitized tags array, or undefined if no entries survive
487
+ *
488
+ * @internal Exported for facilitator use.
489
+ */
490
+ declare function sanitizeTags(value: unknown): string[] | undefined;
491
+ /**
492
+ * Checks whether an iconUrl value is structurally safe for the bazaar
493
+ * `resource.iconUrl` field.
494
+ *
495
+ * Rules (see `specs/extensions/bazaar.md` "Service Metadata on `resource`"):
496
+ * - String of length ≤ 2048
497
+ * - No ASCII control characters
498
+ * - Parses as an absolute http:// or https:// URL
499
+ * - No userinfo (user@host)
500
+ * - Host is IDN-normalized (UTS #46) before checks, so confusable
501
+ * full-width / Unicode forms (e.g. `localhost`) collapse to their
502
+ * ASCII canonical and get caught by the loopback check
503
+ * - Host is not an IP literal (v4 or v6), not in the loopback set
504
+ * (`localhost`, `localhost.localdomain`, `ip6-localhost`, `ip6-loopback`)
505
+ * - Host is not a decimal IP encoding (e.g. `2130706433` → 127.0.0.1) or
506
+ * hex literal (e.g. `0x7f000001`) — common SSRF bypass forms
507
+ *
508
+ * Percent-decoding is applied to the hostname before IDN normalization, and
509
+ * IDN normalization runs before the IP / loopback checks (parallel to the
510
+ * routeTemplate decoder).
511
+ *
512
+ * Mirrors `_is_valid_icon_url` (Python) and `isValidIconUrl` (Go).
513
+ * All three implementations must stay in sync.
514
+ *
515
+ * @param value - The raw iconUrl string from the resource object
516
+ * @returns true if the value is a structurally safe iconUrl, false otherwise
517
+ *
518
+ * @internal Exported for facilitator use.
519
+ */
520
+ declare function isValidIconUrl(value: string | undefined): value is string;
521
+ /**
522
+ * Sanitized service metadata extracted from a `resource` object.
523
+ */
524
+ interface SanitizedResourceServiceMetadata {
525
+ serviceName?: string;
526
+ tags?: string[];
527
+ iconUrl?: string;
528
+ }
529
+ /**
530
+ * Applies the bazaar service-metadata validation rules to a `resource` object
531
+ * and returns only the fields that survive. Missing or invalid fields are
532
+ * dropped silently (soft-drop semantics — see spec).
533
+ *
534
+ * @param resource - The raw `resource` object from a PaymentRequired or
535
+ * PaymentPayload, or undefined.
536
+ * @returns An object containing only the valid serviceName / tags / iconUrl.
537
+ *
538
+ * @internal Exported for facilitator use.
539
+ */
540
+ declare function sanitizeResourceServiceMetadata(resource: ResourceInfo | undefined | null): SanitizedResourceServiceMetadata;
541
+ /**
542
+ * Validation result for discovery extensions
543
+ */
544
+ interface ValidationResult {
545
+ valid: boolean;
546
+ errors?: string[];
547
+ }
548
+ /**
549
+ * Validates a discovery extension's info against its schema
550
+ *
551
+ * @param extension - The discovery extension containing info and schema
552
+ * @returns Validation result indicating if the info matches the schema
553
+ *
554
+ * @example
555
+ * ```typescript
556
+ * const extension = declareDiscoveryExtension(...);
557
+ * const result = validateDiscoveryExtension(extension);
558
+ *
559
+ * if (result.valid) {
560
+ * console.log("Extension is valid");
561
+ * } else {
562
+ * console.error("Validation errors:", result.errors);
563
+ * }
564
+ * ```
565
+ */
566
+ declare function validateDiscoveryExtension(extension: DiscoveryExtension): ValidationResult;
567
+ /**
568
+ * Validates a discovery extension against the Bazaar protocol specification.
569
+ *
570
+ * Unlike `validateDiscoveryExtension` which checks internal consistency (info vs schema),
571
+ * this function enforces protocol-level invariants:
572
+ * - `info.input.type` must be "http" or "mcp"
573
+ * - HTTP: if `method` is present it must be GET/POST/PUT/PATCH/DELETE/HEAD
574
+ * - HTTP body methods: `bodyType` must be "json" | "form-data" | "text"
575
+ * - MCP: `toolName` (string) and `inputSchema` (object) are required
576
+ * - MCP: if `transport` is present it must be "streamable-http" | "sse"
577
+ *
578
+ * Designed to be safe for pre-enrichment HTTP extensions where `method` may be absent.
579
+ *
580
+ * @param extension - The discovery extension to validate
581
+ * @returns Validation result with spec-level errors
582
+ */
583
+ declare function validateDiscoveryExtensionSpec(extension: Record<string, unknown>): ValidationResult;
584
+
585
+ type DiscoveredResource = DiscoveredHTTPResource | DiscoveredMCPResource;
586
+ /**
587
+ * Extracts discovery information from payment payload and requirements.
588
+ * Combines resource URL, HTTP method, version, and discovery info into a single object.
589
+ *
590
+ * @param paymentPayload - The payment payload containing extensions and resource info
591
+ * @param paymentRequirements - The payment requirements to validate against
592
+ * @param validate - Whether to validate the discovery info against the schema (default: true)
593
+ * @returns Discovered resource info with URL, method, version, discovery data, and catalog
594
+ * extensions echo (v2: `paymentPayload.extensions`; v1: synthesized `extensions.bazaar`
595
+ * from requirements outputSchema), or null if not found
596
+ */
597
+ declare function extractDiscoveryInfo(paymentPayload: PaymentPayload, paymentRequirements: PaymentRequirements | PaymentRequirementsV1, validate?: boolean): DiscoveredResource | null;
598
+ /**
599
+ * Extracts discovery info from a v2 extension directly
600
+ *
601
+ * This is a lower-level function for when you already have the extension object.
602
+ * For general use, prefer the main extractDiscoveryInfo function.
603
+ *
604
+ * @param extension - The discovery extension to extract info from
605
+ * @param validate - Whether to validate before extracting (default: true)
606
+ * @returns The discovery info if valid
607
+ * @throws Error if validation fails and validate is true
608
+ */
609
+ declare function extractDiscoveryInfoFromExtension(extension: DiscoveryExtension, validate?: boolean): DiscoveryInfo;
610
+ /**
611
+ * Validates and extracts discovery info in one step
612
+ *
613
+ * This is a convenience function that combines validation and extraction,
614
+ * returning both the validation result and the info if valid.
615
+ *
616
+ * @param extension - The discovery extension to validate and extract
617
+ * @returns Object containing validation result and info (if valid)
618
+ *
619
+ * @example
620
+ * ```typescript
621
+ * const extension = declareDiscoveryExtension(...);
622
+ * const { valid, info, errors } = validateAndExtract(extension);
623
+ *
624
+ * if (valid && info) {
625
+ * // Store info in Bazaar catalog
626
+ * } else {
627
+ * console.error("Validation errors:", errors);
628
+ * }
629
+ * ```
630
+ */
631
+ declare function validateAndExtract(extension: DiscoveryExtension): {
632
+ valid: boolean;
633
+ info?: DiscoveryInfo;
634
+ errors?: string[];
635
+ };
636
+
637
+ /**
638
+ * V1 Facilitator functions for extracting Bazaar discovery information
639
+ *
640
+ * In v1, discovery information is stored in the `outputSchema` field
641
+ * of PaymentRequirements, which has a different structure than v2.
642
+ *
643
+ * This module transforms v1 data into v2 DiscoveryInfo format.
644
+ */
645
+
646
+ /**
647
+ * Extracts discovery info from v1 PaymentRequirements and transforms to v2 format
648
+ *
649
+ * In v1, the discovery information is stored in the `outputSchema` field,
650
+ * which contains both input (endpoint shape) and output (response schema) information.
651
+ *
652
+ * This function makes smart assumptions to normalize v1 data into v2 DiscoveryInfo format:
653
+ * - For GET/HEAD/DELETE: Looks for queryParams, query, or params fields
654
+ * - For POST/PUT/PATCH: Looks for bodyFields, body, or data fields and normalizes bodyType
655
+ * - Extracts optional headers if present
656
+ *
657
+ * @param paymentRequirements - V1 payment requirements
658
+ * @returns Discovery info in v2 format if present and valid, or null if not discoverable
659
+ *
660
+ * @example
661
+ * ```typescript
662
+ * const requirements: PaymentRequirementsV1 = {
663
+ * scheme: "exact",
664
+ * network: "eip155:8453",
665
+ * maxAmountRequired: "100000",
666
+ * resource: "https://api.example.com/data",
667
+ * description: "Get data",
668
+ * mimeType: "application/json",
669
+ * outputSchema: {
670
+ * input: {
671
+ * type: "http",
672
+ * method: "GET",
673
+ * discoverable: true,
674
+ * queryParams: { query: "string" }
675
+ * },
676
+ * output: { type: "object" }
677
+ * },
678
+ * payTo: "0x...",
679
+ * maxTimeoutSeconds: 300,
680
+ * asset: "0x...",
681
+ * extra: {}
682
+ * };
683
+ *
684
+ * const info = extractDiscoveryInfoV1(requirements);
685
+ * if (info) {
686
+ * console.log("Endpoint method:", info.input.method);
687
+ * }
688
+ * ```
689
+ */
690
+ declare function extractDiscoveryInfoV1(paymentRequirements: PaymentRequirementsV1): DiscoveryInfo | null;
691
+ /**
692
+ * Checks if v1 PaymentRequirements contains discoverable information
693
+ *
694
+ * @param paymentRequirements - V1 payment requirements
695
+ * @returns True if the requirements contain valid discovery info
696
+ *
697
+ * @example
698
+ * ```typescript
699
+ * if (isDiscoverableV1(requirements)) {
700
+ * const info = extractDiscoveryInfoV1(requirements);
701
+ * // Catalog info in Bazaar
702
+ * }
703
+ * ```
704
+ */
705
+ declare function isDiscoverableV1(paymentRequirements: PaymentRequirementsV1): boolean;
706
+ /**
707
+ * Extracts resource metadata from v1 PaymentRequirements
708
+ *
709
+ * In v1, resource information is embedded directly in the payment requirements
710
+ * rather than in a separate resource object.
711
+ *
712
+ * @param paymentRequirements - V1 payment requirements
713
+ * @returns Resource metadata
714
+ *
715
+ * @example
716
+ * ```typescript
717
+ * const metadata = extractResourceMetadataV1(requirements);
718
+ * console.log("Resource URL:", metadata.url);
719
+ * console.log("Description:", metadata.description);
720
+ * ```
721
+ */
722
+ declare function extractResourceMetadataV1(paymentRequirements: PaymentRequirementsV1): {
723
+ url: string;
724
+ description: string;
725
+ mimeType: string;
726
+ };
727
+
728
+ /**
729
+ * Shared startup-time validation utilities for bazaar extensions in route configs.
730
+ *
731
+ * Used by middleware packages (Express, Hono, Next) to validate bazaar extensions
732
+ * at server startup without duplicating the iteration and warning logic.
733
+ */
734
+
735
+ /**
736
+ * Validate bazaar extensions on all routes using JSON-schema validation.
737
+ * Emits console warnings for invalid extensions but does not throw.
738
+ *
739
+ * @param routes - Route configuration to scan for bazaar extensions
740
+ */
741
+ declare function validateBazaarRouteExtensions(routes: RoutesConfig): void;
742
+
743
+ /**
744
+ * Client extensions for querying Bazaar discovery resources
745
+ */
746
+
747
+ /**
748
+ * Parameters for listing discovery resources.
749
+ * All parameters are optional and used for filtering/pagination.
750
+ */
751
+ interface ListDiscoveryResourcesParams {
752
+ /**
753
+ * Filter by protocol type (e.g., "http", "mcp").
754
+ */
755
+ type?: string;
756
+ /**
757
+ * Filter by payment recipient address.
758
+ */
759
+ payTo?: string;
760
+ /**
761
+ * Filter by payment scheme (e.g., "exact").
762
+ */
763
+ scheme?: string;
764
+ /**
765
+ * Filter by payment network (e.g., "eip155:8453").
766
+ */
767
+ network?: string;
768
+ /**
769
+ * Filter by extension key present on the discovered resource.
770
+ */
771
+ extensions?: string;
772
+ /**
773
+ * The number of discovered x402 resources to return per page.
774
+ */
775
+ limit?: number;
776
+ /**
777
+ * The offset of the first discovered x402 resource to return.
778
+ */
779
+ offset?: number;
780
+ }
781
+ /**
782
+ * Parameters for searching discovery resources.
783
+ */
784
+ interface SearchDiscoveryResourcesParams {
785
+ /**
786
+ * Natural-language search query.
787
+ */
788
+ query: string;
789
+ /**
790
+ * Filter by protocol type (e.g., "http", "mcp").
791
+ */
792
+ type?: string;
793
+ /**
794
+ * Filter by payment recipient address.
795
+ */
796
+ payTo?: string;
797
+ /**
798
+ * Filter by payment scheme (e.g., "exact").
799
+ */
800
+ scheme?: string;
801
+ /**
802
+ * Filter by payment network (e.g., "eip155:8453").
803
+ */
804
+ network?: string;
805
+ /**
806
+ * Filter by extension key present on the discovered resource.
807
+ */
808
+ extensions?: string;
809
+ /**
810
+ * Advisory maximum number of results. The server may return fewer or ignore this.
811
+ */
812
+ limit?: number;
813
+ /**
814
+ * Advisory continuation cursor from a previous response. The server may ignore this.
815
+ */
816
+ cursor?: string;
817
+ }
818
+ /**
819
+ * A discovered x402 resource from the bazaar.
820
+ */
821
+ interface DiscoveryResource {
822
+ /** The URL or identifier of the discovered resource */
823
+ resource: string;
824
+ /** The protocol type of the resource (e.g., "http") */
825
+ type: string;
826
+ /** The x402 protocol version supported by this resource */
827
+ x402Version: number;
828
+ /** Array of accepted payment methods for this resource */
829
+ accepts: PaymentRequirements[];
830
+ /** ISO 8601 timestamp of when the resource was last updated */
831
+ lastUpdated: string;
832
+ /** Human-readable description of the resource */
833
+ description?: string;
834
+ /** MIME type of the resource response */
835
+ mimeType?: string;
836
+ /** Human-readable name for the service hosting the resource */
837
+ serviceName?: string;
838
+ /** Short topical tags for discovery search */
839
+ tags?: string[];
840
+ /** Absolute http(s) URL to a service icon */
841
+ iconUrl?: string;
842
+ /** Extension payloads echoed from discovery (e.g. bazaar info/schema) */
843
+ extensions?: Record<string, unknown>;
844
+ }
845
+ /**
846
+ * Response from listing discovery resources.
847
+ */
848
+ interface DiscoveryResourcesResponse {
849
+ /** The x402 protocol version of this response */
850
+ x402Version: number;
851
+ /** The list of discovered resources */
852
+ items: DiscoveryResource[];
853
+ /** Pagination information for the response */
854
+ pagination: {
855
+ /** Maximum number of results returned */
856
+ limit: number;
857
+ /** Number of results skipped */
858
+ offset: number;
859
+ /** Total count of resources matching the query */
860
+ total: number;
861
+ };
862
+ }
863
+ /**
864
+ * Response from searching discovery resources.
865
+ */
866
+ interface SearchDiscoveryResourcesResponse {
867
+ /** The x402 protocol version of this response */
868
+ x402Version: number;
869
+ /** The list of matching discovered resources */
870
+ resources: DiscoveryResource[];
871
+ /** Whether additional matches were truncated by facilitator */
872
+ partialResults?: boolean;
873
+ /** Optional pagination details when a paginated response is returned */
874
+ pagination?: {
875
+ /** Number of results in this page */
876
+ limit: number;
877
+ /** Continuation cursor for the next page; may be null */
878
+ cursor: string | null;
879
+ } | null;
880
+ }
881
+ /**
882
+ * Bazaar client extension interface providing discovery query functionality.
883
+ */
884
+ interface BazaarClientExtension {
885
+ bazaar: {
886
+ /**
887
+ * List x402 discovery resources from the bazaar.
888
+ *
889
+ * @param params - Optional filtering and pagination parameters
890
+ * @returns A promise resolving to the discovery resources response
891
+ */
892
+ listResources(params?: ListDiscoveryResourcesParams): Promise<DiscoveryResourcesResponse>;
893
+ /**
894
+ * Search x402 discovery resources from the bazaar using a natural-language query.
895
+ *
896
+ * Pagination is optional: facilitators may ignore `limit` and `cursor`, or include
897
+ * `response.pagination` when pagination is used.
898
+ *
899
+ * @param params - Search parameters including the required query string
900
+ * @returns A promise resolving to the search response
901
+ */
902
+ search(params: SearchDiscoveryResourcesParams): Promise<SearchDiscoveryResourcesResponse>;
903
+ };
904
+ }
905
+ /**
906
+ * Extends a facilitator client with Bazaar discovery query functionality.
907
+ * Preserves and merges with any existing extensions from prior chaining.
908
+ *
909
+ * @param client - The facilitator client to extend
910
+ * @returns The client extended with bazaar discovery capabilities
911
+ *
912
+ * @example
913
+ * ```ts
914
+ * // Basic usage
915
+ * const client = withBazaar(new HTTPFacilitatorClient());
916
+ * const resources = await client.extensions.bazaar.listResources({ type: "http" });
917
+ *
918
+ * // Search
919
+ * const results = await client.extensions.bazaar.search({ query: "weather APIs" });
920
+ *
921
+ * // Chaining with other extensions
922
+ * const client = withBazaar(withOtherExtension(new HTTPFacilitatorClient()));
923
+ * await client.extensions.other.someMethod();
924
+ * await client.extensions.bazaar.listResources();
925
+ * ```
926
+ */
927
+ declare function withBazaar<T extends HTTPFacilitatorClient>(client: T): WithExtensions<T, BazaarClientExtension>;
928
+
929
+ export { type DiscoveredHTTPResource as A, type BodyDiscoveryInfo as B, type DiscoveredMCPResource as C, type DiscoveryInfo as D, type DiscoveredResource as E, extractDiscoveryInfoV1 as F, isDiscoverableV1 as G, extractResourceMetadataV1 as H, validateBazaarRouteExtensions as I, withBazaar as J, type BazaarClientExtension as K, type ListDiscoveryResourcesParams as L, type McpDiscoveryInfo as M, type SearchDiscoveryResourcesParams as N, type DiscoveryResource as O, type DiscoveryResourcesResponse as P, type QueryDiscoveryInfo as Q, type SearchDiscoveryResourcesResponse as R, type SanitizedResourceServiceMetadata as S, type ValidationResult as V, type WithExtensions as W, type QueryDiscoveryExtension as a, bazaarResourceServerExtension as b, type BodyDiscoveryExtension as c, type McpDiscoveryExtension as d, type DiscoveryExtension as e, type DeclareQueryDiscoveryExtensionConfig as f, type DeclareBodyDiscoveryExtensionConfig as g, type DeclareMcpDiscoveryExtensionConfig as h, type DeclareDiscoveryExtensionConfig as i, type DeclareDiscoveryExtensionInput as j, BAZAAR as k, isMcpExtensionConfig as l, isQueryExtensionConfig as m, isBodyExtensionConfig as n, declareDiscoveryExtension as o, isValidRouteTemplate as p, validateRouteTemplate as q, isValidServiceName as r, sanitizeTags as s, isValidIconUrl as t, sanitizeResourceServiceMetadata as u, validateDiscoveryExtension as v, validateDiscoveryExtensionSpec as w, extractDiscoveryInfo as x, extractDiscoveryInfoFromExtension as y, validateAndExtract as z };