From 9dbc1ff66d9aba6b62cc3a113440593d5992e22b Mon Sep 17 00:00:00 2001 From: Egge Date: Wed, 17 Jan 2024 11:27:31 +0100 Subject: [PATCH] added decodeInvoice util --- src/model/types/index.ts | 10 ++++++++++ src/utils.ts | 29 ++++++++++++++++++++++++++++- test/utils.test.ts | 16 ++++++++++++++++ 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/src/model/types/index.ts b/src/model/types/index.ts index 1fd13cdcb..3b6422271 100644 --- a/src/model/types/index.ts +++ b/src/model/types/index.ts @@ -341,3 +341,13 @@ export type AmountPreference = { amount: number; count: number; }; + +export type InvoiceData = { + paymentRequest: string; + amountInSats: number; + amountInMSats: number; + timestamp: number; + paymentHash: string; + memo: string; + expiry: number; +}; diff --git a/src/utils.ts b/src/utils.ts index 541a94f64..b25bde53d 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,6 +1,8 @@ +import { decode } from '@gandlaf21/bolt11-decode'; import { encodeBase64ToJson, encodeJsonToBase64 } from './base64.js'; import { AmountPreference, + InvoiceData, MintKeys, Proof, Token, @@ -184,10 +186,35 @@ export function checkResponse(data: { error?: string; detail?: string }) { } } -export function joinUrls(...parts: string[]): string { +export function joinUrls(...parts: Array): string { return parts.map((part) => part.replace(/(^\/+|\/+$)/g, '')).join('/'); } +export function decodeInvoice(bolt11Invoice: string): InvoiceData { + const invoiceData: InvoiceData = {} as InvoiceData; + const decodeResult = decode(bolt11Invoice); + for (let i = 0; i < decodeResult.sections.length; i++) { + const decodedSection = decodeResult.sections[i]; + if (decodedSection.name === 'amount') { + invoiceData.amountInSats = Number(decodedSection.value) / 1000; + invoiceData.amountInMSats = Number(decodedSection.value); + } + if (decodedSection.name === 'timestamp') { + invoiceData.timestamp = decodedSection.value; + } + if (decodedSection.name === 'description') { + invoiceData.memo = decodedSection.value; + } + if (decodedSection.name === 'expiry') { + invoiceData.expiry = decodedSection.value; + } + if (decodedSection.name === 'payment_hash') { + invoiceData.paymentHash = decodedSection.value.toString('hex'); + } + } + return invoiceData; +} + export { bigIntStringify, bytesToNumber, diff --git a/test/utils.test.ts b/test/utils.test.ts index 3795a91a0..ba8948e82 100644 --- a/test/utils.test.ts +++ b/test/utils.test.ts @@ -298,3 +298,19 @@ describe('test cleanToken', () => { expect(mint_info_url).toBe('https://8333.space:3338/info'); }); }); + +describe('test decodeInvoice', () => { + test('decoding a lightning invoice', async () => { + const invoice = + 'lnbc15u1p3xnhl2pp5jptserfk3zk4qy42tlucycrfwxhydvlemu9pqr93tuzlv9cc7g3sdqsvfhkcap3xyhx7un8cqzpgxqzjcsp5f8c52y2stc300gl6s4xswtjpc37hrnnr3c9wvtgjfuvqmpm35evq9qyyssqy4lgd8tj637qcjp05rdpxxykjenthxftej7a2zzmwrmrl70fyj9hvj0rewhzj7jfyuwkwcg9g2jpwtk3wkjtwnkdks84hsnu8xps5vsq4gj5hs'; + const invoiceData = utils.decodeInvoice(invoice); + expect(invoiceData.timestamp).toStrictEqual(1651105770); + expect(invoiceData.amountInMSats).toStrictEqual(1500000); + expect(invoiceData.amountInSats).toStrictEqual(1500); + expect(invoiceData.paymentHash).toStrictEqual( + '90570c8d3688ad5012aa5ff982606971ae46b3f9df0a100cb15f05f61718f223' + ); + expect(invoiceData.expiry).toStrictEqual(600); + expect(invoiceData.memo).toStrictEqual('bolt11.org'); + }); +});