@alleyboss/micropay-solana-x402-paywall 1.0.1 → 2.0.0

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 (62) hide show
  1. package/README.md +100 -167
  2. package/dist/client/index.cjs +99 -0
  3. package/dist/client/index.cjs.map +1 -0
  4. package/dist/client/index.d.cts +112 -0
  5. package/dist/client/index.d.ts +112 -0
  6. package/dist/client/index.js +95 -0
  7. package/dist/client/index.js.map +1 -0
  8. package/dist/client-CSZHI8o8.d.ts +32 -0
  9. package/dist/client-vRr48m2x.d.cts +32 -0
  10. package/dist/index.cjs +624 -6
  11. package/dist/index.cjs.map +1 -1
  12. package/dist/index.d.cts +11 -3
  13. package/dist/index.d.ts +11 -3
  14. package/dist/index.js +604 -7
  15. package/dist/index.js.map +1 -1
  16. package/dist/memory-Daxkczti.d.cts +29 -0
  17. package/dist/memory-Daxkczti.d.ts +29 -0
  18. package/dist/middleware/index.cjs +261 -0
  19. package/dist/middleware/index.cjs.map +1 -0
  20. package/dist/middleware/index.d.cts +90 -0
  21. package/dist/middleware/index.d.ts +90 -0
  22. package/dist/middleware/index.js +255 -0
  23. package/dist/middleware/index.js.map +1 -0
  24. package/dist/nextjs-BK0pVb9Y.d.ts +78 -0
  25. package/dist/nextjs-Bm272Jkj.d.cts +78 -0
  26. package/dist/{client-kfCr7G-P.d.cts → payment-CTxdtqmc.d.cts} +23 -34
  27. package/dist/{client-kfCr7G-P.d.ts → payment-CTxdtqmc.d.ts} +23 -34
  28. package/dist/pricing/index.cjs +79 -0
  29. package/dist/pricing/index.cjs.map +1 -0
  30. package/dist/pricing/index.d.cts +67 -0
  31. package/dist/pricing/index.d.ts +67 -0
  32. package/dist/pricing/index.js +72 -0
  33. package/dist/pricing/index.js.map +1 -0
  34. package/dist/session/index.d.cts +29 -1
  35. package/dist/session/index.d.ts +29 -1
  36. package/dist/{index-uxMb72hH.d.cts → session-D2IoWAWV.d.cts} +1 -27
  37. package/dist/{index-uxMb72hH.d.ts → session-D2IoWAWV.d.ts} +1 -27
  38. package/dist/solana/index.cjs +193 -0
  39. package/dist/solana/index.cjs.map +1 -1
  40. package/dist/solana/index.d.cts +60 -3
  41. package/dist/solana/index.d.ts +60 -3
  42. package/dist/solana/index.js +190 -1
  43. package/dist/solana/index.js.map +1 -1
  44. package/dist/store/index.cjs +99 -0
  45. package/dist/store/index.cjs.map +1 -0
  46. package/dist/store/index.d.cts +38 -0
  47. package/dist/store/index.d.ts +38 -0
  48. package/dist/store/index.js +96 -0
  49. package/dist/store/index.js.map +1 -0
  50. package/dist/utils/index.cjs +68 -0
  51. package/dist/utils/index.cjs.map +1 -0
  52. package/dist/utils/index.d.cts +30 -0
  53. package/dist/utils/index.d.ts +30 -0
  54. package/dist/utils/index.js +65 -0
  55. package/dist/utils/index.js.map +1 -0
  56. package/dist/x402/index.cjs +2 -1
  57. package/dist/x402/index.cjs.map +1 -1
  58. package/dist/x402/index.d.cts +2 -1
  59. package/dist/x402/index.d.ts +2 -1
  60. package/dist/x402/index.js +2 -1
  61. package/dist/x402/index.js.map +1 -1
  62. package/package.json +56 -3
