Compare commits

..

366 Commits

Author SHA1 Message Date
9b81cc6287
Store and return invoice memo 2022-03-01 21:54:52 -06:00
947c7f7056
Fix onchain txs not being accounted for 2022-03-01 21:52:59 -06:00
9563cb9714
Merge branch 'BlueWallet:master' into master 2021-11-05 21:10:00 +02:00
Overtorment
aca47a23e9
ref 2021-10-28 14:25:51 +01:00
Overtorment
53361d2e3a
FIX: process locked script would wrongfully evict successfull payment 2021-10-28 14:00:31 +01:00
snyk-bot
ac4461c7f3 fix: upgrade express-rate-limit from 5.3.0 to 5.4.1
Snyk has created this PR to upgrade express-rate-limit from 5.3.0 to 5.4.1.

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=referral&page=upgrade-pr
2021-10-27 20:13:20 +01:00
snyk-bot
b7d106b499 fix: upgrade ioredis from 4.27.9 to 4.27.10
Snyk has created this PR to upgrade ioredis from 4.27.9 to 4.27.10.

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=referral&page=upgrade-pr
2021-10-27 20:12:49 +01:00
ac2061c6ed Add support to pass description_hash to LND 2021-10-19 20:22:31 +02:00
snyk-bot
14478becae fix: upgrade @grpc/proto-loader from 0.6.4 to 0.6.5
Snyk has created this PR to upgrade @grpc/proto-loader from 0.6.4 to 0.6.5.

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=referral&page=upgrade-pr
2021-10-05 15:52:11 +01:00
snyk-bot
292107342e fix: upgrade @babel/preset-env from 7.15.4 to 7.15.6
Snyk has created this PR to upgrade @babel/preset-env from 7.15.4 to 7.15.6.

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=referral&page=upgrade-pr
2021-10-01 13:02:08 +01:00
MG-ng
661248702d Last .md style improvement 2021-09-28 21:50:45 +01:00
MG-ng
d5fb16b074 Unified more .md style 2021-09-28 21:50:45 +01:00
MG-ng
a184872b02 Unified .md style
There were some tabs and broken Indentations which I corrected and converted to spaces.
2021-09-28 21:50:45 +01:00
MG-ng
6047383747 /getinvoice instead of /getaddinvoice
According to the code 
66a54570c5/controllers/api.js (L177)
2021-09-28 21:50:16 +01:00
dependabot[bot]
2f2c105177 build(deps): bump ansi-regex from 5.0.0 to 5.0.1
Bumps [ansi-regex](https://github.com/chalk/ansi-regex) from 5.0.0 to 5.0.1.
- [Release notes](https://github.com/chalk/ansi-regex/releases)
- [Commits](https://github.com/chalk/ansi-regex/compare/v5.0.0...v5.0.1)

---
updated-dependencies:
- dependency-name: ansi-regex
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-09-27 15:41:22 +01:00
Overtorment
64adcfc279
REL 2021-09-26 12:59:29 +01:00
Aaron Dewes
3a9cefa64b Update node from 12-buster to 16-bullseye
With Node 16 and Debian Bullseye being out now, this updates the BlueWallet docker containers to these versions. On Citadel, this will allow faster downloads of the app because it always uses the up-to-date containers, and when (if) Umbrel migrates to Node 16, it'll also allow faster downloads there.
2021-09-26 12:57:47 +01:00
MG-ng
e149f695cc or instead of of
according to the code
66a54570c5/controllers/api.js (L158)
2021-09-25 20:01:24 +01:00
Overtorment
c4a41fff48
Update README.md 2021-09-22 19:28:58 +01:00
Overtorment
688798024c
REL: v1.4.0 2021-09-22 14:18:04 +01:00
Overtorment
66a54570c5
DOC 2021-09-22 14:11:39 +01:00
Overtorment
e42ef3a85e
FIX: default values for fees config 2021-09-22 14:11:20 +01:00
Overtorment
600556f84c
FIX: qr in index page 2021-09-22 14:03:47 +01:00
xanoni
a01a8c6e14 index.js: add HOST environment argument 2021-09-22 13:54:34 +01:00
MG-ng
e9c6f3abde accounttype and partnerid check on create account
Refined the partnerid and accounttype check in the /create route according to the /doc/Send-requirements.md
Both are not mandatory but if given, they should be strings.

The typeof check is for direct string initialisation with "".
instanceof is used for string initialisation with new String() / the primitiv wrapper class.
2021-09-22 13:49:03 +01:00
lndhub-admin
7f9463bbbc sync changes to variable name 2021-09-22 13:46:51 +01:00
lndhub-admin
1b1fe8f08b tip invoices now use forwardFee
changed internalFee for tip invoices to forwardFee
2021-09-22 13:46:51 +01:00
lndhub-admin
28dd3a847a shorten default variables 2021-09-22 13:46:51 +01:00
lndhub-admin
a28eead0ab move default in varible name to comment
keep // default  0.* comment as reminder what defaults was
2021-09-22 13:46:51 +01:00
lndhub-admin
87afa20019 deleted space becouse karen said so 2021-09-22 13:46:51 +01:00
lndhub-admin
067f6d6667 delete commented fields 2021-09-22 13:46:51 +01:00
xraid
957d6c5951 Add global fee settings from config.js 2021-09-22 13:46:51 +01:00
Overtorment
d3df6aab05
REF: remove obsolete dep; small fixes 2021-09-07 22:00:33 +01:00
snyk-bot
4e8ce5e46f fix: upgrade @grpc/grpc-js from 1.3.6 to 1.3.7
Snyk has created this PR to upgrade @grpc/grpc-js from 1.3.6 to 1.3.7.

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-08-31 12:10:24 +01:00
snyk-bot
1fd24b640e fix: upgrade core-js from 3.16.0 to 3.16.1
Snyk has created this PR to upgrade core-js from 3.16.0 to 3.16.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-08-30 10:20:39 +01:00
snyk-bot
c47211f984 fix: upgrade multiple dependencies with Snyk
Snyk has created this PR to upgrade:
  - @babel/core from 7.14.8 to 7.15.0.
    See this package in npm: https://www.npmjs.com/package/@babel/core
  - @babel/preset-env from 7.14.9 to 7.15.0.
    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-08-26 09:04:38 +01:00
Denys Zaliskyi
5223edc2b7 Update README.md
fix reference to `lightning-custodian-wallet`
2021-08-25 18:56:51 +01:00
snyk-bot
92e626508c fix: upgrade multiple dependencies with Snyk
Snyk has created this PR to upgrade:
  - @babel/node from 7.14.5 to 7.14.9.
    See this package in npm: https://www.npmjs.com/package/@babel/node
  - @babel/preset-env from 7.14.8 to 7.14.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-08-23 13:15:56 +01:00
Denys Zaliskyi
3e2c31f429 Fix typo in Readme 2021-08-22 20:56:13 +01:00
snyk-bot
376d61f81d fix: upgrade core-js from 3.15.2 to 3.16.0
Snyk has created this PR to upgrade core-js from 3.15.2 to 3.16.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-08-21 19:46:06 +01:00
snyk-bot
1bb781270c fix: package.json & package-lock.json to reduce vulnerabilities
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-JS-IOREDIS-1567196
2021-08-19 11:29:37 +01:00
dependabot[bot]
c0716bc6e9 build(deps): bump url-parse from 1.5.1 to 1.5.3
Bumps [url-parse](https://github.com/unshiftio/url-parse) from 1.5.1 to 1.5.3.
- [Release notes](https://github.com/unshiftio/url-parse/releases)
- [Commits](https://github.com/unshiftio/url-parse/compare/1.5.1...1.5.3)

---
updated-dependencies:
- dependency-name: url-parse
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-11 11:37:34 +01:00
snyk-bot
358f858ad8 fix: upgrade multiple dependencies with Snyk
Snyk has created this PR to upgrade:
  - @babel/cli from 7.14.5 to 7.14.8.
    See this package in npm: https://www.npmjs.com/package/@babel/cli
  - @babel/core from 7.14.5 to 7.14.8.
    See this package in npm: https://www.npmjs.com/package/@babel/core
  - @babel/preset-env from 7.14.5 to 7.14.8.
    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-08-11 11:34:26 +01:00
snyk-bot
7a6e8a2940 fix: upgrade @grpc/grpc-js from 1.3.5 to 1.3.6
Snyk has created this PR to upgrade @grpc/grpc-js from 1.3.5 to 1.3.6.

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-08-10 12:14:34 +01:00
snyk-bot
96e82ad20d fix: upgrade @grpc/grpc-js from 1.3.4 to 1.3.5
Snyk has created this PR to upgrade @grpc/grpc-js from 1.3.4 to 1.3.5.

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-08-04 14:07:49 +01:00
snyk-bot
406afef7f7 fix: upgrade express-rate-limit from 5.2.6 to 5.3.0
Snyk has created this PR to upgrade express-rate-limit from 5.2.6 to 5.3.0.

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
2021-07-23 12:08:37 +01:00
snyk-bot
3ebe1938ab fix: upgrade core-js from 3.14.0 to 3.15.2
Snyk has created this PR to upgrade core-js from 3.14.0 to 3.15.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-07-21 12:35:06 +01:00
snyk-bot
ee2398f247 fix: upgrade @grpc/proto-loader from 0.6.3 to 0.6.4
Snyk has created this PR to upgrade @grpc/proto-loader from 0.6.3 to 0.6.4.

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-07-21 12:32:48 +01:00
xanoni
bc84429b61 README.md: cleaned up and removed 'deprecatedrpc' recommendation 2021-07-20 11:35:05 +01:00
snyk-bot
ec3039d91d fix: upgrade bolt11 from 1.3.1 to 1.3.2
Snyk has created this PR to upgrade bolt11 from 1.3.1 to 1.3.2.

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-07-20 11:33:21 +01:00
snyk-bot
1483449529 fix: upgrade @grpc/grpc-js from 1.3.3 to 1.3.4
Snyk has created this PR to upgrade @grpc/grpc-js from 1.3.3 to 1.3.4.

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-07-17 11:41:40 +01:00
snyk-bot
e0f037ea95 fix: upgrade jayson from 3.6.3 to 3.6.4
Snyk has created this PR to upgrade jayson from 3.6.3 to 3.6.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
2021-07-17 11:41:18 +01:00
snyk-bot
b4f880b35d fix: upgrade @grpc/proto-loader from 0.6.2 to 0.6.3
Snyk has created this PR to upgrade @grpc/proto-loader from 0.6.2 to 0.6.3.

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-07-16 11:06:57 +01:00
Overtorment
35fe816d0a Merge branch 'master' of github.com:BlueWallet/LndHub into sunset 2021-07-14 17:29:00 +01:00
snyk-bot
4a4daccecd fix: upgrade @grpc/grpc-js from 1.3.2 to 1.3.3
Snyk has created this PR to upgrade @grpc/grpc-js from 1.3.2 to 1.3.3.

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-07-14 16:53:23 +01:00
Overtorment
66b9d3ab92 ADD: option to shut lndhub down 2021-07-12 20:34:51 +01:00
Overtorment
87fc5d6ff7 Merge branch 'master' of github.com:BlueWallet/LndHub 2021-07-12 15:52:16 +01:00
Overtorment
e6b1f950f3 REF: force restart upon lnd failure; ADD: mission control in queryRoutes 2021-07-12 15:52:05 +01:00
snyk-bot
eab49fde2f fix: upgrade multiple dependencies with Snyk
Snyk has created this PR to upgrade:
  - @babel/cli from 7.14.3 to 7.14.5.
    See this package in npm: https://www.npmjs.com/package/@babel/cli
  - @babel/core from 7.14.3 to 7.14.5.
    See this package in npm: https://www.npmjs.com/package/@babel/core
  - @babel/node from 7.13.13 to 7.14.5.
    See this package in npm: https://www.npmjs.com/package/@babel/node
  - @babel/preset-env from 7.14.1 to 7.14.5.
    See this package in npm: https://www.npmjs.com/package/@babel/preset-env
  - @babel/register from 7.13.16 to 7.14.5.
    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-07-02 12:29:16 +01:00
snyk-bot
aa11daf608 fix: upgrade core-js from 3.13.0 to 3.14.0
Snyk has created this PR to upgrade core-js from 3.13.0 to 3.14.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-06-27 15:47:50 +01:00
Overtorment
4e7731ff54 REL: ver bump 2021-06-21 12:29:46 +01:00
Overtorment
1c8232d1ec FIX: hsts header 2021-06-21 12:29:13 +01:00
snyk-bot
fd6caf859c fix: upgrade core-js from 3.12.1 to 3.13.0
Snyk has created this PR to upgrade core-js from 3.12.1 to 3.13.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-06-16 11:32:20 +01:00
snyk-bot
df6412a525 fix: upgrade jayson from 3.6.1 to 3.6.3
Snyk has created this PR to upgrade jayson from 3.6.1 to 3.6.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
2021-06-12 17:23:22 +01:00
snyk-bot
c46c1385c6 fix: upgrade @babel/core from 7.14.0 to 7.14.3
Snyk has created this PR to upgrade @babel/core from 7.14.0 to 7.14.3.

See this package in npm:
https://www.npmjs.com/package/@babel/core

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-06-10 20:17:01 +01:00
snyk-bot
dd5d96aa56 fix: upgrade @babel/eslint-parser from 7.13.14 to 7.14.2
Snyk has created this PR to upgrade @babel/eslint-parser from 7.13.14 to 7.14.2.

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-06-09 14:00:02 +01:00
snyk-bot
d6d563039e fix: upgrade @grpc/grpc-js from 1.3.0 to 1.3.2
Snyk has created this PR to upgrade @grpc/grpc-js from 1.3.0 to 1.3.2.

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-06-09 13:57:01 +01:00
snyk-bot
f5eb5d0c78 fix: upgrade @babel/cli from 7.13.16 to 7.14.3
Snyk has created this PR to upgrade @babel/cli from 7.13.16 to 7.14.3.

See this package in npm:
https://www.npmjs.com/package/@babel/cli

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-06-08 14:03:38 +01:00
snyk-bot
9d17ceb23f fix: upgrade @grpc/proto-loader from 0.6.1 to 0.6.2
Snyk has created this PR to upgrade @grpc/proto-loader from 0.6.1 to 0.6.2.

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-06-02 13:17:17 +01:00
snyk-bot
d0406afd31 fix: upgrade prettier from 2.2.1 to 2.3.0
Snyk has created this PR to upgrade prettier from 2.2.1 to 2.3.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
2021-06-01 11:33:50 +01:00
snyk-bot
6411e9bd28 fix: upgrade core-js from 3.12.0 to 3.12.1
Snyk has created this PR to upgrade core-js from 3.12.0 to 3.12.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-05-31 12:07:34 +01:00
snyk-bot
db218ef440 fix: upgrade core-js from 3.11.2 to 3.12.0
Snyk has created this PR to upgrade core-js from 3.11.2 to 3.12.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-28 13:31:49 +01:00
snyk-bot
735b65dc0f fix: upgrade ioredis from 4.26.0 to 4.27.2
Snyk has created this PR to upgrade ioredis from 4.26.0 to 4.27.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
2021-05-26 11:25:53 +01:00
snyk-bot
c73d762028 fix: upgrade @babel/preset-env from 7.14.0 to 7.14.1
Snyk has created this PR to upgrade @babel/preset-env from 7.14.0 to 7.14.1.

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-26 11:25:30 +01:00
snyk-bot
4f3dff6022 fix: upgrade core-js from 3.11.1 to 3.11.2
Snyk has created this PR to upgrade core-js from 3.11.1 to 3.11.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-25 10:57:35 +01:00
snyk-bot
a792432700 fix: upgrade multiple dependencies with Snyk
Snyk has created this PR to upgrade:
  - @babel/core from 7.13.16 to 7.14.0.
    See this package in npm: https://www.npmjs.com/package/@babel/core
  - @babel/preset-env from 7.13.15 to 7.14.0.
    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-21 14:11:52 +01:00
snyk-bot
590bccd4c0 fix: upgrade core-js from 3.11.0 to 3.11.1
Snyk has created this PR to upgrade core-js from 3.11.0 to 3.11.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-05-20 10:14:45 +01:00
snyk-bot
d90881771c fix: upgrade jayson from 3.5.2 to 3.6.1
Snyk has created this PR to upgrade jayson from 3.5.2 to 3.6.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
2021-05-20 10:14:16 +01:00
snyk-bot
d9d75a0b29 fix: upgrade @grpc/grpc-js from 1.2.12 to 1.3.0
Snyk has created this PR to upgrade @grpc/grpc-js from 1.2.12 to 1.3.0.

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-05-19 12:13:10 +01:00
snyk-bot
34ffd59c1b fix: upgrade eslint-config-prettier from 8.1.0 to 8.3.0
Snyk has created this PR to upgrade eslint-config-prettier from 8.1.0 to 8.3.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
2021-05-17 12:24:48 +01:00
snyk-bot
7dce6b848e fix: upgrade jayson from 3.4.4 to 3.5.2
Snyk has created this PR to upgrade jayson from 3.4.4 to 3.5.2.

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
2021-05-17 12:21:29 +01:00
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 e890513e7ccd0e69f4d8a927e1c4bcdb37d98fab.
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
Overtorment
fc0d2a4c86 RE: v1.2.0 2020-05-04 14:11:56 +01:00
Overtorment
b125d68fff Merge branch 'master' of github.com:BlueWallet/LndHub 2020-05-04 14:10:22 +01:00
Overtorment
e390a06aae ADD: process-unpaid-invoices; REF: stuck payments script; REF: website; REF: important channels script; DOC: some docs 2020-05-04 14:09:37 +01:00
snyk-bot
c8ef1e59e2 fix: upgrade ioredis from 4.16.1 to 4.16.2
Snyk has created this PR to upgrade ioredis from 4.16.1 to 4.16.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-05-04 11:45:14 +01:00
snyk-bot
3ad92da8a6 fix: upgrade ioredis from 4.16.1 to 4.16.2
Snyk has created this PR to upgrade ioredis from 4.16.1 to 4.16.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-05-04 11:45:14 +01:00
snyk-bot
61956f2a46 fix: upgrade prettier from 2.0.3 to 2.0.4
Snyk has created this PR to upgrade prettier from 2.0.3 to 2.0.4.

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-04-29 16:15:15 +01:00
snyk-bot
93899facd6 fix: upgrade prettier from 2.0.3 to 2.0.4
Snyk has created this PR to upgrade prettier from 2.0.3 to 2.0.4.

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-04-29 16:15:15 +01:00
snyk-bot
6723094ed6 fix: upgrade prettier from 2.0.2 to 2.0.3
Snyk has created this PR to upgrade prettier from 2.0.2 to 2.0.3.

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-04-28 16:59:39 +01:00
snyk-bot
ca1f5427cb fix: upgrade prettier from 2.0.2 to 2.0.3
Snyk has created this PR to upgrade prettier from 2.0.2 to 2.0.3.

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-04-28 16:59:39 +01:00
Overtorment
d4e8d9b476
Merge pull request #61 from bitarmy/master
Minimal changes
2020-04-02 10:46:53 +01:00
Agustin Kassis
3a2ee779b6 Revert config change 2020-04-01 23:08:02 -03:00
Agustin Kassis
ea1035e414 Lookup invoice on lnd if not already cached as paid on redis 2020-04-01 22:58:24 -03:00
Agustin Kassis
7afb56398a Updated npm packages 2020-04-01 20:52:22 -03:00
Agustin Kassis
a4cd81a106 Removed duplicated balance api 2020-04-01 20:51:14 -03:00
Agustin Kassis
7a94225d87 Error typos 2020-04-01 20:46:48 -03:00
Agustin Kassis
9be413a549 added tls.cert debug 2020-04-01 20:43:36 -03:00
Agustin Kassis
305559174f Removed checkinvoicepaid 2020-04-01 20:43:13 -03:00
Agustin Kassis
bfdd319070 Height check only on mainnet 2020-04-01 20:32:22 -03:00
Agustin Kassis
a6b08363a7 Merge branch 'bluewallet-lndhub'
# Conflicts:
#	controllers/api.js
2020-03-30 21:24:32 -03:00
Overtorment
9f45c31618 REL: ver bump 2020-03-27 21:09:55 +00:00
Overtorment
d7e91f51ec REF: get user invoices 2020-03-27 21:03:38 +00:00
Overtorment
b58e7dac88 stricted rate limiting for /getuserinvoices 2020-03-27 20:09:50 +00:00
Overtorment
7b5c6bc7e0 REF: more logging 2020-03-27 19:51:06 +00:00
Agustin Kassis
f9b2cca0bd Check individual invoice's payment 2020-03-23 13:44:44 +00:00
Agustin Kassis
376a3402bd Merge branch 'bluewallet-lndhub' 2020-03-20 20:32:07 -03:00
Agustin Kassis
38a3dea8c2 Check individual invoice's payment 2020-03-20 19:56:22 -03:00
snyk-bot
cdcd1fdd82 fix: upgrade babel-eslint from 10.0.3 to 10.1.0
Snyk has created this PR to upgrade babel-eslint from 10.0.3 to 10.1.0.

See this package in NPM:
https://www.npmjs.com/package/babel-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
2020-03-19 10:34:11 +00:00
dependabot[bot]
f4105292a3 Build(deps): Bump acorn from 6.3.0 to 6.4.1
Bumps [acorn](https://github.com/acornjs/acorn) from 6.3.0 to 6.4.1.
- [Release notes](https://github.com/acornjs/acorn/releases)
- [Commits](https://github.com/acornjs/acorn/compare/6.3.0...6.4.1)

Signed-off-by: dependabot[bot] <support@github.com>
2020-03-16 11:57:49 +00:00
Agustin Kassis
6074dc6c2c Merge branch 'bluewallet-lndhub'
# Conflicts:
#	package.json
2020-03-15 00:19:51 -03:00
snyk-bot
76421f2850 fix: upgrade ioredis from 4.15.1 to 4.16.0
Snyk has created this PR to upgrade ioredis from 4.15.1 to 4.16.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-03-13 11:42:52 +00:00
Overtorment
f01c533899 REF: minor 2020-03-11 16:01:35 +00:00
Overtorment
6b67839414 REF 2020-03-02 12:34:43 +00:00
Overtorment
dfe55a4f9f Merge branch 'master' of github.com:BlueWallet/LndHub 2020-01-25 15:41:55 +00:00
Overtorment
14d42a7aed REF 2020-01-25 15:41:49 +00:00
snyk-bot
a4b24ec00a fix: upgrade mustache from 3.1.0 to 3.2.1
Snyk has created this PR to upgrade mustache from 3.1.0 to 3.2.1.

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

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-01-25 15:00:02 +00:00
snyk-bot
0a0bf5caa3 fix: upgrade ioredis from 4.14.1 to 4.15.1
Snyk has created this PR to upgrade ioredis from 4.14.1 to 4.15.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-01-25 14:59:49 +00:00
snyk-bot
2f1c89bb8f fix: upgrade prettier from 1.18.2 to 1.19.1
Snyk has created this PR to upgrade prettier from 1.18.2 to 1.19.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-01-25 14:58:36 +00:00
snyk-bot
243902faad fix: upgrade eslint-plugin-prettier from 3.1.1 to 3.1.2
Snyk has created this PR to upgrade eslint-plugin-prettier from 3.1.1 to 3.1.2.

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-01-25 14:57:47 +00:00
Overtorment
03ddddbf6a Merge branch 'master' of github.com:BlueWallet/LndHub 2020-01-24 21:20:03 +00:00
Overtorment
8e06bef3b9 REF: better error handling 2020-01-24 21:19:54 +00:00
Overtorment
b55e0f0327
FIX: fees 2020-01-24 09:44:13 +00:00
Overtorment
ec9a71f4e9 FIX: account for msats in /payinvoice 2020-01-24 00:19:27 +00:00
Overtorment
9d8466b595 FIX: invoice description decode 2020-01-23 23:09:50 +00:00
Overtorment
0f6a4d8cba FIX: default invoice expiry is 24h 2020-01-19 23:43:45 +00:00
Overtorment
b56064a7ba
error logging 2020-01-18 13:39:55 +00:00
Agustin Kassis
6507de9770 Updated npm packages to latest version
Remove blockcount check for regtest
FIX
FIX: change default ln invoice expiry hour -> day
REF
FIX: added some caching; skip checking old invoices
Update README.md
2020-01-14 13:25:51 -03:00
Overtorment
1e17b9925b FIX 2019-12-21 15:00:36 +00:00
Overtorment
41736cccd8 FIX: change default ln invoice expiry hour -> day 2019-12-14 19:51:44 +00:00
Overtorment
dd409cc04f REF 2019-12-14 19:26:06 +00:00
Overtorment
daeae3c72d FIX: added some caching; skip checking old invoices 2019-12-14 19:25:14 +00:00
Overtorment
3af9cda96d
Update README.md 2019-12-09 21:41:25 +00:00
Agustin Kassis
8f28fd2865 Updated npm packages to latest version 2019-11-26 18:12:00 -03:00
Agustin Kassis
013cadc5c8 Remove blockcount check for regtest 2019-11-26 18:05:12 -03:00
Overtorment
ba38ed330d OPS 2019-11-04 15:09:19 +00:00
Overtorment
bac9480f31 OPS 2019-11-04 14:51:51 +00:00
Overtorment
5895573112 Merge branch 'master' of github.com:BlueWallet/LndHub 2019-11-04 14:36:23 +00:00
Overtorment
d595120a05 OPS 2019-11-04 14:36:15 +00:00
Kim Neunert
60ea4b2368 MIT License added see #40 2019-11-04 14:23:43 +00:00
Overtorment
8aa496938e DOC 2019-05-18 12:23:49 +01:00
Overtorment
070a7d8232 ADD: some util cli scripts 2019-05-03 22:33:54 +01:00
Overtorment
cc4503ecbd ADD: preimage in /gettxs response 2019-05-03 22:31:22 +01:00
Overtorment
cf5441c08a FIX: NaN 2019-04-14 20:06:50 +01:00
Overtorment
2c25a2090e FIX: better stuck payments handling 2019-04-13 18:56:12 +01:00
Overtorment
35d8ff5599 FIX: improve stuck payments processing 2019-04-13 00:27:07 +01:00
Overtorment
4a871a7d17 FIX: listtransactions caching 2019-04-06 20:21:13 +01:00
alerobrod
6a6611e9b6 Issue #12: Fix to ensure the Bluewallet app does not see on-chain Tx(s) if LND was to funnel channels using the user's BTC address for deposits. 2019-04-06 18:38:07 +01:00
alerobrod
16c6d167da Issue #12: Fetching all on-chain txs and filtering based on user's address. Note: This permits running LndHub without -deprecatedrpc=accounts switch. 2019-04-06 18:38:07 +01:00
Overtorment
70262b1059 FIX 2019-04-04 17:22:54 +01:00
Overtorment
724bc3d656 REF 2019-04-04 14:10:05 +01:00
Overtorment
862cda69fa FIX: internal invoice fee 2019-04-04 13:38:09 +01:00
Overtorment
75bfac565c REF 2019-04-04 12:51:46 +01:00
Overtorment
0f423817c3 ADD: rate limiting 2019-03-21 21:45:22 +00:00
Overtorment
995374ff48 ADD: rate limiting 2019-03-21 20:49:45 +00:00
Overtorment
0fed216b32 FIX: fee_limit when paying 2019-03-19 00:11:25 +00:00
Overtorment
067f2aeae4 FIX 2019-03-14 00:04:01 +00:00
Overtorment
f0d9fee177 Merge branch 'master' of github.com:BlueWallet/LndHub 2019-03-13 23:51:39 +00:00
Overtorment
a74f1e9ff2 FIX: adjusted fees; cache invalidation 2019-03-13 23:51:28 +00:00
Dimitris Tsapakidis
43ceee11ce Fix typos in Send-requirements.md 2019-03-13 20:25:17 +00:00
Overtorment
7c71c5e775 DOC 2019-03-13 00:21:27 +00:00
Igor Korsakov
92f1370dba
Merge pull request #25 from BlueWallet/unlock-payments-script_ver2
ADD: unlock stuck payments script
2019-03-10 23:41:10 +00:00
Overtorment
c1ac67a853 ADD: unlock stuck payments script 2019-03-10 23:39:48 +00:00
Igor Korsakov
7517b02d1e
Merge pull request #24 from BlueWallet/revert-23-unlock-payments-script
Revert "ADD: unlock stuck payments script"
2019-03-10 23:38:36 +00:00
Igor Korsakov
454dc50693
Revert "ADD: unlock stuck payments script" 2019-03-10 23:38:23 +00:00
Igor Korsakov
6cf75686da
Merge pull request #23 from BlueWallet/unlock-payments-script
ADD: unlock stuck payments script
2019-03-10 23:34:18 +00:00
Overtorment
7eea6c650f ADD: unlock stuck payments script 2019-03-10 23:32:34 +00:00
Overtorment
1ad26e21b8 ADD: Proper error message when payment fails 2019-03-06 23:59:06 +00:00
Overtorment
f7ed99173f Merge branch 'master' of github.com:BlueWallet/LndHub 2019-03-06 20:21:51 +00:00
Overtorment
402d07a97f FIX: sometimes feex are x10 bigger than they should 2019-03-06 20:21:37 +00:00
Igor Korsakov
6fa5791d89
Merge pull request #21 from BlueWallet/revert-20-master
Revert "Some minor fixes"
2019-03-06 20:14:54 +00:00
Igor Korsakov
31b718e115
Revert "Some minor fixes" 2019-03-06 20:14:39 +00:00
Igor Korsakov
1da578e8a4
Merge pull request #20 from Mikefluff/master
Some minor fixes
2019-03-06 19:36:12 +00:00
Mike Fluff
3317e620dd Linter fixes 2019-03-06 11:36:19 +07:00
Mike Fluff
cb722e1608 Fix after merge 2019-03-06 11:34:17 +07:00
Mike Fluff
f624ced5ce Fix with null result TXs fetcher 2019-03-06 11:27:40 +07:00
Mike Fluff
27ebe36b4b Merge branch 'master' of github.com:BlueWallet/LndHub 2019-03-06 11:02:45 +07:00
Mike Fluff
65a9541673 TLS config fix 2019-03-06 11:01:59 +07:00
Overtorment
77fb7c0daa FIX: display negative balance as zero 2019-03-04 12:16:03 +00:00
Overtorment
23e835c888 FIX: fees 2019-03-03 22:01:15 +00:00
Overtorment
91f552ca7e ADD: fees 2019-03-03 18:57:45 +00:00
Overtorment
8f2d98774b FIX: properly locked payments 2019-03-03 15:59:30 +00:00
Overtorment
afb07aa9ba REF: remove debug 2019-03-01 22:47:43 +00:00
Overtorment
3cbe38ed28 FIX: increase lock 2019-03-01 22:41:50 +00:00
Overtorment
17cd8adf41 REF 2019-02-28 23:07:31 +00:00
Overtorment
1a740d6b06 REF 2019-02-28 22:23:21 +00:00
Overtorment
ef9cc6d388 Merge branch 'master' of github.com:BlueWallet/LndHub 2019-02-16 13:07:19 +00:00
Overtorment
a7cfbca1e7 DOC 2019-02-16 13:07:08 +00:00
Overtorment
daa25d1b75 OPS 2019-02-16 12:58:34 +00:00
Igor Korsakov
fe6cf0e860
Update README.md 2019-02-07 14:46:00 +00:00
Overtorment
e9bf03b58b Merge branch 'master' of github.com:BlueWallet/LndHub 2019-02-06 20:52:22 +00:00
Overtorment
efd31067ba REF: default lock time 2 min -> 5 min 2019-02-06 20:50:58 +00:00
Igor Korsakov
db9ccb9dbe
Merge pull request #10 from marcosrdz/patch-1
ADD: Added  '1.ln.aantonop.com',
2019-02-03 21:56:12 +00:00
Marcos Rodriguez Vélez
2f5f300a90
ADD: Added '1.ln.aantonop.com', 2019-02-03 16:22:20 -05:00
Overtorment
216de588a0 Merge branch 'master' of github.com:BlueWallet/LndHub 2019-02-02 23:22:49 +00:00
Overtorment
6d2abdfcce OPS: logging 2019-02-02 23:22:33 +00:00
Igor Korsakov
dd288d413f
Update README.md 2019-02-01 19:28:26 +00:00
Overtorment
d04b155e11 FIX: can pay negative free amount invoices 2019-02-01 19:06:47 +00:00
Overtorment
e59ea298d1 REF: removing unsued by client fields to reduce size 2019-01-28 21:39:34 +00:00
Overtorment
d6bb2bbe25 REF 2019-01-26 00:15:29 +00:00
Overtorment
da37b5315d REF: better logging 2019-01-25 23:44:07 +00:00
Overtorment
1df24d0e80 ADD: lnd wallet unlock attempt upon start 2019-01-25 22:59:32 +00:00
Overtorment
0f75933bf0 FIX: no crash 2019-01-24 20:14:27 +00:00
Overtorment
4a9c4ef996 Merge branch 'master' of github.com:BlueWallet/LndHub 2019-01-23 12:12:27 +00:00
Overtorment
dec313aa4c FIX: incorrect balance after invoice paid 2019-01-23 12:12:16 +00:00
Overtorment
b85097f7cc OPS: dep 2019-01-23 11:55:36 +00:00
Overtorment
c1e13e9c8c FIX: (re #8) 2019-01-21 20:18:04 +00:00
Overtorment
e854626a45 FIX: more strict balance check (re #8) 2019-01-21 19:49:19 +00:00
Overtorment
f2386f0acf REF: retry 2019-01-21 14:18:09 +00:00
Overtorment
ff2d98dc10 OPS: turn off explicit logging 2019-01-21 13:17:23 +00:00
Overtorment
9c47746eba FIX: redis balance is only a cashe; tx list is a source of truth for user's balance 2019-01-21 13:17:04 +00:00
Overtorment
a08f02572f ADD: limit to getUserInvoices 2019-01-10 17:01:46 +00:00
Overtorment
f2616044eb ADD: globee 2019-01-10 12:32:01 +00:00
Overtorment
4317123ffe FIX (rel #3) 2019-01-09 02:38:54 +00:00
Overtorment
dd7430503d FIX: able to pay same internal invoice twice (closes #5) 2019-01-09 01:56:09 +00:00
Overtorment
d8bd2aacdf FIX: better locking when importing onchain tx 2019-01-07 17:25:04 +00:00
Overtorment
b7073abb0e FIX: better locks (rel #3) 2019-01-07 16:40:32 +00:00
Overtorment
98ba940342 REL 2019-01-07 16:21:35 +00:00
Overtorment
6851769be6 FIX: no crashes, just hangs 2019-01-06 14:36:23 +00:00
Overtorment
d3100a1390 FIX: occasional duplicate payments (closes #3) 2019-01-06 14:35:14 +00:00
Overtorment
6a57559b16 REF 2019-01-06 13:37:37 +00:00
Overtorment
4f345b20a8 FIX: potential crash 2019-01-06 13:17:52 +00:00
Overtorment
a42d331e38 FIX: potential crash 2019-01-06 12:44:41 +00:00
Overtorment
130a8dc773 FIX: potential crash 2019-01-06 12:19:08 +00:00
Overtorment
b3c0873e4c FIX: more logging, more error handling 2019-01-05 22:01:50 +00:00
Overtorment
6a3de700f4 FIX: race condition when processing onchain topup 2019-01-05 21:27:34 +00:00
Overtorment
51b0f89fd1 REF: better channels display 2019-01-05 18:10:05 +00:00
Overtorment
55ac146f1e FIX: potential crash 2019-01-05 18:09:30 +00:00
Overtorment
2904afaf26 FIX: possible crashes 2019-01-05 16:16:28 +00:00
Overtorment
2cd9a19d67 REL 2019-01-05 14:52:45 +00:00
Overtorment
765eeed9c9 ADD: pay for zero-amount (tip) invoices 2019-01-05 14:52:27 +00:00
Overtorment
bc5841d07d OPS 2019-01-03 01:28:26 +00:00
Overtorment
5b8ab18a59 OPS 2018-12-30 19:28:10 +00:00
Overtorment
7e1d4a3110 OPS 2018-12-27 00:44:28 +00:00
Overtorment
5100252ea5 FIX: internal invoice wasnt saving record in senders tx list 2018-12-27 00:44:13 +00:00
Overtorment
b8bc4dd0cd FIX: user invoice 2018-12-25 17:40:21 +00:00
Overtorment
a7294cbbbd FIX: user invoice 2018-12-25 16:16:54 +00:00
Overtorment
950900b136 FIX: user invoice 2018-12-25 15:23:18 +00:00
Overtorment
4ad56aaebe OPS 2018-12-25 13:51:38 +00:00
Overtorment
f4b35e4895 ADD: channel list in lndhub console 2018-12-25 13:51:29 +00:00
Overtorment
9e70f123a6 FIX: user invoices are correctly processed if paid 2018-12-25 13:50:09 +00:00
43 changed files with 9368 additions and 6457 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:16-bullseye-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:16-bullseye-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

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 BlueWallet
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,21 +1,33 @@
LndHub
======
Wrapper for Lightning Network Daemon. It provides separate accounts with minimum trust for end users
Wrapper for Lightning Network Daemon (lnd). It provides separate accounts with minimum trust for end users.
INSTALLATION
------------
You can use those guides or follow instructions below:
* https://github.com/dangeross/guides/blob/master/raspibolt/raspibolt_6B_lndhub.md
* https://medium.com/@jpthor/running-lndhub-on-mac-osx-5be6671b2e0c
```
git clone git@github.com:BlueWallet/LndHub.git
cd LndHub
npm i
```
Install `bitcoind`, `lnd` and `redis`.
Install `bitcoind`, `lnd`, and `redis`. Edit LndHub's `config.js` to set it up correctly.
Copy the files `admin.macaroon` (for Bitcoin mainnet, usually stored in `~/.lnd/data/chain/bitcoin/mainnet/admin.macaroon`)
and `tls.cert` (usually stored in `~/.lnd/tls.cert`) into the root folder of LndHub.
Edit `config.js` and set it up correctly.
Copy `admin.macaroon` and `tls.cert` in root folder of LndHub.
LndHub expects LND's wallet to be unlocked, if not — it will attempt to unlock it with the password stored in `config.lnd.password`.
Don't forget to configure disk-persistence for `redis` (e.g., you may want to set `appendonly` to `yes` in `redis.conf` (see
http://redis.io/topics/persistence for more information).
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 note that this feature is limited to Bitcoin, so you can't use it if you use any other cryptocurrency with LND (e.g., Litecoin).
### Deploy to Heroku
@ -24,7 +36,29 @@ 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
* https://github.com/BlueWallet/BlueWallet/blob/master/class/wallets/lightning-custodian-wallet.js
### Tests
Acceptance tests are in https://github.com/BlueWallet/BlueWallet/blob/master/LightningCustodianWallet.test.js
Acceptance tests are in https://github.com/BlueWallet/BlueWallet/blob/master/tests/integration/lightning-custodian-wallet.test.js
![image](https://user-images.githubusercontent.com/1913337/52418916-f30beb00-2ae6-11e9-9d63-17189dc1ae8c.png)
## Responsible disclosure
Found critical bugs/vulnerabilities? Please email them to bluewallet@bluewallet.io
Thanks!

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 = 5000;
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();
};

113
class/Invo.js Normal file
View File

@ -0,0 +1,113 @@
var crypto = require('crypto');
var lightningPayReq = require('bolt11');
export class Invo {
constructor(redis, bitcoindrpc, lightning) {
this._redis = redis;
this._bitcoindrpc = bitcoindrpc;
this._lightning = lightning;
this._decoded = false;
this._bolt11 = false;
this._isPaid = null;
}
setInvoice(bolt11) {
this._bolt11 = bolt11;
}
async getIsMarkedAsPaidInDatabase() {
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._getIsPaymentHashMarkedPaidInDatabase(paymentHash);
}
async markAsPaidInDatabase() {
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._setIsPaymentHashPaidInDatabase(paymentHash, decoded.satoshis);
}
async markAsUnpaidInDatabase() {
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._setIsPaymentHashPaidInDatabase(paymentHash, false);
}
async _setIsPaymentHashPaidInDatabase(paymentHash, settleAmountSat) {
if (settleAmountSat) {
return await this._redis.set('ispaid_' + paymentHash, settleAmountSat);
} else {
return await this._redis.del('ispaid_' + paymentHash);
}
}
async _getIsPaymentHashMarkedPaidInDatabase(paymentHash) {
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
*
* @return {Promise<array>}
*/
async listInvoices() {
return new Promise((resolve, reject) => {
this._lightning.listInvoices(
{
num_max_invoices: 99000111,
reversed: true,
},
function (err, response) {
if (err) return reject(err);
resolve(response);
},
);
});
}
}

35
class/Lock.js Normal file
View File

@ -0,0 +1,35 @@
export class Lock {
/**
*
* @param {Redis} redis
* @param {String} lock_key
*/
constructor(redis, lock_key) {
this._redis = redis;
this._lock_key = lock_key;
}
/**
* Tries to obtain lock in single-threaded Redis.
* Returns TRUE if success.
*
* @returns {Promise<boolean>}
*/
async obtainLock() {
const timestamp = +new Date();
let setResult = await this._redis.setnx(this._lock_key, timestamp);
if (!setResult) {
// it already held a value - failed locking
return false;
}
// success - got lock
await this._redis.expire(this._lock_key, 5 * 60);
// lock expires in 5 mins just for any case
return true;
}
async releaseLock() {
await this._redis.del(this._lock_key);
}
}

155
class/Paym.js Normal file
View File

@ -0,0 +1,155 @@
var crypto = require('crypto');
var lightningPayReq = require('bolt11');
import { BigNumber } from 'bignumber.js';
export class Paym {
constructor(redis, bitcoindrpc, lightning) {
this._redis = redis;
this._bitcoindrpc = bitcoindrpc;
this._lightning = lightning;
this._decoded = false;
this._bolt11 = false;
this._isPaid = null;
}
setInvoice(bolt11) {
this._bolt11 = bolt11;
}
async decodePayReqViaRpc(invoice) {
let that = this;
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);
});
});
}
async queryRoutes() {
if (!this._bolt11) throw new Error('bolt11 is not provided');
if (!this._decoded) await this.decodePayReqViaRpc(this._bolt11);
var request = {
pub_key: this._decoded.destination,
amt: this._decoded.num_satoshis,
final_cltv_delta: 144,
fee_limit: { fixed: Math.floor(this._decoded.num_satoshis * forwardFee) + 1 },
};
let that = this;
return new Promise(function (resolve, reject) {
that._lightning.queryRoutes(request, function (err, response) {
if (err) return reject(err);
resolve(response);
});
});
}
async sendToRouteSync(routes) {
if (!this._bolt11) throw new Error('bolt11 is not provided');
if (!this._decoded) await this.decodePayReqViaRpc(this._bolt11);
let request = {
payment_hash_string: this._decoded.payment_hash,
route: routes[0],
};
console.log('sendToRouteSync:', { request });
let that = this;
return new Promise(function (resolve, reject) {
that._lightning.sendToRouteSync(request, function (err, response) {
if (err) reject(err);
resolve(that.processSendPaymentResponse(response));
});
});
}
processSendPaymentResponse(payment) {
if (payment && payment.payment_route && payment.payment_route.total_amt_msat) {
// paid just now
this._isPaid = true;
payment.payment_route.total_fees = +payment.payment_route.total_fees + Math.floor(+payment.payment_route.total_amt * internalFee);
if (this._bolt11) payment.pay_req = this._bolt11;
if (this._decoded) payment.decoded = this._decoded;
}
if (payment.payment_error && payment.payment_error.indexOf('already paid') !== -1) {
// already paid
this._isPaid = true;
if (this._decoded) {
payment.decoded = this._decoded;
if (this._bolt11) payment.pay_req = this._bolt11;
// trying to guess the fee
payment.payment_route = payment.payment_route || {};
payment.payment_route.total_fees = Math.floor(this._decoded.num_satoshis * forwardFee); // we dont know the exact fee, so we use max (same as fee_limit)
payment.payment_route.total_amt = this._decoded.num_satoshis;
}
}
if (payment.payment_error && payment.payment_error.indexOf('unable to') !== -1) {
// failed to pay
this._isPaid = false;
}
if (payment.payment_error && payment.payment_error.indexOf('FinalExpiryTooSoon') !== -1) {
this._isPaid = false;
}
if (payment.payment_error && payment.payment_error.indexOf('UnknownPaymentHash') !== -1) {
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
}
return payment;
}
/**
* Returns NULL if unknown, true if its paid, false if its unpaid
* (judging by error in sendPayment response)
*
* @returns {boolean|null}
*/
getIsPaid() {
return this._isPaid;
}
async attemptPayToRoute() {
let routes = await this.queryRoutes();
return await this.sendToRouteSync(routes.routes);
}
async listPayments() {
return new Promise((resolve, reject) => {
this._lightning.listPayments({}, function (err, response) {
if (err) return reject(err);
resolve(response);
});
});
}
async isExpired() {
if (!this._bolt11) throw new Error('bolt11 is not provided');
const decoded = await this.decodePayReqViaRpc(this._bolt11);
return +decoded.timestamp + +decoded.expiry < +new Date() / 1000;
}
decodePayReqLocally(payReq) {
this._decoded_locally = lightningPayReq.decode(payReq);
}
async getPaymentHash() {
if (!this._bolt11) throw new Error('bolt11 is not provided');
if (!this._decoded) await this.decodePayReqViaRpc(this._bolt11);
return this._decoded['payment_hash'];
}
}

View File

@ -1,6 +1,15 @@
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 = {};
let _listtransactions_cache = false;
let _listtransactions_cache_expiry_ts = 0;
export class User {
/**
@ -35,6 +44,7 @@ export class User {
}
async loadByAuthorization(authorization) {
if (!authorization) return false;
let access_token = authorization.replace('Bearer ', '');
let userid = await this._redis.get('userid_for_' + access_token);
@ -99,23 +109,94 @@ 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 getBalance() {
return (await this._redis.get('balance_for_' + this._userid)) * 1;
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.
*
* @returns {Promise<number>} Balance available to spend
*/
async getBalance() {
let balance = (await this._redis.get('balance_for_' + this._userid)) * 1;
if (!balance) {
balance = await this.getCalculatedBalance();
await this.saveBalance(balance);
}
return balance;
}
/**
* Accounts for all possible transactions in user's account and
* sums their amounts.
*
* @returns {Promise<number>} Balance available to spend
*/
async getCalculatedBalance() {
let calculatedBalance = 0;
let userinvoices = await this.getUserInvoices();
for (let invo of userinvoices) {
if (invo && invo.ispaid) {
calculatedBalance += +invo.amt;
}
}
let txs = await this.getTxs();
for (let tx of txs) {
if (tx.type === 'bitcoind_tx') {
// topup
calculatedBalance += new BigNumber(tx.amount).multipliedBy(100000000).toNumber();
} else {
calculatedBalance -= +tx.value;
}
}
let lockedPayments = await this.getLockedPayments();
for (let paym of lockedPayments) {
// locked payments are processed in scripts/process-locked-payments.js
calculatedBalance -= +paym.amount + /* feelimit */ Math.floor(paym.amount * forwardFee);
}
return calculatedBalance;
}
/**
* LndHub no longer relies on redis balance as source of truth, this is
* more a cache now. See `this.getCalculatedBalance()` to get correct balance.
*
* @param balance
* @returns {Promise<void>}
*/
async saveBalance(balance) {
return await this._redis.set('balance_for_' + this._userid, balance);
const key = 'balance_for_' + this._userid;
await this._redis.set(key, balance);
await this._redis.expire(key, 1800);
}
async clearBalanceCache() {
const key = 'balance_for_' + this._userid;
return this._redis.del(key);
}
async savePaidLndInvoice(doc) {
@ -144,15 +225,17 @@ export class User {
/**
* Doent belong here, FIXME
* @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);
});
@ -161,13 +244,29 @@ export class User {
/**
* Doent belong here, FIXME
* @see Invo._getIsPaymentHashMarkedPaidInDatabase
* @see Invo.getIsMarkedAsPaidInDatabase
*/
async getPaymentHashPaid(payment_hash) {
return await this._redis.get('ispaid_' + payment_hash);
}
async getUserInvoices() {
async syncInvoicePaid(payment_hash) {
const invoice = await this.lookupInvoice(payment_hash);
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, invoice.amt_paid_msat ? Math.floor(invoice.amt_paid_msat / 1000) : invoice.amt_paid_sat);
await this.clearBalanceCache();
}
return ispaid;
}
async getUserInvoices(limit) {
let range = await this._redis.lrange('userinvoices_for_' + this._userid, 0, -1);
if (limit && !isNaN(parseInt(limit))) {
range = range.slice(parseInt(limit) * -1);
}
let result = [];
for (let invoice of range) {
invoice = JSON.parse(invoice);
@ -175,20 +274,46 @@ export class User {
invoice.description = '';
for (let tag of decoded.tags) {
if (tag.tagName === 'description') {
invoice.description += decodeURIComponent(tag.data);
try {
invoice.description += decodeURIComponent(tag.data);
} catch (_) {
invoice.description += tag.data;
}
}
if (tag.tagName === 'payment_hash') {
invoice.payment_hash = tag.data;
}
}
invoice.ispaid = !!(await this.getPaymentHashPaid(invoice.payment_hash));
if (!invoice.ispaid) {
// attempting to lookup invoice
let lookup_info = await this.lookupInvoice(invoice.payment_hash);
invoice.ispaid = lookup_info.settled;
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;
}
invoice.amt = decoded.satoshis;
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] = paymentHashPaidAmountSat;
}
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;
invoice.type = 'user_invoice';
result.push(invoice);
}
@ -201,17 +326,17 @@ export class User {
/**
* User's onchain txs that are >= 3 confs
* Queries bitcoind RPC.
*
* @returns {Promise<Array>}
*/
async getTxs() {
let addr = await this.getAddress();
if (!addr) throw new Error('cannot get transactions: no onchain address assigned to user');
let txs = await this._bitcoindrpc.request('listtransactions', [addr, 100500, 0, true]);
const addr = await this.getOrGenerateAddress();
let txs = await this._listtransactions();
txs = txs.result;
let result = [];
for (let tx of txs) {
if (tx.confirmations >= 3) {
if (tx.confirmations >= 3 && tx.address === addr && tx.category === 'receive') {
tx.type = 'bitcoind_tx';
result.push(tx);
}
@ -221,29 +346,132 @@ export class User {
for (let invoice of range) {
invoice = JSON.parse(invoice);
invoice.type = 'paid_invoice';
invoice.fee = +invoice.payment_route.total_fees;
invoice.value = +invoice.payment_route.total_fees + +invoice.payment_route.total_amt;
invoice.timestamp = invoice.decoded.timestamp;
invoice.memo = invoice.decoded.description;
// for internal invoices it might not have properties `payment_route` and `decoded`...
if (invoice.payment_route) {
invoice.fee = +invoice.payment_route.total_fees;
invoice.value = +invoice.payment_route.total_fees + +invoice.payment_route.total_amt;
if (invoice.payment_route.total_amt_msat && invoice.payment_route.total_amt_msat / 1000 !== +invoice.payment_route.total_amt) {
// okay, we have to account for MSAT
invoice.value =
+invoice.payment_route.total_fees +
Math.max(parseInt(invoice.payment_route.total_amt_msat / 1000), +invoice.payment_route.total_amt) +
1; // extra sat to cover for msats, as external layer (clients) dont have that resolution
}
} else {
invoice.fee = 0;
}
if (invoice.decoded) {
invoice.timestamp = invoice.decoded.timestamp;
invoice.memo = invoice.memo || invoice.decoded.description;
}
if (invoice.payment_preimage) {
invoice.payment_preimage = Buffer.from(invoice.payment_preimage, 'hex').toString('hex');
}
// removing unsued by client fields to reduce size
delete invoice.payment_error;
delete invoice.payment_route;
delete invoice.pay_req;
delete invoice.decoded;
result.push(invoice);
}
return result;
}
/**
* Simple caching for this._bitcoindrpc.request('listtransactions', ['*', 100500, 0, true]);
* since its too much to fetch from bitcoind every time
*
* @returns {Promise<*>}
* @private
*/
async _listtransactions() {
let response = _listtransactions_cache;
if (response) {
if (+new Date() > _listtransactions_cache_expiry_ts) {
// invalidate cache
response = _listtransactions_cache = false;
} else {
try {
return JSON.parse(response);
} catch (_) {
// nop
}
}
}
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);
}
}
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);
});
});
}
/**
* Returning onchain txs for user's address that are less than 3 confs
*
* @returns {Promise<Array>}
*/
async getPendingTxs() {
let addr = await this.getAddress();
if (!addr) throw new Error('cannot get transactions: no onchain address assigned to user');
let txs = await this._bitcoindrpc.request('listtransactions', [addr, 100500, 0, true]);
const addr = await this.getOrGenerateAddress();
let txs = await this._listtransactions();
txs = txs.result;
let result = [];
for (let tx of txs) {
if (tx.confirmations < 3) {
if (tx.confirmations < 3 && tx.address === addr && tx.category === 'receive') {
result.push(tx);
}
}
@ -276,8 +504,9 @@ export class User {
* @returns {Promise<void>}
*/
async accountForPosibleTxids() {
let imported_txids = await this._redis.lrange('imported_txids_for_' + this._userid, 0, -1);
// return; // TODO: remove
let onchain_txs = await this.getTxs();
let imported_txids = await this._redis.lrange('imported_txids_for_' + this._userid, 0, -1);
for (let tx of onchain_txs) {
if (tx.type !== 'bitcoind_tx') continue;
let already_imported = false;
@ -286,19 +515,103 @@ export class User {
}
if (!already_imported && tx.category === 'receive') {
let userBalance = await this.getBalance();
userBalance += new BigNumber(tx.amount).multipliedBy(100000000).toNumber();
// first, locking...
let lock = new Lock(this._redis, 'importing_' + tx.txid);
if (!(await lock.obtainLock())) {
// someone's already importing this tx
return;
}
let userBalance = await this.getCalculatedBalance();
// userBalance += new BigNumber(tx.amount).multipliedBy(100000000).toNumber();
// no need to add since it was accounted for in `this.getCalculatedBalance()`
await this.saveBalance(userBalance);
await this._redis.rpush('imported_txids_for_' + this._userid, tx.txid);
await lock.releaseLock();
}
}
}
/**
* Adds invoice to a list of user's locked payments.
* Used to calculate balance till the lock is lifted (payment is in
* determined state - succeded or failed).
*
* @param {String} pay_req
* @param {Object} decodedInvoice
* @returns {Promise<void>}
*/
async lockFunds(pay_req, decodedInvoice) {
let doc = {
pay_req,
amount: +decodedInvoice.num_satoshis,
timestamp: Math.floor(+new Date() / 1000),
};
return this._redis.rpush('locked_payments_for_' + this._userid, JSON.stringify(doc));
}
/**
* Strips specific payreq from the list of locked payments
* @param pay_req
* @returns {Promise<void>}
*/
async unlockFunds(pay_req) {
let payments = await this.getLockedPayments();
let saveBack = [];
for (let paym of payments) {
if (paym.pay_req !== pay_req) {
saveBack.push(paym);
}
}
await this._redis.del('locked_payments_for_' + this._userid);
for (let doc of saveBack) {
await this._redis.rpush('locked_payments_for_' + this._userid, JSON.stringify(doc));
}
}
async getLockedPayments() {
let payments = await this._redis.lrange('locked_payments_for_' + this._userid, 0, -1);
let result = [];
for (let paym of payments) {
let json;
try {
json = JSON.parse(paym);
result.push(json);
} catch (_) {}
}
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');
}
/**
* Shuffles array in place. ES6 version
* @param {Array} a items An array containing the items.
*/
static _shuffle(a) {
for (let i = a.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[a[i], a[j]] = [a[j], a[i]];
}
return a;
}
static async _sleep(s) {
return new Promise((r) => setTimeout(r, s * 1000));
}
}

View File

@ -1 +1,4 @@
export * from './User';
export * from './Lock';
export * from './Paym';
export * from './Invo';

View File

@ -1,6 +1,11 @@
let config = {
enableUpdateDescribeGraph: false,
postRateLimit: 100,
rateLimit: 200,
forwardReserveFee: 0.01, // default 0.01
intraHubFee: 0.003, // default 0.003
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,
@ -11,6 +16,7 @@ let config = {
},
lnd: {
url: '1.1.1.1:10009',
password: '',
},
};

View File

@ -1,70 +1,163 @@
import { User } from '../class/User';
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) {
console.log('REDIS', JSON.stringify(args));
redis.monitor(function (err, monitor) {
monitor.on('monitor', function (time, args, source, database) {
// console.log('REDIS', JSON.stringify(args));
});
});
/****** START SET FEES FROM CONFIG AT STARTUP ******/
/** GLOBALS */
global.forwardFee = config.forwardReserveFee || 0.01;
global.internalFee = config.intraHubFee || 0.003;
/****** END SET FEES FROM CONFIG AT STARTUP ******/
let bitcoinclient = require('../bitcoin');
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.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');
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) {
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 ########################
router.post('/create', async function(req, res) {
if (!(req.body.partnerid && req.body.partnerid === 'bluewallet' && req.body.accounttype)) return errorBadArguments(res);
const rateLimit = require('express-rate-limit');
const postLimiter = rateLimit({
windowMs: 30 * 60 * 1000,
max: config.postRateLimit || 100,
});
let u = new User(redis);
router.post('/create', postLimiter, async function (req, res) {
logger.log('/create', [req.id]);
// Valid if the partnerid isn't there or is a string (same with accounttype)
if (! (
(!req.body.partnerid || (typeof req.body.partnerid === 'string' || req.body.partnerid instanceof String))
&& (!req.body.accounttype || (typeof req.body.accounttype === 'string' || req.body.accounttype instanceof String))
) ) return errorBadArguments(res);
if (config.sunset) return errorSunset(res);
let u = new User(redis, bitcoinclient, lightning);
await u.create();
await u.saveMetadata({ partnerid: req.body.partnerid, accounttype: req.body.accounttype, created_at: new Date().toISOString() });
res.send({ login: u.getLogin(), password: u.getPassword() });
});
router.post('/auth', 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);
let u = new User(redis);
let u = new User(redis, bitcoinclient, lightning);
if (req.body.refresh_token) {
// need to refresh token
@ -81,85 +174,181 @@ router.post('/auth', async function(req, res) {
}
});
router.post('/addinvoice', async function(req, res) {
let u = new User(redis);
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))) {
return errorBadAuth(res);
}
logger.log('/addinvoice', [req.id, 'userid: ' + u.getUserId()]);
if (!req.body.amt) return errorBadArguments(res);
if (!req.body.amt || /*stupid NaN*/ !(req.body.amt > 0)) return errorBadArguments(res);
lightning.addInvoice({ memo: req.body.memo, value: req.body.amt }, async function(err, info) {
if (err) return errorLnd(res);
if (config.sunset) return errorSunsetAddInvoice(res);
info.pay_req = info.payment_request; // client backwards compatibility
await u.saveUserInvoice(info);
const invoice = new Invo(redis, bitcoinclient, lightning);
const r_preimage = invoice.makePreimageHex();
const invoice_args = { memo: req.body.memo, value: req.body.amt, expiry: 3600 * 24, r_preimage: Buffer.from(r_preimage, 'hex').toString('base64') };
if (req.body.description_hash) {
invoice_args.description_hash = Buffer.from(req.body.description_hash, 'hex').toString('base64')
}
lightning.addInvoice(
invoice_args,
async function (err, info) {
if (err) return errorLnd(res);
res.send(info);
});
info.memo = req.body.memo;
info.pay_req = info.payment_request; // client backwards compatibility
await u.saveUserInvoice(info);
await invoice.savePreimage(r_preimage);
res.send(info);
},
);
});
router.post('/payinvoice', async function(req, res) {
let u = new User(redis);
router.post('/payinvoice', async function (req, res) {
let u = new User(redis, bitcoinclient, lightning);
if (!(await u.loadByAuthorization(req.headers.authorization))) {
return errorBadAuth(res);
}
logger.log('/payinvoice', [req.id, 'userid: ' + u.getUserId(), 'invoice: ' + req.body.invoice]);
if (!req.body.invoice) return errorBadArguments(res);
let freeAmount = false;
if (req.body.amount) {
freeAmount = parseInt(req.body.amount);
if (freeAmount <= 0) return errorBadArguments(res);
}
let userBalance = await u.getBalance();
// obtaining a lock
let lock = new Lock(redis, 'invoice_paying_for_' + u.getUserId());
if (!(await lock.obtainLock())) {
return errorGeneralServerError(res);
}
lightning.decodePayReq({ pay_req: req.body.invoice }, async function(err, info) {
if (err) return errorNotAValidInvoice(res);
let userBalance;
try {
userBalance = await u.getCalculatedBalance();
} catch (Error) {
logger.log('', [req.id, 'error running getCalculatedBalance():', Error.message]);
lock.releaseLock();
return errorTryAgainLater(res);
}
if (userBalance >= info.num_satoshis) {
// got enough balance
lightning.decodePayReq({ pay_req: req.body.invoice }, async function (err, info) {
if (err) {
await lock.releaseLock();
return errorNotAValidInvoice(res);
}
if (+info.num_satoshis === 0) {
// 'tip' invoices
info.num_satoshis = freeAmount;
}
logger.log('/payinvoice', [req.id, 'userBalance: ' + userBalance, 'num_satoshis: ' + info.num_satoshis]);
if (userBalance >= +info.num_satoshis + Math.floor(info.num_satoshis * forwardFee)) {
// got enough balance, including 1% of payment amount - reserve for fees
if (identity_pubkey === info.destination) {
// this is internal invoice
// now, receiver add balance
let userid_payee = await u.getUseridByPaymentHash(info.payment_hash);
if (!userid_payee) return errorGeneralServerError(res);
if (!userid_payee) {
await lock.releaseLock();
return errorGeneralServerError(res);
}
let UserPayee = new User(redis);
if (await u.getPaymentHashPaid(info.payment_hash)) {
// this internal invoice was paid, no sense paying it again
await lock.releaseLock();
return errorLnd(res);
}
let UserPayee = new User(redis, bitcoinclient, lightning);
UserPayee._userid = userid_payee; // hacky, fixme
let payee_balance = await UserPayee.getBalance();
payee_balance += info.num_satoshis * 1;
await UserPayee.saveBalance(payee_balance);
await UserPayee.clearBalanceCache();
// sender spent his balance:
userBalance -= info.num_satoshis * 1;
await u.saveBalance(userBalance);
await u.clearBalanceCache();
await u.savePaidLndInvoice({
timestamp: parseInt(+new Date() / 1000),
type: 'paid_invoice',
value: +info.num_satoshis + Math.floor(info.num_satoshis * internalFee),
fee: Math.floor(info.num_satoshis * internalFee),
memo: decodeURIComponent(info.description),
pay_req: req.body.invoice,
});
await u.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);
}
// else - regular lightning network payment:
var call = lightning.sendPayment();
call.on('data', 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) {
userBalance -= +payment.payment_route.total_fees + +payment.payment_route.total_amt;
u.saveBalance(userBalance);
let PaymentShallow = new Paym(false, false, false);
payment = PaymentShallow.processSendPaymentResponse(payment);
payment.pay_req = req.body.invoice;
payment.decoded = info;
u.savePaidLndInvoice(payment);
await u.savePaidLndInvoice(payment);
await u.clearBalanceCache();
lock.releaseLock();
res.send(payment);
} else {
// payment failed
return errorLnd(res);
lock.releaseLock();
return errorPaymentFailed(res);
}
});
let inv = { payment_request: req.body.invoice };
call.write(inv);
if (!info.num_satoshis) {
// tip invoice, but someone forgot to specify amount
await lock.releaseLock();
return errorBadArguments(res);
}
let inv = {
payment_request: req.body.invoice,
amt: info.num_satoshis, // amt is used only for 'tip' invoices
fee_limit: { fixed: Math.floor(info.num_satoshis * forwardFee) + 1 },
};
try {
await u.lockFunds(req.body.invoice, info);
call.write(inv);
} catch (Err) {
await lock.releaseLock();
return errorPaymentFailed(res);
}
} else {
await lock.releaseLock();
return errorNotEnougBalance(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);
@ -167,66 +356,121 @@ router.get('/getbtc', async function(req, res) {
return errorBadAuth(res);
}
if (config.sunset) return errorSunsetAddInvoice(res);
let address = await u.getAddress();
if (!address) {
await u.generateAddress();
address = await u.getAddress();
}
u.watchAddress(address);
res.send([{ address }]);
});
router.get('/balance', 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);
if (!u.getUserId()) {
return errorBadAuth(res);
}
let paid = true;
if (!(await u.getPaymentHashPaid(req.params.payment_hash))) {
// Not found on cache
paid = await u.syncInvoicePaid(req.params.payment_hash);
}
res.send({ paid: paid });
});
router.get('/balance', postLimiter, async function (req, res) {
let u = new User(redis, bitcoinclient, lightning);
try {
logger.log('/balance', [req.id]);
if (!(await u.loadByAuthorization(req.headers.authorization))) {
return errorBadAuth(res);
}
logger.log('/balance', [req.id, 'userid: ' + u.getUserId()]);
if (!(await u.getAddress())) await u.generateAddress(); // onchain address needed further
await u.accountForPosibleTxids();
let balance = await u.getBalance();
if (balance < 0) balance = 0;
res.send({ BTC: { AvailableBalance: balance } });
} catch (Error) {
logger.log('', [req.id, 'error getting balance:', Error, 'userid:', u.getUserId()]);
return errorGeneralServerError(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);
}
if (!(await u.getAddress())) await u.generateAddress(); // onchain address needed further
await u.accountForPosibleTxids();
let balance = await u.getBalance();
res.send({ BTC: { AvailableBalance: balance } });
});
router.get('/getinfo', async function(req, res) {
let u = new User(redis);
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))) {
return errorBadAuth(res);
}
logger.log('/gettxs', [req.id, 'userid: ' + u.getUserId()]);
if (!(await u.getAddress())) await u.generateAddress(); // onchain addr needed further
await u.accountForPosibleTxids();
let txs = await u.getTxs();
res.send(txs);
try {
await u.accountForPosibleTxids();
let txs = await u.getTxs();
let lockedPayments = await u.getLockedPayments();
for (let locked of lockedPayments) {
txs.push({
type: 'paid_invoice',
fee: Math.floor(locked.amount * forwardFee) /* feelimit */,
value: locked.amount + Math.floor(locked.amount * forwardFee) /* feelimit */,
timestamp: locked.timestamp,
memo: 'Payment in transition',
});
}
res.send(txs);
} catch (Err) {
logger.log('', [req.id, 'error gettxs:', Err.message, 'userid:', u.getUserId()]);
res.send([]);
}
});
router.get('/getuserinvoices', 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))) {
return errorBadAuth(res);
}
logger.log('/getuserinvoices', [req.id, 'userid: ' + u.getUserId()]);
let invoices = await u.getUserInvoices();
res.send(invoices);
try {
let invoices = await u.getUserInvoices(req.query.limit);
res.send(invoices);
} catch (Err) {
logger.log('', [req.id, 'error getting user invoices:', Err.message, 'userid:', u.getUserId()]);
res.send([]);
}
});
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))) {
return errorBadAuth(res);
}
logger.log('/getpending', [req.id, 'userid: ' + u.getUserId()]);
if (!(await u.getAddress())) await u.generateAddress(); // onchain address needed further
await u.accountForPosibleTxids();
@ -234,22 +478,24 @@ router.get('/getpending', async function(req, res) {
res.send(txs);
});
router.get('/decodeinvoice', async function(req, res) {
let u = new User(redis, bitcoinclient);
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))) {
return errorBadAuth(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) {
let u = new User(redis, bitcoinclient);
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))) {
return errorBadAuth(res);
}
@ -258,12 +504,40 @@ 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,
use_mission_control: true,
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 ###########################
@ -280,7 +554,7 @@ function errorNotEnougBalance(res) {
return res.send({
error: true,
code: 2,
message: 'not enough balance',
message: 'not enough balance. Make sure you have at least 1% reserved for potential fees',
});
}
@ -304,7 +578,7 @@ function errorGeneralServerError(res) {
return res.send({
error: true,
code: 6,
message: 'Server fault',
message: 'Something went wrong. Please try again later',
});
}
@ -315,3 +589,35 @@ function errorBadArguments(res) {
message: 'Bad arguments',
});
}
function errorTryAgainLater(res) {
return res.send({
error: true,
code: 9,
message: 'Your previous payment is in transit. Try again in 5 minutes',
});
}
function errorPaymentFailed(res) {
return res.send({
error: true,
code: 10,
message: 'Payment failed. Does the receiver have enough inbound capacity?',
});
}
function errorSunset(res) {
return res.send({
error: true,
code: 11,
message: 'This LNDHub instance is not accepting any more users',
});
}
function errorSunsetAddInvoice(res) {
return res.send({
error: true,
code: 11,
message: 'This LNDHub instance is scheduled to shut down. Withdraw any remaining funds',
});
}

