Skip to content

Commit 286f513

Browse files
authored
Merge pull request #164 from getAlby/task-nwc-transactions
feat: add NWC listTransactions method
2 parents 50c16ae + 5852711 commit 286f513

File tree

6 files changed

+130
-18
lines changed

6 files changed

+130
-18
lines changed

.vscode/settings.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{
22
"editor.formatOnSave": true,
3-
"editor.defaultFormatter": "esbenp.prettier-vscode"
3+
"editor.defaultFormatter": "esbenp.prettier-vscode",
4+
"prettier.trailingComma": "all"
45
}

examples/nwc/list-transactions.js

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import * as crypto from "node:crypto"; // required in node.js
2+
global.crypto = crypto; // required in node.js
3+
import "websocket-polyfill"; // required in node.js
4+
5+
import * as readline from "node:readline/promises";
6+
import { stdin as input, stdout as output } from "node:process";
7+
8+
import { webln as providers } from "../../dist/index.module.js";
9+
10+
const rl = readline.createInterface({ input, output });
11+
12+
const nwcUrl =
13+
process.env.NWC_URL ||
14+
(await rl.question("Nostr Wallet Connect URL (nostr+walletconnect://...): "));
15+
rl.close();
16+
17+
const webln = new providers.NostrWebLNProvider({
18+
nostrWalletConnectUrl: nwcUrl,
19+
});
20+
await webln.enable();
21+
22+
const ONE_WEEK_IN_SECONDS = 60 * 60 * 24 * 7;
23+
const response = await webln.listTransactions({
24+
from: Math.floor(new Date().getTime() / 1000 - ONE_WEEK_IN_SECONDS),
25+
until: Math.ceil(new Date().getTime() / 1000),
26+
limit: 30,
27+
// type: "incoming",
28+
});
29+
30+
console.info(
31+
response.transactions.length + "transactions, ",
32+
response.transactions.filter((t) => t.type === "incoming").length +
33+
" incoming",
34+
response,
35+
);
36+
37+
webln.close();

examples/nwc/lookup-invoice.js

+11-6
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@ import { webln as providers } from "../../dist/index.module.js";
99

1010
const rl = readline.createInterface({ input, output });
1111

12-
const nwcUrl = await rl.question(
13-
"Nostr Wallet Connect URL (nostr+walletconnect://...): ",
14-
);
12+
const nwcUrl =
13+
process.env.NWC_URL ||
14+
(await rl.question("Nostr Wallet Connect URL (nostr+walletconnect://...): "));
15+
16+
const invoiceOrPaymentHash = await rl.question("Invoice or payment hash: ");
1517
rl.close();
1618

