abstract methods and update dependencies

This commit is contained in:
Alex Bosworth 2020-07-18 13:16:37 -07:00
parent 25f08edabc
commit 91957107bc
No known key found for this signature in database
GPG key ID: E80D2F3F311FD87E
17 changed files with 287 additions and 748 deletions

View file

@ -1,6 +1,6 @@
# Versions
## Version 5.41.1
## Version 5.41.2
- `probe`: Add `--max-paths` option to inform `--find-max` probing
- `telegram` Improve database-sync reliability

4
bos
View file

@ -50,6 +50,7 @@ const {lndCredentials} = require('./lnd');
const marketPairs = require('./fiat').pairs;
const {openChannel} = require('./network');
const {openChannels} = require('./network');
const {peerSortOptions} = require('./network');
const {priceProviders} = require('./fiat');
const {probe} = require('./network');
const {probeDestination} = require('./network');
@ -840,6 +841,7 @@ prog
// Get a list of channel-connected peers
.command('peers', 'Get a list of channel-connected peers')
.help(`Sort options: ${peerSortOptions.join(', ')}`)
.option('--active', 'Only active peer channels')
.option('--complete', 'Show complete set of records in non table view')
.option('--fee-days <past_days>', 'Include fees earned over n days', INT)
@ -852,7 +854,7 @@ prog
.option('--outbound-below <amount>', 'Outbound liquidity below amount', INT)
.option('--private', 'Only private channels')
.option('--public', 'Only peers with public channels')
.option('--sort', 'Sort results by peer attribute')
.option('--sort <by>', 'Sort results by peer attribute', peerSortOptions)
.action((args, options, logger) => {
const table = !!options.complete ? undefined : 'rows';

11
network/constants.json Normal file
View file

@ -0,0 +1,11 @@
{
"peerSortOptions": [
"alias",
"fee_earnings",
"first_connected",
"inbound_fee_rate",
"inbound_liquidity",
"outbound_liquidity",
"public_key"
]
}

View file

@ -9,6 +9,7 @@ const multiPathProbe = require('./multi_path_probe');
const networks = require('./networks');
const openChannel = require('./open_channel');
const openChannels = require('./open_channels');
const {peerSortOptions} = require('./constants');
const probe = require('./probe');
const probeDestination = require('./probe_destination');
const reconnect = require('./reconnect');
@ -28,6 +29,7 @@ module.exports = {
networks,
openChannel,
openChannels,
peerSortOptions,
probe,
probeDestination,
reconnect,

View file

@ -85,7 +85,7 @@ module.exports = (args, cbk) => {
channels: getChannels.channels,
from: getKey.public_key,
ignore: args.ignore,
probes: args.probes,
probes: args.probes.filter(n => !!n.relays),
tokens: args.tokens,
});
@ -131,10 +131,6 @@ module.exports = (args, cbk) => {
return cbk(null, {error});
}
if (!probe.route_maximum) {
return cbk(null, {});
}
return cbk(null, {probe});
});
}],

View file

