87 lines
2.8 KiB
TypeScript
87 lines
2.8 KiB
TypeScript
import { useEffect, useState } from "react";
|
|
import QRCode from "qrcode";
|
|
import { getDeposit, postRedeemCashu, type DepositInfo } from "../api";
|
|
import { useToast } from "../contexts/ToastContext";
|
|
|
|
export function DepositSection() {
|
|
const [deposit, setDeposit] = useState<DepositInfo | null>(null);
|
|
const [qrDataUrl, setQrDataUrl] = useState<string | null>(null);
|
|
const [cashuToken, setCashuToken] = useState("");
|
|
const [cashuLoading, setCashuLoading] = useState(false);
|
|
const { showToast } = useToast();
|
|
|
|
useEffect(() => {
|
|
getDeposit().then((d) => {
|
|
setDeposit(d);
|
|
const qrContent = d.lightningAddress || d.lnurlp;
|
|
if (qrContent) QRCode.toDataURL(qrContent, { width: 180 }).then(setQrDataUrl);
|
|
}).catch(() => setDeposit(null));
|
|
}, []);
|
|
|
|
const copyAddress = () => {
|
|
if (!deposit?.lightningAddress) return;
|
|
navigator.clipboard.writeText(deposit.lightningAddress);
|
|
showToast("Copied");
|
|
};
|
|
|
|
const handleRedeemCashu = async () => {
|
|
const token = cashuToken.trim();
|
|
if (!token || !token.toLowerCase().startsWith("cashu")) {
|
|
showToast("Enter a valid Cashu token (cashuA... or cashuB...)");
|
|
return;
|
|
}
|
|
setCashuLoading(true);
|
|
try {
|
|
const result = await postRedeemCashu(token);
|
|
setCashuToken("");
|
|
const amount = result.amount ?? result.netAmount ?? result.invoiceAmount;
|
|
showToast(amount != null ? `Redeemed ${amount} sats to faucet!` : "Cashu token redeemed to faucet.");
|
|
} catch (e) {
|
|
showToast(e instanceof Error ? e.message : "Redeem failed");
|
|
} finally {
|
|
setCashuLoading(false);
|
|
}
|
|
};
|
|
|
|
if (!deposit) return null;
|
|
if (!deposit.lightningAddress && !deposit.lnurlp) return null;
|
|
|
|
return (
|
|
<div className="deposit-box">
|
|
<h3>Fund the faucet</h3>
|
|
{deposit.lightningAddress && (
|
|
<div className="copy-row">
|
|
<input type="text" readOnly value={deposit.lightningAddress} />
|
|
<button type="button" onClick={copyAddress}>
|
|
Copy
|
|
</button>
|
|
</div>
|
|
)}
|
|
{qrDataUrl && (
|
|
<div className="qr-wrap">
|
|
<img src={qrDataUrl} alt="Deposit QR" width={180} height={180} />
|
|
</div>
|
|
)}
|
|
<div className="cashu-redeem">
|
|
<label className="cashu-redeem-label">Redeem Cashu token to faucet</label>
|
|
<textarea
|
|
className="cashu-redeem-input"
|
|
placeholder="Paste Cashu token (cashuA... or cashuB...)"
|
|
value={cashuToken}
|
|
onChange={(e) => setCashuToken(e.target.value)}
|
|
rows={2}
|
|
disabled={cashuLoading}
|
|
/>
|
|
<button
|
|
type="button"
|
|
className="cashu-redeem-btn"
|
|
onClick={handleRedeemCashu}
|
|
disabled={cashuLoading || !cashuToken.trim()}
|
|
>
|
|
{cashuLoading ? "Redeeming…" : "Redeem to faucet"}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|