126 Commits

Author SHA1 Message Date
Overtorment
0d337bdc7b REL 2021-05-14 11:11:23 +01:00
Overtorment
f0bf066cfd FIX: updateDescribeGraph() is disabled by default (too slow on low-end machines) 2021-05-14 11:10:41 +01:00
snyk-bot
f0ad86f1b9 fix: upgrade core-js from 3.10.2 to 3.11.0
Snyk has created this PR to upgrade core-js from 3.10.2 to 3.11.0.

See this package in npm:
https://www.npmjs.com/package/core-js

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2021-05-14 10:54:51 +01:00
snyk-bot
12d1e9560f fix: upgrade multiple dependencies with Snyk
Snyk has created this PR to upgrade:
  - @babel/cli from 7.13.14 to 7.13.16.
    See this package in npm: https://www.npmjs.com/package/@babel/cli
  - @babel/core from 7.13.15 to 7.13.16.
    See this package in npm: https://www.npmjs.com/package/@babel/core
  - @babel/register from 7.13.14 to 7.13.16.
    See this package in npm: https://www.npmjs.com/package/@babel/register

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2021-05-12 11:48:39 +01:00
snyk-bot
1eaf6c5a47 fix: upgrade core-js from 3.10.0 to 3.10.2
Snyk has created this PR to upgrade core-js from 3.10.0 to 3.10.2.

See this package in npm:
https://www.npmjs.com/package/core-js

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2021-05-11 10:16:33 +01:00
snyk-bot
dfcaac2cfa fix: upgrade @grpc/proto-loader from 0.6.0 to 0.6.1
Snyk has created this PR to upgrade @grpc/proto-loader from 0.6.0 to 0.6.1.

See this package in npm:
https://www.npmjs.com/package/@grpc/proto-loader

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2021-05-06 10:59:01 +01:00
snyk-bot
f11c02d2f2 fix: upgrade eslint-plugin-prettier from 3.3.1 to 3.4.0
Snyk has created this PR to upgrade eslint-plugin-prettier from 3.3.1 to 3.4.0.

See this package in npm:
https://www.npmjs.com/package/eslint-plugin-prettier

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2021-05-06 10:58:11 +01:00
snyk-bot
a4eedde3fb fix: upgrade ioredis from 4.25.0 to 4.26.0
Snyk has created this PR to upgrade ioredis from 4.25.0 to 4.26.0.

See this package in npm:
https://www.npmjs.com/package/ioredis

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2021-05-04 10:52:28 +01:00
snyk-bot
597615209b fix: upgrade multiple dependencies with Snyk
Snyk has created this PR to upgrade:
  - @babel/core from 7.13.14 to 7.13.15.
    See this package in npm: https://www.npmjs.com/package/@babel/core
  - @babel/preset-env from 7.13.12 to 7.13.15.
    See this package in npm: https://www.npmjs.com/package/@babel/preset-env

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2021-05-04 10:51:06 +01:00
snyk-bot
5fc7b074f9 fix: upgrade eslint from 7.23.0 to 7.24.0
Snyk has created this PR to upgrade eslint from 7.23.0 to 7.24.0.

See this package in npm:
https://www.npmjs.com/package/eslint

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2021-05-04 10:48:01 +01:00
Overtorment
df9b9a71d9 REL: v1.3.3 2021-04-29 15:34:09 +01:00
Overtorment
ede2359e8a FIX 2021-04-29 15:33:37 +01:00
Aaron Dewes
b9a55f01d7 Allow custom ratelimits 2021-04-29 15:31:13 +01:00
Overtorment
1c4eb6d83a REL: v1.3.2 2021-04-29 13:40:30 +01:00
Aaron Dewes
d4c2771f4a Fix: Fix actions for Umbrel 2021-04-29 13:39:32 +01:00
snyk-bot
f64a8c8102 fix: upgrade @grpc/proto-loader from 0.5.6 to 0.6.0
Snyk has created this PR to upgrade @grpc/proto-loader from 0.5.6 to 0.6.0.

See this package in npm:
https://www.npmjs.com/package/@grpc/proto-loader

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2021-04-28 10:50:07 +01:00
Overtorment
170bf0d120 FIX: time -> blocktime 2021-04-17 00:51:37 +01:00
Overtorment
049ae5de5c REL 2021-04-16 22:08:51 +01:00
Overtorment
877d7762ff ADD: bitcoind migrate script 2021-04-16 22:08:20 +01:00
Overtorment
e0a0eed038 DOC 2021-04-16 22:07:02 +01:00
Overtorment
26692d6c92 FIX: minor improv 2021-04-16 22:06:03 +01:00
ViktorBohu
68fd866894 Fixed progress bar css for small values 2021-04-08 19:27:31 +01:00
Aaron Dewes
d7216e1506 doc: Add options that were added for Umbrel
These options that aren't documented yet were added recently, I hope this documentation looks okay for you.
2021-04-08 12:54:57 +01:00
Overtorment
30c8bb2d94 REF 2021-04-05 12:14:41 +01:00
Overtorment
17e9bd30c8 ADD: /getchaninfo/:chanid 2021-04-03 12:35:45 +01:00
snyk-bot
d47f03501d fix: upgrade bolt11 from 1.2.7 to 1.3.1
Snyk has created this PR to upgrade bolt11 from 1.2.7 to 1.3.1.

See this package in npm:
https://www.npmjs.com/package/bolt11

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2021-04-02 12:32:53 +01:00
snyk-bot
3d1abda05b fix: upgrade @babel/eslint-parser from 7.13.4 to 7.13.10
Snyk has created this PR to upgrade @babel/eslint-parser from 7.13.4 to 7.13.10.

See this package in npm:
https://www.npmjs.com/package/@babel/eslint-parser

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2021-04-02 12:32:06 +01:00
snyk-bot
de64f1c55a fix: upgrade @grpc/grpc-js from 1.2.9 to 1.2.10
Snyk has created this PR to upgrade @grpc/grpc-js from 1.2.9 to 1.2.10.

See this package in npm:
https://www.npmjs.com/package/@grpc/grpc-js

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2021-03-27 10:00:05 +00:00
snyk-bot
bcf87de2b4 fix: upgrade @grpc/grpc-js from 1.2.8 to 1.2.9
Snyk has created this PR to upgrade @grpc/grpc-js from 1.2.8 to 1.2.9.

See this package in npm:
https://www.npmjs.com/package/@grpc/grpc-js

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2021-03-25 12:32:00 +00:00
snyk-bot
ad1b1d3da4 fix: upgrade @babel/preset-env from 7.13.8 to 7.13.9
Snyk has created this PR to upgrade @babel/preset-env from 7.13.8 to 7.13.9.

See this package in npm:
https://www.npmjs.com/package/@babel/preset-env

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2021-03-23 14:34:39 +00:00
snyk-bot
a6f354600c fix: upgrade core-js from 3.9.0 to 3.9.1
Snyk has created this PR to upgrade core-js from 3.9.0 to 3.9.1.