@ -1,4 +1,5 @@
const flatten = arr => [].concat(...arr);
const {isArray} = Array;
const uniq = arr => Array.from(new Set(arr));
/** Calculate multi-probe adjustments
@ -46,7 +47,21 @@ const uniq = arr => Array.from(new Set(arr));
}
*/
module.exports = ({channels, from, ignore, probes, tokens}) => {
const msSpent = probes.reduce((sum, n) => sum + n.latency_ms, Number());
if (!isArray(probes)) {
throw new Error('ExpectedArrayOfProbesToGenerateMultiProbeIgnores');
}
if (probes.filter(n => !!n).length !== probes.length) {
throw new Error('ExpectedProbeDetailsToGenerateMultiProbeIgnores');
}
if (!!probes.find(n => !isArray(n.relays))) {
throw new Error('ExpectedArrayOfRelaysToGenerateMultiProbeIgnores');
}
const latencies = probes.map(n => n.latency_ms).filter(n => !!n);
const msSpent = latencies.reduce((sum, n) => sum + n, Number());
const pairs = probes.map(probe => {
const [out, ...network] = probe.relays.map((to, i, arr) => {

View file

@ -131,10 +131,11 @@ module.exports = (args, cbk) => {
const latencyMs = completed
.map(n => n.latency_ms)
.filter(n => !!n)
.reduce((sum, n) => sum + n, Number());
const max = completed
.map(n => n.route_maximum)
.map(n => n.route_maximum || Number())
.reduce((sum, n) => sum + n, Number());
return cbk(null, {

View file

@ -11,10 +11,10 @@ const {getWalletInfo} = require('ln-service');
const {payViaRoutes} = require('ln-service');
const {returnResult} = require('asyncjs-util');
const {signBytes} = require('ln-service');
const {subscribeToFindMaxPayable} = require('probing');
const {authenticatedLnd} = require('./../lnd');
const executeProbe = require('./execute_probe');
const {findMaxRoutable} = require('./../routing');
const {getInboundPath} = require('./../routing');
const {sortBy} = require('./../arrays');
@ -338,18 +338,26 @@ module.exports = (args, cbk) => {
// Get maximum value of the successful route
getMax: ['probe', 'to', ({probe, to}, cbk) => {
if (!args.find_max || !probe.route) {
return cbk();
return cbk(null, {});
}
return findMaxRoutable({
const sub = subscribeToFindMaxPayable({
cltv: to.cltv_delta || defaultCltvDelta,
hops: probe.route.hops,
lnd: args.lnd,
logger: args.logger,
max: args.find_max,
request: args.request,
},
cbk);
});
sub.on('evaluating', ({tokens}) => {
return args.logger.info({evaluating_amount: tokens});
});
sub.once('error', err => cbk(err));
sub.once('failure', () => cbk(null, {maximum: Number()}));
sub.once('success', ({maximum}) => cbk(null, {maximum}));
return;
}],
// If there is a successful route, pay it
@ -387,7 +395,7 @@ module.exports = (args, cbk) => {
return cbk(null, {
fee: !route ? undefined : route.fee,
latency_ms: !route ? undefined : probe.latency_ms,
route_maximum: !getMax ? undefined : getMax.maximum,
route_maximum: getMax.maximum,
paid: !pay ? undefined : pay.tokens,
preimage: !pay ? undefined : pay.secret,
probed: !!pay ? undefined : route.tokens - route.fee,

369
package-lock.json generated
View file

@ -1,15 +1,15 @@
{
"name": "balanceofsatoshis",
"version": "5.41.1",
"version": "5.41.2",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"@alexbosworth/html2unicode": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/@alexbosworth/html2unicode/-/html2unicode-1.1.4.tgz",
"integrity": "sha512-pwZNCDbjyTSsxwyeGqYa9v4eMf9ZvPKuMQFFPpXHt5wNRAbxbY9F7lBVw1ep4Mj9sEs+uiM6vGdLbmgyfmh3pA==",
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/@alexbosworth/html2unicode/-/html2unicode-1.1.5.tgz",
"integrity": "sha512-CXMFAyovJHtLzKlraBpGlM/8TX9bvVz081IDZkQF3IMGHePgHCAs1vQdnKM38VMGekywNCbo7kt3fHooSMgA2w==",
"requires": {
"saxophone": "0.6.1"
"@alexbosworth/saxophone": "0.6.2"
}
},
"@alexbosworth/request": {
@ -46,6 +46,15 @@
}
}
},
"@alexbosworth/saxophone": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/@alexbosworth/saxophone/-/saxophone-0.6.2.tgz",
"integrity": "sha512-o/xdK8b4P0t/xpCARgWXAeaiWeh9jeua6bP1jrcbfN39+Z4zC4x2jg4NysHNhz6spRG8dJFH3kJIUoIbs0Ckww==",
"requires": {
"readable-stream": "3.6.0",
"string_decoder": "^1.3.0"
}
},
"@alexbosworth/tap": {
"version": "14.10.9",
"resolved": "https://registry.npmjs.org/@alexbosworth/tap/-/tap-14.10.9.tgz",
@ -1637,9 +1646,9 @@
}
},
"@grpc/proto-loader": {
"version": "0.5.4",
"resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.5.4.tgz",
"integrity": "sha512-HTM4QpI9B2XFkPz7pjwMyMgZchJ93TVkL3kWPW8GDMDKYxsMnmf4w2TNMJK7+KNiYHS5cJrCEAFlF+AwtXWVPA==",
"version": "0.5.5",
"resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.5.5.tgz",
"integrity": "sha512-WwN9jVNdHRQoOBo9FDH7qU+mgfjPc8GygPYms3M+y3fbQLfnCe/Kv/E01t7JRgnrsOHH8euvSbed3mIalXhwqQ==",
"requires": {
"lodash.camelcase": "^4.3.0",
"protobufjs": "^6.8.6"
@ -1967,9 +1976,9 @@
}
},
"asyncjs-util": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/asyncjs-util/-/asyncjs-util-1.2.2.tgz",
"integrity": "sha512-ms8WTLX2hZbEl24rpS1SFvvGbUNPkQZRN5sbpx2ZRHoYA0oB/hLFvpm04Kvfr1HNOWqa38jHfRG6MUgWBb4INA==",
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/asyncjs-util/-/asyncjs-util-1.2.3.tgz",
"integrity": "sha512-gwrRUMa6oZ1qssVupX4lgSey1PDCEbouUjCqa2/MRgaZ4gZmZfAVBZ/Nzple7r9BN+iVMJPIWrwVu00CRgjHgw==",
"requires": {
"async": "3.2.0"
}
@ -2164,9 +2173,9 @@
}
},
"bolt03": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/bolt03/-/bolt03-1.2.5.tgz",
"integrity": "sha512-sP9USXa+bPn3vc+Tb55/iLG3J26g+C3dfUPtCGR2KbwHvLvVR+Ujtr9YdzfN5WE7miJq9BlpQUaCIh4UlYCh9g==",
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/bolt03/-/bolt03-1.2.6.tgz",
"integrity": "sha512-0C4V+EHHysAm6tCmqbo63kK4chJUxvma020JLD0xbiDhHwE4U16m/7MjlunY/tHPbDeWSlr26k/QRnFXEvFwNg==",
"requires": {
"bitcoin-ops": "1.4.1",
"bitcoinjs-lib": "5.1.10"
@ -2188,9 +2197,9 @@
}
},
"bolt09": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/bolt09/-/bolt09-0.1.0.tgz",
"integrity": "sha512-n1jBGRip56E3SXQ+4KdzV/EcJ3Ls4R8Qyd0KTgNzCaSV+2SyNVsr0w0lKYzTBzwoctEBKHsytGjZ3qNxnt02nw=="
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/bolt09/-/bolt09-0.1.1.tgz",
"integrity": "sha512-BX1LjpvU7qLyv8LRpYsq7p6fM2SiECWtfwjzx2/cStT0YFJhS74qFw5CfivoRz6ZEg3W7g1Exrv0tmDRkKeBkA=="
},
"boxen": {
"version": "4.2.0",
@ -3471,21 +3480,21 @@
"dev": true
},
"goldengate": {
"version": "5.8.0",
"resolved": "https://registry.npmjs.org/goldengate/-/goldengate-5.8.0.tgz",
"integrity": "sha512-G1jmKieDzwvhPI80FYK9Xg6UbZrb+SW3wPaew70rI8dTh1/c2rumt04hUy0aGQqzjYkRuAvDzZ4oX4NHre277g==",
"version": "5.8.1",
"resolved": "https://registry.npmjs.org/goldengate/-/goldengate-5.8.1.tgz",
"integrity": "sha512-iguifP35jtOCkpz7LGFnSuOuK04v0B1vFngU3bD5MW50GWjmybNxAKA2mC1G/PBnponFo0/+uHe5sYn8ZihEjw==",
"requires": {
"@grpc/proto-loader": "0.5.4",
"@grpc/proto-loader": "0.5.5",
"@mitmaro/http-authorization-header": "1.0.0",
"async": "3.2.0",
"asyncjs-util": "1.2.2",
"asyncjs-util": "1.2.3",
"bip65": "1.0.3",
"bitcoin-ops": "1.4.1",
"bitcoinjs-lib": "5.1.10",
"bn.js": "5.1.2",
"cbor": "5.0.2",
"grpc": "1.24.3",
"ln-service": "49.1.2",
"ln-service": "49.3.4",
"macaroon": "3.0.4",
"pushdata-bitcoin": "1.0.1",
"varuint-bitcoin": "1.1.2"
@ -3496,34 +3505,36 @@
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.2.tgz",
"integrity": "sha512-40rZaf3bUNKTVYu9sIeeEGOg7g14Yvnj9kH7b50EiwX0Q7A6umbvfI5tvHaOERH0XigqKkfLkFQxzb4e6CIXnA=="
},
"bolt07": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/bolt07/-/bolt07-1.5.1.tgz",
"integrity": "sha512-pNFpkyu5zW0NUKErTjRNcHsmTjEghvx02t/lscnke9xbJgxE2ZnLMDZFBhgl5xBPCeGGouIuEWd3MXsBLSd6Cg==",
"requires": {
"bn.js": "5.1.2"
}
},
"ln-service": {
"version": "49.1.2",
"resolved": "https://registry.npmjs.org/ln-service/-/ln-service-49.1.2.tgz",
"integrity": "sha512-2XvP4aEzAfHXed3aCZ5ZPL1UVLVSAi+m48cwDepSAsUFQ6dMzKqC4VFf0/jyHBxaDLt8YTNqKhDbjCO5TUYyLw==",
"version": "49.3.4",
"resolved": "https://registry.npmjs.org/ln-service/-/ln-service-49.3.4.tgz",
"integrity": "sha512-UTVxXqgin7zrluEHi/JyDqFbpGlDY5uHy0b5y4/wtjwP0dIAgB2w6si9lMpTsncHsHmN0Rdtzn+sH1jS7a078Q==",
"requires": {
"@datastructures-js/priority-queue": "4.1.1",
"async": "3.2.0",
"asyncjs-util": "1.2.2",
"bitcoinjs-lib": "5.1.10",
"bn.js": "5.1.2",
"bolt07": "1.5.1",
"bolt09": "0.1.0",
"bolt07": "1.5.2",
"bolt09": "0.1.1",
"cors": "2.8.5",
"express": "4.17.1",
"invoices": "1.1.0",
"invoices": "1.1.1",
"is-base64": "1.1.0",
"lightning": "2.0.19",
"lightning": "2.0.25",
"macaroon": "3.0.4",
"morgan": "1.10.0",
"ws": "7.3.0"
"ws": "7.3.1"
},
"dependencies": {
"asyncjs-util": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/asyncjs-util/-/asyncjs-util-1.2.2.tgz",
"integrity": "sha512-ms8WTLX2hZbEl24rpS1SFvvGbUNPkQZRN5sbpx2ZRHoYA0oB/hLFvpm04Kvfr1HNOWqa38jHfRG6MUgWBb4INA==",
"requires": {
"async": "3.2.0"
}
}
}
}
}
@ -3935,15 +3946,15 @@
"integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY="
},
"invoices": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/invoices/-/invoices-1.1.0.tgz",
"integrity": "sha512-Ma9FlCTTbeyWs4LFtH5kn7CSyux55KEyZuB+vs5Yx8QaQKfJ25pANVsw9vxmiHQqZxf3wY68y+RGfxHkXTPMyQ==",
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/invoices/-/invoices-1.1.1.tgz",
"integrity": "sha512-vcqo6soFOi+BXbirhuw1KRsL9GKmIbG150dk8Pb5SH/GfECxxEJwnY6DX4qcHylTy3GJSfAsiBT2jFgpls33Aw==",
"requires": {
"bech32": "1.1.4",
"bitcoinjs-lib": "5.1.10",
"bn.js": "5.1.2",
"bolt07": "1.5.1",
"bolt09": "0.1.0",
"bolt07": "1.5.2",
"bolt09": "0.1.1",
"secp256k1": "4.0.1"
},
"dependencies": {
@ -3951,14 +3962,6 @@
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.2.tgz",
"integrity": "sha512-40rZaf3bUNKTVYu9sIeeEGOg7g14Yvnj9kH7b50EiwX0Q7A6umbvfI5tvHaOERH0XigqKkfLkFQxzb4e6CIXnA=="
},
"bolt07": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/bolt07/-/bolt07-1.5.1.tgz",
"integrity": "sha512-pNFpkyu5zW0NUKErTjRNcHsmTjEghvx02t/lscnke9xbJgxE2ZnLMDZFBhgl5xBPCeGGouIuEWd3MXsBLSd6Cg==",
"requires": {
"bn.js": "5.1.2"
}
}
}
},
@ -4438,36 +4441,36 @@
"dev": true
},
"lightning": {
"version": "2.0.19",
"resolved": "https://registry.npmjs.org/lightning/-/lightning-2.0.19.tgz",
"integrity": "sha512-b3GH6KhjbTJTjk9KJ3+9UWz9TSLYfKlZ/3/L+XlrcwydvRjcLsPmefcTL6/R4o9BU0yVWF0NUMuZXJtnRWap5g==",
"version": "2.0.25",
"resolved": "https://registry.npmjs.org/lightning/-/lightning-2.0.25.tgz",
"integrity": "sha512-dy+Ox8BevHYPZb4lyDgz7gKLvrCdrg1hxUkwtesA+naTVkHsGhe2UqaTM7l+DgJ30jVxgXCfs80dU8j9rTu70A==",
"requires": {
"@grpc/proto-loader": "0.5.4",
"@grpc/proto-loader": "0.5.5",
"async": "3.2.0",
"asyncjs-util": "1.2.2",
"bitcoinjs-lib": "5.1.10",
"bn.js": "5.1.2",
"body-parser": "1.19.0",
"bolt07": "1.5.1",
"bolt09": "0.1.0",
"bolt07": "1.5.2",
"bolt09": "0.1.1",
"cbor": "5.0.2",
"express": "4.17.1",
"grpc": "1.24.3",
"invoices": "1.1.0"
"invoices": "1.1.1"
},
"dependencies": {
"asyncjs-util": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/asyncjs-util/-/asyncjs-util-1.2.2.tgz",
"integrity": "sha512-ms8WTLX2hZbEl24rpS1SFvvGbUNPkQZRN5sbpx2ZRHoYA0oB/hLFvpm04Kvfr1HNOWqa38jHfRG6MUgWBb4INA==",
"requires": {
"async": "3.2.0"
}
},
"bn.js": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.2.tgz",
"integrity": "sha512-40rZaf3bUNKTVYu9sIeeEGOg7g14Yvnj9kH7b50EiwX0Q7A6umbvfI5tvHaOERH0XigqKkfLkFQxzb4e6CIXnA=="
},
"bolt07": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/bolt07/-/bolt07-1.5.1.tgz",
"integrity": "sha512-pNFpkyu5zW0NUKErTjRNcHsmTjEghvx02t/lscnke9xbJgxE2ZnLMDZFBhgl5xBPCeGGouIuEWd3MXsBLSd6Cg==",
"requires": {
"bn.js": "5.1.2"
}
}
}
},
@ -4484,14 +4487,22 @@
},
"dependencies": {
"@grpc/proto-loader": {
"version": "0.5.5",
"resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.5.5.tgz",
"integrity": "sha512-WwN9jVNdHRQoOBo9FDH7qU+mgfjPc8GygPYms3M+y3fbQLfnCe/Kv/E01t7JRgnrsOHH8euvSbed3mIalXhwqQ==",
"version": "0.5.4",
"resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.5.4.tgz",
"integrity": "sha512-HTM4QpI9B2XFkPz7pjwMyMgZchJ93TVkL3kWPW8GDMDKYxsMnmf4w2TNMJK7+KNiYHS5cJrCEAFlF+AwtXWVPA==",
"requires": {
"lodash.camelcase": "^4.3.0",
"protobufjs": "^6.8.6"
}
},
"asyncjs-util": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/asyncjs-util/-/asyncjs-util-1.2.2.tgz",
"integrity": "sha512-ms8WTLX2hZbEl24rpS1SFvvGbUNPkQZRN5sbpx2ZRHoYA0oB/hLFvpm04Kvfr1HNOWqa38jHfRG6MUgWBb4INA==",
"requires": {
"async": "3.2.0"
}
},
"bn.js": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.2.tgz",
@ -4505,12 +4516,75 @@
"bn.js": "5.1.2"
}
},
"lightning": {
"version": "2.0.24",
"resolved": "https://registry.npmjs.org/lightning/-/lightning-2.0.24.tgz",
"integrity": "sha512-oeYsjtR/gnsrE04EX8Cy2AAPJCQRGVr7rlt40aV788JA0rFzxfxmTed59wsd0QiYdBk4Cz6q9Zh/RC8ppEIF5A==",
"bolt09": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/bolt09/-/bolt09-0.1.0.tgz",
"integrity": "sha512-n1jBGRip56E3SXQ+4KdzV/EcJ3Ls4R8Qyd0KTgNzCaSV+2SyNVsr0w0lKYzTBzwoctEBKHsytGjZ3qNxnt02nw=="
},
"goldengate": {
"version": "5.8.0",
"resolved": "https://registry.npmjs.org/goldengate/-/goldengate-5.8.0.tgz",
"integrity": "sha512-G1jmKieDzwvhPI80FYK9Xg6UbZrb+SW3wPaew70rI8dTh1/c2rumt04hUy0aGQqzjYkRuAvDzZ4oX4NHre277g==",
"requires": {
"@grpc/proto-loader": "0.5.5",
"@grpc/proto-loader": "0.5.4",
"@mitmaro/http-authorization-header": "1.0.0",
"async": "3.2.0",
"asyncjs-util": "1.2.2",
"bip65": "1.0.3",
"bitcoin-ops": "1.4.1",
"bitcoinjs-lib": "5.1.10",
"bn.js": "5.1.2",
"cbor": "5.0.2",
"grpc": "1.24.3",
"ln-service": "49.1.2",
"macaroon": "3.0.4",
"pushdata-bitcoin": "1.0.1",
"varuint-bitcoin": "1.1.2"
},
"dependencies": {
"ln-service": {
"version": "49.1.2",
"resolved": "https://registry.npmjs.org/ln-service/-/ln-service-49.1.2.tgz",
"integrity": "sha512-2XvP4aEzAfHXed3aCZ5ZPL1UVLVSAi+m48cwDepSAsUFQ6dMzKqC4VFf0/jyHBxaDLt8YTNqKhDbjCO5TUYyLw==",
"requires": {
"@datastructures-js/priority-queue": "4.1.1",
"async": "3.2.0",
"asyncjs-util": "1.2.2",
"bitcoinjs-lib": "5.1.10",
"bn.js": "5.1.2",
"bolt07": "1.5.1",
"bolt09": "0.1.0",
"cors": "2.8.5",
"express": "4.17.1",
"invoices": "1.1.0",
"is-base64": "1.1.0",
"lightning": "2.0.19",
"macaroon": "3.0.4",
"morgan": "1.10.0",
"ws": "7.3.0"
}
}
}
},
"invoices": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/invoices/-/invoices-1.1.0.tgz",
"integrity": "sha512-Ma9FlCTTbeyWs4LFtH5kn7CSyux55KEyZuB+vs5Yx8QaQKfJ25pANVsw9vxmiHQqZxf3wY68y+RGfxHkXTPMyQ==",
"requires": {
"bech32": "1.1.4",
"bitcoinjs-lib": "5.1.10",
"bn.js": "5.1.2",
"bolt07": "1.5.1",
"bolt09": "0.1.0",
"secp256k1": "4.0.1"
}
},
"lightning": {
"version": "2.0.19",
"resolved": "https://registry.npmjs.org/lightning/-/lightning-2.0.19.tgz",
"integrity": "sha512-b3GH6KhjbTJTjk9KJ3+9UWz9TSLYfKlZ/3/L+XlrcwydvRjcLsPmefcTL6/R4o9BU0yVWF0NUMuZXJtnRWap5g==",
"requires": {
"@grpc/proto-loader": "0.5.4",
"async": "3.2.0",
"asyncjs-util": "1.2.2",
"bitcoinjs-lib": "5.1.10",
@ -4544,23 +4618,58 @@
"macaroon": "3.0.4",
"morgan": "1.10.0",
"ws": "7.3.1"
},
"dependencies": {
"@grpc/proto-loader": {
"version": "0.5.5",
"resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.5.5.tgz",
"integrity": "sha512-WwN9jVNdHRQoOBo9FDH7qU+mgfjPc8GygPYms3M+y3fbQLfnCe/Kv/E01t7JRgnrsOHH8euvSbed3mIalXhwqQ==",
"requires": {
"lodash.camelcase": "^4.3.0",
"protobufjs": "^6.8.6"
}
},
"lightning": {
"version": "2.0.24",
"resolved": "https://registry.npmjs.org/lightning/-/lightning-2.0.24.tgz",
"integrity": "sha512-oeYsjtR/gnsrE04EX8Cy2AAPJCQRGVr7rlt40aV788JA0rFzxfxmTed59wsd0QiYdBk4Cz6q9Zh/RC8ppEIF5A==",
"requires": {
"@grpc/proto-loader": "0.5.5",
"async": "3.2.0",
"asyncjs-util": "1.2.2",
"bitcoinjs-lib": "5.1.10",
"bn.js": "5.1.2",
"body-parser": "1.19.0",
"bolt07": "1.5.1",
"bolt09": "0.1.0",
"cbor": "5.0.2",
"express": "4.17.1",
"grpc": "1.24.3",
"invoices": "1.1.0"
}
},
"ws": {
"version": "7.3.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.3.1.tgz",
"integrity": "sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA=="
}
}
},
"ws": {
"version": "7.3.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.3.1.tgz",
"integrity": "sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA=="
"version": "7.3.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.3.0.tgz",
"integrity": "sha512-iFtXzngZVXPGgpTlP1rBqsUK82p9tKqsWRPg5L56egiljujJT3vGAYnHANvFxBieXrTFavhzhxW52jnaWV+w2w=="
}
}
},
"ln-service": {
"version": "49.3.4",
"resolved": "https://registry.npmjs.org/ln-service/-/ln-service-49.3.4.tgz",
"integrity": "sha512-UTVxXqgin7zrluEHi/JyDqFbpGlDY5uHy0b5y4/wtjwP0dIAgB2w6si9lMpTsncHsHmN0Rdtzn+sH1jS7a078Q==",
"version": "49.3.7",
"resolved": "https://registry.npmjs.org/ln-service/-/ln-service-49.3.7.tgz",
"integrity": "sha512-UPWF9oJowvU6GQLkXQTM7c7Og3N1BipK+Brd4vImqXONHZTE9514UKawqpi+JU8FwNlzB75A3PgqFFbiTZriUQ==",
"requires": {
"@datastructures-js/priority-queue": "4.1.1",
"async": "3.2.0",
"asyncjs-util": "1.2.2",
"asyncjs-util": "1.2.3",
"bitcoinjs-lib": "5.1.10",
"bn.js": "5.1.2",
"bolt07": "1.5.2",
@ -4569,52 +4678,25 @@
"express": "4.17.1",
"invoices": "1.1.1",
"is-base64": "1.1.0",
"lightning": "2.0.25",
"lightning": "2.0.28",
"macaroon": "3.0.4",
"morgan": "1.10.0",
"ws": "7.3.1"
},
"dependencies": {
"@grpc/proto-loader": {
"version": "0.5.5",
"resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.5.5.tgz",
"integrity": "sha512-WwN9jVNdHRQoOBo9FDH7qU+mgfjPc8GygPYms3M+y3fbQLfnCe/Kv/E01t7JRgnrsOHH8euvSbed3mIalXhwqQ==",
"requires": {
"lodash.camelcase": "^4.3.0",
"protobufjs": "^6.8.6"
}
},
"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=="
},
"invoices": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/invoices/-/invoices-1.1.1.tgz",
"integrity": "sha512-vcqo6soFOi+BXbirhuw1KRsL9GKmIbG150dk8Pb5SH/GfECxxEJwnY6DX4qcHylTy3GJSfAsiBT2jFgpls33Aw==",
"requires": {
"bech32": "1.1.4",
"bitcoinjs-lib": "5.1.10",
"bn.js": "5.1.2",
"bolt07": "1.5.2",
"bolt09": "0.1.1",
"secp256k1": "4.0.1"
}
},
"lightning": {
"version": "2.0.25",
"resolved": "https://registry.npmjs.org/lightning/-/lightning-2.0.25.tgz",
"integrity": "sha512-dy+Ox8BevHYPZb4lyDgz7gKLvrCdrg1hxUkwtesA+naTVkHsGhe2UqaTM7l+DgJ30jVxgXCfs80dU8j9rTu70A==",
"version": "2.0.28",
"resolved": "https://registry.npmjs.org/lightning/-/lightning-2.0.28.tgz",
"integrity": "sha512-nx3HPpJncS/c8BnvCwX8jEbePFzrj+gVk47VZtuYYWKTrZPn2PHqTOBnCVbHM9rkjeJjJuT3074n4pmSWpTAcw==",
"requires": {
"@grpc/proto-loader": "0.5.5",
"async": "3.2.0",
"asyncjs-util": "1.2.2",
"asyncjs-util": "1.2.3",
"bitcoinjs-lib": "5.1.10",
"bn.js": "5.1.2",
"body-parser": "1.19.0",
@ -4625,24 +4707,19 @@
"grpc": "1.24.3",
"invoices": "1.1.1"
}
},
"ws": {
"version": "7.3.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.3.1.tgz",
"integrity": "sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA=="
}
}
},
"ln-sync": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/ln-sync/-/ln-sync-0.0.8.tgz",
"integrity": "sha512-ZTKgrQRRoexvVZvo0DdaAOHvnJvGC5X3x+CrDaTfcURhbBsmafkt3mQ12OOfkoieeQggBI6tfWyJLhey/JUi0w==",
"version": "0.0.9",
"resolved": "https://registry.npmjs.org/ln-sync/-/ln-sync-0.0.9.tgz",
"integrity": "sha512-ZJw1ZwoZqXFRV1EMScPjgBUipzZfxhh1KROBh6KcSiVM0tOTRLXL9YNrFPLPYe2KzROq18Ak1hinDaz3fJRhTA==",
"requires": {
"async": "3.2.0",
"asyncjs-util": "1.2.2",
"asyncjs-util": "1.2.3",
"cbor": "5.0.2",
"colorette": "1.2.1",
"ln-service": "49.3.4",
"ln-service": "49.3.7",
"node-lmdb": "0.9.2"
}
},
@ -5731,6 +5808,17 @@
"minimist": "^1.2.0"
}
},
"probing": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/probing/-/probing-1.0.1.tgz",
"integrity": "sha512-llIRWvdX7I3PLDXDrUjYCSwYFuMKqHX3qFYA58qba8CRJt9FRfucPcpI84MdVS9NzpehRibKAvDm89+xzhfBLg==",
"requires": {
"async": "3.2.0",
"asyncjs-util": "1.2.3",
"invoices": "1.1.1",
"ln-service": "49.3.7"
}
},
"process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
@ -5784,9 +5872,9 @@
}
},
"psbt": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/psbt/-/psbt-1.1.3.tgz",
"integrity": "sha512-S5aNs32patUooy1IvDLmozu8N1hzAZ+Fkhjt7fNMumbqguU3UMe1E0xEEhM/uZG4DLbmzQbzxTCrakGSbimbXQ==",
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/psbt/-/psbt-1.1.4.tgz",
"integrity": "sha512-Oz8gEs68wCvnxod60svvnAYYIxcm5Jn2NIqAPVr9QR3R4ub7EhLryychlA9AhDJiyONzOkPEEhNVtDmsJHl39A==",
"requires": {
"bip66": "1.1.5",
"bitcoin-ops": "1.4.1",
@ -6146,15 +6234,6 @@
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
},
"saxophone": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/saxophone/-/saxophone-0.6.1.tgz",
"integrity": "sha512-sVFlC/UNSsqB+ZEiZJPoKn3NewiqifEtJP6WKXgV31HcZDmxVPsWHjeWSm5S+tMVAR6id6DTLz84a24/fz53JQ==",
"requires": {
"readable-stream": "^3.4.0",
"string_decoder": "^1.3.0"
}
},
"secp256k1": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.1.tgz",
@ -6263,9 +6342,9 @@
"integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA=="
},
"simple-concat": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.0.tgz",
"integrity": "sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY="
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
"integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q=="
},
"simple-get": {
"version": "3.1.0",
@ -6917,9 +6996,9 @@
"integrity": "sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g=="
},
"typescript": {
"version": "3.9.6",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.6.tgz",
"integrity": "sha512-Pspx3oKAPJtjNwE92YS05HQoY7z2SFyOpHo9MqJor3BXAGNaPUs83CuVp9VISFkSjyRfiTpmKuAYGJB7S7hOxw==",
"version": "3.9.7",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.7.tgz",
"integrity": "sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==",
"dev": true
},
"unicode-length": {
@ -7252,9 +7331,9 @@
}
},
"ws": {
"version": "7.3.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.3.0.tgz",
"integrity": "sha512-iFtXzngZVXPGgpTlP1rBqsUK82p9tKqsWRPg5L56egiljujJT3vGAYnHANvFxBieXrTFavhzhxW52jnaWV+w2w=="
"version": "7.3.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.3.1.tgz",
"integrity": "sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA=="
},
"xdg-basedir": {
"version": "4.0.0",

View file

@ -10,14 +10,14 @@
"url": "https://github.com/alexbosworth/balanceofsatoshis/issues"
},
"dependencies": {
"@alexbosworth/html2unicode": "1.1.4",
"@alexbosworth/html2unicode": "1.1.5",
"@alexbosworth/request": "2.88.3",
"asciichart": "1.5.21",
"async": "3.2.0",
"asyncjs-util": "1.2.2",
"asyncjs-util": "1.2.3",
"bitcoin-ops": "1.4.1",
"bitcoinjs-lib": "5.1.10",
"bolt03": "1.2.5",
"bolt03": "1.2.6",
"bolt07": "1.5.2",
"caporal": "1.4.0",
"cbor": "5.0.2",
@ -25,17 +25,17 @@
"colorette": "1.2.1",
"crypto-js": "4.0.0",
"csv-parse": "4.11.1",
"goldengate": "5.8.0",
"goldengate": "5.8.1",
"ini": "1.3.5",
"inquirer": "7.3.2",
"ln-accounting": "4.1.7",
"ln-service": "49.3.4",
"ln-sync": "0.0.8",
"ln-service": "49.3.7",
"ln-sync": "0.0.9",
"moment": "2.27.0",
"psbt": "1.1.3",
"probing": "1.0.1",
"psbt": "1.1.4",
"qrcode-terminal": "0.12.0",
"sanitize-filename": "1.6.3",
"saxophone": "0.6.1",
"stats-lite": "2.2.0",
"table": "5.4.6",
"telegraf": "3.38.0",
@ -67,5 +67,5 @@
"scripts": {
"test": "tap test/arrays/*.js test/balances/*.js test/chain/*.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/telegram/*.js test/wallets/*.js"
},
"version": "5.41.1"
"version": "5.41.2"
}

