@doujins/payments-ui 0.0.6 → 0.0.7

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/index.js CHANGED
@@ -35,12 +35,18 @@ var loadCollectJs = (tokenizationKey) => {
35
35
  if (existing) return;
36
36
  const script = document.createElement("script");
37
37
  script.src = SCRIPT_SRC;
38
- script.setAttribute("data-tokenization-key", "8u8B78-23Z347-c2svF3-pbEb7G");
38
+ script.setAttribute("data-tokenization-key", trimmed);
39
39
  script.setAttribute("data-field-ccnumber-placeholder", "0000 0000 0000 0000");
40
40
  script.setAttribute("data-field-ccexp-placeholder", "10 / 25");
41
41
  script.setAttribute("data-field-cvv-placeholder", "123");
42
42
  script.setAttribute("data-variant", "inline");
43
43
  script.async = true;
44
+ script.addEventListener("load", () => {
45
+ console.log("payments-ui: Collect.js loaded");
46
+ });
47
+ script.addEventListener("error", (event) => {
48
+ console.error("payments-ui: failed to load Collect.js", event);
49
+ });
44
50
  document.head.appendChild(script);
45
51
  };
46
52
 
@@ -76,20 +82,31 @@ var createApiClient = (paymentConfig, baseUrl, fetcher, resolveAuthToken) => {
76
82
  if (token) {
77
83
  headers.Authorization = `Bearer ${token}`;
78
84
  }
79
- const response = await fetcher(url, {
80
- method,
81
- headers,
82
- body: options?.body ? JSON.stringify(options.body) : void 0
83
- });
84
- if (!response.ok) {
85
- const message = await response.text();
86
- throw new Error(message || `Request failed with status ${response.status}`);
87
- }
88
- if (response.status === 204) {
89
- return void 0;
85
+ try {
86
+ const response = await fetcher(url, {
87
+ method,
88
+ headers,
89
+ body: options?.body ? JSON.stringify(options.body) : void 0
90
+ });
91
+ if (!response.ok) {
92
+ const message = await response.text();
93
+ console.error("payments-ui: API request failed", {
94
+ url,
95
+ method,
96
+ status: response.status,
97
+ message
98
+ });
99
+ throw new Error(message || `Request failed with status ${response.status}`);
100
+ }
101
+ if (response.status === 204) {
102
+ return void 0;
103
+ }
104
+ const data = await response.json();
105
+ return data;
106
+ } catch (error) {
107
+ console.error("payments-ui: API request error", { url, method, error });
108
+ throw error;
90
109
  }
91
- const data = await response.json();
92
- return data;
93
110
  };
94
111
  return {
95
112
  request,
@@ -1565,8 +1582,16 @@ var useSolanaDirectPayment = (options) => {
1565
1582
  const balance = balanceInfo?.balance || 0;
1566
1583
  const hasBalanceFlag = hasSufficientBalance(balance, tokenAmount);
1567
1584
  setTokenBalance({ balance, hasBalance: hasBalanceFlag });
1585
+ console.log("payments-ui: Solana wallet balance", {
1586
+ token: selectedToken.symbol,
1587
+ balance,
1588
+ required: tokenAmount
1589
+ });
1568
1590
  } catch (error) {
1569
- console.error("Failed to fetch token balance:", error);
1591
+ console.error("Failed to fetch token balance:", {
1592
+ token: selectedToken?.symbol,
1593
+ error
1594
+ });
1570
1595
  setTokenBalance({ balance: 0, hasBalance: false });
1571
1596
  } finally {
1572
1597
  setIsBalanceLoading(false);
@@ -1630,30 +1655,49 @@ var useSolanaDirectPayment = (options) => {
1630
1655
  return;
1631
1656
  }
1632
1657
  if (!tokenBalance?.hasBalance) {
1658
+ console.warn("payments-ui: insufficient balance for Solana direct payment", {
1659
+ token: selectedToken.symbol
1660
+ });
1633
1661
  onError("Insufficient balance for this token");
1634
1662
  return;
1635
1663
  }
1636
1664
  try {
1637
1665
  setIsProcessing(true);
1638
1666
  onStart();
1667
+ console.log("payments-ui: initiating Solana direct payment", {
1668
+ priceId,
1669
+ token: selectedToken.symbol
1670
+ });
1639
1671
  const paymentData = await solanaService.generatePayment(
1640
1672
  priceId,
1641
1673
  selectedToken.symbol,
1642
1674
  publicKey.toBase58()
1643
1675
  );
1676
+ console.log("payments-ui: Solana payment intent created", {
1677
+ intentId: paymentData.intent_id
1678
+ });
1644
1679
  const transactionToSign = decodeTransaction(paymentData.transaction);
1680
+ console.log("payments-ui: requesting Solana wallet signature");
1645
1681
  const signedTx = await signWithWallet(transactionToSign);
1646
1682
  const signedSerialized = Buffer.from(signedTx.serialize()).toString("base64");
1647
1683
  onConfirming();
1684
+ console.log("payments-ui: submitting signed Solana transaction");
1648
1685
  const result = await solanaService.submitPayment(
1649
1686
  signedSerialized,
1650
1687
  priceId,
1651
1688
  paymentData.intent_id,
1652
1689
  `Payment for subscription - ${selectedToken.symbol}`
1653
1690
  );
1691
+ console.log("payments-ui: Solana direct payment confirmed", {
1692
+ transactionId: result.transaction_id
1693
+ });
1654
1694
  onSuccess(result, result.transaction_id);
1655
1695
  } catch (err) {
1656
- console.error("Payment failed:", err);
1696
+ console.error("Solana direct payment failed:", {
1697
+ priceId,
1698
+ token: selectedToken.symbol,
1699
+ error: err
1700
+ });
1657
1701
  let errorMessage = "Payment failed. Please try again.";
1658
1702
  const message = err instanceof Error ? err.message : typeof err === "string" ? err : "";
1659
1703
  if (message.includes("User rejected")) {
@@ -1745,11 +1789,13 @@ var DirectPayment = ({
1745
1789
  var useSolanaQrPayment = (options) => {
1746
1790
  const { priceId, selectedToken, onSuccess, onError } = options;
1747
1791
  const solanaService = useSolanaService();
1792
+ const tokenSymbol = selectedToken?.symbol ?? null;
1748
1793
  const [intent, setIntent] = useState(null);
1749
1794
  const [qrDataUri, setQrDataUri] = useState(null);
1750
1795
  const [isLoading, setIsLoading] = useState(false);
1751
1796
  const [error, setError] = useState(null);
1752
1797
  const [timeRemaining, setTimeRemaining] = useState(0);
1798
+ const [refreshNonce, setRefreshNonce] = useState(0);
1753
1799
  const pollRef = useRef(null);
1754
1800
  const countdownRef = useRef(null);
1755
1801
  const clearTimers = useCallback(() => {
@@ -1767,27 +1813,41 @@ var useSolanaQrPayment = (options) => {
1767
1813
  clearTimers();
1768
1814
  };
1769
1815
  }, [clearTimers]);
1816
+ const resetState = useCallback(
1817
+ (message) => {
1818
+ clearTimers();
1819
+ setIntent((prev) => prev ? null : prev);
1820
+ setQrDataUri((prev) => prev ? null : prev);
1821
+ setTimeRemaining((prev) => prev !== 0 ? 0 : prev);
1822
+ setError((prev) => {
1823
+ const next = message === void 0 ? null : message;
1824
+ return prev === next ? prev : next;
1825
+ });
1826
+ },
1827
+ [clearTimers]
1828
+ );
1770
1829
  const handleError = useCallback(
1771
1830
  (message, notifyParent = false) => {
1831
+ console.error("[payments-ui] Solana Pay QR error:", message);
1772
1832
  clearTimers();
1773
- setError(message);
1774
- setIntent(null);
1775
- setQrDataUri(null);
1776
- setTimeRemaining(0);
1833
+ resetState(message);
1777
1834
  if (notifyParent) {
1778
1835
  onError(message);
1779
1836
  }
1780
1837
  },
1781
- [clearTimers, onError]
1838
+ [clearTimers, onError, resetState]
1782
1839
  );
1783
1840
  const handleSuccess = useCallback(
1784
1841
  (status) => {
1785
1842
  clearTimers();
1786
- setTimeRemaining(0);
1787
- setIntent(null);
1843
+ resetState(null);
1844
+ console.log("[payments-ui] Solana Pay QR confirmed", {
1845
+ paymentId: status.payment_id,
1846
+ intentId: status.intent_id
1847
+ });
1788
1848
  onSuccess(status.payment_id, status.transaction || "");
1789
1849
  },
1790
- [clearTimers, onSuccess]
1850
+ [clearTimers, onSuccess, resetState]
1791
1851
  );
1792
1852
  const pollStatus = useCallback(
1793
1853
  async (reference) => {
@@ -1839,57 +1899,75 @@ var useSolanaQrPayment = (options) => {
1839
1899
  handleError("Unable to render QR code");
1840
1900
  }
1841
1901
  }, [handleError]);
1842
- const fetchIntent = useCallback(async () => {
1843
- if (!selectedToken) {
1844
- setIntent(null);
1845
- setQrDataUri(null);
1846
- setError(null);
1902
+ useEffect(() => {
1903
+ let cancelled = false;
1904
+ const generateIntent = async () => {
1847
1905
  clearTimers();
1848
- setTimeRemaining(0);
1849
- return;
1850
- }
1851
- try {
1852
- setIsLoading(true);
1853
- setError(null);
1906
+ if (!tokenSymbol || !priceId) {
1907
+ resetState(null);
1908
+ setIsLoading((prev) => prev ? false : prev);
1909
+ return;
1910
+ }
1911
+ try {
1912
+ setIsLoading(true);
1913
+ setError(null);
1914
+ console.log("[payments-ui] Requesting Solana Pay QR intent", {
1915
+ priceId,
1916
+ token: tokenSymbol
1917
+ });
1918
+ const nextIntent = await solanaService.generateQRCode(
1919
+ priceId,
1920
+ tokenSymbol
1921
+ );
1922
+ if (cancelled) return;
1923
+ setIntent(nextIntent);
1924
+ setTimeRemaining(
1925
+ Math.max(0, Math.floor(nextIntent.expires_at - Date.now() / 1e3))
1926
+ );
1927
+ await renderQr(nextIntent);
1928
+ console.log("[payments-ui] Solana Pay QR ready", {
1929
+ reference: nextIntent.reference
1930
+ });
1931
+ startCountdown(nextIntent.expires_at, nextIntent.reference);
1932
+ pollStatus(nextIntent.reference);
1933
+ } catch (err) {
1934
+ if (cancelled) return;
1935
+ console.error("Failed to generate Solana Pay QR intent:", err);
1936
+ const message = err instanceof Error ? err.message : "Unable to create Solana Pay QR code";
1937
+ handleError(message);
1938
+ } finally {
1939
+ if (!cancelled) {
1940
+ setIsLoading(false);
1941
+ }
1942
+ }
1943
+ };
1944
+ void generateIntent();
1945
+ return () => {
1946
+ cancelled = true;
1854
1947
  clearTimers();
1855
- const nextIntent = await solanaService.generateQRCode(
1856
- priceId,
1857
- selectedToken.symbol
1858
- );
1859
- setIntent(nextIntent);
1860
- setTimeRemaining(
1861
- Math.max(0, Math.floor(nextIntent.expires_at - Date.now() / 1e3))
1862
- );
1863
- await renderQr(nextIntent);
1864
- startCountdown(nextIntent.expires_at, nextIntent.reference);
1865
- pollStatus(nextIntent.reference);
1866
- } catch (err) {
1867
- console.error("Failed to generate Solana Pay QR intent:", err);
1868
- const message = err instanceof Error ? err.message : "Unable to create Solana Pay QR code";
1869
- handleError(message);
1870
- } finally {
1871
- setIsLoading(false);
1872
- }
1948
+ };
1873
1949
  }, [
1874
1950
  clearTimers,
1875
1951
  handleError,
1876
1952
  pollStatus,
1877
1953
  priceId,
1878
- selectedToken,
1954
+ renderQr,
1955
+ resetState,
1879
1956
  solanaService,
1880
1957
  startCountdown,
1881
- renderQr
1958
+ tokenSymbol,
1959
+ refreshNonce
1882
1960
  ]);
1883
- useEffect(() => {
1884
- void fetchIntent();
1885
- }, [fetchIntent]);
1961
+ const refresh = useCallback(() => {
1962
+ setRefreshNonce((value) => value + 1);
1963
+ }, []);
1886
1964
  return {
1887
1965
  intent,
1888
1966
  qrDataUri,
1889
1967
  isLoading,
1890
1968
  error,
1891
1969
  timeRemaining,
1892
- refresh: fetchIntent
1970
+ refresh
1893
1971
  };
1894
1972
  };
1895
1973
  var QRCodePayment = ({
@@ -2012,11 +2090,15 @@ var useSupportedTokens = () => {
2012
2090
  setIsLoading(true);
2013
2091
  setError(null);
2014
2092
  try {
2093
+ console.log("payments-ui: fetching supported Solana tokens");
2015
2094
  const tokens2 = await solanaService.getSupportedTokens();
2016
2095
  const sortedTokens = [...tokens2].sort(
2017
2096
  (a, b) => a.symbol.localeCompare(b.symbol)
2018
2097
  );
2019
2098
  setTokens(sortedTokens);
2099
+ console.log("payments-ui: loaded supported tokens", {
2100
+ count: sortedTokens.length
2101
+ });
2020
2102
  setLastFetched(Date.now());
2021
2103
  return sortedTokens;
2022
2104
  } catch (error2) {
@@ -2862,7 +2944,10 @@ var usePaymentStatus = (options = {}) => {
2862
2944
  error: err ? `Transaction failed: ${err}` : void 0
2863
2945
  };
2864
2946
  } catch (error2) {
2865
- console.error("Failed to check transaction status:", error2);
2947
+ console.error("Failed to check transaction status:", {
2948
+ signature,
2949
+ error: error2
2950
+ });
2866
2951
  return {
2867
2952
  signature,
2868
2953
  confirmationStatus: "failed",
@@ -2884,7 +2969,10 @@ var usePaymentStatus = (options = {}) => {
2884
2969
  if (error2?.status === 404) {
2885
2970
  return null;
2886
2971
  }
2887
- console.error("Failed to check payment status:", error2);
2972
+ console.error("Failed to check payment status:", {
2973
+ purchaseId: id,
2974
+ error: error2
2975
+ });
2888
2976
  return null;
2889
2977
  }
2890
2978
  },
@@ -2947,7 +3035,11 @@ var usePaymentStatus = (options = {}) => {
2947
3035
  return;
2948
3036
  }
2949
3037
  } catch (error2) {
2950
- console.error("Error monitoring payment:", error2);
3038
+ console.error("Error monitoring payment:", {
3039
+ transactionId,
3040
+ purchaseId,
3041
+ error: error2
3042
+ });
2951
3043
  setRetryCount((prev) => prev + 1);
2952
3044
  if (retryCount >= maxRetries) {
2953
3045
  if (intervalRef.current) {
@@ -2997,6 +3089,11 @@ var usePaymentStatus = (options = {}) => {
2997
3089
  } catch (error2) {
2998
3090
  const errorMessage = error2 instanceof Error ? error2.message : "Failed to check status";
2999
3091
  setError(errorMessage);
3092
+ console.error("Failed to check payment status:", {
3093
+ transactionId,
3094
+ purchaseId,
3095
+ error: error2
3096
+ });
3000
3097
  } finally {
3001
3098
  setIsLoading(false);
3002
3099
  }