@@ -0,0 +1,79 @@
1
+ 'use strict';
2
+
3
+ // src/pricing/index.ts
4
+ var cachedPrice = null;
5
+ var CACHE_TTL_MS = 6e4;
6
+ async function getSolPrice() {
7
+ if (cachedPrice && Date.now() - cachedPrice.fetchedAt.getTime() < CACHE_TTL_MS) {
8
+ return cachedPrice;
9
+ }
10
+ try {
11
+ const response = await fetch(
12
+ "https://api.coingecko.com/api/v3/simple/price?ids=solana&vs_currencies=usd",
13
+ {
14
+ headers: { "Accept": "application/json" },
15
+ signal: AbortSignal.timeout(5e3)
16
+ }
17
+ );
18
+ if (!response.ok) {
19
+ throw new Error(`Price fetch failed: ${response.status}`);
20
+ }
21
+ const data = await response.json();
22
+ if (!data.solana?.usd) {
23
+ throw new Error("Invalid price response");
24
+ }
25
+ cachedPrice = {
26
+ solPrice: data.solana.usd,
27
+ fetchedAt: /* @__PURE__ */ new Date(),
28
+ source: "coingecko"
29
+ };
30
+ return cachedPrice;
31
+ } catch (error) {
32
+ if (cachedPrice) {
33
+ return cachedPrice;
34
+ }
35
+ return {
36
+ solPrice: 150,
37
+ // Fallback price
38
+ fetchedAt: /* @__PURE__ */ new Date(),
39
+ source: "fallback"
40
+ };
41
+ }
42
+ }
43
+ async function lamportsToUsd(lamports) {
44
+ const { solPrice } = await getSolPrice();
45
+ const sol = Number(lamports) / 1e9;
46
+ return sol * solPrice;
47
+ }
48
+ async function usdToLamports(usd) {
49
+ const { solPrice } = await getSolPrice();
50
+ const sol = usd / solPrice;
51
+ return BigInt(Math.floor(sol * 1e9));
52
+ }
53
+ async function formatPriceDisplay(lamports) {
54
+ const { solPrice } = await getSolPrice();
55
+ const sol = Number(lamports) / 1e9;
56
+ const usd = sol * solPrice;
57
+ return `${sol.toFixed(4)} SOL (~$${usd.toFixed(2)})`;
58
+ }
59
+ function formatPriceSync(lamports, solPrice) {
60
+ const sol = Number(lamports) / 1e9;
61
+ const usd = sol * solPrice;
62
+ return {
63
+ sol,
64
+ usd,
65
+ formatted: `${sol.toFixed(4)} SOL (~$${usd.toFixed(2)})`
66
+ };
67
+ }
68
+ function clearPriceCache() {
69
+ cachedPrice = null;
70
+ }
71
+
72
+ exports.clearPriceCache = clearPriceCache;
73
+ exports.formatPriceDisplay = formatPriceDisplay;
74
+ exports.formatPriceSync = formatPriceSync;
75
+ exports.getSolPrice = getSolPrice;
76
+ exports.lamportsToUsd = lamportsToUsd;
77
+ exports.usdToLamports = usdToLamports;
78
+ //# sourceMappingURL=index.cjs.map
79
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/pricing/index.ts"],"names":[],"mappings":";;;AAkBA,IAAI,WAAA,GAAgC,IAAA;AACpC,IAAM,YAAA,GAAe,GAAA;AAYrB,eAAsB,WAAA,GAAkC;AAEpD,EAAA,IAAI,WAAA,IAAe,KAAK,GAAA,EAAI,GAAI,YAAY,SAAA,CAAU,OAAA,KAAY,YAAA,EAAc;AAC5E,IAAA,OAAO,WAAA;AAAA,EACX;AAEA,EAAA,IAAI;AAEA,IAAA,MAAM,WAAW,MAAM,KAAA;AAAA,MACnB,4EAAA;AAAA,MACA;AAAA,QACI,OAAA,EAAS,EAAE,QAAA,EAAU,kBAAA,EAAmB;AAAA,QACxC,MAAA,EAAQ,WAAA,CAAY,OAAA,CAAQ,GAAI;AAAA;AACpC,KACJ;AAEA,IAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AACd,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,oBAAA,EAAuB,QAAA,CAAS,MAAM,CAAA,CAAE,CAAA;AAAA,IAC5D;AAEA,IAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,IAAA,EAAK;AAEjC,IAAA,IAAI,CAAC,IAAA,CAAK,MAAA,EAAQ,GAAA,EAAK;AACnB,MAAA,MAAM,IAAI,MAAM,wBAAwB,CAAA;AAAA,IAC5C;AAEA,IAAA,WAAA,GAAc;AAAA,MACV,QAAA,EAAU,KAAK,MAAA,CAAO,GAAA;AAAA,MACtB,SAAA,sBAAe,IAAA,EAAK;AAAA,MACpB,MAAA,EAAQ;AAAA,KACZ;AAEA,IAAA,OAAO,WAAA;AAAA,EACX,SAAS,KAAA,EAAO;AAEZ,IAAA,IAAI,WAAA,EAAa;AACb,MAAA,OAAO,WAAA;AAAA,IACX;AAGA,IAAA,OAAO;AAAA,MACH,QAAA,EAAU,GAAA;AAAA;AAAA,MACV,SAAA,sBAAe,IAAA,EAAK;AAAA,MACpB,MAAA,EAAQ;AAAA,KACZ;AAAA,EACJ;AACJ;AAWA,eAAsB,cAAc,QAAA,EAAmC;AACnE,EAAA,MAAM,EAAE,QAAA,EAAS,GAAI,MAAM,WAAA,EAAY;AACvC,EAAA,MAAM,GAAA,GAAM,MAAA,CAAO,QAAQ,CAAA,GAAI,GAAA;AAC/B,EAAA,OAAO,GAAA,GAAM,QAAA;AACjB;AAWA,eAAsB,cAAc,GAAA,EAA8B;AAC9D,EAAA,MAAM,EAAE,QAAA,EAAS,GAAI,MAAM,WAAA,EAAY;AACvC,EAAA,MAAM,MAAM,GAAA,GAAM,QAAA;AAClB,EAAA,OAAO,MAAA,CAAO,IAAA,CAAK,KAAA,CAAM,GAAA,GAAM,GAAa,CAAC,CAAA;AACjD;AAWA,eAAsB,mBAAmB,QAAA,EAAmC;AACxE,EAAA,MAAM,EAAE,QAAA,EAAS,GAAI,MAAM,WAAA,EAAY;AACvC,EAAA,MAAM,GAAA,GAAM,MAAA,CAAO,QAAQ,CAAA,GAAI,GAAA;AAC/B,EAAA,MAAM,MAAM,GAAA,GAAM,QAAA;AAElB,EAAA,OAAO,CAAA,EAAG,IAAI,OAAA,CAAQ,CAAC,CAAC,CAAA,QAAA,EAAW,GAAA,CAAI,OAAA,CAAQ,CAAC,CAAC,CAAA,CAAA,CAAA;AACrD;AAMO,SAAS,eAAA,CAAgB,UAAkB,QAAA,EAIhD;AACE,EAAA,MAAM,GAAA,GAAM,MAAA,CAAO,QAAQ,CAAA,GAAI,GAAA;AAC/B,EAAA,MAAM,MAAM,GAAA,GAAM,QAAA;AAElB,EAAA,OAAO;AAAA,IACH,GAAA;AAAA,IACA,GAAA;AAAA,IACA,SAAA,EAAW,CAAA,EAAG,GAAA,CAAI,OAAA,CAAQ,CAAC,CAAC,CAAA,QAAA,EAAW,GAAA,CAAI,OAAA,CAAQ,CAAC,CAAC,CAAA,CAAA;AAAA,GACzD;AACJ;AAKO,SAAS,eAAA,GAAwB;AACpC,EAAA,WAAA,GAAc,IAAA;AAClB","file":"index.cjs","sourcesContent":["// Price Conversion Helpers\n// Fetch SOL price and convert between USD/SOL\n\n/**\n * Price data from API\n */\nexport interface PriceData {\n /** SOL price in USD */\n solPrice: number;\n /** Timestamp of price fetch */\n fetchedAt: Date;\n /** Source of price data */\n source: string;\n}\n\n/**\n * Cached price data\n */\nlet cachedPrice: PriceData | null = null;\nconst CACHE_TTL_MS = 60000; // 1 minute cache\n\n/**\n * Fetch current SOL price from CoinGecko\n * Includes caching to avoid rate limits\n * \n * @example\n * ```typescript\n * const { solPrice } = await getSolPrice();\n * console.log(`SOL is $${solPrice}`);\n * ```\n */\nexport async function getSolPrice(): Promise<PriceData> {\n // Return cached price if still valid\n if (cachedPrice && Date.now() - cachedPrice.fetchedAt.getTime() < CACHE_TTL_MS) {\n return cachedPrice;\n }\n\n try {\n // CoinGecko free API (no key required, 10-30 calls/min)\n const response = await fetch(\n 'https://api.coingecko.com/api/v3/simple/price?ids=solana&vs_currencies=usd',\n {\n headers: { 'Accept': 'application/json' },\n signal: AbortSignal.timeout(5000),\n }\n );\n\n if (!response.ok) {\n throw new Error(`Price fetch failed: ${response.status}`);\n }\n\n const data = await response.json() as { solana?: { usd?: number } };\n\n if (!data.solana?.usd) {\n throw new Error('Invalid price response');\n }\n\n cachedPrice = {\n solPrice: data.solana.usd,\n fetchedAt: new Date(),\n source: 'coingecko',\n };\n\n return cachedPrice;\n } catch (error) {\n // If fetch fails and we have stale cache, use it\n if (cachedPrice) {\n return cachedPrice;\n }\n\n // Fallback to a reasonable estimate (update periodically)\n return {\n solPrice: 150, // Fallback price\n fetchedAt: new Date(),\n source: 'fallback',\n };\n }\n}\n\n/**\n * Convert lamports to USD\n * \n * @example\n * ```typescript\n * const usd = await lamportsToUsd(10000000n); // 0.01 SOL\n * console.log(`$${usd.toFixed(2)}`);\n * ```\n */\nexport async function lamportsToUsd(lamports: bigint): Promise<number> {\n const { solPrice } = await getSolPrice();\n const sol = Number(lamports) / 1_000_000_000; // LAMPORTS_PER_SOL\n return sol * solPrice;\n}\n\n/**\n * Convert USD to lamports\n * \n * @example\n * ```typescript\n * const lamports = await usdToLamports(1.50); // $1.50\n * console.log(`${lamports} lamports`);\n * ```\n */\nexport async function usdToLamports(usd: number): Promise<bigint> {\n const { solPrice } = await getSolPrice();\n const sol = usd / solPrice;\n return BigInt(Math.floor(sol * 1_000_000_000));\n}\n\n/**\n * Format a price for display with both SOL and USD\n * \n * @example\n * ```typescript\n * const display = await formatPriceDisplay(10000000n);\n * // Returns: \"0.01 SOL (~$1.50)\"\n * ```\n */\nexport async function formatPriceDisplay(lamports: bigint): Promise<string> {\n const { solPrice } = await getSolPrice();\n const sol = Number(lamports) / 1_000_000_000;\n const usd = sol * solPrice;\n\n return `${sol.toFixed(4)} SOL (~$${usd.toFixed(2)})`;\n}\n\n/**\n * Synchronous price formatting (requires pre-fetched price)\n * Use this when you've already fetched the price\n */\nexport function formatPriceSync(lamports: bigint, solPrice: number): {\n sol: number;\n usd: number;\n formatted: string;\n} {\n const sol = Number(lamports) / 1_000_000_000;\n const usd = sol * solPrice;\n\n return {\n sol,\n usd,\n formatted: `${sol.toFixed(4)} SOL (~$${usd.toFixed(2)})`,\n };\n}\n\n/**\n * Clear the price cache (for testing or manual refresh)\n */\nexport function clearPriceCache(): void {\n cachedPrice = null;\n}\n"]}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Price data from API
3
+ */
4
+ interface PriceData {
5
+ /** SOL price in USD */
6
+ solPrice: number;
7
+ /** Timestamp of price fetch */
8
+ fetchedAt: Date;
9
+ /** Source of price data */
10
+ source: string;
11
+ }
12
+ /**
13
+ * Fetch current SOL price from CoinGecko
14
+ * Includes caching to avoid rate limits
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * const { solPrice } = await getSolPrice();
19
+ * console.log(`SOL is $${solPrice}`);
20
+ * ```
21
+ */
22
+ declare function getSolPrice(): Promise<PriceData>;
23
+ /**
24
+ * Convert lamports to USD
25
+ *
26
+ * @example
27
+ * ```typescript
28
+ * const usd = await lamportsToUsd(10000000n); // 0.01 SOL
29
+ * console.log(`$${usd.toFixed(2)}`);
30
+ * ```
31
+ */
32
+ declare function lamportsToUsd(lamports: bigint): Promise<number>;
33
+ /**
34
+ * Convert USD to lamports
35
+ *
36
+ * @example
37
+ * ```typescript
38
+ * const lamports = await usdToLamports(1.50); // $1.50
39
+ * console.log(`${lamports} lamports`);
40
+ * ```
41
+ */
42
+ declare function usdToLamports(usd: number): Promise<bigint>;
43
+ /**
44
+ * Format a price for display with both SOL and USD
45
+ *
46
+ * @example
47
+ * ```typescript
48
+ * const display = await formatPriceDisplay(10000000n);
49
+ * // Returns: "0.01 SOL (~$1.50)"
50
+ * ```
51
+ */
52
+ declare function formatPriceDisplay(lamports: bigint): Promise<string>;
53
+ /**
54
+ * Synchronous price formatting (requires pre-fetched price)
55
+ * Use this when you've already fetched the price
56
+ */
57
+ declare function formatPriceSync(lamports: bigint, solPrice: number): {
58
+ sol: number;
59
+ usd: number;
60
+ formatted: string;
61
+ };
62
+ /**
63
+ * Clear the price cache (for testing or manual refresh)
64
+ */
65
+ declare function clearPriceCache(): void;
66
+
67
+ export { type PriceData, clearPriceCache, formatPriceDisplay, formatPriceSync, getSolPrice, lamportsToUsd, usdToLamports };
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Price data from API
3
+ */
4
+ interface PriceData {
5
+ /** SOL price in USD */
6
+ solPrice: number;
7
+ /** Timestamp of price fetch */
8
+ fetchedAt: Date;
9
+ /** Source of price data */
10
+ source: string;
11
+ }
12
+ /**
13
+ * Fetch current SOL price from CoinGecko
14
+ * Includes caching to avoid rate limits
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * const { solPrice } = await getSolPrice();
19
+ * console.log(`SOL is $${solPrice}`);
20
+ * ```
21
+ */
22
+ declare function getSolPrice(): Promise<PriceData>;
23
+ /**
24
+ * Convert lamports to USD
25
+ *
26
+ * @example
27
+ * ```typescript
28
+ * const usd = await lamportsToUsd(10000000n); // 0.01 SOL
29
+ * console.log(`$${usd.toFixed(2)}`);
30
+ * ```
31
+ */
32
+ declare function lamportsToUsd(lamports: bigint): Promise<number>;
33
+ /**
34
+ * Convert USD to lamports
35
+ *
36
+ * @example
37
+ * ```typescript
38
+ * const lamports = await usdToLamports(1.50); // $1.50
39
+ * console.log(`${lamports} lamports`);
40
+ * ```
41
+ */
42
+ declare function usdToLamports(usd: number): Promise<bigint>;
43
+ /**
44
+ * Format a price for display with both SOL and USD
45
+ *
46
+ * @example
47
+ * ```typescript
48
+ * const display = await formatPriceDisplay(10000000n);
49
+ * // Returns: "0.01 SOL (~$1.50)"
50
+ * ```
51
+ */
52
+ declare function formatPriceDisplay(lamports: bigint): Promise<string>;
53
+ /**
54
+ * Synchronous price formatting (requires pre-fetched price)
55
+ * Use this when you've already fetched the price
56
+ */
57
+ declare function formatPriceSync(lamports: bigint, solPrice: number): {
58
+ sol: number;
59
+ usd: number;
60
+ formatted: string;
61
+ };
62
+ /**
63
+ * Clear the price cache (for testing or manual refresh)
64
+ */
65
+ declare function clearPriceCache(): void;
66
+
67
+ export { type PriceData, clearPriceCache, formatPriceDisplay, formatPriceSync, getSolPrice, lamportsToUsd, usdToLamports };
@@ -0,0 +1,72 @@
1
+ // src/pricing/index.ts
2
+ var cachedPrice = null;
3
+ var CACHE_TTL_MS = 6e4;
4
+ async function getSolPrice() {
5
+ if (cachedPrice && Date.now() - cachedPrice.fetchedAt.getTime() < CACHE_TTL_MS) {
6
+ return cachedPrice;
7
+ }
8
+ try {
9
+ const response = await fetch(
10
+ "https://api.coingecko.com/api/v3/simple/price?ids=solana&vs_currencies=usd",
11
+ {
12
+ headers: { "Accept": "application/json" },
13
+ signal: AbortSignal.timeout(5e3)
14
+ }
15
+ );
16
+ if (!response.ok) {
17
+ throw new Error(`Price fetch failed: ${response.status}`);
18
+ }
19
+ const data = await response.json();
20
+ if (!data.solana?.usd) {
21
+ throw new Error("Invalid price response");
22
+ }
23
+ cachedPrice = {
24
+ solPrice: data.solana.usd,
25
+ fetchedAt: /* @__PURE__ */ new Date(),
26
+ source: "coingecko"
27
+ };
28
+ return cachedPrice;
29
+ } catch (error) {
30
+ if (cachedPrice) {
31
+ return cachedPrice;
32
+ }
33
+ return {
34
+ solPrice: 150,
35
+ // Fallback price
36
+ fetchedAt: /* @__PURE__ */ new Date(),
37
+ source: "fallback"
38
+ };
39
+ }
40
+ }
41
+ async function lamportsToUsd(lamports) {
42
+ const { solPrice } = await getSolPrice();
43
+ const sol = Number(lamports) / 1e9;
44
+ return sol * solPrice;
45
+ }
46
+ async function usdToLamports(usd) {
47
+ const { solPrice } = await getSolPrice();
48
+ const sol = usd / solPrice;
49
+ return BigInt(Math.floor(sol * 1e9));
50
+ }
51
+ async function formatPriceDisplay(lamports) {
52
+ const { solPrice } = await getSolPrice();
53
+ const sol = Number(lamports) / 1e9;
54
+ const usd = sol * solPrice;
55
+ return `${sol.toFixed(4)} SOL (~$${usd.toFixed(2)})`;
56
+ }
57
+ function formatPriceSync(lamports, solPrice) {
58
+ const sol = Number(lamports) / 1e9;
59
+ const usd = sol * solPrice;
60
+ return {
61
+ sol,
62
+ usd,
63
+ formatted: `${sol.toFixed(4)} SOL (~$${usd.toFixed(2)})`
64
+ };
65
+ }
66
+ function clearPriceCache() {
67
+ cachedPrice = null;
68
+ }
69
+
70
+ export { clearPriceCache, formatPriceDisplay, formatPriceSync, getSolPrice, lamportsToUsd, usdToLamports };
71
+ //# sourceMappingURL=index.js.map
72
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/pricing/index.ts"],"names":[],"mappings":";AAkBA,IAAI,WAAA,GAAgC,IAAA;AACpC,IAAM,YAAA,GAAe,GAAA;AAYrB,eAAsB,WAAA,GAAkC;AAEpD,EAAA,IAAI,WAAA,IAAe,KAAK,GAAA,EAAI,GAAI,YAAY,SAAA,CAAU,OAAA,KAAY,YAAA,EAAc;AAC5E,IAAA,OAAO,WAAA;AAAA,EACX;AAEA,EAAA,IAAI;AAEA,IAAA,MAAM,WAAW,MAAM,KAAA;AAAA,MACnB,4EAAA;AAAA,MACA;AAAA,QACI,OAAA,EAAS,EAAE,QAAA,EAAU,kBAAA,EAAmB;AAAA,QACxC,MAAA,EAAQ,WAAA,CAAY,OAAA,CAAQ,GAAI;AAAA;AACpC,KACJ;AAEA,IAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AACd,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,oBAAA,EAAuB,QAAA,CAAS,MAAM,CAAA,CAAE,CAAA;AAAA,IAC5D;AAEA,IAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,IAAA,EAAK;AAEjC,IAAA,IAAI,CAAC,IAAA,CAAK,MAAA,EAAQ,GAAA,EAAK;AACnB,MAAA,MAAM,IAAI,MAAM,wBAAwB,CAAA;AAAA,IAC5C;AAEA,IAAA,WAAA,GAAc;AAAA,MACV,QAAA,EAAU,KAAK,MAAA,CAAO,GAAA;AAAA,MACtB,SAAA,sBAAe,IAAA,EAAK;AAAA,MACpB,MAAA,EAAQ;AAAA,KACZ;AAEA,IAAA,OAAO,WAAA;AAAA,EACX,SAAS,KAAA,EAAO;AAEZ,IAAA,IAAI,WAAA,EAAa;AACb,MAAA,OAAO,WAAA;AAAA,IACX;AAGA,IAAA,OAAO;AAAA,MACH,QAAA,EAAU,GAAA;AAAA;AAAA,MACV,SAAA,sBAAe,IAAA,EAAK;AAAA,MACpB,MAAA,EAAQ;AAAA,KACZ;AAAA,EACJ;AACJ;AAWA,eAAsB,cAAc,QAAA,EAAmC;AACnE,EAAA,MAAM,EAAE,QAAA,EAAS,GAAI,MAAM,WAAA,EAAY;AACvC,EAAA,MAAM,GAAA,GAAM,MAAA,CAAO,QAAQ,CAAA,GAAI,GAAA;AAC/B,EAAA,OAAO,GAAA,GAAM,QAAA;AACjB;AAWA,eAAsB,cAAc,GAAA,EAA8B;AAC9D,EAAA,MAAM,EAAE,QAAA,EAAS,GAAI,MAAM,WAAA,EAAY;AACvC,EAAA,MAAM,MAAM,GAAA,GAAM,QAAA;AAClB,EAAA,OAAO,MAAA,CAAO,IAAA,CAAK,KAAA,CAAM,GAAA,GAAM,GAAa,CAAC,CAAA;AACjD;AAWA,eAAsB,mBAAmB,QAAA,EAAmC;AACxE,EAAA,MAAM,EAAE,QAAA,EAAS,GAAI,MAAM,WAAA,EAAY;AACvC,EAAA,MAAM,GAAA,GAAM,MAAA,CAAO,QAAQ,CAAA,GAAI,GAAA;AAC/B,EAAA,MAAM,MAAM,GAAA,GAAM,QAAA;AAElB,EAAA,OAAO,CAAA,EAAG,IAAI,OAAA,CAAQ,CAAC,CAAC,CAAA,QAAA,EAAW,GAAA,CAAI,OAAA,CAAQ,CAAC,CAAC,CAAA,CAAA,CAAA;AACrD;AAMO,SAAS,eAAA,CAAgB,UAAkB,QAAA,EAIhD;AACE,EAAA,MAAM,GAAA,GAAM,MAAA,CAAO,QAAQ,CAAA,GAAI,GAAA;AAC/B,EAAA,MAAM,MAAM,GAAA,GAAM,QAAA;AAElB,EAAA,OAAO;AAAA,IACH,GAAA;AAAA,IACA,GAAA;AAAA,IACA,SAAA,EAAW,CAAA,EAAG,GAAA,CAAI,OAAA,CAAQ,CAAC,CAAC,CAAA,QAAA,EAAW,GAAA,CAAI,OAAA,CAAQ,CAAC,CAAC,CAAA,CAAA;AAAA,GACzD;AACJ;AAKO,SAAS,eAAA,GAAwB;AACpC,EAAA,WAAA,GAAc,IAAA;AAClB","file":"index.js","sourcesContent":["// Price Conversion Helpers\n// Fetch SOL price and convert between USD/SOL\n\n/**\n * Price data from API\n */\nexport interface PriceData {\n /** SOL price in USD */\n solPrice: number;\n /** Timestamp of price fetch */\n fetchedAt: Date;\n /** Source of price data */\n source: string;\n}\n\n/**\n * Cached price data\n */\nlet cachedPrice: PriceData | null = null;\nconst CACHE_TTL_MS = 60000; // 1 minute cache\n\n/**\n * Fetch current SOL price from CoinGecko\n * Includes caching to avoid rate limits\n * \n * @example\n * ```typescript\n * const { solPrice } = await getSolPrice();\n * console.log(`SOL is $${solPrice}`);\n * ```\n */\nexport async function getSolPrice(): Promise<PriceData> {\n // Return cached price if still valid\n if (cachedPrice && Date.now() - cachedPrice.fetchedAt.getTime() < CACHE_TTL_MS) {\n return cachedPrice;\n }\n\n try {\n // CoinGecko free API (no key required, 10-30 calls/min)\n const response = await fetch(\n 'https://api.coingecko.com/api/v3/simple/price?ids=solana&vs_currencies=usd',\n {\n headers: { 'Accept': 'application/json' },\n signal: AbortSignal.timeout(5000),\n }\n );\n\n if (!response.ok) {\n throw new Error(`Price fetch failed: ${response.status}`);\n }\n\n const data = await response.json() as { solana?: { usd?: number } };\n\n if (!data.solana?.usd) {\n throw new Error('Invalid price response');\n }\n\n cachedPrice = {\n solPrice: data.solana.usd,\n fetchedAt: new Date(),\n source: 'coingecko',\n };\n\n return cachedPrice;\n } catch (error) {\n // If fetch fails and we have stale cache, use it\n if (cachedPrice) {\n return cachedPrice;\n }\n\n // Fallback to a reasonable estimate (update periodically)\n return {\n solPrice: 150, // Fallback price\n fetchedAt: new Date(),\n source: 'fallback',\n };\n }\n}\n\n/**\n * Convert lamports to USD\n * \n * @example\n * ```typescript\n * const usd = await lamportsToUsd(10000000n); // 0.01 SOL\n * console.log(`$${usd.toFixed(2)}`);\n * ```\n */\nexport async function lamportsToUsd(lamports: bigint): Promise<number> {\n const { solPrice } = await getSolPrice();\n const sol = Number(lamports) / 1_000_000_000; // LAMPORTS_PER_SOL\n return sol * solPrice;\n}\n\n/**\n * Convert USD to lamports\n * \n * @example\n * ```typescript\n * const lamports = await usdToLamports(1.50); // $1.50\n * console.log(`${lamports} lamports`);\n * ```\n */\nexport async function usdToLamports(usd: number): Promise<bigint> {\n const { solPrice } = await getSolPrice();\n const sol = usd / solPrice;\n return BigInt(Math.floor(sol * 1_000_000_000));\n}\n\n/**\n * Format a price for display with both SOL and USD\n * \n * @example\n * ```typescript\n * const display = await formatPriceDisplay(10000000n);\n * // Returns: \"0.01 SOL (~$1.50)\"\n * ```\n */\nexport async function formatPriceDisplay(lamports: bigint): Promise<string> {\n const { solPrice } = await getSolPrice();\n const sol = Number(lamports) / 1_000_000_000;\n const usd = sol * solPrice;\n\n return `${sol.toFixed(4)} SOL (~$${usd.toFixed(2)})`;\n}\n\n/**\n * Synchronous price formatting (requires pre-fetched price)\n * Use this when you've already fetched the price\n */\nexport function formatPriceSync(lamports: bigint, solPrice: number): {\n sol: number;\n usd: number;\n formatted: string;\n} {\n const sol = Number(lamports) / 1_000_000_000;\n const usd = sol * solPrice;\n\n return {\n sol,\n usd,\n formatted: `${sol.toFixed(4)} SOL (~$${usd.toFixed(2)})`,\n };\n}\n\n/**\n * Clear the price cache (for testing or manual refresh)\n */\nexport function clearPriceCache(): void {\n cachedPrice = null;\n}\n"]}
@@ -1 +1,29 @@
1
- export { e as addArticleToSession, d as createSession, i as isArticleUnlocked, v as validateSession } from '../index-uxMb72hH.cjs';
1
+ import { a as SessionConfig, S as SessionData, b as SessionValidation } from '../session-D2IoWAWV.cjs';
2
+
3
+ /**
4
+ * Create a new session after successful payment
5
+ * SECURITY: Validates inputs, enforces limits
6
+ */
7
+ declare function createSession(walletAddress: string, articleId: string, config: SessionConfig, siteWide?: boolean): Promise<{
8
+ token: string;
9
+ session: SessionData;
10
+ }>;
11
+ /**
12
+ * Validate an existing session token
13
+ * SECURITY: jose library handles timing-safe comparison internally
14
+ */
15
+ declare function validateSession(token: string, secret: string): Promise<SessionValidation>;
16
+ /**
17
+ * Add an article to an existing session
18
+ * SECURITY: Enforces article limit to prevent token bloat
19
+ */
20
+ declare function addArticleToSession(token: string, articleId: string, secret: string): Promise<{
21
+ token: string;
22
+ session: SessionData;
23
+ } | null>;
24
+ /**
25
+ * Check if an article is unlocked for a session
26
+ */
27
+ declare function isArticleUnlocked(token: string, articleId: string, secret: string): Promise<boolean>;
28
+
29
+ export { addArticleToSession, createSession, isArticleUnlocked, validateSession };
@@ -1 +1,29 @@
1
- export { e as addArticleToSession, d as createSession, i as isArticleUnlocked, v as validateSession } from '../index-uxMb72hH.js';
1
+ import { a as SessionConfig, S as SessionData, b as SessionValidation } from '../session-D2IoWAWV.js';
2
+
3
+ /**
4
+ * Create a new session after successful payment
5
+ * SECURITY: Validates inputs, enforces limits
6
+ */
7
+ declare function createSession(walletAddress: string, articleId: string, config: SessionConfig, siteWide?: boolean): Promise<{
8
+ token: string;
9
+ session: SessionData;
10
+ }>;
11
+ /**
12
+ * Validate an existing session token
13
+ * SECURITY: jose library handles timing-safe comparison internally
14
+ */
15
+ declare function validateSession(token: string, secret: string): Promise<SessionValidation>;
16
+ /**
17
+ * Add an article to an existing session
18
+ * SECURITY: Enforces article limit to prevent token bloat
19
+ */
20
+ declare function addArticleToSession(token: string, articleId: string, secret: string): Promise<{
21
+ token: string;
22
+ session: SessionData;
23
+ } | null>;
24
+ /**
25
+ * Check if an article is unlocked for a session
26
+ */
27
+ declare function isArticleUnlocked(token: string, articleId: string, secret: string): Promise<boolean>;
28
+
29
+ export { addArticleToSession, createSession, isArticleUnlocked, validateSession };
@@ -45,30 +45,4 @@ interface SessionJWTPayload {
45
45
  exp: number;
46
46
  }