View file

@ -1,146 +0,0 @@
const asyncAuto = require('async/auto');
const asyncMapSeries = require('async/mapSeries');
const {decodePaymentRequest} = require('ln-service');
const {getChannel} = require('ln-service');
const {getMaximum} = require('asyncjs-util');
const {parsePaymentRequest} = require('ln-service');
const {returnResult} = require('asyncjs-util');
const channelsFromHints = require('./channels_from_hints');
const isRoutePayable = require('./is_route_payable');
const accuracy = 10000;
const {isArray} = Array;
const from = 0;
const nextAttemptDelayMs = 1000 * 1;
const slowPaymentMs = 1000 * 60 * 4.5;
const to = tokens => tokens - Math.round(Math.random() * 1000);
/** Find max routable
{
cltv: <Final CLTV Delta Number>
hops: [{
channel: <Standard Format Channel Id String>
public_key: <Forward to Public Key With Hex String>
}]
lnd: <Authenticated LND gRPC API Object>
logger: <Winston Logger Object>
max: <Max Attempt Tokens Number>
[request]: <BOLT 11 Payment Request String>
}
@returns via cbk or Promise
{
maximum: <Maximum Routeable Tokens Number>
}
*/
module.exports = ({cltv, hops, lnd, logger, max, request}, cbk) => {
return new Promise((resolve, reject) => {
return asyncAuto({
// Check arguments
validate: cbk => {
if (!cltv) {
return cbk([400, 'ExpectedFinalCltvToFindMaxRoutable']);
}
if (!isArray(hops)) {
return cbk([400, 'ExpectedArrayOfHopsToFindMaxRoutable']);
}
if (!!hops.find(({channel}) => !channel)) {
return cbk([400, 'ExpectedChannelsInHopsToFindMaxRoutable']);
}
if (!!hops.find(n => !n.public_key)) {
return cbk([400, 'ExpectedPublicKeyInHopsToFindMaxRoutable']);
}
if (!lnd) {
return cbk([400, 'ExpectedLndToFindMaxRoutableAmount']);
}
if (!logger) {
return cbk([400, 'ExpectedLoggerToFindMaxRoutable']);
}
if (!max) {
return cbk([400, 'ExpectedMaxLimitTokensToFindMaxRoutable']);
}
return cbk();
},
// Get channels
channels: ['validate', ({}, cbk) => {
const {channels} = channelsFromHints({request});
return asyncMapSeries(hops, (hop, cbk) => {
return getChannel({lnd, id: hop.channel}, (err, channel) => {
// Avoid returning an error when channel is known from hops
if (!!err && !!channels.find(n => n.id === hop.channel)) {
return cbk(null, channels.find(n => n.id === hop.channel));
}
if (!!err) {
return cbk(err);
}
return cbk(null, {
capacity: channel.capacity,
destination: hop.public_key,
id: hop.channel,
policies: channel.policies,
});
});
},
cbk);
}],
// Find maximum
findMax: ['channels', ({channels}, cbk) => {
let isPayable = false;
return getMaximum({accuracy, from, to: to(max)}, ({cursor}, cbk) => {
const tokens = cursor;
logger.info({evaluating_amount: cursor});
const slowWarning = setTimeout(() => {
logger.info({slow_path_timeout_in: '30 seconds'});
},
slowPaymentMs);
return isRoutePayable({channels, cltv, lnd, tokens}, (err, res) => {
clearTimeout(slowWarning);
if (!!err) {
return cbk(err);
}
if (!!res.is_payable) {
isPayable = tokens;
}
return setTimeout(() => {
return cbk(null, res.is_payable);
},
nextAttemptDelayMs);
});
},
(err, res) => {
if (!!err) {
return cbk(err);
}
if (!isPayable) {
return cbk([503, 'FailedToFindRoute']);
}
return cbk(null, res);
});
}],
},
returnResult({reject, resolve, of: 'findMax'}, cbk));
});
};

