@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.cjs CHANGED
@@ -65,12 +65,18 @@ var loadCollectJs = (tokenizationKey) => {
65
65
  if (existing) return;
66
66
  const script = document.createElement("script");
67
67
  script.src = SCRIPT_SRC;
68
- script.setAttribute("data-tokenization-key", "8u8B78-23Z347-c2svF3-pbEb7G");
68
+ script.setAttribute("data-tokenization-key", trimmed);
69
69
  script.setAttribute("data-field-ccnumber-placeholder", "0000 0000 0000 0000");
70
70
  script.setAttribute("data-field-ccexp-placeholder", "10 / 25");
71
71
  script.setAttribute("data-field-cvv-placeholder", "123");
72
72
  script.setAttribute("data-variant", "inline");
73
73
  script.async = true;
74
+ script.addEventListener("load", () => {
75
+ console.log("payments-ui: Collect.js loaded");
76
+ });
77
+ script.addEventListener("error", (event) => {
78
+ console.error("payments-ui: failed to load Collect.js", event);
79
+ });
74
80
  document.head.appendChild(script);
75
81
  };
76
82
 
@@ -106,20 +112,31 @@ var createApiClient = (paymentConfig, baseUrl, fetcher, resolveAuthToken) => {
106
112
  if (token) {
107
113
  headers.Authorization = `Bearer ${token}`;
108
114
  }
109
- const response = await fetcher(url, {
110
- method,
111
- headers,
112
- body: options?.body ? JSON.stringify(options.body) : void 0
113
- });
114
- if (!response.ok) {
115
- const message = await response.text();
116
- throw new Error(message || `Request failed with status ${response.status}`);
117
- }
118
- if (response.status === 204) {
119
- return void 0;
115
+ try {
116
+ const response = await fetcher(url, {
117
+ method,
118
+ headers,
119
+ body: options?.body ? JSON.stringify(options.body) : void 0
120
+ });
121
+ if (!response.ok) {
122
+ const message = await response.text();
123
+ console.error("payments-ui: API request failed", {
124
+ url,
125
+ method,
126
+ status: response.status,
127
+ message
128
+ });
129
+ throw new Error(message || `Request failed with status ${response.status}`);
130
+ }
131
+ if (response.status === 204) {
132
+ return void 0;
133
+ }
134
+ const data = await response.json();
135
+ return data;
136
+ } catch (error) {
137
+ console.error("payments-ui: API request error", { url, method, error });
138
+ throw error;
120
139
  }
121
- const data = await response.json();
122
- return data;
123
140
  };
124
141
  return {
125
142
  request,
@@ -1595,8 +1612,16 @@ var useSolanaDirectPayment = (options) => {
1595
1612
  const balance = balanceInfo?.balance || 0;
1596
1613
  const hasBalanceFlag = hasSufficientBalance(balance, tokenAmount);
1597
1614
  setTokenBalance({ balance, hasBalance: hasBalanceFlag });
1615
+ console.log("payments-ui: Solana wallet balance", {
1616
+ token: selectedToken.symbol,
1617
+ balance,
1618
+ required: tokenAmount
1619
+ });
1598
1620
  } catch (error) {
1599
- console.error("Failed to fetch token balance:", error);
1621
+ console.error("Failed to fetch token balance:", {
1622
+ token: selectedToken?.symbol,
1623
+ error
1624
+ });
1600
1625
  setTokenBalance({ balance: 0, hasBalance: false });
1601
1626
  } finally {
1602
1627
  setIsBalanceLoading(false);
@@ -1660,30 +1685,49 @@ var useSolanaDirectPayment = (options) => {
1660
1685
  return;
1661
1686
  }
1662
1687
  if (!tokenBalance?.hasBalance) {
1688
+ console.warn("payments-ui: insufficient balance for Solana direct payment", {
1689
+ token: selectedToken.symbol
1690
+ });
1663
1691
  onError("Insufficient balance for this token");
1664
1692
  return;
1665
1693
  }
1666
1694
  try {
1667
1695
  setIsProcessing(true);
1668
1696
  onStart();
1697
+ console.log("payments-ui: initiating Solana direct payment", {
1698
+ priceId,
1699
+ token: selectedToken.symbol
1700
+ });
1669
1701
  const paymentData = await solanaService.generatePayment(
1670
1702
  priceId,
1671
1703
  selectedToken.symbol,
1672
1704
  publicKey.toBase58()
1673
1705
  );
1706
+ console.log("payments-ui: Solana payment intent created", {
1707
+ intentId: paymentData.intent_id
1708
+ });
1674
1709
  const transactionToSign = decodeTransaction(paymentData.transaction);
1710
+ console.log("payments-ui: requesting Solana wallet signature");
1675
1711
  const signedTx = await signWithWallet(transactionToSign);
1676
1712
  const signedSerialized = buffer.Buffer.from(signedTx.serialize()).toString("base64");
1677
1713
  onConfirming();
1714
+ console.log("payments-ui: submitting signed Solana transaction");
1678
1715
  const result = await solanaService.submitPayment(
1679
1716
  signedSerialized,
1680
1717
  priceId,
1681
1718
  paymentData.intent_id,
1682
1719
  `Payment for subscription - ${selectedToken.symbol}`
1683
1720
  );
1721
+ console.log("payments-ui: Solana direct payment confirmed", {
1722
+ transactionId: result.transaction_id
1723
+ });
1684
1724
  onSuccess(result, result.transaction_id);
1685
1725
  } catch (err) {
1686
- console.error("Payment failed:", err);
1726
+ console.error("Solana direct payment failed:", {
1727
+ priceId,
1728
+ token: selectedToken.symbol,
1729
+ error: err
1730
+ });
1687
1731
  let errorMessage = "Payment failed. Please try again.";
1688
1732
  const message = err instanceof Error ? err.message : typeof err === "string" ? err : "";
1689
1733
  if (message.includes("User rejected")) {
@@ -1775,11 +1819,13 @@ var DirectPayment = ({
1775
1819
  var useSolanaQrPayment = (options) => {
1776
1820
  const { priceId, selectedToken, onSuccess, onError } = options;
1777
1821
  const solanaService = useSolanaService();
1822
+ const tokenSymbol = selectedToken?.symbol ?? null;
1778
1823
  const [intent, setIntent] = React3.useState(null);
1779
1824
  const [qrDataUri, setQrDataUri] = React3.useState(null);
1780
1825
  const [isLoading, setIsLoading] = React3.useState(false);
1781
1826
  const [error, setError] = React3.useState(null);
1782
1827
  const [timeRemaining, setTimeRemaining] = React3.useState(0);
1828
+ const [refreshNonce, setRefreshNonce] = React3.useState(0);
1783
1829
  const pollRef = React3.useRef(null);
1784
1830
  const countdownRef = React3.useRef(null);
1785
1831
  const clearTimers = React3.useCallback(() => {
@@ -1797,27 +1843,41 @@ var useSolanaQrPayment = (options) => {
1797
1843
  clearTimers();
1798
1844
  };
1799
1845
  }, [clearTimers]);
1846
+ const resetState = React3.useCallback(
1847
+ (message) => {
1848
+ clearTimers();
1849
+ setIntent((prev) => prev ? null : prev);
1850
+ setQrDataUri((prev) => prev ? null : prev);
1851
+ setTimeRemaining((prev) => prev !== 0 ? 0 : prev);
1852
+ setError((prev) => {
1853
+ const next = message === void 0 ? null : message;
1854
+ return prev === next ? prev : next;
1855
+ });
1856
+ },
1857
+ [clearTimers]
1858
+ );
1800
1859
  const handleError = React3.useCallback(
1801
1860
  (message, notifyParent = false) => {
1861
+ console.error("[payments-ui] Solana Pay QR error:", message);
1802
1862
  clearTimers();
1803
- setError(message);
1804
- setIntent(null);
1805
- setQrDataUri(null);
1806
- setTimeRemaining(0);
1863
+ resetState(message);
1807
1864
  if (notifyParent) {
1808
1865
  onError(message);
1809
1866
  }
1810
1867
  },
1811
- [clearTimers, onError]
1868
+ [clearTimers, onError, resetState]
1812
1869
  );
1813
1870
  const handleSuccess = React3.useCallback(
1814
1871
  (status) => {
1815
1872
  clearTimers();
1816
- setTimeRemaining(0);
1817
- setIntent(null);
1873
+ resetState(null);
1874
+ console.log("[payments-ui] Solana Pay QR confirmed", {
1875
+ paymentId: status.payment_id,
1876
+ intentId: status.intent_id
1877
+ });
1818
1878
  onSuccess(status.payment_id, status.transaction || "");
1819
1879
  },
1820
- [clearTimers, onSuccess]
1880
+ [clearTimers, onSuccess, resetState]
1821
1881
  );
1822
1882
  const pollStatus = React3.useCallback(
1823
1883
  async (reference) => {
@@ -1869,57 +1929,75 @@ var useSolanaQrPayment = (options) => {
1869
1929
  handleError("Unable to render QR code");
1870
1930
  }
1871
1931
  }, [handleError]);
1872
- const fetchIntent = React3.useCallback(async () => {
1873
- if (!selectedToken) {
1874
- setIntent(null);
1875
- setQrDataUri(null);
1876
- setError(null);
1932
+ React3.useEffect(() => {
1933
+ let cancelled = false;
1934
+ const generateIntent = async () => {
1877
1935
  clearTimers();
1878
- setTimeRemaining(0);
1879
- return;
1880
- }
1881
- try {
1882
- setIsLoading(true);
1883
- setError(null);
1936
+ if (!tokenSymbol || !priceId) {
1937
+ resetState(null);
1938
+ setIsLoading((prev) => prev ? false : prev);
1939
+ return;
1940
+ }
1941
+ try {
1942
+ setIsLoading(true);
1943
+ setError(null);
1944
+ console.log("[payments-ui] Requesting Solana Pay QR intent", {
1945
+ priceId,
1946
+ token: tokenSymbol
1947
+ });
1948
+ const nextIntent = await solanaService.generateQRCode(
1949
+ priceId,
1950
+ tokenSymbol
1951
+ );
1952
+ if (cancelled) return;
1953
+ setIntent(nextIntent);
1954
+ setTimeRemaining(
1955
+ Math.max(0, Math.floor(nextIntent.expires_at - Date.now() / 1e3))
1956
+ );
1957
+ await renderQr(nextIntent);
1958
+ console.log("[payments-ui] Solana Pay QR ready", {
1959
+ reference: nextIntent.reference
1960
+ });
1961
+ startCountdown(nextIntent.expires_at, nextIntent.reference);
1962
+ pollStatus(nextIntent.reference);
1963
+ } catch (err) {
1964
+ if (cancelled) return;
1965
+ console.error("Failed to generate Solana Pay QR intent:", err);
1966
+ const message = err instanceof Error ? err.message : "Unable to create Solana Pay QR code";
1967
+ handleError(message);
1968
+ } finally {
1969
+ if (!cancelled) {
1970
+ setIsLoading(false);
1971
+ }
1972
+ }
1973
+ };
1974
+ void generateIntent();
1975
+ return () => {
1976
+ cancelled = true;
1884
1977
  clearTimers();
1885
- const nextIntent = await solanaService.generateQRCode(
1886
- priceId,
1887
- selectedToken.symbol
1888
- );
1889
- setIntent(nextIntent);
1890
- setTimeRemaining(
1891
- Math.max(0, Math.floor(nextIntent.expires_at - Date.now() / 1e3))
1892
- );
1893
- await renderQr(nextIntent);
1894
- startCountdown(nextIntent.expires_at, nextIntent.reference);
1895
- pollStatus(nextIntent.reference);
1896
- } catch (err) {
1897
- console.error("Failed to generate Solana Pay QR intent:", err);
1898
- const message = err instanceof Error ? err.message : "Unable to create Solana Pay QR code";
1899
- handleError(message);
1900
- } finally {
1901
- setIsLoading(false);
1902
- }
1978
+ };
1903
1979
  }, [
1904
1980
  clearTimers,
1905
1981
  handleError,
1906
1982
  pollStatus,
1907
1983
  priceId,
1908
- selectedToken,
1984
+ renderQr,
1985
+ resetState,
1909
1986
  solanaService,
1910
1987
  startCountdown,
1911
- renderQr
1988
+ tokenSymbol,
1989
+ refreshNonce
1912
1990
  ]);
1913
- React3.useEffect(() => {
1914
- void fetchIntent();
1915
- }, [fetchIntent]);
1991
+ const refresh = React3.useCallback(() => {
1992
+ setRefreshNonce((value) => value + 1);
1993
+ }, []);
1916
1994
  return {
1917
1995
  intent,
1918
1996
  qrDataUri,
1919
1997
  isLoading,
1920
1998
  error,
1921
1999
  timeRemaining,
1922
- refresh: fetchIntent
2000
+ refresh
1923
2001
  };
1924
2002
  };
1925
2003
  var QRCodePayment = ({
@@ -2042,11 +2120,15 @@ var useSupportedTokens = () => {
2042
2120
  setIsLoading(true);
2043
2121
  setError(null);
2044
2122
  try {
2123
+ console.log("payments-ui: fetching supported Solana tokens");
2045
2124
  const tokens2 = await solanaService.getSupportedTokens();
2046
2125
  const sortedTokens = [...tokens2].sort(
2047
2126
  (a, b) => a.symbol.localeCompare(b.symbol)
2048
2127
  );
2049
2128
  setTokens(sortedTokens);
2129
+ console.log("payments-ui: loaded supported tokens", {
2130
+ count: sortedTokens.length
2131
+ });
2050
2132
  setLastFetched(Date.now());
2051
2133
  return sortedTokens;
2052
2134
  } catch (error2) {
@@ -2892,7 +2974,10 @@ var usePaymentStatus = (options = {}) => {
2892
2974
  error: err ? `Transaction failed: ${err}` : void 0
2893
2975
  };
2894
2976
  } catch (error2) {
2895
- console.error("Failed to check transaction status:", error2);
2977
+ console.error("Failed to check transaction status:", {
2978
+ signature,
2979
+ error: error2
2980
+ });
2896
2981
  return {
2897
2982
  signature,
2898
2983
  confirmationStatus: "failed",
@@ -2914,7 +2999,10 @@ var usePaymentStatus = (options = {}) => {
2914
2999
  if (error2?.status === 404) {
2915
3000
  return null;
2916
3001
  }
2917
- console.error("Failed to check payment status:", error2);
3002
+ console.error("Failed to check payment status:", {
3003
+ purchaseId: id,
3004
+ error: error2
3005
+ });
2918
3006
  return null;
2919
3007
  }
2920
3008
  },
@@ -2977,7 +3065,11 @@ var usePaymentStatus = (options = {}) => {
2977
3065
  return;
2978
3066
  }
2979
3067
  } catch (error2) {
2980
- console.error("Error monitoring payment:", error2);
3068
+ console.error("Error monitoring payment:", {
3069
+ transactionId,
3070
+ purchaseId,
3071
+ error: error2
3072
+ });
2981
3073
  setRetryCount((prev) => prev + 1);
2982
3074
  if (retryCount >= maxRetries) {
2983
3075
  if (intervalRef.current) {
@@ -3027,6 +3119,11 @@ var usePaymentStatus = (options = {}) => {
3027
3119
  } catch (error2) {
3028
3120
  const errorMessage = error2 instanceof Error ? error2.message : "Failed to check status";
3029
3121
  setError(errorMessage);
3122
+ console.error("Failed to check payment status:", {
3123
+ transactionId,
3124
+ purchaseId,
3125
+ error: error2
3126
+ });
3030
3127
  } finally {
3031
3128
  setIsLoading(false);
3032
3129
  }