47
47
 
48
- /**
49
- * Create a new session after successful payment
50
- * SECURITY: Validates inputs, enforces limits
51
- */
52
- declare function createSession(walletAddress: string, articleId: string, config: SessionConfig, siteWide?: boolean): Promise<{
53
- token: string;
54
- session: SessionData;
55
- }>;
56
- /**
57
- * Validate an existing session token
58
- * SECURITY: jose library handles timing-safe comparison internally
59
- */
60
- declare function validateSession(token: string, secret: string): Promise<SessionValidation>;
61
- /**
62
- * Add an article to an existing session
63
- * SECURITY: Enforces article limit to prevent token bloat
64
- */
65
- declare function addArticleToSession(token: string, articleId: string, secret: string): Promise<{
66
- token: string;
67
- session: SessionData;
68
- } | null>;
69
- /**
70
- * Check if an article is unlocked for a session
71
- */
72
- declare function isArticleUnlocked(token: string, articleId: string, secret: string): Promise<boolean>;
73
-
74
- export { type SessionData as S, type SessionConfig as a, type SessionValidation as b, type SessionJWTPayload as c, createSession as d, addArticleToSession as e, isArticleUnlocked as i, validateSession as v };
48
+ export type { SessionData as S, SessionConfig as a, SessionValidation as b, SessionJWTPayload as c };
@@ -45,30 +45,4 @@ interface SessionJWTPayload {
45
45
  exp: number;
46
46
  }
