Skip to content

Commit

Permalink
Merge pull request #2987 from getAlby/task-nwc-makeinvoice
Browse files Browse the repository at this point in the history
feat: use new nwc client from sdk
  • Loading branch information
pavanjoshi914 authored Jul 15, 2024
2 parents 7a4c58e + 41f63ea commit b43119d
Showing 1 changed file with 58 additions and 44 deletions.
102 changes: 58 additions & 44 deletions src/extension/background-script/connectors/nwc.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { webln } from "@getalby/sdk";
import { NostrWebLNProvider } from "@getalby/sdk/dist/webln";
import { nwc } from "@getalby/sdk";
import lightningPayReq from "bolt11-signet";
import Base64 from "crypto-js/enc-base64";
import Hex from "crypto-js/enc-hex";
import UTF8 from "crypto-js/enc-utf8";
import SHA256 from "crypto-js/sha256";
import { Account } from "~/types";
import Connector, {
Expand Down Expand Up @@ -35,9 +35,14 @@ interface Config {
nostrWalletConnectUrl: string;
}

interface TlvRecord {
type: number;
value: string;
}

class NWCConnector implements Connector {
config: Config;
nwc: NostrWebLNProvider;
nwc: nwc.NWCClient;

get supportedMethods() {
return [
Expand All @@ -54,13 +59,13 @@ class NWCConnector implements Connector {

constructor(account: Account, config: Config) {
this.config = config;
this.nwc = new webln.NostrWebLNProvider({
this.nwc = new nwc.NWCClient({
nostrWalletConnectUrl: this.config.nostrWalletConnectUrl,
});
}

async init() {
return this.nwc.enable();
return Promise.resolve();
}

async unload() {
Expand All @@ -70,14 +75,14 @@ class NWCConnector implements Connector {
async getInfo(): Promise<GetInfoResponse> {
const info = await this.nwc.getInfo();
return {
data: info.node,
data: info,
};
}

async getBalance(): Promise<GetBalanceResponse> {
const balance = await this.nwc.getBalance();
return {
data: { balance: balance.balance, currency: "BTC" },
data: { balance: Math.floor(balance.balance / 1000), currency: "BTC" },
};
}

Expand All @@ -96,9 +101,9 @@ class NWCConnector implements Connector {
payment_hash: transaction.payment_hash,
settled: true,
settleDate: transaction.settled_at * 1000,
totalAmount: transaction.amount,
totalAmount: Math.floor(transaction.amount / 1000),
type: transaction.type == "incoming" ? "received" : "sent",
custom_records: mapTLVRecords(
custom_records: this.tlvToCustomRecords(
transaction.metadata?.["tlv_records"] as TLVRecord[] | undefined
),
})
Expand All @@ -112,22 +117,17 @@ class NWCConnector implements Connector {

async makeInvoice(args: MakeInvoiceArgs): Promise<MakeInvoiceResponse> {
const invoice = await this.nwc.makeInvoice({
amount: args.amount,
defaultMemo: args.memo,
amount:
typeof args.amount === "number"
? args.amount * 1000
: parseInt(args.amount) * 1000 || 0,
description: 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,
rHash: paymentHash,
paymentRequest: invoice.invoice,
rHash: invoice.payment_hash,
},
};
}
Expand All @@ -141,26 +141,29 @@ class NWCConnector implements Connector {
throw new Error("Could not find payment hash in invoice");
}

const response = await this.nwc.sendPayment(args.paymentRequest);
const response = await this.nwc.payInvoice({
invoice: args.paymentRequest,
});

return {
data: {
preimage: response.preimage,
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_amt: Math.floor(parseInt(invoice.millisatoshis || "0") / 1000),
// TODO: How to get fees?
total_fees: 0,
},
},
};
}

async keysend(args: KeysendArgs): Promise<SendPaymentResponse> {
const data = await this.nwc.keysend({
destination: args.pubkey,
amount: args.amount,
customRecords: args.customRecords,
const data = await this.nwc.payKeysend({
pubkey: args.pubkey,
amount: args.amount * 1000,
tlv_records: this.customRecordsToTlv(args.customRecords),
});

const paymentHash = SHA256(data.preimage).toString(Hex);
Expand All @@ -172,7 +175,7 @@ class NWCConnector implements Connector {

route: {
total_amt: args.amount,
// TODO: How to get fees from WebLN?
// TODO: How to get fees?
total_fees: 0,
},
},
Expand All @@ -182,12 +185,12 @@ class NWCConnector implements Connector {
async checkPayment(args: CheckPaymentArgs): Promise<CheckPaymentResponse> {
try {
const response = await this.nwc.lookupInvoice({
paymentHash: args.paymentHash,
payment_hash: args.paymentHash,
});

return {
data: {
paid: response.paid,
paid: !!response.settled_at,
preimage: response.preimage,
},
};
Expand All @@ -202,7 +205,7 @@ class NWCConnector implements Connector {
}

async signMessage(args: SignMessageArgs): Promise<SignMessageResponse> {
const response = await this.nwc.signMessage(args.message);
const response = await this.nwc.signMessage({ message: args.message });

return Promise.resolve({
data: {
Expand All @@ -215,21 +218,32 @@ class NWCConnector implements Connector {
connectPeer(args: ConnectPeerArgs): Promise<ConnectPeerResponse> {
throw new Error("Method not implemented.");
}
}

function mapTLVRecords(
tlvRecords: TLVRecord[] | undefined
): ConnectorTransaction["custom_records"] | undefined {
if (!tlvRecords) {
return undefined;
private customRecordsToTlv(
customRecords: Record<string, string>
): TlvRecord[] {
return Object.entries(customRecords).map(([key, value]) => ({
type: parseInt(key),
value: UTF8.parse(value).toString(Hex),
}));
}
const customRecords: ConnectorTransaction["custom_records"] = {};
for (const tlv of tlvRecords) {
// TODO: ConnectorTransaction["custom_records"] should not be in base64 format
// as this requires unnecessary re-encoding
customRecords[tlv.type.toString()] = Hex.parse(tlv.value).toString(Base64);

private tlvToCustomRecords(
tlvRecords: TLVRecord[] | undefined
): ConnectorTransaction["custom_records"] | undefined {
if (!tlvRecords) {
return undefined;
}
const customRecords: ConnectorTransaction["custom_records"] = {};
for (const tlv of tlvRecords) {
// TODO: ConnectorTransaction["custom_records"] should not be in base64 format
// as this requires unnecessary re-encoding
customRecords[tlv.type.toString()] = Hex.parse(tlv.value).toString(
Base64
);
}
return customRecords;
}
return customRecords;
}

export default NWCConnector;

0 comments on commit b43119d

Please sign in to comment.