Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: use new nwc client from sdk #2987

Merged
merged 8 commits into from
Jul 15, 2024
83 changes: 50 additions & 33 deletions src/extension/background-script/connectors/nwc.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
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";
Expand Down Expand Up @@ -35,9 +34,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 +58,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 +74,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,7 +100,7 @@ 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(
transaction.metadata?.["tlv_records"] as TLVRecord[] | undefined
Expand All @@ -112,22 +116,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,39 +140,48 @@ 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,
});

const transaction = await this.nwc.lookupInvoice({
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_fees: 0,
total_amt: Math.floor(parseInt(invoice.millisatoshis || "0") / 1000),
total_fees: Math.floor(transaction.fees_paid / 1000),
},
},
};
}

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,
im-adithya marked this conversation as resolved.
Show resolved Hide resolved
tlv_records: this.convertCustomRecords(args.customRecords),
});

const paymentHash = SHA256(data.preimage).toString(Hex);

const transaction = await this.nwc.lookupInvoice({
payment_hash: paymentHash,
});

return {
data: {
preimage: data.preimage,
paymentHash,

route: {
total_amt: args.amount,
// TODO: How to get fees from WebLN?
total_fees: 0,
total_fees: Math.floor(transaction.fees_paid / 1000),
},
},
};
Expand All @@ -182,12 +190,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 +210,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,6 +223,15 @@ class NWCConnector implements Connector {
connectPeer(args: ConnectPeerArgs): Promise<ConnectPeerResponse> {
throw new Error("Method not implemented.");
}

private convertCustomRecords(
customRecords: Record<string, string>
im-adithya marked this conversation as resolved.
Show resolved Hide resolved
): TlvRecord[] {
return Object.entries(customRecords).map(([key, value]) => ({
type: parseInt(key),
value: Hex.parse(value).toString(Base64),
}));
im-adithya marked this conversation as resolved.
Show resolved Hide resolved
}
}

function mapTLVRecords(
Expand Down
Loading