47
47
 
48
- /**
49
- * Create a new session after successful payment
50
- * SECURITY: Validates inputs, enforces limits
51
- */
52
- declare function createSession(walletAddress: string, articleId: string, config: SessionConfig, siteWide?: boolean): Promise<{
53
- token: string;
54
- session: SessionData;
55
- }>;
56
- /**
57
- * Validate an existing session token
58
- * SECURITY: jose library handles timing-safe comparison internally
59
- */
60
- declare function validateSession(token: string, secret: string): Promise<SessionValidation>;
61
- /**
62
- * Add an article to an existing session
63
- * SECURITY: Enforces article limit to prevent token bloat
64
- */
65
- declare function addArticleToSession(token: string, articleId: string, secret: string): Promise<{
66
- token: string;
67
- session: SessionData;
68
- } | null>;
69
- /**
70
- * Check if an article is unlocked for a session
71
- */
72
- declare function isArticleUnlocked(token: string, articleId: string, secret: string): Promise<boolean>;
73
-
74
- export { type SessionData as S, type SessionConfig as a, type SessionValidation as b, type SessionJWTPayload as c, createSession as d, addArticleToSession as e, isArticleUnlocked as i, validateSession as v };
48
+ export type { SessionData as S, SessionConfig as a, SessionValidation as b, SessionJWTPayload as c };
@@ -210,14 +210,207 @@ function solToLamports(sol) {
210
210
  return BigInt(Math.floor(sol * web3_js.LAMPORTS_PER_SOL));
211
211
  }