See this package in npm:
https://www.npmjs.com/package/core-js

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2021-03-22 10:59:57 +00:00
snyk-bot
647632c914 fix: upgrade multiple dependencies with Snyk
Snyk has created this PR to upgrade:
  - @babel/core from 7.13.1 to 7.13.8.
    See this package in npm: https://www.npmjs.com/package/@babel/core
  - @babel/preset-env from 7.13.5 to 7.13.8.
    See this package in npm: https://www.npmjs.com/package/@babel/preset-env
  - @babel/register from 7.13.0 to 7.13.8.
    See this package in npm: https://www.npmjs.com/package/@babel/register

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2021-03-20 19:06:57 +00:00
Overtorment
d24de77b59 REL: v1.3.0 2021-02-24 15:20:41 +00:00
Aaron Dewes
f0493d595f Umbrel support (#141)
* Don't require BTC core connection
* Docker: Don't clone, but use local repo
* Add GitHub workflows
* Allow to overwrite hostname
* chore: update dependencies
* Get tor URL from env
2021-02-24 15:17:22 +00:00
snyk-bot
76b289b652 fix: upgrade eslint from 7.18.0 to 7.19.0
Snyk has created this PR to upgrade eslint from 7.18.0 to 7.19.0.

See this package in npm:
https://www.npmjs.com/package/eslint

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2021-02-22 12:13:39 +00:00
Overtorment
73d65bb7b3 FIX: bars 2021-02-21 12:26:40 +00:00
ncoelho
076bb485d9 change colors logic 2021-02-18 12:11:01 +00:00
ncoelho
9c66b33477 REF: Change title 2021-02-18 12:11:01 +00:00
ncoelho
eae9da8044 update favicon 2021-02-18 12:11:01 +00:00
ncoelho
a72b722d1d improve radius 2021-02-18 12:11:01 +00:00
ncoelho
5457d377f3 REF: Channel size GUI 2021-02-18 12:11:01 +00:00
ncoelho
36ae5c5f4e print 2021-02-18 12:11:01 +00:00
ncoelho
989b195ba5 print 2021-02-18 12:11:01 +00:00
ncoelho
7df309771e print 2021-02-18 12:11:01 +00:00
ncoelho
c177a046f8 print 2021-02-18 12:11:01 +00:00
ncoelho
41567ac160 local and remote 2021-02-18 12:11:01 +00:00
ncoelho
e3b4071bdb try values for channels 2021-02-18 12:11:01 +00:00
ncoelho
325015d95b Revert "try channel values"
This reverts commit 11655e8aba22b7ba1ed5447939f78818ea006668.
2021-02-18 12:11:01 +00:00
ncoelho
2fd40eb4f6 try channel values 2021-02-18 12:11:01 +00:00
ncoelho
d94afd9860 blind fix name 2021-02-18 12:11:01 +00:00
ncoelho
c937ef94aa blind fix on active state 2021-02-18 12:11:01 +00:00
ncoelho
2e574df0fb Fix static files 2021-02-18 12:11:01 +00:00
ncoelho
3838746a13 Fix template 2021-02-18 12:11:01 +00:00
ncoelho
59ca61657e ADD: lndhub home redesign 2021-02-18 12:11:01 +00:00
snyk-bot
6d0e58a422 fix: upgrade @grpc/proto-loader from 0.5.5 to 0.5.6
Snyk has created this PR to upgrade @grpc/proto-loader from 0.5.5 to 0.5.6.

See this package in npm:
https://www.npmjs.com/package/@grpc/proto-loader

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2021-02-12 16:39:06 +00:00
Overtorment
8e49fe975f ADD: queryroutes api call (#144) 2021-01-19 13:00:06 +00:00
Aaron Dewes
cf40d77b01 Update dependencies (#121) 2021-01-04 12:49:42 +00:00
Overtorment
b8cd8d05b0 REL: ver bump 2020-12-31 20:57:15 +00:00
Overtorment
61353a71e2 FIX: Debit correct amount in case of overpaid userinvoice (closes #138) 2020-12-31 19:59:25 +00:00
Overtorment
4138082a02 ADD: qr image on pain page 2020-12-31 17:48:17 +00:00
Aaron Dewes
6e4dec556e Fix & Optimize Dockerfile 2020-12-18 15:56:15 +00:00
Aaron Dewes
a6940cb3c8 Comments 2020-12-18 12:36:25 +00:00
Aaron Dewes
3e61a40480 Add a Dockerfile 2020-12-18 12:36:25 +00:00
dependabot[bot]
716c8e53a4 Build(deps): Bump ini from 1.3.5 to 1.3.8
Bumps [ini](https://github.com/isaacs/ini) from 1.3.5 to 1.3.8.
- [Release notes](https://github.com/isaacs/ini/releases)
- [Commits](https://github.com/isaacs/ini/compare/v1.3.5...v1.3.8)

Signed-off-by: dependabot[bot] <support@github.com>
2020-12-14 11:47:11 +00:00
snyk-bot
2cb5e95112 fix: upgrade express-rate-limit from 5.1.3 to 5.2.3
Snyk has created this PR to upgrade express-rate-limit from 5.1.3 to 5.2.3.

See this package in npm:
https://www.npmjs.com/package/express-rate-limit

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2020-12-12 18:11:45 +00:00
snyk-bot
99c419e4a6 fix: upgrade prettier from 2.1.2 to 2.2.0
Snyk has created this PR to upgrade prettier from 2.1.2 to 2.2.0.

See this package in npm:
https://www.npmjs.com/package/prettier

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2020-12-12 18:09:58 +00:00
Overtorment
5bce8181e3 Revert "Add Dockerfile example"
This reverts commit e890513e7c.
2020-12-08 18:15:07 +00:00
David Parrish
e890513e7c Add Dockerfile example 2020-12-08 13:12:09 +00:00
Overtorment
7163416dfb OPS 2020-12-04 19:13:59 +00:00
Aaron Dewes
592ff93c93 Update .babelrc 2020-12-04 18:59:57 +00:00
Aaron Dewes
e38f323e07 Update package.json 2020-12-04 18:59:57 +00:00
snyk-bot
ce58175bc0 fix: upgrade ioredis from 4.19.1 to 4.19.2
Snyk has created this PR to upgrade ioredis from 4.19.1 to 4.19.2.

See this package in npm:
https://www.npmjs.com/package/ioredis

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2020-11-23 18:39:48 +00:00
snyk-bot
9faf8bd944 fix: upgrade ioredis from 4.19.0 to 4.19.1
Snyk has created this PR to upgrade ioredis from 4.19.0 to 4.19.1.

See this package in npm:
https://www.npmjs.com/package/ioredis

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2020-11-21 13:23:15 +00:00
snyk-bot
b693c6f1e1 fix: upgrade ioredis from 4.17.3 to 4.19.0
Snyk has created this PR to upgrade ioredis from 4.17.3 to 4.19.0.

See this package in npm:
https://www.npmjs.com/package/ioredis

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2020-11-20 15:28:56 +00:00
snyk-bot
7b71a7ee9a fix: upgrade eslint-config-prettier from 6.14.0 to 6.15.0
Snyk has created this PR to upgrade eslint-config-prettier from 6.14.0 to 6.15.0.

See this package in npm:
https://www.npmjs.com/package/eslint-config-prettier

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2020-11-20 15:23:39 +00:00
snyk-bot
04a4e042b6 fix: upgrade eslint-config-prettier from 6.13.0 to 6.14.0
Snyk has created this PR to upgrade eslint-config-prettier from 6.13.0 to 6.14.0.

See this package in npm:
https://www.npmjs.com/package/eslint-config-prettier

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2020-11-13 12:29:48 +00:00
snyk-bot
3ddda25ea2 fix: package.json & package-lock.json to reduce vulnerabilities
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-JS-GRPC-598671
2020-11-12 11:48:46 +00:00
snyk-bot
e201ce765b fix: upgrade eslint-config-prettier from 6.12.0 to 6.13.0
Snyk has created this PR to upgrade eslint-config-prettier from 6.12.0 to 6.13.0.

See this package in npm:
https://www.npmjs.com/package/eslint-config-prettier

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2020-11-10 18:56:51 +00:00
snyk-bot
ebe2681d3c fix: upgrade eslint-config-prettier from 6.11.0 to 6.12.0
Snyk has created this PR to upgrade eslint-config-prettier from 6.11.0 to 6.12.0.

See this package in npm:
https://www.npmjs.com/package/eslint-config-prettier

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2020-10-23 20:11:10 +01:00
snyk-bot
19e4ae977c fix: upgrade bignumber.js from 9.0.0 to 9.0.1
Snyk has created this PR to upgrade bignumber.js from 9.0.0 to 9.0.1.

See this package in npm:
https://www.npmjs.com/package/bignumber.js

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2020-10-23 20:05:28 +01:00
Overtorment
f4b642f3b2 FIX: undefined amount in pushes to groundcontrol when paying internal invoice 2020-10-20 21:07:26 +01:00
Overtorment
999f0534e0 REF: listtransactions from bitcoind 2020-10-12 18:16:14 +01:00
snyk-bot
ff23e41be7 fix: upgrade prettier from 2.1.1 to 2.1.2
Snyk has created this PR to upgrade prettier from 2.1.1 to 2.1.2.

See this package in npm:
https://www.npmjs.com/package/prettier

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2020-10-12 14:54:59 +01:00
snyk-bot
7d5b38c52e fix: upgrade prettier from 2.1.0 to 2.1.1
Snyk has created this PR to upgrade prettier from 2.1.0 to 2.1.1.

See this package in npm:
https://www.npmjs.com/package/prettier

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2020-09-22 14:51:43 +01:00
snyk-bot
8f162ec522 fix: upgrade prettier from 2.0.5 to 2.1.0
Snyk has created this PR to upgrade prettier from 2.0.5 to 2.1.0.

See this package in npm:
https://www.npmjs.com/package/prettier

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2020-09-21 20:07:00 +01:00
snyk-bot
c440cd1e08 fix: upgrade jayson from 3.3.3 to 3.3.4
Snyk has created this PR to upgrade jayson from 3.3.3 to 3.3.4.

See this package in npm:
https://www.npmjs.com/package/jayson

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2020-09-14 11:52:33 +01:00
Overtorment
988ac805d0 FIX: pass fixed (promised in bolt11) sat amount to groundcontrol instead of delivered by HTLC (closes #99) 2020-09-01 16:01:26 +01:00
Overtorment
d71bedbcd1 FIX: force using specific bitcoind wallet file 2020-08-16 15:18:30 +01:00
snyk-bot
002fd6ffd0 fix: upgrade request-promise from 4.2.5 to 4.2.6
Snyk has created this PR to upgrade request-promise from 4.2.5 to 4.2.6.

See this package in npm:
https://www.npmjs.com/package/request-promise

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2020-08-13 13:15:24 +01:00
Overtorment
5596912faf OPS 2020-08-12 16:58:46 +01:00
Overtorment
091e0f6b3e OPS 2020-08-12 16:45:29 +01:00
Overtorment
a079399759 FIX: race condition in generateAddress (closes #93) 2020-08-03 13:06:05 +01:00
snyk-bot
00f7923568 fix: upgrade frisbee from 3.1.3 to 3.1.4
Snyk has created this PR to upgrade frisbee from 3.1.3 to 3.1.4.

See this package in npm:
https://www.npmjs.com/package/frisbee

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2020-08-02 12:29:34 +01:00
dependabot[bot]
29c1ba913b Build(deps): Bump elliptic from 6.5.2 to 6.5.3
Bumps [elliptic](https://github.com/indutny/elliptic) from 6.5.2 to 6.5.3.
- [Release notes](https://github.com/indutny/elliptic/releases)
- [Commits](https://github.com/indutny/elliptic/compare/v6.5.2...v6.5.3)

Signed-off-by: dependabot[bot] <support@github.com>
2020-07-30 11:36:19 +01:00
snyk-bot
d1ad083316 fix: upgrade winston from 3.3.2 to 3.3.3
Snyk has created this PR to upgrade winston from 3.3.2 to 3.3.3.

See this package in npm:
https://www.npmjs.com/package/winston

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2020-07-24 15:41:38 +01:00
snyk-bot
3f74f3abf3 fix: upgrade winston from 3.2.1 to 3.3.2
Snyk has created this PR to upgrade winston from 3.2.1 to 3.3.2.

See this package in NPM:
https://www.npmjs.com/package/winston

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2020-07-20 15:48:43 +01:00
dependabot[bot]
f528c03d00 Build(deps): Bump lodash from 4.17.15 to 4.17.19
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.15 to 4.17.19.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.15...4.17.19)

Signed-off-by: dependabot[bot] <support@github.com>
2020-07-20 15:33:48 +01:00
Overtorment
f30363ff39 FIX: groundcontrol notifications for internal invoices 2020-07-13 14:43:13 +01:00
Overtorment
17bdf37f9b FIX: clear balance cache when user's invoice was paid (closes #85) 2020-07-13 13:14:57 +01:00
Overtorment
ac14a50137 FIX: deduplicate groundcontrol calls 2020-07-11 15:20:05 +01:00
Overtorment
69ce4d032a ADD: post to GroundControl notification about invoice paid 2020-07-11 14:42:09 +01:00
snyk-bot
9533e43d19 fix: upgrade eslint-plugin-prettier from 3.1.3 to 3.1.4
Snyk has created this PR to upgrade eslint-plugin-prettier from 3.1.3 to 3.1.4.

See this package in NPM:
https://www.npmjs.com/package/eslint-plugin-prettier

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2020-07-06 12:53:10 +01:00
snyk-bot
9108daf5e9 fix: upgrade jayson from 3.3.1 to 3.3.3
Snyk has created this PR to upgrade jayson from 3.3.1 to 3.3.3.

See this package in NPM:
https://www.npmjs.com/package/jayson

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2020-06-30 12:54:32 +01:00
snyk-bot
ec8b28b13d fix: upgrade grpc from 1.24.2 to 1.24.3
Snyk has created this PR to upgrade grpc from 1.24.2 to 1.24.3.

See this package in NPM:
https://www.npmjs.com/package/grpc

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2020-06-26 12:50:28 +01:00
snyk-bot
00561677da fix: upgrade ioredis from 4.17.1 to 4.17.3
Snyk has created this PR to upgrade ioredis from 4.17.1 to 4.17.3.

See this package in NPM:
https://www.npmjs.com/package/ioredis

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2020-06-22 12:24:00 +01:00
snyk-bot
864a00ab1f fix: upgrade jayson from 3.2.1 to 3.3.1
Snyk has created this PR to upgrade jayson from 3.2.1 to 3.3.1.

See this package in NPM:
https://www.npmjs.com/package/jayson

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2020-06-19 12:26:10 +01:00
snyk-bot
c69ad09a70 fix: upgrade ioredis from 4.16.3 to 4.17.1
Snyk has created this PR to upgrade ioredis from 4.16.3 to 4.17.1.

See this package in NPM:
https://www.npmjs.com/package/ioredis

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2020-06-09 17:44:53 +01:00
snyk-bot
b9c5241a55 fix: upgrade express-rate-limit from 5.1.1 to 5.1.3
Snyk has created this PR to upgrade express-rate-limit from 5.1.1 to 5.1.3.

See this package in NPM:
https://www.npmjs.com/package/express-rate-limit

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2020-05-21 14:44:35 +01:00
snyk-bot
a9ee760a40 fix: upgrade express-rate-limit from 5.1.1 to 5.1.3
Snyk has created this PR to upgrade express-rate-limit from 5.1.1 to 5.1.3.

See this package in NPM:
https://www.npmjs.com/package/express-rate-limit

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2020-05-21 14:44:35 +01:00
snyk-bot
046380fdb6 fix: upgrade ioredis from 4.16.2 to 4.16.3
Snyk has created this PR to upgrade ioredis from 4.16.2 to 4.16.3.

See this package in NPM:
https://www.npmjs.com/package/ioredis

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2020-05-15 16:31:56 +01:00
snyk-bot
eec5213624 fix: upgrade ioredis from 4.16.2 to 4.16.3
Snyk has created this PR to upgrade ioredis from 4.16.2 to 4.16.3.

See this package in NPM:
https://www.npmjs.com/package/ioredis

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2020-05-15 16:31:56 +01:00
snyk-bot
8192d892bb fix: upgrade eslint-config-prettier from 6.10.1 to 6.11.0
Snyk has created this PR to upgrade eslint-config-prettier from 6.10.1 to 6.11.0.

See this package in NPM:
https://www.npmjs.com/package/eslint-config-prettier

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2020-05-15 16:31:44 +01:00
snyk-bot
389947ecd5 fix: upgrade eslint-config-prettier from 6.10.1 to 6.11.0
Snyk has created this PR to upgrade eslint-config-prettier from 6.10.1 to 6.11.0.

See this package in NPM:
https://www.npmjs.com/package/eslint-config-prettier

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2020-05-15 16:31:44 +01:00
snyk-bot
0f55b52a33 fix: upgrade prettier from 2.0.4 to 2.0.5
Snyk has created this PR to upgrade prettier from 2.0.4 to 2.0.5.

See this package in NPM:
https://www.npmjs.com/package/prettier

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2020-05-15 16:31:28 +01:00
snyk-bot
d361578301 fix: upgrade prettier from 2.0.4 to 2.0.5
Snyk has created this PR to upgrade prettier from 2.0.4 to 2.0.5.

See this package in NPM:
https://www.npmjs.com/package/prettier

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2020-05-15 16:31:28 +01:00
snyk-bot
ec9fad0738 fix: upgrade jayson from 3.2.0 to 3.2.1
Snyk has created this PR to upgrade jayson from 3.2.0 to 3.2.1.

See this package in NPM:
https://www.npmjs.com/package/jayson

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2020-05-11 15:34:15 +01:00
snyk-bot
5431bcbd15 fix: upgrade jayson from 3.2.0 to 3.2.1
Snyk has created this PR to upgrade jayson from 3.2.0 to 3.2.1.

See this package in NPM:
https://www.npmjs.com/package/jayson

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2020-05-11 15:34:15 +01:00
Overtorment
558c84b7e2 REF: script 2020-05-10 12:12:40 +01:00
Overtorment
9df3ce249b FIX: process locked script 2020-05-06 13:00:33 +01:00
Overtorment
963348102d Merge branch 'master' of github.com:BlueWallet/LndHub 2020-05-06 11:18:01 +01:00
Overtorment
2f5c487f8a FIX: important channels & process locked reduced to 1 day max 2020-05-06 11:17:38 +01:00
snyk-bot
3e45ef30dd fix: upgrade eslint-plugin-prettier from 3.1.2 to 3.1.3
Snyk has created this PR to upgrade eslint-plugin-prettier from 3.1.2 to 3.1.3.

See this package in NPM:
https://www.npmjs.com/package/eslint-plugin-prettier

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2020-05-05 21:33:35 +01:00
snyk-bot
63a99c7147 fix: upgrade eslint-plugin-prettier from 3.1.2 to 3.1.3
Snyk has created this PR to upgrade eslint-plugin-prettier from 3.1.2 to 3.1.3.

See this package in NPM:
https://www.npmjs.com/package/eslint-plugin-prettier

See this project in Snyk:
https://app.snyk.io/org/bluewallet/project/29c066bc-abce-44d9-b68e-064466e610e7?utm_source=github&utm_medium=upgrade-pr
2020-05-05 21:33:35 +01:00
Overtorment
b4a0a7d3d8 REF 2020-05-05 16:05:14 +01:00
Overtorment
30422d9ac7 REF 2020-05-05 08:22:29 +01:00
Overtorment
83f6b08b82 FIX: script oom 2020-05-04 15:11:26 +01:00
39 changed files with 6755 additions and 5478 deletions

View File

@@ -1,3 +1,12 @@
{
"presets": ["es2015"]
"presets": [
[
"@babel/preset-env",
{
"targets": {
"node": true
}
}
]
]
}

View File

@@ -1,16 +1,16 @@
{
"parser": "babel-eslint",
"parser": "@babel/eslint-parser",
"plugins": [
"prettier"
],
"extends": ["prettier"],
"extends": ["plugin:prettier/recommended"],
"rules": {
'prettier/prettier': [
'warn',
"prettier/prettier": [
"warn",
{
singleQuote: true,
printWidth: 140,
trailingComma: 'all'
"singleQuote": true,
"printWidth": 140,
"trailingComma": "all"
}
]
},

49
.github/workflows/push.yml vendored Normal file
View File

@@ -0,0 +1,49 @@
name: Build on push
on:
push:
branches:
- master
env:
DOCKER_CLI_EXPERIMENTAL: enabled
jobs:
build:
name: Build image
runs-on: ubuntu-20.04
steps:
- name: Checkout project
uses: actions/checkout@v2
- name: Set env variables
run: echo "BRANCH=$(echo ${GITHUB_REF#refs/heads/} | sed 's/\//-/g')" >> $GITHUB_ENV
- name: Login to Docker Hub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
id: qemu
- name: Setup Docker buildx action
uses: docker/setup-buildx-action@v1
id: buildx
- name: Show available Docker buildx platforms
run: echo ${{ steps.buildx.outputs.platforms }}
- name: Run Docker buildx
run: |
docker buildx build \
--cache-from "type=local,src=/tmp/.buildx-cache" \
--cache-to "type=local,dest=/tmp/.buildx-cache" \
--platform linux/arm64,linux/amd64 \
--tag ${{ secrets.DOCKER_CONTAINER_USERNAME }}/lndhub:$BRANCH \
--output "type=registry" ./

57
.github/workflows/tag.yml vendored Normal file
View File

@@ -0,0 +1,57 @@
name: Build on push
on:
push:
tags:
- v[0-9]+.[0-9]+.[0-9]+
- v[0-9]+.[0-9]+.[0-9]+-*
env:
DOCKER_CLI_EXPERIMENTAL: enabled
jobs:
build:
name: Build image
runs-on: ubuntu-20.04
steps:
- name: Checkout project
uses: actions/checkout@v2
- name: Set env variables
run: echo "TAG=${GITHUB_REF/refs\/tags\//}" >> $GITHUB_ENV
- name: Login to Docker Hub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
id: qemu
- name: Setup Docker buildx action
uses: docker/setup-buildx-action@v1
id: buildx
- name: Show available Docker buildx platforms
run: echo ${{ steps.buildx.outputs.platforms }}
- name: Run Docker buildx
run: |
docker buildx build \
--cache-from "type=local,src=/tmp/.buildx-cache" \
--cache-to "type=local,dest=/tmp/.buildx-cache" \
--platform linux/arm64,linux/amd64 \
--tag ${{ secrets.DOCKER_CONTAINER_USERNAME }}/lndhub:$TAG \
--output "type=registry" ./
- name: Run Docker buildx
run: |
docker buildx build \
--cache-from "type=local,src=/tmp/.buildx-cache" \
--cache-to "type=local,dest=/tmp/.buildx-cache" \
--platform linux/arm64,linux/amd64 \
--tag ${{ secrets.DOCKER_CONTAINER_USERNAME }}/lndhub:latest \
--output "type=registry" ./

43
Dockerfile Normal file
View File

@@ -0,0 +1,43 @@
FROM alpine:latest AS perms
# This is a bit weird, but required to make sure the LND data can be accessed.
RUN adduser --disabled-password \
--home "/lndhub" \
--gecos "" \
"lndhub"
FROM node:12-buster-slim AS builder
# These packages are required for building LNDHub
RUN apt-get update && apt-get -y install python3
WORKDIR /lndhub
# Copy 'package-lock.json' and 'package.json'
COPY package.json package-lock.json ./
# Install dependencies
RUN npm i
# Copy project files and folders to the current working directory
COPY . .
# Delete git data as it's not needed inside the container
RUN rm -rf .git
FROM node:12-buster-slim
# Create a specific user so LNDHub doesn't run as root
COPY --from=perms /etc/group /etc/passwd /etc/shadow /etc/
# Copy LNDHub with installed modules from builder
COPY --from=builder /lndhub /lndhub
# Create logs folder and ensure permissions are set correctly
RUN mkdir /lndhub/logs && chown -R lndhub:lndhub /lndhub
USER lndhub
ENV PORT=3000
EXPOSE 3000
CMD cp $LND_CERT_FILE /lndhub/ && cp $LND_ADMIN_MACAROON_FILE /lndhub/ && cd /lndhub && npm start

View File

@@ -23,6 +23,9 @@ Copy `admin.macaroon` and `tls.cert` in root folder of LndHub.
`bitcoind` should run with `-deprecatedrpc=accounts`, for now. Lndhub expects Lnd's wallet to be unlocked, if not - it will attempt to unlock it with password stored in `config.lnd.password`.
Don't forget to enable disk-persistance for `redis`.
If you have no `bitcoind` instance, for example if you use neutrino, or you have no bitcoind wallet,
for example if you use LND for wallet managment, you can remove the bitcoind settings from `config.js`.
Please not that this feature is limited to Bitcoin, so you can't use this feature if you use any other cryptocurrency with LND.
### Deploy to Heroku
@@ -31,6 +34,12 @@ Add config vars :
* `MACAROON`: hex-encoded `admin.macaroon`
* `TLSCERT`: hex-encoded `tls.cert`
### Run in docker
LndHub is available on Docker Hub as [`bluewalletorganization/lndhub`](https://hub.docker.com/r/bluewalletorganization/lndhub).
Please note that this requires a separate instance of redis and LND and optionally, bitcoind.
You can also view Umbrel's implementation using docker-compose [here](https://github.com/getumbrel/umbrel/blob/280c87f0f323666b1b0552aeb24f60df94d1e43c/apps/lndhub/docker-compose.yml).
### Reference client implementation
Can be used in ReactNative or Nodejs environment

View File

@@ -2,6 +2,10 @@
const config = require('./config');
let jayson = require('jayson/promise');
let url = require('url');
let rpc = url.parse(config.bitcoind.rpc);
rpc.timeout = 15000;
module.exports = jayson.client.http(rpc);
if (config.bitcoind) {
let rpc = url.parse(config.bitcoind.rpc);
rpc.timeout = 15000;
module.exports = jayson.client.http(rpc);
} else {
module.exports = {};
}

79
btc-decoder.js Normal file
View File

@@ -0,0 +1,79 @@
const bitcoin = require('bitcoinjs-lib');
const classify = require('bitcoinjs-lib/src/classify');
const decodeFormat = (tx) => ({
txid: tx.getId(),
version: tx.version,
locktime: tx.locktime,
});
const decodeInput = function (tx) {
const result = [];
tx.ins.forEach(function (input, n) {
result.push({
txid: input.hash.reverse().toString('hex'),
n: input.index,
script: bitcoin.script.toASM(input.script),
sequence: input.sequence,
});
});
return result;
};
const decodeOutput = function (tx, network) {
const format = function (out, n, network) {
const vout = {
satoshi: out.value,
value: (1e-8 * out.value).toFixed(8),
n: n,
scriptPubKey: {
asm: bitcoin.script.toASM(out.script),
hex: out.script.toString('hex'),
type: classify.output(out.script),
addresses: [],
},
};
switch (vout.scriptPubKey.type) {
case 'pubkeyhash':
case 'scripthash':
vout.scriptPubKey.addresses.push(bitcoin.address.fromOutputScript(out.script, network));
break;
case 'witnesspubkeyhash':
case 'witnessscripthash':
const data = bitcoin.script.decompile(out.script)[1];
vout.scriptPubKey.addresses.push(bitcoin.address.toBech32(data, 0, network.bech32));
break;
}
return vout;
};
const result = [];
tx.outs.forEach(function (out, n) {
result.push(format(out, n, network));
});
return result;
};
class TxDecoder {
constructor(rawTx, network = bitcoin.networks.bitcoin) {
this.tx = bitcoin.Transaction.fromHex(rawTx);
this.format = decodeFormat(this.tx);
this.inputs = decodeInput(this.tx);
this.outputs = decodeOutput(this.tx, network);
}
decode() {
const result = {};
const self = this;
Object.keys(self.format).forEach(function (key) {
result[key] = self.format[key];
});
result.outputs = self.outputs;
result.inputs = self.inputs;
return result;
}
}
module.exports.decodeRawHex = (rawTx, network = bitcoin.networks.bitcoin) => {
return new TxDecoder(rawTx, network).decode();
};

View File

@@ -1,3 +1,4 @@
var crypto = require('crypto');
var lightningPayReq = require('bolt11');
export class Invo {
@@ -37,7 +38,7 @@ export class Invo {
}
}
if (!paymentHash) throw new Error('Could not find payment hash in invoice tags');
return await this._setIsPaymentHashPaidInDatabase(paymentHash, true);
return await this._setIsPaymentHashPaidInDatabase(paymentHash, decoded.satoshis);
}
async markAsUnpaidInDatabase() {
@@ -53,9 +54,9 @@ export class Invo {
return await this._setIsPaymentHashPaidInDatabase(paymentHash, false);
}
async _setIsPaymentHashPaidInDatabase(paymentHash, isPaid) {
if (isPaid) {
return await this._redis.set('ispaid_' + paymentHash, 1);
async _setIsPaymentHashPaidInDatabase(paymentHash, settleAmountSat) {
if (settleAmountSat) {
return await this._redis.set('ispaid_' + paymentHash, settleAmountSat);
} else {
return await this._redis.del('ispaid_' + paymentHash);
}
@@ -65,6 +66,31 @@ export class Invo {
return await this._redis.get('ispaid_' + paymentHash);
}
async getPreimage() {
if (!this._bolt11) throw new Error('bolt11 is not provided');
const decoded = lightningPayReq.decode(this._bolt11);
let paymentHash = false;
for (const tag of decoded.tags) {
if (tag.tagName === 'payment_hash') {
paymentHash = tag.data;
}
}
if (!paymentHash) throw new Error('Could not find payment hash in invoice tags');
return await this._redis.get('preimage_for_' + paymentHash);
}
async savePreimage(preimageHex) {
const paymentHashHex = require('crypto').createHash('sha256').update(Buffer.from(preimageHex, 'hex')).digest('hex');
const key = 'preimage_for_' + paymentHashHex;
await this._redis.set(key, preimageHex);
await this._redis.expire(key, 3600 * 24 * 30); // 1 month
}
makePreimageHex() {
let buffer = crypto.randomBytes(32);
return buffer.toString('hex');
}
/**
* Queries LND ofr all user invoices
*
@@ -74,9 +100,10 @@ export class Invo {
return new Promise((resolve, reject) => {
this._lightning.listInvoices(
{
num_max_invoices: 9000111,
num_max_invoices: 99000111,
reversed: true,
},
function(err, response) {
function (err, response) {
if (err) return reject(err);
resolve(response);
},

View File

@@ -22,8 +22,8 @@ export class Paym {
async decodePayReqViaRpc(invoice) {
let that = this;
return new Promise(function(resolve, reject) {
that._lightning.decodePayReq({ pay_req: invoice }, function(err, info) {
return new Promise(function (resolve, reject) {
that._lightning.decodePayReq({ pay_req: invoice }, function (err, info) {
if (err) return reject(err);
that._decoded = info;
return resolve(info);
@@ -42,8 +42,8 @@ export class Paym {
fee_limit: { fixed: Math.floor(this._decoded.num_satoshis * 0.01) + 1 },
};
let that = this;
return new Promise(function(resolve, reject) {
that._lightning.queryRoutes(request, function(err, response) {
return new Promise(function (resolve, reject) {
that._lightning.queryRoutes(request, function (err, response) {
if (err) return reject(err);
resolve(response);
});
@@ -62,8 +62,8 @@ export class Paym {
console.log('sendToRouteSync:', { request });
let that = this;
return new Promise(function(resolve, reject) {
that._lightning.sendToRouteSync(request, function(err, response) {
return new Promise(function (resolve, reject) {
that._lightning.sendToRouteSync(request, function (err, response) {
if (err) reject(err);
resolve(that.processSendPaymentResponse(response));
});
@@ -105,6 +105,10 @@ export class Paym {
this._isPaid = false;
}
if (payment.payment_error && payment.payment_error.indexOf('IncorrectOrUnknownPaymentDetails') !== -1) {
this._isPaid = false;
}
if (payment.payment_error && payment.payment_error.indexOf('payment is in transition') !== -1) {
this._isPaid = null; // null is default, but lets set it anyway
}
@@ -129,7 +133,7 @@ export class Paym {
async listPayments() {
return new Promise((resolve, reject) => {
this._lightning.listPayments({}, function(err, response) {
this._lightning.listPayments({}, function (err, response) {
if (err) return reject(err);
resolve(response);
});

View File

@@ -3,6 +3,8 @@ import { Lock } from './Lock';
var crypto = require('crypto');
var lightningPayReq = require('bolt11');
import { BigNumber } from 'bignumber.js';
import { decodeRawHex } from '../btc-decoder';
const config = require('../config');
// static cache:
let _invoice_ispaid_cache = {};
@@ -107,17 +109,28 @@ export class User {
* @returns {Promise<any>}
*/
async generateAddress() {
let lock = new Lock(this._redis, 'generating_address_' + this._userid);
if (!(await lock.obtainLock())) {
// someone's already generating address
return;
}
let self = this;
return new Promise(function(resolve, reject) {
self._lightning.newAddress({ type: 0 }, async function(err, response) {
if (err) return reject('LND failure');
return new Promise(function (resolve, reject) {
self._lightning.newAddress({ type: 0 }, async function (err, response) {
if (err) return reject('LND failure when trying to generate new address');
await self.addAddress(response.address);
self._bitcoindrpc.request('importaddress', [response.address, response.address, false]);
if (config.bitcoind) self._bitcoindrpc.request('importaddress', [response.address, response.address, false]);
resolve();
});
});
}
async watchAddress(address) {
if (!address) return;
if (config.bitcoind) return this._bitcoindrpc.request('importaddress', [address, address, false]);
}
/**
* LndHub no longer relies on redis balance as source of truth, this is
* more a cache now. See `this.getCalculatedBalance()` to get correct balance.
@@ -215,14 +228,14 @@ export class User {
* @see Invo._setIsPaymentHashPaidInDatabase
* @see Invo.markAsPaidInDatabase
*/
async setPaymentHashPaid(payment_hash) {
return await this._redis.set('ispaid_' + payment_hash, 1);
async setPaymentHashPaid(payment_hash, settleAmountSat) {
return await this._redis.set('ispaid_' + payment_hash, settleAmountSat);
}
async lookupInvoice(payment_hash) {
let that = this;
return new Promise(function(resolve, reject) {
that._lightning.lookupInvoice({ r_hash_str: payment_hash }, function(err, response) {
return new Promise(function (resolve, reject) {
that._lightning.lookupInvoice({ r_hash_str: payment_hash }, function (err, response) {
if (err) resolve({});
resolve(response);
});
@@ -243,7 +256,7 @@ export class User {
const ispaid = invoice.settled; // TODO: start using `state` instead as its future proof, and this one might get deprecated
if (ispaid) {
// so invoice was paid after all
await this.setPaymentHashPaid(payment_hash);
await this.setPaymentHashPaid(payment_hash, invoice.amt_paid_msat ? Math.floor(invoice.amt_paid_msat / 1000) : invoice.amt_paid_sat);
await this.clearBalanceCache();
}
return ispaid;
@@ -272,17 +285,31 @@ export class User {
}
}
invoice.ispaid = _invoice_ispaid_cache[invoice.payment_hash] || !!(await this.getPaymentHashPaid(invoice.payment_hash));
let paymentHashPaidAmountSat = 0;
if (_invoice_ispaid_cache[invoice.payment_hash]) {
// static cache hit
invoice.ispaid = true;
paymentHashPaidAmountSat = _invoice_ispaid_cache[invoice.payment_hash];
} else {
// static cache miss, asking redis cache
paymentHashPaidAmountSat = await this.getPaymentHashPaid(invoice.payment_hash);
if (paymentHashPaidAmountSat) invoice.ispaid = true;
}
if (!invoice.ispaid) {
if (decoded && decoded.timestamp > +new Date() / 1000 - 3600 * 24 * 5) {
// if invoice is not too old we query lnd to find out if its paid
invoice.ispaid = await this.syncInvoicePaid(invoice.payment_hash);
paymentHashPaidAmountSat = await this.getPaymentHashPaid(invoice.payment_hash); // since we have just saved it
}
} else {
_invoice_ispaid_cache[invoice.payment_hash] = true;
_invoice_ispaid_cache[invoice.payment_hash] = paymentHashPaidAmountSat;
}
invoice.amt = decoded.satoshis;
invoice.amt =
paymentHashPaidAmountSat && parseInt(paymentHashPaidAmountSat) > decoded.satoshis
? parseInt(paymentHashPaidAmountSat)
: decoded.satoshis;
invoice.expire_time = 3600 * 24;
// ^^^default; will keep for now. if we want to un-hardcode it - it should be among tags (`expire_time`)
invoice.timestamp = decoded.timestamp;
@@ -304,12 +331,7 @@ export class User {
* @returns {Promise<Array>}
*/
async getTxs() {
let addr = await this.getAddress();
if (!addr) {
await this.generateAddress();
addr = await this.getAddress();
}
if (!addr) throw new Error('cannot get transactions: no onchain address assigned to user');
const addr = await this.getOrGenerateAddress();
let txs = await this._listtransactions();
txs = txs.result;
let result = [];
@@ -379,22 +401,63 @@ export class User {
}
}
let txs = await this._bitcoindrpc.request('listtransactions', ['*', 100500, 0, true]);
// now, compacting response a bit
let ret = { result: [] };
for (const tx of txs.result) {
ret.result.push({
category: tx.category,
amount: tx.amount,
confirmations: tx.confirmations,
address: tx.address,
time: tx.time,
});
try {
let ret = { result: [] };
if (config.bitcoind) {
let txs = await this._bitcoindrpc.request('listtransactions', ['*', 100500, 0, true]);
// now, compacting response a bit
for (const tx of txs.result) {
ret.result.push({
category: tx.category,
amount: tx.amount,
confirmations: tx.confirmations,
address: tx.address,
time: tx.blocktime || tx.time,
});
}
} else {
let txs = await this._getChainTransactions();
ret.result.push(...txs);
}
_listtransactions_cache = JSON.stringify(ret);
_listtransactions_cache_expiry_ts = +new Date() + 5 * 60 * 1000; // 5 min
this._redis.set('listtransactions', _listtransactions_cache);
return ret;
} catch (error) {
console.warn('listtransactions error:', error);
let _listtransactions_cache = await this._redis.get('listtransactions');
if (!_listtransactions_cache) return { result: [] };
return JSON.parse(_listtransactions_cache);
}
_listtransactions_cache = JSON.stringify(ret);
_listtransactions_cache_expiry_ts = +new Date() + 5 * 60 * 1000; // 5 min
this._redis.set('listtransactions', _listtransactions_cache); // backup, will use later TODO
return ret;
}
async _getChainTransactions() {
return new Promise((resolve, reject) => {
this._lightning.getTransactions({}, (err, data) => {
if (err) return reject(err);
const { transactions } = data;
const outTxns = [];
// on lightning incoming transactions have no labels
// for now filter out known labels to reduce transactions
transactions
.filter((tx) => tx.label !== 'external' && !tx.label.includes('openchannel'))
.map((tx) => {
const decodedTx = decodeRawHex(tx.raw_tx_hex);
decodedTx.outputs.forEach((vout) =>
outTxns.push({
// mark all as received, since external is filtered out
category: 'receive',
confirmations: tx.num_confirmations,
amount: Number(vout.value),
address: vout.scriptPubKey.addresses[0],
time: tx.time_stamp,
}),
);
});
resolve(outTxns);
});
});
}
/**
@@ -403,12 +466,7 @@ export class User {
* @returns {Promise<Array>}
*/
async getPendingTxs() {
let addr = await this.getAddress();
if (!addr) {
await this.generateAddress();
addr = await this.getAddress();
}
if (!addr) throw new Error('cannot get transactions: no onchain address assigned to user');
const addr = await this.getOrGenerateAddress();
let txs = await this._listtransactions();
txs = txs.result;
let result = [];
@@ -527,12 +585,18 @@ export class User {
return result;
}
async getOrGenerateAddress() {
let addr = await this.getAddress();
if (!addr) {
await this.generateAddress();
addr = await this.getAddress();
}
if (!addr) throw new Error('cannot get transactions: no onchain address assigned to user');
return addr;
}
_hash(string) {
return crypto
.createHash('sha256')
.update(string)
.digest()
.toString('hex');
return crypto.createHash('sha256').update(string).digest().toString('hex');
}
/**
@@ -548,6 +612,6 @@ export class User {
}
static async _sleep(s) {
return new Promise(r => setTimeout(r, s * 1000));
return new Promise((r) => setTimeout(r, s * 1000));
}
}

View File

@@ -1,6 +1,9 @@
let config = {
enableUpdateDescribeGraph: false,
postRateLimit: 100,
rateLimit: 200,
bitcoind: {
rpc: 'http://login:password@1.1.1.1:8332',
rpc: 'http://login:password@1.1.1.1:8332/wallet/wallet.dat',
},
redis: {
port: 12914,

View File

@@ -1,14 +1,16 @@
import { User, Lock, Paym } from '../class/';
import { User, Lock, Paym, Invo } from '../class/';
import Frisbee from 'frisbee';
const config = require('../config');
let express = require('express');
let router = express.Router();
let logger = require('../utils/logger');
const MIN_BTC_BLOCK = 670000;
console.log('using config', JSON.stringify(config));
var Redis = require('ioredis');
var redis = new Redis(config.redis);
redis.monitor(function(err, monitor) {
monitor.on('monitor', function(time, args, source, database) {
redis.monitor(function (err, monitor) {
monitor.on('monitor', function (time, args, source, database) {
// console.log('REDIS', JSON.stringify(args));
});
});
@@ -18,50 +20,118 @@ let lightning = require('../lightning');
let identity_pubkey = false;
// ###################### SMOKE TESTS ########################
bitcoinclient.request('getblockchaininfo', false, function(err, info) {
if (info && info.result && info.result.blocks) {
if (info.result.chain === 'mainnet' && info.result.blocks < 550000) {
console.error('bitcoind is not caught up');
process.exit(1);
if (config.bitcoind) {
bitcoinclient.request('getblockchaininfo', false, function (err, info) {
if (info && info.result && info.result.blocks) {
if (info.result.chain === 'mainnet' && info.result.blocks < MIN_BTC_BLOCK && !config.forceStart) {
console.error('bitcoind is not caught up');
process.exit(1);
}
console.log('bitcoind getblockchaininfo:', info);
} else {
console.error('bitcoind failure:', err, info);
process.exit(2);
}
} else {
console.error('bitcoind failure:', err, info);
process.exit(2);
}
});
});
}
lightning.getInfo({}, function(err, info) {
lightning.getInfo({}, function (err, info) {
if (err) {
console.error('lnd failure');
console.dir(err);
process.exit(3);
}
if (info) {
console.info(info);
if (!info.synced_to_chain) {
console.info('lnd getinfo:', info);
if (!info.synced_to_chain && !config.forceStart) {
console.error('lnd not synced');
process.exit(4);
// process.exit(4);
}
identity_pubkey = info.identity_pubkey;
}
});
redis.info(function(err, info) {
redis.info(function (err, info) {
if (err || !info) {
console.error('redis failure');
process.exit(5);
}
});
const subscribeInvoicesCallCallback = async function (response) {
if (response.state === 'SETTLED') {
const LightningInvoiceSettledNotification = {
memo: response.memo,
preimage: response.r_preimage.toString('hex'),
hash: response.r_hash.toString('hex'),
amt_paid_sat: response.amt_paid_msat ? Math.floor(response.amt_paid_msat / 1000) : response.amt_paid_sat,
};
// obtaining a lock, to make sure we push to groundcontrol only once
// since this web server can have several instances running, and each will get the same callback from LND
// and dont release the lock - it will autoexpire in a while
let lock = new Lock(redis, 'groundcontrol_hash_' + LightningInvoiceSettledNotification.hash);
if (!(await lock.obtainLock())) {
return;
}
let invoice = new Invo(redis, bitcoinclient, lightning);
await invoice._setIsPaymentHashPaidInDatabase(
LightningInvoiceSettledNotification.hash,
LightningInvoiceSettledNotification.amt_paid_sat || 1,
);
const user = new User(redis, bitcoinclient, lightning);
user._userid = await user.getUseridByPaymentHash(LightningInvoiceSettledNotification.hash);
await user.clearBalanceCache();
console.log('payment', LightningInvoiceSettledNotification.hash, 'was paid, posting to GroundControl...');
const baseURI = process.env.GROUNDCONTROL;
if (!baseURI) return;
const _api = new Frisbee({ baseURI: baseURI });
const apiResponse = await _api.post(
'/lightningInvoiceGotSettled',
Object.assign(
{},
{
headers: {
'Access-Control-Allow-Origin': '*',
'Content-Type': 'application/json',
},
body: LightningInvoiceSettledNotification,
},
),
);
console.log('GroundControl:', apiResponse.originalResponse.status);
}
};
let subscribeInvoicesCall = lightning.subscribeInvoices({});
subscribeInvoicesCall.on('data', subscribeInvoicesCallCallback);
subscribeInvoicesCall.on('status', function (status) {
// The current status of the stream.
});
subscribeInvoicesCall.on('end', function () {
// The server has closed the stream.
});
let lightningDescribeGraph = {};
function updateDescribeGraph() {
console.log('updateDescribeGraph()');
lightning.describeGraph({ include_unannounced: true }, function (err, response) {
if (!err) lightningDescribeGraph = response;
console.log('updated graph');
});
}
if (config.enableUpdateDescribeGraph) {
updateDescribeGraph();
setInterval(updateDescribeGraph, 120000);
}
// ######################## ROUTES ########################
const rateLimit = require('express-rate-limit');
const postLimiter = rateLimit({
windowMs: 30 * 60 * 1000,
max: 100,
max: config.postRateLimit || 100,
});
router.post('/create', postLimiter, async function(req, res) {
router.post('/create', postLimiter, async function (req, res) {
logger.log('/create', [req.id]);
if (!(req.body.partnerid && req.body.partnerid === 'bluewallet' && req.body.accounttype)) return errorBadArguments(res);
@@ -71,7 +141,7 @@ router.post('/create', postLimiter, async function(req, res) {
res.send({ login: u.getLogin(), password: u.getPassword() });
});
router.post('/auth', postLimiter, async function(req, res) {
router.post('/auth', postLimiter, async function (req, res) {
logger.log('/auth', [req.id]);
if (!((req.body.login && req.body.password) || req.body.refresh_token)) return errorBadArguments(res);
@@ -92,7 +162,7 @@ router.post('/auth', postLimiter, async function(req, res) {
}
});
router.post('/addinvoice', postLimiter, async function(req, res) {
router.post('/addinvoice', postLimiter, async function (req, res) {
logger.log('/addinvoice', [req.id]);
let u = new User(redis, bitcoinclient, lightning);
if (!(await u.loadByAuthorization(req.headers.authorization))) {
@@ -102,17 +172,23 @@ router.post('/addinvoice', postLimiter, async function(req, res) {
if (!req.body.amt || /*stupid NaN*/ !(req.body.amt > 0)) return errorBadArguments(res);
lightning.addInvoice({ memo: req.body.memo, value: req.body.amt, expiry: 3600 * 24 }, async function(err, info) {
if (err) return errorLnd(res);
const invoice = new Invo(redis, bitcoinclient, lightning);
const r_preimage = invoice.makePreimageHex();
lightning.addInvoice(
{ memo: req.body.memo, value: req.body.amt, expiry: 3600 * 24, r_preimage: Buffer.from(r_preimage, 'hex').toString('base64') },
async function (err, info) {
if (err) return errorLnd(res);
info.pay_req = info.payment_request; // client backwards compatibility
await u.saveUserInvoice(info);
info.pay_req = info.payment_request; // client backwards compatibility
await u.saveUserInvoice(info);
await invoice.savePreimage(r_preimage);
res.send(info);
});
res.send(info);
},
);
});
router.post('/payinvoice', async function(req, res) {
router.post('/payinvoice', async function (req, res) {
let u = new User(redis, bitcoinclient, lightning);
if (!(await u.loadByAuthorization(req.headers.authorization))) {
return errorBadAuth(res);
@@ -142,7 +218,7 @@ router.post('/payinvoice', async function(req, res) {
return errorTryAgainLater(res);
}
lightning.decodePayReq({ pay_req: req.body.invoice }, async function(err, info) {
lightning.decodePayReq({ pay_req: req.body.invoice }, async function (err, info) {
if (err) {
await lock.releaseLock();
return errorNotAValidInvoice(res);
@@ -188,8 +264,21 @@ router.post('/payinvoice', async function(req, res) {
pay_req: req.body.invoice,
});
await UserPayee.setPaymentHashPaid(info.payment_hash);
const invoice = new Invo(redis, bitcoinclient, lightning);
invoice.setInvoice(req.body.invoice);
await invoice.markAsPaidInDatabase();
// now, faking LND callback about invoice paid:
const preimage = await invoice.getPreimage();
if (preimage) {
subscribeInvoicesCallCallback({
state: 'SETTLED',
memo: info.description,
r_preimage: Buffer.from(preimage, 'hex'),
r_hash: Buffer.from(info.payment_hash, 'hex'),
amt_paid_sat: +info.num_satoshis,
});
}
await lock.releaseLock();
return res.send(info);
}
@@ -197,7 +286,7 @@ router.post('/payinvoice', async function(req, res) {
// else - regular lightning network payment:
var call = lightning.sendPayment();
call.on('data', async function(payment) {
call.on('data', async function (payment) {
// payment callback
await u.unlockFunds(req.body.invoice);
if (payment && payment.payment_route && payment.payment_route.total_amt_msat) {
@@ -239,7 +328,7 @@ router.post('/payinvoice', async function(req, res) {
});
});
router.get('/getbtc', async function(req, res) {
router.get('/getbtc', async function (req, res) {
logger.log('/getbtc', [req.id]);
let u = new User(redis, bitcoinclient, lightning);
await u.loadByAuthorization(req.headers.authorization);
@@ -253,11 +342,12 @@ router.get('/getbtc', async function(req, res) {
await u.generateAddress();
address = await u.getAddress();
}
u.watchAddress(address);
res.send([{ address }]);
});
router.get('/checkpayment/:payment_hash', async function(req, res) {
router.get('/checkpayment/:payment_hash', async function (req, res) {
logger.log('/checkpayment', [req.id]);
let u = new User(redis, bitcoinclient, lightning);
await u.loadByAuthorization(req.headers.authorization);
@@ -267,16 +357,17 @@ router.get('/checkpayment/:payment_hash', async function(req, res) {
}
let paid = true;
if (!(await u.getPaymentHashPaid(req.params.payment_hash))) { // Not found on cache
if (!(await u.getPaymentHashPaid(req.params.payment_hash))) {
// Not found on cache
paid = await u.syncInvoicePaid(req.params.payment_hash);
}
res.send({paid: paid});
res.send({ paid: paid });
});
router.get('/balance', postLimiter, async function(req, res) {
router.get('/balance', postLimiter, async function (req, res) {
let u = new User(redis, bitcoinclient, lightning);
try {
logger.log('/balance', [req.id]);
let u = new User(redis, bitcoinclient, lightning);
if (!(await u.loadByAuthorization(req.headers.authorization))) {
return errorBadAuth(res);
}
@@ -288,25 +379,25 @@ router.get('/balance', postLimiter, async function(req, res) {
if (balance < 0) balance = 0;
res.send({ BTC: { AvailableBalance: balance } });
} catch (Error) {
logger.log('', [req.id, 'error getting balance:', Error.message, 'userid:', u.getUserId()]);
logger.log('', [req.id, 'error getting balance:', Error, 'userid:', u.getUserId()]);
return errorGeneralServerError(res);
}
});
router.get('/getinfo', postLimiter, async function(req, res) {
router.get('/getinfo', postLimiter, async function (req, res) {
logger.log('/getinfo', [req.id]);
let u = new User(redis, bitcoinclient, lightning);
if (!(await u.loadByAuthorization(req.headers.authorization))) {
return errorBadAuth(res);
}
lightning.getInfo({}, function(err, info) {
lightning.getInfo({}, function (err, info) {
if (err) return errorLnd(res);
res.send(info);
});
});
router.get('/gettxs', async function(req, res) {
router.get('/gettxs', async function (req, res) {
logger.log('/gettxs', [req.id]);
let u = new User(redis, bitcoinclient, lightning);
if (!(await u.loadByAuthorization(req.headers.authorization))) {
@@ -335,7 +426,7 @@ router.get('/gettxs', async function(req, res) {
}
});
router.get('/getuserinvoices', postLimiter, async function(req, res) {
router.get('/getuserinvoices', postLimiter, async function (req, res) {
logger.log('/getuserinvoices', [req.id]);
let u = new User(redis, bitcoinclient, lightning);
if (!(await u.loadByAuthorization(req.headers.authorization))) {
@@ -352,7 +443,7 @@ router.get('/getuserinvoices', postLimiter, async function(req, res) {
}
});
router.get('/getpending', async function(req, res) {
router.get('/getpending', async function (req, res) {
logger.log('/getpending', [req.id]);
let u = new User(redis, bitcoinclient, lightning);
if (!(await u.loadByAuthorization(req.headers.authorization))) {
@@ -366,7 +457,7 @@ router.get('/getpending', async function(req, res) {
res.send(txs);
});
router.get('/decodeinvoice', async function(req, res) {
router.get('/decodeinvoice', async function (req, res) {
logger.log('/decodeinvoice', [req.id]);
let u = new User(redis, bitcoinclient, lightning);
if (!(await u.loadByAuthorization(req.headers.authorization))) {
@@ -375,13 +466,13 @@ router.get('/decodeinvoice', async function(req, res) {
if (!req.query.invoice) return errorGeneralServerError(res);
lightning.decodePayReq({ pay_req: req.query.invoice }, function(err, info) {
lightning.decodePayReq({ pay_req: req.query.invoice }, function (err, info) {
if (err) return errorNotAValidInvoice(res);
res.send(info);
});
});
router.get('/checkrouteinvoice', async function(req, res) {
router.get('/checkrouteinvoice', async function (req, res) {
logger.log('/checkrouteinvoice', [req.id]);
let u = new User(redis, bitcoinclient, lightning);
if (!(await u.loadByAuthorization(req.headers.authorization))) {
@@ -392,12 +483,39 @@ router.get('/checkrouteinvoice', async function(req, res) {
// at the momment does nothing.
// TODO: decode and query actual route to destination
lightning.decodePayReq({ pay_req: req.query.invoice }, function(err, info) {
lightning.decodePayReq({ pay_req: req.query.invoice }, function (err, info) {
if (err) return errorNotAValidInvoice(res);
res.send(info);
});
});
router.get('/queryroutes/:source/:dest/:amt', async function (req, res) {
logger.log('/queryroutes', [req.id]);
let request = {
pub_key: req.params.dest,
amt: req.params.amt,
source_pub_key: req.params.source,
};
lightning.queryRoutes(request, function (err, response) {
console.log(JSON.stringify(response, null, 2));
res.send(response);
});
});
router.get('/getchaninfo/:chanid', async function (req, res) {
logger.log('/getchaninfo', [req.id]);
if (lightningDescribeGraph && lightningDescribeGraph.edges) {
for (const edge of lightningDescribeGraph.edges) {
if (edge.channel_id == req.params.chanid) {
return res.send(JSON.stringify(edge, null, 2));
}
}
}
res.send('');
});
module.exports = router;
// ################# HELPERS ###########################

View File

@@ -1,37 +1,41 @@
let express = require('express');
let router = express.Router();
let fs = require('fs');
let mustache = require('mustache');
let lightning = require('../lightning');
let logger = require('../utils/logger');
const express = require('express');
const router = express.Router();
const fs = require('fs');
const mustache = require('mustache');
const lightning = require('../lightning');
const logger = require('../utils/logger');
const qr = require('qr-image');
let lightningGetInfo = {};
let lightningListChannels = {};
function updateLightning() {
console.log('updateLightning()');
try {
lightning.getInfo({}, function(err, info) {
if (err) {
console.error('lnd failure:', err);
}
lightningGetInfo = info;
});
lightning.listChannels({}, function(err, response) {
lightning.getInfo({}, function (err, info) {
if (err) {
console.error('lnd failure:', err);
return;
}
lightningGetInfo = info;
});
lightning.listChannels({}, function (err, response) {
if (err) {
console.error('lnd failure:', err);
return;
}
console.log('updated');
lightningListChannels = response;
let channels = [];
let max_chan_capacity = -1;
for (const channel of lightningListChannels.channels) {
max_chan_capacity = Math.max(max_chan_capacity, channel.capacity);
}
for (let channel of lightningListChannels.channels) {
let divider = 5242870;
let ascii_length1 = channel.local_balance / divider;
let ascii_length2 = channel.remote_balance / divider;
channel.ascii = '[';
channel.ascii += '-'.repeat(Math.round(ascii_length1));
channel.ascii += '/' + '-'.repeat(Math.round(ascii_length2));
channel.ascii += ']';
let magic = max_chan_capacity / 100;
channel.local = channel.local_balance * 1;
channel.total = channel.capacity * 1;
channel.size = Math.round(channel.capacity / magic); // total size of the bar on page. 100% means it takes maximum width
channel.capacity_btc = channel.capacity / 100000000;
channel.name = pubkey2name[channel.remote_pubkey];
if (channel.name) {
@@ -45,7 +49,6 @@ function updateLightning() {
} catch (Err) {
console.log(Err);
}
console.log('updated');
}
updateLightning();
setInterval(updateLightning, 60000);
@@ -67,6 +70,7 @@ const pubkey2name = {
'026c7d28784791a4b31a64eb34d9ab01552055b795919165e6ae886de637632efb': 'LivingRoomOfSatoshi',
'02816caed43171d3c9854e3b0ab2cf0c42be086ff1bd4005acc2a5f7db70d83774': 'ln.pizza',
'0254ff808f53b2f8c45e74b70430f336c6c76ba2f4af289f48d6086ae6e60462d3': 'bitrefill thor',
'03d607f3e69fd032524a867b288216bfab263b6eaee4e07783799a6fe69bb84fac': 'bitrefill 3',
'02a0bc43557fae6af7be8e3a29fdebda819e439bea9c0f8eb8ed6a0201f3471ca9': 'LightningPeachHub',
'02d4531a2f2e6e5a9033d37d548cff4834a3898e74c3abe1985b493c42ebbd707d': 'coinfinity.co',
'02d23fa6794d8fd056c757f3c8f4877782138dafffedc831fc570cab572620dc61': 'paywithmoon.com',
@@ -78,7 +82,7 @@ const pubkey2name = {
'037cc5f9f1da20ac0d60e83989729a204a33cc2d8e80438969fadf35c1c5f1233b': 'lnd2.bluewallet.io',
};
router.get('/', function(req, res) {
router.get('/', function (req, res) {
logger.log('/', [req.id]);
if (!lightningGetInfo) {
console.error('lnd failure');
@@ -89,14 +93,18 @@ router.get('/', function(req, res) {
return res.status(200).send(mustache.render(html, Object.assign({}, lightningGetInfo, lightningListChannels)));
});
router.get('/about', function(req, res) {
logger.log('/about', [req.id]);
let html = fs.readFileSync('./templates/about.html').toString('utf8');
res.setHeader('Content-Type', 'text/html');
return res.status(200).send(mustache.render(html, {}));
router.get('/qr', function (req, res) {
let host = req.headers.host;
if (process.env.TOR_URL) {
host = process.env.TOR_URL;
}
const url = 'bluewallet:setlndhuburl?url=' + encodeURIComponent(req.protocol + '://' + host);
var code = qr.image(url, { type: 'png' });
res.setHeader('Content-type', 'image/png');
code.pipe(res);
});
router.use(function(req, res) {
router.use(function (req, res) {
res.status(404).send('404');
});

View File

@@ -512,25 +512,3 @@ Oauth2 process consists of such stages as:
- Token service checks user id and secret and sends token data with refresh token to Authorization service which sends it to Client
- Client uses token to access protected resources (GET ?access_token=XXXXXXXXXXXXXX)
- When token expires or needs to refresh token for security issues Client sends refresh_token to Token service (POST /auth?type=refresh_token), which sends new token data with refresh_token and disables to access old
```
Добавил POST метод /addinvoice для того, чтобы пользователь мог создать свой инвойс
в боди передаются параметы:
{
"amt": "string" обязательный
"memo":"string" не обязательный
"receipt":"string" не обязательный
"preimage": "string" не обязательный
"fallbackAddr": "string" не обязательны
"expiry": "string" не обязательны
"private": "string" не обязательны
}
информация по инвойсам, которые оплатили пользователям досутпна через метод GET /getuserinvoices , полученные коины учитываются в балансе (settled в unconfirmed balance, остальной в confirmed balance)
```

View File

@@ -11,6 +11,8 @@ User storage schema
* refresh_token_for_{userid} = {access_token}
* importing_{txid} = 1 `atomic lock when processing topup tx`
* invoice_paying_for_{userid} = 1 `lock for when payinvoice is in progress`
* generating_address_{userid} = 1 `lock for address generation`
* preimage_for_{payment_hash_hex} = {preimage_hex} `ttl 1 month`
@@ -26,6 +28,13 @@ User storage schema
* metadata_for_{userid}= {serialized json}
* userinvoices_for_{userid} = []
* payment_hash_{payment_hash} = {userid}
* ispaid_{payment_hash} = 1
* ispaid_{payment_hash} = {settleAmountSat}
####cleanup test user
* del locked_payments_for_666
* del txs_for_666
* del invoice_paying_for_666
* del userinvoices_for_666
* del balance_for_666

View File

@@ -1,4 +1,4 @@
process.on('uncaughtException', function(err) {
process.on('uncaughtException', function (err) {
console.error(err);
console.log('Node NOT Exiting...');
});
@@ -6,8 +6,9 @@ process.on('uncaughtException', function(err) {
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
let express = require('express');
let morgan = require('morgan');
let uuid = require('node-uuid');
import { v4 as uuidv4 } from 'uuid';
let logger = require('./utils/logger');
const config = require('./config');
morgan.token('id', function getId(req) {
return req.id;
@@ -19,12 +20,12 @@ app.enable('trust proxy');
const rateLimit = require('express-rate-limit');
const limiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 200,
max: config.rateLimit || 200,
});
app.use(limiter);
app.use(function(req, res, next) {
req.id = uuid.v4();
app.use(function (req, res, next) {
req.id = uuidv4();
next();
});
@@ -35,7 +36,6 @@ app.use(
);
let bodyParser = require('body-parser');
let config = require('./config');
app.use(bodyParser.urlencoded({ extended: false })); // parse application/x-www-form-urlencoded
app.use(bodyParser.json(null)); // parse application/json
@@ -44,7 +44,7 @@ app.use('/static', express.static('static'));
app.use(require('./controllers/api'));
app.use(require('./controllers/website'));
let server = app.listen(process.env.PORT || 3000, function() {
let server = app.listen(process.env.PORT || 3000, function () {
logger.log('BOOTING UP', 'Listening on port ' + (process.env.PORT || 3000));
});
module.exports = server;

View File

@@ -1,8 +1,18 @@
// setup lnd rpc
const config = require('./config');
var fs = require('fs');
var grpc = require('grpc');
var lnrpc = grpc.load('rpc.proto').lnrpc;
var grpc = require('@grpc/grpc-js');
const protoLoader = require('@grpc/proto-loader');
const loaderOptions = {
keepCase: true,
longs: String,
enums: String,
defaults: true,
oneofs: true,
};
const packageDefinition = protoLoader.loadSync('rpc.proto', loaderOptions);
var lnrpc = grpc.loadPackageDefinition(packageDefinition).lnrpc;
process.env.GRPC_SSL_CIPHER_SUITES = 'HIGH+ECDSA';
var lndCert;
if (process.env.TLSCERT) {
@@ -10,7 +20,7 @@ if (process.env.TLSCERT) {
} else {
lndCert = fs.readFileSync('tls.cert');
}
console.log('using tls.cert', lndCert.toString('hex'));
process.env.VERBOSE && console.log('using tls.cert', lndCert.toString('hex'));
let sslCreds = grpc.credentials.createSsl(lndCert);
let macaroon;
if (process.env.MACAROON) {
@@ -18,8 +28,8 @@ if (process.env.MACAROON) {
} else {
macaroon = fs.readFileSync('admin.macaroon').toString('hex');
}
console.log('using macaroon', macaroon);
let macaroonCreds = grpc.credentials.createFromMetadataGenerator(function(args, callback) {
process.env.VERBOSE && console.log('using macaroon', macaroon);
let macaroonCreds = grpc.credentials.createFromMetadataGenerator(function (args, callback) {
let metadata = new grpc.Metadata();
metadata.add('macaroon', macaroon);
callback(null, metadata);
@@ -28,15 +38,15 @@ let creds = grpc.credentials.combineChannelCredentials(sslCreds, macaroonCreds);
// trying to unlock the wallet:
if (config.lnd.password) {
console.log('trying to unlock the wallet');
process.env.VERBOSE && console.log('trying to unlock the wallet');
var walletUnlocker = new lnrpc.WalletUnlocker(config.lnd.url, creds);
walletUnlocker.unlockWallet(
{
wallet_password: Buffer.from(config.lnd.password).toString('base64'),
},
function(err, response) {
function (err, response) {
if (err) {
console.log('unlockWallet failed, probably because its been aleady unlocked');
process.env.VERBOSE && console.log('unlockWallet failed, probably because its been aleady unlocked');
} else {
console.log('unlockWallet:', response);
}

6344
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "LndHub",
"version": "1.2.0",
"name": "lndhub",
"version": "1.3.4",
"description": "",
"main": "index.js",
"scripts": {
@@ -12,29 +12,33 @@
"author": "Igor Korsakov <overtorment@gmail.com>",
"license": "MIT",
"dependencies": {
"babel": "^6.23.0",
"babel-cli": "^6.26.0",
"babel-eslint": "^10.1.0",
"babel-polyfill": "^6.26.0",
"babel-preset-env": "^1.7.0",
"babel-preset-es2015": "^6.24.1",
"babel-register": "^6.26.0",
"bignumber.js": "^9.0.0",
"bolt11": "^1.2.6",
"eslint": "^6.8.0",
"eslint-config-prettier": "^6.10.1",
"eslint-plugin-prettier": "^3.1.2",
"express": "^4.16.4",
"express-rate-limit": "^5.0.0",
"grpc": "^1.17.0-pre1",
"ioredis": "^4.16.2",
"jayson": "^3.1.2",
"morgan": "^1.9.1",
"mustache": "^4.0.1",
"node-uuid": "^1.4.8",
"prettier": "^2.0.4",
"request": "^2.88.0",
"request-promise": "^4.2.2",
"winston": "^3.1.0"
"@babel/cli": "^7.13.16",
"@babel/core": "^7.13.16",
"@babel/eslint-parser": "^7.13.10",
"@babel/node": "^7.13.0",
"@babel/preset-env": "^7.13.15",
"@babel/register": "^7.13.16",
"@grpc/grpc-js": "^1.2.10",
"@grpc/proto-loader": "^0.6.1",
"bignumber.js": "^9.0.1",
"bitcoinjs-lib": "^5.2.0",
"bolt11": "^1.3.1",
"core-js": "^3.11.0",
"eslint": "^7.24.0",
"eslint-config-prettier": "^8.0.0",
"eslint-plugin-prettier": "^3.4.0",
"express": "^4.17.1",
"express-rate-limit": "^5.2.6",
"frisbee": "^3.1.4",
"ioredis": "^4.26.0",
"jayson": "^3.4.4",
"morgan": "^1.10.0",
"mustache": "^4.1.0",
"prettier": "^2.2.1",
"qr-image": "3.2.0",
"request": "^2.88.2",
"request-promise": "^4.2.6",
"uuid": "^8.3.2",
"winston": "^3.3.3"
}
}

3468
rpc.proto

File diff suppressed because it is too large Load Diff

7
run-process-locked.sh Executable file
View File

@@ -0,0 +1,7 @@
while [ 1 ] ;
do
date
./node_modules/.bin/babel-node scripts/process-locked-payments.js 2>/dev/null
sleep 3600
done

View File

@@ -2,56 +2,75 @@ const important_channels = {
'03864ef025fde8fb587d989186ce6a4a186895ee44a926bfc370e2c366597a3f8f': {
name: 'ACINQ',
uri: '03864ef025fde8fb587d989186ce6a4a186895ee44a926bfc370e2c366597a3f8f@34.239.230.56:9735',
wumbo: 1,
},
'03abf6f44c355dec0d5aa155bdbdd6e0c8fefe318eff402de65c6eb2e1be55dc3e': {
name: 'OpenNode',
uri: '03abf6f44c355dec0d5aa155bdbdd6e0c8fefe318eff402de65c6eb2e1be55dc3e@18.221.23.28:9735',
wumbo: 1,
},
'0242a4ae0c5bef18048fbecf995094b74bfb0f7391418d71ed394784373f41e4f3': {
name: 'coingate.com',
uri: '0242a4ae0c5bef18048fbecf995094b74bfb0f7391418d71ed394784373f41e4f3@3.124.63.44:9735',
},
'0254ff808f53b2f8c45e74b70430f336c6c76ba2f4af289f48d6086ae6e60462d3': {
name: 'bitrefill thor',
uri: '0254ff808f53b2f8c45e74b70430f336c6c76ba2f4af289f48d6086ae6e60462d3@52.30.63.2:9735',
// '0242a4ae0c5bef18048fbecf995094b74bfb0f7391418d71ed394784373f41e4f3': {
// name: 'coingate.com',
// uri: '0242a4ae0c5bef18048fbecf995094b74bfb0f7391418d71ed394784373f41e4f3@3.124.63.44:9735',
// },
// '0254ff808f53b2f8c45e74b70430f336c6c76ba2f4af289f48d6086ae6e60462d3': {
// name: 'bitrefill thor',
// uri: '0254ff808f53b2f8c45e74b70430f336c6c76ba2f4af289f48d6086ae6e60462d3@52.30.63.2:9735',
// wumbo: 1,
// },
// '030c3f19d742ca294a55c00376b3b355c3c90d61c6b6b39554dbc7ac19b141c14f': {
// name: 'bitrefill 2',
// uri: '030c3f19d742ca294a55c00376b3b355c3c90d61c6b6b39554dbc7ac19b141c14f@52.50.244.44:9735',
// wumbo: 1,
// },
'03d607f3e69fd032524a867b288216bfab263b6eaee4e07783799a6fe69bb84fac': {
name: 'bitrefill 3',
uri: '03d607f3e69fd032524a867b288216bfab263b6eaee4e07783799a6fe69bb84fac@3.237.23.179:9735',
wumbo: 1,
},
'030c3f19d742ca294a55c00376b3b355c3c90d61c6b6b39554dbc7ac19b141c14f': {
name: 'bitrefill 2',
uri: '030c3f19d742ca294a55c00376b3b355c3c90d61c6b6b39554dbc7ac19b141c14f@52.50.244.44:9735',
wumbo: 1,
},
'025f1456582e70c4c06b61d5c8ed3ce229e6d0db538be337a2dc6d163b0ebc05a5': {
name: 'paywithmoon.com',
uri: '025f1456582e70c4c06b61d5c8ed3ce229e6d0db538be337a2dc6d163b0ebc05a5@52.86.210.65:9735',
},
'0279c22ed7a068d10dc1a38ae66d2d6461e269226c60258c021b1ddcdfe4b00bc4': {
name: 'ln1.satoshilabs.com',
uri: '0279c22ed7a068d10dc1a38ae66d2d6461e269226c60258c021b1ddcdfe4b00bc4@157.230.28.160:9735',
},
'02004c625d622245606a1ea2c1c69cfb4516b703b47945a3647713c05fe4aaeb1c': {
name: 'LivingRoomOfSatoshi',
uri: '02004c625d622245606a1ea2c1c69cfb4516b703b47945a3647713c05fe4aaeb1c@172.81.178.151:9735',
},
// '025f1456582e70c4c06b61d5c8ed3ce229e6d0db538be337a2dc6d163b0ebc05a5': {
// name: 'paywithmoon.com',
// uri: '025f1456582e70c4c06b61d5c8ed3ce229e6d0db538be337a2dc6d163b0ebc05a5@52.86.210.65:9735',
// },
// '0279c22ed7a068d10dc1a38ae66d2d6461e269226c60258c021b1ddcdfe4b00bc4': {
// name: 'ln1.satoshilabs.com',
// uri: '0279c22ed7a068d10dc1a38ae66d2d6461e269226c60258c021b1ddcdfe4b00bc4@157.230.28.160:9735',
// },
// '02004c625d622245606a1ea2c1c69cfb4516b703b47945a3647713c05fe4aaeb1c': {
// name: 'LivingRoomOfSatoshi',
// uri: '02004c625d622245606a1ea2c1c69cfb4516b703b47945a3647713c05fe4aaeb1c@172.81.178.151:9735',
// },
'02816caed43171d3c9854e3b0ab2cf0c42be086ff1bd4005acc2a5f7db70d83774': {
name: 'ln.pizza aka fold',
uri: '02816caed43171d3c9854e3b0ab2cf0c42be086ff1bd4005acc2a5f7db70d83774@35.238.153.25:9735',
wumbo: 1,
},
'0331f80652fb840239df8dc99205792bba2e559a05469915804c08420230e23c7c': {
name: 'LightningPowerUsers.com',
uri: '0331f80652fb840239df8dc99205792bba2e559a05469915804c08420230e23c7c@34.200.181.109:9735',
},
'033d8656219478701227199cbd6f670335c8d408a92ae88b962c49d4dc0e83e025': {
name: 'bfx-lnd0',
uri: '033d8656219478701227199cbd6f670335c8d408a92ae88b962c49d4dc0e83e025@34.65.85.39:9735',
'02570432c30df86ff7dbe3b49e24e8280411674f96470154cadc76d447e339292b': {
name: 'okcoin',
uri: '02570432c30df86ff7dbe3b49e24e8280411674f96470154cadc76d447e339292b@8.210.75.128:26657',
wumbo: 1,
},
// '0331f80652fb840239df8dc99205792bba2e559a05469915804c08420230e23c7c': {
// name: 'LightningPowerUsers.com',
// uri: '0331f80652fb840239df8dc99205792bba2e559a05469915804c08420230e23c7c@34.200.181.109:9735',
// },
// '033d8656219478701227199cbd6f670335c8d408a92ae88b962c49d4dc0e83e025': {
// name: 'bfx-lnd0',
// uri: '033d8656219478701227199cbd6f670335c8d408a92ae88b962c49d4dc0e83e025@34.65.85.39:9735',
// },
// '037f990e61acee8a7697966afd29dd88f3b1f8a7b14d625c4f8742bd952003a590': {
// name: 'fixedfloat.com',
// uri: '037f990e61acee8a7697966afd29dd88f3b1f8a7b14d625c4f8742bd952003a590@185.5.53.91:9735',
// },
// '03c2abfa93eacec04721c019644584424aab2ba4dff3ac9bdab4e9c97007491dda': {
// name: 'tippin.me',
// uri: '03c2abfa93eacec04721c019644584424aab2ba4dff3ac9bdab4e9c97007491dda@157.245.68.47:9735',
// },
};
let lightning = require('../lightning');
lightning.listChannels({}, function(err, response) {
lightning.listChannels({}, function (err, response) {
console.log();
if (err) {
console.error('lnd failure:', err);
@@ -72,50 +91,77 @@ lightning.listChannels({}, function(err, response) {
}
}
console.log('# reconnect important channels that are inactive:\n');
if (process.argv.includes('--reconnect')) {
let doneReconnect = {}; // so theres no duplicates
console.log('# reconnect important channels that are inactive:\n');
for (const important of Object.keys(important_channels)) {
for (let channel of lightningListChannels.channels) {
if (channel.remote_pubkey === important && !channel.active && !doneReconnect[channel.remote_pubkey]) {
doneReconnect[channel.remote_pubkey] = true;
console.log(
'lncli disconnect',
channel.remote_pubkey,
'; sleep 5;',
'lncli connect',
important_channels[channel.remote_pubkey].uri,
'#',
important_channels[channel.remote_pubkey].name,
);
}
}
}
}
for (const important of Object.keys(important_channels)) {
for (let channel of lightningListChannels.channels) {
if (channel.remote_pubkey === important && !channel.active) {
if (process.argv.includes('--reconnect-all')) {
let doneReconnect = {}; // so theres no duplicates
console.log('# reconnect important channels that are inactive:\n');
for (const important of Object.keys(important_channels)) {
for (let channel of lightningListChannels.channels) {
if (channel.remote_pubkey === important && !doneReconnect[channel.remote_pubkey]) {
doneReconnect[channel.remote_pubkey] = true;
console.log(
'lncli disconnect',
channel.remote_pubkey,
'; sleep 5;',
'lncli connect',
important_channels[channel.remote_pubkey].uri,
'#',
important_channels[channel.remote_pubkey].name,
);
}
}
}
}
if (process.argv.includes('--open')) {
console.log('\n# open important channels:\n');
for (const important of Object.keys(important_channels)) {
let atLeastOneChannelIsSufficientCapacity = false;
for (let channel of lightningListChannels.channels) {
if (channel.remote_pubkey === important && channel.local_balance >= 4000000 && channel.active) {
atLeastOneChannelIsSufficientCapacity = true;
}
}
if (!atLeastOneChannelIsSufficientCapacity) {
console.log(
'lncli disconnect',
channel.remote_pubkey,
'; sleep 5;',
'lncli connect',
important_channels[channel.remote_pubkey].uri,
important,
'; sleep 3;',
'lncli openchannel --node_key',
important,
'--connect',
important_channels[important].uri.split('@')[1],
'--local_amt',
important_channels[important].wumbo ? '100000000' : '16777215',
'--remote_csv_delay 144',
'--sat_per_byte 10',
'#',
important_channels[channel.remote_pubkey].name,
important_channels[important].name,
);
}
}
}
console.log('\n# open important channels:\n');
for (const important of Object.keys(important_channels)) {
let atLeastOneChannelIsSufficientCapacity = false;
for (let channel of lightningListChannels.channels) {
if (channel.remote_pubkey === important && channel.local_balance >= 4000000 && channel.active) {
atLeastOneChannelIsSufficientCapacity = true;
}
}
if (!atLeastOneChannelIsSufficientCapacity) {
console.log(
'lncli disconnect',
important,
'; sleep 3;',
'lncli openchannel --node_key',
important,
'--connect',
important_channels[important].uri.split('@')[1],
'--local_amt',
important_channels[important].wumbo ? '167772150' : '16777215',
'#',
important_channels[important].name,
);
}
}
process.exit();
});

View File

@@ -0,0 +1,25 @@
# this script should be used if youre retiring one bitcoind in favor of new one
# it exports all addresses from the old one and prepares script to import them on a new node
#
echo export 1...
./bitcoin-0.21.0/bin/bitcoin-cli -rpcwallet="" -rpcconnect=1.1.1.1 -rpcuser=user -rpcpassword=oldPassword listreceivedbyaddress 0 true true > addresses.txt
echo export 2...
./bitcoin-0.21.0/bin/bitcoin-cli -rpcwallet="wallet.dat" -rpcconnect=1.1.1.1 -rpcuser=user -rpcpassword=oldPassword listreceivedbyaddress 0 true true >> addresses.txt
echo clean...
cat addresses.txt | grep address | sort -u | awk '{print $2}' | sed 's/"//g' | sed 's/,//g' > addresses_clean.txt
echo "got addresses:"
wc -l < addresses_clean.txt
echo writing import_on_other_node.sh ...
>import_on_other_node.sh
chmod +x import_on_other_node.sh
while read in; do
echo "./bitcoin-0.21.0/bin/bitcoin-cli -rpcconnect=2.2.2.2 -rpcuser=user -rpcpassword=newPassword importaddress $in $in false" >> import_on_other_node.sh
done < addresses_clean.txt
echo 'done. dont forget to run ./import_on_other_node.sh and then ./bitcoin-0.21.0/bin/bitcoin-cli -rpcconnect=2.2.2.2 -rpcwallet="wallet.dat" -rpcuser=user -rpcpassword=newPassword rescanblockchain 459491'

View File

@@ -38,7 +38,7 @@ let lightning = require('../lightning');
let payment = new Paym(redis, bitcoinclient, lightning);
payment.setInvoice(lockedPayment.pay_req);
if (daysPassed < 2) {
if (daysPassed > 1 / 24 && daysPassed <= 1) {
// if (!await payment.isExpired()) {
let sendResult;
console.log('attempting to pay to route');
@@ -67,7 +67,7 @@ let lightning = require('../lightning');
console.log('sleeping 5 sec...');
console.log('-----------------------------------------------------------------------------------');
await User._sleep(0);
} else if (daysPassed > 4) {
} else if (daysPassed > 1) {
// trying to lookup this stuck payment in an array of delivered payments
let isPaid = false;
for (let sentPayment of listPayments['payments']) {

View File

@@ -18,11 +18,12 @@ let lightning = require('../lightning');
let listinvoices = await tempInv.listInvoices();
console.log('done', 'got', listinvoices['invoices'].length, 'invoices');
fs.writeFileSync('listInvoices.json', JSON.stringify(listinvoices['invoices'], null, 2));
fs.writeFileSync('listInvoices.json', '[\n');
let markedInvoices = 0;
for (const invoice of listinvoices['invoices']) {
if (invoice.state === 'SETTLED' && +invoice.creation_date >= +new Date() / 1000 - 3600 * 24 * 7) {
fs.appendFileSync('listInvoices.json', JSON.stringify(invoice, null, 2) + ',\n');
if (invoice.state === 'SETTLED' && +invoice.creation_date >= +new Date() / 1000 - 3600 * 24 * 7 * 2) {
tempInv.setInvoice(invoice.payment_request);
await tempInv.markAsPaidInDatabase();
markedInvoices++;
@@ -30,6 +31,8 @@ let lightning = require('../lightning');
}
}
fs.appendFileSync('listInvoices.json', ']');
console.log('done, marked', markedInvoices, 'invoices');
process.exit();
})();

View File

@@ -5,7 +5,7 @@ const config = require('../config');
var Redis = require('ioredis');
var redis = new Redis(config.redis);
redis.info(function(err, info) {
redis.info(function (err, info) {
if (err || !info) {
console.error('redis failure');
process.exit(5);

View File

@@ -1,145 +0,0 @@
/*
* Globals
*/
/* Links */
a,
a:focus,
a:hover {
color: #fff;
}
.lead {
font-size: 18px;
font-weight: 400;
}
.lead strong {
font-weight: bold;
}
/* Custom default button */
.btn-secondary,
.btn-secondary:hover,
.btn-secondary:focus {
color: #333;
text-shadow: none; /* Prevent inheritance from `body` */
background-color: #fff;
border: .05rem solid #fff;
}
/*
* Base structure
*/
html,
body {
background-color: #1C2529;
}
.clear {
clear: both;
display: block;
}
body {
color: #fff;
}
h1 {
font-size: 70px;
font-weight: bold;
}
h2 {
font-size: 50px;
font-weight: bold;
padding-top: 80px;
margin-bottom: 40px;
}
.cover-heading {
padding-top: 190px;
margin-bottom: 40px;
}
.cover-container {
max-width: 960px;
}
@media (max-width: 991px) {
.cover-container {
padding-left: 16px;
padding-right: 16px;
}
}
.github {
margin-top: 80px;
}
/*
* Header
*/
.masthead {
padding-top: 58px;
}
.masthead-brand {
margin-bottom: 0;
}
@media (min-width: 48em) {
.masthead-brand {
float: left;
}
.nav-masthead {
float: right;
}
}
/*
* Cover
*/
.cover {
padding-bottom: 140px;
}
.cover .btn-lg {
padding: .75rem 1.25rem;
font-weight: 700;
}
.explain {
min-height: 800px;
background: #29353C;
}
.explain img {
margin: 90px auto;
}
.lndhub-graph {
max-width: 100%;
}
.promote {
padding-bottom: 80px;
}
.promote img {
max-width: 232px;
}
.cta {
margin-top: 40px;
}
@media (min-width: 992px) {
.cta li:first-child {
float: left;
}
.cta li {
margin: 0 auto;
text-align: center;
}
}
@media (max-width: 991px) {
.cta li {
margin: 0 auto 32px 0;
text-align: center;
width: 50%;
float: left;
}
.cta li img{
width: 150px;
}
}
/*
* Footer
*/
.mastfoot {
color: rgba(255, 255, 255, .5);
}

253
static/css/style.css Normal file
View File

@@ -0,0 +1,253 @@
html, body {
height: 100%;
background: #FAFBFE;
color: #000;
}
html {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box
}
*, :before, :after {
box-sizing: inherit
}
body {
margin: 0;
font-family: Helvetica Neue, Menlo, Consolas, "Courier New", monospace;
word-wrap: break-word;
font-weight: 400;
height: 100%;
width: 100%;
}
.sidebar {
background: #fff;
box-shadow: 0 -1px 4px 0 rgba(0,0,0,.20);
}
.container32 {
padding: 32px;
}
.container24 {
padding: 24px;
}
.container16 {
padding: 16px;
}
.nosidepadding {
padding-right: 0;
padding-left: 0;
}
.boxes {
display: flex;
margin: 40px 0 56px 0;
}
.box {
background: #fff;
box-shadow: 0 1px 4px 0 rgba(0,0,0,.12);
border-radius: 6px;
position: relative;
}
.boxes .box {
width: 25%;
margin-right: 32px;
}
.box h3 {
font-size: 18px;
margin: 0;
padding: 0;
font-weight: 500;
}
.meta {
font-size: 13px;
color: #9AA0AA;
margin: 0 0 4px 0;
padding: 0;
font-weight: 500;
}
.uri {
font-size: 13px;
color: #000;
font-weight: 500;
}
.number1 {
font-size: 30px;
font-weight: 500;
margin-top: 32px;
display: inline-block;
}
.right {
float: right;
}
.label {
padding: 4px 8px;
border-radius: 16px;
color: #fff;
font-size: 13px;
}
[title~=true], [title~=active] {
background: #50E3C2;
}
[title~=false], [title~=inactive] {
background: #8E8E8E;
}
.label[title~=true]::after {
content: "synced";
}
.label[title~=false]::after {
content: "not synced";
}
.label[title~=active]::after {
content: "active";
}
.label[title~=inactive]::after {
content: "inactive";
}
.synced {
position: absolute;
top: 24px;
right: 24px;
}
#progressbar {
appearance: none;
margin: 0;
padding: 0;
max-width: 100%;
-webkit-appearance: none;
border-radius: 8px;
overflow: hidden;
}
#progressbar[max]::-webkit-progress-value {
border-radius: 8px 4px 4px 8px;
-webkit-appearance: none;
background: linear-gradient(0deg, rgba(47,95,179,1) 0%, rgba(63,120,220,1) 100%);
}
#progressbar[value]::-webkit-progress-bar {
background: linear-gradient(0deg, rgba(104,187,225,1) 0%, rgba(139,215,249,1) 100%);
height: 16px;
border-radius: 8px;
transition: 0.4s linear;
transition-property: width, background-color;
-webkit-appearance: none;
}
.row {
padding: 8px 0;
border-radius: 8px;
transition: 0.2s ease-in-out;
}
.row:hover {
background: #F4F8FB;
}
.row .name {
padding: 2px 4px 2px 8px;
}
.row .name h2 {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.row .graph {
flex-grow: 1;
padding: 0 16px 0 0;
align-self: center;
padding: 2px 4px;
}
.row .status {
align-self: center;
padding: 2px 8px 2px 4px;
}
.decor {
text-decoration : none;
}
.name h2 {
color: #000;
margin: 0;
font-weight: 500;
font-size: 18px;
}
.amount {
color: #9AA0AA;
margin: 4px 0;
font-weight: 500;
}
.qr {
margin: 0 -24px;
width: 268px
}
footer {
color: #9AA0AA;
}
footer a {
font-size: 14px;
color: #0070FF;
text-decoration: none;
}
@media (min-width: 1200px){
body {
padding-right: 300px;
}
.sidebar {
position: fixed;
top: 0;
right: 0;
width: 300px;
height: 100%;
box-shadow: 0 0 4px 0 rgba(0,0,0,.20);
}
footer {
position: absolute;
bottom: 32px;
color: #9AA0AA;
}
.boxes .box:last-child {
margin-right: 0;
}
.row {
display: flex;
}
.row .name {
flex-grow: 0.2;
max-width: 20%;
}
.row .status {
flex-grow: 0.1;
max-width: 10%;
}
}
@media (max-width: 1199px){
.logo {
width: 200px;
}
.scroll {
overflow: scroll;
padding: 0px 16px 0px 1px;
margin-right: -32px;
}
.boxes {
width: 900px;
}
.boxes .box {
width: 180px;
}
.row {
position: relative;
}
.row .name {
flex-grow: 0.8;
max-width: 80%;
}
.row .status {
position: absolute;
top: 16px;
right: 0;
}
}
@media (max-width: 959px){
.logo {
width: 200px;
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

View File

@@ -1,57 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="197px" height="69px" viewBox="0 0 197 69" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 52.5 (67469) - http://www.bohemiancoding.com/sketch -->
<title>app-store-badge</title>
<desc>Created with Sketch.</desc>
<defs>
<path d="M174.564444,53.2702703 L6.30148148,53.2702703 C2.81555556,53.2702703 0,50.4735811 0,47.0110135 L0,6.39243243 C0,2.92986486 2.81555556,0.133175676 6.30148148,0.133175676 L174.564444,0.133175676 C178.05037,0.133175676 181,2.92986486 181,6.39243243 L181,47.0110135 C181,50.4735811 178.05037,53.2702703 174.564444,53.2702703 Z" id="path-1"></path>
<filter x="-7.2%" y="-20.7%" width="114.4%" height="148.9%" filterUnits="objectBoundingBox" id="filter-2">
<feOffset dx="0" dy="2" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
<feGaussianBlur stdDeviation="4" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.907382246 0" type="matrix" in="shadowBlurOuter1"></feColorMatrix>
</filter>
</defs>
<g id="Page-2" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Desktop-HD" transform="translate(-725.000000, -2060.000000)" fill-rule="nonzero">
<g id="Group-5" transform="translate(253.000000, 1680.000000)">
<g id="app-store-badge" transform="translate(480.000000, 386.000000)">
<g id="Group">
<g id="Shape">
<use fill="black" fill-opacity="1" filter="url(#filter-2)" xlink:href="#path-1"></use>
<use fill="#FFFFFF" xlink:href="#path-1"></use>
</g>
<g transform="translate(16.818728, 7.990541)" fill="#222A2E" id="Shape">
<path d="M23.5375687,18.3782432 C23.5375687,14.1166216 27.0234946,11.9858108 27.2916428,11.8526351 C25.2805317,8.92277027 22.0627539,8.52324324 20.9901613,8.52324324 C18.3086798,8.25689189 15.7612724,10.1213514 14.4205317,10.1213514 C13.0797909,10.1213514 10.9346057,8.52324324 8.78942055,8.65641892 C5.97386499,8.65641892 3.29238351,10.3877027 1.8175687,12.9180405 C-1.26613501,18.1118919 1.01312425,25.8360811 3.96275388,30.0977027 C5.4375687,32.2285135 7.18053166,34.4925 9.32571685,34.3593243 C11.470902,34.2261486 12.2753465,33.0275676 14.956828,33.0275676 C17.5042354,33.0275676 18.3086798,34.3593243 20.5879391,34.3593243 C22.8671983,34.3593243 24.3420131,32.2285135 25.816828,30.2308784 C27.5597909,27.8337162 28.2301613,25.5697297 28.2301613,25.4365541 C28.0960872,25.1702027 23.6716428,23.4389189 23.5375687,18.3782432 Z"></path>
<path d="M19.2471983,5.72655405 C20.453865,4.26162162 21.2583094,2.26398649 20.9901613,0.266351351 C19.2471983,0.399527027 17.2360872,1.46493243 15.8953465,2.79668919 C14.8227539,3.99527027 13.8842354,6.12608108 14.1523835,7.99054054 C16.1634946,8.25689189 18.0405317,7.19148649 19.2471983,5.72655405 Z"></path>
</g>
<g transform="translate(56.311111, 23.971622)" fill="#222A2E" id="Shape">
<path d="M15.5525926,17.9787162 L12.4688889,17.9787162 L10.86,12.7848649 L5.09481481,12.7848649 L3.48592593,17.9787162 L0.536296296,17.9787162 L6.30148148,0.266351351 L9.78740741,0.266351351 L15.5525926,17.9787162 Z M10.4577778,10.6540541 L8.98296296,5.99290541 C8.84888889,5.4602027 8.58074074,4.3947973 8.04444444,2.66351351 C7.91037037,3.46256757 7.64222222,4.52797297 7.24,5.99290541 L5.76518519,10.6540541 L10.4577778,10.6540541 Z"></path>
<path d="M30.4348148,11.4531081 C30.4348148,13.5839189 29.8985185,15.3152027 28.6918519,16.6469595 C27.6192593,17.7123649 26.2785185,18.3782432 24.8037037,18.3782432 C23.0607407,18.3782432 21.8540741,17.7123649 21.1837037,16.5137838 L21.1837037,23.3057432 L18.3681481,23.3057432 L18.3681481,9.58864865 C18.3681481,8.25689189 18.3681481,6.79195946 18.2340741,5.32702703 L20.7814815,5.32702703 L20.9155556,7.32466216 C21.8540741,5.85972973 23.3288889,5.06067568 25.2059259,5.06067568 C26.6807407,5.06067568 28.0214815,5.59337838 28.96,6.79195946 C29.8985185,7.85736486 30.4348148,9.45547297 30.4348148,11.4531081 Z M27.4851852,11.5862838 C27.4851852,10.3877027 27.217037,9.3222973 26.6807407,8.52324324 C26.0103704,7.72418919 25.2059259,7.32466216 24.1333333,7.32466216 C23.462963,7.32466216 22.7925926,7.59101351 22.2562963,7.99054054 C21.72,8.52324324 21.3177778,9.05594595 21.1837037,9.855 C21.0496296,10.254527 21.0496296,10.5208784 21.0496296,10.6540541 L21.0496296,12.7848649 C21.0496296,13.7170946 21.3177778,14.5161486 21.8540741,15.182027 C22.3903704,15.8479054 23.1948148,16.1142568 24.1333333,16.1142568 C25.2059259,16.1142568 26.0103704,15.7147297 26.6807407,14.9156757 C27.217037,13.9834459 27.4851852,12.9180405 27.4851852,11.5862838 Z"></path>
<path d="M45.182963,11.4531081 C45.182963,13.5839189 44.6466667,15.3152027 43.44,16.6469595 C42.3674074,17.7123649 41.0266667,18.3782432 39.5518519,18.3782432 C37.8088889,18.3782432 36.6022222,17.7123649 35.9318519,16.5137838 L35.9318519,23.3057432 L33.1162963,23.3057432 L33.1162963,9.58864865 C33.1162963,8.25689189 33.1162963,6.79195946 32.9822222,5.32702703 L35.5296296,5.32702703 L35.6637037,7.32466216 C36.6022222,5.85972973 38.077037,5.06067568 39.9540741,5.06067568 C41.4288889,5.06067568 42.7696296,5.59337838 43.7081481,6.79195946 C44.6466667,7.85736486 45.182963,9.45547297 45.182963,11.4531081 Z M42.2333333,11.5862838 C42.2333333,10.3877027 41.9651852,9.3222973 41.4288889,8.52324324 C40.7585185,7.72418919 39.9540741,7.32466216 38.8814815,7.32466216 C38.2111111,7.32466216 37.5407407,7.59101351 37.0044444,7.99054054 C36.4681481,8.52324324 36.0659259,9.05594595 35.9318519,9.855 C35.7977778,10.254527 35.7977778,10.5208784 35.7977778,10.6540541 L35.7977778,12.7848649 C35.7977778,13.7170946 36.0659259,14.5161486 36.6022222,15.182027 C37.1385185,15.8479054 37.942963,16.1142568 38.8814815,16.1142568 C39.9540741,16.1142568 40.7585185,15.7147297 41.4288889,14.9156757 C41.9651852,13.9834459 42.2333333,12.9180405 42.2333333,11.5862838 Z"></path>
<path d="M61.6740741,13.0512162 C61.6740741,14.5161486 61.1377778,15.8479054 60.0651852,16.7801351 C58.8585185,17.8455405 57.2496296,18.3782432 55.2385185,18.3782432 C53.3614815,18.3782432 51.7525926,17.9787162 50.68,17.3128378 L51.3503704,14.9156757 C52.557037,15.7147297 54.0318519,16.1142568 55.5066667,16.1142568 C56.5792593,16.1142568 57.3837037,15.8479054 58.0540741,15.4483784 C58.5903704,14.9156757 58.9925926,14.382973 58.9925926,13.4507432 C58.9925926,12.7848649 58.7244444,12.1189865 58.1881481,11.5862838 C57.6518519,11.0535811 56.8474074,10.6540541 55.7748148,10.254527 C52.6911111,9.05594595 51.0822222,7.45783784 51.0822222,5.19385135 C51.0822222,3.72891892 51.6185185,2.53033784 52.6911111,1.59810811 C53.7637037,0.665878378 55.2385185,0.266351351 57.1155556,0.266351351 C58.7244444,0.266351351 60.0651852,0.532702703 61.1377778,1.06540541 L60.4674074,3.32939189 C59.3948148,2.79668919 58.3222222,2.53033784 57.1155556,2.53033784 C56.042963,2.53033784 55.3725926,2.79668919 54.7022222,3.32939189 C54.1659259,3.72891892 54.0318519,4.26162162 54.0318519,4.9275 C54.0318519,5.59337838 54.3,6.25925676 54.8362963,6.65878378 C55.3725926,7.05831081 56.177037,7.59101351 57.3837037,7.99054054 C58.8585185,8.65641892 60.0651852,9.3222973 60.7355556,10.1213514 C61.4059259,10.7872297 61.6740741,11.8526351 61.6740741,13.0512162 Z"></path>
<path d="M71.1933333,7.32466216 L67.9755556,7.32466216 L67.9755556,13.5839189 C67.9755556,15.182027 68.5118519,15.9810811 69.5844444,15.9810811 C70.1207407,15.9810811 70.522963,15.9810811 70.7911111,15.8479054 L70.9251852,17.9787162 C70.3888889,18.2450676 69.5844444,18.2450676 68.6459259,18.2450676 C67.5733333,18.2450676 66.6348148,17.8455405 65.9644444,17.1796622 C65.2940741,16.5137838 65.0259259,15.3152027 65.0259259,13.7170946 L65.0259259,7.32466216 L63.1488889,7.32466216 L63.1488889,5.19385135 L65.0259259,5.19385135 L65.0259259,2.79668919 L67.8414815,1.99763514 L67.8414815,5.19385135 L70.9251852,5.19385135 C71.1933333,5.19385135 71.1933333,7.32466216 71.1933333,7.32466216 Z"></path>
<path d="M85.4051852,11.4531081 C85.4051852,13.4507432 84.8688889,15.0488514 83.6622222,16.2474324 C82.4555556,17.5791892 80.8466667,18.2450676 78.9696296,18.2450676 C77.0925926,18.2450676 75.6177778,17.5791892 74.4111111,16.3806081 C73.3385185,15.182027 72.6681481,13.5839189 72.6681481,11.7194595 C72.6681481,9.72182432 73.2044444,8.12371622 74.4111111,6.79195946 C75.6177778,5.59337838 77.0925926,4.9275 79.1037037,4.9275 C80.9807407,4.9275 82.4555556,5.59337838 83.6622222,6.79195946 C84.8688889,7.99054054 85.4051852,9.58864865 85.4051852,11.4531081 Z M82.4555556,11.5862838 C82.4555556,10.3877027 82.1874074,9.45547297 81.6511111,8.52324324 C81.1148148,7.45783784 80.1762963,7.05831081 79.1037037,7.05831081 C77.897037,7.05831081 77.0925926,7.59101351 76.4222222,8.52324324 C75.8859259,9.3222973 75.6177778,10.3877027 75.6177778,11.5862838 C75.6177778,12.7848649 75.8859259,13.7170946 76.4222222,14.6493243 C77.0925926,15.7147297 77.897037,16.1142568 78.9696296,16.1142568 C80.0422222,16.1142568 80.9807407,15.5815541 81.517037,14.5161486 C82.1874074,13.7170946 82.4555556,12.7848649 82.4555556,11.5862838 Z"></path>
<path d="M94.6562963,7.72418919 C94.3881481,7.72418919 94.12,7.59101351 93.7177778,7.59101351 C92.6451852,7.59101351 91.9748148,7.99054054 91.4385185,8.78959459 C90.9022222,9.45547297 90.7681481,10.254527 90.7681481,11.3199324 L90.7681481,17.9787162 L87.9525926,17.9787162 L87.9525926,9.18912162 C87.9525926,7.72418919 87.9525926,6.39243243 87.8185185,5.19385135 L90.3659259,5.19385135 L90.5,7.59101351 L90.6340741,7.59101351 C90.9022222,6.79195946 91.4385185,6.12608108 92.1088889,5.59337838 C92.7792593,5.19385135 93.4496296,4.9275 94.12,4.9275 C94.3881481,4.9275 94.6562963,4.9275 94.7903704,4.9275 C94.6562963,5.06067568 94.6562963,7.72418919 94.6562963,7.72418919 Z"></path>
<path d="M107.527407,11.0535811 C107.527407,11.5862838 107.527407,11.9858108 107.393333,12.3853378 L98.8125926,12.3853378 C98.8125926,13.5839189 99.2148148,14.6493243 100.019259,15.3152027 C100.68963,15.8479054 101.628148,16.2474324 102.834815,16.2474324 C104.041481,16.2474324 105.248148,15.9810811 106.320741,15.5815541 L106.722963,17.5791892 C105.516296,18.1118919 104.041481,18.3782432 102.432593,18.3782432 C100.421481,18.3782432 98.8125926,17.8455405 97.74,16.6469595 C96.6674074,15.4483784 95.997037,13.8502703 95.997037,11.9858108 C95.997037,10.1213514 96.5333333,8.39006757 97.6059259,7.19148649 C98.6785185,5.85972973 100.153333,5.19385135 102.164444,5.19385135 C104.041481,5.19385135 105.382222,5.85972973 106.320741,7.19148649 C107.125185,7.99054054 107.527407,9.45547297 107.527407,11.0535811 Z M104.711852,10.254527 C104.711852,9.45547297 104.577778,8.65641892 104.175556,8.12371622 C103.639259,7.32466216 102.968889,6.92513514 101.896296,6.92513514 C100.957778,6.92513514 100.153333,7.32466216 99.617037,8.12371622 C99.0807407,8.78959459 98.8125926,9.45547297 98.8125926,10.3877027 L104.711852,10.254527 Z"></path>
</g>
<g transform="translate(58.381691, 7.990541)" fill="#222A2E" id="Shape">
<path d="M7.31460573,5.32702703 C7.31460573,6.92513514 6.77830944,8.12371622 5.83979092,8.92277027 C4.9012724,9.58864865 3.69460573,9.98817568 2.08571685,9.98817568 C1.2812724,9.98817568 0.610902031,9.98817568 0.0746057348,9.855 L0.0746057348,1.33175676 C0.879050179,1.19858108 1.68349462,1.19858108 2.48793907,1.19858108 C3.96275388,1.19858108 5.16942055,1.46493243 5.97386499,2.13081081 C6.91238351,2.92986486 7.31460573,3.99527027 7.31460573,5.32702703 Z M5.83979092,5.32702703 C5.83979092,4.26162162 5.57164277,3.59574324 5.03534648,2.92986486 C4.49905018,2.39716216 3.69460573,2.13081081 2.62201314,2.13081081 C2.21979092,2.13081081 1.8175687,2.13081081 1.54942055,2.26398649 L1.54942055,8.78959459 C1.68349462,8.78959459 2.08571685,8.78959459 2.48793907,8.78959459 C3.56053166,8.78959459 4.36497611,8.52324324 5.03534648,7.85736486 C5.57164277,7.32466216 5.83979092,6.52560811 5.83979092,5.32702703 Z"></path>
<path d="M15.2249761,6.65878378 C15.2249761,7.59101351 14.956828,8.39006757 14.4205317,9.05594595 C13.8842354,9.72182432 13.0797909,9.98817568 12.1412724,9.98817568 C11.2027539,9.98817568 10.5323835,9.72182432 9.86201314,9.05594595 C9.32571685,8.39006757 9.0575687,7.72418919 9.0575687,6.79195946 C9.0575687,5.85972973 9.32571685,5.06067568 9.86201314,4.3947973 C10.3983094,3.72891892 11.2027539,3.46256757 12.1412724,3.46256757 C13.0797909,3.46256757 13.7501613,3.72891892 14.4205317,4.3947973 C14.956828,5.06067568 15.2249761,5.72655405 15.2249761,6.65878378 Z M13.7501613,6.79195946 C13.7501613,6.25925676 13.6160872,5.72655405 13.3479391,5.32702703 C13.0797909,4.79432432 12.6775687,4.52797297 12.1412724,4.52797297 C11.6049761,4.52797297 11.2027539,4.79432432 10.8005317,5.32702703 C10.5323835,5.72655405 10.3983094,6.25925676 10.3983094,6.79195946 C10.3983094,7.32466216 10.5323835,7.85736486 10.8005317,8.25689189 C11.0686798,8.78959459 11.470902,9.05594595 12.1412724,9.05594595 C12.6775687,9.05594595 13.0797909,8.78959459 13.3479391,8.25689189 C13.6160872,7.85736486 13.7501613,7.32466216 13.7501613,6.79195946 Z"></path>
<path d="M25.816828,3.59574324 L23.8057168,9.855 L22.4649761,9.855 L21.6605317,7.19148649 C21.3923835,6.52560811 21.2583094,5.85972973 21.1242354,5.19385135 C20.9901613,5.85972973 20.8560872,6.52560811 20.5879391,7.19148649 L19.7834946,9.855 L18.4427539,9.855 L16.5657168,3.59574324 L18.0405317,3.59574324 L18.710902,6.52560811 C18.8449761,7.19148649 18.9790502,7.85736486 19.1131243,8.52324324 C19.2471983,7.99054054 19.3812724,7.32466216 19.6494205,6.52560811 L20.5879391,3.46256757 L21.7946057,3.46256757 L22.5990502,6.39243243 C22.8671983,7.05831081 23.0012724,7.85736486 23.1353465,8.52324324 C23.2694205,7.85736486 23.4034946,7.19148649 23.5375687,6.39243243 L24.3420131,3.46256757 L25.816828,3.59574324 Z"></path>
<path d="M33.056828,9.855 L31.7160872,9.855 L31.7160872,6.25925676 C31.7160872,5.19385135 31.313865,4.66114865 30.3753465,4.66114865 C29.9731243,4.66114865 29.570902,4.79432432 29.3027539,5.06067568 C29.0346057,5.32702703 28.9005317,5.72655405 28.9005317,6.12608108 L28.9005317,9.855 L27.5597909,9.855 L27.5597909,5.32702703 C27.5597909,4.79432432 27.5597909,4.12844595 27.5597909,3.59574324 L28.7664576,3.59574324 L28.7664576,4.52797297 C28.9005317,4.26162162 29.1686798,3.99527027 29.436828,3.72891892 C29.8390502,3.46256757 30.2412724,3.32939189 30.6434946,3.32939189 C31.1797909,3.32939189 31.7160872,3.46256757 32.1183094,3.86209459 C32.6546057,4.26162162 32.7886798,5.06067568 32.7886798,5.99290541 L32.7886798,9.855 L33.056828,9.855 Z"></path>
<polygon points="36.9449761 9.855 35.6042354 9.855 35.6042354 0.665878378 36.9449761 0.665878378"></polygon>
<path d="M45.2575687,6.65878378 C45.2575687,7.59101351 44.9894205,8.39006757 44.4531243,9.05594595 C43.916828,9.72182432 43.1123835,9.98817568 42.173865,9.98817568 C41.2353465,9.98817568 40.5649761,9.72182432 39.8946057,9.05594595 C39.3583094,8.39006757 39.0901613,7.72418919 39.0901613,6.79195946 C39.0901613,5.85972973 39.3583094,5.06067568 39.8946057,4.3947973 C40.430902,3.72891892 41.2353465,3.46256757 42.173865,3.46256757 C43.1123835,3.46256757 43.7827539,3.72891892 44.4531243,4.3947973 C44.9894205,5.06067568 45.2575687,5.72655405 45.2575687,6.65878378 Z M43.7827539,6.79195946 C43.7827539,6.25925676 43.6486798,5.72655405 43.3805317,5.32702703 C43.1123835,4.79432432 42.7101613,4.52797297 42.173865,4.52797297 C41.6375687,4.52797297 41.2353465,4.79432432 40.8331243,5.32702703 C40.5649761,5.72655405 40.430902,6.25925676 40.430902,6.79195946 C40.430902,7.32466216 40.5649761,7.85736486 40.8331243,8.25689189 C41.1012724,8.78959459 41.5034946,9.05594595 42.173865,9.05594595 C42.7101613,9.05594595 43.1123835,8.78959459 43.3805317,8.25689189 C43.6486798,7.85736486 43.7827539,7.32466216 43.7827539,6.79195946 Z"></path>
<path d="M51.9612724,9.855 L50.7546057,9.855 L50.6205317,9.18912162 C50.2183094,9.72182432 49.5479391,9.98817568 48.7434946,9.98817568 C48.2071983,9.98817568 47.670902,9.855 47.2686798,9.45547297 C47.0005317,9.05594595 46.7323835,8.65641892 46.7323835,8.12371622 C46.7323835,7.32466216 47.0005317,6.79195946 47.670902,6.39243243 C48.3412724,5.99290541 49.2797909,5.72655405 50.3523835,5.85972973 L50.3523835,5.72655405 C50.3523835,4.9275 49.9501613,4.52797297 49.0116428,4.52797297 C48.3412724,4.52797297 47.8049761,4.66114865 47.4027539,4.9275 L47.1346057,3.99527027 C47.670902,3.59574324 48.4753465,3.46256757 49.2797909,3.46256757 C50.8886798,3.46256757 51.8271983,4.26162162 51.8271983,5.99290541 L51.8271983,8.25689189 C51.9612724,9.05594595 51.9612724,9.58864865 51.9612724,9.855 Z M50.4864576,7.72418919 L50.4864576,6.79195946 C48.8775687,6.79195946 48.2071983,7.19148649 48.2071983,7.99054054 C48.2071983,8.25689189 48.3412724,8.52324324 48.4753465,8.78959459 C48.6094205,9.05594595 48.8775687,9.05594595 49.1457168,9.05594595 C49.413865,9.05594595 49.6820131,8.92277027 49.9501613,8.78959459 C50.2183094,8.65641892 50.3523835,8.39006757 50.4864576,7.99054054 C50.4864576,7.85736486 50.4864576,7.85736486 50.4864576,7.72418919 Z"></path>
<path d="M60.0057168,9.855 L58.7990502,9.855 L58.7990502,8.78959459 C58.396828,9.58864865 57.7264576,9.98817568 56.7879391,9.98817568 C55.9834946,9.98817568 55.4471983,9.72182432 54.910902,9.05594595 C54.3746057,8.39006757 54.1064576,7.72418919 54.1064576,6.79195946 C54.1064576,5.72655405 54.3746057,4.9275 54.910902,4.26162162 C55.4471983,3.72891892 56.1175687,3.32939189 56.9220131,3.32939189 C57.7264576,3.32939189 58.396828,3.59574324 58.6649761,4.12844595 L58.6649761,0.532702703 L60.0057168,0.532702703 L60.0057168,7.99054054 C59.8716428,8.78959459 60.0057168,9.3222973 60.0057168,9.855 Z M58.530902,7.19148649 L58.530902,6.12608108 C58.530902,5.99290541 58.530902,5.85972973 58.530902,5.72655405 C58.396828,5.32702703 58.2627539,5.06067568 57.9946057,4.9275 C57.7264576,4.66114865 57.4583094,4.52797297 57.0560872,4.52797297 C56.5197909,4.52797297 56.1175687,4.79432432 55.8494205,5.19385135 C55.5812724,5.59337838 55.4471983,6.12608108 55.4471983,6.79195946 C55.4471983,7.45783784 55.5812724,7.85736486 55.8494205,8.25689189 C56.1175687,8.65641892 56.5197909,8.92277027 57.0560872,8.92277027 C57.4583094,8.92277027 57.8605317,8.78959459 58.1286798,8.39006757 C58.396828,8.12371622 58.530902,7.72418919 58.530902,7.19148649 Z"></path>
<path d="M71.9383094,6.65878378 C71.9383094,7.59101351 71.6701613,8.39006757 71.133865,9.05594595 C70.5975687,9.72182432 69.7931243,9.98817568 68.8546057,9.98817568 C67.9160872,9.98817568 67.2457168,9.72182432 66.5753465,9.05594595 C66.0390502,8.39006757 65.770902,7.72418919 65.770902,6.79195946 C65.770902,5.85972973 66.0390502,5.06067568 66.5753465,4.3947973 C67.1116428,3.72891892 67.9160872,3.46256757 68.8546057,3.46256757 C69.7931243,3.46256757 70.4634946,3.72891892 71.133865,4.3947973 C71.6701613,5.06067568 71.9383094,5.72655405 71.9383094,6.65878378 Z M70.5975687,6.79195946 C70.5975687,6.25925676 70.4634946,5.72655405 70.1953465,5.32702703 C69.9271983,4.79432432 69.5249761,4.52797297 68.9886798,4.52797297 C68.4523835,4.52797297 68.0501613,4.79432432 67.6479391,5.32702703 C67.3797909,5.72655405 67.2457168,6.25925676 67.2457168,6.79195946 C67.2457168,7.32466216 67.3797909,7.85736486 67.6479391,8.25689189 C67.9160872,8.78959459 68.3183094,9.05594595 68.9886798,9.05594595 C69.5249761,9.05594595 69.9271983,8.78959459 70.1953465,8.25689189 C70.4634946,7.85736486 70.5975687,7.32466216 70.5975687,6.79195946 Z"></path>
<path d="M79.5805317,9.855 L78.2397909,9.855 L78.2397909,6.25925676 C78.2397909,5.19385135 77.8375687,4.66114865 76.8990502,4.66114865 C76.496828,4.66114865 76.0946057,4.79432432 75.8264576,5.06067568 C75.5583094,5.32702703 75.4242354,5.72655405 75.4242354,6.12608108 L75.4242354,9.855 L74.0834946,9.855 L74.0834946,5.32702703 C74.0834946,4.79432432 74.0834946,4.12844595 74.0834946,3.59574324 L75.2901613,3.59574324 L75.2901613,4.52797297 C75.4242354,4.26162162 75.6923835,3.99527027 75.9605317,3.72891892 C76.3627539,3.46256757 76.7649761,3.32939189 77.3012724,3.32939189 C77.8375687,3.32939189 78.373865,3.46256757 78.7760872,3.86209459 C79.3123835,4.26162162 79.4464576,5.06067568 79.4464576,5.99290541 L79.4464576,9.855 L79.5805317,9.855 Z"></path>
<path d="M88.9657168,4.66114865 L87.356828,4.66114865 L87.356828,7.72418919 C87.356828,8.52324324 87.6249761,8.92277027 88.1612724,8.92277027 C88.4294205,8.92277027 88.5634946,8.92277027 88.8316428,8.92277027 L88.8316428,9.98817568 C88.5634946,10.1213514 88.1612724,10.1213514 87.7590502,10.1213514 C87.2227539,10.1213514 86.8205317,9.98817568 86.4183094,9.58864865 C86.1501613,9.18912162 86.0160872,8.65641892 86.0160872,7.85736486 L86.0160872,4.66114865 L85.0775687,4.66114865 L85.0775687,3.59574324 L86.0160872,3.59574324 L86.0160872,2.39716216 L87.356828,1.99763514 L87.356828,3.59574324 L88.9657168,3.59574324 L88.9657168,4.66114865 Z"></path>
<path d="M96.473865,9.855 L95.1331243,9.855 L95.1331243,6.25925676 C95.1331243,5.19385135 94.730902,4.52797297 93.9264576,4.52797297 C93.2560872,4.52797297 92.853865,4.79432432 92.5857168,5.4602027 C92.5857168,5.59337838 92.5857168,5.72655405 92.5857168,5.99290541 L92.5857168,9.72182432 L91.2449761,9.72182432 L91.2449761,0.532702703 L92.5857168,0.532702703 L92.5857168,4.26162162 C92.9879391,3.59574324 93.6583094,3.19621622 94.4627539,3.19621622 C94.9990502,3.19621622 95.5353465,3.32939189 95.9375687,3.72891892 C96.473865,4.26162162 96.6079391,4.9275 96.6079391,5.85972973 C96.473865,6.12608108 96.473865,9.855 96.473865,9.855 Z"></path>
<path d="M104.116087,6.52560811 C104.116087,6.79195946 104.116087,6.92513514 104.116087,7.19148649 L99.9597909,7.19148649 C99.9597909,7.85736486 100.227939,8.25689189 100.630161,8.65641892 C101.032384,8.92277027 101.434606,9.05594595 101.970902,9.05594595 C102.641272,9.05594595 103.177569,8.92277027 103.713865,8.78959459 L103.982013,9.72182432 C103.445717,9.98817568 102.641272,10.1213514 101.836828,10.1213514 C100.898309,10.1213514 100.093865,9.855 99.5575687,9.3222973 C99.0212724,8.78959459 98.7531243,7.99054054 98.7531243,7.05831081 C98.7531243,6.12608108 99.0212724,5.32702703 99.5575687,4.66114865 C100.093865,3.99527027 100.898309,3.59574324 101.702754,3.59574324 C102.641272,3.59574324 103.311643,3.99527027 103.713865,4.66114865 C103.982013,5.06067568 104.116087,5.72655405 104.116087,6.52560811 Z M102.775346,6.12608108 C102.775346,5.72655405 102.641272,5.32702703 102.507198,5.06067568 C102.23905,4.66114865 101.836828,4.52797297 101.434606,4.52797297 C101.032384,4.52797297 100.630161,4.66114865 100.362013,5.06067568 C100.093865,5.32702703 99.9597909,5.72655405 99.9597909,6.12608108 C99.8257168,6.12608108 102.775346,6.12608108 102.775346,6.12608108 Z"></path>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 23 KiB

BIN
static/img/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 180 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 15 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -1,96 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="LNDhub - Open source Bank on top of the lightning network">
<meta name="author" content="Nuno Coelho">
<meta content="http://lndhub.io" property="og:url">
<meta content="lndhub.io" property="og:title">
<meta content="lndhub" property="og:description">
<meta content="http://lndhub.io/img/lndhub.svg" property="og:image">
<meta content="800" property="og:image:width">
<meta content="800" property="og:image:height">
<link rel="icon" href="/static/favicon.png">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<title>LNDhub - Open source Bank</title>
<!-- Custom styles for this template -->
<link href="/static/css/lndhub.css" rel="stylesheet">
</head>
<body>
<div class="cover-container mx-auto">
<header class="masthead mb-auto">
<div class="inner">
<h3 class="masthead-brand"><img src="/static/img/lndhub.svg"></h3>
</div>
</header>
<main role="main" class="inner cover">
<h1 class="cover-heading">An open source bank</h1>
<p class="lead"><strong>LNDHub is an opensource wrapper for Lightning Network Daemon. It provides <br/>
separate accounts with minimum trust for end users.</strong></p>
<p class="lead">We want to hide the complexity of running a node, and take over the work of a hub operator. Users want to make payments without the hassle of operating a node, opening channels, take care of liquidity or watching these channels.</p>
<p class="lead">We want to bring Lightning payments to everyone and speed up Bitcoin adoption.</p>
<p class="lead">We called it <strong>LNDhub</strong>.</p>
<div class="github">
<!-- Place this tag where you want the button to render. -->
<a class="github-button" href="https://github.com/bluewallet/lndhub" data-size="large" data-show-count="true" aria-label="Star bluewallet/lndhub on GitHub">Star</a>
</div>
<div class="clear"></div>
</main>
</div>
<div class="explain">
<div class="cover-container mx-auto">
<h2>How does it work?</h2>
<img class="lndhub-graph" src="/static/img/lndhub-graph.png">
<p class="lead">When the user sends Bitcoin to a dedicated top-up address, this balance is added to his account on LNDhub. Then, the user can use this balance to pay Lightning invoices, from everything to coffees to any micro-transaction he wants. But under the hood, its actually LNDhub who pays the invoice, deducting the users account balance. It works the same way when the user wants to receive a Lightning payment - its LNDhub who creates a Lightning invoice and actually receives the value on one of its channels.</p>
</div>
</div>
<div class="promote">
<div class="cover-container mx-auto">
<h2>Where can I test it?</h1>
<div class="row">
<div class="col-md-6 text-center">
<img class="lndhub-graph" src="/static/img/iphoneX.png">
</div>
<div class="col-md-6">
<p class="lead">Live on <strong>Blue wallet</strong>, a bitcoin wallet for iOS and android. <strong>LNDhub</strong> implementation on Blue wallet takes full advantage of this revolutionary payments network.</p>
<p>Enabling Blue wallet users to have unfairly cheap and fast Bitcoin transactions..
</p>
<ul class="list-unstyled cta">
<li><a class="badge-link2" href="https://itunes.apple.com/us/app/bluewallet-bitcoin-wallet/id1376878040?l=ru&amp;ls=1&amp;mt=8" target="_blank">
<img src="/static/img/app-store-badge.svg" alt="app store link"></a></li>
<li><a href="https://play.google.com/store/apps/details?id=io.bluewallet.bluewallet" target="_blank">
<img src="/static/img/play-store-badge.svg" alt="play store link"></a></li>
</ul>
</div>
</div>
</div>
</div>
<div class="promote">
<div class="cover-container mx-auto">
<h2>Why should you use it?</h1>
<div class="row">
<div class="col-md-8">
<p class="lead">Read our article on Medium on the reasoning behind the system and the pros and cons.</p>
</div>
<div class="col-md-4">
<a href="https://medium.com/bluewallet/bluewallet-brings-zero-configuration-lightning-payments-to-ios-and-android-30137a69f071" class="btn btn-lg btn-block btn-dark">read here &rarr;</a>
</div>
</div>
<footer class="mastfoot mt-auto">
<div class="inner">
<p>&nbsp;</p>
</div>
</footer>
<!-- Place this tag in your head or just before your close body tag. -->
<script async defer src="https://buttons.github.io/buttons.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
</body>
</html>

File diff suppressed because one or more lines are too long

View File

@@ -7,16 +7,13 @@
*
+ + + + + + + + + + + + + + + + + + + + + */
let fs = require('fs');
let winston = require('winston');
let createLogger = winston.createLogger;
let format = winston.format;
let transports = winston.transports;
import { createLogger, format, transports } from 'winston';
/* + + + + + + + + + + + + + + + + + + + + +
// Start
+ + + + + + + + + + + + + + + + + + + + + */
const { combine, timestamp, printf } = format;
const logFormat = printf(info => {
const logFormat = printf((info) => {
return `${info.timestamp} : ${info.level}: [${info.label}] : ${info.message}`;
});
const logger = createLogger({