-
Notifications
You must be signed in to change notification settings - Fork 40
chore: add example for wrapped invoices #529
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,80 @@ | ||
| import "websocket-polyfill"; // required in node.js | ||
|
|
||
| import * as readline from "node:readline/promises"; | ||
| import { stdin as input, stdout as output } from "node:process"; | ||
|
|
||
| import { Nip47Notification, NWCClient } from "@getalby/sdk/nwc"; | ||
| import { Invoice } from "@getalby/lightning-tools"; | ||
|
|
||
| console.warn( | ||
| "Alby Hub WARNING: This currently only works with Alby Hub LND backend or self payments between sub-wallets\n", | ||
| ); | ||
|
|
||
| const rl = readline.createInterface({ input, output }); | ||
|
|
||
| const nwcUrl = | ||
| process.env.NWC_URL || | ||
| (await rl.question("Nostr Wallet Connect URL (nostr+walletconnect://...): ")); | ||
|
|
||
| const upstreamInvoice = await rl.question("Upstream Invoice: "); | ||
|
|
||
| const paymentHash = new Invoice({ pr: upstreamInvoice.trim() }).paymentHash; | ||
| console.info("Payment hash:", paymentHash); | ||
|
|
||
| const amount = | ||
| parseInt( | ||
| (await rl.question("Extra amount in sats (default 1 sat): ")) || "1", | ||
| ) * 1000; | ||
|
|
||
| rl.close(); | ||
|
|
||
| const client = new NWCClient({ | ||
| nostrWalletConnectUrl: nwcUrl, | ||
| }); | ||
|
|
||
| const response = await client.makeHoldInvoice({ | ||
| amount, // in millisats | ||
| description: "NWC HODL invoice example", | ||
| payment_hash: paymentHash, | ||
| // or set a 256-bit description hash: | ||
| //description_hash: "a40f2b27a4414044995b26b73eb5aa66688b5f18d6a8a2513827d9a116ad95f1", | ||
| }); | ||
|
|
||
| console.info(response.invoice); | ||
|
|
||
| const onNotification = async (notification: Nip47Notification) => { | ||
| if (notification.notification.payment_hash !== paymentHash) { | ||
| console.info("Skipping unrelated notification", notification); | ||
| return; | ||
| } | ||
| console.info( | ||
| "HOLD invoice accepted! It can be settled or canceled before block " + | ||
| notification.notification.settle_deadline, | ||
| ); | ||
|
|
||
| console.info("Paying upstream invoice", upstreamInvoice); | ||
|
|
||
| const { preimage } = await client.payInvoice({ | ||
| invoice: upstreamInvoice, | ||
| }); | ||
|
|
||
| console.info("Paid upstream invoice", preimage); | ||
|
|
||
| await client.settleHoldInvoice({ preimage }); | ||
|
|
||
| process.exit(); | ||
|
Comment on lines
+57
to
+65
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing error handling: upstream payment failure leaves hold invoice in limbo. If Proposed fix- const { preimage } = await client.payInvoice({
- invoice: upstreamInvoice,
- });
-
- console.info("Paid upstream invoice", preimage);
-
- await client.settleHoldInvoice({ preimage });
+ try {
+ const { preimage } = await client.payInvoice({
+ invoice: upstreamInvoice,
+ });
+
+ console.info("Paid upstream invoice", preimage);
+
+ await client.settleHoldInvoice({ preimage });
+ } catch (e) {
+ console.error("Failed to pay upstream invoice, canceling hold invoice", e);
+ await client.cancelHoldInvoice({ payment_hash: paymentHash });
+ }🤖 Prompt for AI Agents |
||
| }; | ||
|
|
||
| const unsub = await client.subscribeNotifications(onNotification, [ | ||
| "hold_invoice_accepted", | ||
| ]); | ||
|
|
||
| console.info("Waiting for payment to be made..."); | ||
| process.on("SIGINT", function () { | ||
| console.info("Caught interrupt signal"); | ||
|
|
||
| unsub(); | ||
| client.close(); | ||
|
|
||
| process.exit(); | ||
| }); | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
# First, let's examine the actual file to see the full context head -80 examples/nwc/client/wrapped-invoice.tsRepository: getAlby/js-sdk
Length of output: 2268
🏁 Script executed:
Repository: getAlby/js-sdk
Length of output: 948
🏁 Script executed:
Repository: getAlby/js-sdk
Length of output: 3766
🏁 Script executed:
Repository: getAlby/js-sdk
Length of output: 93
🏁 Script executed:
Repository: getAlby/js-sdk
Length of output: 2243
🏁 Script executed:
Repository: getAlby/js-sdk
Length of output: 40
🏁 Script executed:
Repository: getAlby/js-sdk
Length of output: 384
🏁 Script executed:
# Look at hold-invoice.ts to compare the pattern cat examples/nwc/client/hold-invoice.tsRepository: getAlby/js-sdk
Length of output: 2447
🏁 Script executed:
Repository: getAlby/js-sdk
Length of output: 1654
🏁 Script executed:
Repository: getAlby/js-sdk
Length of output: 40
🏁 Script executed:
Repository: getAlby/js-sdk
Length of output: 40
🏁 Script executed:
Repository: getAlby/js-sdk
Length of output: 3180
🏁 Script executed:
Repository: getAlby/js-sdk
Length of output: 4501
🏁 Script executed:
Repository: getAlby/js-sdk
Length of output: 40
🏁 Script executed:
Repository: getAlby/js-sdk
Length of output: 602
🌐 Web query:
@getalby/lightning-tools Invoice class satoshi amount property documentation💡 Result:
In
@getalby/lightning-tools, theInvoiceclass exposes the invoice amount as asatoshi: numberproperty (there isn’t anamountfield on the class). It’s set when the constructor decodes the BOLT11prand assignsthis.satoshi = decodedInvoice.satoshi. (raw.githubusercontent.com)Usage-wise, the README shows both:
{ satoshi: 1000 }, and{ paymentHash, satoshi, description, createdDate, expiryDate }from theInvoiceinstance. (github.com)Citations:
🏁 Script executed:
Repository: getAlby/js-sdk
Length of output: 2466
🏁 Script executed:
Repository: getAlby/js-sdk
Length of output: 2575
🏁 Script executed:
Repository: getAlby/js-sdk
Length of output: 42
🏁 Script executed:
Repository: getAlby/js-sdk
Length of output: 40
Hold invoice amount must include the upstream invoice amount plus the extra fee.
The
amountvariable (lines 24-27) is calculated only from user input for the extra fee and passed directly tomakeHoldInvoice(line 35). For a wrapped invoice to function correctly, the hold invoice must be created forupstream_amount + extra_amountso that paying it provides sufficient funds to cover the upstream payment. Currently, if the upstream invoice is 10,000 sats and the extra is 1 sat (default), the hold invoice will only be 1 sat—insufficient to pay upstream.Extract the upstream amount and include it in the calculation:
Proposed fix
Also applies to: lines 35-41
🤖 Prompt for AI Agents