@dexterai/x402 1.9.2 → 1.9.4

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 (37) hide show
  1. package/dist/adapters/index.cjs +14 -5
  2. package/dist/adapters/index.cjs.map +1 -1
  3. package/dist/adapters/index.d.cts +5 -5
  4. package/dist/adapters/index.d.ts +5 -5
  5. package/dist/adapters/index.js +14 -5
  6. package/dist/adapters/index.js.map +1 -1
  7. package/dist/client/index.cjs +60 -24
  8. package/dist/client/index.cjs.map +1 -1
  9. package/dist/client/index.d.cts +22 -8
  10. package/dist/client/index.d.ts +22 -8
  11. package/dist/client/index.js +59 -24
  12. package/dist/client/index.js.map +1 -1
  13. package/dist/react/index.cjs +63 -30
  14. package/dist/react/index.cjs.map +1 -1
  15. package/dist/react/index.d.cts +10 -5
  16. package/dist/react/index.d.ts +10 -5
  17. package/dist/react/index.js +63 -30
  18. package/dist/react/index.js.map +1 -1
  19. package/dist/server/index.cjs +36 -10
  20. package/dist/server/index.cjs.map +1 -1
  21. package/dist/server/index.d.cts +48 -14
  22. package/dist/server/index.d.ts +48 -14
  23. package/dist/server/index.js +35 -10
  24. package/dist/server/index.js.map +1 -1
  25. package/dist/{solana-CfHuiW2H.d.cts → solana-BcOfK6Eq.d.cts} +2 -2
  26. package/dist/{solana-kZcwbUK9.d.ts → solana-Cxr5byPa.d.ts} +2 -2
  27. package/dist/{sponsored-access-H1EX6zpi.d.ts → sponsored-access-Br6YPA-m.d.cts} +20 -2
  28. package/dist/{sponsored-access-BCB2CxdG.d.cts → sponsored-access-D1_mINs4.d.ts} +20 -2
  29. package/dist/{types-ENcnkof8.d.ts → types-BIHhO2-I.d.ts} +1 -1
  30. package/dist/{types-DmqH9yD8.d.cts → types-CfKflCZO.d.cts} +1 -1
  31. package/dist/{types-BQvaF8lB.d.cts → types-CjLMR7qs.d.cts} +1 -1
  32. package/dist/{types-BQvaF8lB.d.ts → types-CjLMR7qs.d.ts} +1 -1
  33. package/dist/utils/index.cjs +8 -6
  34. package/dist/utils/index.cjs.map +1 -1
  35. package/dist/utils/index.js +8 -6
  36. package/dist/utils/index.js.map +1 -1
  37. package/package.json +1 -1
@@ -1,10 +1,10 @@
1
- import { a as X402Client } from '../sponsored-access-BCB2CxdG.cjs';
2
- export { f as fireImpressionBeacon, b as getSponsoredRecommendations } from '../sponsored-access-BCB2CxdG.cjs';
3
- import { W as WalletSet, B as BalanceInfo } from '../types-DmqH9yD8.cjs';
1
+ import { a as X402Client } from '../sponsored-access-Br6YPA-m.cjs';
2
+ export { f as fireImpressionBeacon, b as getSponsoredRecommendations } from '../sponsored-access-Br6YPA-m.cjs';
3
+ import { W as WalletSet, B as BalanceInfo } from '../types-CfKflCZO.cjs';
4
4
  import { SponsoredRecommendation } from '@dexterai/x402-ads-types';
5
5
  export { SponsoredRecommendation } from '@dexterai/x402-ads-types';
6
- import { a as AccessPassTier } from '../types-BQvaF8lB.cjs';
7
- export { A as AccessPassClientConfig, b as AccessPassInfo, X as X402Error } from '../types-BQvaF8lB.cjs';
6
+ import { a as AccessPassTier } from '../types-CjLMR7qs.cjs';
7
+ export { A as AccessPassClientConfig, b as AccessPassInfo, X as X402Error } from '../types-CjLMR7qs.cjs';
8
8
 