View file

@ -2,7 +2,6 @@ const adjustFees = require('./adjust_fees');
const channelForGift = require('./channel_for_gift');
const channelsFromHints = require('./channels_from_hints');
const describeConfidence = require('./describe_confidence');
const findMaxRoutable = require('./find_max_routable');
const getFeesChart = require('./get_fees_chart');
const getFeesPaid = require('./get_fees_paid');
const getInboundPath = require('./get_inbound_path');
@ -15,7 +14,6 @@ module.exports = {
channelForGift,
channelsFromHints,
describeConfidence,
findMaxRoutable,
getFeesChart,
getFeesPaid,
getInboundPath,

View file

@ -1,123 +0,0 @@
const asyncAuto = require('async/auto');
const asyncTimeout = require('async/timeout');
const {getRouteThroughHops} = require('ln-service');
const {getWalletInfo} = require('ln-service');
const {payViaRoutes} = require('ln-service');
const {returnResult} = require('asyncjs-util');
const {routeFromChannels} = require('ln-service');
const invalidCltvExpiry = 'IncorrectCltvExpiry';
const invalidPaymentMessage = 'UnknownPaymentHash';
const {isArray} = Array;
const mtokensFromTokens = tokens => (BigInt(tokens) * BigInt(1e3)).toString();
const pathfindingTimeoutMs = 1000 * 60 * 5;
const payWithTimeout = asyncTimeout(payViaRoutes, 1000 * 60);
/** Find out if route is payable
{
channels: [{
capacity: <Maximum Tokens Number>
destination: <Next Node Public Key Hex String>
id: <Standard Format Channel Id String>
policies: [{
base_fee_mtokens: <Base Fee Millitokens String>
cltv_delta: <Locktime Delta Number>
fee_rate: <Fees Charged Per Million Tokens Number>
is_disabled: <Channel Is Disabled Bool>
min_htlc_mtokens: <Minimum HTLC Millitokens Value String>
public_key: <Node Public Key String>
}]
}]
cltv: <Final CLTV Delta Number>
lnd: <Authenticated LND gRPC API Object>
tokens: <Payable Tokens Number>
}
@returns via cbk or Promise
{
is_payable: <Route is Payable Bool>
}
*/
module.exports = ({channels, cltv, lnd, tokens}, cbk) => {
return new Promise((resolve, reject) => {
return asyncAuto({
// Check arguments
validate: cbk => {
if (!isArray(channels)) {
return cbk([400, 'ExpectedArrayOfChannelsToTestRoutePayable']);
}
if (!cltv) {
return cbk([400, 'ExpectedFinalCltvDeltaToTestRoutePayable']);
}
if (!lnd) {
return cbk([400, 'ExpectedLndToTestRoutePayable']);
}
if (!tokens) {
return cbk([400, 'ExpectedTokensToTestRoutePayable']);
}
return cbk();
},
// Get current height
getHeight: cbk => getWalletInfo({lnd}, cbk),
// Assemble route
route: ['getHeight', ({getHeight}, cbk) => {
const {route} = routeFromChannels({
channels,
cltv_delta: cltv,
height: getHeight.current_block_height,
mtokens: mtokensFromTokens(tokens),
});
return cbk(null, route);
}],
// Build a route
getRoute: ['validate', ({}, cbk) => {
return getRouteThroughHops({
lnd,
cltv_delta: cltv,
mtokens: mtokensFromTokens(tokens),
public_keys: channels.map(n => n.destination),
},
(err, res) => {
// Exit early when there is an error and use local route calculation
if (!!err) {
return cbk();
}
return cbk(null, res.route);
});
}],
// Attempt the route
attempt: ['getRoute', 'route', ({getRoute, route}, cbk) => {
return payWithTimeout({
lnd,
pathfinding_timeout: pathfindingTimeoutMs,
routes: [getRoute || route],
},
err => {
if (!!err && !isArray(err)) {
return cbk(null, {is_payable: false});
}
const [, code] = err;
if (code === invalidCltvExpiry) {
return cbk([503, 'UnexpectedErrorCode', {err}]);
}
return cbk(null, {is_payable: code === invalidPaymentMessage});
});
}],
},
returnResult({reject, resolve, of: 'attempt'}, cbk));
});
};

View file

@ -223,6 +223,7 @@ module.exports = (args, cbk) => {
const latencyMs = complete
.map(n => n.latency_ms)
.filter(n => !!n)
.reduce((sum, n) => sum + n, Number());
const max = complete

View file

@ -78,21 +78,13 @@ module.exports = ({db, logger, nodes}, cbk) => {
cbk);
}],
// Backfill records
syncRecords: ['getLnds', ({getLnds}, cbk) => {
return asyncEach(getLnds.lnds, (lnd, cbk) => {
return syncCurrentRecords({db, lnd}, cbk);
},
cbk);
}],
// Start watching for new records
syncChanges: ['getKeys', 'getLnds', ({getKeys, getLnds}, cbk) => {
const fromNodes = nodes.map((node, i) => {
return {node, lnd: getLnds.lnds[i]};
});
return asyncEach(fromNodes, async ({lnd, node}, cbk) => {
asyncEach(fromNodes, ({lnd, node}, cbk) => {
let sub;
try {
@ -251,7 +243,7 @@ module.exports = ({db, logger, nodes}, cbk) => {
}
});
sub.on('error', err => logger.error({err, node}));
sub.on('error', err => logger.error(err));
sub.on('failed_forward', async forward => {
try {

View file

@ -1,181 +0,0 @@
const {test} = require('@alexbosworth/tap');
const {findMaxRoutable} = require('./../../routing');
const {getInfoResponse} = require('./../fixtures');
const getInfoRes = () => JSON.parse(JSON.stringify(getInfoResponse));
const tests = [
{
args: {},
description: 'A final cltv is required',
error: [400, 'ExpectedFinalCltvToFindMaxRoutable'],
},
{
args: {cltv: 1},
description: 'Hops are required',
error: [400, 'ExpectedArrayOfHopsToFindMaxRoutable'],
},
{
args: {cltv: 1, hops: [{}]},
description: 'Hops require channels',
error: [400, 'ExpectedChannelsInHopsToFindMaxRoutable'],
},
{
args: {cltv: 1, hops: [{channel: '0x0x0'}]},
description: 'Hops require public keys',
error: [400, 'ExpectedPublicKeyInHopsToFindMaxRoutable'],
},
{
args: {cltv: 1, hops: [{channel: '0x0x0', public_key: 'a'}]},
description: 'Logger is required to find max routable',
error: [400, 'ExpectedLndToFindMaxRoutableAmount'],
},
{
args: {cltv: 1, hops: [{channel: '0x0x0', public_key: 'a'}], lnd: {}},
description: 'Logger is required to find max routable',
error: [400, 'ExpectedLoggerToFindMaxRoutable'],
},
{
args: {
cltv: 1,
hops: [{channel: '0x0x0', public_key: 'a'}],
lnd: {},
logger: {},
},
description: 'Max limit is required to find max routable',
error: [400, 'ExpectedMaxLimitTokensToFindMaxRoutable'],
},
{
args: {
cltv: 1,
hops: [{channel: '0x0x0', public_key: 'a'}],
lnd: {default: {getChanInfo: ({channel}, cbk) => cbk('err')}},
logger: {},
max: 1e6,
},
description: 'Get channel errors are passed back',
error: [503, 'UnexpectedGetChannelInfoError', {err: 'err'}],
},
{
args: {
cltv: 1,
hops: [{channel: '0x0x0', public_key: 'a'}],
lnd: {
default: {
getChanInfo: ({channel}, cbk) => cbk(null, {
capacity: '1',
chan_point: '1:1',
channel_id: 1,
node1_policy: {
disabled: false,
fee_base_msat: '1',
fee_rate_milli_msat: '1',
last_update: 1,
max_htlc_msat: '1',
min_htlc: '1',
time_lock_delta: 1,
},
node1_pub: 'a',
node2_policy: {
disabled: false,
fee_base_msat: '2',
fee_rate_milli_msat: '2',
last_update: 2,
max_htlc_msat: '2',
min_htlc: '2',
time_lock_delta: 2,
},
node2_pub: 'b',
}),
getInfo: ({}, cbk) => cbk(null, getInfoRes()),
},
router: {
buildRoute: ({}, cbk) => cbk('err'),
sendToRoute: ({}, cbk) => cbk(null, {
failure: {code: 'UNKNOWN_PAYMENT_HASH'},
}),
},
},
logger: {
info: n => {
if (!n.evaluating_amount) {
throw new Error('ExpectedEvaluationAmountLogged');
}
return;
},
},
max: 1e6,
},
description: 'Get maximum finds rough maximum',
expected: {maximum: 999000},
},
{
args: {
cltv: 1,
hops: [{channel: '0x0x0', public_key: 'a'}],
lnd: {
default: {
getChanInfo: ({channel}, cbk) => cbk(null, {
capacity: '1',
chan_point: '1:1',
channel_id: 1,
node1_policy: {
disabled: false,
fee_base_msat: '1',
fee_rate_milli_msat: '1',
last_update: 1,
max_htlc_msat: '1',
min_htlc: '1',
time_lock_delta: 1,
},
node1_pub: 'a',
node2_policy: {
disabled: false,
fee_base_msat: '2',
fee_rate_milli_msat: '2',
last_update: 2,
max_htlc_msat: '2',
min_htlc: '2',
time_lock_delta: 2,
},
node2_pub: 'b',
}),
getInfo: ({}, cbk) => cbk('err'),
},
router: {
sendToRoute: ({}, cbk) => cbk(null, {
failure: {code: 'UNKNOWN_PAYMENT_HASH'},
}),
},
},
logger: {
info: n => {
if (!n.evaluating_amount) {
throw new Error('ExpectedEvaluationAmountLogged');
}
return;
},
},
max: 1e6,
},
description: 'Get maximum finds rough maximum',
error: [503, 'GetWalletInfoErr', {err: 'err'}],
},
];
tests.forEach(({args, description, error, expected}) => {
return test(description, async ({end, equal, rejects}) => {
if (!!error) {
rejects(findMaxRoutable(args), error, 'Got expected error');
} else {
const {maximum} = await findMaxRoutable(args);
equal(maximum > expected.maximum - 10000, true, 'Got expected maximum');
}
return end();
});
});

View file

@ -1,116 +0,0 @@
const {test} = require('@alexbosworth/tap');
const {getInfoResponse} = require('./../fixtures');
const isRoutePayable = require('./../../routing/is_route_payable');
const getInfoRes = () => JSON.parse(JSON.stringify(getInfoResponse));
const tests = [
{
args: {},
description: 'An array of channels for the route is required',
error: [400, 'ExpectedArrayOfChannelsToTestRoutePayable'],
},
{
args: {channels: []},
description: 'A final cltv delta is required',
error: [400, 'ExpectedFinalCltvDeltaToTestRoutePayable'],
},
{
args: {channels: [], cltv: 1},
description: 'LND object is required',
error: [400, 'ExpectedLndToTestRoutePayable'],
},
{
args: {channels: [], cltv: 1, lnd: {}},
description: 'Tokens are required',
error: [400, 'ExpectedTokensToTestRoutePayable'],
},
{
args: {
channels: [{
capacity: 1,
destination: 'b',
id: '0x0x0',
policies: [
{
base_fee_mtokens: '1',
cltv_delta: 1,
fee_rate: 1,
is_disabled: false,
min_htlc_mtokens: '1',
public_key: 'a',
},
{
base_fee_mtokens: '2',
cltv_delta: 2,
fee_rate: 2,
is_disabled: false,
min_htlc_mtokens: '2',
public_key: 'b',
},
],
}],
cltv: 1,
lnd: {
default: {getInfo: ({}, cbk) => cbk(null, getInfoRes())},
router: {
buildRoute: ({}, cbk) => cbk('err'),
sendToRoute: ({}, cbk) => cbk(null, {
failure: {code: 'UNKNOWN_PAYMENT_HASH'},
},
)},
},
tokens: 1,
},
description: 'Unknown hash means payment is possible',
expected: {is_payable: true},
},
{
args: {
channels: [{
capacity: 1,
destination: 'b',
id: '0x0x0',
policies: [
{
base_fee_mtokens: '1',
cltv_delta: 1,
fee_rate: 1,
is_disabled: false,
min_htlc_mtokens: '1',
public_key: 'a',
},
{
base_fee_mtokens: '2',
cltv_delta: 2,
fee_rate: 2,
is_disabled: false,
min_htlc_mtokens: '2',
public_key: 'b',
},
],
}],
cltv: 1,
lnd: {default: {getInfo: ({}, cbk) => cbk(null, getInfoRes())}},
tokens: 1,
},
description: 'Invoice is not payable',
expected: {is_payable: false},
},
];
tests.forEach(({args, description, error, expected}) => {
return test(description, async ({end, equal, rejects}) => {
if (!!error) {
rejects(isRoutePayable(args), error, 'Got expected error');
} else {
const payable = await isRoutePayable(args);
equal(payable.is_payable, expected.is_payable, 'Got is_payable');
}
return end();
});
});