@dexterai/x402 1.8.2 → 1.9.1

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 (36) hide show
  1. package/README.md +101 -8
  2. package/dist/adapters/index.cjs +15 -3
  3. package/dist/adapters/index.cjs.map +1 -1
  4. package/dist/adapters/index.d.cts +5 -5
  5. package/dist/adapters/index.d.ts +5 -5
  6. package/dist/adapters/index.js +5 -3
  7. package/dist/adapters/index.js.map +1 -1
  8. package/dist/client/index.cjs +50 -9
  9. package/dist/client/index.cjs.map +1 -1
  10. package/dist/client/index.d.cts +7 -6
  11. package/dist/client/index.d.ts +7 -6
  12. package/dist/client/index.js +37 -9
  13. package/dist/client/index.js.map +1 -1
  14. package/dist/react/index.cjs +64 -12
  15. package/dist/react/index.cjs.map +1 -1
  16. package/dist/react/index.d.cts +13 -4
  17. package/dist/react/index.d.ts +13 -4
  18. package/dist/react/index.js +52 -12
  19. package/dist/react/index.js.map +1 -1
  20. package/dist/server/index.cjs +43 -18
  21. package/dist/server/index.cjs.map +1 -1
  22. package/dist/server/index.d.cts +12 -3
  23. package/dist/server/index.d.ts +12 -3
  24. package/dist/server/index.js +40 -16
  25. package/dist/server/index.js.map +1 -1
  26. package/dist/{solana-BeGAqPta.d.cts → solana-CfHuiW2H.d.cts} +2 -2
  27. package/dist/{solana-CQD9yMju.d.ts → solana-kZcwbUK9.d.ts} +2 -2
  28. package/dist/{x402-client-Dk9q2QQF.d.cts → sponsored-access-BCB2CxdG.d.cts} +70 -3
  29. package/dist/{x402-client-D9b3PHai.d.ts → sponsored-access-H1EX6zpi.d.ts} +70 -3
  30. package/dist/{types-DYLi7SuF.d.cts → types-BQvaF8lB.d.cts} +7 -5
  31. package/dist/{types-DYLi7SuF.d.ts → types-BQvaF8lB.d.ts} +7 -5
  32. package/dist/{types-B477nBpg.d.cts → types-DmqH9yD8.d.cts} +1 -1
  33. package/dist/{types-BWnUAPvD.d.ts → types-ENcnkof8.d.ts} +1 -1
  34. package/dist/utils/index.cjs.map +1 -1
  35. package/dist/utils/index.js.map +1 -1
  36. package/package.json +2 -6