View File

@ -1,28 +1,118 @@
let express = require('express');
let router = express.Router();
let fs = require('fs');
let mustache = require('mustache');
let lightning = require('../lightning');
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');
router.get('/', function(req, res) {
let html = fs.readFileSync('./templates/index.html').toString('utf8');
lightning.getInfo({}, function(err, info) {
if (err) {
console.error('lnd failure');
process.exit(3);
}
res.setHeader('Content-Type', 'text/html');
return res.status(200).send(mustache.render(html, info));
});
});
let lightningGetInfo = {};
let lightningListChannels = {};
function updateLightning() {
console.log('updateLightning()');
try {
lightning.getInfo({}, function (err, info) {
if (err) {
console.error('lnd failure:', err);
process.exit(4);
return;
}
lightningGetInfo = info;
});
router.get('/about', function(req, res) {
let html = fs.readFileSync('./templates/about.html').toString('utf8');
lightning.listChannels({}, function (err, response) {
if (err) {
console.error('lnd failure:', err);
process.exit(4);
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 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) {
channels.unshift(channel);
} else {
channels.push(channel);
}
}
lightningListChannels.channels = channels;
});
} catch (Err) {
console.log(Err);
}
}
updateLightning();
setInterval(updateLightning, 60000);
const pubkey2name = {
'03e50492eab4107a773141bb419e107bda3de3d55652e6e1a41225f06a0bbf2d56': 'yalls.org',
'0232e20e7b68b9b673fb25f48322b151a93186bffe4550045040673797ceca43cf': 'zigzag.io',
'02df5ffe895c778e10f7742a6c5b8a0cefbe9465df58b92fadeb883752c8107c8f': 'blockstream store',
'030c3f19d742ca294a55c00376b3b355c3c90d61c6b6b39554dbc7ac19b141c14f': 'bitrefill.com',
'03864ef025fde8fb587d989186ce6a4a186895ee44a926bfc370e2c366597a3f8f': 'ACINQ',
'03abf6f44c355dec0d5aa155bdbdd6e0c8fefe318eff402de65c6eb2e1be55dc3e': 'OpenNode',
'028d98b9969fbed53784a36617eb489a59ab6dc9b9d77fcdca9ff55307cd98e3c4': 'OpenNode 2',
'0242a4ae0c5bef18048fbecf995094b74bfb0f7391418d71ed394784373f41e4f3': 'coingate.com',
'0279c22ed7a068d10dc1a38ae66d2d6461e269226c60258c021b1ddcdfe4b00bc4': 'ln1.satoshilabs.com',
'02c91d6aa51aa940608b497b6beebcb1aec05be3c47704b682b3889424679ca490': 'lnd-21.LNBIG.com',
'024655b768ef40951b20053a5c4b951606d4d86085d51238f2c67c7dec29c792ca': 'satoshis.place',
'03c2abfa93eacec04721c019644584424aab2ba4dff3ac9bdab4e9c97007491dda': 'tippin.me',
'022c699df736064b51a33017abfc4d577d133f7124ac117d3d9f9633b6297a3b6a': 'globee.com',
'0237fefbe8626bf888de0cad8c73630e32746a22a2c4faa91c1d9877a3826e1174': '1.ln.aantonop.com',
'026c7d28784791a4b31a64eb34d9ab01552055b795919165e6ae886de637632efb': 'LivingRoomOfSatoshi',
'02816caed43171d3c9854e3b0ab2cf0c42be086ff1bd4005acc2a5f7db70d83774': 'ln.pizza',
'0254ff808f53b2f8c45e74b70430f336c6c76ba2f4af289f48d6086ae6e60462d3': 'bitrefill thor',
'03d607f3e69fd032524a867b288216bfab263b6eaee4e07783799a6fe69bb84fac': 'bitrefill 3',
'02a0bc43557fae6af7be8e3a29fdebda819e439bea9c0f8eb8ed6a0201f3471ca9': 'LightningPeachHub',
'02d4531a2f2e6e5a9033d37d548cff4834a3898e74c3abe1985b493c42ebbd707d': 'coinfinity.co',
'02d23fa6794d8fd056c757f3c8f4877782138dafffedc831fc570cab572620dc61': 'paywithmoon.com',
'025f1456582e70c4c06b61d5c8ed3ce229e6d0db538be337a2dc6d163b0ebc05a5': 'paywithmoon.com',
'02004c625d622245606a1ea2c1c69cfb4516b703b47945a3647713c05fe4aaeb1c': 'walletofsatoshi',
'0331f80652fb840239df8dc99205792bba2e559a05469915804c08420230e23c7c': 'LightningPowerUsers.com',
'033d8656219478701227199cbd6f670335c8d408a92ae88b962c49d4dc0e83e025': 'bfx-lnd0',
'03021c5f5f57322740e4ee6936452add19dc7ea7ccf90635f95119ab82a62ae268': 'lnd1.bluewallet.io',
'037cc5f9f1da20ac0d60e83989729a204a33cc2d8e80438969fadf35c1c5f1233b': 'lnd2.bluewallet.io',
'036b53093df5a932deac828cca6d663472dbc88322b05eec1d42b26ab9b16caa1c': 'okcoin',
'038f8f113c580048d847d6949371726653e02b928196bad310e3eda39ff61723f6': 'magnetron',
'03829249ef39746fd534a196510232df08b83db0967804ec71bf4120930864ff97': 'blokada.org',
'02ce691b2e321954644514db708ba2a72769a6f9142ac63e65dd87964e9cf2add9': 'Satoshis.Games',
};
router.get('/', function (req, res) {
logger.log('/', [req.id]);
if (!lightningGetInfo) {
console.error('lnd failure');
process.exit(3);
}
res.setHeader('Content-Type', 'text/html');
return res.status(200).send(mustache.render(html, {}));
let html = fs.readFileSync('./templates/index.html').toString('utf8');
return res.status(200).send(mustache.render(html, Object.assign({}, lightningGetInfo, lightningListChannels)));
});
router.use(function(req, res) {
router.get('/qr', function (req, res) {
let host = req.headers.host;
if (process.env.TOR_URL) {
host = process.env.TOR_URL;
}
const customPath = req.url.replace('/qr', '');
const url = 'bluewallet:setlndhuburl?url=' + encodeURIComponent(req.protocol + '://' + host + customPath);
var code = qr.image(url, { type: 'png' });
res.setHeader('Content-type', 'image/png');
code.pipe(res);
});
router.use(function (req, res) {
res.status(404).send('404');
});

View File

@ -1,11 +1,11 @@
# User story
- *As a user, I want to have ability to topup my balance with Bitcoin and send payments within Lightning network.*
- *As a product owner, I want to have transparent usage statistic and run-time information on payment channels and environment.*
- *As a product owner, I want to have transparent usage statistics and run-time information on payment channels and environment.*
# Basics
1. LndHub API is standalone software and needs LND client syncronized and running. LndHub API is not a Lightning wallet
in terms of funds storage, it operates whole amout of available funds on channels. User's balances and transactions
1. LndHub API is standalone software and needs LND client synchronized and running. LndHub API is not a Lightning wallet
in terms of funds storage, it operates whole amount of available funds on channels. User's balances and transactions
stored in internal database.
2. LndHub API is accessible for everyone, but only `/create` can be called without authorization token.
@ -16,13 +16,13 @@ for Lightning payments.
4. gRPC RPC framework is used for communication with LND. See https://github.com/lightningnetwork/lnd/tree/master/lnrpc
5. Outh2 library, MongoDB and Golang backend is used for API implementation. Every request from user is sighned and
5. Outh2 library, MongoDB and Golang backend is used for API implementation. Every request from user is signed and
associated with corresponding user id.
6. Double entry system is used for internal accounting https://en.wikipedia.org/wiki/Double-entry_bookkeeping_system
6.1. Internal accounting requirements https://github.com/matveyco/lnd-wallet-api-spec/edit/master/Accounting-requirements.md
7. All amounts are satoshis (int), althrough millisatoshis are used in LND internally (rounding is up to server implementation).
7. All amounts are satoshis (int), although millisatoshis are used in LND internally (rounding is up to server implementation).
8. Every account has its separate Lightning, BTC addresses and unique session. If user runs few accounts from one device or wallet, corresponding amount of sessions should be opened.
@ -33,10 +33,10 @@ associated with corresponding user id.
| Call | Method | Handler | Params | Return | Description |
| ------------- | ------------- | ------------- | ------------- | ------------- | ------------- |
| Create Account | POST | /create | {none} | JSON Auth Data | Create new user account and get credentials |
| Authorize | POST | /auth | auth params (login/password of refresh_token) | JSON token data | Authorize user with Oauth. When user use refresh_token to auth, then this refresh_token not available for access once again. Use new refresh_token |
| Authorize | POST | /auth | auth params (login/password or refresh_token) | JSON token data | Authorize user with Oauth. When user use refresh_token to auth, then this refresh_token not available for access once again. Use new refresh_token |
| Get token | POST | /oauth2/token | user id, secret, grant_type and scope | token data | Get token data from user id, secret, grant_type and scope |
| Get BTC Addr | GET | /getbtc | {none} | Text address | Get user's BTC address to top-up his account |
| New BTC Addr | POST | /newbtc | {none} | Text address | Create new BTC address for user. Old addresses should remain valid, so if user accidentialy sends money to old address transaction will be assigned to his account |
| New BTC Addr | POST | /newbtc | {none} | Text address | Create new BTC address for user. Old addresses should remain valid, so if user accidentaly sends money to old address transaction will be assigned to his account |
| Get Pending Balance | GET | /getpending | {none} | JSON | Get information about BTC pending transactions which have less than 3 confirmations |
| Decode Invoice | GET | /decodeinvoice | Invoice string | JSON | Decode invoice from invoice string. If invoice is represented as QR-code, fronted device should decode it first |
| Check Route | GET | /checkroute | Payment destination | Success | Check if payment destination is available and invoice could be paid |
@ -45,7 +45,7 @@ associated with corresponding user id.
| Get transactions | GET | /gettxs | Offset, limit | JSON array | Get transactions for a wallet. With load offset at limit |
| Get transaction | GET | /gettx | Tx id | JSON | Get tx info by its ID |
| Get balance| GET | /balance | {none} | int64 | Available unspent internal balance (in Satoshis)
| Get info | GET | /getinfo | {none} | JSON | Tech info. Fee on transactions for current user (0 for a start), availble actual funds on channel, maximum tx size, service status etc.
| Get info | GET | /getinfo | {none} | JSON | Tech info. Fee on transactions for current user (0 for a start), available actual funds on channel, maximum tx size, service status etc.
| Get info | POST | /addinvoice | JSON | JSON | Create invoice.
| Get info | GET | /getuserinvoices | {none} | JSON | List of invoices created by user.
@ -70,9 +70,9 @@ Response is always JSON.
`error:true` should be always present.
{
"error" : true, // boolean
"code" : 1, // int
"message": "..." // string
"error" : true, // boolean
"code" : 1, // int
"message": "..." // string
}
Error code | Error message
@ -95,15 +95,15 @@ Create new user account and get credentials. Not whitelisted partners should ret
Request:
{
"partnerid" : "bluewallet" // string, not mandatory parameter
"accounttype" : "..." // string, not mandatory, default is common, also can be test or core
"partnerid" : "bluewallet" // string, not mandatory parameter
"accounttype" : "..." // string, not mandatory, default is common, also can be test or core
}
Response:
{
"login":"...", // srting
"password":"...", // srting
"login":"...", // string
"password":"...", // string
}
## POST /auth?type=auth
@ -113,16 +113,16 @@ Authorize user with Oauth user and login
Request:
{
"login": "...", //string
"password": "..." //string
"login": "...", // string
"password": "..." // string
}
Response:
{
"access_token": "...", //string
"token_type": "...", //string
"refresh_token": "...", //string
"access_token": "...", // string
"token_type": "...", // string
"refresh_token": "...", // string
"expiry": "0001-01-01T00:00:00Z" // datetime
}
@ -135,16 +135,16 @@ Authorize user with Oauth user and login
Request:
{
"refresh_token": "...", //string
"refresh_token": "...", // string
}
Response:
{
"access_token": "...", //string
"token_type": "...", //string
"refresh_token": "...", //string
"expiry": "0001-01-01T00:00:00Z" // datetime
"access_token": "...", // string
"token_type": "...", // string
"refresh_token": "...", // string
"expiry": "0001-01-01T00:00:00Z" // datetime
}
## POST /oauth2/token
@ -154,17 +154,17 @@ Authorize user with Oauth user and login
Request:
{
"grant_type": "client_credentials", //string
"client_id": "...", //string
"grant_type": "client_credentials", // string
"client_id": "...", // string
"client_secret": "..." // string
}
Response:
{
"access_token": "...", //string
"token_type": "...", //string
"refresh_token": "...", //string
"access_token": "...", // string
"token_type": "...", // string
"refresh_token": "...", // string
"expiry": "0001-01-01T00:00:00Z" // datetime
}
@ -185,7 +185,7 @@ Response:
## POST /newbtc
Create new BTC address for user. Old addresses should remain valid, so if user accidentialy sends
Create new BTC address for user. Old addresses should remain valid, so if user accidentaly sends
money to old address transaction will be assigned to his account
Request:
@ -229,34 +229,34 @@ Request:
Response:
{
"destination": "...", //string, lnd node address
"payment_hash": "...", //string
"num_satoshis": "78497", //string, satoshis
"timestamp": "1534430501", //string, unixtime
"expiry": "3600", //string, seconds
"description": "...", //string
"description_hash": "", //string
"fallback_addr": "...", //string, fallback on-chain address
"cltv_expiry": "...", //string, delta to use for the time-lock of the CLTV extended to the final hop
"destination": "...", // string, lnd node address
"payment_hash": "...", // string
"num_satoshis": "78497", // string, satoshis
"timestamp": "1534430501", // string, unixtime
"expiry": "3600", // string, seconds
"description": "...", // string
"description_hash": "", // string
"fallback_addr": "...", // string, fallback on-chain address
"cltv_expiry": "...", // string, delta to use for the time-lock of the CLTV extended to the final hop
"route_hints": [
{
"hop_hints" : [
{
"node_id": "..", //string, the public key of the node at the start of the
"node_id": "..", // string, the public key of the node at the start of the
// channel.
"chan_id": ..., //int, the unique identifier of the channel.
"chan_id": ..., // int, the unique identifier of the channel.
"fee_base_msat": ..., //int, The base fee of the channel denominated in
"fee_base_msat": ..., // int, The base fee of the channel denominated in
// millisatoshis.
"fee_proportional_millionths": ...,
//int, the fee rate of the channel
// int, the fee rate of the channel
// for sending one satoshi across it denominated
// in millionths of a satoshi
"cltv_expiry_delta": ...
//int, the fee rate of the channel for sending one satoshi
// int, the fee rate of the channel for sending one satoshi
// across it denominated in millionths of a satoshi
}, ...
]
@ -288,7 +288,7 @@ Request:
{
"destination" : "..." // string, destination lnd node address
"amt": "..." // string,
"amt": "..." // string,
}
Response:
@ -311,26 +311,26 @@ Request:
Response:
{
"payment_error": "..." //string
"payment_preimage": "..." //string
"payment_route": {
"total_time_lock": ... , //int
"total_fees": ... , //int
"total_amt": ... , //int
"total_fees_msat": ... , //int
"total_amt_msat": ... , //int
"hops": [
{
"chan_id": ... , //int
"chan_capacity": ... , //int
"amt_to_forward": ... , //int
"fee": ... , //int
"expiry": ... , //int
"amt_to_forward_msat": ... , //int
"fee_msat": ... , //int
},
]
}
"payment_error": "..." // string
"payment_preimage": "..." // string
"payment_route": {
"total_time_lock": ... , // int
"total_fees": ... , // int
"total_amt": ... , // int
"total_fees_msat": ... , // int
"total_amt_msat": ... , // int
"hops": [
{
"chan_id": ... , // int
"chan_capacity": ... , // int
"amt_to_forward": ... , // int
"fee": ... , // int
"expiry": ... , // int
"amt_to_forward_msat": ... , // int
"fee_msat": ... , // int
},
]
}
}
## POST /sendcoins
@ -351,19 +351,19 @@ Response:
## GET /gettxs
Get successfull lightning and btc transactions user made. Order newest to oldest.
Get successful lightning and btc transactions user made. Order newest to oldest.
Request:
{
"limit" : 10, // INT
"offset": 0, // INT
"limit" : 10, // INT
"offset": 0, // INT
}
Response:
{
[ // array of Transaction object (see below)
[ // array of Transaction object (see below)
{
...
}
@ -372,7 +372,7 @@ Response:
## GET /gettx
Get info on successfull lighning transaction user made. TXID is an internal LndHub identifier,
Get info on successful lightning transaction user made. TXID is an internal LndHub identifier,
no relation to onchain bitcoin txid.
Request:
@ -398,10 +398,10 @@ Request:
Response:
{
"BTC": { //string, currency
"TotalBalance": 109388, //int, satoshis
"BTC": { // string, currency
"TotalBalance": 109388, // int, satoshis
"AvailableBalance": 109388, // int, satoshis
"UncomfirmedBalance": 0 //int, satoshis
"UncomfirmedBalance": 0 // int, satoshis
}, ...
//now available only btc balance
@ -422,50 +422,52 @@ Response:
"fee": 0, // int, in cents of percent, i.e. 100 for 1%, 50 for 0.5%, 1 for 0.01%
"identity_pubkey": "...", //string, lnd node identity pubkey
"alias": "...", //string, lnd node alias
"num_pending_channels": 0, //int
"num_active_channels": 3, //int
"num_peers": 6, //int
"block_height": 542389, //int
"block_hash": "...", //string
"synced_to_chain": true, //bool
"testnet": false,
"chains": [
"bitcoin" //string, available chans to operate by lnd
],
"uris": [
"...", //string, uris of lnd node
],
"best_header_timestamp": "...", //string, unixtime
"version": "..." // string, lnd version
"identity_pubkey": "...", // string, lnd node identity pubkey
"alias": "...", // string, lnd node alias
"num_pending_channels": 0, // int
"num_active_channels": 3, // int
"num_peers": 6, // int
"block_height": 542389, // int
"block_hash": "...", // string
"synced_to_chain": true, // bool
"testnet": false,
"chains": [
"bitcoin" // string, available chans to operate by lnd
],
"uris": [
"...", // string, uris of lnd node
],
"best_header_timestamp": "...", // string, unixtime
"version": "..." // string, lnd version
}
## GET /getaddinvoice
## GET /getinvoice
Returns fees user pays for payments, status of the system, etc.
Request:
{
"amt": "...", //string
"memo":"...", //string
"receipt":"...", //string, not mandatory parameter
"preimage": "...", //string, not mandatory parameter
"fallbackAddr": "...", //string, not mandatory parameter
"expiry": "...", //string, not mandatory parameter
"private": "..." //string, not mandatory parameter
"amt": "...", // string
"memo":"...", // string
"receipt":"...", // string, not mandatory parameter
"preimage": "...", // string, not mandatory parameter
"fallbackAddr": "...", // string, not mandatory parameter
"expiry": "...", // string, not mandatory parameter
"private": "..." // string, not mandatory parameter
}
Response:
{
"r_hash": "...", //string,
"pay_req": "...", //string, a bare-bones invoice for a payment within the Lightning Network
"add_index": ... //int, The “add” index of this invoice. Each newly created invoice will
"r_hash": "...", // string,
"pay_req": "...", // string, a bare-bones invoice for a payment within the Lightning Network
"add_index": ... // int, The “add” index of this invoice. Each newly created invoice will
// increment this index making it monotonically increasing.
// Callers to the SubscribeInvoices call can use this to instantly
// get notified of all added invoices with an add_index greater than this one.
}
## GET /getuserinvoices
Returns fees user pays for payments, status of the system, etc.
@ -475,62 +477,42 @@ Request:
none
Response:
{
"r_hash": "...", //string
"payment_request": "...", //string
"add_index": "...", //string
"description": "...", //string
"amt": ... , //int
"ispaid": ... //bool
}
{
"r_hash": "...", // string
"payment_request": "...", // string
"add_index": "...", // string
"description": "...", // string
"amt": ... , // int
"ispaid": ... // bool
}
# Data structures
## Transaction object
{
"type": "...", // string, type of txs. Types:
// bitcoind_internal_tx - moves to user btc address or account
// bitcoind_tx - received by address or account
// paid_invoice - user paid someone's invoice
// sent_coins - user sent coins by lnd to someone's btc account
// received_invoice_payments - user received payments by invoice
"txid": "...", // string, internal tx id. not related to onchain transaction id
"amt": 666, // satoshi, int
"fee": 11, // satoshi, int
"timestamp": 1234567, // int, unixtime
"from": "...", // string
"to": "...", // string
"description": "...", // string, user-defined text
"invoice": "...", // string, original bolt11-format invoice
// bitcoind_internal_tx - moves to user btc address or account
// bitcoind_tx - received by address or account
// paid_invoice - user paid someone's invoice
// sent_coins - user sent coins by lnd to someone's btc account
// received_invoice_payments - user received payments by invoice
"txid": "...", // string, internal tx id. not related to onchain transaction id
"amt": 666, // satoshi, int
"fee": 11, // satoshi, int
"timestamp": 1234567, // int, unixtime
"from": "...", // string
"to": "...", // string
"description": "...", // string, user-defined text
"invoice": "...", // string, original bolt11-format invoice
}
# Explaining oauth2 mechanism
## Oauth2 processes
Oauth2 process consists of such stages as:
- Client (someone, who use api), make request to Authorization service with credentials (POST /auth?type=auth)
- Authorization service checks credentials and searchs for appropriate user id and secret (stored on Authoriztion service and Token service) and sends user id and secret to Token service (for example POST /getinfo/oauth2/token)
- Token service checks user id and secret and sends token data with refresh token to Authorization sevice which sends it to Client
- Authorization service checks credentials and searches for appropriate user id and secret (stored on Authorization service and Token service) and sends user id and secret to Token service (for example POST /getinfo/oauth2/token)
- 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)
```

18
doc/recover.md Normal file
View File

@ -0,0 +1,18 @@
recover user's wallet
=====================
* find user's id
f0db84e6fd5dee530314fbb90cec24839f4620914e7cd0c7
* issue new credentials via tests/integration/LightningCustodianWallet.test.js
lndhub://3d7c028419356d017199:66666666666666666666
(this is user:password)
* lookup redis record `user_{login}_{password_hash} = {userid}` :
```
> keys user_3d7c028419356d017199*
1) "user_3d7c028419356d017199_505018e35414147406fcacdae63babbfca9b1abfcb6d091a4cca9a7611183284"
```
* save to this record old user's id:
`> set user_3d7c028419356d017199_505018e35414147406fcacdae63babbfca9b1abfcb6d091a4cca9a7611183284 f0db84e6fd5dee530314fbb90cec24839f4620914e7cd0c7`
done! issued credentials should point to old user

View File

@ -9,6 +9,10 @@ User storage schema
* access_token_for_{userid} = {access_token}
* userid_for_{refresh_token} = {userid}
* 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`
@ -18,10 +22,19 @@ User storage schema
* bitcoin_address_for_{userid} = {address}
* balance_for_{userid} = {int}
* txs_for_{userid} = [] `serialized paid lnd invoices in a list`
* locked_payments_for_{userid} = [] `serialized attempts to pay invoice. used in calculating user's balance`
: {pay_req:..., amount:666, timestamp:666}
* imported_txids_for_{userid} = [] `list of txids processed for this user`
* 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,17 +1,34 @@
process.on('uncaughtException', function (err) {
console.error(err);
console.log('Node NOT Exiting...');
});
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
let express = require('express');
const helmet = require('helmet');
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;
});
let app = express();
app.enable('trust proxy');
app.use(helmet.hsts());
app.use(helmet.hidePoweredBy());
app.use(function(req, res, next) {
req.id = uuid.v4();
const rateLimit = require('express-rate-limit');
const limiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: config.rateLimit || 200,
});
app.use(limiter);
app.use(function (req, res, next) {
req.id = uuidv4();
next();
});
@ -21,10 +38,7 @@ app.use(
),
);
app.set('trust proxy', 'loopback');
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
@ -33,7 +47,10 @@ 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() {
logger.log('BOOTING UP', 'Listening on port ' + (process.env.PORT || 3000));
const bindHost = process.env.HOST || '0.0.0.0';
const bindPort = process.env.PORT || 3000;
let server = app.listen(bindPort, bindHost, function () {
logger.log('BOOTING UP', 'Listening on ' + bindHost + ':' + bindPort);
});
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,11 +28,30 @@ 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);
});
let creds = grpc.credentials.combineChannelCredentials(sslCreds, macaroonCreds);
module.exports = new lnrpc.Lightning(config.lnd.url, creds);
// trying to unlock the wallet:
if (config.lnd.password) {
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) {
if (err) {
process.env.VERBOSE && console.log('unlockWallet failed, probably because its been aleady unlocked');
} else {
console.log('unlockWallet:', response);
}
},
);
}
module.exports = new lnrpc.Lightning(config.lnd.url, creds, { 'grpc.max_receive_message_length': 1024 * 1024 * 1024 });

8578
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{
"name": "LndHub",
"version": "1.0.0",
"name": "lndhub",
"version": "1.4.1",
"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.0.1",
"babel-polyfill": "^6.26.0",
"babel-preset-env": "^1.7.0",
"babel-preset-es2015": "^6.24.1",
"babel-register": "^6.26.0",
"bignumber.js": "^8.0.1",
"bitcoinjs-lib": "^4.0.2",
"bolt11": "https://github.com/bitcoinjs/bolt11",
"eslint": "^5.9.0",
"eslint-config-prettier": "^3.3.0",
"eslint-plugin-prettier": "^3.0.0",
"express": "^4.16.4",
"grpc": "^1.17.0-pre1",
"ioredis": "^4.2.0",
"jayson": "^2.1.0",
"morgan": "^1.9.1",
"mustache": "^3.0.1",
"node-uuid": "^1.4.8",
"prettier": "^1.15.3",
"request": "^2.88.0",
"request-promise": "^4.2.2",
"winston": "^3.1.0"
"@babel/cli": "^7.14.8",
"@babel/core": "^7.15.0",
"@babel/eslint-parser": "^7.14.2",
"@babel/node": "^7.14.9",
"@babel/preset-env": "^7.15.6",
"@babel/register": "^7.14.5",
"@grpc/grpc-js": "^1.3.7",
"@grpc/proto-loader": "^0.6.5",
"bignumber.js": "^9.0.1",
"bitcoinjs-lib": "^5.2.0",
"bolt11": "^1.3.2",
"eslint": "^7.24.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^3.4.0",
"express": "^4.17.1",
"express-rate-limit": "^5.4.1",
"frisbee": "^3.1.4",
"helmet": "^4.6.0",
"ioredis": "^4.27.10",
"jayson": "^3.6.4",
"morgan": "^1.10.0",
"mustache": "^4.1.0",
"prettier": "^2.3.0",
"qr-image": "3.2.0",
"request": "^2.88.2",
"request-promise": "^4.2.6",
"uuid": "^8.3.2",
"winston": "^3.3.3"
}
}

