Compare commits

..

26 Commits

Author SHA1 Message Date
dependabot[bot]
819518eab0 build(deps): bump elliptic from 6.5.4 to 6.6.1
Some checks failed
Build on push / Build image (push) Has been cancelled
Bumps [elliptic](https://github.com/indutny/elliptic) from 6.5.4 to 6.6.1.
- [Commits](https://github.com/indutny/elliptic/compare/v6.5.4...v6.6.1)

---
updated-dependencies:
- dependency-name: elliptic
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-15 19:55:29 +00:00
overtorment
0311e56aa2 FIX: groundcontrol post notification 2024-11-05 11:15:34 +00:00
dependabot[bot]
0cf7387c30 build(deps): bump ws from 7.5.4 to 7.5.10
Bumps [ws](https://github.com/websockets/ws) from 7.5.4 to 7.5.10.
- [Release notes](https://github.com/websockets/ws/releases)
- [Commits](https://github.com/websockets/ws/compare/7.5.4...7.5.10)

---
updated-dependencies:
- dependency-name: ws
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-01 11:21:18 +01:00
snyk-bot
edb2ab0949 fix: package.json & package-lock.json to reduce vulnerabilities
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-JS-SEMVER-3247795
2023-12-29 12:00:36 +00:00
dependabot[bot]
625a6e9526 build(deps): bump @babel/traverse from 7.15.4 to 7.23.2
Bumps [@babel/traverse](https://github.com/babel/babel/tree/HEAD/packages/babel-traverse) from 7.15.4 to 7.23.2.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.23.2/packages/babel-traverse)

---
updated-dependencies:
- dependency-name: "@babel/traverse"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-21 18:15:13 +01:00
dependabot[bot]
525e309105 build(deps): bump protobufjs from 6.11.2 to 6.11.4
Bumps [protobufjs](https://github.com/protobufjs/protobuf.js) from 6.11.2 to 6.11.4.
- [Release notes](https://github.com/protobufjs/protobuf.js/releases)
- [Changelog](https://github.com/protobufjs/protobuf.js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/protobufjs/protobuf.js/commits)

---
updated-dependencies:
- dependency-name: protobufjs
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-31 00:06:41 +01:00
overtorment
0964ebfca5 REL 2023-02-10 18:52:11 +00:00
overtorment
c87f1b322a FIX: add rate limiter to more api calls 2023-02-10 18:51:15 +00:00
overtorment
3a7b452c65 FIX: correct sat amount when unlocking paid stuck zero-sat invoice 2023-02-10 18:44:48 +00:00
Overtorment
fb023b02be FIX: race condition for address generation 2022-04-14 17:49:50 +01:00
Overtorment
60cda5eb14 FIX: unlock wont retry anymore, only sit tight and wait for a payment result 2022-04-13 12:51:22 +01:00
dependabot[bot]
c6dc983964 build(deps): bump minimist from 1.2.5 to 1.2.6
Bumps [minimist](https://github.com/substack/minimist) from 1.2.5 to 1.2.6.
- [Release notes](https://github.com/substack/minimist/releases)
- [Commits](https://github.com/substack/minimist/compare/1.2.5...1.2.6)

---
updated-dependencies:
- dependency-name: minimist
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-03 13:15:52 +01:00
Overtorment
481758f03a FIX: required reserve rounding for small amounts 2022-02-04 10:45:56 +00:00
Overtorment
348ee7ce81 OPS: renamed build action so its not triggered on heroku 2022-02-03 21:51:40 +00:00
kwizzn
05eace759f Add the transpiled artifacts to build/ for a slimmer native Node Docker container 2021-11-22 14:20:59 +00: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
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
10 changed files with 4923 additions and 2865 deletions

15
.dockerignore Normal file
View File

@ -0,0 +1,15 @@
*
!build/
!class/
!controllers/
!scripts/
!static/
!templates/
!utils/
!*.js
!.babelrc
!.eslint*
!admin.macaroon
!package*.json
!rpc.proto
!tls.cert

1
.gitignore vendored
View File

@ -2,6 +2,7 @@
admin.macaroon
tls.cert
build/
logs/
# dependencies

View File

@ -13,19 +13,17 @@ RUN apt-get update && apt-get -y install python3
WORKDIR /lndhub
# Copy 'package-lock.json' and 'package.json'
COPY package.json package-lock.json ./
# Copy project files and folders to the current working directory
COPY . .
# Install dependencies
RUN npm i
# Copy project files and folders to the current working directory
COPY . .
RUN npm run dockerbuild
# Delete git data as it's not needed inside the container
RUN rm -rf .git
FROM node:16-bullseye-slim
FROM node:16-alpine
# Create a specific user so LNDHub doesn't run as root
COPY --from=perms /etc/group /etc/passwd /etc/shadow /etc/
@ -34,10 +32,11 @@ COPY --from=perms /etc/group /etc/passwd /etc/shadow /etc/
COPY --from=builder /lndhub /lndhub
# Create logs folder and ensure permissions are set correctly
RUN mkdir /lndhub/logs && chown -R lndhub:lndhub /lndhub
RUN mkdir -p /lndhub/logs && chown -R lndhub:lndhub /lndhub
USER lndhub
ENV PORT=3000
EXPOSE 3000
WORKDIR /lndhub
CMD cp $LND_CERT_FILE /lndhub/ && cp $LND_ADMIN_MACAROON_FILE /lndhub/ && cd /lndhub && npm start

View File

@ -119,6 +119,12 @@ export class User {
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');
const addressAlreadyExists = await self.getAddress();
if (addressAlreadyExists) {
// one last final check, for a case of really long race condition
resolve();
return;
}
await self.addAddress(response.address);
if (config.bitcoind) self._bitcoindrpc.request('importaddress', [response.address, response.address, false]);
resolve();

View File

@ -1,11 +1,13 @@
import { User, Lock, Paym, Invo } from '../class/';
import Frisbee from 'frisbee';
import fetch from 'node-fetch';
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));
if (process.env.NODE_ENV !== 'prod') {
console.log('using config', JSON.stringify(config));
}
var Redis = require('ioredis');
var redis = new Redis(config.redis);
@ -90,21 +92,16 @@ const subscribeInvoicesCallCallback = async function (response) {
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);
const apiResponse = await fetch(`${baseURI}/lightningInvoiceGotSettled`, {
method: 'POST',
headers: {
'Access-Control-Allow-Origin': '*',
'Content-Type': 'application/json',
},
body: JSON.stringify(LightningInvoiceSettledNotification),
});
console.log('Groundcontrol apiResponse=', apiResponse);
}
};
let subscribeInvoicesCall = lightning.subscribeInvoices({});
@ -144,7 +141,7 @@ router.post('/create', postLimiter, async function (req, res) {
(!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);
@ -202,7 +199,7 @@ router.post('/addinvoice', postLimiter, async function (req, res) {
);
});
router.post('/payinvoice', async function (req, res) {
router.post('/payinvoice', postLimiter, async function (req, res) {
let u = new User(redis, bitcoinclient, lightning);
if (!(await u.loadByAuthorization(req.headers.authorization))) {
return errorBadAuth(res);
@ -245,7 +242,7 @@ router.post('/payinvoice', async function (req, res) {
logger.log('/payinvoice', [req.id, 'userBalance: ' + userBalance, 'num_satoshis: ' + info.num_satoshis]);
if (userBalance >= +info.num_satoshis + Math.floor(info.num_satoshis * forwardFee)) {
if (userBalance >= +info.num_satoshis + Math.floor(info.num_satoshis * forwardFee) + 1) {
// got enough balance, including 1% of payment amount - reserve for fees
if (identity_pubkey === info.destination) {
@ -413,7 +410,7 @@ router.get('/getinfo', postLimiter, async function (req, res) {
});
});
router.get('/gettxs', async function (req, res) {
router.get('/gettxs', postLimiter, async function (req, res) {
logger.log('/gettxs', [req.id]);
let u = new User(redis, bitcoinclient, lightning);
if (!(await u.loadByAuthorization(req.headers.authorization))) {
@ -459,7 +456,7 @@ router.get('/getuserinvoices', postLimiter, async function (req, res) {
}
});
router.get('/getpending', async function (req, res) {
router.get('/getpending', postLimiter, async function (req, res) {
logger.log('/getpending', [req.id]);
let u = new User(redis, bitcoinclient, lightning);
if (!(await u.loadByAuthorization(req.headers.authorization))) {
@ -473,7 +470,7 @@ router.get('/getpending', async function (req, res) {
res.send(txs);
});
router.get('/decodeinvoice', async function (req, res) {
router.get('/decodeinvoice', postLimiter, async function (req, res) {
logger.log('/decodeinvoice', [req.id]);
let u = new User(redis, bitcoinclient, lightning);
if (!(await u.loadByAuthorization(req.headers.authorization))) {

View File

@ -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
}
@ -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
@ -356,14 +356,14 @@ 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)
{
...
}
@ -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,33 +477,35 @@ 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

View File

@ -52,5 +52,6 @@ const bindPort = process.env.PORT || 3000;
let server = app.listen(bindPort, bindHost, function () {
logger.log('BOOTING UP', 'Listening on ' + bindHost + ':' + bindPort);
logger.log('using GroundControl', process.env.GROUNDCONTROL);
});
module.exports = server;

7392
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,11 @@
{
"name": "lndhub",
"version": "1.4.1",
"version": "1.4.3",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dockerbuild": "./node_modules/.bin/babel ./ --ignore node_modules/ --ignore *.spec.js --out-dir ./build",
"dev": "nodemon node_modules/.bin/babel-node index.js",
"start": "node_modules/.bin/babel-node index.js",
"lint": "./node_modules/.bin/eslint ./ controllers/ class/ --fix"
@ -16,10 +17,10 @@
"@babel/core": "^7.15.0",
"@babel/eslint-parser": "^7.14.2",
"@babel/node": "^7.14.9",
"@babel/preset-env": "^7.15.0",
"@babel/preset-env": "^7.22.0",
"@babel/register": "^7.14.5",
"@grpc/grpc-js": "^1.3.7",
"@grpc/proto-loader": "^0.6.4",
"@grpc/proto-loader": "^0.6.5",
"bignumber.js": "^9.0.1",
"bitcoinjs-lib": "^5.2.0",
"bolt11": "^1.3.2",
@ -27,13 +28,13 @@
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^3.4.0",
"express": "^4.17.1",
"express-rate-limit": "^5.3.0",
"frisbee": "^3.1.4",
"express-rate-limit": "^5.4.1",
"helmet": "^4.6.0",
"ioredis": "^4.27.8",
"ioredis": "^4.27.10",
"jayson": "^3.6.4",
"morgan": "^1.10.0",
"mustache": "^4.1.0",
"node-fetch": "^2.6.1",
"prettier": "^2.3.0",
"qr-image": "3.2.0",
"request": "^2.88.2",

View File

@ -3,10 +3,15 @@
* 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, Lock, Paym } from '../class/';
import { User, Paym } from '../class/';
const config = require('../config');
const fs = require('fs');
/****** 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);
@ -20,8 +25,8 @@ let lightning = require('../lightning');
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');
fs.writeFileSync('listPayments.json', JSON.stringify(listPayments['payments'], null, 2));
for (let key of keys) {
const userid = key.replace('locked_payments_for_', '');
@ -30,7 +35,7 @@ let lightning = require('../lightning');
let user = new User(redis, bitcoinclient, lightning);
user._userid = userid;
let lockedPayments = await user.getLockedPayments();
// lockedPayments = [{pay_req : 'lnbc2m1pwgd4tdpp5vjz80mm8murdkskrnre6w4kphzy3d6gap5jyffr93u02ruaj0wtsdq2xgcrqvpsxqcqzysk34zva4h9ce9jdf08nfdm2sh2ek4y4hjse8ww9jputneltjl24krkv50sene4jh0wpull6ujgrg632u2qt3lkva74vpkqr5e5tuuljspasqfhx'}];
// DEBUG let lockedPayments = [{ pay_req : 'lnbc108130n1pshdaeupp58kw9djt9vcdx26wkdxl07tgncdmxz2w7s9hzul45tf8gfplme94sdqqcqzzgxqrrssrzjqw8c7yfutqqy3kz8662fxutjvef7q2ujsxtt45csu0k688lkzu3ld93gutl3k6wauyqqqqryqqqqthqqpysp5jcmk82hypuud0lhpf66dg3w5ta6aumc4w9g9sxljazglq9wkwstq9qypqsqnw8hwwauvzrala3g4yrkgazk2l2fh582j9ytz7le46gmsgglvmrknx842ej9z4c63en5866l8tpevm8cwul8g94kf2nepppn256unucp43jnsw', amount: 10813, timestamp: 1635186606 }];
for (let lockedPayment of lockedPayments) {
let daysPassed = (+new Date() / 1000 - lockedPayment.timestamp) / 3600 / 24;
@ -38,52 +43,33 @@ let lightning = require('../lightning');
let payment = new Paym(redis, bitcoinclient, lightning);
payment.setInvoice(lockedPayment.pay_req);
if (daysPassed > 1 / 24 && daysPassed <= 1) {
// if (!await payment.isExpired()) {
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
// 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
if (sendResult.decoded.num_satoshis == 0) {
// zero sat invoice, get corect sat number from the lockedPayment info
sendResult.decoded.num_satoshis = lockedPayment.amount + Math.ceil(lockedPayment.amount * forwardFee);
sendResult.decoded.num_msat = sendResult.decoded.num_satoshis * 1000;
sendResult.payment_route.total_fees = 0;
sendResult.payment_route.total_amt = sendResult.decoded.num_satoshis;
}
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) {
// 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);
process.exit();
break;
}
isPaid = true;
console.log('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!', await payment.getPaymentHash(), sentPayment.payment_hash);
break;
}
}
// could not find...
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);