9
9
  /**
10
10
  * React Hook for x402 v2 Payments
@@ -135,6 +135,11 @@ declare function useX402Payment(config: UseX402PaymentConfig): UseX402PaymentRet
135
135
  * Dedicated hook for managing the access pass lifecycle:
136
136
  * tier discovery, pass purchase, token caching, and auto-fetch with pass.
137
137
  *
138
+ * **Storage:** Access pass JWTs are stored in `sessionStorage` (cleared on browser close).
139
+ * This means passes don't persist across tabs or sessions. The JWT is accessible to
140
+ * any JavaScript on the page — ensure your site is free of XSS vulnerabilities.
141
+ * The server re-verifies the JWT signature on every request regardless.
142
+ *
138
143
  * @example
139
144
  * ```tsx
140
145
  * import { useAccessPass } from '@dexterai/x402/react';
@@ -1,10 +1,10 @@
1
- import { a as X402Client } from '../sponsored-access-H1EX6zpi.js';
2
- export { f as fireImpressionBeacon, b as getSponsoredRecommendations } from '../sponsored-access-H1EX6zpi.js';
3
- import { W as WalletSet, B as BalanceInfo } from '../types-ENcnkof8.js';
1
+ import { a as X402Client } from '../sponsored-access-D1_mINs4.js';
2
+ export { f as fireImpressionBeacon, b as getSponsoredRecommendations } from '../sponsored-access-D1_mINs4.js';
3
+ import { W as WalletSet, B as BalanceInfo } from '../types-BIHhO2-I.js';
4
4
  import { SponsoredRecommendation } from '@dexterai/x402-ads-types';
5
5
  export { SponsoredRecommendation } from '@dexterai/x402-ads-types';
6
- import { a as AccessPassTier } from '../types-BQvaF8lB.js';
7
- export { A as AccessPassClientConfig, b as AccessPassInfo, X as X402Error } from '../types-BQvaF8lB.js';
6
+ import { a as AccessPassTier } from '../types-CjLMR7qs.js';
7
+ export { A as AccessPassClientConfig, b as AccessPassInfo, X as X402Error } from '../types-CjLMR7qs.js';
8
8
 
9
9
  /**
10
10
  * React Hook for x402 v2 Payments
@@ -135,6 +135,11 @@ declare function useX402Payment(config: UseX402PaymentConfig): UseX402PaymentRet
135
135
  * Dedicated hook for managing the access pass lifecycle:
136
136
  * tier discovery, pass purchase, token caching, and auto-fetch with pass.
137
137
  *
138
+ * **Storage:** Access pass JWTs are stored in `sessionStorage` (cleared on browser close).
139
+ * This means passes don't persist across tabs or sessions. The JWT is accessible to
140
+ * any JavaScript on the page — ensure your site is free of XSS vulnerabilities.
141
+ * The server re-verifies the JWT signature on every request regardless.
142
+ *
138
143
  * @example
139
144
  * ```tsx
140
145
  * import { useAccessPass } from '@dexterai/x402/react';
@@ -109,8 +109,11 @@ var SolanaAdapter = class {
109
109
  const account = await getAccount(connection, ata, void 0, programId);
110
110
  const decimals = accept.extra?.decimals ?? 6;
111
111
  return Number(account.amount) / Math.pow(10, decimals);
112
- } catch {
113
- return 0;
112
+ } catch (err) {
113
+ if (err && typeof err === "object" && "name" in err && (err.name === "TokenAccountNotFoundError" || err.name === "TokenInvalidAccountOwnerError")) {
114
+ return 0;
115
+ }
116
+ throw err;
114
117
  }
115
118
  }
116
119
  async buildTransaction(accept, wallet, rpcUrl) {
@@ -338,15 +341,21 @@ var EvmAdapter = class {
338
341
  ]
339
342
  })
340
343
  });
344
+ if (!response.ok) {
345
+ throw new Error(`RPC request failed: ${response.status}`);
346
+ }
341
347
  const result = await response.json();
342
- if (result.error || !result.result) {
348
+ if (result.error) {
349
+ throw new Error(`RPC error: ${JSON.stringify(result.error)}`);
350
+ }
351
+ if (!result.result || result.result === "0x") {
343
352
  return 0;
344
353
  }
345
354
  const balance = BigInt(result.result);
346
355
  const decimals = accept.extra?.decimals ?? 6;
347
356
  return Number(balance) / Math.pow(10, decimals);
348
- } catch {
349
- return 0;
357
+ } catch (err) {
358
+ throw err;
350
359
  }
351
360
  }
352
361
  encodeBalanceOf(address) {
@@ -462,7 +471,8 @@ function createX402Client(config) {
462
471
  maxAmountAtomic,
463
472
  fetch: customFetch = globalThis.fetch,
464
473
  verbose = false,
465
- accessPass: accessPassConfig
474
+ accessPass: accessPassConfig,
475
+ onPaymentRequired
466
476
  } = config;
467
477
  const log = verbose ? console.log.bind(console, "[x402]") : () => {
468
478
  };
@@ -575,13 +585,17 @@ function createX402Client(config) {
575
585
  const paymentAmount = accept.amount ?? accept.maxAmountRequired;
576
586
  if (!paymentAmount) return null;
577
587
  const rpcUrl = getRpcUrl(accept.network, adapter);
578
- const balance = await adapter.getBalance(accept, wallet, rpcUrl);
579
- const requiredAmount = Number(paymentAmount) / Math.pow(10, decimals);
580
- if (balance < requiredAmount) {
581
- throw new X402Error(
582
- "insufficient_balance",
583
- `Insufficient balance for access pass. Have $${balance.toFixed(4)}, need $${requiredAmount.toFixed(4)}`
584
- );
588
+ try {
589
+ const balance = await adapter.getBalance(accept, wallet, rpcUrl);
590
+ const requiredAmount = Number(paymentAmount) / Math.pow(10, decimals);
591
+ if (balance < requiredAmount) {
592
+ throw new X402Error(
593
+ "insufficient_balance",
594
+ `Insufficient balance for access pass. Have $${balance.toFixed(4)}, need $${requiredAmount.toFixed(4)}`
595
+ );
596
+ }
597
+ } catch (err) {
598
+ if (err instanceof X402Error) throw err;
585
599
  }
586
600
  const signedTx = await adapter.buildTransaction(accept, wallet, rpcUrl);
587
601
  let payload;
@@ -594,13 +608,19 @@ function createX402Client(config) {
594
608
  let resolvedResource = requirements.resource;
595
609
  if (typeof requirements.resource === "string") {
596
610
  try {
597
- resolvedResource = new URL(requirements.resource, originalUrl).toString();
611
+ const resolved = new URL(requirements.resource, originalUrl);
612
+ if (["http:", "https:"].includes(resolved.protocol)) {
613
+ resolvedResource = resolved.toString();
614
+ }
598
615
  } catch {
599
616
  }
600
617
  } else if (requirements.resource && typeof requirements.resource === "object" && "url" in requirements.resource) {
601
618
  const rObj = requirements.resource;
602
619
  try {
603
- resolvedResource = { ...rObj, url: new URL(rObj.url, originalUrl).toString() };
620
+ const resolved = new URL(rObj.url, originalUrl);
621
+ if (["http:", "https:"].includes(resolved.protocol)) {
622
+ resolvedResource = { ...rObj, url: resolved.toString() };
623
+ }
604
624
  } catch {
605
625
  }
606
626
  }
@@ -728,16 +748,27 @@ function createX402Client(config) {
728
748
  }
729
749
  const rpcUrl = getRpcUrl(accept.network, adapter);
730
750
  log("Checking balance...");
731
- const balance = await adapter.getBalance(accept, wallet, rpcUrl);
732
- const requiredAmount = Number(paymentAmount) / Math.pow(10, decimals);
733
- if (balance < requiredAmount) {
734
- const network = adapter.name === "EVM" ? "Base" : "Solana";
735
- throw new X402Error(
736
- "insufficient_balance",
737
- `Insufficient USDC balance on ${network}. Have $${balance.toFixed(4)}, need $${requiredAmount.toFixed(4)}`
738
- );
751
+ try {
752
+ const balance = await adapter.getBalance(accept, wallet, rpcUrl);
753
+ const requiredAmount = Number(paymentAmount) / Math.pow(10, decimals);
754
+ if (balance < requiredAmount) {
755
+ const network = adapter.name === "EVM" ? "Base" : "Solana";
756
+ throw new X402Error(
757
+ "insufficient_balance",
758
+ `Insufficient USDC balance on ${network}. Have $${balance.toFixed(4)}, need $${requiredAmount.toFixed(4)}`
759
+ );
760
+ }
761
+ log(`Balance OK: $${balance.toFixed(4)} >= $${requiredAmount.toFixed(4)}`);
762
+ } catch (err) {
763
+ if (err instanceof X402Error) throw err;
764
+ log("Balance check failed (RPC error), proceeding with transaction attempt");
765
+ }
766
+ if (onPaymentRequired) {
767
+ const approved = await onPaymentRequired(accept);
768
+ if (!approved) {
769
+ throw new X402Error("payment_rejected", "Payment rejected by onPaymentRequired callback");
770
+ }
739
771
  }
740
- log(`Balance OK: $${balance.toFixed(4)} >= $${requiredAmount.toFixed(4)}`);
741
772
  log("Building transaction...");
742
773
  const signedTx = await adapter.buildTransaction(accept, wallet, rpcUrl);
743
774
  log("Transaction signed");
@@ -822,13 +853,15 @@ function createX402Client(config) {
822
853
  }
823
854
 
824
855
  // src/utils.ts
856
+ function isSolanaNetwork(network) {
857
+ return network.startsWith("solana:") || network === "solana";
858
+ }
859
+ function isEvmNetwork(network) {
860
+ return network.startsWith("eip155:") || ["base", "ethereum", "arbitrum"].includes(network);
861
+ }
825
862
  function getChainFamily(network) {
826
- if (network.startsWith("solana:") || network === "solana") {
827
- return "solana";
828
- }
829
- if (network.startsWith("eip155:") || ["base", "ethereum", "arbitrum"].includes(network)) {
830
- return "evm";
831
- }
863
+ if (isSolanaNetwork(network)) return "solana";
864
+ if (isEvmNetwork(network)) return "evm";
832
865
  return "unknown";
833
866
  }
834
867
  function getChainName(network) {