@dexterai/x402 1.5.5 → 1.6.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.
@@ -59,6 +59,7 @@ __export(server_exports, {
59
59
  isValidModel: () => isValidModel,
60
60
  isValidModelId: () => isValidModelId,
61
61
  x402AccessPass: () => x402AccessPass,
62
+ x402BrowserSupport: () => x402BrowserSupport,
62
63
  x402Middleware: () => x402Middleware
63
64
  });
64
65
  module.exports = __toCommonJS(server_exports);
@@ -422,6 +423,342 @@ function x402Middleware(config) {
422
423
  };
423
424
  }
424
425
 
426
+ // src/server/browser-support.ts
427
+ 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
+ var DEXTER_STYLES = `
429
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Orbitron:wght@500;700&display=swap');
430
+ *{margin:0;padding:0;box-sizing:border-box}
431
+ body{font-family:'Inter',system-ui,-apple-system,sans-serif;background:#0a0a0a;color:#e2e8f0;min-height:100vh;display:flex;align-items:center;justify-content:center;padding:1rem}
432
+ .card{max-width:460px;width:100%;background:rgba(20,20,20,.85);border:1px solid rgba(242,107,26,.12);border-radius:8px;padding:2rem 2rem 1.75rem;text-align:center;backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px)}
433
+ .crest{margin:0 auto .75rem}
434
+ h1{font-family:'Orbitron',sans-serif;font-size:1.15rem;font-weight:700;color:#f1f5f9;letter-spacing:.04em;margin-bottom:.35rem}
435
+ .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}
437
+ .chain{color:#525252;font-size:.75rem;margin-bottom:1.25rem;letter-spacing:.03em}
438
+ .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
+ .endpoint code{font-family:'SF Mono',Monaco,Consolas,monospace;font-size:.8rem;color:#F26B1A}
440
+ .info{background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.06);border-radius:6px;padding:.85rem 1rem;font-size:.82rem;color:#737373;line-height:1.6;text-align:left}
441
+ .info strong{color:#a3a3a3}
442
+ .info code{background:rgba(242,107,26,.08);padding:2px 5px;border-radius:3px;font-size:.78rem;color:#F26B1A;font-family:'SF Mono',Monaco,Consolas,monospace}
443
+ .info a{color:#F26B1A;text-decoration:none;font-weight:600}
444
+ .info a:hover{text-decoration:underline}
445
+ .footer{margin-top:1.25rem;display:flex;align-items:center;justify-content:center;gap:.75rem;font-size:.7rem;color:#404040}
446
+ .footer a{color:#525252;text-decoration:none}
447
+ .footer a:hover{color:#737373}
448
+ .sep{width:3px;height:3px;border-radius:50%;background:#333}
449
+ `;
450
+ var PAY_BUTTON_STYLES = `
451
+ .pay-section{margin:1.25rem 0}
452
+ .pay-btn{display:inline-flex;align-items:center;justify-content:center;gap:.5rem;background:linear-gradient(135deg,#F26B1A,#D13F00);color:#fff;border:none;padding:.65rem 2rem;border-radius:6px;font-family:'Inter',sans-serif;font-size:.95rem;font-weight:600;cursor:pointer;transition:opacity .15s,transform .1s;min-width:180px}
453
+ .pay-btn:hover:not(:disabled){opacity:.9;transform:translateY(-1px)}
454
+ .pay-btn:active:not(:disabled){transform:translateY(0)}
455
+ .pay-btn:disabled{opacity:.6;cursor:not-allowed}
456
+ .pay-btn .spinner{width:16px;height:16px;border:2px solid rgba(255,255,255,.3);border-top-color:#fff;border-radius:50%;animation:spin .6s linear infinite}
457
+ @keyframes spin{to{transform:rotate(360deg)}}
458
+ .pay-status{font-size:.8rem;color:#737373;margin-top:.5rem;min-height:1.2em}
459
+ .pay-status.error{color:#ef4444}
460
+ .pay-status.success{color:#22c55e}
461
+ .pay-alt{font-size:.78rem;color:#404040;margin-top:.75rem}
462
+ .pay-alt a{color:#F26B1A;text-decoration:none}
463
+ .result-box{background:rgba(34,197,94,.06);border:1px solid rgba(34,197,94,.15);border-radius:6px;padding:.75rem;margin-top:.75rem;text-align:left;font-size:.78rem;max-height:200px;overflow:auto}
464
+ .result-box pre{color:#94a3b8;font-family:'SF Mono',Monaco,Consolas,monospace;white-space:pre-wrap;word-break:break-all}
465
+ .no-wallet{font-size:.82rem;color:#737373;margin:1rem 0}
466
+ `;
467
+ var PAY_SCRIPT = `
468
+ <script type="module">
469
+ // Payment data is embedded in #x402-data attributes
470
+ const dataEl = document.getElementById('x402-data');
471
+ if (!dataEl) throw new Error('Missing payment data');
472
+
473
+ const requirements = JSON.parse(atob(dataEl.dataset.requirements));
474
+ const requestMethod = dataEl.dataset.method;
475
+ const requestUrl = dataEl.dataset.url;
476
+ const rpcUrl = dataEl.dataset.rpc || 'https://api.dexter.cash/api/solana/rpc';
477
+
478
+ // Detect wallet provider
479
+ function getWalletProvider() {
480
+ if (window.phantom?.solana?.isPhantom) return { name: 'Phantom', provider: window.phantom.solana };
481
+ if (window.solflare?.isSolflare) return { name: 'Solflare', provider: window.solflare };
482
+ if (window.backpack) return { name: 'Backpack', provider: window.backpack };
483
+ // Generic wallet-standard fallback
484
+ if (window.solana) return { name: 'Wallet', provider: window.solana };
485
+ return null;
486
+ }
487
+
488
+ const walletInfo = getWalletProvider();
489
+ const btn = document.getElementById('pay-btn');
490
+ const status = document.getElementById('pay-status');
491
+ const section = document.getElementById('pay-section');
492
+ const noWallet = document.getElementById('no-wallet');
493
+
494
+ if (walletInfo && btn) {
495
+ section.style.display = 'block';
496
+ if (noWallet) noWallet.style.display = 'none';
497
+ } else if (noWallet) {
498
+ noWallet.style.display = 'block';
499
+ if (section) section.style.display = 'none';
500
+ }
501
+
502
+ // Preload Solana libraries in background
503
+ let solanaLibs = null;
504
+ const preload = (async () => {
505
+ try {
506
+ const [web3, spl] = await Promise.all([
507
+ import('https://esm.sh/@solana/web3.js@1.98.0'),
508
+ import('https://esm.sh/@solana/spl-token@0.4.9'),
509
+ ]);
510
+ solanaLibs = { web3, spl };
511
+ } catch (e) {
512
+ console.warn('[x402] Failed to preload Solana libraries:', e);
513
+ }
514
+ })();
515
+
516
+ function setStatus(msg, type) {
517
+ if (!status) return;
518
+ status.textContent = msg;
519
+ status.className = 'pay-status' + (type ? ' ' + type : '');
520
+ }
521
+
522
+ function setBtnState(text, disabled, loading) {
523
+ if (!btn) return;
524
+ btn.disabled = disabled;
525
+ btn.innerHTML = loading
526
+ ? '<span class="spinner"></span>' + text
527
+ : text;
528
+ }
529
+
530
+ if (btn) {
531
+ btn.addEventListener('click', async () => {
532
+ if (!walletInfo) return;
533
+ const { provider } = walletInfo;
534
+
535
+ try {
536
+ // 1. Connect wallet
537
+ setBtnState('Connecting...', true, true);
538
+ setStatus('');
539
+ await provider.connect();
540
+
541
+ if (!provider.publicKey) {
542
+ throw new Error('Wallet did not provide a public key');
543
+ }
544
+
545
+ // 2. Load Solana libraries (should already be cached from preload)
546
+ setBtnState('Preparing...', true, true);
547
+ await preload;
548
+ if (!solanaLibs) {
549
+ // Retry once
550
+ const [web3, spl] = await Promise.all([
551
+ import('https://esm.sh/@solana/web3.js@1.98.0'),
552
+ import('https://esm.sh/@solana/spl-token@0.4.9'),
553
+ ]);
554
+ solanaLibs = { web3, spl };
555
+ }
556
+
557
+ const { web3, spl } = solanaLibs;
558
+ const { PublicKey, Connection, TransactionMessage, VersionedTransaction, ComputeBudgetProgram } = web3;
559
+ const { getAssociatedTokenAddress, createTransferCheckedInstruction, getMint, TOKEN_PROGRAM_ID, TOKEN_2022_PROGRAM_ID } = spl;
560
+
561
+ // 3. Parse payment requirements
562
+ const accept = requirements.accepts[0];
563
+ if (!accept) throw new Error('No payment method available');
564
+
565
+ const payTo = new PublicKey(accept.payTo);
566
+ const amount = BigInt(accept.amount || accept.maxAmountRequired);
567
+ const mintPubkey = new PublicKey(accept.asset);
568
+ const feePayer = accept.extra?.feePayer ? new PublicKey(accept.extra.feePayer) : provider.publicKey;
569
+ const userPubkey = provider.publicKey;
570
+
571
+ // 4. Build transaction
572
+ setBtnState('Building tx...', true, true);
573
+ const connection = new Connection(rpcUrl, 'confirmed');
574
+
575
+ const instructions = [];
576
+
577
+ // ComputeBudget
578
+ instructions.push(ComputeBudgetProgram.setComputeUnitLimit({ units: 12000 }));
579
+ instructions.push(ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 1 }));
580
+
581
+ // Determine token program
582
+ const mintInfo = await connection.getAccountInfo(mintPubkey, 'confirmed');
583
+ if (!mintInfo) throw new Error('Token mint not found');
584
+ const programId = mintInfo.owner.toBase58() === TOKEN_2022_PROGRAM_ID.toBase58() ? TOKEN_2022_PROGRAM_ID : TOKEN_PROGRAM_ID;
585
+
586
+ const mint = await getMint(connection, mintPubkey, undefined, programId);
587
+
588
+ // ATAs
589
+ const sourceAta = await getAssociatedTokenAddress(mintPubkey, userPubkey, false, programId);
590
+ const destAta = await getAssociatedTokenAddress(mintPubkey, payTo, false, programId);
591
+
592
+ // Verify source exists
593
+ const sourceInfo = await connection.getAccountInfo(sourceAta, 'confirmed');
594
+ if (!sourceInfo) throw new Error('No USDC token account found. Make sure you have USDC in your wallet.');
595
+
596
+ // TransferChecked
597
+ instructions.push(createTransferCheckedInstruction(sourceAta, mintPubkey, destAta, userPubkey, amount, mint.decimals, [], programId));
598
+
599
+ const { blockhash } = await connection.getLatestBlockhash('confirmed');
600
+ const message = new TransactionMessage({ payerKey: feePayer, recentBlockhash: blockhash, instructions }).compileToV0Message();
601
+ const transaction = new VersionedTransaction(message);
602
+
603
+ // 5. Sign
604
+ setBtnState('Sign in wallet...', true, true);
605
+ setStatus('Approve the transaction in your wallet');
606
+ const signed = await provider.signTransaction(transaction);
607
+ const serialized = signed.serialize();
608
+
609
+ // Convert Uint8Array to base64
610
+ let payload = '';
611
+ const bytes = new Uint8Array(serialized);
612
+ const chunk = 8192;
613
+ for (let i = 0; i < bytes.length; i += chunk) {
614
+ payload += String.fromCharCode.apply(null, bytes.slice(i, i + chunk));
615
+ }
616
+ payload = btoa(payload);
617
+
618
+ // 6. Build payment-signature header (x402 v2 format)
619
+ const paymentSignature = {
620
+ x402Version: accept.x402Version ?? 2,
621
+ resource: requirements.resource,
622
+ accepted: accept,
623
+ payload,
624
+ };
625
+ const paymentHeader = btoa(JSON.stringify(paymentSignature));
626
+
627
+ // 7. Submit payment
628
+ setBtnState('Verifying...', true, true);
629
+ setStatus('Payment submitted, verifying...');
630
+
631
+ const response = await fetch(requestUrl, {
632
+ method: requestMethod,
633
+ headers: {
634
+ 'Content-Type': 'application/json',
635
+ 'PAYMENT-SIGNATURE': paymentHeader,
636
+ },
637
+ body: requestMethod !== 'GET' ? '{}' : undefined,
638
+ });
639
+
640
+ if (response.ok) {
641
+ const data = await response.json();
642
+ setBtnState('Paid', true, false);
643
+ setStatus('Payment successful', 'success');
644
+ // Show response
645
+ const resultBox = document.createElement('div');
646
+ resultBox.className = 'result-box';
647
+ resultBox.innerHTML = '<pre>' + JSON.stringify(data, null, 2).replace(/</g, '&lt;') + '</pre>';
648
+ section.appendChild(resultBox);
649
+ } else {
650
+ const err = await response.json().catch(() => ({ error: 'Payment verification failed' }));
651
+ throw new Error(err.error || err.reason || 'Payment failed');
652
+ }
653
+ } catch (err) {
654
+ console.error('[x402] Payment error:', err);
655
+ setBtnState('Pay $' + document.getElementById('price-value').textContent, false, false);
656
+ setStatus(err.message || 'Payment failed', 'error');
657
+ }
658
+ });
659
+ }
660
+ </script>
661
+ `;
662
+ function generatePaywallHtml(paymentRequiredHeader, requestUrl, method, config, rpcUrl) {
663
+ let price = "?";
664
+ let description = "This resource requires payment";
665
+ let network = "";
666
+ try {
667
+ const decoded = JSON.parse(Buffer.from(paymentRequiredHeader, "base64").toString());
668
+ const accept = decoded.accepts?.[0];
669
+ if (accept) {
670
+ const amount = accept.amount || accept.maxAmountRequired || "0";
671
+ const decimals = accept.extra?.decimals || 6;
672
+ price = (Number(amount) / Math.pow(10, decimals)).toFixed(decimals > 4 ? 4 : 2);
673
+ network = accept.network || "";
674
+ }
675
+ if (decoded.resource?.description) {
676
+ description = decoded.resource.description;
677
+ }
678
+ } catch {
679
+ }
680
+ const chainName = network.includes("solana") ? "Solana" : network.includes("eip155") ? "Base" : "";
681
+ const endpointSection = config.showEndpoint ? `<div class="endpoint"><code>${method} ${requestUrl}</code></div>` : "";
682
+ return `<!DOCTYPE html>
683
+ <html lang="en">
684
+ <head>
685
+ <meta charset="utf-8">
686
+ <meta name="viewport" content="width=device-width,initial-scale=1">
687
+ <title>${config.title} \u2014 $${price} USDC</title>
688
+ <style>${DEXTER_STYLES}${PAY_BUTTON_STYLES}</style>
689
+ </head>
690
+ <body>
691
+ <div class="card">
692
+ <div class="crest">${DEXTER_CREST_SVG}</div>
693
+ <h1>${config.title}</h1>
694
+ <p class="desc">${description}</p>
695
+ <div class="price">$<span id="price-value">${price}</span> USDC</div>
696
+ <div class="chain">${chainName}${chainName ? " network" : ""}</div>
697
+ ${endpointSection}
698
+
699
+ <div id="pay-section" class="pay-section" style="display:none">
700
+ <button id="pay-btn" class="pay-btn">Pay $${price}</button>
701
+ <div id="pay-status" class="pay-status"></div>
702
+ <div class="pay-alt">or use <a href="${config.sdkUrl}">x402 SDK</a> for programmatic access</div>
703
+ </div>
704
+
705
+ <div id="no-wallet" class="no-wallet" style="display:none">
706
+ <div class="info">
707
+ <strong>Access this endpoint:</strong><br><br>
708
+ Use any x402-compatible client or a browser with a Solana wallet extension (Phantom, Solflare, Backpack).<br><br>
709
+ <code>npm install @dexterai/x402</code><br><br>
710
+ <a href="${config.sdkUrl}">x402 SDK docs &rarr;</a>
711
+ </div>
712
+ </div>
713
+
714
+ <div class="footer">
715
+ <a href="https://x402.org">x402</a>
716
+ <span class="sep"></span>
717
+ <a href="https://dexter.cash">Dexter</a>
718
+ </div>
719
+ </div>
720
+
721
+ <div id="x402-data" style="display:none"
722
+ data-requirements="${paymentRequiredHeader}"
723
+ data-method="${method}"
724
+ data-url="${requestUrl}"
725
+ data-rpc="${rpcUrl}"
726
+ ></div>
727
+ ${PAY_SCRIPT}
728
+ </body>
729
+ </html>`;
730
+ }
731
+ function x402BrowserSupport(config = {}) {
732
+ const resolvedConfig = {
733
+ title: config.title ?? "Payment Required",
734
+ branding: config.branding ?? 'Powered by <a href="https://x402.org">x402</a>',
735
+ sdkUrl: config.sdkUrl ?? "https://x402.org",
736
+ showEndpoint: config.showEndpoint ?? true
737
+ };
738
+ const rpcUrl = config.rpcUrl ?? "https://api.dexter.cash/api/solana/rpc";
739
+ return (req, res, next) => {
740
+ const originalJson = res.json.bind(res);
741
+ res.json = function(body) {
742
+ if (res.statusCode === 402 && req.accepts("html") && !req.headers["payment-signature"]) {
743
+ const paymentRequired = res.getHeader("PAYMENT-REQUIRED") || res.getHeader("payment-required");
744
+ if (paymentRequired && typeof paymentRequired === "string") {
745
+ const html = generatePaywallHtml(
746
+ paymentRequired,
747
+ req.originalUrl,
748
+ req.method,
749
+ resolvedConfig,
750
+ rpcUrl
751
+ );
752
+ res.status(402).type("html").send(html);
753
+ return res;
754
+ }
755
+ }
756
+ return originalJson(body);
757
+ };
758
+ next();
759
+ };
760
+ }
761
+
425
762
  // src/server/access-pass.ts
426
763
  var import_crypto = __toESM(require("crypto"), 1);
427
764
  var DURATION_REGEX = /^(\d+)(m|h|d|w)$/;
@@ -1462,6 +1799,7 @@ function formatTokenPricing(model = DEFAULT_MODEL) {
1462
1799
  isValidModel,
1463
1800
  isValidModelId,
1464
1801
  x402AccessPass,
1802
+ x402BrowserSupport,
1465
1803
  x402Middleware
1466
1804
  });
1467
1805
  //# sourceMappingURL=index.cjs.map