212
212
 
213
+ // src/types/payment.ts
214
+ var TOKEN_MINTS = {
215
+ /** USDC on mainnet */
216
+ USDC_MAINNET: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
217
+ /** USDC on devnet */
218
+ USDC_DEVNET: "4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU",
219
+ /** USDT on mainnet */
220
+ USDT_MAINNET: "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB"
221
+ };
222
+
223
+ // src/solana/spl.ts
224
+ var SIGNATURE_REGEX2 = /^[1-9A-HJ-NP-Za-km-z]{87,88}$/;
225
+ var WALLET_REGEX2 = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;
226
+ function resolveMintAddress(asset, network) {
227
+ if (asset === "native") return null;
228
+ if (asset === "usdc") {
229
+ return network === "mainnet-beta" ? TOKEN_MINTS.USDC_MAINNET : TOKEN_MINTS.USDC_DEVNET;
230
+ }
231
+ if (asset === "usdt") {
232
+ return TOKEN_MINTS.USDT_MAINNET;
233
+ }
234
+ if (typeof asset === "object" && "mint" in asset) {
235
+ return asset.mint;
236
+ }
237
+ return null;
238
+ }
239
+ function getTokenDecimals(asset) {
240
+ if (asset === "native") return 9;
241
+ if (asset === "usdc" || asset === "usdt") return 6;
242
+ if (typeof asset === "object" && "decimals" in asset) {
243
+ return asset.decimals ?? 6;
244
+ }
245
+ return 6;
246
+ }
247
+ function parseSPLTransfer(transaction, expectedRecipient, expectedMint) {
248
+ const instructions = transaction.transaction.message.instructions;
249
+ for (const ix of instructions) {
250
+ if ("parsed" in ix && (ix.program === "spl-token" || ix.program === "spl-token-2022")) {
251
+ const parsed = ix.parsed;
252
+ if (parsed.type === "transfer" || parsed.type === "transferChecked") {
253
+ const amount = parsed.info.amount || parsed.info.tokenAmount?.amount;
254
+ if (amount && parsed.info.destination) {
255
+ return {
256
+ from: parsed.info.authority || parsed.info.source || "",
257
+ to: parsed.info.destination,
258
+ amount: BigInt(amount),
259
+ mint: parsed.info.mint || expectedMint
260
+ };
261
+ }
262
+ }
263
+ }
264
+ }
265
+ if (transaction.meta?.innerInstructions) {
266
+ for (const inner of transaction.meta.innerInstructions) {
267
+ for (const ix of inner.instructions) {
268
+ if ("parsed" in ix && (ix.program === "spl-token" || ix.program === "spl-token-2022")) {
269
+ const parsed = ix.parsed;
270
+ if (parsed.type === "transfer" || parsed.type === "transferChecked") {
271
+ const amount = parsed.info.amount || parsed.info.tokenAmount?.amount;
272
+ if (amount) {
273
+ return {
274
+ from: parsed.info.authority || parsed.info.source || "",
275
+ to: parsed.info.destination || "",
276
+ amount: BigInt(amount),
277
+ mint: parsed.info.mint || expectedMint
278
+ };
279
+ }
280
+ }
281
+ }
282
+ }
283
+ }
284
+ }
285
+ if (transaction.meta?.postTokenBalances && transaction.meta?.preTokenBalances) {
286
+ const preBalances = transaction.meta.preTokenBalances;
287
+ const postBalances = transaction.meta.postTokenBalances;
288
+ for (const post of postBalances) {
289
+ if (post.mint === expectedMint && post.owner === expectedRecipient) {
290
+ const pre = preBalances.find(
291
+ (p) => p.accountIndex === post.accountIndex
292
+ );
293
+ const preAmount = BigInt(pre?.uiTokenAmount?.amount || "0");
294
+ const postAmount = BigInt(post.uiTokenAmount?.amount || "0");
295
+ const transferred = postAmount - preAmount;
296
+ if (transferred > 0n) {
297
+ return {
298
+ from: "",
299
+ // Can't determine from balance changes
300
+ to: expectedRecipient,
301
+ amount: transferred,
302
+ mint: expectedMint
303
+ };
304
+ }
305
+ }
306
+ }
307
+ }
308
+ return null;
309
+ }
310
+ async function verifySPLPayment(params) {
311
+ const {
312
+ signature,
313
+ expectedRecipient,
314
+ expectedAmount,
315
+ asset,
316
+ clientConfig,
317
+ maxAgeSeconds = 300
318
+ } = params;
319
+ if (!SIGNATURE_REGEX2.test(signature)) {
320
+ return { valid: false, confirmed: false, signature, error: "Invalid signature format" };
321
+ }
322
+ if (!WALLET_REGEX2.test(expectedRecipient)) {
323
+ return { valid: false, confirmed: false, signature, error: "Invalid recipient address" };
324
+ }
325
+ const mintAddress = resolveMintAddress(asset, clientConfig.network);
326
+ if (!mintAddress) {
327
+ return { valid: false, confirmed: false, signature, error: "Invalid asset configuration" };
328
+ }
329
+ if (expectedAmount <= 0n) {
330
+ return { valid: false, confirmed: false, signature, error: "Invalid expected amount" };
331
+ }
332
+ const effectiveMaxAge = Math.min(Math.max(maxAgeSeconds, 60), 3600);
333
+ const connection = getConnection(clientConfig);
334
+ try {
335
+ const transaction = await connection.getParsedTransaction(signature, {
336
+ commitment: "confirmed",
337
+ maxSupportedTransactionVersion: 0
338
+ });
339
+ if (!transaction) {
340
+ return { valid: false, confirmed: false, signature, error: "Transaction not found" };
341
+ }
342
+ if (transaction.meta?.err) {
343
+ return { valid: false, confirmed: true, signature, error: "Transaction failed on-chain" };
344
+ }
345
+ if (transaction.blockTime) {
346
+ const now = Math.floor(Date.now() / 1e3);
347
+ if (now - transaction.blockTime > effectiveMaxAge) {
348
+ return { valid: false, confirmed: true, signature, error: "Transaction too old" };
349
+ }
350
+ if (transaction.blockTime > now + 60) {
351
+ return { valid: false, confirmed: true, signature, error: "Invalid transaction time" };
352
+ }
353
+ }
354
+ const transfer = parseSPLTransfer(transaction, expectedRecipient, mintAddress);
355
+ if (!transfer) {
356
+ return {
357
+ valid: false,
358
+ confirmed: true,
359
+ signature,
360
+ error: "No valid token transfer to recipient found"
361
+ };
362
+ }
363
+ if (transfer.mint !== mintAddress) {
364
+ return {
365
+ valid: false,
366
+ confirmed: true,
367
+ signature,
368
+ error: "Token mint mismatch"
369
+ };
370
+ }
371
+ if (transfer.amount < expectedAmount) {
372
+ return {
373
+ valid: false,
374
+ confirmed: true,
375
+ signature,
376
+ from: transfer.from,
377
+ to: transfer.to,
378
+ mint: transfer.mint,
379
+ amount: transfer.amount,
380
+ error: "Insufficient payment amount"
381
+ };
382
+ }
383
+ return {
384
+ valid: true,
385
+ confirmed: true,
386
+ signature,
387
+ from: transfer.from,
388
+ to: transfer.to,
389
+ mint: transfer.mint,
390
+ amount: transfer.amount,
391
+ blockTime: transaction.blockTime ?? void 0,
392
+ slot: transaction.slot
393
+ };
394
+ } catch {
395
+ return { valid: false, confirmed: false, signature, error: "Verification failed" };
396
+ }
397
+ }
398
+ function isNativeAsset(asset) {
399
+ return asset === "native";
400
+ }
401
+
213
402
  exports.getConnection = getConnection;
403
+ exports.getTokenDecimals = getTokenDecimals;
214
404
  exports.getWalletTransactions = getWalletTransactions;
215
405
  exports.isMainnet = isMainnet;
406
+ exports.isNativeAsset = isNativeAsset;
216
407
  exports.lamportsToSol = lamportsToSol;
217
408
  exports.resetConnection = resetConnection;
409
+ exports.resolveMintAddress = resolveMintAddress;
218
410
  exports.solToLamports = solToLamports;
219
411
  exports.toX402Network = toX402Network;
220
412
  exports.verifyPayment = verifyPayment;
413
+ exports.verifySPLPayment = verifySPLPayment;
221
414
  exports.waitForConfirmation = waitForConfirmation;
222
415
  //# sourceMappingURL=index.cjs.map
223
416
  //# sourceMappingURL=index.cjs.map