3479
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

@ -0,0 +1,172 @@
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,
},
'028d98b9969fbed53784a36617eb489a59ab6dc9b9d77fcdca9ff55307cd98e3c4': {
name: 'OpenNode 2',
uri: '028d98b9969fbed53784a36617eb489a59ab6dc9b9d77fcdca9ff55307cd98e3c4@18.222.70.85: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',
// 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,
},
// '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,
},
'036b53093df5a932deac828cca6d663472dbc88322b05eec1d42b26ab9b16caa1c': {
name: 'okcoin',
uri: '036b53093df5a932deac828cca6d663472dbc88322b05eec1d42b26ab9b16caa1c@47.243.25.4:26658',
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) {
console.log();
if (err) {
console.error('lnd failure:', err);
return;
}
let lightningListChannels = response;
for (let channel of lightningListChannels.channels) {
if (channel.capacity <= 1000000) {
console.log(
'lncli closechannel',
channel.channel_point.replace(':', ' '),
(!channel.active && '--force') || '',
'; sleep 10 #',
'low capacity channel',
channel.capacity / 100000000,
'btc',
);
}
}
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,
);
}
}
}
}
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',
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[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

@ -0,0 +1,103 @@
/**
* This script gets all locked payments from our database and cross-checks them with actual
* sentout payments from LND. If locked payment is in there we moe locked payment to array of real payments for the user
* (it is effectively spent coins by user), if not - we attempt to pay it again (if it is not too old).
*/
import { User, Paym } from '../class/';
const config = require('../config');
/****** START SET FEES FROM CONFIG AT STARTUP ******/
/** GLOBALS */
global.forwardFee = config.forwardReserveFee || 0.01;
global.internalFee = config.intraHubFee || 0.003;
/****** END SET FEES FROM CONFIG AT STARTUP ******/
var Redis = require('ioredis');
var redis = new Redis(config.redis);
let bitcoinclient = require('../bitcoin');
let lightning = require('../lightning');
(async () => {
let keys = await redis.keys('locked_payments_for_*');
keys = User._shuffle(keys);
console.log('fetching listPayments...');
let tempPaym = new Paym(redis, bitcoinclient, lightning);
let listPayments = await tempPaym.listPayments();
// DEBUG let listPayments = JSON.parse(fs.readFileSync('listpayments.txt').toString('ascii'));
console.log('done', 'got', listPayments['payments'].length, 'payments');
for (let key of keys) {
const userid = key.replace('locked_payments_for_', '');
console.log('===================================================================================');
console.log('userid=', userid);
let user = new User(redis, bitcoinclient, lightning);
user._userid = userid;
let lockedPayments = await user.getLockedPayments();
// DEBUG let lockedPayments = [{ pay_req : 'lnbc108130n1pshdaeupp58kw9djt9vcdx26wkdxl07tgncdmxz2w7s9hzul45tf8gfplme94sdqqcqzzgxqrrssrzjqw8c7yfutqqy3kz8662fxutjvef7q2ujsxtt45csu0k688lkzu3ld93gutl3k6wauyqqqqryqqqqthqqpysp5jcmk82hypuud0lhpf66dg3w5ta6aumc4w9g9sxljazglq9wkwstq9qypqsqnw8hwwauvzrala3g4yrkgazk2l2fh582j9ytz7le46gmsgglvmrknx842ej9z4c63en5866l8tpevm8cwul8g94kf2nepppn256unucp43jnsw', amount: 10813, timestamp: 1635186606 }];
for (let lockedPayment of lockedPayments) {
let daysPassed = (+new Date() / 1000 - lockedPayment.timestamp) / 3600 / 24;
console.log('processing lockedPayment=', lockedPayment, daysPassed, 'days passed');
let payment = new Paym(redis, bitcoinclient, lightning);
payment.setInvoice(lockedPayment.pay_req);
// first things first:
// trying to lookup this stuck payment in an array of delivered payments
let isPaid = false;
for (let sentPayment of listPayments['payments']) {
if ((await payment.getPaymentHash()) == sentPayment.payment_hash) {
console.log('found this payment in listPayments array, so it is paid successfully');
let sendResult = payment.processSendPaymentResponse({ payment_error: 'already paid' } /* hacky */); // adds fees
console.log('saving paid invoice:', sendResult);
await user.savePaidLndInvoice(sendResult);
await user.unlockFunds(lockedPayment.pay_req);
isPaid = true;
console.log('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!', await payment.getPaymentHash(), sentPayment.payment_hash);
break;
}
}
// could not find...
if (daysPassed > 1 / 24 && daysPassed <= 1) {
let sendResult;
console.log('attempting to pay to route');
try {
sendResult = await payment.attemptPayToRoute();
} catch (_) {
console.log(_);
console.log('evict lock');
await user.unlockFunds(lockedPayment.pay_req);
continue;
}
console.log('sendResult=', sendResult);
console.log('payment.getIsPaid() = ', payment.getIsPaid());
if (payment.getIsPaid() === true) {
console.log('paid successfully');
sendResult = payment.processSendPaymentResponse(sendResult); // adds fees
console.log('saving paid invoice:', sendResult);
await user.savePaidLndInvoice(sendResult);
await user.unlockFunds(lockedPayment.pay_req);
} else if (payment.getIsPaid() === false) {
console.log('not paid, just evict the lock');
await user.unlockFunds(lockedPayment.pay_req);
} else {
console.log('payment is in unknown state');
}
console.log('sleeping 5 sec...');
console.log('-----------------------------------------------------------------------------------');
await User._sleep(0);
} else if (daysPassed > 1) {
// could not find in listpayments array; too late to retry
if (!isPaid) {
console.log('very old payment, evict the lock');
await user.unlockFunds(lockedPayment.pay_req);
}
}
}
}
console.log('done');
process.exit();
})();

View File

@ -0,0 +1,38 @@
/**
* This script goes through all user invoices in LND and if it is settled - marks it
* so in our database. Does this only for invoices younger than week. *
*/
import { Invo } from '../class/';
const config = require('../config');
const fs = require('fs');
const Redis = require('ioredis');
const redis = new Redis(config.redis);
let bitcoinclient = require('../bitcoin');
let lightning = require('../lightning');
(async () => {
console.log('fetching listinvoices...');
let tempInv = new Invo(redis, bitcoinclient, lightning);
let listinvoices = await tempInv.listInvoices();
console.log('done', 'got', listinvoices['invoices'].length, 'invoices');
fs.writeFileSync('listInvoices.json', '[\n');
let markedInvoices = 0;
for (const invoice of listinvoices['invoices']) {
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++;
process.stdout.write(markedInvoices + '\r');
}
}
fs.appendFileSync('listInvoices.json', ']');
console.log('done, marked', markedInvoices, 'invoices');
process.exit();
})();

