@dexterai/x402 1.6.1 → 1.6.3
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/react/index.cjs.map +1 -1
- package/dist/react/index.js.map +1 -1
- package/dist/server/index.cjs +54 -16
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.d.cts +1 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.js +54 -16
- package/dist/server/index.js.map +1 -1
- package/dist/utils/index.cjs.map +1 -1
- package/dist/utils/index.js.map +1 -1
- package/package.json +1 -1
package/dist/server/index.cjs
CHANGED
|
@@ -76,8 +76,33 @@ function toAtomicUnits(amount, decimals) {
|
|
|
76
76
|
const multiplier = Math.pow(10, decimals);
|
|
77
77
|
return Math.floor(amount * multiplier).toString();
|
|
78
78
|
}
|
|
79
|
+
function safeBase64Encode(str) {
|
|
80
|
+
if (typeof Buffer !== "undefined") {
|
|
81
|
+
return Buffer.from(str, "utf-8").toString("base64");
|
|
82
|
+
}
|
|
83
|
+
const bytes = new TextEncoder().encode(str);
|
|
84
|
+
let binary = "";
|
|
85
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
86
|
+
binary += String.fromCharCode(bytes[i]);
|
|
87
|
+
}
|
|
88
|
+
return btoa(binary);
|
|
89
|
+
}
|
|
90
|
+
function safeBase64Decode(encoded) {
|
|
91
|
+
if (typeof Buffer !== "undefined") {
|
|
92
|
+
return Buffer.from(encoded, "base64").toString("utf-8");
|
|
93
|
+
}
|
|
94
|
+
const binary = atob(encoded);
|
|
95
|
+
const bytes = new Uint8Array(binary.length);
|
|
96
|
+
for (let i = 0; i < binary.length; i++) {
|
|
97
|
+
bytes[i] = binary.charCodeAt(i);
|
|
98
|
+
}
|
|
99
|
+
return new TextDecoder().decode(bytes);
|
|
100
|
+
}
|
|
101
|
+
function encodeBase64Json(obj) {
|
|
102
|
+
return safeBase64Encode(JSON.stringify(obj));
|
|
103
|
+
}
|
|
79
104
|
function decodeBase64Json(encoded) {
|
|
80
|
-
return JSON.parse(
|
|
105
|
+
return JSON.parse(safeBase64Decode(encoded));
|
|
81
106
|
}
|
|
82
107
|
|
|
83
108
|
// src/server/facilitator-client.ts
|
|
@@ -287,7 +312,7 @@ function createX402Server(config) {
|
|
|
287
312
|
};
|
|
288
313
|
}
|
|
289
314
|
function encodeRequirements(requirements) {
|
|
290
|
-
return
|
|
315
|
+
return encodeBase64Json(requirements);
|
|
291
316
|
}
|
|
292
317
|
function create402Response(requirements) {
|
|
293
318
|
return {
|
|
@@ -411,7 +436,7 @@ function x402Middleware(config) {
|
|
|
411
436
|
network,
|
|
412
437
|
payer: verifyResult.payer ?? ""
|
|
413
438
|
};
|
|
414
|
-
res.setHeader("PAYMENT-RESPONSE",
|
|
439
|
+
res.setHeader("PAYMENT-RESPONSE", encodeBase64Json(paymentResponseData));
|
|
415
440
|
next();
|
|
416
441
|
} catch (error) {
|
|
417
442
|
log("Middleware error:", error);
|
|
@@ -424,6 +449,7 @@ function x402Middleware(config) {
|
|
|
424
449
|
}
|
|
425
450
|
|
|
426
451
|
// src/server/browser-support.ts
|
|
452
|
+
var USDC_ICON_SVG = `<svg width="18" height="18" viewBox="0 0 2000 2000" xmlns="http://www.w3.org/2000/svg"><path d="M1000 2000c554.17 0 1000-445.83 1000-1000S1554.17 0 1000 0 0 445.83 0 1000s445.83 1000 1000 1000z" fill="#2775ca"/><path d="M1275 1158.33c0-145.83-87.5-195.83-262.5-216.66-125-16.67-150-50-150-108.34s41.67-95.83 125-95.83c75 0 116.67 25 137.5 87.5 4.17 12.5 16.67 20.83 29.17 20.83h66.66c16.67 0 29.17-12.5 29.17-29.16v-4.17c-16.67-91.67-91.67-162.5-187.5-170.83v-100c0-16.67-12.5-29.17-33.33-33.34h-62.5c-16.67 0-29.17 12.5-33.34 33.34v95.83c-125 16.67-204.16 100-204.16 204.17 0 137.5 83.33 191.66 258.33 212.5 116.67 20.83 154.17 45.83 154.17 112.5s-58.34 112.5-137.5 112.5c-108.34 0-145.84-45.84-158.34-108.34-4.16-16.66-16.66-25-29.16-25h-70.84c-16.66 0-29.16 12.5-29.16 29.17v4.17c16.66 104.16 83.33 179.16 220.83 200v100c0 16.66 12.5 29.16 33.33 33.33h62.5c16.67 0 29.17-12.5 33.34-33.33v-100c125-20.84 208.33-108.34 208.33-220.84z" fill="#fff"/><path d="M787.5 1595.83c-325-116.66-491.67-479.16-370.83-800 62.5-175 200-308.33 370.83-370.83 16.67-8.33 25-20.83 25-41.67V325c0-16.67-8.33-29.17-25-33.33-4.17 0-12.5 0-16.67 4.16-395.83 125-612.5 545.84-487.5 941.67 75 233.33 254.17 412.5 487.5 487.5 16.67 8.33 33.34 0 37.5-16.67 4.17-4.16 4.17-8.33 4.17-16.66v-58.34c0-12.5-12.5-29.16-25-37.5zM1229.17 295.83c-16.67-8.33-33.34 0-37.5 16.67-4.17 4.17-4.17 8.33-4.17 16.67v58.33c0 16.67 12.5 33.33 25 41.67 325 116.66 491.67 479.16 370.83 800-62.5 175-200 308.33-370.83 370.83-16.67 8.33-25 20.83-25 41.67V1700c0 16.67 8.33 29.17 25 33.33 4.17 0 12.5 0 16.67-4.16 395.83-125 612.5-545.84 487.5-941.67-75-237.5-258.34-416.67-487.5-491.67z" fill="#fff"/></svg>`;
|
|
427
453
|
var DEXTER_CREST_SVG = `<svg width="36" height="36" viewBox="0 0 300 300" xmlns="http://www.w3.org/2000/svg"><g><path fill="#F2681A" d="m324.93,313.11c-115.5,0-231,0-350,0l350,0z"/><path fill="#FDFAF5" d="m230.43,50.62c1.1.85 2.19 1.7 3.32 2.57 6.02 4.8 11.77 9.88 17.46 15.07.92.84.92.84 1.86 1.69 1.82 1.69 3.59 3.42 5.35 5.16.61.56 1.22 1.13 1.84 1.71 5.66 5.76 6.18 10.43 6.13 18.3.02 1.16.04 2.32.06 3.52.06 3.83.06 7.65.07 11.48.02 2.68.05 5.35.08 8.03.05 5.6.09 11.21.1 16.81.02 7.15.09 14.31.17 21.46.06 5.53.1 11.05.13 16.58.02 2.64.04 5.27.07 7.91.18 17.58.12 32.82-11.24 47.32-7.35 7.27-16.54 12.06-25.42 17.22-1.97 1.16-3.94 2.33-5.91 3.49-7.16 4.24-14.34 8.44-21.53 12.62-4.8 2.79-9.59 5.6-14.38 8.42-1.25.73-2.5 1.47-3.79 2.23-2.32 1.36-4.64 2.73-6.96 4.1-27.47 16.09-27.47 16.09-42.16 12.93-8.06-2.28-14.94-5.82-22.16-10.02-1.17-.67-2.34-1.34-3.54-2.04-24.55-14.25-43.58-27.03-51.9-55.58-1.07-4.58-1.54-8.92-1.52-13.61.28-9.5.28-9.5-3.3-17.97-1.81-1.49-3.68-2.92-5.59-4.28-9.19-7.06-12.7-20.03-14.18-31.06-.54-5.77-.55-11.56-.6-17.35-.03-1.32-.07-2.63-.1-3.99-.01-1.26-.02-2.53-.03-3.83-.02-1.15-.03-2.29-.05-3.47.72-4.02 1.94-5.36 5.21-7.74 2.89-.53 2.89-.53 6.07-.46 1.71.02 1.71.02 3.46.05 1.19.04 2.37.08 3.59.12 1.2.02 2.41.04 3.65.06 2.97.05 5.93.13 8.9.23.14-1.35.29-2.7.43-4.08.63-5 1.78-9.74 3.14-14.58.22-.79.43-1.59.66-2.4.53-1.92 1.06-3.84 1.6-5.76-1.55-.45-1.55-.45-3.13-.9-9.52-3.52-17.1-10.95-21.37-20.1-3.81-9.26-3.87-20.34-.29-29.68 6.49-13.99 16.36-23.23 30.66-29.01 49.81-17.69 115.79 8.35 155.13 38.85z"/><path fill="#F2671A" d="m142.93,22.62c.86.19 1.73.39 2.62.59 36.12 8.21 68.79 24.98 95.38 50.75 1.02.98 2.03 1.97 3.08 2.98 10.84 10.66 10.84 10.66 11.05 14.62-2.06 3.55-5.44 4.18-9.17 5.3-.79.25-1.59.49-2.41.75-28.13 8.43-60.95 6.37-87.13-7.16-.86-.49-1.71-.97-2.6-1.48-7.37-4.05-12.59-3.36-20.59-1.54-22.76 4-48.47 1.53-68.69-9.74-4.88-3.88-8.23-8.29-10.21-14.22-.93-10.38-.67-18.44 5.83-26.83 19.57-23.38 55.99-20.36 82.83-14z"/><path fill="#F16619" d="m44.93,129.12c27.36-.03 54.72-.05 82.08-.06 12.7-.01 25.41-.01 38.11-.03 11.07-.01 22.14-.02 33.2-.02 5.86 0 11.73-.01 17.59-.01 5.51-.01 11.03-.01 16.54-.01 2.03 0 4.06 0 6.09-.01 2.76-.01 5.52 0 8.28 0 .81 0 1.63-.01 2.47-.01 5.51.02 5.51.02 6.81 1.32.22 3.43.22 3.43 0 7-2.75 2.75-3.42 2.66-7.15 2.82-1.41.07-1.41.07-2.85.14-1.47.05-1.47.05-2.98.11-1.49.07-1.49.07-3 .14-2.45.11-4.9.21-7.35.3-.2 1.3-.4 2.59-.6 3.93-2.57 16.08-5.93 29.89-18.89 40.86-10.35 7.28-21.87 8.49-34.17 7.71-13.11-2.33-22.52-9.19-30.33-19.83-4.49-7.64-4.8-17.05-5.83-25.67-4.24.39-8.47.77-12.83 1.17-.28 1.84-.28 1.84-.56 3.71-2.32 14.39-5.63 23.35-16.95 33.11-2.32 1.67-2.32 1.67-4.65 1.67 4 4.67 9.06 6.59 14.87 8.24 3.79 1.09 3.79 1.09 6.12 3.43-.65 5.31-.65 5.31-2.33 7-8.42-.27-15.13-2.29-22.17-7-1.09-1.21-2.17-2.43-3.25-3.65-2.72-2.81-4.45-3.84-8.36-4.16-1.67-.02-3.34-.02-5.01.01-1.77-.04-3.54-.09-5.3-.15-1.27-.04-1.27-.04-2.56-.08-9.26-.54-17.6-4.56-24.51-10.64-9.58-11.11-11.03-22.56-10.72-36.82.02-1.4.03-2.8.05-4.24.04-3.42.1-6.85.17-10.27z"/><path fill="#F26117" d="m172.68,203.08c7.27.09 13.23 1.97 18.87 6.65 2.88 3.07 3.86 5.12 4.25 9.32-.12 1.01-.24 2.02-.36 3.06-2.55.95-2.55.95-5.83 1.17-3.28-2.84-3.28-2.84-5.83-5.83-.36.58-.71 1.16-1.08 1.75-7.6 11.29-20.06 17.74-33.05 21.09-20.36 3.1-36.81-1.66-53.37-13.73-2.33-2.11-2.33-2.11-4.67-5.61.42-3.45.99-4.49 3.5-7 4.07.37 5.95 2.13 8.75 4.96 9.81 8.93 22.53 11.87 35.51 11.69 11.74-1.05 22.38-5.85 31.57-13.15 2.06-2.45 2.06-2.45 3.5-4.67-1.66.07-1.66.07-3.35.15-3.65-.15-3.65-.15-5.98-2.48.75-6.18 1.46-7.19 7.58-7.36z"/></g></svg>`;
|
|
428
454
|
var DEXTER_STYLES = `
|
|
429
455
|
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Orbitron:wght@500;700&display=swap');
|
|
@@ -433,7 +459,8 @@ body{font-family:'Inter',system-ui,-apple-system,sans-serif;background:#0a0a0a;c
|
|
|
433
459
|
.crest{margin:0 auto .75rem}
|
|
434
460
|
h1{font-family:'Orbitron',sans-serif;font-size:1.15rem;font-weight:700;color:#f1f5f9;letter-spacing:.04em;margin-bottom:.35rem}
|
|
435
461
|
.desc{color:#94a3b8;font-size:.9rem;margin-bottom:1.25rem;line-height:1.5}
|
|
436
|
-
.price{font-family:'Orbitron',sans-serif;font-size:1.6rem;font-weight:700;color:#F26B1A;margin:.75rem 0 .25rem}
|
|
462
|
+
.price{font-family:'Orbitron',sans-serif;font-size:1.6rem;font-weight:700;color:#F26B1A;margin:.75rem 0 .25rem;display:inline-flex;align-items:center;gap:.35rem}
|
|
463
|
+
.price svg{width:1.3em;height:1.3em;flex-shrink:0}
|
|
437
464
|
.chain{color:#525252;font-size:.75rem;margin-bottom:1.25rem;letter-spacing:.03em}
|
|
438
465
|
.endpoint{background:rgba(242,107,26,.06);border:1px solid rgba(242,107,26,.12);border-radius:6px;padding:.5rem .75rem;margin-bottom:1.25rem}
|
|
439
466
|
.endpoint code{font-family:'SF Mono',Monaco,Consolas,monospace;font-size:.8rem;color:#F26B1A}
|
|
@@ -628,13 +655,15 @@ if (btn) {
|
|
|
628
655
|
setBtnState('Verifying...', true, true);
|
|
629
656
|
setStatus('Payment submitted, verifying...');
|
|
630
657
|
|
|
658
|
+
// Use the original request body if available
|
|
659
|
+
const originalBody = dataEl.dataset.body ? atob(dataEl.dataset.body) : '{}';
|
|
631
660
|
const response = await fetch(requestUrl, {
|
|
632
661
|
method: requestMethod,
|
|
633
662
|
headers: {
|
|
634
663
|
'Content-Type': 'application/json',
|
|
635
664
|
'PAYMENT-SIGNATURE': paymentHeader,
|
|
636
665
|
},
|
|
637
|
-
body: requestMethod !== 'GET' ?
|
|
666
|
+
body: requestMethod !== 'GET' ? originalBody : undefined,
|
|
638
667
|
});
|
|
639
668
|
|
|
640
669
|
if (response.ok) {
|
|
@@ -652,14 +681,14 @@ if (btn) {
|
|
|
652
681
|
}
|
|
653
682
|
} catch (err) {
|
|
654
683
|
console.error('[x402] Payment error:', err);
|
|
655
|
-
setBtnState('Pay
|
|
684
|
+
setBtnState('Pay ' + document.getElementById('price-value').textContent, false, false);
|
|
656
685
|
setStatus(err.message || 'Payment failed', 'error');
|
|
657
686
|
}
|
|
658
687
|
});
|
|
659
688
|
}
|
|
660
689
|
</script>
|
|
661
690
|
`;
|
|
662
|
-
function generatePaywallHtml(paymentRequiredHeader, requestUrl, method, config, rpcUrl) {
|
|
691
|
+
function generatePaywallHtml(paymentRequiredHeader, requestUrl, method, config, rpcUrl, requestBody) {
|
|
663
692
|
let price = "?";
|
|
664
693
|
let description = "This resource requires payment";
|
|
665
694
|
let network = "";
|
|
@@ -684,7 +713,7 @@ function generatePaywallHtml(paymentRequiredHeader, requestUrl, method, config,
|
|
|
684
713
|
<head>
|
|
685
714
|
<meta charset="utf-8">
|
|
686
715
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
687
|
-
<title>${config.title} \u2014
|
|
716
|
+
<title>${config.title} \u2014 ${price} USDC</title>
|
|
688
717
|
<style>${DEXTER_STYLES}${PAY_BUTTON_STYLES}</style>
|
|
689
718
|
</head>
|
|
690
719
|
<body>
|
|
@@ -692,12 +721,12 @@ function generatePaywallHtml(paymentRequiredHeader, requestUrl, method, config,
|
|
|
692
721
|
<div class="crest">${DEXTER_CREST_SVG}</div>
|
|
693
722
|
<h1>${config.title}</h1>
|
|
694
723
|
<p class="desc">${description}</p>
|
|
695
|
-
<div class="price"
|
|
724
|
+
<div class="price">${USDC_ICON_SVG}<span id="price-value">${price}</span></div>
|
|
696
725
|
<div class="chain">${chainName}${chainName ? " network" : ""}</div>
|
|
697
726
|
${endpointSection}
|
|
698
727
|
|
|
699
728
|
<div id="pay-section" class="pay-section" style="display:none">
|
|
700
|
-
<button id="pay-btn" class="pay-btn">Pay
|
|
729
|
+
<button id="pay-btn" class="pay-btn">Pay ${price}</button>
|
|
701
730
|
<div id="pay-status" class="pay-status"></div>
|
|
702
731
|
<div class="pay-alt">or use <a href="${config.sdkUrl}">x402 SDK</a> for programmatic access</div>
|
|
703
732
|
</div>
|
|
@@ -712,7 +741,7 @@ function generatePaywallHtml(paymentRequiredHeader, requestUrl, method, config,
|
|
|
712
741
|
</div>
|
|
713
742
|
|
|
714
743
|
<div class="footer">
|
|
715
|
-
<a href="https://
|
|
744
|
+
<a href="https://docs.dexter.cash/docs/sdk/">x402</a>
|
|
716
745
|
<span class="sep"></span>
|
|
717
746
|
<a href="https://dexter.cash">Dexter</a>
|
|
718
747
|
</div>
|
|
@@ -723,6 +752,7 @@ function generatePaywallHtml(paymentRequiredHeader, requestUrl, method, config,
|
|
|
723
752
|
data-method="${method}"
|
|
724
753
|
data-url="${requestUrl}"
|
|
725
754
|
data-rpc="${rpcUrl}"
|
|
755
|
+
data-body="${requestBody ? Buffer.from(requestBody).toString("base64") : ""}"
|
|
726
756
|
></div>
|
|
727
757
|
${PAY_SCRIPT}
|
|
728
758
|
</body>
|
|
@@ -731,8 +761,8 @@ ${PAY_SCRIPT}
|
|
|
731
761
|
function x402BrowserSupport(config = {}) {
|
|
732
762
|
const resolvedConfig = {
|
|
733
763
|
title: config.title ?? "Payment Required",
|
|
734
|
-
branding: config.branding ?? 'Powered by <a href="https://
|
|
735
|
-
sdkUrl: config.sdkUrl ?? "https://
|
|
764
|
+
branding: config.branding ?? 'Powered by <a href="https://docs.dexter.cash/docs/sdk/">Dexter x402</a>',
|
|
765
|
+
sdkUrl: config.sdkUrl ?? "https://docs.dexter.cash/docs/sdk/",
|
|
736
766
|
showEndpoint: config.showEndpoint ?? true
|
|
737
767
|
};
|
|
738
768
|
const rpcUrl = config.rpcUrl ?? "https://api.dexter.cash/api/solana/rpc";
|
|
@@ -742,12 +772,20 @@ function x402BrowserSupport(config = {}) {
|
|
|
742
772
|
if (res.statusCode === 402 && req.accepts("html") && !req.headers["payment-signature"]) {
|
|
743
773
|
const paymentRequired = res.getHeader("PAYMENT-REQUIRED") || res.getHeader("payment-required");
|
|
744
774
|
if (paymentRequired && typeof paymentRequired === "string") {
|
|
775
|
+
let bodyStr;
|
|
776
|
+
if (req.body && typeof req.body === "object" && Object.keys(req.body).length > 0) {
|
|
777
|
+
try {
|
|
778
|
+
bodyStr = JSON.stringify(req.body);
|
|
779
|
+
} catch {
|
|
780
|
+
}
|
|
781
|
+
}
|
|
745
782
|
const html = generatePaywallHtml(
|
|
746
783
|
paymentRequired,
|
|
747
784
|
req.originalUrl,
|
|
748
785
|
req.method,
|
|
749
786
|
resolvedConfig,
|
|
750
|
-
rpcUrl
|
|
787
|
+
rpcUrl,
|
|
788
|
+
bodyStr
|
|
751
789
|
);
|
|
752
790
|
res.status(402).type("html").send(html);
|
|
753
791
|
return res;
|
|
@@ -858,7 +896,7 @@ function x402AccessPass(config) {
|
|
|
858
896
|
ratePerHour: ratePerHour || void 0,
|
|
859
897
|
issuer
|
|
860
898
|
};
|
|
861
|
-
const passInfoEncoded =
|
|
899
|
+
const passInfoEncoded = encodeBase64Json(passInfo);
|
|
862
900
|
function calculateCustomPrice(durationSeconds) {
|
|
863
901
|
if (!ratePerHour) {
|
|
864
902
|
throw new Error("Custom durations not supported \u2014 no ratePerHour configured");
|
|
@@ -948,7 +986,7 @@ function x402AccessPass(config) {
|
|
|
948
986
|
network,
|
|
949
987
|
payer: verifyResult.payer ?? ""
|
|
950
988
|
};
|
|
951
|
-
res.setHeader("PAYMENT-RESPONSE",
|
|
989
|
+
res.setHeader("PAYMENT-RESPONSE", encodeBase64Json(paymentResponseData));
|
|
952
990
|
res.setHeader("ACCESS-PASS", jwt);
|
|
953
991
|
res.json({
|
|
954
992
|
accessPass: {
|