diff --git a/CHANGELOG.md b/CHANGELOG.md index b1d7e7e..c21714a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Versions +## Version 6.4.0 + +- `accounting`: Improve the speed and reduce the backend burden of getting payment records +- `credentials`: Allow exporting credentials without spending privileges: `--nospend` +- `credentials`: Allow exporting credentials with read-only privileges: `--readonly` +- `delete-payments-history`: Add "hidden" command to allow deleting all payment records +- `increase-inbound-liquidity`: Fix issue when attempting without a specified API key +- `telegram`: Improve automatic recovery in situations where errors are encountered +- `telegram`: Reveal unverified "from" public key when receiving keysends with invalid signatures + ## Version 6.3.2 - `increase-inbound-liquidity`: Backup on-chain recovery to safeguard swap completion diff --git a/bos b/bos index 00a42ed..429d7bb 100755 --- a/bos +++ b/bos @@ -9,6 +9,7 @@ const {statSync} = require('fs'); const {unlink} = require('fs'); const {writeFile} = require('fs'); +const {deletePayments} = require('ln-service'); const fetch = require('node-fetch'); const {findKey} = require('ln-sync'); const inquirer = require('inquirer'); @@ -369,12 +370,14 @@ prog }); }) - // Export LND credentials from the standard + // Export LND credentials .command('credentials', 'Export local credentials') .help('Output encrypted remote access credentials. Use with "nodes --add"') .option('--cleartext', 'Output remote access credentials without encryption') .option('--days ', 'Expiration days for credentials', INT, 365) .option('--node ', 'Get credentials for a saved node') + .option('--nospend', 'Credentials do not include spending privileges') + .option('--readonly', 'Credentials only include read permissions') .action((args, options, logger) => { return new Promise((resolve, reject) => { return getCredentials({ @@ -382,6 +385,8 @@ prog ask: (n, cbk) => inquirer.prompt([n]).then(res => cbk(res)), expire_days: options.days, is_cleartext: options.cleartext, + is_nospend: options.nospend, + is_readonly: options.readonly, node: options.node, }, returnObject({logger, reject, resolve})); @@ -408,6 +413,23 @@ prog }); }) + // Delete all payments + .command('delete-payments-history', 'Delete all records of past payments') + .visible(false) + .option('--node ', 'Node to delete all past payments on') + .action((args, options, logger) => { + return new Promise(async (resolve, reject) => { + try { + return deletePayments({ + lnd: (await authenticatedLnd({logger, node: options.node})).lnd, + }, + returnObject({logger, reject, resolve})); + } catch (err) { + return reject(err); + } + }); + }) + // Encrypt a message .command('encrypt', 'Encrypt data using the node key') .visible(false) diff --git a/display/describe_route.js b/display/describe_route.js index d3e5ca9..2782904 100644 --- a/display/describe_route.js +++ b/display/describe_route.js @@ -1,7 +1,8 @@ const asyncAuto = require('async/auto'); const asyncMap = require('async/map'); const {getNode} = require('ln-service'); -const {green} = require('colorette'); +const {gray} = require('colorette'); +const {greenBright} = require('colorette'); const {returnResult} = require('asyncjs-util'); const describeConfidence = require('./describe_confidence'); @@ -90,22 +91,24 @@ module.exports = ({lnd, route}, cbk) => { const path = route.hops.map((hop, i, hops) => { const {alias} = getAliases.find(n => n.id === hop.public_key); + const {channel} = hop; + const isFinal = i === hops.length - 1; - const feeMtokens = !i ? hop.fee_mtokens : hops[i - 1].fee_mtokens; - const forwarder = `${alias} ${hop.public_key}`.trim(); + const feeMtokens = isFinal ? hops[i-1].fee_mtokens : hop.fee_mtokens; + const forwarder = `${greenBright(alias)} ${hop.public_key}`.trim(); const feeRate = effectiveFeeRate(feeMtokens, hop.forward_mtokens); const rate = formatFeeRate({rate: feeRate}).display; - const forward = `${green(forwarder)}. Hop fee rate ${rate}`; + const forward = `${forwarder}. Fee rate: ${rate}`; if (!i) { - return [`${hop.channel} ${description || String()}`, forward]; + return [`${gray(channel)} ${description || String()}`, forward]; } else if (i === hops.length - [i].length) { - return [`${hop.channel}`]; + return [`${gray(channel)}`]; } else { - return [`${hop.channel}`, forward]; + return [`${gray(channel)}`, forward]; } }); diff --git a/lnd/constants.json b/lnd/constants.json new file mode 100644 index 0000000..ab46cde --- /dev/null +++ b/lnd/constants.json @@ -0,0 +1,28 @@ +{ + "noSpendPerms": [ + "address:read", + "address:write", + "info:read", + "info:write", + "invoices:read", + "invoices:write", + "macaroon:read", + "message:read", + "offchain:read", + "onchain:read", + "peers:read", + "peers:write", + "signer:read" + ], + "permissionEntities": [ + "address", + "info", + "invoices", + "macaroon", + "message", + "offchain", + "onchain", + "peers", + "signer" + ] +} diff --git a/lnd/get_credentials.js b/lnd/get_credentials.js index 29ff544..bdaa611 100644 --- a/lnd/get_credentials.js +++ b/lnd/get_credentials.js @@ -1,5 +1,6 @@ const asyncAuto = require('async/auto'); const {encode} = require('cbor'); +const {grantAccess} = require('ln-service'); const moment = require('moment'); const {returnResult} = require('asyncjs-util'); @@ -12,6 +13,8 @@ const {pemAsDer} = require('./../encryption'); ask: ({message, name, type}, cbk) => {} [expire_days]: is_cleartext: + is_nospend: + is_readonly: logger: ({info}) => () [node]: } @@ -75,6 +78,8 @@ module.exports = (args, cbk) => { return lndCredentials({ expiry, key, + is_nospend: args.is_nospend, + is_readonly: args.is_readonly, logger: args.logger, node: args.node, }, diff --git a/lnd/lnd_credentials.js b/lnd/lnd_credentials.js index 1da7a0e..d854659 100644 --- a/lnd/lnd_credentials.js +++ b/lnd/lnd_credentials.js @@ -6,6 +6,8 @@ const {readFile} = require('fs'); const {spawn} = require('child_process'); const asyncAuto = require('async/auto'); +const {authenticatedLndGrpc} = require('ln-service'); +const {grantAccess} = require('ln-service'); const {restrictMacaroon} = require('ln-service'); const {returnResult} = require('asyncjs-util'); @@ -15,6 +17,8 @@ const getCert = require('./get_cert'); const getMacaroon = require('./get_macaroon'); const {getSavedCredentials} = require('./../nodes'); const getSocket = require('./get_socket'); +const {noSpendPerms} = require('./constants'); +const {permissionEntities} = require('./constants'); const config = 'config.json'; const defaultNodeName = process.env.BOS_DEFAULT_SAVED_NODE; @@ -22,12 +26,15 @@ const fs = {getFile: readFile}; const home = '.bos'; const os = {homedir, platform}; const {parse} = JSON; +const readPerms = permissionEntities.map(entity => `${entity}:read`); const socket = 'localhost:10009'; /** LND credentials { [expiry]: + [is_nospend]: + [is_readonly]: [key]: [logger]: [node]: // Defaults to default local mainnet node creds @@ -42,13 +49,13 @@ const socket = 'localhost:10009'; socket: } */ -module.exports = ({expiry, logger, key, node}, cbk) => { +module.exports = (args, cbk) => { return new Promise((resolve, reject) => { return asyncAuto({ // Figure out which node the credentials are for forNode: cbk => { - if (!!node) { - return cbk(null, node); + if (!!args.node) { + return cbk(null, args.node); } if (!!defaultNodeName) { @@ -129,8 +136,8 @@ module.exports = ({expiry, logger, key, node}, cbk) => { const cipher = credentials.encrypted_macaroon; - if (!!logger) { - logger.info({decrypt_credentials_for: forNode}); + if (!!args.logger) { + args.logger.info({decrypt_credentials_for: forNode}); } return decryptCiphertext({cipher, spawn}, (err, res) => { @@ -172,37 +179,60 @@ module.exports = ({expiry, logger, key, node}, cbk) => { // Macaroon with restriction macaroon: ['credentials', ({credentials}, cbk) => { - if (!expiry) { + if (!args.expiry) { return cbk(null, credentials.macaroon); } const {macaroon} = restrictMacaroon({ - expires_at: expiry, + expires_at: args.expiry, macaroon: credentials.macaroon, }); return cbk(null, macaroon); }], + // Get read-only macaroon if necessary + restrictMacaroon: [ + 'credentials', + 'macaroon', + ({credentials, macaroon}, cbk) => + { + // Exit early when readonly credentials are not requested + if (!args.is_readonly && !args.is_nospend) { + return cbk(null, {macaroon}); + } + + const {lnd} = authenticatedLndGrpc({ + macaroon, + cert: credentials.cert, + socket: credentials.socket, + }); + + const permissions = !!args.is_readonly ? readPerms : noSpendPerms; + + return grantAccess({lnd, permissions}, cbk); + }], + // Final credentials with encryption applied finalCredentials: [ 'credentials', 'getSocket', - 'macaroon', - ({credentials, getSocket, macaroon}, cbk) => + 'restrictMacaroon', + ({credentials, getSocket, restrictMacaroon}, cbk) => { // Exit early when the credentials are not encrypted - if (!key) { + if (!args.key) { return cbk(null, { - macaroon, + macaroon: restrictMacaroon.macaroon, cert: credentials.cert, socket: credentials.socket, }); } - const macaroonData = Buffer.from(macaroon, 'base64'); + const macaroonData = Buffer.from(restrictMacaroon.macaroon, 'base64'); + const {pem} = derAsPem({key: args.key}); - const encrypted = publicEncrypt(derAsPem({key}).pem, macaroonData); + const encrypted = publicEncrypt(pem, macaroonData); return cbk(null, { cert: credentials.cert, diff --git a/network/execute_probe.js b/network/execute_probe.js index 33210f5..4e74170 100644 --- a/network/execute_probe.js +++ b/network/execute_probe.js @@ -6,6 +6,7 @@ const {subscribeToProbe} = require('ln-service'); const {subscribeToProbeForRoute} = require('ln-service'); const {describeConfidence} = require('./../display'); +const {describeRoute} = require('./../display'); const {now} = Date; const minutesAsMs = minutes => 1000 * 60 * minutes; @@ -192,51 +193,12 @@ module.exports = (args, cbk) => { }); // Log probing attempts - sub.on('probing', ({route}) => { + sub.on('probing', async ({route}) => { attemptedPaths.push(route); - return asyncMapSeries(route.hops, (hop, cbk) => { - return getNode({ - is_omitting_channels: true, - lnd: args.lnd, - public_key: hop.public_key, - }, - (err, node) => { - // Ignore errors, not all nodes may be in the graph - const alias = (!!err || !node || !node.alias) ? '' : node.alias; + const {description} = await describeRoute({route, lnd: args.lnd}); - const towards = `${alias} ${hop.public_key}`; - - return cbk(null, {towards, channel: hop.channel, fee: hop.fee}); - }); - }, - (err, path) => { - if (!!err) { - return args.logger.error(err); - } - - const {confidence} = route; - - const {description} = describeConfidence({confidence}); - - const evaluating = path - .map((n, i) => { - const nextHop = path[i + 1]; - - if (!nextHop) { - return; - } - - return `${n.channel} ${n.towards}. Hop fee: ${n.fee}`; - }) - .filter(n => !!n); - - return args.logger.info({ - evaluating: !!evaluating.length ? evaluating : undefined, - confidence: description || undefined, - potential_fee: route.fee, - }); - }); + return args.logger.info({evaluating: description}); }); return; diff --git a/network/open_channels.js b/network/open_channels.js index ae12512..3b7c454 100644 --- a/network/open_channels.js +++ b/network/open_channels.js @@ -35,6 +35,7 @@ const interrogationSeparator = ' and \n '; const {isArray} = Array; const isHex = n => !!n && !(n.length % 2) && /^[0-9A-F]*$/i.test(n); const makeId = () => randomBytes(32).toString('hex'); +const peerAddedDelayMs = 1000 * 5; const per = (a, b) => (a / b).toFixed(2); const times = 10; const tokAsBigUnit = tokens => (tokens / 1e8).toFixed(8); @@ -208,7 +209,7 @@ module.exports = (args, cbk) => { return cbk([503, 'FailedToConnectToPeer', ({peer: key})]); } - return cbk(null, true); + return setTimeout(() => cbk(null, true), peerAddedDelayMs); }); }, cbk); diff --git a/package-lock.json b/package-lock.json index 01dcc26..c04abc4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "balanceofsatoshis", - "version": "6.3.2", + "version": "6.4.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -65,12 +65,12 @@ } }, "@babel/generator": { - "version": "7.11.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.6.tgz", - "integrity": "sha512-DWtQ1PV3r+cLbySoHrwn9RWEgKMBLLma4OBQloPRyDYvc5msJM9kvTLo1YnlJd1P/ZuKbdli3ijr5q3FvAF3uA==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.12.1.tgz", + "integrity": "sha512-DB+6rafIdc9o72Yc3/Ph5h+6hUjeOp66pF0naQBgUFFuPqzQwIlPTm3xZR7YNvduIMtkDIj2t21LSQwnbCrXvg==", "dev": true, "requires": { - "@babel/types": "^7.11.5", + "@babel/types": "^7.12.1", "jsesc": "^2.5.1", "source-map": "^0.5.0" }, @@ -182,9 +182,9 @@ } }, "@babel/parser": { - "version": "7.11.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz", - "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==", + "version": "7.12.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.3.tgz", + "integrity": "sha512-kFsOS0IbsuhO5ojF8Hc8z/8vEIOkylVBrjiZUbLTE3XFe0Qi+uu6HjzQixkFaqr0ZPAMZcBVxEwmsnsLPZ2Xsw==", "dev": true }, "@babel/template": { @@ -199,17 +199,17 @@ } }, "@babel/traverse": { - "version": "7.11.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.5.tgz", - "integrity": "sha512-EjiPXt+r7LiCZXEfRpSJd+jUMnBd4/9OUv7Nx3+0u9+eimMwJmG0Q98lw4/289JCoxSE8OolDMNZaaF/JZ69WQ==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.1.tgz", + "integrity": "sha512-MA3WPoRt1ZHo2ZmoGKNqi20YnPt0B1S0GTZEPhhd+hw2KGUzBlHuVunj6K4sNuK+reEvyiPwtp0cpaqLzJDmAw==", "dev": true, "requires": { "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.11.5", + "@babel/generator": "^7.12.1", "@babel/helper-function-name": "^7.10.4", "@babel/helper-split-export-declaration": "^7.11.0", - "@babel/parser": "^7.11.5", - "@babel/types": "^7.11.5", + "@babel/parser": "^7.12.1", + "@babel/types": "^7.12.1", "debug": "^4.1.0", "globals": "^11.1.0", "lodash": "^4.17.19" @@ -233,9 +233,9 @@ } }, "@babel/types": { - "version": "7.11.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", - "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.1.tgz", + "integrity": "sha512-BzSY3NJBKM4kyatSOWh3D/JJ2O3CVzBybHWxtgxnggaxEuaSTTDqeiSb/xk9lrkw2Tbqyivw5ZU4rT+EfznQsA==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.10.4", @@ -355,9 +355,9 @@ } }, "@types/bytebuffer": { - "version": "5.0.41", - "resolved": "https://registry.npmjs.org/@types/bytebuffer/-/bytebuffer-5.0.41.tgz", - "integrity": "sha512-Mdrv4YcaHvpkx25ksqqFaezktx3yZRcd51GZY0rY/9avyaqZdiT/GiWRhfrJhMpgzXqTOSHgGvsumGxJFNiZZA==", + "version": "5.0.42", + "resolved": "https://registry.npmjs.org/@types/bytebuffer/-/bytebuffer-5.0.42.tgz", + "integrity": "sha512-lEgKojWUAc/MG2t649oZS5AfYFP2xRNPoDuwDBlBMjHXd8MaGPgFgtCXUK7inZdBOygmVf10qxc1Us8GXC96aw==", "requires": { "@types/long": "*", "@types/node": "*" @@ -388,9 +388,9 @@ } }, "ajv": { - "version": "6.12.5", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.5.tgz", - "integrity": "sha512-lRF8RORchjpKG50/WFf8xmg7sgCLFiYNNnqdKflk63whMQcWR5ngGjiSXkL9bjxy6B2npOK2HSMN49jEBMSkag==", + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "requires": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -1153,9 +1153,9 @@ "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" }, "chokidar": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz", - "integrity": "sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz", + "integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==", "dev": true, "requires": { "anymatch": "~3.1.1", @@ -1165,7 +1165,7 @@ "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", - "readdirp": "~3.4.0" + "readdirp": "~3.5.0" } }, "chownr": { @@ -1321,9 +1321,9 @@ } }, "commander": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", - "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==" + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.1.0.tgz", + "integrity": "sha512-wl7PNrYWd2y5mp1OK/LhTlv8Ff4kQJQRXXAvF+uU/TPNiVJUxZLRYGj/B0y/lPGAVcSbJqH2Za/cvHmrPMC8mA==" }, "commondir": { "version": "1.0.1", @@ -1939,18 +1939,18 @@ "dev": true }, "flow-parser": { - "version": "0.135.0", - "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.135.0.tgz", - "integrity": "sha512-ev8SvmG+XU9D6WgHVezP4kY3Myr1tJvTUTEi7mbhhj+rn889K7YXdakte6oqXNLIJYJ2f5Fuw18zXTVa1NO8Kw==", + "version": "0.136.0", + "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.136.0.tgz", + "integrity": "sha512-PB2vYAqmz+dRikpx8TpNgRtBsyemP+7oQa0BcPZWnGABlJlB2WgJc/Lx0HeEPOUxDO/TxBbPaIHsffEIL9M6BQ==", "dev": true }, "flow-remove-types": { - "version": "2.135.0", - "resolved": "https://registry.npmjs.org/flow-remove-types/-/flow-remove-types-2.135.0.tgz", - "integrity": "sha512-l/9INhkrrTD+91k35P0eiF94E1cOpjfd86WVVqRwQRjamjSwTKKgu7MDLel3DGmBB09I2AXv7IjacNiwt0yc1g==", + "version": "2.136.0", + "resolved": "https://registry.npmjs.org/flow-remove-types/-/flow-remove-types-2.136.0.tgz", + "integrity": "sha512-VLmnyCbIx2thjuyidNeAMltxzpFxpFtx+6b0pYlpDz4O338HZPziRSDd2ytpk0/xRFbGrys38pscbmW3UbZtJw==", "dev": true, "requires": { - "flow-parser": "^0.135.0", + "flow-parser": "^0.136.0", "pirates": "^3.0.2", "vlq": "^0.2.1" } @@ -2129,6 +2129,28 @@ "version": "5.1.3", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==" + }, + "ln-service": { + "version": "49.14.0", + "resolved": "https://registry.npmjs.org/ln-service/-/ln-service-49.14.0.tgz", + "integrity": "sha512-01CoIfdo1vRQfc3siVGAZEDaKv3IrAwpjLLCtOa8aYxIwjQN+a7YC4GIBysbxiOaF0E+eZZIGz8Y76U7zWHhEQ==", + "requires": { + "@datastructures-js/priority-queue": "4.1.2", + "async": "3.2.0", + "asyncjs-util": "1.2.3", + "bitcoinjs-lib": "5.2.0", + "bn.js": "5.1.3", + "bolt07": "1.6.0", + "bolt09": "0.1.2", + "cors": "2.8.5", + "express": "4.17.1", + "invoices": "1.1.4", + "is-base64": "1.1.0", + "lightning": "2.0.54", + "macaroon": "3.0.4", + "morgan": "1.10.0", + "ws": "7.3.1" + } } } }, @@ -2958,11 +2980,11 @@ "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" }, "json2csv": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json2csv/-/json2csv-5.0.1.tgz", - "integrity": "sha512-QFMifUX1y8W2tKi2TwZpnzf2rHdZvzdmgZUMEMDF46F90f4a9mUeWfx/qg4kzXSZYJYc3cWA5O+eLXk5lj9g8g==", + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/json2csv/-/json2csv-5.0.3.tgz", + "integrity": "sha512-e3gEZU/4fp8CVQMHlwT77RayAR7nylCzCYN7jTIbPTEqk0oTaE8GTcBudLgXrHt4ltOs9SAsbveMJT0YK/QUSg==", "requires": { - "commander": "^5.0.0", + "commander": "^6.1.0", "jsonparse": "^1.3.1", "lodash.get": "^4.4.2" } @@ -3043,33 +3065,6 @@ "psbt": "1.1.5" }, "dependencies": { - "bn.js": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", - "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==" - } - } - }, - "ln-accounting": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/ln-accounting/-/ln-accounting-4.1.10.tgz", - "integrity": "sha512-9PgMSZ06ZQE3jjGphVqgZ6zGOvsxLdSK/KJyPEra/0+/ggsf/96j/4df3GWq5Sqs3uvOWlAqU7xrkIupbMmokg==", - "requires": { - "async": "3.2.0", - "asyncjs-util": "1.2.3", - "goldengate": "7.0.2", - "json2csv": "5.0.1", - "ln-service": "49.10.0" - }, - "dependencies": { - "@datastructures-js/priority-queue": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@datastructures-js/priority-queue/-/priority-queue-4.1.1.tgz", - "integrity": "sha512-2i9+/23VjcJRZrPRoQtuQwL8lMy/FVoRTMurZAV+1x0lZxCJjUUo8m83SC0ndCycFmiNjxdWVns/vsHWtj4bpQ==", - "requires": { - "@datastructures-js/heap": "^2.0.0" - } - }, "bip174": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/bip174/-/bip174-1.0.1.tgz", @@ -3080,59 +3075,17 @@ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==" }, - "bolt07": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/bolt07/-/bolt07-1.5.2.tgz", - "integrity": "sha512-P7LNOnBLtRYe0v30JvVR2xVvWWNrUt4IZ19njFRJb1NMhEx2xe+O0G7x4WZTWB7bHPAdkfR76l9F7jEVxizjlQ==", + "psbt": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/psbt/-/psbt-1.1.5.tgz", + "integrity": "sha512-NqVxxE78qG6dwnxpwR61niEaE5znUhOJOjjoGVsw4deX4OjE72py8wsEsCLuG7Yma7FsjhN58cmsMb2TqvoEGA==", "requires": { - "bn.js": "5.1.2" - }, - "dependencies": { - "bn.js": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.2.tgz", - "integrity": "sha512-40rZaf3bUNKTVYu9sIeeEGOg7g14Yvnj9kH7b50EiwX0Q7A6umbvfI5tvHaOERH0XigqKkfLkFQxzb4e6CIXnA==" - } - } - }, - "bolt09": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/bolt09/-/bolt09-0.1.1.tgz", - "integrity": "sha512-BX1LjpvU7qLyv8LRpYsq7p6fM2SiECWtfwjzx2/cStT0YFJhS74qFw5CfivoRz6ZEg3W7g1Exrv0tmDRkKeBkA==" - }, - "goldengate": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/goldengate/-/goldengate-7.0.2.tgz", - "integrity": "sha512-ION2SoSTsePG9boPyREvPbH0f3bz9ZnYfUUaZsgPlEwj+od7+vGvHTQRdEvg3hl4Yod2U+gxNG7SpMHsY9Yuaw==", - "requires": { - "@grpc/proto-loader": "0.5.5", - "@mitmaro/http-authorization-header": "1.0.0", - "async": "3.2.0", - "asyncjs-util": "1.2.3", - "bip65": "1.0.3", - "bip68": "1.0.4", + "bip66": "1.1.5", "bitcoin-ops": "1.4.1", - "bitcoinjs-lib": "5.2.0", - "bn.js": "5.1.3", - "cbor": "5.1.0", - "grpc": "1.24.3", - "ln-service": "49.10.0", - "macaroon": "3.0.4", + "bitcoinjs-lib": "5.1.10", + "bn.js": "5.1.2", "pushdata-bitcoin": "1.0.1", "varuint-bitcoin": "1.1.2" - } - }, - "invoices": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/invoices/-/invoices-1.1.3.tgz", - "integrity": "sha512-+RZmDmgVXvn6hAzGUqdl+1q8lEm9Th5XO/yg2aAIHpxhBc+BrrdCaMjjsk+weoZp9jm6LA92Dt2bzo+4ou1SVw==", - "requires": { - "bech32": "1.1.4", - "bitcoinjs-lib": "5.1.10", - "bn.js": "5.1.3", - "bolt07": "1.5.2", - "bolt09": "0.1.1", - "secp256k1": "4.0.2" }, "dependencies": { "bitcoinjs-lib": { @@ -3156,13 +3109,37 @@ "varuint-bitcoin": "^1.0.4", "wif": "^2.0.1" } + }, + "bn.js": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.2.tgz", + "integrity": "sha512-40rZaf3bUNKTVYu9sIeeEGOg7g14Yvnj9kH7b50EiwX0Q7A6umbvfI5tvHaOERH0XigqKkfLkFQxzb4e6CIXnA==" } } + } + } + }, + "ln-accounting": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/ln-accounting/-/ln-accounting-4.1.11.tgz", + "integrity": "sha512-3m6TAmzzhoti2Sshq4GZXOmYDsUu1j6leroTWP9kX1VvO6aYXKZmNhaL02xN64R+2toYeinZpISJWfxBhOJl+Q==", + "requires": { + "async": "3.2.0", + "asyncjs-util": "1.2.3", + "goldengate": "7.1.0", + "json2csv": "5.0.3", + "ln-service": "49.14.1" + }, + "dependencies": { + "bn.js": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", + "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==" }, "lightning": { - "version": "2.0.44", - "resolved": "https://registry.npmjs.org/lightning/-/lightning-2.0.44.tgz", - "integrity": "sha512-Xi8C0FmxIZ1Pg23JlXRoXc7ELEtskiWI7jfcdr1oYWpVlNxUJKc4ALrUMofqo+EXaoHhtEvc6byyHtxuNl6iLw==", + "version": "2.0.55", + "resolved": "https://registry.npmjs.org/lightning/-/lightning-2.0.55.tgz", + "integrity": "sha512-BvO6UblGDT2qyKEmkyk6PizixtynzsCY6xMnnuM9/0DOMLh7qO+vdJzYGZCgFs5EzQUyghJf2urV045l9AwAnA==", "requires": { "@grpc/proto-loader": "0.5.5", "async": "3.2.0", @@ -3170,31 +3147,32 @@ "bitcoinjs-lib": "5.2.0", "bn.js": "5.1.3", "body-parser": "1.19.0", - "bolt07": "1.5.2", - "bolt09": "0.1.1", + "bolt07": "1.6.0", + "bolt09": "0.1.2", "cbor": "5.1.0", "express": "4.17.1", "grpc": "1.24.3", - "invoices": "1.1.3" + "invoices": "1.1.4", + "psbt": "1.1.6" } }, "ln-service": { - "version": "49.10.0", - "resolved": "https://registry.npmjs.org/ln-service/-/ln-service-49.10.0.tgz", - "integrity": "sha512-XK3gFc+Qowy9SquJ37UUktn61dlyoAR/4eN6eV2WPSY4DaSahZ/Xwe9j3ljXnZjTL5FClNzAfPwAhS/ljrgbhw==", + "version": "49.14.1", + "resolved": "https://registry.npmjs.org/ln-service/-/ln-service-49.14.1.tgz", + "integrity": "sha512-VvKMOhpnvPp8NvPbcS2pGk/UwyEZO8jzcbOtflCqLTTuClw7a4pEGQwpPeVCDTD6V+BGVOnZ75OL93OOw+/xuQ==", "requires": { - "@datastructures-js/priority-queue": "4.1.1", + "@datastructures-js/priority-queue": "4.1.2", "async": "3.2.0", "asyncjs-util": "1.2.3", "bitcoinjs-lib": "5.2.0", "bn.js": "5.1.3", - "bolt07": "1.5.2", - "bolt09": "0.1.1", + "bolt07": "1.6.0", + "bolt09": "0.1.2", "cors": "2.8.5", "express": "4.17.1", - "invoices": "1.1.3", + "invoices": "1.1.4", "is-base64": "1.1.0", - "lightning": "2.0.44", + "lightning": "2.0.55", "macaroon": "3.0.4", "morgan": "1.10.0", "ws": "7.3.1" @@ -3203,9 +3181,9 @@ } }, "ln-service": { - "version": "49.14.0", - "resolved": "https://registry.npmjs.org/ln-service/-/ln-service-49.14.0.tgz", - "integrity": "sha512-01CoIfdo1vRQfc3siVGAZEDaKv3IrAwpjLLCtOa8aYxIwjQN+a7YC4GIBysbxiOaF0E+eZZIGz8Y76U7zWHhEQ==", + "version": "49.14.2", + "resolved": "https://registry.npmjs.org/ln-service/-/ln-service-49.14.2.tgz", + "integrity": "sha512-ppLCXAcVl/xMbu+Be9qIyGw2Gzmb4yoeW63adGsTCk7iXxtYg4wl89krem5a8gD/iIIINvv8/Llh7CWXmlzHnQ==", "requires": { "@datastructures-js/priority-queue": "4.1.2", "async": "3.2.0", @@ -3218,7 +3196,7 @@ "express": "4.17.1", "invoices": "1.1.4", "is-base64": "1.1.0", - "lightning": "2.0.54", + "lightning": "2.0.55", "macaroon": "3.0.4", "morgan": "1.10.0", "ws": "7.3.1" @@ -3228,6 +3206,26 @@ "version": "5.1.3", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==" + }, + "lightning": { + "version": "2.0.55", + "resolved": "https://registry.npmjs.org/lightning/-/lightning-2.0.55.tgz", + "integrity": "sha512-BvO6UblGDT2qyKEmkyk6PizixtynzsCY6xMnnuM9/0DOMLh7qO+vdJzYGZCgFs5EzQUyghJf2urV045l9AwAnA==", + "requires": { + "@grpc/proto-loader": "0.5.5", + "async": "3.2.0", + "asyncjs-util": "1.2.3", + "bitcoinjs-lib": "5.2.0", + "bn.js": "5.1.3", + "body-parser": "1.19.0", + "bolt07": "1.6.0", + "bolt09": "0.1.2", + "cbor": "5.1.0", + "express": "4.17.1", + "grpc": "1.24.3", + "invoices": "1.1.4", + "psbt": "1.1.6" + } } } }, @@ -3273,145 +3271,29 @@ } }, "ln-telegram": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ln-telegram/-/ln-telegram-1.1.0.tgz", - "integrity": "sha512-BGW814yCavm/ghA8INX/5cbB977QOi3tp1jyv+u/9vNExaL42bwU1v6nyJZ9ZkyWpYu8HJGev08khzlaxPEC7Q==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/ln-telegram/-/ln-telegram-3.0.2.tgz", + "integrity": "sha512-ZoAG/c9KAwIgN7u4BYaHDWGp5L82NDDrcVyBx/KCdbPc8lT+JsPmhRYZNLcyId5/xmJjW0G4cWjg0WgPyWNSUA==", "requires": { "@alexbosworth/request": "2.88.3", "async": "3.2.0", "asyncjs-util": "1.2.3", - "goldengate": "7.0.2", + "goldengate": "7.1.0", "invoices": "1.1.4", - "ln-service": "49.12.0", + "ln-service": "49.14.1", "ln-sync": "0.3.0", "table": "6.0.3" }, "dependencies": { - "@datastructures-js/priority-queue": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@datastructures-js/priority-queue/-/priority-queue-4.1.1.tgz", - "integrity": "sha512-2i9+/23VjcJRZrPRoQtuQwL8lMy/FVoRTMurZAV+1x0lZxCJjUUo8m83SC0ndCycFmiNjxdWVns/vsHWtj4bpQ==", - "requires": { - "@datastructures-js/heap": "^2.0.0" - } - }, - "bip174": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/bip174/-/bip174-1.0.1.tgz", - "integrity": "sha512-Mq2aFs1TdMfxBpYPg7uzjhsiXbAtoVq44TNjEWtvuZBiBgc3m7+n55orYMtTAxdg7jWbL4DtH0MKocJER4xERQ==" - }, "bn.js": { "version": "5.1.3", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==" }, - "bolt07": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/bolt07/-/bolt07-1.5.2.tgz", - "integrity": "sha512-P7LNOnBLtRYe0v30JvVR2xVvWWNrUt4IZ19njFRJb1NMhEx2xe+O0G7x4WZTWB7bHPAdkfR76l9F7jEVxizjlQ==", - "requires": { - "bn.js": "5.1.2" - }, - "dependencies": { - "bn.js": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.2.tgz", - "integrity": "sha512-40rZaf3bUNKTVYu9sIeeEGOg7g14Yvnj9kH7b50EiwX0Q7A6umbvfI5tvHaOERH0XigqKkfLkFQxzb4e6CIXnA==" - } - } - }, - "bolt09": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/bolt09/-/bolt09-0.1.1.tgz", - "integrity": "sha512-BX1LjpvU7qLyv8LRpYsq7p6fM2SiECWtfwjzx2/cStT0YFJhS74qFw5CfivoRz6ZEg3W7g1Exrv0tmDRkKeBkA==" - }, - "goldengate": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/goldengate/-/goldengate-7.0.2.tgz", - "integrity": "sha512-ION2SoSTsePG9boPyREvPbH0f3bz9ZnYfUUaZsgPlEwj+od7+vGvHTQRdEvg3hl4Yod2U+gxNG7SpMHsY9Yuaw==", - "requires": { - "@grpc/proto-loader": "0.5.5", - "@mitmaro/http-authorization-header": "1.0.0", - "async": "3.2.0", - "asyncjs-util": "1.2.3", - "bip65": "1.0.3", - "bip68": "1.0.4", - "bitcoin-ops": "1.4.1", - "bitcoinjs-lib": "5.2.0", - "bn.js": "5.1.3", - "cbor": "5.1.0", - "grpc": "1.24.3", - "ln-service": "49.10.0", - "macaroon": "3.0.4", - "pushdata-bitcoin": "1.0.1", - "varuint-bitcoin": "1.1.2" - }, - "dependencies": { - "invoices": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/invoices/-/invoices-1.1.3.tgz", - "integrity": "sha512-+RZmDmgVXvn6hAzGUqdl+1q8lEm9Th5XO/yg2aAIHpxhBc+BrrdCaMjjsk+weoZp9jm6LA92Dt2bzo+4ou1SVw==", - "requires": { - "bech32": "1.1.4", - "bitcoinjs-lib": "5.1.10", - "bn.js": "5.1.3", - "bolt07": "1.5.2", - "bolt09": "0.1.1", - "secp256k1": "4.0.2" - }, - "dependencies": { - "bitcoinjs-lib": { - "version": "5.1.10", - "resolved": "https://registry.npmjs.org/bitcoinjs-lib/-/bitcoinjs-lib-5.1.10.tgz", - "integrity": "sha512-CesUqtBtnYc+SOMsYN9jWQWhdohW1MpklUkF7Ukn4HiAyN6yxykG+cIJogfRt6x5xcgH87K1Q+Mnoe/B+du1Iw==", - "requires": { - "bech32": "^1.1.2", - "bip174": "^1.0.1", - "bip32": "^2.0.4", - "bip66": "^1.1.0", - "bitcoin-ops": "^1.4.0", - "bs58check": "^2.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.3", - "merkle-lib": "^2.0.10", - "pushdata-bitcoin": "^1.0.1", - "randombytes": "^2.0.1", - "tiny-secp256k1": "^1.1.1", - "typeforce": "^1.11.3", - "varuint-bitcoin": "^1.0.4", - "wif": "^2.0.1" - } - } - } - }, - "ln-service": { - "version": "49.10.0", - "resolved": "https://registry.npmjs.org/ln-service/-/ln-service-49.10.0.tgz", - "integrity": "sha512-XK3gFc+Qowy9SquJ37UUktn61dlyoAR/4eN6eV2WPSY4DaSahZ/Xwe9j3ljXnZjTL5FClNzAfPwAhS/ljrgbhw==", - "requires": { - "@datastructures-js/priority-queue": "4.1.1", - "async": "3.2.0", - "asyncjs-util": "1.2.3", - "bitcoinjs-lib": "5.2.0", - "bn.js": "5.1.3", - "bolt07": "1.5.2", - "bolt09": "0.1.1", - "cors": "2.8.5", - "express": "4.17.1", - "invoices": "1.1.3", - "is-base64": "1.1.0", - "lightning": "2.0.44", - "macaroon": "3.0.4", - "morgan": "1.10.0", - "ws": "7.3.1" - } - } - } - }, "lightning": { - "version": "2.0.44", - "resolved": "https://registry.npmjs.org/lightning/-/lightning-2.0.44.tgz", - "integrity": "sha512-Xi8C0FmxIZ1Pg23JlXRoXc7ELEtskiWI7jfcdr1oYWpVlNxUJKc4ALrUMofqo+EXaoHhtEvc6byyHtxuNl6iLw==", + "version": "2.0.55", + "resolved": "https://registry.npmjs.org/lightning/-/lightning-2.0.55.tgz", + "integrity": "sha512-BvO6UblGDT2qyKEmkyk6PizixtynzsCY6xMnnuM9/0DOMLh7qO+vdJzYGZCgFs5EzQUyghJf2urV045l9AwAnA==", "requires": { "@grpc/proto-loader": "0.5.5", "async": "3.2.0", @@ -3419,57 +3301,19 @@ "bitcoinjs-lib": "5.2.0", "bn.js": "5.1.3", "body-parser": "1.19.0", - "bolt07": "1.5.2", - "bolt09": "0.1.1", + "bolt07": "1.6.0", + "bolt09": "0.1.2", "cbor": "5.1.0", "express": "4.17.1", "grpc": "1.24.3", - "invoices": "1.1.3" - }, - "dependencies": { - "invoices": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/invoices/-/invoices-1.1.3.tgz", - "integrity": "sha512-+RZmDmgVXvn6hAzGUqdl+1q8lEm9Th5XO/yg2aAIHpxhBc+BrrdCaMjjsk+weoZp9jm6LA92Dt2bzo+4ou1SVw==", - "requires": { - "bech32": "1.1.4", - "bitcoinjs-lib": "5.1.10", - "bn.js": "5.1.3", - "bolt07": "1.5.2", - "bolt09": "0.1.1", - "secp256k1": "4.0.2" - }, - "dependencies": { - "bitcoinjs-lib": { - "version": "5.1.10", - "resolved": "https://registry.npmjs.org/bitcoinjs-lib/-/bitcoinjs-lib-5.1.10.tgz", - "integrity": "sha512-CesUqtBtnYc+SOMsYN9jWQWhdohW1MpklUkF7Ukn4HiAyN6yxykG+cIJogfRt6x5xcgH87K1Q+Mnoe/B+du1Iw==", - "requires": { - "bech32": "^1.1.2", - "bip174": "^1.0.1", - "bip32": "^2.0.4", - "bip66": "^1.1.0", - "bitcoin-ops": "^1.4.0", - "bs58check": "^2.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.3", - "merkle-lib": "^2.0.10", - "pushdata-bitcoin": "^1.0.1", - "randombytes": "^2.0.1", - "tiny-secp256k1": "^1.1.1", - "typeforce": "^1.11.3", - "varuint-bitcoin": "^1.0.4", - "wif": "^2.0.1" - } - } - } - } + "invoices": "1.1.4", + "psbt": "1.1.6" } }, "ln-service": { - "version": "49.12.0", - "resolved": "https://registry.npmjs.org/ln-service/-/ln-service-49.12.0.tgz", - "integrity": "sha512-giGNeXH/d2vpzny9HdxTp7DSHN+gnL2Qz8U4RHW5sIOOdc4dXR4E/G1H5cpKovX0Ix4IuQ8FlyvwwXwMHPJHEw==", + "version": "49.14.1", + "resolved": "https://registry.npmjs.org/ln-service/-/ln-service-49.14.1.tgz", + "integrity": "sha512-VvKMOhpnvPp8NvPbcS2pGk/UwyEZO8jzcbOtflCqLTTuClw7a4pEGQwpPeVCDTD6V+BGVOnZ75OL93OOw+/xuQ==", "requires": { "@datastructures-js/priority-queue": "4.1.2", "async": "3.2.0", @@ -3482,52 +3326,10 @@ "express": "4.17.1", "invoices": "1.1.4", "is-base64": "1.1.0", - "lightning": "2.0.50", + "lightning": "2.0.55", "macaroon": "3.0.4", "morgan": "1.10.0", "ws": "7.3.1" - }, - "dependencies": { - "@datastructures-js/priority-queue": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/@datastructures-js/priority-queue/-/priority-queue-4.1.2.tgz", - "integrity": "sha512-S4fXJcsPdqEp2bbKZlH7suSiZ0lqmIs8n5BXqQXB+7/lA9LSK/Ng0hIehTjgETfe7n3g4ZVLoyjEUWHEbHJFdQ==", - "requires": { - "@datastructures-js/heap": "^2.0.0" - } - }, - "bolt07": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/bolt07/-/bolt07-1.6.0.tgz", - "integrity": "sha512-c+o1FdDxsmrCmrcqW6YRpk/dHDXk3frqHd1552b0JMXM2Kp6K74dbj74vioeYYUTzwyXB3zZFh9g2OZBg3JcYQ==", - "requires": { - "bn.js": "5.1.3" - } - }, - "bolt09": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/bolt09/-/bolt09-0.1.2.tgz", - "integrity": "sha512-UcjCWM5w0ncmeLy+L1ghgWBmFUD7F+tvYpYw/pi1PLXMhRJ10gHFbPjzX2CTMsU0ICb8CisIFBsd16DWaUd4FA==" - }, - "lightning": { - "version": "2.0.50", - "resolved": "https://registry.npmjs.org/lightning/-/lightning-2.0.50.tgz", - "integrity": "sha512-vLD7N0OH5prJ+Ebt0lYestUuVKRmqMapH00jK+SR8IxIxzT6JM/KpMSJNWujUkP6yRSwBPF7QSUrIf/U1nk/FQ==", - "requires": { - "@grpc/proto-loader": "0.5.5", - "async": "3.2.0", - "asyncjs-util": "1.2.3", - "bitcoinjs-lib": "5.2.0", - "bn.js": "5.1.3", - "body-parser": "1.19.0", - "bolt07": "1.6.0", - "bolt09": "0.1.2", - "cbor": "5.1.0", - "express": "4.17.1", - "grpc": "1.24.3", - "invoices": "1.1.4" - } - } } } } @@ -3862,9 +3664,9 @@ "integrity": "sha1-SJYrGeFp/R38JAs/HnMXYnu8R9s=" }, "nan": { - "version": "2.14.1", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz", - "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==" + "version": "2.14.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", + "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==" }, "napi-build-utils": { "version": "1.0.2", @@ -4621,6 +4423,35 @@ "bolt07": "1.6.0", "invoices": "1.1.4", "ln-service": "49.14.0" + }, + "dependencies": { + "bn.js": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", + "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==" + }, + "ln-service": { + "version": "49.14.0", + "resolved": "https://registry.npmjs.org/ln-service/-/ln-service-49.14.0.tgz", + "integrity": "sha512-01CoIfdo1vRQfc3siVGAZEDaKv3IrAwpjLLCtOa8aYxIwjQN+a7YC4GIBysbxiOaF0E+eZZIGz8Y76U7zWHhEQ==", + "requires": { + "@datastructures-js/priority-queue": "4.1.2", + "async": "3.2.0", + "asyncjs-util": "1.2.3", + "bitcoinjs-lib": "5.2.0", + "bn.js": "5.1.3", + "bolt07": "1.6.0", + "bolt09": "0.1.2", + "cors": "2.8.5", + "express": "4.17.1", + "invoices": "1.1.4", + "is-base64": "1.1.0", + "lightning": "2.0.54", + "macaroon": "3.0.4", + "morgan": "1.10.0", + "ws": "7.3.1" + } + } } }, "process-nextick-args": { @@ -4660,9 +4491,9 @@ }, "dependencies": { "@types/node": { - "version": "13.13.24", - "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.24.tgz", - "integrity": "sha512-ry1JlHIVcmQFNq5KWgdEo1NVu7qFDi+vQPknWWDCc05cekTLVr2y0FHAKXTfv4OLWw+GOzdVe8eFWPoYEdk05w==" + "version": "13.13.26", + "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.26.tgz", + "integrity": "sha512-+48LLqolaKj/WnIY1crfLseaGQMIDISBy3PTXVOZ7w/PBaRUv+H8t94++atzfoBAvorbUYz6Xq9vh1fHrg33ig==" } } }, @@ -4676,49 +4507,22 @@ } }, "psbt": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/psbt/-/psbt-1.1.5.tgz", - "integrity": "sha512-NqVxxE78qG6dwnxpwR61niEaE5znUhOJOjjoGVsw4deX4OjE72py8wsEsCLuG7Yma7FsjhN58cmsMb2TqvoEGA==", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/psbt/-/psbt-1.1.6.tgz", + "integrity": "sha512-snms+l+yUEDeYJWJrjIBrYqYseVpuO0jp/wjG6Mkcmhahcs58kswFoL+z4cmKgv11P64BYoIzmUgQBHJC+KxOw==", "requires": { "bip66": "1.1.5", "bitcoin-ops": "1.4.1", - "bitcoinjs-lib": "5.1.10", - "bn.js": "5.1.2", + "bitcoinjs-lib": "5.2.0", + "bn.js": "5.1.3", "pushdata-bitcoin": "1.0.1", "varuint-bitcoin": "1.1.2" }, "dependencies": { - "bip174": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/bip174/-/bip174-1.0.1.tgz", - "integrity": "sha512-Mq2aFs1TdMfxBpYPg7uzjhsiXbAtoVq44TNjEWtvuZBiBgc3m7+n55orYMtTAxdg7jWbL4DtH0MKocJER4xERQ==" - }, - "bitcoinjs-lib": { - "version": "5.1.10", - "resolved": "https://registry.npmjs.org/bitcoinjs-lib/-/bitcoinjs-lib-5.1.10.tgz", - "integrity": "sha512-CesUqtBtnYc+SOMsYN9jWQWhdohW1MpklUkF7Ukn4HiAyN6yxykG+cIJogfRt6x5xcgH87K1Q+Mnoe/B+du1Iw==", - "requires": { - "bech32": "^1.1.2", - "bip174": "^1.0.1", - "bip32": "^2.0.4", - "bip66": "^1.1.0", - "bitcoin-ops": "^1.4.0", - "bs58check": "^2.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.3", - "merkle-lib": "^2.0.10", - "pushdata-bitcoin": "^1.0.1", - "randombytes": "^2.0.1", - "tiny-secp256k1": "^1.1.1", - "typeforce": "^1.11.3", - "varuint-bitcoin": "^1.0.4", - "wif": "^2.0.1" - } - }, "bn.js": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.2.tgz", - "integrity": "sha512-40rZaf3bUNKTVYu9sIeeEGOg7g14Yvnj9kH7b50EiwX0Q7A6umbvfI5tvHaOERH0XigqKkfLkFQxzb4e6CIXnA==" + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", + "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==" } } }, @@ -4809,9 +4613,9 @@ } }, "react": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react/-/react-16.13.1.tgz", - "integrity": "sha512-YMZQQq32xHLX0bz5Mnibv1/LHb3Sqzngu7xstSM+vrkE5Kzr9xE0yMByK5kMoTK30YVJE61WfbxIFFvfeDKT1w==", + "version": "16.14.0", + "resolved": "https://registry.npmjs.org/react/-/react-16.14.0.tgz", + "integrity": "sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==", "dev": true, "requires": { "loose-envify": "^1.1.0", @@ -4857,9 +4661,9 @@ } }, "readdirp": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", - "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", + "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", "dev": true, "requires": { "picomatch": "^2.2.1" @@ -6924,9 +6728,9 @@ } }, "tslib": { - "version": "1.14.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.0.tgz", - "integrity": "sha512-+Zw5lu0D9tvBMjGP8LpvMb0u2WW2QV3y+D8mO6J+cNzCYIN4sVy43Bf9vl92nqFahutN0I8zHa7cc4vihIshnw==" + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "tunnel-agent": { "version": "0.6.0", diff --git a/package.json b/package.json index 54c43ca..ed3ff66 100644 --- a/package.json +++ b/package.json @@ -30,14 +30,14 @@ "ini": "1.3.5", "inquirer": "7.3.3", "invoices": "1.1.4", - "ln-accounting": "4.1.10", - "ln-service": "49.14.0", + "ln-accounting": "4.1.11", + "ln-service": "49.14.2", "ln-sync": "0.3.0", - "ln-telegram": "1.1.0", + "ln-telegram": "3.0.2", "moment": "2.29.1", "node-fetch": "2.6.1", "probing": "1.3.0", - "psbt": "1.1.5", + "psbt": "1.1.6", "qrcode-terminal": "0.12.0", "sanitize-filename": "1.6.3", "stats-lite": "2.2.0", @@ -73,5 +73,5 @@ "postpublish": "docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 -t alexbosworth/balanceofsatoshis --push .", "test": "tap test/arrays/*.js test/balances/*.js test/chain/*.js test/display/*.js test/encryption/*.js test/fiat/*.js test/lnd/*.js test/network/*.js test/nodes/*.js test/responses/*.js test/routing/*.js test/swaps/*.js test/wallets/*.js" }, - "version": "6.3.2" + "version": "6.4.0" } diff --git a/swaps/get_paid_service.js b/swaps/get_paid_service.js index 2b9e21c..ea81eee 100644 --- a/swaps/get_paid_service.js +++ b/swaps/get_paid_service.js @@ -5,11 +5,11 @@ const {getNetwork} = require('ln-sync'); const {getSwapMacaroon} = require('goldengate'); const {lightningLabsSwapService} = require('goldengate'); const {paidMacaroon} = require('goldengate'); +const {payViaPaymentRequest} = require('ln-service'); const {returnResult} = require('asyncjs-util'); const {swapUserId} = require('goldengate'); const decodeSwapApiKey = require('./decode_swap_api_key'); -const {probeDestination} = require('./../network'); const bitcoinTestnetNetwork = 'btctestnet'; const bufferFromBase64 = base64 => Buffer.from(base64, 'base64'); @@ -24,7 +24,6 @@ const testnetSocket = 'https://balanceofsatoshis.com:11010'; { fetch: lnd: - logger: [socket]: [token]: } @@ -39,7 +38,7 @@ const testnetSocket = 'https://balanceofsatoshis.com:11010'; token: } */ -module.exports = ({fetch, lnd, logger, socket, token}, cbk) => { +module.exports = ({fetch, lnd, socket, token}, cbk) => { return new Promise((resolve, reject) => { return asyncAuto({ // Check arguments @@ -52,10 +51,6 @@ module.exports = ({fetch, lnd, logger, socket, token}, cbk) => { return cbk([400, 'ExpectedLndToGetPaidService']); } - if (!logger) { - return cbk([400, 'ExpectedLoggerToGetPaidService']); - } - return cbk(); }, @@ -122,14 +117,12 @@ module.exports = ({fetch, lnd, logger, socket, token}, cbk) => { { // Exit early when there is already a paid service token if (!!decodeToken) { - return cbk(null, {preimage: decodeToken.preimage}); + return cbk(null, {secret: decodeToken.preimage}); } // Purchase the macaroon - return probeDestination({ + return payViaPaymentRequest({ lnd, - logger, - is_real_payment: true, max_fee: maxRoutingFee, request: getUnpaidMacaroon.request, }, @@ -146,11 +139,11 @@ module.exports = ({fetch, lnd, logger, socket, token}, cbk) => { { const {id} = getUnpaidMacaroon; const {macaroon} = getUnpaidMacaroon; - const {paid} = payForMacaroon; - const {preimage} = payForMacaroon; + const paid = payForMacaroon.tokens; + const preimage = payForMacaroon.secret; const {service} = remote; - if (!decodeToken && !paid) { + if (!decodeToken && !preimage) { return cbk([400, 'FailedToPurchasePaidServiceTokens']); } diff --git a/swaps/swap_out.js b/swaps/swap_out.js index a45ee6c..82176fc 100644 --- a/swaps/swap_out.js +++ b/swaps/swap_out.js @@ -336,7 +336,6 @@ module.exports = (args, cbk) => { network, fetch: args.fetch, lnd: args.lnd, - logger: args.logger, socket: args.socket, token: args.api_key, }, diff --git a/telegram/start_telegram_bot.js b/telegram/start_telegram_bot.js index ff9e287..5fefb46 100644 --- a/telegram/start_telegram_bot.js +++ b/telegram/start_telegram_bot.js @@ -5,6 +5,7 @@ const asyncAuto = require('async/auto'); const asyncEach = require('async/each'); const asyncForever = require('async/forever'); const asyncMap = require('async/map'); +const {getForwards} = require('ln-service'); const {getTransactionRecord} = require('ln-sync'); const {getWalletInfo} = require('ln-service'); const {handleBackupCommand} = require('ln-telegram'); @@ -16,14 +17,15 @@ const {handleLiquidityCommand} = require('ln-telegram'); const {handleMempoolCommand} = require('ln-telegram'); const {handlePayCommand} = require('ln-telegram'); const inquirer = require('inquirer'); +const {notifyOfForwards} = require('ln-telegram'); const {postChainTransaction} = require('ln-telegram'); const {postClosedMessage} = require('ln-telegram'); -const {postForwardedPayments} = require('ln-telegram'); const {postOpenMessage} = require('ln-telegram'); const {postSettledInvoice} = require('ln-telegram'); -const {postUpdatedBackups} = require('ln-telegram'); +const {postUpdatedBackup} = require('ln-telegram'); const {returnResult} = require('asyncjs-util'); const {sendMessage} = require('ln-telegram'); +const {subscribeToBackups} = require('ln-service'); const {subscribeToBlocks} = require('goldengate'); const {subscribeToChannels} = require('ln-service'); const {subscribeToInvoices} = require('ln-service'); @@ -40,6 +42,7 @@ const fromName = node => `${node.alias} ${node.public_key.substring(0, 8)}`; const home = '.bos'; const {isArray} = Array; const isNumber = n => !isNaN(n); +const limit = 99999; const maxCommandDelayMs = 1000 * 10; const msSince = epoch => Date.now() - (epoch * 1e3); const network = 'btc'; @@ -68,6 +71,7 @@ module.exports = ({fs, id, lnds, logger, payments, request}, cbk) => { let connectedId = id; let isStopped = false; let paymentsLimit = !payments || !payments.limit ? Number() : payments.limit; + const subscriptions = []; return new Promise((resolve, reject) => { return asyncAuto({ @@ -371,15 +375,34 @@ module.exports = ({fs, id, lnds, logger, payments, request}, cbk) => { // Subscribe to backups backups: ['apiKey', 'getNodes', 'userId', ({apiKey, getNodes}, cbk) => { return asyncEach(getNodes, (node, cbk) => { - return postUpdatedBackups({ - logger, - request, - id: connectedId, - key: apiKey, - lnd: node.lnd, - node: {alias: node.alias, public_key: node.public_key}, - }, - cbk); + let postBackupTimeoutHandle; + const sub = subscribeToBackups({lnd: node.lnd}); + + subscriptions.push(sub); + + sub.on('backup', ({backup}) => { + // Cancel pending backup notification when there is a new backup + if (!!postBackupTimeoutHandle) { + clearTimeout(postBackupTimeoutHandle); + } + + // Time delay backup posting to avoid posting duplicate messages + postBackupTimeoutHandle = setTimeout(() => { + return postUpdatedBackup({ + backup, + request, + id: connectedId, + key: apiKey, + node: {alias: node.alias, public_key: node.public_key}, + }, + err => !!err ? logger.error({post_backup_err: err}) : null); + }, + restartSubscriptionTimeMs); + + return; + }); + + sub.on('error', err => cbk([503, 'ErrorInBackupsSub', {err}])); }, cbk); }], @@ -394,6 +417,8 @@ module.exports = ({fs, id, lnds, logger, payments, request}, cbk) => { return asyncEach(getNodes, ({from, lnd}, cbk) => { const sub = subscribeToChannels({lnd}); + subscriptions.push(sub); + sub.on('channel_closed', update => { return postClosedMessage({ from, @@ -458,13 +483,45 @@ module.exports = ({fs, id, lnds, logger, payments, request}, cbk) => { // Poll for forwards forwards: ['apiKey', 'getNodes', 'userId', ({apiKey, getNodes}, cbk) => { - return asyncEach(getNodes, ({from, lnd}, cbk) => { - return postForwardedPayments({ - from, - lnd, - request, - id: connectedId, - key: apiKey, + return asyncEach(getNodes, (node, cbk) => { + let after = new Date().toISOString(); + const {from} = node; + const {lnd} = node; + + return asyncForever(cbk => { + if (isStopped) { + return cbk([503, 'ExpectedNonStoppedBotToReportForwards']); + } + + const before = new Date().toISOString(); + + return getForwards({after, before, limit, lnd}, (err, res) => { + // Exit early and ignore errors + if (!!err) { + return setTimeout(cbk, restartSubscriptionTimeMs); + } + + // Push cursor forward + after = before; + + // Notify Telegram bot that forwards happened + return notifyOfForwards({ + from, + lnd, + request, + forwards: res.forwards, + id: connectedId, + key: apiKey, + node: node.public_key, + }, + err => { + if (!!err) { + logger.error({forwards_notify_err: err}); + } + + return setTimeout(cbk, restartSubscriptionTimeMs); + }); + }); }, cbk); }, @@ -476,6 +533,8 @@ module.exports = ({fs, id, lnds, logger, payments, request}, cbk) => { return asyncEach(getNodes, ({from, lnd}, cbk) => { const sub = subscribeToInvoices({lnd}); + subscriptions.push(sub); + sub.on('invoice_updated', invoice => { return postSettledInvoice({ from, @@ -518,6 +577,8 @@ module.exports = ({fs, id, lnds, logger, payments, request}, cbk) => { const sub = subscribeToTransactions({lnd}); const transactions = []; + subscriptions.push(sub); + sub.on('chain_transaction', async transaction => { const {id} = transaction; @@ -537,14 +598,13 @@ module.exports = ({fs, id, lnds, logger, payments, request}, cbk) => { return await postChainTransaction({ from, - lnd, request, id: connectedId, key: apiKey, transaction: record, }); } catch (err) { - logger.error({chain_tx_err: err}); + logger.error({chain_tx_err: err, node: from}); if (!!isFinished) { return; @@ -583,7 +643,9 @@ module.exports = ({fs, id, lnds, logger, payments, request}, cbk) => { (err, res) => { isStopped = true; - return returnResult({reject, resolve})(err, res); + subscriptions.forEach(n => n.removeAllListeners()); + + return returnResult({reject, resolve}, cbk)(err, res); }); }); }; diff --git a/test/swaps/test_get_paid_service.js b/test/swaps/test_get_paid_service.js index 9f87feb..f972660 100644 --- a/test/swaps/test_get_paid_service.js +++ b/test/swaps/test_get_paid_service.js @@ -16,7 +16,6 @@ const makeArgs = override => { getInfo: ({}, cbk) => cbk(null, getInfoResponse), }, }, - logger: {}, token: makeToken(Buffer.from(macaroon, 'base64'), Buffer.alloc(1, 1)), }; @@ -31,11 +30,6 @@ const tests = [ description: 'LND object is required', error: [400, 'ExpectedLndToGetPaidService'], }, - { - args: makeArgs({logger: undefined}), - description: 'Logger object is required', - error: [400, 'ExpectedLoggerToGetPaidService'], - }, { args: makeArgs({}), description: 'A paid service object is returned', diff --git a/wallets/report_overview.js b/wallets/report_overview.js index 2e1a65a..8c0bd6c 100644 --- a/wallets/report_overview.js +++ b/wallets/report_overview.js @@ -2,7 +2,7 @@ const moment = require('moment'); const dollarFormat = cents => (cents / 100).toFixed(2); const formatAsBigUnit = tokens => (tokens / 1e8).toFixed(8); -const percentFormat = n => (n * 100).toFixed(); +const percentFormat = n => isNaN(n) ? '0' : (n * 100).toFixed(); /** Derive report overview