You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

122 lines
3.2 KiB

import React, { useState } from "https://esm.sh/react@17.0.2";
import styled from "https://esm.sh/styled-components";
import { QRCode } from "https://esm.sh/react-qr-svg";
import { bech32 } from "https://esm.sh/bech32";
import config from "../back/config/config.ts";
import { bytesToString } from "../back/utils.ts";
export const DonateContainer = styled.div`
margin: 0 auto 100px;
max-width: 400px;
text-align: center;
`;
export const DonateText = styled.a`
display: block;
text-align: center;
color: #404040;
text-shadow: #000 1px 1px 0px;
cursor: pointer;
`;
export const Bolt11Text = styled.a`
display: block;
overflow-wrap: anywhere;
font-size: 11px;
color: #aaa;
cursor: pointer;
margin-top: 5px;
margin-bottom: 15px;
`;
export const InvoiceText = styled.p`
text-align: center;
color: #aaa;
text-shadow: #000 1px 1px 0px;
`;
export const ChangeToBolt11 = styled.a`
display: block;
text-align: center;
color: #aaa;
text-shadow: #000 1px 1px 0px;
cursor: pointer;
text-decoration: underline;
font-size: 14px;
`;
const lnurlPayBech32 = bech32.encode(
"lnurl",
bech32.toWords(new TextEncoder().encode(config.donation?.lnurlPayUrl)),
1024
);
export function Donation() {
const [type, setType] = useState<"lnurl-pay" | "bolt11">("lnurl-pay");
const [invoice, setInvoice] = useState<string | undefined>(undefined);
const showLnUrlPay = () => {
setType("lnurl-pay");
setInvoice(lnurlPayBech32);
};
const decodeLnUrlPay = async () => {
const decodedBech32 = bech32.decode(invoice!, 1024);
const decodedUrl = bytesToString(bech32.fromWords(decodedBech32.words));
const result = await fetch(decodedUrl);
const resultJson = await result.json();
const amount = prompt(
`Choose an amount between ${resultJson.minSendable} sats and ${resultJson.maxSendable} sats`,
resultJson.minSendable
);
const amountNumber = Number.parseInt(amount!) * 1000;
if (Number.isNaN(amountNumber)) {
return;
}
const callback = resultJson.callback;
const resultCallback = await fetch(callback + "?amount=" + amountNumber);
const resultCallbackJson = await resultCallback.json();
setType("bolt11");
setInvoice(resultCallbackJson.pr);
};
const onClickInvoice = () => {
window.location.replace("lightning:" + invoice);
};
return (
<DonateContainer>
{!invoice && <DonateText onClick={showLnUrlPay}>Donate via Lightning Network</DonateText>}
{invoice && (
<>
<InvoiceText>
{type === "lnurl-pay" && <>LNURL-pay</>}
{type === "bolt11" && <>LN Invoice</>} QR code:
</InvoiceText>
<div style={{ cursor: "pointer" }} onClick={onClickInvoice}>
<QRCode
bgColor="#FFFFFF"
fgColor="#000000"
value={invoice.toUpperCase()}
style={{ border: "8px solid #fff", width: 200 }}
/>
</div>
<Bolt11Text onClick={onClickInvoice}>{invoice}</Bolt11Text>
{type == "lnurl-pay" && (
<ChangeToBolt11 onClick={decodeLnUrlPay}>
Unsupported wallet? Click to change to normal BOLT11 invoice
</ChangeToBolt11>
)}
</>
)}
</DonateContainer>
);
}