diff --git a/src/utils/lnurl.test.ts b/src/utils/lnurl.test.ts new file mode 100644 index 00000000..a99f2eec --- /dev/null +++ b/src/utils/lnurl.test.ts @@ -0,0 +1,14 @@ +import { assertEquals } from '@/deps-test.ts'; + +import { lnurlDecode, lnurlEncode } from './lnurl.ts'; + +const lnurl = 'lnurl1dp68gurn8ghj7um5v93kketj9ehx2amn9uh8wetvdskkkmn0wahz7mrww4excup0dajx2mrv92x9xp'; +const url = 'https://stacker.news/.well-known/lnurlp/odell'; + +Deno.test('lnurlEncode', () => { + assertEquals(lnurlEncode(url), lnurl); +}); + +Deno.test('lnurlDecode', () => { + assertEquals(lnurlDecode(lnurl), url); +}); diff --git a/src/utils/lnurl.ts b/src/utils/lnurl.ts new file mode 100644 index 00000000..6d8e7258 --- /dev/null +++ b/src/utils/lnurl.ts @@ -0,0 +1,18 @@ +import { bech32 } from '@/deps.ts'; + +/** Encode a URL to LNURL format. */ +function lnurlEncode(url: string): `lnurl1${string}` { + const data = new TextEncoder().encode(url); + const words = bech32.toWords(data); + return bech32.encode('lnurl', words); +} + +/** Decode a LNURL into a URL. */ +function lnurlDecode(lnurl: string): string { + const { prefix, words } = bech32.decode(lnurl); + if (prefix !== 'lnurl') throw new Error('Invalid LNURL'); + const data = new Uint8Array(bech32.fromWords(words)); + return new TextDecoder().decode(data); +} + +export { lnurlDecode, lnurlEncode };