59
scripts/show_user.js Normal file
View File

@ -0,0 +1,59 @@
import { User } from '../class/';
import { BigNumber } from 'bignumber.js';
const config = require('../config');
var Redis = require('ioredis');
var redis = new Redis(config.redis);
redis.info(function (err, info) {
if (err || !info) {
console.error('redis failure');
process.exit(5);
}
});
let bitcoinclient = require('../bitcoin');
let lightning = require('../lightning');
(async () => {
let userid = process.argv[2];
let U = new User(redis, bitcoinclient, lightning);
U._userid = userid;
let userinvoices = await U.getUserInvoices();
let txs;
let calculatedBalance = 0;
console.log('\ndb balance\n==============\n', await U.getBalance());
console.log('\nuserinvoices\n================\n');
for (let invo of userinvoices) {
if (invo && invo.ispaid) {
console.log('+', +invo.amt, new Date(invo.timestamp * 1000).toString());
calculatedBalance += +invo.amt;
}
}
console.log('\ntxs\n===\n');
txs = await U.getTxs();
for (let tx of txs) {
if (tx.type === 'bitcoind_tx') {
console.log('+', new BigNumber(tx.amount).multipliedBy(100000000).toNumber(), '[on-chain refill]');
calculatedBalance += new BigNumber(tx.amount).multipliedBy(100000000).toNumber();
} else {
console.log('-', +tx.value, new Date(tx.timestamp * 1000).toString(), tx.memo, '; preimage:', tx.payment_preimage || '');
calculatedBalance -= +tx.value;
}
}
let locked = await U.getLockedPayments();
for (let loc of locked) {
console.log('-', loc.amount + /* fee limit */ Math.floor(loc.amount * config.forwardReserveFee), new Date(loc.timestamp * 1000).toString(), '[locked]');
}
console.log('\ncalculatedBalance\n================\n', calculatedBalance, await U.getCalculatedBalance());
console.log('txs:', txs.length, 'userinvoices:', userinvoices.length);
process.exit();
})();

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,29 +7,23 @@
*
+ + + + + + + + + + + + + + + + + + + + + */
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({
level: 'info',
format: combine(timestamp(), logFormat),
transports: [
new transports.File({
filename: './logs/error.log',
new transports.Console({
level: 'error',
}),
new transports.File({
filename: './logs/out.log',
}),
new transports.Console(),
],
});
@ -40,12 +34,7 @@ if (!fs.existsSync('logs')) {
fs.mkdirSync('logs');
}
/**
* @param {string} label group label
* @param {string} message log message
*/
function log(label, message) {
console.log(new Date(), label, message);
logger.log({
level: 'info',
label: label,