From 2e37ab9370eccfde06e333e768ff2072ed30dc90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Aaron?= Date: Fri, 1 Dec 2023 00:05:14 +0100 Subject: [PATCH 01/17] feat: basic NWC connector implementation --- src/app/router/connectorRoutes.tsx | 9 ++ .../screens/connectors/ConnectNWC/index.tsx | 97 ++++++++++++++++++ .../background-script/connectors/index.ts | 2 + .../background-script/connectors/nwc.ts | 99 +++++++++++++++++++ src/i18n/locales/en/translation.json | 13 +++ static/assets/icons/nwc.svg | 1 + 6 files changed, 221 insertions(+) create mode 100644 src/app/screens/connectors/ConnectNWC/index.tsx create mode 100644 src/extension/background-script/connectors/nwc.ts create mode 100644 static/assets/icons/nwc.svg diff --git a/src/app/router/connectorRoutes.tsx b/src/app/router/connectorRoutes.tsx index 417770ed69..760d827153 100644 --- a/src/app/router/connectorRoutes.tsx +++ b/src/app/router/connectorRoutes.tsx @@ -14,6 +14,7 @@ import ConnectUmbrel from "@screens/connectors/ConnectUmbrel"; import { Route } from "react-router-dom"; import i18n from "~/i18n/i18nConfig"; +import ConnectNWC from "~/app/screens/connectors/ConnectNWC"; import ConnectCommando from "../screens/connectors/ConnectCommando"; import btcpay from "/static/assets/icons/btcpay.svg"; import citadel from "/static/assets/icons/citadel.png"; @@ -27,6 +28,7 @@ import lnbits from "/static/assets/icons/lnbits.png"; import lnd from "/static/assets/icons/lnd.png"; import lndhubGo from "/static/assets/icons/lndhub_go.png"; import mynode from "/static/assets/icons/mynode.png"; +import nwc from "/static/assets/icons/nwc.svg"; import raspiblitz from "/static/assets/icons/raspiblitz.png"; import start9 from "/static/assets/icons/start9.png"; import umbrel from "/static/assets/icons/umbrel.png"; @@ -149,6 +151,12 @@ const connectorMap: { [key: string]: ConnectorRoute } = { title: i18n.t("translation:choose_connector.btcpay.title"), logo: btcpay, }, + nwc: { + path: "nwc", + element: , + title: i18n.t("translation:choose_connector.nwc.title"), + logo: nwc, + }, }; function getDistribution(key: string): ConnectorRoute { @@ -235,6 +243,7 @@ function getConnectorRoutes(): ConnectorRoute[] { getDistribution("mynode"), getDistribution("start9"), getDistribution("raspiblitz"), + connectorMap["nwc"], ]; } diff --git a/src/app/screens/connectors/ConnectNWC/index.tsx b/src/app/screens/connectors/ConnectNWC/index.tsx new file mode 100644 index 0000000000..9654287572 --- /dev/null +++ b/src/app/screens/connectors/ConnectNWC/index.tsx @@ -0,0 +1,97 @@ +import ConnectorForm from "@components/ConnectorForm"; +import TextField from "@components/form/TextField"; +import ConnectionErrorToast from "@components/toasts/ConnectionErrorToast"; +import { useState } from "react"; +import { Trans, 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/nwc.svg"; + +export default function ConnectNWC() { + const navigate = useNavigate(); + const { t } = useTranslation("translation", { + keyPrefix: "choose_connector.nwc", + }); + const [formData, setFormData] = useState({ + nostrWalletConnectUrl: "", + }); + const [loading, setLoading] = useState(false); + + function handleChange(event: React.ChangeEvent) { + setFormData({ + ...formData, + [event.target.name]: event.target.value.trim(), + }); + } + + function getConnectorType() { + return "nwc"; + } + + async function handleSubmit(event: React.FormEvent) { + event.preventDefault(); + setLoading(true); + const { nostrWalletConnectUrl } = formData; + const account = { + name: "NWC", + config: { + nostrWalletConnectUrl, + }, + connector: getConnectorType(), + }; + + try { + const 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 { + console.error(validation); + toast.error( + + ); + } + } catch (e) { + console.error(e); + let message = t("page.errors.connection_failed"); + if (e instanceof Error) { + message += `\n\n${e.message}`; + } + toast.error(message); + } + setLoading(false); + } + + return ( + + + + } + description={t("page.instructions")} + logo={logo} + submitLoading={loading} + submitDisabled={formData.nostrWalletConnectUrl === ""} + onSubmit={handleSubmit} + > +
+ +
+
+ ); +} diff --git a/src/extension/background-script/connectors/index.ts b/src/extension/background-script/connectors/index.ts index f98ee5b268..95bbaef680 100644 --- a/src/extension/background-script/connectors/index.ts +++ b/src/extension/background-script/connectors/index.ts @@ -12,6 +12,7 @@ import NativeCitadel from "./nativecitadel"; import NativeLnBits from "./nativelnbits"; import NativeLnd from "./nativelnd"; import NativeLndHub from "./nativelndhub"; +import NWC from "./nwc"; /* const initialize = (account, password) => { @@ -36,6 +37,7 @@ const connectors = { nativecitadel: NativeCitadel, commando: Commando, alby: Alby, + nwc: NWC, }; export default connectors; diff --git a/src/extension/background-script/connectors/nwc.ts b/src/extension/background-script/connectors/nwc.ts new file mode 100644 index 0000000000..84c9e9255d --- /dev/null +++ b/src/extension/background-script/connectors/nwc.ts @@ -0,0 +1,99 @@ +import { webln } from "@getalby/sdk"; +import { NostrWebLNProvider } from "@getalby/sdk/dist/webln"; +import { Account } from "~/types"; +import Connector, { + CheckPaymentArgs, + CheckPaymentResponse, + ConnectPeerArgs, + ConnectPeerResponse, + GetBalanceResponse, + GetInfoResponse, + GetTransactionsResponse, + KeysendArgs, + MakeInvoiceArgs, + MakeInvoiceResponse, + SendPaymentArgs, + SendPaymentResponse, + SignMessageArgs, + SignMessageResponse, +} from "./connector.interface"; + +interface Config { + connectionString: string; +} + +class NWCConnector implements Connector { + config: Config; + nwc: NostrWebLNProvider; + + get supportedMethods() { + return [ + "getInfo", + "makeInvoice", + "sendPayment", + "sendPaymentAsync", + "signMessage", + "getBalance", + ]; + } + + constructor(account: Account, config: Config) { + this.config = config; + this.nwc = new webln.NostrWebLNProvider({ + nostrWalletConnectUrl: this.config.connectionString, + }); + } + + async init() { + await this.nwc.enable(); + } + + async unload() {} + + async getInfo(): Promise { + // TODO: Load via NWC + return { + data: { alias: "NWC" }, + }; + } + + async getBalance(): Promise { + const balance = await this.nwc.getBalance(); + return { + data: { balance: balance.balance, currency: "BTC" }, + }; + } + + async getTransactions(): Promise { + // TODO: Load via NWC + return { + data: { transactions: [] }, + }; + } + + makeInvoice(args: MakeInvoiceArgs): Promise { + throw new Error("Method not implemented."); + } + + sendPayment(args: SendPaymentArgs): Promise { + throw new Error("Method not implemented."); + } + + keysend(args: KeysendArgs): Promise { + throw new Error("Method not implemented."); + } + + checkPayment(args: CheckPaymentArgs): Promise { + throw new Error("Method not implemented."); + } + + signMessage(args: SignMessageArgs): Promise { + throw new Error("Method not implemented."); + } + + connectPeer(args: ConnectPeerArgs): Promise { + throw new Error("Method not implemented."); + } +} + +export default NWCConnector; diff --git a/src/i18n/locales/en/translation.json b/src/i18n/locales/en/translation.json index 6b18ea4713..0f89a55c4d 100644 --- a/src/i18n/locales/en/translation.json +++ b/src/i18n/locales/en/translation.json @@ -281,6 +281,19 @@ "errors": { "connection_failed": "Connection failed. Is your Core Lightning node online and using the commando plugin?" } + }, + "nwc": { + "title": "Nostr Wallet Connect", + "page": { + "instructions": "TBD", + "url": { + "label": "Nostr Wallet Connect URL", + "placeholder": "nostr+walletconnect://69effe..." + }, + "errors": { + "connection_failed": "Connection failed. Is your Core Lightning node online and using the commando plugin?" + } + } } }, "distributions": { diff --git a/static/assets/icons/nwc.svg b/static/assets/icons/nwc.svg new file mode 100644 index 0000000000..7d9c015292 --- /dev/null +++ b/static/assets/icons/nwc.svg @@ -0,0 +1 @@ + \ No newline at end of file From d220e98261396d7aee711d41a10f559e6ec4643c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Aaron?= Date: Fri, 1 Dec 2023 00:06:06 +0100 Subject: [PATCH 02/17] fix: remove outdated connector template --- .../connectors/connector.example | 62 ------------------- 1 file changed, 62 deletions(-) delete mode 100644 src/extension/background-script/connectors/connector.example diff --git a/src/extension/background-script/connectors/connector.example b/src/extension/background-script/connectors/connector.example deleted file mode 100644 index 06a9aaf6c6..0000000000 --- a/src/extension/background-script/connectors/connector.example +++ /dev/null @@ -1,62 +0,0 @@ -import Connector, { - SendPaymentArgs, - SendPaymentResponse, - CheckPaymentArgs, - CheckPaymentResponse, - GetInfoResponse, - GetBalanceResponse, - MakeInvoiceArgs, - MakeInvoiceResponse, - SignMessageArgs, - SignMessageResponse, - VerifyMessageArgs, - VerifyMessageResponse, -} from "./connector.interface"; - -interface Config {} - -class ConnectorExample implements Connector { - config: Config; - - constructor(config: Config) { - this.config = config; - } - - init() { - // add your own implementation or return Promise.resolve(); - } - - unload() { - // add your own implementation or return Promise.resolve(); - } - - getInfo(): Promise { - // Add your own implementation. - } - - getBalance(): Promise { - // Add your own implementation. - } - - sendPayment(args: SendPaymentArgs): Promise { - // Add your own implementation. - } - - checkPayment(args: CheckPaymentArgs): Promise { - // Add your own implementation. - } - - signMessage(args: SignMessageArgs): Promise { - // Add your own implementation. - } - - verifyMessage(args: VerifyMessageArgs): Promise { - // Add your own implementation. - } - - makeInvoice(args: MakeInvoiceArgs): Promise { - // Add your own implementation. - } -} - -export default ConnectorExample; From 78d3d43eae7de4dfa122eb92575d7322230a9e17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Aaron?= Date: Fri, 1 Dec 2023 23:41:25 +0100 Subject: [PATCH 03/17] feat: add nwc to umbrel --- src/app/router/connectorRoutes.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/app/router/connectorRoutes.tsx b/src/app/router/connectorRoutes.tsx index 760d827153..c094d323f4 100644 --- a/src/app/router/connectorRoutes.tsx +++ b/src/app/router/connectorRoutes.tsx @@ -196,6 +196,7 @@ const distributionMap: { [key: string]: { logo: string; children: Route[] } } = connectorMap["lnc"], connectorMap["commando"], connectorMap["lnbits"], + connectorMap["nwc"], ], }, mynode: { From dc3a3f641463c383e714e9a21823bb45d9d07195 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Aaron?= Date: Fri, 1 Dec 2023 23:48:10 +0100 Subject: [PATCH 04/17] fix: close connection on unload --- src/extension/background-script/connectors/nwc.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/extension/background-script/connectors/nwc.ts b/src/extension/background-script/connectors/nwc.ts index 84c9e9255d..afb453351c 100644 --- a/src/extension/background-script/connectors/nwc.ts +++ b/src/extension/background-script/connectors/nwc.ts @@ -45,10 +45,12 @@ class NWCConnector implements Connector { } async init() { - await this.nwc.enable(); + return this.nwc.enable(); } - async unload() {} + async unload() { + return this.nwc.close(); + } async getInfo(): Promise { // TODO: Load via NWC From a541b14bfff95496596a3b57275f383e9fc918ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Aaron?= Date: Sat, 2 Dec 2023 00:24:29 +0100 Subject: [PATCH 05/17] fix: more methods --- .../background-script/connectors/nwc.ts | 41 +++++++++++++++---- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/src/extension/background-script/connectors/nwc.ts b/src/extension/background-script/connectors/nwc.ts index afb453351c..4963c2d686 100644 --- a/src/extension/background-script/connectors/nwc.ts +++ b/src/extension/background-script/connectors/nwc.ts @@ -19,7 +19,7 @@ import Connector, { } from "./connector.interface"; interface Config { - connectionString: string; + nostrWalletConnectUrl: string; } class NWCConnector implements Connector { @@ -40,7 +40,7 @@ class NWCConnector implements Connector { constructor(account: Account, config: Config) { this.config = config; this.nwc = new webln.NostrWebLNProvider({ - nostrWalletConnectUrl: this.config.connectionString, + nostrWalletConnectUrl: this.config.nostrWalletConnectUrl, }); } @@ -49,7 +49,7 @@ class NWCConnector implements Connector { } async unload() { - return this.nwc.close(); + this.nwc.close(); } async getInfo(): Promise { @@ -73,20 +73,43 @@ class NWCConnector implements Connector { }; } - makeInvoice(args: MakeInvoiceArgs): Promise { - throw new Error("Method not implemented."); + async makeInvoice(args: MakeInvoiceArgs): Promise { + const invoice = await this.nwc.makeInvoice({ + amount: args.amount, + defaultMemo: args.memo, + }); + + return { + data: { + paymentRequest: invoice.paymentRequest, + // TODO: payment hash is missing in the make_invoice response? + rHash: "", + }, + }; } - sendPayment(args: SendPaymentArgs): Promise { - throw new Error("Method not implemented."); + async sendPayment(args: SendPaymentArgs): Promise { + const response = await this.nwc.sendPayment(args.paymentRequest); + return { + data: { + preimage: response.preimage, + paymentHash: response.paymentHash, + // TODO: How to get fees via NWC? + route: { total_amt: 1, total_fees: 1 }, + }, + }; } keysend(args: KeysendArgs): Promise { throw new Error("Method not implemented."); } - checkPayment(args: CheckPaymentArgs): Promise { - throw new Error("Method not implemented."); + async checkPayment(args: CheckPaymentArgs): Promise { + const invoice = await this.nwc.lookupInvoice({ + payment_hash: args.paymentHash, + }); + + return invoice.paid; } signMessage(args: SignMessageArgs): Promise { From 7b1b03a86cc84ac98cffcce17175893df8ef982d Mon Sep 17 00:00:00 2001 From: pavanjoshi914 Date: Tue, 19 Dec 2023 14:51:45 +0530 Subject: [PATCH 06/17] feat: getinfo and keysend methods --- package.json | 2 +- .../background-script/connectors/nwc.ts | 21 +++++++++++++++---- yarn.lock | 8 +++---- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index fa6c675733..3808194f59 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "dependencies": { "@bitcoin-design/bitcoin-icons-react": "^0.1.10", "@bitcoinerlab/secp256k1": "^1.0.5", - "@getalby/sdk": "^3.1.0", + "@getalby/sdk": "^3.2.0", "@headlessui/react": "^1.7.16", "@lightninglabs/lnc-web": "^0.2.4-alpha", "@noble/curves": "^1.1.0", diff --git a/src/extension/background-script/connectors/nwc.ts b/src/extension/background-script/connectors/nwc.ts index 4963c2d686..b8e2d1c210 100644 --- a/src/extension/background-script/connectors/nwc.ts +++ b/src/extension/background-script/connectors/nwc.ts @@ -34,6 +34,7 @@ class NWCConnector implements Connector { "sendPaymentAsync", "signMessage", "getBalance", + "keysend", ]; } @@ -53,9 +54,9 @@ class NWCConnector implements Connector { } async getInfo(): Promise { - // TODO: Load via NWC + const info = await this.nwc.getInfo(); return { - data: { alias: "NWC" }, + data: { ...info, alias: "NWC" }, }; } @@ -100,8 +101,20 @@ class NWCConnector implements Connector { }; } - keysend(args: KeysendArgs): Promise { - throw new Error("Method not implemented."); + async keysend(args: KeysendArgs): Promise { + const data = await this.nwc.keysend({ + destination: args.pubkey, + amount: args.amount, + customRecords: args.customRecords, + }); + + return { + data: { + preimage: data.payment_preimage, + paymentHash: data.payment_hash, + route: { total_amt: data.amount, total_fees: data.fee }, + }, + }; } async checkPayment(args: CheckPaymentArgs): Promise { diff --git a/yarn.lock b/yarn.lock index 8d6a01111a..31fcddb0d4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -666,10 +666,10 @@ resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.52.0.tgz#78fe5f117840f69dc4a353adf9b9cd926353378c" integrity sha512-mjZVbpaeMZludF2fsWLD0Z9gCref1Tk4i9+wddjRvpUNqqcndPkBD09N/Mapey0b3jaXbLm2kICwFv2E64QinA== -"@getalby/sdk@^3.1.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@getalby/sdk/-/sdk-3.1.0.tgz#49a6d7b292f3c6ab1c37e72422aa0f0ec8f43226" - integrity sha512-1WwwMfrCRtlUv3BnT/rqYiE5giztH5ZxfT1fDwhaJGeC8EJXxGjFBbaUhE0Wq98Fcs/hKoGM4gSmp3UHFDuQxg== +"@getalby/sdk@^3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@getalby/sdk/-/sdk-3.2.0.tgz#fec967f741116d0f3ac06db8b27b9d225849fabe" + integrity sha512-gHWGeAcvaynSlV8sZ/DouakgJeNiiPDk3JeZvIYlkAN6A9XUE3n5QV6Flw1kmz8kKoVmv9Cqr0mHN/PFSV1YWw== dependencies: events "^3.3.0" nostr-tools "^1.17.0" From ac88d03a847d05c9ff95d7a62bcbe1ea136021dd Mon Sep 17 00:00:00 2001 From: Roland Bewick Date: Tue, 19 Dec 2023 16:42:03 +0700 Subject: [PATCH 07/17] feat: improve NWC connector instructions --- .../screens/connectors/ConnectNWC/index.tsx | 32 +++++++++++++++++-- src/i18n/locales/en/translation.json | 2 +- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/app/screens/connectors/ConnectNWC/index.tsx b/src/app/screens/connectors/ConnectNWC/index.tsx index 9654287572..5aa1111f00 100644 --- a/src/app/screens/connectors/ConnectNWC/index.tsx +++ b/src/app/screens/connectors/ConnectNWC/index.tsx @@ -76,13 +76,41 @@ export default function ConnectNWC() { } - description={t("page.instructions")} + description={ + , + // eslint-disable-next-line react/jsx-key + , + // eslint-disable-next-line react/jsx-key + , + ]} + /> + } logo={logo} submitLoading={loading} submitDisabled={formData.nostrWalletConnectUrl === ""} onSubmit={handleSubmit} > -
+
Alby Nostr Wallet Connect, the <1>Umbrel Nostr Wallet Connect app, or <2>Mutiny Wallet", "url": { "label": "Nostr Wallet Connect URL", "placeholder": "nostr+walletconnect://69effe..." From 5a554fd0523337e2e940c6428c3db1a643ee1d52 Mon Sep 17 00:00:00 2001 From: pavanjoshi914 Date: Tue, 19 Dec 2023 15:17:56 +0530 Subject: [PATCH 08/17] feat: add getTransactions method --- .../background-script/connectors/nwc.ts | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/src/extension/background-script/connectors/nwc.ts b/src/extension/background-script/connectors/nwc.ts index b8e2d1c210..20aef8c359 100644 --- a/src/extension/background-script/connectors/nwc.ts +++ b/src/extension/background-script/connectors/nwc.ts @@ -6,6 +6,7 @@ import Connector, { CheckPaymentResponse, ConnectPeerArgs, ConnectPeerResponse, + ConnectorTransaction, GetBalanceResponse, GetInfoResponse, GetTransactionsResponse, @@ -56,7 +57,7 @@ class NWCConnector implements Connector { async getInfo(): Promise { const info = await this.nwc.getInfo(); return { - data: { ...info, alias: "NWC" }, + data: info, }; } @@ -68,9 +69,27 @@ class NWCConnector implements Connector { } async getTransactions(): Promise { - // TODO: Load via NWC + const listTransactionsResponse = await this.nwc.listTransactions({ + unpaid: false, + }); + + const transactions: ConnectorTransaction[] = + listTransactionsResponse.transactions.map( + (transaction, index): ConnectorTransaction => ({ + id: `${index}`, + memo: transaction.description, + preimage: transaction.preimage, + payment_hash: transaction.payment_hash, + settled: true, + settleDate: new Date(transaction.settled_at).getTime(), + totalAmount: transaction.amount, + type: transaction.type == "incoming" ? "received" : "sent", + }) + ); return { - data: { transactions: [] }, + data: { + transactions, + }, }; } From fd7110391febab34a5b91140f7d830a2ab64cfd4 Mon Sep 17 00:00:00 2001 From: Roland Bewick Date: Tue, 19 Dec 2023 17:00:23 +0700 Subject: [PATCH 09/17] fix: nwc getInfo --- src/extension/background-script/connectors/nwc.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/extension/background-script/connectors/nwc.ts b/src/extension/background-script/connectors/nwc.ts index 20aef8c359..2eb5a86e44 100644 --- a/src/extension/background-script/connectors/nwc.ts +++ b/src/extension/background-script/connectors/nwc.ts @@ -57,7 +57,7 @@ class NWCConnector implements Connector { async getInfo(): Promise { const info = await this.nwc.getInfo(); return { - data: info, + data: info.node, }; } From 5092598397a2c106a391bff6b385006df11a3650 Mon Sep 17 00:00:00 2001 From: Roland Bewick Date: Tue, 19 Dec 2023 17:16:07 +0700 Subject: [PATCH 10/17] fix: nwc transaction amount --- src/extension/background-script/connectors/nwc.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/extension/background-script/connectors/nwc.ts b/src/extension/background-script/connectors/nwc.ts index 2eb5a86e44..8676a681b9 100644 --- a/src/extension/background-script/connectors/nwc.ts +++ b/src/extension/background-script/connectors/nwc.ts @@ -71,6 +71,7 @@ class NWCConnector implements Connector { async getTransactions(): Promise { const listTransactionsResponse = await this.nwc.listTransactions({ unpaid: false, + limit: 50, // restricted by relay max event payload size }); const transactions: ConnectorTransaction[] = From edd91d3c5a4b48056740b60b6ebc32e794ae3a8c Mon Sep 17 00:00:00 2001 From: Roland Bewick Date: Tue, 19 Dec 2023 17:16:28 +0700 Subject: [PATCH 11/17] fix: remove signMessage from nwc supported methods --- src/extension/background-script/connectors/nwc.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/extension/background-script/connectors/nwc.ts b/src/extension/background-script/connectors/nwc.ts index 8676a681b9..f31a279e01 100644 --- a/src/extension/background-script/connectors/nwc.ts +++ b/src/extension/background-script/connectors/nwc.ts @@ -33,7 +33,6 @@ class NWCConnector implements Connector { "makeInvoice", "sendPayment", "sendPaymentAsync", - "signMessage", "getBalance", "keysend", ]; From 2c39ecf9dbcbadd664693c8aa218b4243144a55e Mon Sep 17 00:00:00 2001 From: Roland Bewick Date: Tue, 19 Dec 2023 20:24:56 +0700 Subject: [PATCH 12/17] fix: receive invoice container larger than popup --- src/app/screens/ReceiveInvoice/index.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/app/screens/ReceiveInvoice/index.tsx b/src/app/screens/ReceiveInvoice/index.tsx index 02242e8e2c..5460dc8472 100644 --- a/src/app/screens/ReceiveInvoice/index.tsx +++ b/src/app/screens/ReceiveInvoice/index.tsx @@ -228,9 +228,11 @@ function ReceiveInvoice() { {t("title")} {invoice ? ( - - {renderInvoice()} - +
+ + {renderInvoice()} + +
) : (
From 6229d8112d90895e8db23ebf2c9212dc86497b6c Mon Sep 17 00:00:00 2001 From: Roland Bewick Date: Tue, 19 Dec 2023 20:29:17 +0700 Subject: [PATCH 13/17] fix: response types in nwc connector methods fix getInfo, sendPayment, keysend, checkPayment, makeInvoice --- package.json | 3 +- .../actions/ln/checkPayment.ts | 5 +- .../background-script/connectors/nwc.ts | 57 +++++++++++++++---- src/extension/providers/webln/index.ts | 6 -- yarn.lock | 13 +++-- 5 files changed, 61 insertions(+), 23 deletions(-) diff --git a/package.json b/package.json index 3808194f59..a09ec74221 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "dependencies": { "@bitcoin-design/bitcoin-icons-react": "^0.1.10", "@bitcoinerlab/secp256k1": "^1.0.5", - "@getalby/sdk": "^3.2.0", + "@getalby/sdk": "^3.2.1", "@headlessui/react": "^1.7.16", "@lightninglabs/lnc-web": "^0.2.4-alpha", "@noble/curves": "^1.1.0", @@ -104,6 +104,7 @@ "@types/webextension-polyfill": "^0.10.5", "@typescript-eslint/eslint-plugin": "^6.8.0", "@typescript-eslint/parser": "^6.8.0", + "@webbtc/webln-types": "^3.0.0", "autoprefixer": "^10.4.16", "buffer": "^6.0.3", "clean-webpack-plugin": "^4.0.0", diff --git a/src/extension/background-script/actions/ln/checkPayment.ts b/src/extension/background-script/actions/ln/checkPayment.ts index 0c3051b95b..a187f59edb 100644 --- a/src/extension/background-script/actions/ln/checkPayment.ts +++ b/src/extension/background-script/actions/ln/checkPayment.ts @@ -3,7 +3,10 @@ import { Message } from "~/types"; import state from "../../state"; const checkPayment = async (message: Message) => { - if (typeof message.args.paymentHash !== "string") { + if ( + typeof message.args.paymentHash !== "string" || + !message.args.paymentHash + ) { return { error: "Payment hash missing.", }; diff --git a/src/extension/background-script/connectors/nwc.ts b/src/extension/background-script/connectors/nwc.ts index f31a279e01..50011686e5 100644 --- a/src/extension/background-script/connectors/nwc.ts +++ b/src/extension/background-script/connectors/nwc.ts @@ -1,5 +1,8 @@ import { webln } from "@getalby/sdk"; import { NostrWebLNProvider } from "@getalby/sdk/dist/webln"; +import lightningPayReq from "bolt11"; +import Hex from "crypto-js/enc-hex"; +import SHA256 from "crypto-js/sha256"; import { Account } from "~/types"; import Connector, { CheckPaymentArgs, @@ -99,23 +102,42 @@ class NWCConnector implements Connector { defaultMemo: args.memo, }); + const decodedInvoice = lightningPayReq.decode(invoice.paymentRequest); + const paymentHash = decodedInvoice.tags.find( + (tag) => tag.tagName === "payment_hash" + )?.data as string | undefined; + if (!paymentHash) { + throw new Error("Could not find payment hash in invoice"); + } + return { data: { paymentRequest: invoice.paymentRequest, - // TODO: payment hash is missing in the make_invoice response? - rHash: "", + rHash: paymentHash, }, }; } async sendPayment(args: SendPaymentArgs): Promise { + const invoice = lightningPayReq.decode(args.paymentRequest); + const paymentHash = invoice.tags.find( + (tag) => tag.tagName === "payment_hash" + )?.data as string | undefined; + if (!paymentHash) { + throw new Error("Could not find payment hash in invoice"); + } + const response = await this.nwc.sendPayment(args.paymentRequest); return { data: { preimage: response.preimage, - paymentHash: response.paymentHash, - // TODO: How to get fees via NWC? - route: { total_amt: 1, total_fees: 1 }, + paymentHash, + route: { + // TODO: how to get amount paid for zero-amount invoices? + total_amt: parseInt(invoice.millisatoshis || "0") / 1000, + // TODO: How to get fees from WebLN? + total_fees: 0, + }, }, }; } @@ -127,21 +149,34 @@ class NWCConnector implements Connector { customRecords: args.customRecords, }); + const paymentHash = SHA256(data.preimage).toString(Hex); + return { data: { - preimage: data.payment_preimage, - paymentHash: data.payment_hash, - route: { total_amt: data.amount, total_fees: data.fee }, + preimage: data.preimage, + paymentHash, + + route: { + total_amt: args.amount, + // TODO: How to get fees from WebLN? + total_fees: 0, + }, }, }; } async checkPayment(args: CheckPaymentArgs): Promise { - const invoice = await this.nwc.lookupInvoice({ - payment_hash: args.paymentHash, + // TODO: update WebLN types package + const response = await this.nwc.lookupInvoice({ + paymentHash: args.paymentHash, }); - return invoice.paid; + return { + data: { + paid: response.paid, + preimage: response.preimage, + }, + }; } signMessage(args: SignMessageArgs): Promise { diff --git a/src/extension/providers/webln/index.ts b/src/extension/providers/webln/index.ts index 2ed7815354..1b2e85d6d5 100644 --- a/src/extension/providers/webln/index.ts +++ b/src/extension/providers/webln/index.ts @@ -1,11 +1,5 @@ import ProviderBase from "~/extension/providers/providerBase"; -declare global { - interface Window { - webln: WebLNProvider; - } -} - type RequestInvoiceArgs = { amount?: string | number; defaultAmount?: string | number; diff --git a/yarn.lock b/yarn.lock index 31fcddb0d4..67e4de929b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -666,10 +666,10 @@ resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.52.0.tgz#78fe5f117840f69dc4a353adf9b9cd926353378c" integrity sha512-mjZVbpaeMZludF2fsWLD0Z9gCref1Tk4i9+wddjRvpUNqqcndPkBD09N/Mapey0b3jaXbLm2kICwFv2E64QinA== -"@getalby/sdk@^3.2.0": - version "3.2.0" - resolved "https://registry.yarnpkg.com/@getalby/sdk/-/sdk-3.2.0.tgz#fec967f741116d0f3ac06db8b27b9d225849fabe" - integrity sha512-gHWGeAcvaynSlV8sZ/DouakgJeNiiPDk3JeZvIYlkAN6A9XUE3n5QV6Flw1kmz8kKoVmv9Cqr0mHN/PFSV1YWw== +"@getalby/sdk@^3.2.1": + version "3.2.1" + resolved "https://registry.yarnpkg.com/@getalby/sdk/-/sdk-3.2.1.tgz#22b1b9166b69e1da45d344b77f8392afa260ac9b" + integrity sha512-HiubqthabslUxlMPEy2QtSvZM/Lzd9FjjLsgR8l55hW5lk7FUqcKWGaLFbCCx61CQHuUVjcuf1kiuf1pf235sg== dependencies: events "^3.3.0" nostr-tools "^1.17.0" @@ -2102,6 +2102,11 @@ "@webassemblyjs/ast" "1.11.6" "@xtuc/long" "4.2.2" +"@webbtc/webln-types@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@webbtc/webln-types/-/webln-types-3.0.0.tgz#448b2138423865087ba8859e9e6430fc2463b864" + integrity sha512-aXfTHLKz5lysd+6xTeWl+qHNh/p3qVYbeLo+yDN5cUDmhie2ZoGvkppfWxzbGkcFBzb6dJyQ2/i2cbmDHas+zQ== + "@webpack-cli/configtest@^2.1.1": version "2.1.1" resolved "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz" From 260aa9b2dbbcf26fa750a5719282f89c96dc3feb Mon Sep 17 00:00:00 2001 From: Roland Bewick Date: Tue, 19 Dec 2023 20:32:55 +0700 Subject: [PATCH 14/17] chore: simplify nwc instructions --- src/i18n/locales/en/translation.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i18n/locales/en/translation.json b/src/i18n/locales/en/translation.json index ad2c0333ee..8a9b538844 100644 --- a/src/i18n/locales/en/translation.json +++ b/src/i18n/locales/en/translation.json @@ -289,7 +289,7 @@ "nwc": { "title": "Nostr Wallet Connect", "page": { - "instructions": "Paste a NWC connection string from <0>Alby Nostr Wallet Connect, the <1>Umbrel Nostr Wallet Connect app, or <2>Mutiny Wallet", + "instructions": "Paste a NWC connection string from <0>Alby Nostr Wallet Connect, <1>Umbrel Nostr Wallet Connect, or <2>Mutiny Wallet", "url": { "label": "Nostr Wallet Connect URL", "placeholder": "nostr+walletconnect://69effe..." From ad26b98322d8101ce4a326bc852dd412eab26ffa Mon Sep 17 00:00:00 2001 From: Roland <33993199+rolznz@users.noreply.github.com> Date: Tue, 19 Dec 2023 20:40:17 +0700 Subject: [PATCH 15/17] chore: remove old TODO --- src/extension/background-script/connectors/nwc.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/extension/background-script/connectors/nwc.ts b/src/extension/background-script/connectors/nwc.ts index 50011686e5..cc53fa751a 100644 --- a/src/extension/background-script/connectors/nwc.ts +++ b/src/extension/background-script/connectors/nwc.ts @@ -166,7 +166,6 @@ class NWCConnector implements Connector { } async checkPayment(args: CheckPaymentArgs): Promise { - // TODO: update WebLN types package const response = await this.nwc.lookupInvoice({ paymentHash: args.paymentHash, }); From 74055d20200b055286288a3c78006e4a0a8a5601 Mon Sep 17 00:00:00 2001 From: pavanjoshi914 Date: Tue, 19 Dec 2023 19:15:20 +0530 Subject: [PATCH 16/17] chore: add getTransaction in list of supported methods --- src/extension/background-script/connectors/nwc.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/extension/background-script/connectors/nwc.ts b/src/extension/background-script/connectors/nwc.ts index cc53fa751a..5f065f77d1 100644 --- a/src/extension/background-script/connectors/nwc.ts +++ b/src/extension/background-script/connectors/nwc.ts @@ -38,6 +38,7 @@ class NWCConnector implements Connector { "sendPaymentAsync", "getBalance", "keysend", + "getTransactions", ]; } From 5cfae974a3d3cd29bdd8b001a9c80fa023221862 Mon Sep 17 00:00:00 2001 From: Roland Bewick Date: Fri, 22 Dec 2023 12:38:41 +0700 Subject: [PATCH 17/17] chore: bump alby js sdk version --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index a09ec74221..834c1129e9 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "dependencies": { "@bitcoin-design/bitcoin-icons-react": "^0.1.10", "@bitcoinerlab/secp256k1": "^1.0.5", - "@getalby/sdk": "^3.2.1", + "@getalby/sdk": "^3.2.2", "@headlessui/react": "^1.7.16", "@lightninglabs/lnc-web": "^0.2.4-alpha", "@noble/curves": "^1.1.0", diff --git a/yarn.lock b/yarn.lock index 67e4de929b..5694c21c67 100644 --- a/yarn.lock +++ b/yarn.lock @@ -666,10 +666,10 @@ resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.52.0.tgz#78fe5f117840f69dc4a353adf9b9cd926353378c" integrity sha512-mjZVbpaeMZludF2fsWLD0Z9gCref1Tk4i9+wddjRvpUNqqcndPkBD09N/Mapey0b3jaXbLm2kICwFv2E64QinA== -"@getalby/sdk@^3.2.1": - version "3.2.1" - resolved "https://registry.yarnpkg.com/@getalby/sdk/-/sdk-3.2.1.tgz#22b1b9166b69e1da45d344b77f8392afa260ac9b" - integrity sha512-HiubqthabslUxlMPEy2QtSvZM/Lzd9FjjLsgR8l55hW5lk7FUqcKWGaLFbCCx61CQHuUVjcuf1kiuf1pf235sg== +"@getalby/sdk@^3.2.2": + version "3.2.2" + resolved "https://registry.yarnpkg.com/@getalby/sdk/-/sdk-3.2.2.tgz#a640fef78f4462fd8924eab9ab8a8f9a0339a11e" + integrity sha512-G4Ooteo/5D6SXB+y8OK8gxXWALGh4HFgq8ZqT3rBMo3FV7U/fDjf+/jn/SMsJ7ub/nEzUBBTGdfARdVoYqMvSQ== dependencies: events "^3.3.0" nostr-tools "^1.17.0"