@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.d.cts
CHANGED
|
@@ -343,7 +343,7 @@ interface X402BrowserSupportConfig {
|
|
|
343
343
|
title?: string;
|
|
344
344
|
/** Custom branding text. @default 'Powered by x402' */
|
|
345
345
|
branding?: string;
|
|
346
|
-
/** URL to link for SDK/documentation. @default 'https://
|
|
346
|
+
/** URL to link for SDK/documentation. @default 'https://docs.dexter.cash/docs/sdk/' */
|
|
347
347
|
sdkUrl?: string;
|
|
348
348
|
/** Whether to include the request method and path. @default true */
|
|
349
349
|
showEndpoint?: boolean;
|
package/dist/server/index.d.ts
CHANGED
|
@@ -343,7 +343,7 @@ interface X402BrowserSupportConfig {
|
|
|
343
343
|
title?: string;
|
|
344
344
|
/** Custom branding text. @default 'Powered by x402' */
|
|
345
345
|
branding?: string;
|
|
346
|
-
/** URL to link for SDK/documentation. @default 'https://
|
|
346
|
+
/** URL to link for SDK/documentation. @default 'https://docs.dexter.cash/docs/sdk/' */
|
|
347
347
|
sdkUrl?: string;
|
|
348
348
|
/** Whether to include the request method and path. @default true */
|
|
349
349
|
showEndpoint?: boolean;
|
package/dist/server/index.js
CHANGED
|
@@ -10,8 +10,33 @@ function toAtomicUnits(amount, decimals) {
|
|
|
10
10
|
const multiplier = Math.pow(10, decimals);
|
|
11
11
|
return Math.floor(amount * multiplier).toString();
|
|
12
12
|
}
|
|
13
|
+
function safeBase64Encode(str) {
|
|
14
|
+
if (typeof Buffer !== "undefined") {
|
|
15
|
+
return Buffer.from(str, "utf-8").toString("base64");
|
|
16
|
+
}
|
|
17
|
+
const bytes = new TextEncoder().encode(str);
|
|
18
|
+
let binary = "";
|
|
19
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
20
|
+
binary += String.fromCharCode(bytes[i]);
|
|
21
|
+
}
|
|
22
|
+
return btoa(binary);
|
|
23
|
+
}
|
|
24
|
+
function safeBase64Decode(encoded) {
|
|
25
|
+
if (typeof Buffer !== "undefined") {
|
|
26
|
+
return Buffer.from(encoded, "base64").toString("utf-8");
|
|
27
|
+
}
|
|
28
|
+
const binary = atob(encoded);
|
|
29
|
+
const bytes = new Uint8Array(binary.length);
|
|
30
|
+
for (let i = 0; i < binary.length; i++) {
|
|
31
|
+
bytes[i] = binary.charCodeAt(i);
|
|
32
|
+
}
|
|
33
|
+
return new TextDecoder().decode(bytes);
|
|
34
|
+
}
|
|
35
|
+
function encodeBase64Json(obj) {
|
|
36
|
+
return safeBase64Encode(JSON.stringify(obj));
|
|
37
|
+
}
|
|
13
38
|
function decodeBase64Json(encoded) {
|
|
14
|
-
return JSON.parse(
|
|
39
|
+
return JSON.parse(safeBase64Decode(encoded));
|
|
15
40
|
}
|
|
16
41
|
|
|
17
42
|
// src/server/facilitator-client.ts
|
|
@@ -221,7 +246,7 @@ function createX402Server(config) {
|
|
|
221
246
|
};
|
|
222
247
|
}
|
|
223
248
|
function encodeRequirements(requirements) {
|
|
224
|
-
return
|
|
249
|
+
return encodeBase64Json(requirements);
|
|
225
250
|
}
|
|
226
251
|
function create402Response(requirements) {
|
|
227
252
|
return {
|
|
@@ -345,7 +370,7 @@ function x402Middleware(config) {
|
|
|
345
370
|
network,
|
|
346
371
|
payer: verifyResult.payer ?? ""
|
|
347
372
|
};
|
|
348
|
-
res.setHeader("PAYMENT-RESPONSE",
|
|
373
|
+
res.setHeader("PAYMENT-RESPONSE", encodeBase64Json(paymentResponseData));
|
|
349
374
|
next();
|
|
350
375
|
} catch (error) {
|
|
351
376
|
log("Middleware error:", error);
|
|
@@ -358,6 +383,7 @@ function x402Middleware(config) {
|
|
|
358
383
|
}
|
|
359
384
|
|
|
360
385
|
// src/server/browser-support.ts
|
|
386
|
+
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>`;
|
|
361
387
|
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>`;
|
|
362
388
|
var DEXTER_STYLES = `
|
|
363
389
|
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Orbitron:wght@500;700&display=swap');
|
|
@@ -367,7 +393,8 @@ body{font-family:'Inter',system-ui,-apple-system,sans-serif;background:#0a0a0a;c
|
|
|
367
393
|
.crest{margin:0 auto .75rem}
|
|
368
394
|
h1{font-family:'Orbitron',sans-serif;font-size:1.15rem;font-weight:700;color:#f1f5f9;letter-spacing:.04em;margin-bottom:.35rem}
|
|
369
395
|
.desc{color:#94a3b8;font-size:.9rem;margin-bottom:1.25rem;line-height:1.5}
|
|
370
|
-
.price{font-family:'Orbitron',sans-serif;font-size:1.6rem;font-weight:700;color:#F26B1A;margin:.75rem 0 .25rem}
|
|
396
|
+
.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}
|
|
397
|
+
.price svg{width:1.3em;height:1.3em;flex-shrink:0}
|
|
371
398
|
.chain{color:#525252;font-size:.75rem;margin-bottom:1.25rem;letter-spacing:.03em}
|
|
372
399
|
.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}
|
|
373
400
|
.endpoint code{font-family:'SF Mono',Monaco,Consolas,monospace;font-size:.8rem;color:#F26B1A}
|
|
@@ -562,13 +589,15 @@ if (btn) {
|
|
|
562
589
|
setBtnState('Verifying...', true, true);
|
|
563
590
|
setStatus('Payment submitted, verifying...');
|
|
564
591
|
|
|
592
|
+
// Use the original request body if available
|
|
593
|
+
const originalBody = dataEl.dataset.body ? atob(dataEl.dataset.body) : '{}';
|
|
565
594
|
const response = await fetch(requestUrl, {
|
|
566
595
|
method: requestMethod,
|
|
567
596
|
headers: {
|
|
568
597
|
'Content-Type': 'application/json',
|
|
569
598
|
'PAYMENT-SIGNATURE': paymentHeader,
|
|
570
599
|
},
|
|
571
|
-
body: requestMethod !== 'GET' ?
|
|
600
|
+
body: requestMethod !== 'GET' ? originalBody : undefined,
|
|
572
601
|
});
|
|
573
602
|
|
|
574
603
|
if (response.ok) {
|
|
@@ -586,14 +615,14 @@ if (btn) {
|
|
|
586
615
|
}
|
|
587
616
|
} catch (err) {
|
|
588
617
|
console.error('[x402] Payment error:', err);
|
|
589
|
-
setBtnState('Pay
|
|
618
|
+
setBtnState('Pay ' + document.getElementById('price-value').textContent, false, false);
|
|
590
619
|
setStatus(err.message || 'Payment failed', 'error');
|
|
591
620
|
}
|
|
592
621
|
});
|
|
593
622
|
}
|
|
594
623
|
</script>
|
|
595
624
|
`;
|
|
596
|
-
function generatePaywallHtml(paymentRequiredHeader, requestUrl, method, config, rpcUrl) {
|
|
625
|
+
function generatePaywallHtml(paymentRequiredHeader, requestUrl, method, config, rpcUrl, requestBody) {
|
|
597
626
|
let price = "?";
|
|
598
627
|
let description = "This resource requires payment";
|
|
599
628
|
let network = "";
|
|
@@ -618,7 +647,7 @@ function generatePaywallHtml(paymentRequiredHeader, requestUrl, method, config,
|
|
|
618
647
|
<head>
|
|
619
648
|
<meta charset="utf-8">
|
|
620
649
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
621
|
-
<title>${config.title} \u2014
|
|
650
|
+
<title>${config.title} \u2014 ${price} USDC</title>
|
|
622
651
|
<style>${DEXTER_STYLES}${PAY_BUTTON_STYLES}</style>
|
|
623
652
|
</head>
|
|
624
653
|
<body>
|
|
@@ -626,12 +655,12 @@ function generatePaywallHtml(paymentRequiredHeader, requestUrl, method, config,
|
|
|
626
655
|
<div class="crest">${DEXTER_CREST_SVG}</div>
|
|
627
656
|
<h1>${config.title}</h1>
|
|
628
657
|
<p class="desc">${description}</p>
|
|
629
|
-
<div class="price"
|
|
658
|
+
<div class="price">${USDC_ICON_SVG}<span id="price-value">${price}</span></div>
|
|
630
659
|
<div class="chain">${chainName}${chainName ? " network" : ""}</div>
|
|
631
660
|
${endpointSection}
|
|
632
661
|
|
|
633
662
|
<div id="pay-section" class="pay-section" style="display:none">
|
|
634
|
-
<button id="pay-btn" class="pay-btn">Pay
|
|
663
|
+
<button id="pay-btn" class="pay-btn">Pay ${price}</button>
|
|
635
664
|
<div id="pay-status" class="pay-status"></div>
|
|
636
665
|
<div class="pay-alt">or use <a href="${config.sdkUrl}">x402 SDK</a> for programmatic access</div>
|
|
637
666
|
</div>
|
|
@@ -646,7 +675,7 @@ function generatePaywallHtml(paymentRequiredHeader, requestUrl, method, config,
|
|
|
646
675
|
</div>
|
|
647
676
|
|
|
648
677
|
<div class="footer">
|
|
649
|
-
<a href="https://
|
|
678
|
+
<a href="https://docs.dexter.cash/docs/sdk/">x402</a>
|
|
650
679
|
<span class="sep"></span>
|
|
651
680
|
<a href="https://dexter.cash">Dexter</a>
|
|
652
681
|
</div>
|
|
@@ -657,6 +686,7 @@ function generatePaywallHtml(paymentRequiredHeader, requestUrl, method, config,
|
|
|
657
686
|
data-method="${method}"
|
|
658
687
|
data-url="${requestUrl}"
|
|
659
688
|
data-rpc="${rpcUrl}"
|
|
689
|
+
data-body="${requestBody ? Buffer.from(requestBody).toString("base64") : ""}"
|
|
660
690
|
></div>
|
|
661
691
|
${PAY_SCRIPT}
|
|
662
692
|
</body>
|
|
@@ -665,8 +695,8 @@ ${PAY_SCRIPT}
|
|
|
665
695
|
function x402BrowserSupport(config = {}) {
|
|
666
696
|
const resolvedConfig = {
|
|
667
697
|
title: config.title ?? "Payment Required",
|
|
668
|
-
branding: config.branding ?? 'Powered by <a href="https://
|
|
669
|
-
sdkUrl: config.sdkUrl ?? "https://
|
|
698
|
+
branding: config.branding ?? 'Powered by <a href="https://docs.dexter.cash/docs/sdk/">Dexter x402</a>',
|
|
699
|
+
sdkUrl: config.sdkUrl ?? "https://docs.dexter.cash/docs/sdk/",
|
|
670
700
|
showEndpoint: config.showEndpoint ?? true
|
|
671
701
|
};
|
|
672
702
|
const rpcUrl = config.rpcUrl ?? "https://api.dexter.cash/api/solana/rpc";
|
|
@@ -676,12 +706,20 @@ function x402BrowserSupport(config = {}) {
|
|
|
676
706
|
if (res.statusCode === 402 && req.accepts("html") && !req.headers["payment-signature"]) {
|
|
677
707
|
const paymentRequired = res.getHeader("PAYMENT-REQUIRED") || res.getHeader("payment-required");
|
|
678
708
|
if (paymentRequired && typeof paymentRequired === "string") {
|
|
709
|
+
let bodyStr;
|
|
710
|
+
if (req.body && typeof req.body === "object" && Object.keys(req.body).length > 0) {
|
|
711
|
+
try {
|
|
712
|
+
bodyStr = JSON.stringify(req.body);
|
|
713
|
+
} catch {
|
|
714
|
+
}
|
|
715
|
+
}
|
|
679
716
|
const html = generatePaywallHtml(
|
|
680
717
|
paymentRequired,
|
|
681
718
|
req.originalUrl,
|
|
682
719
|
req.method,
|
|
683
720
|
resolvedConfig,
|
|
684
|
-
rpcUrl
|
|
721
|
+
rpcUrl,
|
|
722
|
+
bodyStr
|
|
685
723
|
);
|
|
686
724
|
res.status(402).type("html").send(html);
|
|
687
725
|
return res;
|
|
@@ -792,7 +830,7 @@ function x402AccessPass(config) {
|
|
|
792
830
|
ratePerHour: ratePerHour || void 0,
|
|
793
831
|
issuer
|
|
794
832
|
};
|
|
795
|
-
const passInfoEncoded =
|
|
833
|
+
const passInfoEncoded = encodeBase64Json(passInfo);
|
|
796
834
|
function calculateCustomPrice(durationSeconds) {
|
|
797
835
|
if (!ratePerHour) {
|
|
798
836
|
throw new Error("Custom durations not supported \u2014 no ratePerHour configured");
|
|
@@ -882,7 +920,7 @@ function x402AccessPass(config) {
|
|
|
882
920
|
network,
|
|
883
921
|
payer: verifyResult.payer ?? ""
|
|
884
922
|
};
|
|
885
|
-
res.setHeader("PAYMENT-RESPONSE",
|
|
923
|
+
res.setHeader("PAYMENT-RESPONSE", encodeBase64Json(paymentResponseData));
|
|
886
924
|
res.setHeader("ACCESS-PASS", jwt);
|
|
887
925
|
res.json({
|
|
888
926
|
accessPass: {
|