@@ -37,6 +37,7 @@ __export(server_exports, {
37
37
  MODEL_PRICING_MAP: () => MODEL_PRICING_MAP,
38
38
  MODEL_REGISTRY: () => MODEL_REGISTRY,
39
39
  SOLANA_MAINNET_NETWORK: () => SOLANA_MAINNET_NETWORK,
40
+ SPONSORED_ACCESS_EXTENSION_KEY: () => import_x402_ads_types.SPONSORED_ACCESS_EXTENSION_KEY,
40
41
  USDC_BASE: () => USDC_BASE,
41
42
  USDC_MINT: () => USDC_MINT,
42
43
  countTokens: () => countTokens,
@@ -577,9 +578,19 @@ function x402Middleware(config) {
577
578
  res.setHeader("PAYMENT-RESPONSE", encodeBase64Json(paymentResponseData));
578
579
  if (config.sponsoredAccess && settleResult.extensions?.["sponsored-access"]) {
579
580
  const extData = settleResult.extensions["sponsored-access"];
580
- const recs = extData?.info?.recommendations;
581
+ const recs = extData?.info?.recommendations ?? extData?.recommendations;
581
582
  if (recs && recs.length > 0) {
582
583
  log("Injecting sponsored-access recommendations into response");
584
+ if (typeof config.sponsoredAccess === "object" && config.sponsoredAccess.onMatch) {
585
+ try {
586
+ config.sponsoredAccess.onMatch(recs, {
587
+ transaction: settleResult.transaction,
588
+ network: settledNetwork,
589
+ payer: verifyResult.payer ?? ""
590
+ });
591
+ } catch {
592
+ }
593
+ }
583
594
  const originalJson = res.json.bind(res);
584
595
  res.json = function patchedJson(body) {
585
596
  if (typeof config.sponsoredAccess === "object" && config.sponsoredAccess.inject) {
@@ -748,7 +759,7 @@ if (btn) {
748
759
  if (!accept) throw new Error('No payment method available');
749
760
 
750
761
  const payTo = new PublicKey(accept.payTo);
751
- const amount = BigInt(accept.amount || accept.maxAmountRequired);
762
+ const amount = BigInt(accept.amount ?? accept.maxAmountRequired);
752
763
  const mintPubkey = new PublicKey(accept.asset);
753
764
  const feePayer = accept.extra?.feePayer ? new PublicKey(accept.extra.feePayer) : provider.publicKey;
754
765
  const userPubkey = provider.publicKey;
@@ -855,7 +866,7 @@ function generatePaywallHtml(paymentRequiredHeader, requestUrl, method, config,
855
866
  const decoded = JSON.parse(Buffer.from(paymentRequiredHeader, "base64").toString());
856
867
  const accept = decoded.accepts?.[0];
857
868
  if (accept) {
858
- const amount = accept.amount || accept.maxAmountRequired || "0";
869
+ const amount = accept.amount ?? accept.maxAmountRequired ?? "0";
859
870
  const decimals = accept.extra?.decimals || 6;
860
871
  price = (Number(amount) / Math.pow(10, decimals)).toFixed(decimals > 4 ? 4 : 2);
861
872
  network = accept.network || "";
@@ -1200,14 +1211,8 @@ function x402AccessPass(config) {
1200
1211
  }
1201
1212
 
1202
1213
  // src/server/dynamic-pricing.ts
1203
- function simpleHash(str) {
1204
- let hash = 2166136261;
1205
- for (let i = 0; i < str.length; i++) {
1206
- hash ^= str.charCodeAt(i);
1207
- hash = Math.imul(hash, 16777619);
1208
- }
1209
- return (hash >>> 0).toString(16).padStart(8, "0");
1210
- }
1214
+ var import_crypto2 = require("crypto");
1215
+ var QUOTE_MAX_AGE_SECONDS = 300;
1211
1216
  function createDynamicPricing(config) {
1212
1217
  const fullConfig = {
1213
1218
  unitSize: config.unitSize,
@@ -1222,7 +1227,8 @@ function createDynamicPricing(config) {
1222
1227
  if (ratePerUnit <= 0) throw new Error("ratePerUnit must be positive");
1223
1228
  if (minUsd < 0) throw new Error("minUsd cannot be negative");
1224
1229
  if (maxUsd < minUsd) throw new Error("maxUsd must be >= minUsd");
1225
- function buildHashInput(input) {
1230
+ const hmacSecret = (0, import_crypto2.randomBytes)(32);
1231
+ function signQuote(input, timestamp) {
1226
1232
  const configStr = JSON.stringify({
1227
1233
  unitSize,
1228
1234
  ratePerUnit,
@@ -1230,7 +1236,8 @@ function createDynamicPricing(config) {
1230
1236
  maxUsd: maxUsd === Infinity ? "none" : maxUsd,
1231
1237
  roundingMode
1232
1238
  });
1233
- return `${input}|${configStr}`;
1239
+ const data = `${input}|${configStr}|${timestamp}`;
1240
+ return (0, import_crypto2.createHmac)("sha256", hmacSecret).update(data).digest("hex").slice(0, 16);
1234
1241
  }
1235
1242
  function calculate(input) {
1236
1243
  const inputLength = input.length;
@@ -1255,7 +1262,9 @@ function createDynamicPricing(config) {
1255
1262
  usdAmount = Math.min(maxUsd, usdAmount);
1256
1263
  const multiplier = Math.pow(10, decimals);
1257
1264
  const amountAtomic = Math.floor(usdAmount * multiplier).toString();
1258
- const quoteHash = simpleHash(buildHashInput(input));
1265
+ const timestamp = Math.floor(Date.now() / 1e3);
1266
+ const mac = signQuote(input, timestamp);
1267
+ const quoteHash = `${timestamp}.${mac}`;
1259
1268
  return {
1260
1269
  amountAtomic,
1261
1270
  usdAmount,
@@ -1266,8 +1275,20 @@ function createDynamicPricing(config) {
1266
1275
  }
1267
1276
  function validateQuote(input, quoteHash) {
1268
1277
  if (!quoteHash) return false;
1269
- const expectedHash = simpleHash(buildHashInput(input));
1270
- return expectedHash === quoteHash;
1278
+ const dotIndex = quoteHash.indexOf(".");
1279
+ if (dotIndex === -1) return false;
1280
+ const timestamp = parseInt(quoteHash.slice(0, dotIndex), 10);
1281
+ const mac = quoteHash.slice(dotIndex + 1);
1282
+ if (isNaN(timestamp) || !mac) return false;
1283
+ const age = Math.floor(Date.now() / 1e3) - timestamp;
1284
+ if (age < 0 || age > QUOTE_MAX_AGE_SECONDS) return false;
1285
+ const expectedMac = signQuote(input, timestamp);
1286
+ if (mac.length !== expectedMac.length) return false;
1287
+ let mismatch = 0;
1288
+ for (let i = 0; i < mac.length; i++) {
1289
+ mismatch |= mac.charCodeAt(i) ^ expectedMac.charCodeAt(i);
1290
+ }
1291
+ return mismatch === 0;
1271
1292
  }
1272
1293
  return {
1273
1294
  calculate,
@@ -1282,7 +1303,7 @@ function formatPricing(config) {
1282
1303
  }
1283
1304
 
1284
1305
  // src/server/token-pricing.ts
1285
- var import_crypto2 = require("crypto");
1306
+ var import_crypto3 = require("crypto");
1286
1307
  var import_tiktoken = require("tiktoken");
1287
1308
 
1288
1309
  // src/server/model-registry.ts
@@ -1880,7 +1901,7 @@ function countTokens(text, model = DEFAULT_MODEL) {
1880
1901
  }
1881
1902
  function generateQuoteHash(prompt, model, rate, tokens) {
1882
1903
  const configString = JSON.stringify({ model, rate, tokens });
1883
- return (0, import_crypto2.createHash)("sha256").update(prompt + configString).digest("hex").slice(0, 16);
1904
+ return (0, import_crypto3.createHash)("sha256").update(prompt + configString).digest("hex").slice(0, 16);
1884
1905
  }
1885
1906
  function createTokenPricing(config = {}) {
1886
1907
  const model = config.model ?? DEFAULT_MODEL;
@@ -2060,6 +2081,9 @@ function stripePayTo(secretKeyOrConfig) {
2060
2081
  provider._stripeNetwork = caip2Network;
2061
2082
  return provider;
2062
2083
  }
2084
+
2085
+ // src/server/index.ts
2086
+ var import_x402_ads_types = require("@dexterai/x402-ads-types");
2063
2087
  // Annotate the CommonJS export names for ESM import in node:
2064
2088
  0 && (module.exports = {
2065
2089
  BASE_MAINNET_NETWORK,
@@ -2069,6 +2093,7 @@ function stripePayTo(secretKeyOrConfig) {
2069
2093
  MODEL_PRICING_MAP,
2070
2094
  MODEL_REGISTRY,
2071
2095
  SOLANA_MAINNET_NETWORK,
2096
+ SPONSORED_ACCESS_EXTENSION_KEY,
2072
2097
  USDC_BASE,
2073
2098
  USDC_MINT,
2074
2099
  countTokens,