@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 +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.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",
|
|
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
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
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:",
|
|
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("
|
|
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
|
-
|
|
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
|
-
|
|
1787
|
-
|
|
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
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
setQrDataUri(null);
|
|
1846
|
-
setError(null);
|
|
1902
|
+
useEffect(() => {
|
|
1903
|
+
let cancelled = false;
|
|
1904
|
+
const generateIntent = async () => {
|
|
1847
1905
|
clearTimers();
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1954
|
+
renderQr,
|
|
1955
|
+
resetState,
|
|
1879
1956
|
solanaService,
|
|
1880
1957
|
startCountdown,
|
|
1881
|
-
|
|
1958
|
+
tokenSymbol,
|
|
1959
|
+
refreshNonce
|
|
1882
1960
|
]);
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
}, [
|
|
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
|
|
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:",
|
|
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:",
|
|
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:",
|
|
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
|
}
|