Merge branch 'master' of github.com:BlueWallet/LndHub
This commit is contained in:
commit
27ebe36b4b
24
README.md
24
README.md
@ -6,17 +6,24 @@ Wrapper for Lightning Network Daemon. It provides separate accounts with minimum
|
||||
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`.
|
||||
|
||||
Edit `config.js` and set it up correctly.
|
||||
Install `bitcoind`, `lnd` and `redis`. Edit `config.js` and set it up correctly.
|
||||
Copy `admin.macaroon` and `tls.cert` in root folder of LndHub.
|
||||
|
||||
`bitcoind` should run with `-deprecatedrpc=accounts`, for now. Lndhub expects Lnd's wallet to be unlocked, if not - it will attempt to unlock it with password stored in `config.lnd.password`.
|
||||
Don't forget to enable disk-persistance for `redis`.
|
||||
|
||||
|
||||
### Deploy to Heroku
|
||||
|
||||
Add config vars :
|
||||
@ -27,4 +34,13 @@ Add config vars :
|
||||
|
||||
### 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/LightningCustodianWallet.test.js
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
## Responsible disclosure
|
||||
|
||||
Found critical bugs/vulnerabilities? Please email them bluewallet@bluewallet.io
|
||||
Thanks!
|
||||
|
@ -24,8 +24,8 @@ export class Lock {
|
||||
}
|
||||
|
||||
// success - got lock
|
||||
await this._redis.expire(this._lock_key, 2 * 60);
|
||||
// lock expires in 2 mins just for any case
|
||||
await this._redis.expire(this._lock_key, 3600);
|
||||
// lock expires in 5 mins just for any case
|
||||
return true;
|
||||
}
|
||||
|
||||
|
25
class/Paym.js
Normal file
25
class/Paym.js
Normal file
@ -0,0 +1,25 @@
|
||||
var crypto = require('crypto');
|
||||
var lightningPayReq = require('bolt11');
|
||||
import { BigNumber } from 'bignumber.js';
|
||||
|
||||
export class Payment {
|
||||
constructor(redis, bitcoindrpc, lightning) {
|
||||
this._redis = redis;
|
||||
this._bitcoindrpc = bitcoindrpc;
|
||||
this._lightning = lightning;
|
||||
this._decoded = false;
|
||||
}
|
||||
|
||||
async decodePayReqViaRpc(invoice) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
this._lightning.decodePayReq({ pay_req: invoice }, function(err, info) {
|
||||
if (err) return reject(err);
|
||||
return resolve(info);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
decodePayReq(payReq) {
|
||||
this._decoded = lightningPayReq.decode(payReq);
|
||||
}
|
||||
}
|
134
class/User.js
134
class/User.js
@ -113,12 +113,67 @@ export class User {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 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() {
|
||||
return (await this._redis.get('balance_for_' + this._userid)) * 1;
|
||||
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) {
|
||||
// TODO: check if payment in determined state and actually evict it from this list
|
||||
calculatedBalance -= +paym.amount;
|
||||
}
|
||||
|
||||
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, 3600 * 24);
|
||||
}
|
||||
|
||||
async savePaidLndInvoice(doc) {
|
||||
@ -192,7 +247,7 @@ export class User {
|
||||
if (invoice.ispaid) {
|
||||
// so invoice was paid after all
|
||||
await this.setPaymentHashPaid(invoice.payment_hash);
|
||||
await this.saveBalance((await this.getBalance()) + decoded.satoshis);
|
||||
await this.saveBalance(await this.getCalculatedBalance());
|
||||
}
|
||||
}
|
||||
|
||||
@ -213,11 +268,16 @@ 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) {
|
||||
await this.generateAddress();
|
||||
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]);
|
||||
txs = txs.result;
|
||||
@ -245,6 +305,12 @@ export class User {
|
||||
invoice.timestamp = invoice.decoded.timestamp;
|
||||
invoice.memo = invoice.decoded.description;
|
||||
}
|
||||
// removing unsued by client fields to reduce size
|
||||
delete invoice.payment_error;
|
||||
delete invoice.payment_preimage;
|
||||
delete invoice.payment_route;
|
||||
delete invoice.pay_req;
|
||||
delete invoice.decoded;
|
||||
result.push(invoice);
|
||||
}
|
||||
|
||||
@ -258,6 +324,10 @@ export class User {
|
||||
*/
|
||||
async getPendingTxs() {
|
||||
let addr = await this.getAddress();
|
||||
if (!addr) {
|
||||
await this.generateAddress();
|
||||
addr = await this.getAddress();
|
||||
}
|
||||
if (!addr) throw new Error('cannot get transactions: no onchain address assigned to user');
|
||||
let txs = await this._bitcoindrpc.request('listtransactions', [addr, 100500, 0, true]);
|
||||
txs = txs.result;
|
||||
@ -313,8 +383,9 @@ export class User {
|
||||
return;
|
||||
}
|
||||
|
||||
let userBalance = await this.getBalance();
|
||||
userBalance += new BigNumber(tx.amount).multipliedBy(100000000).toNumber();
|
||||
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();
|
||||
@ -322,6 +393,59 @@ export class User {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
_hash(string) {
|
||||
return crypto
|
||||
.createHash('sha256')
|
||||
|
@ -9,7 +9,7 @@ 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));
|
||||
// console.log('REDIS', JSON.stringify(args));
|
||||
});
|
||||
});
|
||||
|
||||
@ -58,7 +58,7 @@ router.post('/create', async function(req, res) {
|
||||
logger.log('/create', [req.id]);
|
||||
if (!(req.body.partnerid && req.body.partnerid === 'bluewallet' && req.body.accounttype)) return errorBadArguments(res);
|
||||
|
||||
let u = new User(redis);
|
||||
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() });
|
||||
@ -68,7 +68,7 @@ router.post('/auth', 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
|
||||
@ -87,7 +87,7 @@ router.post('/auth', async function(req, res) {
|
||||
|
||||
router.post('/addinvoice', async function(req, res) {
|
||||
logger.log('/addinvoice', [req.id]);
|
||||
let u = new User(redis);
|
||||
let u = new User(redis, bitcoinclient, lightning);
|
||||
if (!(await u.loadByAuthorization(req.headers.authorization))) {
|
||||
return errorBadAuth(res);
|
||||
}
|
||||
@ -105,15 +105,19 @@ router.post('/addinvoice', async function(req, res) {
|
||||
});
|
||||
|
||||
router.post('/payinvoice', async function(req, res) {
|
||||
logger.log('/payinvoice', [req.id]);
|
||||
let u = new User(redis);
|
||||
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 (req.body.amount) {
|
||||
freeAmount = parseInt(req.body.amount);
|
||||
if (freeAmount <= 0) return errorBadArguments(res);
|
||||
}
|
||||
|
||||
// obtaining a lock
|
||||
let lock = new Lock(redis, 'invoice_paying_for_' + u.getUserId());
|
||||
@ -121,7 +125,7 @@ router.post('/payinvoice', async function(req, res) {
|
||||
return errorTryAgainLater(res);
|
||||
}
|
||||
|
||||
let userBalance = await u.getBalance();
|
||||
let userBalance = await u.getCalculatedBalance();
|
||||
|
||||
lightning.decodePayReq({ pay_req: req.body.invoice }, async function(err, info) {
|
||||
if (err) {
|
||||
@ -134,8 +138,10 @@ router.post('/payinvoice', async function(req, res) {
|
||||
info.num_satoshis = freeAmount;
|
||||
}
|
||||
|
||||
if (userBalance >= info.num_satoshis) {
|
||||
// got enough balance
|
||||
logger.log('/payinvoice', [req.id, 'userBalance: ' + userBalance, 'num_satoshis: ' + info.num_satoshis]);
|
||||
|
||||
if (userBalance >= +info.num_satoshis + Math.floor(info.num_satoshis * 0.01)) {
|
||||
// got enough balance, including 1% of payment amount - reserve for fees
|
||||
|
||||
if (identity_pubkey === info.destination) {
|
||||
// this is internal invoice
|
||||
@ -152,7 +158,7 @@ router.post('/payinvoice', async function(req, res) {
|
||||
return errorLnd(res);
|
||||
}
|
||||
|
||||
let UserPayee = new User(redis);
|
||||
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;
|
||||
@ -164,8 +170,8 @@ router.post('/payinvoice', async function(req, res) {
|
||||
await u.savePaidLndInvoice({
|
||||
timestamp: parseInt(+new Date() / 1000),
|
||||
type: 'paid_invoice',
|
||||
value: info.num_satoshis * 1,
|
||||
fee: 0, // internal invoices are free
|
||||
value: +info.num_satoshis + Math.floor(info.num_satoshis * 0.01),
|
||||
fee: Math.floor(info.num_satoshis * 0.01),
|
||||
memo: decodeURIComponent(info.description),
|
||||
});
|
||||
|
||||
@ -178,14 +184,16 @@ router.post('/payinvoice', async function(req, res) {
|
||||
// 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) {
|
||||
payment.payment_route.total_fees += Math.floor(+payment.payment_route.total_amt * 0.01);
|
||||
userBalance -= +payment.payment_route.total_fees + +payment.payment_route.total_amt;
|
||||
u.saveBalance(userBalance);
|
||||
payment.pay_req = req.body.invoice;
|
||||
payment.decoded = info;
|
||||
u.savePaidLndInvoice(payment);
|
||||
await u.savePaidLndInvoice(payment);
|
||||
lock.releaseLock();
|
||||
res.send(payment);
|
||||
} else {
|
||||
@ -199,12 +207,15 @@ router.post('/payinvoice', async function(req, res) {
|
||||
await lock.releaseLock();
|
||||
return errorBadArguments(res);
|
||||
}
|
||||
let inv = { payment_request: req.body.invoice, amt: info.num_satoshis }; // amt is used only for 'tip' invoices
|
||||
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 * 0.005) },
|
||||
};
|
||||
try {
|
||||
logger.log('/payinvoice', [req.id, 'before write', JSON.stringify(inv)]);
|
||||
await u.lockFunds(req.body.invoice, info);
|
||||
call.write(inv);
|
||||
} catch (Err) {
|
||||
logger.log('/payinvoice', [req.id, 'exception', JSON.stringify(Err)]);
|
||||
await lock.releaseLock();
|
||||
return errorLnd(res);
|
||||
}
|
||||
@ -243,12 +254,13 @@ router.get('/balance', async function(req, res) {
|
||||
if (!(await u.getAddress())) await u.generateAddress(); // onchain address needed further
|
||||
u.accountForPosibleTxids();
|
||||
let balance = await u.getBalance();
|
||||
if (balance < 0) balance = 0;
|
||||
res.send({ BTC: { AvailableBalance: balance } });
|
||||
});
|
||||
|
||||
router.get('/getinfo', async function(req, res) {
|
||||
logger.log('/getinfo', [req.id]);
|
||||
let u = new User(redis);
|
||||
let u = new User(redis, bitcoinclient, lightning);
|
||||
if (!(await u.loadByAuthorization(req.headers.authorization))) {
|
||||
return errorBadAuth(res);
|
||||
}
|
||||
@ -272,7 +284,7 @@ router.get('/gettxs', async function(req, res) {
|
||||
let txs = await u.getTxs();
|
||||
res.send(txs);
|
||||
} catch (Err) {
|
||||
console.log(Err);
|
||||
logger.log('', [req.id, 'error:', Err]);
|
||||
res.send([]);
|
||||
}
|
||||
});
|
||||
@ -292,7 +304,7 @@ router.get('/getuserinvoices', async function(req, res) {
|
||||
res.send(invoices);
|
||||
}
|
||||
} catch (Err) {
|
||||
console.log(Err);
|
||||
logger.log('', [req.id, 'error:', Err]);
|
||||
res.send([]);
|
||||
}
|
||||
});
|
||||
@ -312,7 +324,7 @@ router.get('/getpending', async function(req, res) {
|
||||
|
||||
router.get('/decodeinvoice', async function(req, res) {
|
||||
logger.log('/decodeinvoice', [req.id]);
|
||||
let u = new User(redis, bitcoinclient);
|
||||
let u = new User(redis, bitcoinclient, lightning);
|
||||
if (!(await u.loadByAuthorization(req.headers.authorization))) {
|
||||
return errorBadAuth(res);
|
||||
}
|
||||
@ -327,7 +339,7 @@ router.get('/decodeinvoice', async function(req, res) {
|
||||
|
||||
router.get('/checkrouteinvoice', async function(req, res) {
|
||||
logger.log('/checkrouteinvoice', [req.id]);
|
||||
let u = new User(redis, bitcoinclient);
|
||||
let u = new User(redis, bitcoinclient, lightning);
|
||||
if (!(await u.loadByAuthorization(req.headers.authorization))) {
|
||||
return errorBadAuth(res);
|
||||
}
|
||||
@ -398,6 +410,6 @@ function errorTryAgainLater(res) {
|
||||
return res.send({
|
||||
error: true,
|
||||
code: 9,
|
||||
message: 'Try again later',
|
||||
message: 'Your previous payment is in transit. Try again in 5 minutes',
|
||||
});
|
||||
}
|
||||
|
@ -12,14 +12,15 @@ function updateLightning() {
|
||||
try {
|
||||
lightning.getInfo({}, function(err, info) {
|
||||
if (err) {
|
||||
console.error('lnd failure');
|
||||
console.error('lnd failure:', err);
|
||||
}
|
||||
lightningGetInfo = info;
|
||||
});
|
||||
|
||||
lightning.listChannels({}, function(err, response) {
|
||||
if (err) {
|
||||
console.error('lnd failure');
|
||||
console.error('lnd failure:', err);
|
||||
return;
|
||||
}
|
||||
lightningListChannels = response;
|
||||
let channels = [];
|
||||
@ -44,6 +45,7 @@ function updateLightning() {
|
||||
} catch (Err) {
|
||||
console.log(Err);
|
||||
}
|
||||
console.log('updated');
|
||||
}
|
||||
updateLightning();
|
||||
setInterval(updateLightning, 60000);
|
||||
@ -61,6 +63,11 @@ const pubkey2name = {
|
||||
'024655b768ef40951b20053a5c4b951606d4d86085d51238f2c67c7dec29c792ca': 'satoshis.place',
|
||||
'03c2abfa93eacec04721c019644584424aab2ba4dff3ac9bdab4e9c97007491dda': 'tippin.me',
|
||||
'022c699df736064b51a33017abfc4d577d133f7124ac117d3d9f9633b6297a3b6a': 'globee.com',
|
||||
'0237fefbe8626bf888de0cad8c73630e32746a22a2c4faa91c1d9877a3826e1174': '1.ln.aantonop.com',
|
||||
'036a54f02d2186de192e4bcec3f7b47adb43b1fa965793387cd2471990ce1d236b': 'capacity.network',
|
||||
'026c7d28784791a4b31a64eb34d9ab01552055b795919165e6ae886de637632efb': 'LivingRoomOfSatoshi.com_LND_1',
|
||||
'02816caed43171d3c9854e3b0ab2cf0c42be086ff1bd4005acc2a5f7db70d83774': 'ln.pizza',
|
||||
'024a2e265cd66066b78a788ae615acdc84b5b0dec9efac36d7ac87513015eaf6ed': 'Bitrefill.com/lightning',
|
||||
};
|
||||
|
||||
router.get('/', function(req, res) {
|
||||
|
@ -20,6 +20,8 @@ User storage schema
|
||||
* bitcoin_address_for_{userid} = {address}
|
||||
* balance_for_{userid} = {int}
|
||||
* txs_for_{userid} = [] `serialized paid lnd invoices in a list`
|
||||
* locked_invoices_for_{userod} = [] `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} = []
|
||||
|
19
lightning.js
19
lightning.js
@ -25,4 +25,23 @@ let macaroonCreds = grpc.credentials.createFromMetadataGenerator(function(args,
|
||||
callback(null, metadata);
|
||||
});
|
||||
let creds = grpc.credentials.combineChannelCredentials(sslCreds, macaroonCreds);
|
||||
|
||||
// trying to unlock the wallet:
|
||||
if (config.lnd.password) {
|
||||
console.log('trying to unlock the wallet');
|
||||
var walletUnlocker = new lnrpc.WalletUnlocker(config.lnd.url, creds);
|
||||
walletUnlocker.unlockWallet(
|
||||
{
|
||||
wallet_password: config.lnd.password,
|
||||
},
|
||||
function(err, response) {
|
||||
if (err) {
|
||||
console.log('unlockWallet failed, probably because its been aleady unlocked');
|
||||
} else {
|
||||
console.log('unlockWallet:', response);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = new lnrpc.Lightning(config.lnd.url, creds);
|
||||
|
@ -23,13 +23,10 @@ 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(),
|
||||
],
|
||||
});
|
||||
|
||||
@ -45,7 +42,6 @@ if (!fs.existsSync('logs')) {
|
||||
* @param {string} message log message
|
||||
*/
|
||||
function log(label, message) {
|
||||
console.log(new Date(), label, message);
|
||||
logger.log({
|
||||
level: 'info',
|
||||
label: label,
|
||||
|
Loading…
x
Reference in New Issue
Block a user