{"_id":"@aeon-ai-pay/extensions","name":"@aeon-ai-pay/extensions","dist-tags":{"latest":"2.1.0"},"versions":{"2.1.0":{"name":"@aeon-ai-pay/extensions","version":"2.1.0","main":"./dist/cjs/index.js","module":"./dist/esm/index.js","types":"./dist/cjs/index.d.ts","keywords":["x402","payment","protocol","extensions"],"license":"Apache-2.0","author":{"name":"Coinbase Inc."},"repository":{"type":"git","url":"git+https://github.com/coinbase/x402.git"},"description":"x402 Payment Protocol Extensions","devDependencies":{"@eslint/js":"^9.24.0","@types/node":"^22.13.4","@typescript-eslint/eslint-plugin":"^8.29.1","@typescript-eslint/parser":"^8.29.1","eslint":"^9.24.0","eslint-plugin-import":"^2.31.0","eslint-plugin-jsdoc":"^50.6.9","eslint-plugin-prettier":"^5.2.6","prettier":"3.5.2","tsup":"^8.4.0","tsx":"^4.19.2","typescript":"^5.7.3","vite":"^6.2.6","vite-tsconfig-paths":"^5.1.4","vitest":"^3.0.5"},"dependencies":{"ajv":"^8.17.1","zod":"^3.24.2","@aeon-ai-pay/core":"2.1.0"},"exports":{".":{"import":{"types":"./dist/esm/index.d.mts","default":"./dist/esm/index.mjs"},"require":{"types":"./dist/cjs/index.d.ts","default":"./dist/cjs/index.js"}},"./bazaar":{"import":{"types":"./dist/esm/bazaar/index.d.mts","default":"./dist/esm/bazaar/index.mjs"},"require":{"types":"./dist/cjs/bazaar/index.d.ts","default":"./dist/cjs/bazaar/index.js"}},"./sign-in-with-x":{"import":{"types":"./dist/esm/sign-in-with-x/index.d.mts","default":"./dist/esm/sign-in-with-x/index.mjs"},"require":{"types":"./dist/cjs/sign-in-with-x/index.d.ts","default":"./dist/cjs/sign-in-with-x/index.js"}}},"publishConfig":{"access":"public"},"scripts":{"start":"tsx --env-file=.env index.ts","build":"tsup","test":"vitest run","test:watch":"vitest","watch":"tsc --watch","format":"prettier -c .prettierrc --write \"**/*.{ts,js,cjs,json,md}\"","format:check":"prettier -c .prettierrc --check \"**/*.{ts,js,cjs,json,md}\"","lint":"eslint . --ext .ts --fix","lint:check":"eslint . --ext .ts"},"_id":"@aeon-ai-pay/extensions@2.1.0","bugs":{"url":"https://github.com/coinbase/x402/issues"},"homepage":"https://github.com/coinbase/x402#readme","_integrity":"sha512-Ad3OC6Fl8iU1VPAilf5RYRYyNdZphlYiOc9uoYQwHlw0tAOA8M+xH5x3FZMYOwqIh8ZutluJBzxaM+Nk9PaaNQ==","_resolved":"/private/var/folders/rr/hyts0bs54zn73fgjjlld0tvm0000gn/T/4f518ab1e749d96396aacb98515c17b9/aeon-ai-pay-extensions-2.1.0.tgz","_from":"file:aeon-ai-pay-extensions-2.1.0.tgz","_nodeVersion":"25.8.1","_npmVersion":"11.11.0","dist":{"integrity":"sha512-Ad3OC6Fl8iU1VPAilf5RYRYyNdZphlYiOc9uoYQwHlw0tAOA8M+xH5x3FZMYOwqIh8ZutluJBzxaM+Nk9PaaNQ==","shasum":"7e85cda9c63b920b08dda752a46dc3662fbce111","tarball":"https://registry.npmjs.org/@aeon-ai-pay/extensions/-/extensions-2.1.0.tgz","fileCount":24,"unpackedSize":240847,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIASKsvCstNi8z5F1AvRxeSNkPSM2EE0ty6t1/gecrZVcAiEA9mH34CNxHTo8QAnmVGBkOYG2SBBIgwXWJ/fUHZzWd9E="}]},"_npmUser":{"name":"aeon_project","email":"code@alchemypay.org"},"directories":{},"maintainers":[{"name":"aeon_project","email":"code@alchemypay.org"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/extensions_2.1.0_1775096312215_0.5332436734236221"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-02T02:18:32.129Z","2.1.0":"2026-04-02T02:18:32.369Z","modified":"2026-04-02T02:18:32.582Z"},"maintainers":[{"name":"aeon_project","email":"code@alchemypay.org"}],"description":"x402 Payment Protocol Extensions","homepage":"https://github.com/coinbase/x402#readme","keywords":["x402","payment","protocol","extensions"],"repository":{"type":"git","url":"git+https://github.com/coinbase/x402.git"},"author":{"name":"Coinbase Inc."},"bugs":{"url":"https://github.com/coinbase/x402/issues"},"license":"Apache-2.0","readme":"# @x402/extensions\n\nx402 Payment Protocol Extensions. This package provides optional extensions that enhance the x402 payment protocol with additional functionality like resource discovery and cataloging.\n\n## Installation\n\n```bash\npnpm install @x402/extensions\n```\n\n## Overview\n\nExtensions are optional features that can be added to x402 payment flows. They allow servers to provide additional metadata and enable facilitators to offer enhanced services like resource discovery and cataloging.\n\nCurrently, this package includes:\n- **Bazaar Discovery Extension**: Enables automatic cataloging and indexing of x402-enabled resources\n\n## Bazaar Discovery Extension\n\nThe Bazaar Discovery Extension enables facilitators to automatically catalog and index x402-enabled resources by following server-declared discovery instructions. This allows users to discover paid APIs and services through facilitator catalogs.\n\n### How It Works\n\n1. **Servers** declare discovery metadata when configuring their payment endpoints\n2. The HTTP method is automatically inferred from the route definition (e.g., `\"GET /weather\"`)\n3. **Facilitators** extract this metadata from payment requests\n4. **Users** can browse and discover available paid resources through facilitator catalogs\n\n### For Resource Servers\n\nDeclare endpoint discovery metadata in your payment middleware configuration. This helps facilitators understand how to call your endpoints and what they return.\n\n> **Note:** The HTTP method is automatically inferred from the route key (e.g., `\"GET /weather\"` → GET method). You don't need to specify it in `declareDiscoveryExtension`.\n\n#### Basic Example: GET Endpoint with Query Parameters\n\n```typescript\nimport { declareDiscoveryExtension } from \"@x402/extensions/bazaar\";\n\nconst resources = {\n  \"GET /weather\": {\n    accepts: { \n      scheme: \"exact\", \n      price: \"$0.001\", \n      network: \"eip155:84532\", \n      payTo: \"0xYourAddress\" \n    },\n    extensions: {\n      ...declareDiscoveryExtension({\n        input: { city: \"San Francisco\" },\n        inputSchema: {\n          properties: { \n            city: { type: \"string\" },\n            units: { type: \"string\", enum: [\"celsius\", \"fahrenheit\"] }\n          },\n          required: [\"city\"]\n        },\n        output: { \n          example: { \n            city: \"San Francisco\", \n            weather: \"foggy\",\n            temperature: 15,\n            humidity: 85\n          } \n        },\n      }),\n    },\n  },\n};\n```\n\n#### Example: POST Endpoint with JSON Body\n\nFor POST, PUT, and PATCH endpoints, specify `bodyType` to indicate the request body format:\n\n```typescript\nimport { declareDiscoveryExtension } from \"@x402/extensions/bazaar\";\n\nconst resources = {\n  \"POST /api/translate\": {\n    accepts: { \n      scheme: \"exact\", \n      price: \"$0.01\", \n      network: \"eip155:84532\", \n      payTo: \"0xYourAddress\" \n    },\n    extensions: {\n      ...declareDiscoveryExtension({\n        input: { \n          text: \"Hello, world!\",\n          targetLanguage: \"es\"\n        },\n        inputSchema: {\n          properties: {\n            text: { type: \"string\" },\n            targetLanguage: { type: \"string\", pattern: \"^[a-z]{2}$\" }\n          },\n          required: [\"text\", \"targetLanguage\"]\n        },\n        bodyType: \"json\",\n        output: {\n          example: {\n            translatedText: \"¡Hola, mundo!\",\n            sourceLanguage: \"en\",\n            targetLanguage: \"es\"\n          }\n        },\n      }),\n    },\n  },\n};\n```\n\n#### Example: PUT Endpoint with Form Data\n\n```typescript\nconst resources = {\n  \"PUT /api/user/profile\": {\n    accepts: { \n      scheme: \"exact\", \n      price: \"$0.05\", \n      network: \"eip155:84532\", \n      payTo: \"0xYourAddress\" \n    },\n    extensions: {\n      ...declareDiscoveryExtension({\n        input: { \n          name: \"John Doe\",\n          email: \"john@example.com\",\n          bio: \"Software developer\"\n        },\n        inputSchema: {\n          properties: {\n            name: { type: \"string\", minLength: 1 },\n            email: { type: \"string\", format: \"email\" },\n            bio: { type: \"string\", maxLength: 500 }\n          },\n          required: [\"name\", \"email\"]\n        },\n        bodyType: \"form-data\",\n        output: {\n          example: {\n            success: true,\n            userId: \"123\",\n            updatedAt: \"2024-01-01T00:00:00Z\"\n          }\n        },\n      }),\n    },\n  },\n};\n```\n\n#### Example: DELETE Endpoint\n\n```typescript\nconst resources = {\n  \"DELETE /api/data/:id\": {\n    accepts: { \n      scheme: \"exact\", \n      price: \"$0.001\", \n      network: \"eip155:84532\", \n      payTo: \"0xYourAddress\" \n    },\n    extensions: {\n      ...declareDiscoveryExtension({\n        input: { id: \"123\" },\n        inputSchema: {\n          properties: {\n            id: { type: \"string\" }\n          },\n          required: [\"id\"]\n        },\n        output: {\n          example: {\n            success: true,\n            deletedId: \"123\"\n          }\n        },\n      }),\n    },\n  },\n};\n```\n\n#### Using with Next.js Middleware\n\n```typescript\nimport { paymentProxy, x402ResourceServer } from \"@x402/next\";\nimport { HTTPFacilitatorClient } from \"@x402/core/http\";\nimport { ExactEvmScheme } from \"@x402/evm/exact/server\";\nimport { declareDiscoveryExtension } from \"@x402/extensions/bazaar\";\n\nconst facilitatorClient = new HTTPFacilitatorClient({ url: \"https://facilitator.x402.org\" });\nconst resourceServer = new x402ResourceServer(facilitatorClient)\n  .register(\"eip155:84532\", new ExactEvmScheme());\n\nexport const proxy = paymentProxy(\n  {\n    \"/api/weather\": {\n      accepts: {\n        scheme: \"exact\",\n        price: \"$0.001\",\n        network: \"eip155:84532\",\n        payTo: \"0xYourAddress\",\n      },\n      extensions: {\n        ...declareDiscoveryExtension({\n          input: { city: \"San Francisco\" },\n          inputSchema: {\n            properties: { city: { type: \"string\" } },\n            required: [\"city\"],\n          },\n          output: {\n            example: { city: \"San Francisco\", weather: \"foggy\" }\n          },\n        }),\n      },\n    },\n  },\n  resourceServer,\n);\n```\n\n### For Facilitators\n\nExtract discovery information from incoming payment requests to catalog resources in the Bazaar.\n\n#### Basic Usage\n\n```typescript\nimport { extractDiscoveryInfo } from \"@x402/extensions/bazaar\";\nimport type { PaymentPayload, PaymentRequirements } from \"@x402/core/types\";\n\nasync function handlePayment(\n  paymentPayload: PaymentPayload,\n  paymentRequirements: PaymentRequirements\n) {\n  // Extract discovery info from the payment\n  const discovered = extractDiscoveryInfo(paymentPayload, paymentRequirements);\n\n  if (discovered) {\n    // discovered contains:\n    // {\n    //   resourceUrl: \"https://api.example.com/weather\",\n    //   method: \"GET\",\n    //   x402Version: 2,\n    //   discoveryInfo: {\n    //     input: { type: \"http\", method: \"GET\", queryParams: { city: \"...\" } },\n    //     output: { type: \"json\", example: { ... } }\n    //   }\n    // }\n\n    // Catalog the resource in your Bazaar\n    await catalogResource({\n      url: discovered.resourceUrl,\n      method: discovered.method,\n      inputSchema: discovered.discoveryInfo.input,\n      outputExample: discovered.discoveryInfo.output?.example,\n    });\n  }\n}\n```\n\n#### Validating Discovery Extensions\n\n```typescript\nimport { validateDiscoveryExtension, extractDiscoveryInfo } from \"@x402/extensions/bazaar\";\n\nfunction processPayment(paymentPayload: PaymentPayload, paymentRequirements: PaymentRequirements) {\n  const discovered = extractDiscoveryInfo(paymentPayload, paymentRequirements);\n  \n  if (discovered && paymentPayload.extensions?.bazaar) {\n    // Validate the extension schema\n    const validation = validateDiscoveryExtension(paymentPayload.extensions.bazaar);\n    \n    if (!validation.valid) {\n      console.warn(\"Invalid discovery extension:\", validation.errors);\n      // Handle invalid extension (log, reject, etc.)\n      return;\n    }\n    \n    // Extension is valid, proceed with cataloging\n    catalogResource(discovered);\n  }\n}\n```\n\n#### Using with Server Extension Helper\n\nThe `bazaarResourceServerExtension` automatically enriches discovery extensions with HTTP method information from the request context:\n\n```typescript\nimport { bazaarResourceServerExtension } from \"@x402/extensions/bazaar\";\nimport { x402ResourceServer } from \"@x402/core/server\";\n\n// The extension helper automatically extracts discovery info\nconst resourceServer = new x402ResourceServer(facilitatorClient)\n  .register(\"eip155:84532\", new ExactEvmScheme())\n  .useExtension(bazaarResourceServerExtension);\n```\n\n## API Reference\n\n### `declareDiscoveryExtension(config)`\n\nCreates a discovery extension object for resource servers.\n\n**Parameters:**\n- `config.input` (optional): Example input values (query params for GET/HEAD/DELETE, body for POST/PUT/PATCH)\n- `config.inputSchema` (optional): JSON Schema for input validation\n- `config.bodyType` (optional): For POST/PUT/PATCH, specify `\"json\"`, `\"form-data\"`, or `\"text\"` (default: `\"json\"`)\n- `config.output` (optional): Output specification\n  - `output.example`: Example output data\n  - `output.schema`: JSON Schema for output validation\n\n> **Note:** The HTTP method is NOT passed to this function. It is automatically inferred from the route key (e.g., `\"GET /weather\"`) or enriched by `bazaarResourceServerExtension` at runtime.\n\n**Returns:** An object with a `bazaar` key containing the discovery extension.\n\n**Example:**\n```typescript\nconst extension = declareDiscoveryExtension({\n  input: { query: \"search term\" },\n  inputSchema: {\n    properties: { query: { type: \"string\" } },\n    required: [\"query\"]\n  },\n  output: {\n    example: { results: [] }\n  }\n});\n// Returns: { bazaar: { info: {...}, schema: {...} } }\n```\n\n### `extractDiscoveryInfo(paymentPayload, paymentRequirements, validate?)`\n\nExtracts discovery information from a payment request (for facilitators).\n\n**Parameters:**\n- `paymentPayload`: The payment payload from the client\n- `paymentRequirements`: The payment requirements from the server\n- `validate` (optional): Whether to validate the extension (default: `true`)\n\n**Returns:** `DiscoveredResource` object or `null` if not found.\n\n```typescript\ninterface DiscoveredResource {\n  resourceUrl: string;\n  method: string;\n  x402Version: number;\n  discoveryInfo: DiscoveryInfo;\n}\n```\n\n**Example:**\n```typescript\nconst info = extractDiscoveryInfo(paymentPayload, paymentRequirements);\nif (info) {\n  console.log(info.resourceUrl); // \"https://api.example.com/endpoint\"\n  console.log(info.method);       // \"GET\"\n  console.log(info.discoveryInfo); // { input: {...}, output: {...} }\n}\n```\n\n### `validateDiscoveryExtension(extension)`\n\nValidates a discovery extension's info against its schema.\n\n**Parameters:**\n- `extension`: A discovery extension object\n\n**Returns:** `{ valid: boolean, errors?: string[] }`\n\n**Example:**\n```typescript\nconst result = validateDiscoveryExtension(extension);\nif (!result.valid) {\n  console.error(\"Validation errors:\", result.errors);\n}\n```\n\n### `validateAndExtract(extension)`\n\nValidates and extracts discovery info in one step.\n\n**Parameters:**\n- `extension`: A discovery extension object\n\n**Returns:** `{ valid: boolean, info?: DiscoveryInfo, errors?: string[] }`\n\n**Example:**\n```typescript\nconst { valid, info, errors } = validateAndExtract(extension);\nif (valid && info) {\n  // Use info\n}\n```\n\n### `bazaarResourceServerExtension`\n\nA server extension that automatically enriches discovery extensions with HTTP method information from the request context.\n\n**Usage:**\n```typescript\nimport { bazaarResourceServerExtension } from \"@x402/extensions/bazaar\";\n\nconst resourceServer = new x402ResourceServer(facilitatorClient)\n  .useExtension(bazaarResourceServerExtension);\n```\n\n### `BAZAAR`\n\nThe extension identifier constant (`\"bazaar\"`).\n\n```typescript\nimport { BAZAAR } from \"@x402/extensions/bazaar\";\n// BAZAAR === \"bazaar\"\n```\n\n## Use Cases\n\n### 1. API Marketplace Discovery\nEnable users to discover paid APIs through facilitator catalogs. Servers declare their endpoints, and facilitators index them for easy discovery.\n\n### 2. Developer Tools\nBuild tools that automatically generate API documentation or client SDKs from discovery metadata.\n\n### 3. Resource Cataloging\nFacilitators can maintain catalogs of available paid resources, making it easier for users to find services.\n\n### 4. Testing and Validation\nUse discovery schemas to validate API requests and responses during development.\n\n## Troubleshooting\n\n### Extension Not Being Extracted\n\n**Problem:** `extractDiscoveryInfo` returns `null`.\n\n**Solutions:**\n- Ensure the server has declared the extension using `declareDiscoveryExtension`\n- Check that `paymentPayload.extensions.bazaar` exists\n- Verify you're using x402 v2 (v1 uses a different format in `outputSchema`)\n\n### Schema Validation Fails\n\n**Problem:** `validateDiscoveryExtension` returns `valid: false`.\n\n**Solutions:**\n- Ensure `inputSchema` matches the structure of `input`\n- Check that required fields are marked in `inputSchema.required`\n- Verify JSON Schema syntax is correct\n\n### Missing Discovery Info\n\n**Problem:** Discovery info is incomplete.\n\n**Solutions:**\n- Ensure both `input` and `inputSchema` are provided\n- For POST/PUT/PATCH, include `bodyType` in the config\n- Check that `output.example` is provided if you want output documentation\n\n### Method Not Being Detected\n\n**Problem:** The HTTP method is missing from discovery info.\n\n**Solutions:**\n- Use `bazaarResourceServerExtension` which automatically injects the method\n- Ensure the route key follows the format `\"METHOD /path\"` (e.g., `\"GET /weather\"`)\n\n## Related Resources\n\n- [x402 Core Package](../core/README.md) - Core x402 protocol implementation\n- [x402 Specification](../../../specs/x402-specification.md) - Full protocol specification\n\n## Version Support\n\nThis package supports both x402 v1 and v2:\n- **v2**: Extensions are in `PaymentPayload.extensions` and `PaymentRequired.extensions`\n- **v1**: Discovery info is in `PaymentRequirements.outputSchema` (automatically converted)\n\nThe `extractDiscoveryInfo` function automatically handles both versions.\n","readmeFilename":"README.md","_rev":"1-aa90367e660fb5587f8e368c391d9ba0"}