{"id":13666747,"url":"https://github.com/chill117/lnurl-node","last_synced_at":"2025-12-27T02:17:03.718Z","repository":{"id":35206683,"uuid":"216046603","full_name":"chill117/lnurl-node","owner":"chill117","description":"Flexible lnurl server implementation with API and CLI implemented in nodejs.","archived":false,"fork":false,"pushed_at":"2024-08-27T14:50:20.000Z","size":921,"stargazers_count":97,"open_issues_count":9,"forks_count":24,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-10-21T01:29:03.852Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/chill117.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2019-10-18T14:49:34.000Z","updated_at":"2025-08-26T17:19:14.000Z","dependencies_parsed_at":"2024-04-18T15:40:56.994Z","dependency_job_id":"dc2f9453-01a2-453e-ae24-a9bdbc36c41f","html_url":"https://github.com/chill117/lnurl-node","commit_stats":{"total_commits":288,"total_committers":9,"mean_commits":32.0,"dds":0.02777777777777779,"last_synced_commit":"574cf561e0f15d90d8179b12db7ea30d8b490818"},"previous_names":[],"tags_count":44,"template":false,"template_full_name":null,"purl":"pkg:github/chill117/lnurl-node","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chill117%2Flnurl-node","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chill117%2Flnurl-node/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chill117%2Flnurl-node/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chill117%2Flnurl-node/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chill117","download_url":"https://codeload.github.com/chill117/lnurl-node/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chill117%2Flnurl-node/sbom","scorecard":{"id":277637,"data":{"date":"2025-08-11","repo":{"name":"github.com/chill117/lnurl-node","commit":"8e22e7158cbeee9725a4e4214ac2bf39b642556d"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.6,"checks":[{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Code-Review","score":0,"reason":"Found 1/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/tests.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Pinned-Dependencies","score":2,"reason":"dependency not pinned by hash detected -- score normalized to 2","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/tests.yml:31: update your workflow using https://app.stepsecurity.io/secureworkflow/chill117/lnurl-node/tests.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/tests.yml:33: update your workflow using https://app.stepsecurity.io/secureworkflow/chill117/lnurl-node/tests.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/tests.yml:66: update your workflow using https://app.stepsecurity.io/secureworkflow/chill117/lnurl-node/tests.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/tests.yml:68: update your workflow using https://app.stepsecurity.io/secureworkflow/chill117/lnurl-node/tests.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/tests.yml:87: update your workflow using https://app.stepsecurity.io/secureworkflow/chill117/lnurl-node/tests.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/tests.yml:89: update your workflow using https://app.stepsecurity.io/secureworkflow/chill117/lnurl-node/tests.yml/master?enable=pin","Warn: npmCommand not pinned by hash: .github/workflows/tests.yml:40","Warn: npmCommand not pinned by hash: .github/workflows/tests.yml:75","Warn: npmCommand not pinned by hash: .github/workflows/tests.yml:96","Info:   0 out of   6 GitHub-owned GitHubAction dependencies pinned","Info:   3 out of   6 npmCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 1 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":0,"reason":"12 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-xq7p-g2vc-g82p","Warn: Project is vulnerable to: GHSA-qwcr-r2fm-qrc7","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-pxg6-pf52-xh8x","Warn: Project is vulnerable to: GHSA-fc9h-whq2-v747","Warn: Project is vulnerable to: GHSA-vjh7-7g9h-fjfh","Warn: Project is vulnerable to: GHSA-qw6h-vgh9-j6wx","Warn: Project is vulnerable to: GHSA-9wv6-86v2-598j","Warn: Project is vulnerable to: GHSA-rhx6-c78j-4q9w","Warn: Project is vulnerable to: GHSA-584q-6j8j-r5pm","Warn: Project is vulnerable to: GHSA-m6fv-jmcg-4jfg","Warn: Project is vulnerable to: GHSA-cm22-4g7w-348p"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-17T14:56:20.460Z","repository_id":35206683,"created_at":"2025-08-17T14:56:20.460Z","updated_at":"2025-08-17T14:56:20.460Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28069278,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-12-27T02:00:05.897Z","response_time":58,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-02T06:01:24.531Z","updated_at":"2025-12-27T02:17:03.683Z","avatar_url":"https://github.com/chill117.png","language":"JavaScript","funding_links":[],"categories":["Uncategorized"],"sub_categories":["Uncategorized"],"readme":"# lnurl-node\n\n![Build Status](https://github.com/chill117/lnurl-node/actions/workflows/tests.yml/badge.svg)\n\nNode.js implementation of [lnurl](https://github.com/fiatjaf/lnurl-rfc). The purpose of this project is to provide an easy and flexible lnurl server that you can run as a stand-alone process (via CLI) or integrated with your own custom node.js application (via API).\n\nOptionally, your lnurl server can authorize other applications (offline or otherwise). Possible use-cases include offline Lightning Network ATMs (e.g. [Bleskomat](https://www.bleskomat.com/)), static QR codes for receiving donations, authentication mechanism for web sites or web services (login / registration / 2FA).\n\nThis project attempts to maintain backwards compatibility for any features, methods, options, hooks, and events which are documented here.\n\n\n* [Specification Support](#specification-support)\n* [Installation](#installation)\n* [Command-line interface](#command-line-interface)\n  * [help](#cli-help)\n  * [encode](#cli-encode)\n  * [decode](#cli-decode)\n  * [server](#cli-server)\n  * [generateNewUrl](#cli-generatenewurl)\n* [API](#api)\n  * [encode](#encode)\n  * [decode](#decode)\n  * [createServer](#createserver)\n    * [options](#createserver-options)\n  * [generateNewUrl](#generatenewurl)\n* [Tags and Parameters](#tags-and-parameters)\n* [Hooks](#hooks)\n\t* [error](#hook-error)\n\t* [status](#hook-status)\n\t* [url:process](#hook-urlprocess)\n\t* [login](#hook-login)\n\t* [channelRequest:validate](#hook-channelrequestvalidate)\n\t* [channelRequest:info](#hook-channelrequestinfo)\n\t* [channelRequest:action](#hook-channelrequestaction)\n\t* [payRequest:validate](#hook-payrequestvalidate)\n\t* [payRequest:info](#hook-payrequestinfo)\n\t* [payRequest:action](#hook-payrequestaction)\n\t* [withdrawRequest:validate](#hook-withdrawrequestvalidate)\n\t* [withdrawRequest:info](#hook-withdrawrequestinfo)\n\t* [withdrawRequest:action](#hook-withdrawrequestaction)\n* [Events](#events)\n\t* [login](#event-login)\n\t* [channelRequest:action:processed](#event-channelrequestactionprocessed)\n\t* [channelRequest:action:failed](#event-channelrequestactionfailed)\n\t* [payRequest:action:processed](#event-payrequestactionprocessed)\n\t* [payRequest:action:failed](#event-payrequestactionfailed)\n\t* [withdrawRequest:action:processed](#event-withdrawrequestactionprocessed)\n\t* [withdrawRequest:action:failed](#event-withdrawrequestactionfailed)\n* [Supported Lightning Network Backends](#supported-lightning-network-backends)\n* [Configuring Data Store](#configuring-data-store)\n* [Debugging](#debugging)\n* [Tests](#tests)\n* [Changelog](#changelog)\n* [License](#license)\n\n\n## Specification Support\n\nThe LNURL specification is divided into separate documents called \"LUDs\". These documents can be found in the [lnurl-rfc repository](https://github.com/fiatjaf/lnurl-rfc).\n\nThe following is a list of LUDs which this module already (or plans to) support:\n* [x] [LUD-01](https://github.com/fiatjaf/lnurl-rfc/blob/luds/01.md) - encode/decode\n* [x] [LUD-02](https://github.com/fiatjaf/lnurl-rfc/blob/luds/02.md) - channelRequest\n* [x] [LUD-03](https://github.com/fiatjaf/lnurl-rfc/blob/luds/03.md) - withdrawRequest\n* [x] [LUD-04](https://github.com/fiatjaf/lnurl-rfc/blob/luds/04.md) - auth\n* [x] [LUD-06](https://github.com/fiatjaf/lnurl-rfc/blob/luds/06.md) - payRequest\n* [ ] [LUD-08](https://github.com/fiatjaf/lnurl-rfc/blob/luds/08.md) - Fast withdrawRequest\n* [x] [LUD-09](https://github.com/fiatjaf/lnurl-rfc/blob/luds/09.md) - successAction in payRequest\n* [ ] [LUD-10](https://github.com/fiatjaf/lnurl-rfc/blob/luds/10.md) - aes successAction in payRequest\n* [x] [LUD-12](https://github.com/fiatjaf/lnurl-rfc/blob/luds/12.md) - Comments in payRequest\n* [ ] [LUD-16](https://github.com/fiatjaf/lnurl-rfc/blob/luds/16.md) - Lightning Address\n* [ ] [LUD-17](https://github.com/fiatjaf/lnurl-rfc/blob/luds/17.md) - New URI schema prefixes\n\n\n## Installation\n\nIf you wish to use this module as a [CLI tool](#command-line-interface), install it globally via npm:\n```\nnpm install -g lnurl\n```\n\nAdd to your application via `npm`:\n```\nnpm install lnurl --save\n```\nThis will install `lnurl` and add it to your application's `package.json` file.\n\n\n\n## Command-line interface\n\nThis section assumes that you have `lnurl` installed globally and that it is available on your current user's PATH.\n\n### CLI: help\n\nTo view the help menu:\n```bash\nlnurl --help\n```\n\n### CLI: encode\n\nEncode a URL:\n```bash\nlnurl encode \"https://service.com/api?q=3fc3645b439ce8e7f2553a69e5267081d96dcd340693afabe04be7b0ccd178df\"\n```\nExpected output:\n```\nlnurl1dp68gurn8ghj7um9wfmxjcm99e3k7mf0v9cxj0m385ekvcenxc6r2c35xvukxefcv5mkvv34x5ekzd3ev56nyd3hxqurzepexejxxepnxscrvwfnv9nxzcn9xq6xyefhvgcxxcmyxymnserxfq5fns\n```\nThis command also accepts piped input. For example:\n```bash\necho -n \"https://service.com/api?q=3fc3645b439ce8e7f2553a69e5267081d96dcd340693afabe04be7b0ccd178df\" \\\n\t| lnurl encode\n```\n\n\n### CLI: decode\n\nDecode an lnurl:\n```bash\nlnurl decode \"lnurl1dp68gurn8ghj7um9wfmxjcm99e3k7mf0v9cxj0m385ekvcenxc6r2c35xvukxefcv5mkvv34x5ekzd3ev56nyd3hxqurzepexejxxepnxscrvwfnv9nxzcn9xq6xyefhvgcxxcmyxymnserxfq5fns\"\n```\nExpected output:\n```\nhttps://service.com/api?q=3fc3645b439ce8e7f2553a69e5267081d96dcd340693afabe04be7b0ccd178df\n```\nThis command also accepts piped input. For example:\n```bash\necho -n \"lnurl1dp68gurn8ghj7um9wfmxjcm99e3k7mf0v9cxj0m385ekvcenxc6r2c35xvukxefcv5mkvv34x5ekzd3ev56nyd3hxqurzepexejxxepnxscrvwfnv9nxzcn9xq6xyefhvgcxxcmyxymnserxfq5fns\" \\\n\t| lnurl decode\n```\n\n\n### CLI: generateNewUrl\n\nTo generate a new lnurl that a client application can then use:\n```bash\nlnurl generateNewUrl \\\n\t--host \"localhost\" \\\n\t--port \"3000\" \\\n\t--endpoint \"/lnurl\" \\\n\t--store.backend \"knex\" \\\n\t--store.config '{\"client\":\"postgres\",\"connection\":{\"host\":\"127.0.0.1\",\"user\":\"postgres\",\"password\":\"example\",\"database\":\"lnurl_example\"}}' \\\n\t--tag \"withdrawRequest\" \\\n\t--params '{\"minWithdrawable\":10000,\"maxWithdrawable\":10000,\"defaultDescription\":\"\"}'\n```\nSee [Tags and Parameters](#tags-and-parameters) for a full list of possible tags and params.\n\nAlternatively, a configuration file can be used:\n```bash\nlnurl generateNewUrl \\\n\t--configFile ./config.json \\\n\t--tag \"withdrawRequest\" \\\n\t--params '{\"minWithdrawable\":10000,\"maxWithdrawable\":10000,\"defaultDescription\":\"\"}'\n```\nExample output:\n```json\n{\n\t\"encoded\": \"lnurl1dp68gup69uhkcmmrv9kxsmmnwsarxvpsxqhkcmn4wfkr7ufavvexxvpk893rswpjxcmnvctyvgexzen9xvmkycnxv33rvdtrvy6xzv3ex43xzve5vvexgwfj8yenxvm9xaskzdmpxuexywt9893nqvcly0lgs\",\n\t\"secret\": \"c2c069b882676adb2afe37bbfdb65ca4a295ba34c2d929333e7aa7a72b9e9c03\",\n\t\"url\": \"http://localhost:3000/lnurl?q=c2c069b882676adb2afe37bbfdb65ca4a295ba34c2d929333e7aa7a72b9e9c03\"\n}\n```\nIt is possible to set the number of uses allowed for the new URL:\n```bash\nlnurl generateNewUrl \\\n\t--configFile ./config.json \\\n\t--tag \"withdrawRequest\" \\\n\t--params '{\"minWithdrawable\":10000,\"maxWithdrawable\":10000,\"defaultDescription\":\"\"}' \\\n\t--uses 3\n```\nSet `--uses` equal to `0` to allow the URL to be used an unlimited number of times.\n\nFor a list of available options:\n```bash\nlnurl generateNewUrl --help\n```\n\nIt is also possible to generate lnurls in other ways:\n* [generateNewUrl](#generateNewUrl) - API method\n\n\n### CLI: server\n\nStart an lnurl application server with the following command:\n```bash\nlnurl server \\\n\t--host \"localhost\" \\\n\t--port \"3000\" \\\n\t--lightning.backend \"dummy\" \\\n\t--lightning.config '{}'\n```\n* The example above uses the \"dummy\" LN backend. For details about how to connect to a real LN backend, see [Supported Lightning Network Backends](#supported-lightning-network-backends)\n* By default the lnurl server stores data in memory - which is fine for development and testing. But once you plan to run it in production, it is recommended that you use a proper data store - see [Configuring Data Store](#configuring-data-store).\n* To enable debugging messages, see the [Debugging](#debugging) section of this readme.\n\nAlternatively, a configuration file can be used:\n```bash\nlnurl server --configFile ./config.json\n```\n\nTo print all available options for the server command:\n```bash\nlnurl server --help\n```\n\n\n## API\n\n### encode\n\n`encode(url)`\n\nEncode a url as a bech32-encoded string.\n\nUsage:\n```js\nconst lnurl = require('lnurl');\nconst encoded = lnurl.encode('https://service.com/api?q=3fc3645b439ce8e7f2553a69e5267081d96dcd340693afabe04be7b0ccd178df');\nconsole.log(encoded);\n```\n\nExpected output:\n```json\n\"lnurl1dp68gurn8ghj7um9wfmxjcm99e3k7mf0v9cxj0m385ekvcenxc6r2c35xvukxefcv5mkvv34x5ekzd3ev56nyd3hxqurzepexejxxepnxscrvwfnv9nxzcn9xq6xyefhvgcxxcmyxymnserxfq5fns\"\n```\n\n\n### decode\n\n`decode(url)`\n\nDecode a bech32-encoded lnurl.\n\nUsage:\n```js\nconst lnurl = require('lnurl');\nconst decoded = lnurl.decode('lnurl1dp68gurn8ghj7um9wfmxjcm99e3k7mf0v9cxj0m385ekvcenxc6r2c35xvukxefcv5mkvv34x5ekzd3ev56nyd3hxqurzepexejxxepnxscrvwfnv9nxzcn9xq6xyefhvgcxxcmyxymnserxfq5fns');\nconsole.log(decoded);\n```\n\nExpected output:\n```json\n\"https://service.com/api?q=3fc3645b439ce8e7f2553a69e5267081d96dcd340693afabe04be7b0ccd178df\"\n```\n\n\n### createServer\n\n`createServer([options])`\n\nCreate and initialize an instance of the lnurl server.\n\nUsage:\n```js\nconst lnurl = require('lnurl');\nconst server = lnurl.createServer({\n\thost: 'localhost',\n\tport: 3000,\n\tauth: {\n\t\tapiKeys: [\n\t\t\t{\n\t\t\t\tid: '46f8cab814de07a8a65f',\n\t\t\t\tkey: 'ee7678f6fa5ab9cf3aa23148ef06553edd858a09639b3687113a5d5cdb5a2a67',\n\t\t\t\tencoding: 'hex',\n\t\t\t},\n\t\t],\n\t},\n\tlightning: {\n\t\tbackend: 'dummy',\n\t\tconfig: {},\n\t},\n});\n```\n* The example above uses the \"dummy\" LN backend. For details about how to connect to a real LN backend, see [Supported Lightning Network Backends](#supported-lightning-network-backends)\n* By default the lnurl server stores data in memory - which is fine for development and testing. But once you plan to run it in production, it is recommended that you use a proper data store - see [Configuring Data Store](#configuring-data-store).\n* To enable debugging messages, see the [Debugging](#debugging) section of this readme.\n\n\n#### createServer: options\n\nBelow is the full list of options that can be passed to the `createServer` method.\n\n```js\n{\n\t// The host for the web server:\n\thost: 'localhost',\n\t// The port for the web server:\n\tport: 3000,\n\t// Whether or not to start listening when the server is created:\n\tlisten: true,\n\t// Whether or not to allow CORS requests:\n\tcors: false,\n\t// The URL where the server is externally reachable (e.g \"https://your-lnurl-server.com\"):\n\turl: null,\n\t// The URI path of the web API end-point:\n\tendpoint: '/lnurl',\n\t// See list of possible LN backends here:\n\t// https://github.com/chill117/lnurl-node#supported-lightning-network-backends\n\tlightning: {\n\t\t// The name of the LN backend to use:\n\t\tbackend: 'dummy',\n\t\t// Configuration options to pass to LN backend:\n\t\tconfig: {},\n\t},\n\tstore: {\n\t\t// Name of store backend ('knex', 'memory'):\n\t\tbackend: 'memory',\n\t\t// Configuration options to pass to store:\n\t\tconfig: {},\n\t},\n\tpayRequest: {\n\t\t// A number greater than 0 indicates the maximum length of comments.\n\t\t// Setting this to 0 ignores comments.\n\t\t//\n\t\t// Note that there is a generally accepted limit (2000 characters)\n\t\t// to the length of URLs; see:\n\t\t// https://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers/417184#417184\n\t\t//\n\t\t// Since comments are sent as a query parameter to the callback URL,\n\t\t// this limit should be set to a maximum of 1000 to be safe.\n\t\tcommentAllowed: 500,\n\t\t// Default metadata to be sent in response object:\n\t\tmetadata: '[[\"text/plain\", \"lnurl-node\"]]',\n\t},\n}\n```\n* To use a custom lightning backend with your server see [Custom Lightning Network Backend](#custom-lightning-network-backend).\n\n\n### generateNewUrl\n\n`generateNewUrl(tag, params)`\n\nTo generate a new lnurl that a client application can then use:\n```js\nconst tag = 'payRequest';\nconst params = {\n\tminSendable: 10000,\n\tmaxSendable: 200000,\n\tmetadata: '[[\"text/plain\", \"lnurl-node\"]]',\n\tcommentAllowed: 500,\n};\nserver.generateNewUrl(tag, params).then(result =\u003e {\n\tconst { encoded, secret, url } = result;\n\tconsole.log({ encoded, secret, url });\n}).catch(error =\u003e {\n\tconsole.error(error);\n});\n```\nExpected output:\n```json\n{\n\t\"encoded\": \"lnurl1dp68gup69uhkcmmrv9kxsmmnwsarxvpsxqhkcmn4wfkr7ufavvexxvpk893rswpjxcmnvctyvgexzen9xvmkycnxv33rvdtrvy6xzv3ex43xzve5vvexgwfj8yenxvm9xaskzdmpxuexywt9893nqvcly0lgs\",\n\t\"secret\": \"c2c069b882676adb2afe37bbfdb65ca4a295ba34c2d929333e7aa7a72b9e9c03\",\n\t\"url\": \"http://localhost:3000/lnurl?q=c2c069b882676adb2afe37bbfdb65ca4a295ba34c2d929333e7aa7a72b9e9c03\"\n}\n```\nSee [Tags and Parameters](#tags-and-parameters) for a full list of possible tags and params.\n\nIt is possible to set the number of uses allowed for the new URL:\n```js\nconst tag = 'payRequest';\nconst params = {\n\tminSendable: 10000,\n\tmaxSendable: 200000,\n\tmetadata: '[[\"text/plain\", \"lnurl-node\"]]',\n\tcommentAllowed: 500,\n};\nconst options = {\n\tuses: 3,\n};\nserver.generateNewUrl(tag, params, options).then(result =\u003e {\n\tconst { encoded, secret, url } = result;\n\tconsole.log({ encoded, secret, url });\n}).catch(error =\u003e {\n\tconsole.error(error);\n});\n```\nSet `uses` equal to `0` to allow the URL to be used an unlimited number of times.\n\nIt is also possible to generate lnurls in other ways:\n* [CLI: generateNewUrl](#cli-generatenewurl)\n\n\n## Tags and Parameters\n\nBelow you will find all tags and their associated params.\n\n`channelRequest`:\n\n| name       | type             | notes         |\n| ---------- | ---------------- | ------------- |\n| `localAmt` | `integer` (sats) | \u003e 0           |\n| `pushAmt`  | `integer` (sats) | \u003c= `localAmt` |\n\n`login`:\n\n_none_\n\n`payRequest`:\n\n| name             | type              | notes                                                                   |\n| ---------------- | ----------------- | ----------------------------------------------------------------------- |\n| `minSendable`    | `integer` (msats) | \u003e 0                                                                     |\n| `maxSendable`    | `integer` (msats) | \u003e= `minSendable`                                                        |\n| `metadata`       | `string`          | stringified JSON                                                        |\n| `commentAllowed` | `integer`         | character limit for comments (max. 1000), set to 0 to disallow comments |\n\n`withdrawRequest`:\n\n| name                 | type              | notes                |\n| -------------------- | ----------------- | -------------------- |\n| `minWithdrawable`    | `integer` (msats) | \u003e 0                  |\n| `maxWithdrawable`    | `integer` (msats) | \u003e= `minWithdrawable` |\n| `defaultDescription` | `string`          |                      |\n\n\n## Hooks\n\nIt is possible to further customize your lnurl server by using hooks to run custom application code at key points in the server application flow.\n\n* [error](#hook-error)\n* [status](#hook-status)\n* [url:process](#hook-urlprocess)\n* [login](#hook-login)\n* [channelRequest:validate](#hook-channelrequestvalidate)\n* [channelRequest:info](#hook-channelrequestinfo)\n* [channelRequest:action](#hook-channelrequestaction)\n* [payRequest:validate](#hook-payrequestvalidate)\n* [payRequest:info](#hook-payrequestinfo)\n* [payRequest:action](#hook-payrequestaction)\n* [withdrawRequest:validate](#hook-withdrawrequestvalidate)\n* [withdrawRequest:info](#hook-withdrawrequestinfo)\n* [withdrawRequest:action](#hook-withdrawrequestaction)\n\nHow to use a hook:\n```js\nconst lnurl = require('lnurl');\nconst server = lnurl.createServer();\nconst { HttpError } = require('lnurl/lib');\n\n// The callback signature can vary depending upon the hook used:\nserver.bindToHook('HOOK', function(arg1, arg2, arg3, next) {\n\t// Fail the request by calling next with an error:\n\tnext(new Error('Your custom error message'));\n\t// Use the HttpError constructor to pass the error to the response object:\n\tnext(new HttpError('Custom error sent in the response object', 400/* status code */));\n\t// Or call next without any arguments to continue with the request:\n\tnext();\n});\n```\n\n\n### Hook: error\n\nThis hook is called when any request fails with an error.\n\nOverride the existing error with a new error:\n```js\nserver.bindToHook('error', function(error, req, res, next) {\n\t// Call next with a new error which will be passed to the default error handler:\n\tnext(new HttpError('A new error message', 400));\n});\n```\nContinue with the existing error:\n```js\nserver.bindToHook('error', function(error, req, res, next) {\n\t// Call next with no arguments to let the error pass-thru to the default error handler:\n\tnext();\n});\n```\nMake a custom response:\n```js\nserver.bindToHook('error', function(error, req, res, next) {\n\t// Use the response object to make a custom response:\n\tres.status(200).json({ message: 'custom error handling' });\n\t// Do not call next in this case.\n});\n```\n\n\n### Hook: status\n\nThis hook is called when a request is received at the web server's `/status` end-point.\n\nExample OK status response:\n```js\nserver.bindToHook('status', function(req, res, next) {\n\t// Call next() with no arguments to continue with the normal status flow.\n\tnext();\n});\n```\n\nExample failed status response:\n```js\nserver.bindToHook('status', function(req, res, next) {\n\t// Or, call next with an error to fail the request:\n\tnext(new HttpError('Service temporarily unavailable', 503));\n});\n```\n\n\n### Hook: url:process\n\nThis hook is called when a request is received at the web server's LNURL end-point.\n\nExample modifying the request object:\n```js\nserver.bindToHook('url:process', function(req, res, next) {\n\treq.query.defaultDescription = 'custom default description';\n\tnext();// Call next() with no arguments to continue the request.\n});\n```\nExample rejecting the request:\n```js\nserver.bindToHook('url:process', function(req, res, next) {\n\t// Call next() with an error to fail the request:\n\tnext(new HttpError('Failed check', 400));\n});\n```\n\n\n### Hook: login\n\n`login`\n\nThe lnurl-auth subprotocol allows users to login/authenticate with your service. You can use the login hook as shown here to execute your own custom code whenever there is a successful login/authentication attempt for your server.\n```js\nserver.bindToHook('login', function(key, next) {\n\t// This code is executed when the lnurl-auth checks have passed (e.g valid signature provided).\n\t// `key` is the public linking key which has just authenticated.\n\t// Perform asynchronous code such as database calls here.\n\t// Call next() without any arguments to continue with the request:\n\tnext();\n});\n```\n\n\n### Hook: channelRequest:validate\n\n### Hook: payRequest:validate\n\n### Hook: withdrawRequest:validate\n\n`channelRequest:validate` `payRequest:validate` `withdrawRequest:validate`\n\nThese hooks are called when validating the parameters provided when creating a new URL. For example, when calling `server.generateNewUrl(tag, params)`.\n```js\nserver.bindToHook('channelRequest:validate', function(params, next) {\n\t// Throw an error to prevent the creation of the new URL:\n\tnext(new Error('Invalid params!'));\n\t// Call next() without any arguments to continue with the creation of the new URL:\n\tnext();\n});\n```\n\n### Hook: channelRequest:info\n\n### Hook: payRequest:info\n\n### Hook: withdrawRequest:info\n\n`channelRequest:info` `payRequest:info` `withdrawRequest:info`\n\nThese hooks are called when the initial request is made to the LNURL end-point. The initial request occurs when a wallet app first scans a QR code containing an LNURL. The wallet app makes the initial request for more information about the tag and other parameters associated with the LNURL it just scanned.\n```js\nserver.bindToHook('channelRequest:info', function(secret, params, next) {\n\t// `secret` is the k1 value that when hashed gives the unique `hash`\n\t//  associated with an LNURL in the data store.\n\t// `params` are the parameters provided when the URL was created.\n\t// Throw an error to fail the request:\n\tnext(new HttpError('Custom error sent in the response object', 400/* status code */));\n\t// Call next() without any arguments to continue with the request:\n\tnext();\n});\n```\n\n\n### Hook: channelRequest:action\n\n### Hook: payRequest:action\n\n### Hook: withdrawRequest:action\n\n`channelRequest:action` `payRequest:action` `withdrawRequest:action`\n\nThese hooks are called when the second request is made to the LNURL end-point. This request occurs when the wallet app wants to complete the action associated with the LNURL it scanned and made an initial request for previously.\n\n* `channelRequest:action` - Wallet app sends its node ID and whether or not to make the channel private:\n\t* `remoteid` - remote node ID (public key) to which the server should open a channel\n\t* `private` - `0` or `1`\n* `payRequest:action` - Wallet sends the amount it wants to pay and an optional comment:\n\t* `amount` - amount the server should use when generating a new invoice\n* `withdrawRequest:action` - Wallet sends a bolt11 invoice that the server should pay:\n\t* `pr` - bolt11 invoice\n\n```js\nserver.bindToHook('channelRequest:action', function(secret, params, next) {\n\t// `secret` is the k1 value that when hashed gives the unique `hash`\n\t//  associated with an LNURL in the data store.\n\t// `params` are the parameters provided when the URL was created plus\n\t// the parameters provided in the request to the server.\n\t// Throw an error to fail the request:\n\tnext(new HttpError('Custom error sent in the response object', 400/* status code */));\n\t// Call next() without any arguments to continue with the request:\n\tnext();\n});\n```\nNote that these hooks are executed before the server calls the LN backend method. So if an error is thrown here, a channel will not be opened; a new invoice will not be generated; the provided invoice will not be paid.\n\n\n## Events\n\n* [login](#event-login)\n* [channelRequest:action:processed](#event-channelrequestactionprocessed)\n* [channelRequest:action:failed](#event-channelrequestactionfailed)\n* [payRequest:action:processed](#event-payrequestactionprocessed)\n* [payRequest:action:failed](#event-payrequestactionfailed)\n* [withdrawRequest:action:processed](#event-withdrawrequestactionprocessed)\n* [withdrawRequest:action:failed](#event-withdrawrequestactionfailed)\n\nThe `server` object extends from the [event emitter class](https://nodejs.org/api/events.html#class-eventemitter). It is possible to listen for events as follows:\n```js\nconst lnurl = require('lnurl');\nconst server = lnurl.createServer();\n\nserver.on('EVENT', function(event) {\n\t// The event object varies depending upon the event type.\n});\n```\n\n### Event: login\n\nThis event is emitted after a successful login attempt.\n```js\nserver.on('login', function(event) {\n\tconst { key, hash } = event;\n\t// `key` - the public key as provided by the LNURL wallet app\n\t// `hash` - the hash of the secret for the LNURL used to login\n});\n```\n\n### Event: channelRequest:action:processed\n\nThis event is emitted after a successful call to the LN backend's `openChannel` method.\n```js\nserver.on('channelRequest:action:processed', function(event) {\n\tconst { secret, params, result } = event;\n\t// `result` is the non-normalized response object from the LN backend\n\t// So this will vary depending upon the backend used.\n});\n```\n\n### Event: payRequest:action:processed\n\nThis event is emitted after a successful call to the LN backend's `addInvoice` method.\n```js\nserver.on('payRequest:action:processed', function(event) {\n\tconst { secret, params, result } = event;\n\tconst { id, invoice } = result;\n\t// `id` - non-standard reference ID for the new invoice, can be NULL if none provided\n\t// `invoice` - bolt11 invoice\n});\n```\n\n### Event: withdrawRequest:action:processed\n\nThis event is emitted after a successful call to the LN backend's `payInvoice` method.\n```js\nserver.on('withdrawRequest:action:processed', function(event) {\n\tconst { secret, params, result } = event;\n\tconst { id } = result;\n\t// `id` - non-standard reference ID for the payment, can be NULL if none provided\n});\n```\n\n### Event: channelRequest:action:failed\n\nThis event is emitted after a failed call to the LN backend's `openChannel` method.\n```js\nserver.on('channelRequest:action:failed', function(event) {\n\tconst { secret, params, error } = event;\n\t// `error` - error from the LN backend\n});\n```\n\n### Event: payRequest:action:failed\n\nThis event is emitted after a failed call to the LN backend's `addInvoice` method.\n```js\nserver.on('payRequest:action:failed', function(event) {\n\tconst { secret, params, error } = event;\n\t// `error` - error from the LN backend\n});\n```\n\n### Event: withdrawRequest:action:failed\n\nThis event is emitted after a failed call to the LN backend's `payInvoice` method.\n```js\nserver.on('withdrawRequest:action:failed', function(event) {\n\tconst { secret, params, error } = event;\n\t// `error` - error from the LN backend\n});\n```\n\n\n## Supported Lightning Network Backends\n\nSee [lightning-backends](https://github.com/bleskomat/lightning-backends-node) for a list of supported Lightning Network backends and their corresponding configuration options.\n\n\n## Configuring Data Store\n\nBy default the lnurl server will store data in memory - which is not ideal for several reasons. It is strongly recommended that you configure a proper data store for your server. This module supports [PostgreSQL](#postgresql).\n\n\n### PostgreSQL\n\nTo use PostgreSQL as your data store you will need to install the [postgres module](https://github.com/brianc/node-postgres) and [knex](http://knexjs.org/) wherever you are running your lnurl server:\n```bash\nnpm install knex pg\n```\nThen you can run your server via the API as follows:\n```js\nconst lnurl = require('lnurl');\nconst server = lnurl.createServer({\n\t// ...\n\tstore: {\n\t\tbackend: 'knex',\n\t\tconfig: {\n\t\t\tclient: 'postgres',\n\t\t\tconnection: {\n\t\t\t\thost: '127.0.0.1',\n\t\t\t\tuser: 'lnurl_server',\n\t\t\t\tpassword: '',\n\t\t\t\tdatabase: 'lnurl_server',\n\t\t\t},\n\t\t},\n\t},\n\t// ...\n});\n```\nOr via the CLI:\n```bash\nlnurl server \\\n\t--store.backend=\"knex\" \\\n\t--store.config='{\"client\":\"postgres\",\"connection\":{\"host\":\"127.0.0.1\",\"user\":\"lnurl_server\",\"password\":\"\",\"database\":\"lnurl_server\"}}'\n```\n\n\n## Debugging\n\nThis module uses [debug](https://github.com/visionmedia/debug) to output debug messages to the console. To output all debug messages, run your node app with the `DEBUG` environment variable:\n```bash\nDEBUG=lnurl* node your-app.js\n```\nOr if using the CLI interface:\n```bash\nDEBUG=lnurl* lnurl server\n```\n\n\n## Tests\n\nTo run all tests:\n```\nnpm test\n```\n\n\n## Changelog\n\nSee [CHANGELOG.md](https://github.com/chill117/lnurl-node/blob/master/CHANGELOG.md)\n\n\n## License\n\nThis software is [MIT licensed](https://tldrlegal.com/license/mit-license):\n\u003e A short, permissive software license. Basically, you can do whatever you want as long as you include the original copyright and license notice in any copy of the software/source.  There are many variations of this license in use.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchill117%2Flnurl-node","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchill117%2Flnurl-node","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchill117%2Flnurl-node/lists"}