Skip to content

Commit

Permalink
feat: connect to btcpay via core lightning
Browse files Browse the repository at this point in the history
  • Loading branch information
pavanjoshi914 committed Feb 7, 2024
1 parent 6b210d1 commit 6429e61
Show file tree
Hide file tree
Showing 4 changed files with 183 additions and 13 deletions.
27 changes: 19 additions & 8 deletions src/app/router/connectorRoutes.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import ChooseConnector from "@screens/connectors/ChooseConnector";
import ConnectBtcpay from "@screens/connectors/ConnectBtcpay";
import ConnectCitadel from "@screens/connectors/ConnectCitadel";
import ConnectEclair from "@screens/connectors/ConnectEclair";
import ConnectGaloy, { galoyUrls } from "@screens/connectors/ConnectGaloy";
Expand All @@ -14,6 +13,8 @@ import ConnectUmbrel from "@screens/connectors/ConnectUmbrel";
import { Route } from "react-router-dom";
import i18n from "~/i18n/i18nConfig";

import ConnectBtcpayCommando from "~/app/screens/connectors/ConnectBtcpayCommando";
import ConnectBtcpayLND from "~/app/screens/connectors/ConnectBtcpayLND";
import ConnectNWC from "~/app/screens/connectors/ConnectNWC";
import ConnectVoltage from "~/app/screens/connectors/ConnectVoltage";
import ConnectCommando from "../screens/connectors/ConnectCommando";
Expand Down Expand Up @@ -81,6 +82,18 @@ const connectorMap: { [key: string]: ConnectorRoute } = {
title: i18n.t("translation:choose_connector.umbrel_lightning_node.title"),
logo: lightning_node,
},
"btcpay-lnd": {
path: "lnd",
element: <ConnectBtcpayLND />,
title: i18n.t("translation:choose_connector.lnd.title"),
logo: lnd,
},
"btcpay-commando": {
path: "commando",
element: <ConnectBtcpayCommando />,
title: i18n.t("translation:choose_connector.commando.title"),
logo: core_ln,
},
"raspiblitz-lnd": {
path: "lnd",
element: <ConnectRaspiBlitz />,
Expand Down Expand Up @@ -153,12 +166,6 @@ const connectorMap: { [key: string]: ConnectorRoute } = {
title: i18n.t("translation:choose_connector.bitcoin_jungle.title"),
logo: galoyBitcoinJungle,
},
btcpay: {
path: "btcpay",
element: <ConnectBtcpay />,
title: i18n.t("translation:choose_connector.btcpay.title"),
logo: btcpay,
},
voltage: {
path: "voltage",
element: <ConnectVoltage />,
Expand Down Expand Up @@ -203,6 +210,10 @@ const distributionMap: { [key: string]: { logo: string; children: Route[] } } =
connectorMap["lnbits"],
],
},
btcpay: {
logo: btcpay,
children: [connectorMap["btcpay-lnd"], connectorMap["btcpay-commando"]],
},
umbrel: {
logo: umbrel,
children: [
Expand Down Expand Up @@ -250,7 +261,7 @@ function getConnectorRoutes(): ConnectorRoute[] {
connectorMap["lnbits"],
connectorMap["lnd-hub-go"],
connectorMap["eclair"],
connectorMap["btcpay"],
getDistribution("btcpay"),
connectorMap["voltage"],
connectorMap[galoyPaths.blink],
connectorMap[galoyPaths.bitcoinJungle],
Expand Down
144 changes: 144 additions & 0 deletions src/app/screens/connectors/ConnectBtcpayCommando/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
import CompanionDownloadInfo from "@components/CompanionDownloadInfo";
import ConnectorForm from "@components/ConnectorForm";
import TextField from "@components/form/TextField";
import ConnectionErrorToast from "@components/toasts/ConnectionErrorToast";
import fetchAdapter from "@vespaiach/axios-fetch-adapter";
import axios from "axios";
import { useState } from "react";
import { useTranslation } from "react-i18next";
import { useNavigate } from "react-router-dom";
import toast from "~/app/components/Toast";
import msg from "~/common/lib/msg";

import logo from "/static/assets/icons/btcpay.svg";

const initialFormData = {
url: "",
macaroon: "",
name: "",
};

export default function ConnectBtcpayCommando() {
const navigate = useNavigate();
const { t } = useTranslation("translation", {
keyPrefix: "choose_connector.btcpay_commando",
});
const [formData, setFormData] = useState(initialFormData);
const [loading, setLoading] = useState(false);
const [hasTorSupport, setHasTorSupport] = useState(false);

function getConfigUrl(data: string) {
const configUrl = data.trim().replace("config=", "");
try {
return new URL(configUrl);
} catch (e) {
return null;
}
}
async function handleChange(event: React.ChangeEvent<HTMLInputElement>) {
const configUrl = getConfigUrl(event.target.value);
if (!configUrl) {
return;
}
const host = configUrl.host;
try {
const response = await axios.get<{
configurations: [{ uri: string; adminMacaroon: string }];
}>(configUrl.toString(), { adapter: fetchAdapter });

if (response.data.configurations[0].uri) {
setFormData({
url: response.data.configurations[0].uri,
macaroon: response.data.configurations[0].adminMacaroon,
name: host,
});
}
} catch (e) {
console.error(e);
toast.error(t("errors.connection_failed"));
}
}

function getConnectorType() {
if (formData.url.match(/\.onion/i) && !hasTorSupport) {
return "nativelnd";
}
// default to LND
return "lnd";
}

async function handleSubmit(event: React.FormEvent<HTMLFormElement>) {
event.preventDefault();
setLoading(true);
const { url, macaroon, name } = formData;
const account = {
name: name || "LND",
config: {
macaroon,
url,
},
connector: getConnectorType(),
};

try {
let validation;
// TODO: for native connectors we currently skip the validation because it is too slow (booting up Tor etc.)
if (account.connector === "nativelnd") {
validation = { valid: true, error: "" };
} else {
validation = await msg.request("validateAccount", account);
}

if (validation.valid) {
const addResult = await msg.request("addAccount", account);
if (addResult.accountId) {
await msg.request("selectAccount", {
id: addResult.accountId,
});
navigate("/test-connection");
}
} else {
toast.error(
<ConnectionErrorToast message={validation.error as string} />
);
}
} catch (e) {
console.error(e);
let message = "";
if (e instanceof Error) {
message += `${e.message}`;
}
toast.error(<ConnectionErrorToast message={message} />);
}
setLoading(false);
}

return (
<ConnectorForm
title={t("page.title")}
description={t("page.instructions")}
logo={logo}
submitLoading={loading}
submitDisabled={formData.url === "" || formData.macaroon === ""}
onSubmit={handleSubmit}
>
<TextField
id="btcpay-config"
label={t("config.label")}
placeholder={t("config.placeholder")}
onChange={handleChange}
required
autoFocus={true}
/>
{formData.url.match(/\.onion/i) && (
<div className="mt-6">
<CompanionDownloadInfo
hasTorCallback={(hasTor: boolean) => {
setHasTorSupport(hasTor);
}}
/>
</div>
)}
</ConnectorForm>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ const initialFormData = {
name: "",
};

export default function ConnectBtcpay() {
export default function ConnectBtcpayLND() {
const navigate = useNavigate();
const { t } = useTranslation("translation", {
keyPrefix: "choose_connector.btcpay",
keyPrefix: "choose_connector.btcpay_lnd",
});
const [formData, setFormData] = useState(initialFormData);
const [loading, setLoading] = useState(false);
Expand Down
21 changes: 18 additions & 3 deletions src/i18n/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -258,10 +258,25 @@
}
},
"btcpay": {
"title": "BTCPay Server",
"title": "BTCPay Server"
},
"btcpay_lnd": {
"page": {
"title": "Connect to BTCPay LND",
"instructions": "Navigate to your BTCPayServer and log in as an admin. Go to Server Settings > Services > LND REST - See information. Then Click \"See QR Code information\" and copy the QR Code data. Paste it below:"
},
"config": {
"label": "Config data",
"placeholder": "config=https://your-btc-pay.org/lnd-config/212121/lnd.co"
},
"errors": {
"connection_failed": "Connection failed. Is the BTCPay connection URL correct and accessible?"
}
},
"btcpay_commando": {
"page": {
"title": "Connect to your BTCPay LND node",
"instructions": "Navigate to your BTCPayServer and log in as an admin. Go to Server Settings > Services > LND Rest - See information. Then Click \"See QR Code information\" and copy the QR Code data. Paste it below:"
"title": "Connect to BTCPay CLN",
"instructions": "Navigate to your BTCPayServer and log in as an admin. Go to Server Settings > Services > C- Lightning REST - See information. Then Click \"See QR Code information\" and copy the QR Code data. Paste it below:"
},
"config": {
"label": "Config data",
Expand Down

0 comments on commit 6429e61

Please sign in to comment.