1719
const webln = new providers.NostrWebLNProvider({
@@ -20,9 +22,12 @@ const webln = new providers.NostrWebLNProvider({
2022
await webln.enable();
2123
const response = await webln.lookupInvoice({
2224
// provide one of the below
23-
//invoice: 'lnbc10n1pjwxschpp5hg0pw234n9ww9q4uy25pnvu8y4jzpznysasyf7m9fka36t7fahysdqufet5xgzhv43ycn3qv4uxzmtsd3jscqzzsxqyz5vqsp5uw023qhxuxqfj69rvj9yns5gufczad5gqw4uer5cgqhw90slkavs9qyyssqvv2tw6c30ssgtpejc3zk7ns0svuj8547d8wxj0e36hltljx5a8x4qj59mk2y7qlt6qazf2j38fzc8uag3887nslxz6fe3vnyvg0f2xqqnlvcu2',
24-
payment_hash:
25-
"ba1e172a35995ce282bc22a819b3872564208a64876044fb654dbb1d2fc9edc9",
25+
invoice: invoiceOrPaymentHash.startsWith("ln")
26+
? invoiceOrPaymentHash
27+
: undefined,
28+
payment_hash: !invoiceOrPaymentHash.startsWith("ln")
29+
? invoiceOrPaymentHash
30+
: undefined,
2631
});
2732

2833
console.info(response);

examples/nwc/make-invoice.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ import { webln as providers } from "../../dist/index.module.js";
99

1010
const rl = readline.createInterface({ input, output });
1111

12-
const nwcUrl = await rl.question(
13-
"Nostr Wallet Connect URL (nostr+walletconnect://...): ",
14-
);
12+
const nwcUrl =
13+
process.env.NWC_URL ||
14+
(await rl.question("Nostr Wallet Connect URL (nostr+walletconnect://...): "));
1515
rl.close();
1616

1717
const webln = new providers.NostrWebLNProvider({

prettierrc.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
"trailingComma": "es5"
2+
"trailingComma": "all"
33
}

src/webln/NostrWeblnProvider.ts

+76-7
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,37 @@ const NWCs: Record<string, NostrWebLNOptions> = {
3636
},
3737
};
3838

39+
// TODO: move to webln-types package
40+
export interface ListTransactionsArgs {
41+
from?: number;
42+
until?: number;
43+
limit?: number;
44+
offset?: number;
45+
unpaid?: boolean;
46+
type?: "incoming" | "outgoing";
47+
}
48+
49+
// TODO: move to webln-types package
50+
export interface Transaction {
51+
type: string;
52+
invoice: string;
53+
description: string;
54+
description_hash: string;
55+
preimage: string;
56+
payment_hash: string;
57+
amount: number;
58+
fees_paid: number;
59+
settled_at: number;
60+
created_at: number;
61+
expires_at: number;
62+
metadata?: Record<string, unknown>;
63+
}
64+
65+
// TODO: move to webln-types package
66+
export interface ListTransactionsResponse {
67+
transactions: Transaction[];
68+
}
69+
3970
interface NostrWebLNOptions {
4071
authorizationUrl?: string; // the URL to the NWC interface for the user to confirm the session
4172
relayUrl: string;
@@ -58,6 +89,11 @@ type Nip47GetInfoResponse = {
5889
methods: string[];
5990
};
6091

92+
type Nip47ListTransactionsResponse = {
93+
transactions: Nip47Transaction[];
94+
};
95+
type Nip47Transaction = Transaction;
96+
6197
type Nip47PayResponse = {
6298
preimage: string;
6399
};
@@ -69,6 +105,7 @@ const nip47ToWeblnRequestMap = {
69105
pay_invoice: "sendPayment",
70106
pay_keysend: "payKeysend",
71107
lookup_invoice: "lookupInvoice",
108+
list_transactions: "listTransactions",
72109
};
73110

74111
export class NostrWebLNProvider implements WebLNProvider, Nip07Provider {
@@ -336,7 +373,7 @@ export class NostrWebLNProvider implements WebLNProvider, Nip07Provider {
336373
throw new Error("No amount specified");
337374
}
338375

339-
return this.executeNip47Request<MakeInvoiceResponse, { invoice: string }>(
376+
return this.executeNip47Request<MakeInvoiceResponse, Nip47Transaction>(
340377
"make_invoice",
341378
{
342379
amount: amount * 1000, // NIP-47 uses msat
@@ -353,14 +390,33 @@ export class NostrWebLNProvider implements WebLNProvider, Nip07Provider {
353390
lookupInvoice(args: LookupInvoiceArgs) {
354391
this.checkConnected();
355392

393+
return this.executeNip47Request<LookupInvoiceResponse, Nip47Transaction>(
394+
"lookup_invoice",
395+
args,
396+
(result) => !!result.invoice,
397+
(result) => ({
398+
paymentRequest: result.invoice,
399+
paid: !!result.settled_at,
400+
}),
401+
);
402+
}
403+
404+
listTransactions(args: ListTransactionsArgs) {
405+
this.checkConnected();
406+
407+
// maybe we can tailor the response to our needs
356408
return this.executeNip47Request<
357-
LookupInvoiceResponse,
358-
{ invoice: string; paid: boolean }
409+
ListTransactionsResponse,
410+
Nip47ListTransactionsResponse
359411
>(
360-
"lookup_invoice",
412+
"list_transactions",
361413
args,
362-
(result) => result.invoice !== undefined && result.paid !== undefined,
363-
(result) => ({ paymentRequest: result.invoice, paid: result.paid }),
414+
(response) => !!response.transactions,
415+
(response) => ({
416+
transactions: response.transactions.map(
417+
mapNip47TransactionToTransaction,
418+
),
419+
}),
364420
);
365421
}
366422

@@ -532,7 +588,7 @@ export class NostrWebLNProvider implements WebLNProvider, Nip07Provider {
532588
}
533589
// @ts-ignore // event is still unknown in nostr-tools
534590
if (event.kind == 23195 && response.result) {
535-
//console.log("NIP-47 result", response.result);
591+
// console.info("NIP-47 result", response.result);
536592
if (resultValidator(response.result)) {
537593
resolve(resultMapper(response.result));
538594
this.notify(weblnMethod, response.result);
@@ -572,4 +628,17 @@ export class NostrWebLNProvider implements WebLNProvider, Nip07Provider {
572628
}
573629
}
574630

631+
function mapNip47TransactionToTransaction(
632+
transaction: Nip47Transaction,
633+
): Transaction {
634+
return {
635+
...transaction,
636+
// NWC uses msats - convert to sats for webln
637+
amount: Math.floor(transaction.amount / 1000),
638+
fees_paid: transaction.fees_paid
639+
? Math.floor(transaction.fees_paid / 1000)
640+
: 0,
641+
};
642+
}
643+
575644
export const NWC = NostrWebLNProvider;

0 commit comments

Comments
 (0)