@x402/extensions 2.3.0 → 2.4.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.
package/dist/cjs/index.js CHANGED
@@ -31,6 +31,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  var src_exports = {};
32
32
  __export(src_exports, {
33
33
  BAZAAR: () => BAZAAR,
34
+ EIP2612_GAS_SPONSORING: () => EIP2612_GAS_SPONSORING,
34
35
  InMemorySIWxStorage: () => InMemorySIWxStorage,
35
36
  PAYMENT_IDENTIFIER: () => PAYMENT_IDENTIFIER,
36
37
  PAYMENT_ID_MAX_LENGTH: () => PAYMENT_ID_MAX_LENGTH,
@@ -50,6 +51,7 @@ __export(src_exports, {
50
51
  createSIWxRequestHook: () => createSIWxRequestHook,
51
52
  createSIWxSettleHook: () => createSIWxSettleHook,
52
53
  declareDiscoveryExtension: () => declareDiscoveryExtension,
54
+ declareEip2612GasSponsoringExtension: () => declareEip2612GasSponsoringExtension,
53
55
  declarePaymentIdentifierExtension: () => declarePaymentIdentifierExtension,
54
56
  declareSIWxExtension: () => declareSIWxExtension,
55
57
  decodeBase58: () => decodeBase58,
@@ -60,6 +62,7 @@ __export(src_exports, {
60
62
  extractDiscoveryInfoFromExtension: () => extractDiscoveryInfoFromExtension,
61
63
  extractDiscoveryInfoV1: () => extractDiscoveryInfoV1,
62
64
  extractEVMChainId: () => extractEVMChainId,
65
+ extractEip2612GasSponsoringInfo: () => extractEip2612GasSponsoringInfo,
63
66
  extractPaymentIdentifier: () => extractPaymentIdentifier,
64
67
  extractResourceMetadataV1: () => extractResourceMetadataV1,
65
68
  extractSolanaChainReference: () => extractSolanaChainReference,
@@ -69,9 +72,14 @@ __export(src_exports, {
69
72
  getEVMAddress: () => getEVMAddress,
70
73
  getSolanaAddress: () => getSolanaAddress,
71
74
  hasPaymentIdentifier: () => hasPaymentIdentifier,
75
+ isBodyExtensionConfig: () => isBodyExtensionConfig,
72
76
  isDiscoverableV1: () => isDiscoverableV1,
77
+ isEVMSigner: () => isEVMSigner,
78
+ isMcpExtensionConfig: () => isMcpExtensionConfig,
73
79
  isPaymentIdentifierExtension: () => isPaymentIdentifierExtension,
74
80
  isPaymentIdentifierRequired: () => isPaymentIdentifierRequired,
81
+ isQueryExtensionConfig: () => isQueryExtensionConfig,
82
+ isSolanaSigner: () => isSolanaSigner,
75
83
  isValidPaymentId: () => isValidPaymentId,
76
84
  parseSIWxHeader: () => parseSIWxHeader,
77
85
  paymentIdentifierResourceServerExtension: () => paymentIdentifierResourceServerExtension,
@@ -81,6 +89,7 @@ __export(src_exports, {
81
89
  siwxResourceServerExtension: () => siwxResourceServerExtension,
82
90
  validateAndExtract: () => validateAndExtract,
83
91
  validateDiscoveryExtension: () => validateDiscoveryExtension,
92
+ validateEip2612GasSponsoringInfo: () => validateEip2612GasSponsoringInfo,
84
93
  validatePaymentIdentifier: () => validatePaymentIdentifier,
85
94
  validatePaymentIdentifierRequirement: () => validatePaymentIdentifierRequirement,
86
95
  validateSIWxMessage: () => validateSIWxMessage,
@@ -92,10 +101,23 @@ __export(src_exports, {
92
101
  });
93
102
  module.exports = __toCommonJS(src_exports);
94
103
 
104
+ // src/bazaar/http/types.ts
105
+ var isQueryExtensionConfig = (config) => {
106
+ return !("bodyType" in config) && !("toolName" in config);
107
+ };
108
+ var isBodyExtensionConfig = (config) => {
109
+ return "bodyType" in config;
110
+ };
111
+
112
+ // src/bazaar/mcp/types.ts
113
+ var isMcpExtensionConfig = (config) => {
114
+ return "toolName" in config;
115
+ };
116
+
95
117
  // src/bazaar/types.ts
96
- var BAZAAR = "bazaar";
118
+ var BAZAAR = { key: "bazaar" };
97
119
 
98
- // src/bazaar/resourceService.ts
120
+ // src/bazaar/http/resourceService.ts
99
121
  function createQueryDiscoveryExtension({
100
122
  method,
101
123
  input = {},
@@ -227,7 +249,97 @@ function createBodyDiscoveryExtension({
227
249
  }
228
250
  };
229
251
  }
252
+
253
+ // src/bazaar/mcp/resourceService.ts
254
+ function createMcpDiscoveryExtension({
255
+ toolName,
256
+ description,
257
+ transport,
258
+ inputSchema,
259
+ example,
260
+ output
261
+ }) {
262
+ return {
263
+ info: {
264
+ input: {
265
+ type: "mcp",
266
+ toolName,
267
+ ...description !== void 0 ? { description } : {},
268
+ ...transport !== void 0 ? { transport } : {},
269
+ inputSchema,
270
+ ...example !== void 0 ? { example } : {}
271
+ },
272
+ ...output?.example ? {
273
+ output: {
274
+ type: "json",
275
+ example: output.example
276
+ }
277
+ } : {}
278
+ },
279
+ schema: {
280
+ $schema: "https://json-schema.org/draft/2020-12/schema",
281
+ type: "object",
282
+ properties: {
283
+ input: {
284
+ type: "object",
285
+ properties: {
286
+ type: {
287
+ type: "string",
288
+ const: "mcp"
289
+ },
290
+ toolName: {
291
+ type: "string"
292
+ },
293
+ ...description !== void 0 ? {
294
+ description: {
295
+ type: "string"
296
+ }
297
+ } : {},
298
+ ...transport !== void 0 ? {
299
+ transport: {
300
+ type: "string",
301
+ enum: ["streamable-http", "sse"]
302
+ }
303
+ } : {},
304
+ inputSchema: {
305
+ type: "object"
306
+ },
307
+ ...example !== void 0 ? {
308
+ example: {
309
+ type: "object"
310
+ }
311
+ } : {}
312
+ },
313
+ required: ["type", "toolName", "inputSchema"],
314
+ additionalProperties: false
315
+ },
316
+ ...output?.example ? {
317
+ output: {
318
+ type: "object",
319
+ properties: {
320
+ type: {
321
+ type: "string"
322
+ },
323
+ example: {
324
+ type: "object",
325
+ ...output.schema && typeof output.schema === "object" ? output.schema : {}
326
+ }
327
+ },
328
+ required: ["type"]
329
+ }
330
+ } : {}
331
+ },
332
+ required: ["input"]
333
+ }
334
+ };
335
+ }
336
+
337
+ // src/bazaar/resourceService.ts
230
338
  function declareDiscoveryExtension(config) {
339
+ if ("toolName" in config) {
340
+ const extension2 = createMcpDiscoveryExtension(config);
341
+ return { bazaar: extension2 };
342
+ }
231
343
  const bodyType = config.bodyType;
232
344
  const isBodyMethod2 = bodyType !== void 0;
233
345
  const extension = isBodyMethod2 ? createBodyDiscoveryExtension(config) : createQueryDiscoveryExtension(config);
@@ -239,12 +351,15 @@ function isHTTPRequestContext(ctx) {
239
351
  return ctx !== null && typeof ctx === "object" && "method" in ctx && "adapter" in ctx;
240
352
  }
241
353
  var bazaarResourceServerExtension = {
242
- key: BAZAAR,
354
+ key: BAZAAR.key,
243
355
  enrichDeclaration: (declaration, transportContext) => {
244
356
  if (!isHTTPRequestContext(transportContext)) {
245
357
  return declaration;
246
358
  }
247
359
  const extension = declaration;
360
+ if (extension.info?.input?.type === "mcp") {
361
+ return declaration;
362
+ }
248
363
  const method = transportContext.method;
249
364
  const existingInputProps = extension.schema?.properties?.input?.properties || {};
250
365
  const updatedInputProps = {
@@ -427,7 +542,7 @@ function extractDiscoveryInfo(paymentPayload, paymentRequirements, validate = tr
427
542
  if (paymentPayload.x402Version === 2) {
428
543
  resourceUrl = paymentPayload.resource?.url ?? "";
429
544
  if (paymentPayload.extensions) {
430
- const bazaarExtension = paymentPayload.extensions[BAZAAR];
545
+ const bazaarExtension = paymentPayload.extensions[BAZAAR.key];
431
546
  if (bazaarExtension && typeof bazaarExtension === "object") {
432
547
  try {
433
548
  const extension = bazaarExtension;
@@ -470,14 +585,17 @@ function extractDiscoveryInfo(paymentPayload, paymentRequirements, validate = tr
470
585
  description = requirementsV1.description;
471
586
  mimeType = requirementsV1.mimeType;
472
587
  }
473
- return {
588
+ const base = {
474
589
  resourceUrl: normalizedResourceUrl,
475
590
  description,
476
591
  mimeType,
477
- method: discoveryInfo.input.method,
478
592
  x402Version: paymentPayload.x402Version,
479
593
  discoveryInfo
480
594
  };
595
+ if (discoveryInfo.input.type === "mcp") {
596
+ return { ...base, toolName: discoveryInfo.input.toolName };
597
+ }
598
+ return { ...base, method: discoveryInfo.input.method };
481
599
  }
482
600
  function extractDiscoveryInfoFromExtension(extension, validate = true) {
483
601
  if (validate) {
@@ -620,6 +738,21 @@ function decodeBase58(encoded) {
620
738
  function encodeBase58(bytes) {
621
739
  return import_base.base58.encode(bytes);
622
740
  }
741
+ function isSolanaSigner(signer) {
742
+ if ("signMessages" in signer && typeof signer.signMessages === "function") {
743
+ return true;
744
+ }
745
+ if ("publicKey" in signer && signer.publicKey) {
746
+ const pk = signer.publicKey;
747
+ if (typeof pk === "object" && pk !== null && "toBase58" in pk) {
748
+ return true;
749
+ }
750
+ if (typeof pk === "string" && !pk.startsWith("0x")) {
751
+ return true;
752
+ }
753
+ }
754
+ return false;
755
+ }
623
756
 
624
757
  // src/sign-in-with-x/schema.ts
625
758
  function buildSIWxSchema() {
@@ -884,6 +1017,30 @@ async function verifyEVMSignature(message, address, signature, verifier) {
884
1017
  }
885
1018
  return (0, import_viem.verifyMessage)(args);
886
1019
  }
1020
+ function isEVMSigner(signer) {
1021
+ if ("signMessages" in signer && typeof signer.signMessages === "function") {
1022
+ return false;
1023
+ }
1024
+ if ("publicKey" in signer && signer.publicKey) {
1025
+ const pk = signer.publicKey;
1026
+ if (typeof pk === "object" && pk !== null && "toBase58" in pk) {
1027
+ return false;
1028
+ }
1029
+ if (typeof pk === "string" && !pk.startsWith("0x")) {
1030
+ return false;
1031
+ }
1032
+ }
1033
+ if ("account" in signer && signer.account && typeof signer.account === "object") {
1034
+ const account = signer.account;
1035
+ if (account.address && account.address.startsWith("0x")) {
1036
+ return true;
1037
+ }
1038
+ }
1039
+ if ("address" in signer && typeof signer.address === "string" && signer.address.startsWith("0x")) {
1040
+ return true;
1041
+ }
1042
+ return false;
1043
+ }
887
1044
 
888
1045
  // src/sign-in-with-x/verify.ts
889
1046
  async function verifySIWxSignature(payload, options) {
@@ -1020,8 +1177,14 @@ function getEVMAddress(signer) {
1020
1177
  throw new Error("EVM signer missing address");
1021
1178
  }
1022
1179
  function getSolanaAddress(signer) {
1023
- const pk = signer.publicKey;
1024
- return typeof pk === "string" ? pk : pk.toBase58();
1180
+ if ("address" in signer && signer.address) {
1181
+ return signer.address;
1182
+ }
1183
+ if ("publicKey" in signer) {
1184
+ const pk = signer.publicKey;
1185
+ return typeof pk === "string" ? pk : pk.toBase58();
1186
+ }
1187
+ throw new Error("Solana signer missing address or publicKey");
1025
1188
  }
1026
1189
  async function signEVMMessage(message, signer) {
1027
1190
  if (signer.account) {
@@ -1031,8 +1194,17 @@ async function signEVMMessage(message, signer) {
1031
1194
  }
1032
1195
  async function signSolanaMessage(message, signer) {
1033
1196
  const messageBytes = new TextEncoder().encode(message);
1034
- const signatureBytes = await signer.signMessage(messageBytes);
1035
- return encodeBase58(signatureBytes);
1197
+ if ("signMessages" in signer) {
1198
+ const results = await signer.signMessages([{ content: messageBytes, signatures: {} }]);
1199
+ const sigDict = results[0];
1200
+ const signatureBytes = Object.values(sigDict)[0];
1201
+ return encodeBase58(signatureBytes);
1202
+ }
1203
+ if ("signMessage" in signer) {
1204
+ const signatureBytes = await signer.signMessage(messageBytes);
1205
+ return encodeBase58(signatureBytes);
1206
+ }
1207
+ throw new Error("Solana signer missing signMessage or signMessages method");
1036
1208
  }
1037
1209
 
1038
1210
  // src/sign-in-with-x/client.ts
@@ -1205,15 +1377,15 @@ function createSIWxRequestHook(options) {
1205
1377
  };
1206
1378
  }
1207
1379
  function createSIWxClientHook(signer) {
1380
+ const signerIsSolana = isSolanaSigner(signer);
1381
+ const expectedSignatureType = signerIsSolana ? "ed25519" : "eip191";
1208
1382
  return async (context) => {
1209
1383
  const extensions = context.paymentRequired.extensions ?? {};
1210
1384
  const siwxExtension = extensions[SIGN_IN_WITH_X];
1211
1385
  if (!siwxExtension?.supportedChains) return;
1212
1386
  try {
1213
- const paymentNetwork = context.paymentRequired.accepts?.[0]?.network;
1214
- if (!paymentNetwork) return;
1215
1387
  const matchingChain = siwxExtension.supportedChains.find(
1216
- (chain) => chain.chainId === paymentNetwork
1388
+ (chain) => chain.type === expectedSignatureType
1217
1389
  );
1218
1390
  if (!matchingChain) {
1219
1391
  return;
@@ -1443,9 +1615,97 @@ var paymentIdentifierResourceServerExtension = {
1443
1615
  // No enrichment needed - the declaration is static
1444
1616
  // Future hooks for idempotency could be added here if needed
1445
1617
  };
1618
+
1619
+ // src/eip2612-gas-sponsoring/types.ts
1620
+ var EIP2612_GAS_SPONSORING = { key: "eip2612GasSponsoring" };
1621
+
1622
+ // src/eip2612-gas-sponsoring/resourceService.ts
1623
+ var eip2612GasSponsoringSchema = {
1624
+ $schema: "https://json-schema.org/draft/2020-12/schema",
1625
+ type: "object",
1626
+ properties: {
1627
+ from: {
1628
+ type: "string",
1629
+ pattern: "^0x[a-fA-F0-9]{40}$",
1630
+ description: "The address of the sender."
1631
+ },
1632
+ asset: {
1633
+ type: "string",
1634
+ pattern: "^0x[a-fA-F0-9]{40}$",
1635
+ description: "The address of the ERC-20 token contract."
1636
+ },
1637
+ spender: {
1638
+ type: "string",
1639
+ pattern: "^0x[a-fA-F0-9]{40}$",
1640
+ description: "The address of the spender (Canonical Permit2)."
1641
+ },
1642
+ amount: {
1643
+ type: "string",
1644
+ pattern: "^[0-9]+$",
1645
+ description: "The amount to approve (uint256). Typically MaxUint."
1646
+ },
1647
+ nonce: {
1648
+ type: "string",
1649
+ pattern: "^[0-9]+$",
1650
+ description: "The current nonce of the sender."
1651
+ },
1652
+ deadline: {
1653
+ type: "string",
1654
+ pattern: "^[0-9]+$",
1655
+ description: "The timestamp at which the signature expires."
1656
+ },
1657
+ signature: {
1658
+ type: "string",
1659
+ pattern: "^0x[a-fA-F0-9]+$",
1660
+ description: "The 65-byte concatenated signature (r, s, v) as a hex string."
1661
+ },
1662
+ version: {
1663
+ type: "string",
1664
+ pattern: "^[0-9]+(\\.[0-9]+)*$",
1665
+ description: "Schema version identifier."
1666
+ }
1667
+ },
1668
+ required: ["from", "asset", "spender", "amount", "nonce", "deadline", "signature", "version"]
1669
+ };
1670
+ function declareEip2612GasSponsoringExtension() {
1671
+ const key = EIP2612_GAS_SPONSORING.key;
1672
+ return {
1673
+ [key]: {
1674
+ info: {
1675
+ description: "The facilitator accepts EIP-2612 gasless Permit to `Permit2` canonical contract.",
1676
+ version: "1"
1677
+ },
1678
+ schema: eip2612GasSponsoringSchema
1679
+ }
1680
+ };
1681
+ }
1682
+
1683
+ // src/eip2612-gas-sponsoring/facilitator.ts
1684
+ function extractEip2612GasSponsoringInfo(paymentPayload) {
1685
+ if (!paymentPayload.extensions) {
1686
+ return null;
1687
+ }
1688
+ const extension = paymentPayload.extensions[EIP2612_GAS_SPONSORING.key];
1689
+ if (!extension?.info) {
1690
+ return null;
1691
+ }
1692
+ const info = extension.info;
1693
+ if (!info.from || !info.asset || !info.spender || !info.amount || !info.nonce || !info.deadline || !info.signature || !info.version) {
1694
+ return null;
1695
+ }
1696
+ return info;
1697
+ }
1698
+ function validateEip2612GasSponsoringInfo(info) {
1699
+ const addressPattern = /^0x[a-fA-F0-9]{40}$/;
1700
+ const numericPattern = /^[0-9]+$/;
1701
+ const hexPattern = /^0x[a-fA-F0-9]+$/;
1702
+ const versionPattern = /^[0-9]+(\.[0-9]+)*$/;
1703
+ return addressPattern.test(info.from) && addressPattern.test(info.asset) && addressPattern.test(info.spender) && numericPattern.test(info.amount) && numericPattern.test(info.nonce) && numericPattern.test(info.deadline) && hexPattern.test(info.signature) && versionPattern.test(info.version);
1704
+ }
1446
1705
  // Annotate the CommonJS export names for ESM import in node:
1447
1706
  0 && (module.exports = {
1448
1707
  BAZAAR,
1708
+ EIP2612_GAS_SPONSORING,
1449
1709
  InMemorySIWxStorage,
1450
1710
  PAYMENT_IDENTIFIER,
1451
1711
  PAYMENT_ID_MAX_LENGTH,
@@ -1465,6 +1725,7 @@ var paymentIdentifierResourceServerExtension = {
1465
1725
  createSIWxRequestHook,
1466
1726
  createSIWxSettleHook,
1467
1727
  declareDiscoveryExtension,
1728
+ declareEip2612GasSponsoringExtension,
1468
1729
  declarePaymentIdentifierExtension,
1469
1730
  declareSIWxExtension,
1470
1731
  decodeBase58,
@@ -1475,6 +1736,7 @@ var paymentIdentifierResourceServerExtension = {
1475
1736
  extractDiscoveryInfoFromExtension,
1476
1737
  extractDiscoveryInfoV1,
1477
1738
  extractEVMChainId,
1739
+ extractEip2612GasSponsoringInfo,
1478
1740
  extractPaymentIdentifier,
1479
1741
  extractResourceMetadataV1,
1480
1742
  extractSolanaChainReference,
@@ -1484,9 +1746,14 @@ var paymentIdentifierResourceServerExtension = {
1484
1746
  getEVMAddress,
1485
1747
  getSolanaAddress,
1486
1748
  hasPaymentIdentifier,
1749
+ isBodyExtensionConfig,
1487
1750
  isDiscoverableV1,
1751
+ isEVMSigner,
1752
+ isMcpExtensionConfig,
1488
1753
  isPaymentIdentifierExtension,
1489
1754
  isPaymentIdentifierRequired,
1755
+ isQueryExtensionConfig,
1756
+ isSolanaSigner,
1490
1757
  isValidPaymentId,
1491
1758
  parseSIWxHeader,
1492
1759
  paymentIdentifierResourceServerExtension,
@@ -1496,6 +1763,7 @@ var paymentIdentifierResourceServerExtension = {
1496
1763
  siwxResourceServerExtension,
1497
1764
  validateAndExtract,
1498
1765
  validateDiscoveryExtension,
1766
+ validateEip2612GasSponsoringInfo,
1499
1767
  validatePaymentIdentifier,
1500
1768
  validatePaymentIdentifierRequirement,
1501
1769
  validateSIWxMessage,