@doujins/payments-ui 0.0.5 → 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 +159 -62
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +159 -62
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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",
|
|
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
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
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:",
|
|
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("
|
|
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
|
-
|
|
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
|
-
|
|
1817
|
-
|
|
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
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
setQrDataUri(null);
|
|
1876
|
-
setError(null);
|
|
1932
|
+
React3.useEffect(() => {
|
|
1933
|
+
let cancelled = false;
|
|
1934
|
+
const generateIntent = async () => {
|
|
1877
1935
|
clearTimers();
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1984
|
+
renderQr,
|
|
1985
|
+
resetState,
|
|
1909
1986
|
solanaService,
|
|
1910
1987
|
startCountdown,
|
|
1911
|
-
|
|
1988
|
+
tokenSymbol,
|
|
1989
|
+
refreshNonce
|
|
1912
1990
|
]);
|
|
1913
|
-
React3.
|
|
1914
|
-
|
|
1915
|
-
}, [
|
|
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
|
|
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:",
|
|
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:",
|
|
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:",
|
|
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
|
}
|