1
1
mirror of https://github.com/bumi/lntip synced 2026-02-16 05:57:49 +00:00

28 Commits

Author SHA1 Message Date
dependabot[bot]
3cd6b82267 Bump golang.org/x/crypto from 0.0.0-20210921155107-089bfa567519 to 0.1.0
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.0.0-20210921155107-089bfa567519 to 0.1.0.
- [Release notes](https://github.com/golang/crypto/releases)
- [Commits](https://github.com/golang/crypto/commits/v0.1.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-07 03:31:55 +00:00
530c7c0942 Merge pull request #50 from ziggie1984/add-private-route-hints
add private routing hints for invoices
2023-01-28 13:02:18 +02:00
ziggie
23a134b28e add private routing hints for invoices 2023-01-23 10:08:26 +01:00
c6dc9308c3 Merge pull request #46 from bumi/dependabot/go_modules/github.com/labstack/echo/v4-4.9.0
Bump github.com/labstack/echo/v4 from 4.7.2 to 4.9.0
2022-11-06 23:24:54 +01:00
dependabot[bot]
897217995a Bump github.com/labstack/echo/v4 from 4.7.2 to 4.9.0
Bumps [github.com/labstack/echo/v4](https://github.com/labstack/echo) from 4.7.2 to 4.9.0.
- [Release notes](https://github.com/labstack/echo/releases)
- [Changelog](https://github.com/labstack/echo/blob/master/CHANGELOG.md)
- [Commits](https://github.com/labstack/echo/compare/v4.7.2...v4.9.0)

---
updated-dependencies:
- dependency-name: github.com/labstack/echo/v4
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-09-30 16:05:20 +00:00
a21e8b96b7 Add fly.io deployment notes 2022-08-19 10:55:00 +02:00
a383a747ef Merge pull request #40 from yanascz/lnurl-comment-allowed
Add configuration property for allowed length of LNURL-pay comments
2022-08-11 09:02:27 +02:00
yanas
9ceea9e6bf Add configuration property for allowed length of LNURL-pay comments 2022-08-11 08:45:19 +02:00
d42c12be9b Merge pull request #43 from ok300/patch-1
Document `listen` startup config
2022-08-11 02:34:25 +02:00
ok300
53253eba76 Document listen startup config 2022-08-09 07:30:02 +02:00
a3675ec746 Update README.md 2022-07-13 20:22:12 +02:00
3c8a76a1c1 Update README.md 2022-05-17 14:14:26 +02:00
f6d089c194 lowercase sats 2022-05-13 11:06:13 +02:00
ae9f643fbf go fmt 2022-05-07 12:50:15 +02:00
5fd10bc647 Add icon assets 2022-05-07 11:36:42 +02:00
5d2c9cd639 Fix: use correct header to get the original request host
Proxy servers can set the X-Forwarded-Host and X-Forwarded-Proto headers to pass on the original host and protocol.
We should also support the Forwarded header (which combines this in one header described in RFC7239 - but seems echo does not support parsing that one?)
2022-05-06 20:30:35 +02:00
bdd3b70e1f Merge pull request #35 from AaronDewes/patch-1
Fix typo
2022-04-18 17:27:51 +02:00
Aaron Dewes
a9a3e8b073 Fix typo
clipboad -> clipboard
2022-04-18 17:24:43 +02:00
e400782449 Some auto-formatting 2022-04-14 20:58:13 -04:00
488eef551f Flag for the LND hex strings 2022-04-14 20:57:51 -04:00
fae94fc021 update dependencies 2022-04-14 20:32:17 -04:00
c2b11e3146 Merge pull request #33 from runcitadel/go-1.17
Drop go rice and switch to go 1.17
2022-04-15 02:15:25 +02:00
1fbfdf059a Update README.md 2022-04-11 17:56:03 +02:00
Aaron Dewes
f8f8525b01 Actually fix the bug 2022-02-01 20:57:28 +01:00
Aaron Dewes
1ea6ce082b Bug fix 2022-02-01 20:23:42 +01:00
Aaron Dewes
31c8b4d080 Remove useless conversion to string 2022-01-31 08:35:08 +01:00
Aaron Dewes
77d21734c3 Drop go rice and switch to go 1.17 2022-01-30 13:41:25 +01:00
c4b4430387 Update README.md 2022-01-14 17:09:20 +02:00
12 changed files with 1020 additions and 476 deletions

View File

@@ -1,15 +1,13 @@
# Go base image
FROM golang:1.17-alpine as builder
RUN go get github.com/GeertJohan/go.rice && go get github.com/GeertJohan/go.rice/rice
WORKDIR /app
COPY . .
RUN go install
RUN rice embed-go && go build
RUN go build
FROM alpine:3.14

137
README.md
View File

@@ -5,7 +5,7 @@ LnMe is a personal Bitcoin Lightning payment page/widget and self-hosted [Lightn
![demo](./lnme-demo.gif)
**See it in action: [ln.michaelbumann.com](https://ln.michaelbumann.com/) - my lightning address: bumi@ln.michaelbumann.com**
**See it in action: [ln.michaelbumann.com](http://ln.michaelbumann.com/) - my lightning address: bumi@ln.michaelbumann.com**
LnMe focusses on simplicity and ease of deployment. It connects to an existing lightning node (currently LND is supported).
@@ -18,7 +18,8 @@ LnMe is one [simple executable](https://github.com/bumi/lnme/releases) file that
- [x] WebLN integration - if [WebLN](https://webln.dev/) is not available a QRcode and the invoice will be shown
- [x] [JavaScript widget](#javascript-widget-integration) for existing websites
- [x] [Invoice API](https://github.com/bumi/lnme/wiki/API) - simple REST API to create LN invoices from existing JS code
- [ ] [LNURL-pay](https://github.com/fiatjaf/lnurl-rfc/blob/luds/06.md) support
- [x] [LNURL-pay](https://github.com/fiatjaf/lnurl-rfc/blob/luds/06.md) support
- [x] [LNURL-pay comment](https://github.com/fiatjaf/lnurl-rfc/blob/luds/12.md) support
## Installation
@@ -35,11 +36,9 @@ There are no other dependencies. Simply download the binary and run it!
1. `$ git clone https://github.com/bumi/lnme.git && cd lnme`
2. `$ go install`
3. `$ rice embed-go && go build`
3. `$ go build`
4. `$ ./lnme`
Note: You must have [go.rice installed](https://github.com/GeertJohan/go.rice#installation)
### Running in Docker
LnMe is now available in docker too.
@@ -52,23 +51,25 @@ A list of existing tags is available [here](https://github.com/bumi/lnme/pkgs/co
To connect to the lnd node the cert, macaroon and address of the lnd node has to be configured. LnMe uses the LND defaults.
* `lnd-address`: Host and port of the LND gRPC service. default: localhost:10009
* `lnd-cert-path`: Path to the LND TLS cert file. default: ~/.lnd/tls.cert
* `lnd-macaroon-path`: Path to the LND macaroon file. default: ~/.lnd/data/chain/bitcoin/mainnet/invoice.macaroon (invoice.macaroon is recommended)
- `lnd-address`: Host and port of the LND gRPC service. default: localhost:10009
- `lnd-cert-path`: Path to the LND TLS cert file. default: ~/.lnd/tls.cert
- `lnd-macaroon-path`: Path to the LND macaroon file. default: ~/.lnd/data/chain/bitcoin/mainnet/invoice.macaroon (invoice.macaroon is recommended)
Instead of the path to the macaroon and cert files you can also provide the hex strings:
* `lnd-cert`: LND TLS cert as HEX string.
* `lnd-macaroon`: LND macaroon HEX string. (invoice.macaroon is recommended)
- `lnd-cert`: LND TLS cert as HEX string.
- `lnd-macaroon`: LND macaroon HEX string. (invoice.macaroon is recommended)
#### Other configuration
* `static-path`: Path to a folder that you want to serve with LnMe (e.g. /home/bitcoin/lnme/website). Use this if you want to customize your ⚡website. default: disabled
* `disable-website`: Disable the default LnMe website. Disable the website if you only want to embed the LnMe widget on your existing website.
* `disable-cors`: Disable CORS headers. (default: false)
* `disable-ln-address`: Disable [Lightning Address](https://lightningaddress.com/) handling.
* `port`: Port to listen on. (default: 1323)
* `request-limit`: Limit the allowed requests per second. (default: 5)
- `static-path`: Path to a folder that you want to serve with LnMe (e.g. /home/bitcoin/lnme/website). Use this if you want to customize your ⚡website. default: disabled
- `lnurlp-comment-allowed`: Allowed length of LNURL-pay comments, maximum around [~2000 characters](https://stackoverflow.com/a/417184). (default: 210)
- `disable-website`: Disable the default LnMe website. Disable the website if you only want to embed the LnMe widget on your existing website.
- `disable-cors`: Disable CORS headers. (default: false)
- `disable-ln-address`: Disable [Lightning Address](https://lightningaddress.com/) handling.
- `port`: Port to listen on. (default: 1323)
- `listen`: IP and port to listen to. Supersedes `port`. (default: :1323).
- `request-limit`: Limit the allowed requests per second. (default: 5)
Depending on your deployment needs LnMe can be configured using the following options:
@@ -100,8 +101,8 @@ All environment variables must be prefixed by `LNME_` use `_` instead of `-`
LnMe needs the following LND permissions:
* Read/Write permission for `invoices`
* Write permission for `address` (if you want to use the onchain option)
- Read/Write permission for `invoices`
- Write permission for `address` (if you want to use the onchain option)
Use the LND [macaroon bakery](http://macaroon-bakery.freedomnode.com/) to create a new macaroon for LnMe.
@@ -111,24 +112,24 @@ To get the HEX versions of the files use `xxd -plain` e.g. `xxd -plain invoice.m
LnMe can connect to your lightning node through [Tor](https://www.torproject.org/). You need to have Tor installed on your system and then simply provide your LND `.onion` address (don't forget to specify the port).
## Deployment
It is the easiest to run LnMe on the same node as LND. But you can run it anywhere as long as your LND node is accessible. Simply run the binary and make sure the PORT is accessible.
If you run LNMe on a different server you will need your LND address, the LND TLS certificate (HEX) and the macaroon (HEX). (see above)
When getting the HEX of the LND files use `xxd -plain YOUR_FILE.cert | tr -d '\n'`. For example for the TLS certificate, use `xxd -plain tls.cert | tr -d '\n'`.
When getting the HEX of the LND files use `xxd -plain YOUR_FILE.cert | tr -d '\n'`. For example for the TLS certificate, use `xxd -plain tls.cert | tr -d '\n'`.
The TLS cert is located in the lnd directory:
* ~/umbrel/lnd/tls.cert on Umbrel
* /mnt/hdd/lnd/tls.cert on Raspiblitz
* Can also be located in ~/.lnd
You should find the macaroon files in the LND data dir (e.g. ~.lnd/data/chain/bitcoin/mainnet/) or see "LND Permissions" how to create a new one.
- ~/umbrel/lnd/tls.cert on Umbrel
- /mnt/hdd/lnd/tls.cert on Raspiblitz
- Can also be located in ~/.lnd
You should find the macaroon files in the LND data dir (e.g. ~.lnd/data/chain/bitcoin/mainnet/) or see "LND Permissions" how to create a new one.
### Heroku
One click deployment with Heroku:
[![Deploy on Heroku](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy?template=https://github.com/bumi/lnme)
@@ -141,20 +142,54 @@ This buildpack can be disabled and removed if not needed or desired, through the
Lastly, using the Heroku deployment, you can link the app to your own domain by following the directions here: https://help.heroku.com/MTG1BIA7/how-do-i-connect-a-domain-to-my-heroku-app
### Deployment Notes
### Fly.io
#### 0. Clone the repo
$ git clone https://github.com/bumi/lnme.git
$ cd lnme
#### 1. Create a new app
$ flyctl launch --generate-name // or set a custom app name: flyctl launch --name lnme-test-1
You will be asked a few things:
* Copy the configuration to the new app
* You do NOT need to create a Postgresql Database
* Do NOT deploy it directly, we first need to set some configs
#### 2. Set the configuration using environment variables:
The LND config variablse are required. Others are optional:
$ flyctl secrets set LNME_LND_ADDRESS="xxx.xxx.xxx.xxx:10009" LNME_LND_CERT=xxx LNME_LND_MACAROON=xxx
$ flyctl secrets set DISABLE_WEBSITE=1 // etc.
#### 3. Launch the app:
$ flyctl deploy
#### 4.Configure your domain
To configure a custom domain check the [fly.io guides](https://fly.io/docs/app-guides/custom-domains-with-fly/)
### Custom deployment notes
To run LnMe as systemd service have a look at the [systemd service example config](https://github.com/bumi/lnme/blob/master/examples/lnme.service)
I am running LnMe behind a reverse proxy using [caddy](https://caddyserver.com/) which comes with [fully-managed HTTPS](https://caddyserver.com/docs/quick-starts/https) via [letsencrypt](https://letsencrypt.org/).
Example Caddyfile:
```
lnme.michaelbumann.com {
reverse_proxy 127.0.0.1:1323
}
```
`$ caddy --config /etc/caddy/Caddyfile`
`$ caddy --config /etc/caddy/Caddyfile`
## Feature Usage
@@ -167,6 +202,13 @@ For more information check out the website: [lightningaddress.com](https://light
Your Lightning Address: `{anything}@{your domain}`
### LNURL
if you got the Lightning Address enabled you also get a LNURL-pay URL:
https://`{your domain}/lnurlp/{anything}`
If you need an bech32 encoded version you can use this online tool: [https://lnurl.fiatjaf.com/codec/](https://lnurl.fiatjaf.com/codec/)
### Customize your ⚡ website
@@ -178,6 +220,12 @@ Take a look at the [embedded default website](https://github.com/bumi/lnme/blob/
2. Create your index.html
3. Run lnme: `lnme --static-path=/home/satoshi/my-ln-page
### Usage with 21 Payment Widgets
[widgets.twentyuno.net](https://widgets.twentyuno.net/) is a beautiful embeddable payment widget for any existing website.
You can use your LnMe instance with the widget by using your [LnMe LNURL](https://github.com/bumi/lnme#lnurl) with the widget.
Use your bech32 encoded [LNURL](https://github.com/bumi/lnme#lnurl) as `Receiver` in the [widget configuration](https://widgets.twentyuno.net/get-started)
### JavaScript Widget integration
@@ -186,7 +234,10 @@ You can integrate the LnMe widget in your existing website.
#### 1. Add the LnMe JavaScript files
```html
<script data-lnme-base-url="https://your-lnme-host.com:1323" src="https://your-lnme-host.com/lnme/lnme.js"></script>
<script
data-lnme-base-url="https://your-lnme-host.com:1323"
src="https://your-lnme-host.com/lnme/lnme.js"
></script>
```
#### 2. Usage
@@ -194,37 +245,40 @@ You can integrate the LnMe widget in your existing website.
To request a lightning payment simply call `request()` on a `new LnMe({value: value, memo: memo})`:
```js
var lnme = new LnMe({ value: 1000, memo: 'high5' });
var lnme = new LnMe({ value: 1000, memo: "high5" });
lnme.request();
```
Use it from a plain HTML link:
```html
<a href="#" onclick="javascript:new LnMe({ value: 1000, memo: 'high5' }).request();return false;">Tip me</a>
<a
href="#"
onclick="javascript:new LnMe({ value: 1000, memo: 'high5' }).request();return false;"
>Tip me</a
>
```
##### More advanced JS API:
```js
let lnme = new LnMe({ value: 1000, memo: 'high5' });
let lnme = new LnMe({ value: 1000, memo: "high5" });
// get a new invoice and watch for a payment
// promise resolves if the invoice is settled
lnme.requestPayment().then(invoice => {
alert('YAY, thanks!');
lnme.requestPayment().then((invoice) => {
alert("YAY, thanks!");
});
// create a new invoice
lnme.addInvoice().then(invoice => {
console.log(invoice.PaymentRequest)
lnme.addInvoice().then((invoice) => {
console.log(invoice.PaymentRequest);
});
// periodically watch if an invoice is settled
lnme.watchPayment().then(invoice => {
alert('YAY, thanks!');
lnme.watchPayment().then((invoice) => {
alert("YAY, thanks!");
});
```
## Motivation
@@ -234,21 +288,22 @@ BTCPay Server is too big and hard to run for that and I do not need most of its
## Development
Use `go run` to ron the service locally:
Use `go run` to run the service locally:
$ go run lnme.go --address=127.0.0.1:10009 --cert=/home/bitcoin/lightning/tls.cert --macaroon=/home/bitcoin/lightning/invoice.macaroon
## Build
LnMe uses [go.rice](https://github.com/GeertJohan/go.rice) to embed assets (HTML, JS, and CSS files). run `rice embed-go` (needs to be [installed](https://github.com/GeertJohan/go.rice#installation))
$ rice embed-go
$ go build
## Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/bumi/lnme
## Support
If you like this software and it is valuable for you, you can send sats to ⚡bumi@getalby.com
## License
Available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).

Binary file not shown.

After

Width:  |  Height:  |  Size: 397 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 760 KiB

View File

@@ -148,7 +148,7 @@ class LnMe {
this.target.querySelectorAll('.lnme-copy').forEach(element => {
element.addEventListener('click', (e) => {
navigator.clipboard.writeText(this.invoice.payment_request).then(() => {
alert('Copied to clipboad');
alert('Copied to clipboard');
});
});
});

View File

@@ -8,7 +8,7 @@
<meta property="og:image" content="/lnme/icon.svg">
<title>Send me some Sats</title>
<title>Send me some sats</title>
<style>
html {
width: 100%;
@@ -118,7 +118,7 @@
<div class="form" id="form">
<p>
Send me<br>
<input type="number" placeholder="10000" class="amount" id="amount" autofocus="true" autocomplete="off" min="100"> Sats
<input type="number" placeholder="10000" class="amount" id="amount" autofocus="true" autocomplete="off" min="100"> sats
<br>
for
<br>
@@ -159,7 +159,7 @@
}
var siteDescription = document.querySelector('head > meta[property="og:description"]');
if (siteDescription && !siteDescription.content) {
siteDescription.content = "Sats for " + window.location.host;
siteDescription.content = "sats for " + window.location.host;
}
document.getElementById("get-new-address").addEventListener('click', function(e) {
e.preventDefault();

37
fly.toml Normal file
View File

@@ -0,0 +1,37 @@
# fly.toml file generated
kill_signal = "SIGINT"
kill_timeout = 5
processes = []
[env]
[experimental]
allowed_public_ports = []
auto_rollback = true
[[services]]
http_checks = []
internal_port = 1323
processes = ["app"]
protocol = "tcp"
script_checks = []
[services.concurrency]
hard_limit = 25
soft_limit = 20
type = "connections"
[[services.ports]]
force_https = true
handlers = ["http"]
port = 80
[[services.ports]]
handlers = ["tls", "http"]
port = 443
[[services.tcp_checks]]
grace_period = "1s"
interval = "15s"
restart_limit = 0
timeout = "2s"

149
go.mod
View File

@@ -1,17 +1,146 @@
// +heroku goVersion 1.15
// +heroku goVersion 1.17
module github.com/bumi/lnme
go 1.15
go 1.17
// https://github.com/lightningnetwork/lnd/issues/5624#issuecomment-897512230
replace go.etcd.io/etcd => go.etcd.io/etcd v0.5.0-alpha.5.0.20201125193152-8a03d2e9614b
require (
github.com/GeertJohan/go.rice v1.0.2
github.com/cretz/bine v0.2.0
github.com/didip/tollbooth/v6 v6.1.1
github.com/knadh/koanf v1.2.1
github.com/labstack/echo/v4 v4.5.0
github.com/lightningnetwork/lnd v0.13.1-beta
google.golang.org/grpc v1.40.0
github.com/didip/tollbooth/v6 v6.1.2
github.com/knadh/koanf v1.4.1
github.com/labstack/echo/v4 v4.9.0
github.com/lightningnetwork/lnd v0.14.1-beta
google.golang.org/grpc v1.45.0
gopkg.in/macaroon.v2 v2.1.0
)
require (
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da // indirect
github.com/aead/siphash v1.0.1 // indirect
github.com/andybalholm/brotli v1.0.3 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/btcsuite/btcd v0.22.0-beta.0.20211005184431-e3449998be39 // indirect
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f // indirect
github.com/btcsuite/btcutil v1.0.3-0.20210527170813-e2ba6805a890 // indirect
github.com/btcsuite/btcutil/psbt v1.0.3-0.20210527170813-e2ba6805a890 // indirect
github.com/btcsuite/btcwallet v0.13.0 // indirect
github.com/btcsuite/btcwallet/wallet/txauthor v1.1.0 // indirect
github.com/btcsuite/btcwallet/wallet/txrules v1.1.0 // indirect
github.com/btcsuite/btcwallet/wallet/txsizes v1.1.0 // indirect
github.com/btcsuite/btcwallet/walletdb v1.3.6-0.20210803004036-eebed51155ec // indirect
github.com/btcsuite/btcwallet/wtxmgr v1.3.1-0.20210822222949-9b5a201c344c // indirect
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd // indirect
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 // indirect
github.com/cespare/xxhash/v2 v2.1.1 // indirect
github.com/coreos/go-semver v0.3.0 // indirect
github.com/coreos/go-systemd/v22 v22.3.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/decred/dcrd/lru v1.0.0 // indirect
github.com/dsnet/compress v0.0.1 // indirect
github.com/dustin/go-humanize v1.0.0 // indirect
github.com/fergusstrange/embedded-postgres v1.10.0 // indirect
github.com/form3tech-oss/jwt-go v3.2.3+incompatible // indirect
github.com/fsnotify/fsnotify v1.4.9 // indirect
github.com/go-errors/errors v1.0.1 // indirect
github.com/go-pkgz/expirable-cache v0.0.3 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/btree v1.0.1 // indirect
github.com/gorilla/websocket v1.4.2 // indirect
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect
github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.5.0 // indirect
github.com/jackc/chunkreader/v2 v2.0.1 // indirect
github.com/jackc/pgconn v1.10.0 // indirect
github.com/jackc/pgio v1.0.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgproto3/v2 v2.1.1 // indirect
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b // indirect
github.com/jackc/pgtype v1.8.1 // indirect
github.com/jackc/pgx/v4 v4.13.0 // indirect
github.com/jonboulle/clockwork v0.2.2 // indirect
github.com/jrick/logrotate v1.0.0 // indirect
github.com/json-iterator/go v1.1.11 // indirect
github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8 // indirect
github.com/kkdai/bstream v1.0.0 // indirect
github.com/klauspost/compress v1.13.6 // indirect
github.com/klauspost/pgzip v1.2.5 // indirect
github.com/labstack/gommon v0.3.1 // indirect
github.com/lib/pq v1.10.3 // indirect
github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf // indirect
github.com/lightninglabs/neutrino v0.13.0 // indirect
github.com/lightningnetwork/lightning-onion v1.0.2-0.20210520211913-522b799e65b1 // indirect
github.com/lightningnetwork/lnd/clock v1.1.0 // indirect
github.com/lightningnetwork/lnd/healthcheck v1.2.0 // indirect
github.com/lightningnetwork/lnd/kvdb v1.2.1 // indirect
github.com/lightningnetwork/lnd/queue v1.1.0 // indirect
github.com/lightningnetwork/lnd/ticker v1.1.0 // indirect
github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796 // indirect
github.com/mattn/go-colorable v0.1.11 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
github.com/mholt/archiver/v3 v3.5.0 // indirect
github.com/miekg/dns v1.1.43 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/mapstructure v1.4.1 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.1 // indirect
github.com/nwaples/rardecode v1.1.2 // indirect
github.com/pelletier/go-toml v1.7.0 // indirect
github.com/pierrec/lz4/v4 v4.1.8 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.11.0 // indirect
github.com/prometheus/client_model v0.2.0 // indirect
github.com/prometheus/common v0.26.0 // indirect
github.com/prometheus/procfs v0.6.0 // indirect
github.com/rogpeppe/fastuuid v1.2.0 // indirect
github.com/sirupsen/logrus v1.7.0 // indirect
github.com/soheilhy/cmux v0.1.5 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/stretchr/testify v1.7.0 // indirect
github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 // indirect
github.com/ulikunitz/xz v0.5.10 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.1 // indirect
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect
go.etcd.io/bbolt v1.3.6 // indirect
go.etcd.io/etcd/api/v3 v3.5.0 // indirect
go.etcd.io/etcd/client/pkg/v3 v3.5.0 // indirect
go.etcd.io/etcd/client/v2 v2.305.0 // indirect
go.etcd.io/etcd/client/v3 v3.5.0 // indirect
go.etcd.io/etcd/pkg/v3 v3.5.0 // indirect
go.etcd.io/etcd/raft/v3 v3.5.0 // indirect
go.etcd.io/etcd/server/v3 v3.5.0 // indirect
go.opentelemetry.io/contrib v0.20.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0 // indirect
go.opentelemetry.io/otel v0.20.0 // indirect
go.opentelemetry.io/otel/exporters/otlp v0.20.0 // indirect
go.opentelemetry.io/otel/metric v0.20.0 // indirect
go.opentelemetry.io/otel/sdk v0.20.0 // indirect
go.opentelemetry.io/otel/sdk/export/metric v0.20.0 // indirect
go.opentelemetry.io/otel/sdk/metric v0.20.0 // indirect
go.opentelemetry.io/otel/trace v0.20.0 // indirect
go.opentelemetry.io/proto/otlp v0.7.0 // indirect
go.uber.org/atomic v1.7.0 // indirect
go.uber.org/multierr v1.6.0 // indirect
go.uber.org/zap v1.17.0 // indirect
golang.org/x/crypto v0.1.0 // indirect
golang.org/x/net v0.1.0 // indirect
golang.org/x/sys v0.1.0 // indirect
golang.org/x/term v0.1.0 // indirect
golang.org/x/text v0.4.0 // indirect
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect
google.golang.org/genproto v0.0.0-20210617175327-b9e0b3197ced // indirect
google.golang.org/protobuf v1.26.0 // indirect
gopkg.in/errgo.v1 v1.0.1 // indirect
gopkg.in/macaroon-bakery.v2 v2.0.1 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
sigs.k8s.io/yaml v1.2.0 // indirect
)

993
go.sum

File diff suppressed because it is too large Load Diff

View File

@@ -47,7 +47,7 @@ type LNDclient struct {
}
// AddInvoice generates an invoice with the given price and memo.
func (c LNDclient) AddInvoice(value int64, memo string, descriptionHash []byte) (Invoice, error) {
func (c LNDclient) AddInvoice(value int64, memo string, descriptionHash []byte, private bool) (Invoice, error) {
result := Invoice{}
stdOutLogger.Printf("Adding invoice: memo=%s value=%v", memo, value)
@@ -55,6 +55,7 @@ func (c LNDclient) AddInvoice(value int64, memo string, descriptionHash []byte)
Memo: memo,
DescriptionHash: descriptionHash,
Value: value,
Private: private,
}
res, err := c.lndClient.AddInvoice(c.ctx, &invoice)
if err != nil {
@@ -173,7 +174,10 @@ func NewLNDclient(lndOptions LNDoptions) (LNDclient, error) {
if err := mac.UnmarshalBinary(macaroonData); err != nil {
return result, err
}
macCred := macaroons.NewMacaroonCredential(mac)
macCred, err := macaroons.NewMacaroonCredential(mac)
if err != nil {
return result, err
}
opts = append(opts, grpc.WithPerRPCCredentials(macCred))
conn, err := grpc.Dial(lndOptions.Address, opts...)

56
lnme.go
View File

@@ -2,15 +2,16 @@ package main
import (
"crypto/sha256"
"embed"
"flag"
"fmt"
"io/fs"
"log"
"net/http"
"os"
"strconv"
"strings"
rice "github.com/GeertJohan/go.rice"
"github.com/bumi/lnme/ln"
"github.com/bumi/lnme/lnurl"
"github.com/didip/tollbooth/v6"
@@ -47,6 +48,12 @@ type Invoice struct {
Memo string `json:"memo"`
}
//go:embed files/assets/*
var embeddedAssets embed.FS
//go:embed files/root/index.html
var indexPage string
func main() {
cfg := LoadConfig()
@@ -57,19 +64,17 @@ func main() {
e.Static("/", cfg.String("static-path"))
// Serve default page
} else if !cfg.Bool("disable-website") {
rootBox := rice.MustFindBox("files/root")
indexPage, err := rootBox.String("index.html")
if err == nil {
stdOutLogger.Print("Running embedded page")
e.GET("/", func(c echo.Context) error {
return c.HTML(200, indexPage)
})
} else {
stdOutLogger.Printf("Failed to run embedded website: %s", err)
}
stdOutLogger.Print("Running embedded page")
e.GET("/", func(c echo.Context) error {
return c.HTML(200, indexPage)
})
}
assetSubdir, err := fs.Sub(embeddedAssets, "files/assets")
if err != nil {
log.Fatal(err)
}
// Embed static files and serve those on /lnme (e.g. /lnme/lnme.js)
assetHandler := http.FileServer(rice.MustFindBox("files/assets").HTTPBox())
assetHandler := http.FileServer(http.FS(assetSubdir))
e.GET("/lnme/*", echo.WrapHandler(http.StripPrefix("/lnme/", assetHandler)))
// CORS settings
@@ -112,7 +117,7 @@ func main() {
return c.JSON(http.StatusBadRequest, "Bad request")
}
invoice, err := lnClient.AddInvoice(i.Value, i.Memo, nil)
invoice, err := lnClient.AddInvoice(i.Value, i.Memo, nil, cfg.Bool("enable-private-channels"))
if err != nil {
stdOutLogger.Printf("Error creating invoice: %s", err)
return c.JSON(http.StatusInternalServerError, "Error adding invoice")
@@ -147,21 +152,27 @@ func main() {
if !cfg.Bool("disable-ln-address") {
lnurlHandler := func(c echo.Context) error {
host := c.Request().Host
if c.Request().Header.Get(echo.HeaderXForwardedFor) != "" {
host = c.Request().Header.Get(echo.HeaderXForwardedFor)
proto := c.Scheme()
// TODO: support RFC7239 Forwarded header
if c.Request().Header.Get("X-Forwarded-Host") != "" {
host = c.Request().Header.Get("X-Forwarded-Host")
}
if c.Request().Header.Get("X-Forwarded-Proto") != "" {
proto = c.Request().Header.Get("X-Forwarded-Proto")
}
name := c.Param("name")
lightningAddress := name + "@" + host
lnurlMetadata := "[[\"text/identifier\", \"" + lightningAddress + "\"], [\"text/plain\", \"Sats for " + lightningAddress + "\"]]"
lnurlpCommentAllowed := cfg.Int64("lnurlp-comment-allowed")
if amount := c.QueryParam("amount"); amount == "" {
lnurlPayResponse1 := lnurl.LNURLPayResponse1{
LNURLResponse: lnurl.LNURLResponse{Status: "OK"},
Callback: fmt.Sprintf("%s://%s%s", c.Scheme(), host, c.Request().URL.Path),
Callback: fmt.Sprintf("%s://%s%s", proto, host, c.Request().URL.Path),
MinSendable: 1000,
MaxSendable: 100000000,
EncodedMetadata: lnurlMetadata,
CommentAllowed: 0,
CommentAllowed: lnurlpCommentAllowed,
Tag: "payRequest",
}
return c.JSON(http.StatusOK, lnurlPayResponse1)
@@ -173,8 +184,13 @@ func main() {
return c.JSON(http.StatusOK, lnurl.LNURLErrorResponse{Status: "ERROR", Reason: "Invalid Amount"})
}
sats := msats / 1000 // we need sats
comment := c.QueryParam("comment")
if commentLength := int64(len(comment)); commentLength > lnurlpCommentAllowed {
stdOutLogger.Printf("Invalid comment length: %d", commentLength)
return c.JSON(http.StatusOK, lnurl.LNURLErrorResponse{Status: "ERROR", Reason: "Invalid comment length"})
}
metadataHash := sha256.Sum256([]byte(lnurlMetadata))
invoice, err := lnClient.AddInvoice(sats, lightningAddress, metadataHash[:])
invoice, err := lnClient.AddInvoice(sats, comment, metadataHash[:], cfg.Bool("enable-private-channels"))
if err != nil {
stdOutLogger.Printf("Error creating invoice: %s", err)
return c.JSON(http.StatusOK, lnurl.LNURLErrorResponse{Status: "ERROR", Reason: "Server Error"})
@@ -225,10 +241,14 @@ func LoadConfig() *koanf.Koanf {
f := flag.NewFlagSet("LnMe", flag.ExitOnError)
f.String("lnd-address", "localhost:10009", "The host and port of the LND gRPC server.")
f.String("lnd-macaroon-path", "~/.lnd/data/chain/bitcoin/mainnet/invoice.macaroon", "Path to the LND macaroon file.")
f.String("lnd-macaroon", "", "HEX string of LND macaroon file.")
f.String("lnd-cert-path", "~/.lnd/tls.cert", "Path to the LND tls.cert file.")
f.String("lnd-cert", "", "HEX string of LND tls cert file.")
f.Int64("lnurlp-comment-allowed", 210, "Allowed length of LNURL-pay comments.")
f.Bool("disable-website", false, "Disable default embedded website.")
f.Bool("disable-ln-address", false, "Disable Lightning Address handling")
f.Bool("disable-cors", false, "Disable CORS headers.")
f.Bool("enable-private-channels", false, "Adds private routing hints to invoices")
f.Float64("request-limit", 5, "Request limit per second.")
f.String("static-path", "", "Path to a static assets directory.")
f.String("port", "", "Port to bind on (deprecated - use listen).")

File diff suppressed because one or more lines are too long