add clean failed payments command

This commit is contained in:
Alex Bosworth 2021-10-12 09:34:19 -07:00
parent 577ff71c09
commit d13ad98f3e
No known key found for this signature in database
GPG key ID: E80D2F3F311FD87E
7 changed files with 250 additions and 51 deletions

View file

@ -1,5 +1,9 @@
# Versions
## Version 11.6.0
- `clean-failed-payments`: Add method to clean out failed past payments
## Version 11.5.1
- `--avoid`: Correct naming`OUT_FEE_RATE`/`IN_FEE_RATE` to `OPPOSITE_FEE_RATE`

20
bos
View file

@ -395,6 +395,26 @@ prog
});
})
// Clean out failed payments
.command('clean-failed-payments', 'Clean out past failed payment data')
.help('Remove old failed payment data for probes and other failed payments')
.option('--dryrun', 'Avoid actually deleting the failed payment record')
.option('--node <node_name>', 'Clean failed payments on a saved node')
.action((args, options, logger) => {
return new Promise(async (resolve, reject) => {
try {
return wallets.cleanFailedPayments({
logger,
is_dry_run: !!options.dryrun,
lnd: (await lnd.authenticatedLnd({logger, node: options.node})).lnd,
},
responses.returnObject({logger, reject, resolve}));
} catch (err) {
return reject(err);
}
});
})
// Determine the outcomes of channel closings
.command('closed', 'Get the status of a channel closings')
.help('Channel closes with chain-transaction derived resolution details')

View file

@ -287,6 +287,22 @@
{
"method": "getConnectedWatchtowers"
},
{
"arguments": [
{
"description": "Results limit",
"named": "limit",
"optional": true,
"type": "number"
},
{
"description": "Paging token",
"named": "token",
"optional": true
}
],
"method": "getFailedPayments"
},
{
"method": "getFeeRates"
},

96
package-lock.json generated
View file

@ -1,12 +1,12 @@
{
"name": "balanceofsatoshis",
"version": "11.5.1",
"version": "11.6.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "balanceofsatoshis",
"version": "11.5.1",
"version": "11.6.0",
"license": "MIT",
"dependencies": {
"@alexbosworth/html2unicode": "1.1.5",
@ -34,7 +34,7 @@
"inquirer": "8.2.0",
"invoices": "2.0.0",
"ln-accounting": "5.0.3",
"ln-service": "52.11.1",
"ln-service": "52.12.0",
"ln-sync": "2.0.2",
"ln-telegram": "3.3.1",
"moment": "2.29.1",
@ -4342,9 +4342,9 @@
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
},
"node_modules/electron-to-chromium": {
"version": "1.3.864",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.864.tgz",
"integrity": "sha512-v4rbad8GO6/yVI92WOeU9Wgxc4NA0n4f6P1FvZTY+jyY7JHEhw3bduYu60v3Q1h81Cg6eo4ApZrFPuycwd5hGw==",
"version": "1.3.866",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.866.tgz",
"integrity": "sha512-iYze6TpDXWxk+sfcpUUdTs6Pv/3kG45Pnjer2DxEeFw0N08bZeNLuz97s2lMgy8yObon48o0WHY2Bkg3xuAPOA==",
"dev": true
},
"node_modules/elliptic": {
@ -5537,9 +5537,9 @@
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
},
"node_modules/istanbul-lib-coverage": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz",
"integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==",
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.2.tgz",
"integrity": "sha512-o5+eTUYzCJ11/+JhW5/FUCdfsdoYVdQ/8I/OveE2XsjehYn5DdeSnNQAbjYaO8gQ6hvGTN6GM6ddQqpTVG5j8g==",
"dev": true,
"engines": {
"node": ">=8"
@ -5608,9 +5608,9 @@
}
},
"node_modules/istanbul-lib-source-maps": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz",
"integrity": "sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg==",
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz",
"integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==",
"dev": true,
"dependencies": {
"debug": "^4.1.1",
@ -5618,7 +5618,7 @@
"source-map": "^0.6.1"
},
"engines": {
"node": ">=8"
"node": ">=10"
}
},
"node_modules/istanbul-lib-source-maps/node_modules/debug": {
@ -5654,9 +5654,9 @@
}
},
"node_modules/istanbul-reports": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.3.tgz",
"integrity": "sha512-0i77ZFLsb9U3DHi22WzmIngVzfoyxxbQcZRqlF3KoKmCJGq9nhFHoGi8FqBztN2rE8w6hURnZghetn0xpkVb6A==",
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.4.tgz",
"integrity": "sha512-bFjUnc95rHjdCR63WMHUS7yfJJh8T9IPSWavvR02hhjVwezWALZ5axF9EqjmwZHpXqkzbgAMP8DmAtiyNxrdrQ==",
"dev": true,
"dependencies": {
"html-escaper": "^2.0.0",
@ -5820,9 +5820,9 @@
}
},
"node_modules/lightning": {
"version": "4.10.4",
"resolved": "https://registry.npmjs.org/lightning/-/lightning-4.10.4.tgz",
"integrity": "sha512-t8tfck7JDCLP9/dnM0ogEciixPERh4B1Lwe927EFoqrrWpmNnsyk3raJQDNh+GkO0naHSyrzN6jo4Wi0VUaTow==",
"version": "4.10.5",
"resolved": "https://registry.npmjs.org/lightning/-/lightning-4.10.5.tgz",
"integrity": "sha512-fpf1TJPCroey0xJsYkBGlWpUV7jUC2Pm/4oVRpqA5GM/ayXvnkxsJFyQFWAY4+zdwUAndeGGQDZACA5uRmS3HQ==",
"dependencies": {
"@grpc/grpc-js": "1.3.7",
"@grpc/proto-loader": "0.6.5",
@ -6221,15 +6221,15 @@
}
},
"node_modules/ln-service": {
"version": "52.11.1",
"resolved": "https://registry.npmjs.org/ln-service/-/ln-service-52.11.1.tgz",
"integrity": "sha512-PTAW+KNMytFQvjyiH/0oOypio3D01Zc3FRh19ubsrkCX1sxy8jzX5m8La6HyejYswZg6tcSefb3DYPPQRfhL7w==",
"version": "52.12.0",
"resolved": "https://registry.npmjs.org/ln-service/-/ln-service-52.12.0.tgz",
"integrity": "sha512-M7dXD+UH85Yr/hiXxbMQC1bodpoSnne9hZ+wXWSfnOQaUKEbn3hAl4NevZLyUZvLlS8MZORCITiL6y/MDalhLA==",
"dependencies": {
"bolt07": "1.7.3",
"cors": "2.8.5",
"express": "4.17.1",
"invoices": "2.0.0",
"lightning": "4.10.4",
"lightning": "4.10.5",
"macaroon": "3.0.4",
"morgan": "1.10.0",
"ws": "8.2.3"
@ -7121,9 +7121,9 @@
"dev": true
},
"node_modules/nofilter": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/nofilter/-/nofilter-3.0.3.tgz",
"integrity": "sha512-TN/MCrQmXQk5DyUJ8TGUq1Il8rv4fTsjddLmMopV006QP8DMkglmGgYfQKD5620vXLRXfr8iGI6ZZ4/ZWld2cQ==",
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/nofilter/-/nofilter-3.1.0.tgz",
"integrity": "sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g==",
"engines": {
"node": ">=12.19"
}
@ -13164,9 +13164,9 @@
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
},
"electron-to-chromium": {
"version": "1.3.864",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.864.tgz",
"integrity": "sha512-v4rbad8GO6/yVI92WOeU9Wgxc4NA0n4f6P1FvZTY+jyY7JHEhw3bduYu60v3Q1h81Cg6eo4ApZrFPuycwd5hGw==",
"version": "1.3.866",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.866.tgz",
"integrity": "sha512-iYze6TpDXWxk+sfcpUUdTs6Pv/3kG45Pnjer2DxEeFw0N08bZeNLuz97s2lMgy8yObon48o0WHY2Bkg3xuAPOA==",
"dev": true
},
"elliptic": {
@ -14071,9 +14071,9 @@
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
},
"istanbul-lib-coverage": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz",
"integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==",
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.2.tgz",
"integrity": "sha512-o5+eTUYzCJ11/+JhW5/FUCdfsdoYVdQ/8I/OveE2XsjehYn5DdeSnNQAbjYaO8gQ6hvGTN6GM6ddQqpTVG5j8g==",
"dev": true
},
"istanbul-lib-hook": {
@ -14126,9 +14126,9 @@
}
},
"istanbul-lib-source-maps": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz",
"integrity": "sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg==",
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz",
"integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==",
"dev": true,
"requires": {
"debug": "^4.1.1",
@ -14160,9 +14160,9 @@
}
},
"istanbul-reports": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.3.tgz",
"integrity": "sha512-0i77ZFLsb9U3DHi22WzmIngVzfoyxxbQcZRqlF3KoKmCJGq9nhFHoGi8FqBztN2rE8w6hURnZghetn0xpkVb6A==",
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.4.tgz",
"integrity": "sha512-bFjUnc95rHjdCR63WMHUS7yfJJh8T9IPSWavvR02hhjVwezWALZ5axF9EqjmwZHpXqkzbgAMP8DmAtiyNxrdrQ==",
"dev": true,
"requires": {
"html-escaper": "^2.0.0",
@ -14283,9 +14283,9 @@
}
},
"lightning": {
"version": "4.10.4",
"resolved": "https://registry.npmjs.org/lightning/-/lightning-4.10.4.tgz",
"integrity": "sha512-t8tfck7JDCLP9/dnM0ogEciixPERh4B1Lwe927EFoqrrWpmNnsyk3raJQDNh+GkO0naHSyrzN6jo4Wi0VUaTow==",
"version": "4.10.5",
"resolved": "https://registry.npmjs.org/lightning/-/lightning-4.10.5.tgz",
"integrity": "sha512-fpf1TJPCroey0xJsYkBGlWpUV7jUC2Pm/4oVRpqA5GM/ayXvnkxsJFyQFWAY4+zdwUAndeGGQDZACA5uRmS3HQ==",
"requires": {
"@grpc/grpc-js": "1.3.7",
"@grpc/proto-loader": "0.6.5",
@ -14584,15 +14584,15 @@
}
},
"ln-service": {
"version": "52.11.1",
"resolved": "https://registry.npmjs.org/ln-service/-/ln-service-52.11.1.tgz",
"integrity": "sha512-PTAW+KNMytFQvjyiH/0oOypio3D01Zc3FRh19ubsrkCX1sxy8jzX5m8La6HyejYswZg6tcSefb3DYPPQRfhL7w==",
"version": "52.12.0",
"resolved": "https://registry.npmjs.org/ln-service/-/ln-service-52.12.0.tgz",
"integrity": "sha512-M7dXD+UH85Yr/hiXxbMQC1bodpoSnne9hZ+wXWSfnOQaUKEbn3hAl4NevZLyUZvLlS8MZORCITiL6y/MDalhLA==",
"requires": {
"bolt07": "1.7.3",
"cors": "2.8.5",
"express": "4.17.1",
"invoices": "2.0.0",
"lightning": "4.10.4",
"lightning": "4.10.5",
"macaroon": "3.0.4",
"morgan": "1.10.0",
"ws": "8.2.3"
@ -15283,9 +15283,9 @@
"dev": true
},
"nofilter": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/nofilter/-/nofilter-3.0.3.tgz",
"integrity": "sha512-TN/MCrQmXQk5DyUJ8TGUq1Il8rv4fTsjddLmMopV006QP8DMkglmGgYfQKD5620vXLRXfr8iGI6ZZ4/ZWld2cQ=="
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/nofilter/-/nofilter-3.1.0.tgz",
"integrity": "sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g=="
},
"normalize-path": {
"version": "3.0.0",

View file

@ -35,7 +35,7 @@
"inquirer": "8.2.0",
"invoices": "2.0.0",
"ln-accounting": "5.0.3",
"ln-service": "52.11.1",
"ln-service": "52.12.0",
"ln-sync": "2.0.2",
"ln-telegram": "3.3.1",
"moment": "2.29.1",
@ -80,5 +80,5 @@
"postpublish": "docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 -t alexbosworth/balanceofsatoshis --push .",
"test": "tap --branches=1 --functions=1 --lines=1 --statements=1 -t 60 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/peers/*.js test/responses/*.js test/routing/*.js test/services/*.js test/swaps/*.js test/tags/*.js test/wallets/*.js"
},
"version": "11.5.1"
"version": "11.6.0"
}

View file

@ -0,0 +1,153 @@
const asyncAuto = require('async/auto');
const asyncEachSeries = require('async/eachSeries');
const asyncWhilst = require('async/whilst');
const {deletePayment} = require('ln-service');
const {getFailedPayments} = require('ln-service');
const {getWalletVersion} = require('ln-service');
const {returnResult} = require('asyncjs-util');
const defaultPagingLimit = 500;
const {isArray} = Array;
const unsupported = 501;
/** Clean out failed payments from the wallet
{
is_dry_run: <Avoid Actually Deleting Payments>
lnd: <Authenticated LND API Object>
logger: <Winston Logger Object>
}
@returns via cbk or Promise
*/
module.exports = (args, cbk) => {
return new Promise((resolve, reject) => {
return asyncAuto({
// Check arguments
validate: cbk => {
if (!args.lnd) {
return cbk([400, 'ExpectedAuthenticatedLndApiToCleanPayments']);
}
if (!args.logger) {
return cbk([400, 'ExpectedWinstonLoggerToCleanFailedPayments']);
}
return cbk();
},
// Try and determine what wallet version this is
getWalletVersion: ['validate', ({}, cbk) => {
return getWalletVersion({lnd: args.lnd}, cbk);
}],
// Deny known unsupported versions
checkWalletVersion: ['getWalletVersion', ({getWalletVersion}, cbk) => {
// Exit early when not actually deleting
if (!!args.is_dry_run) {
return cbk();
}
switch (getWalletVersion.version) {
case '0.11.0-beta':
case '0.11.1-beta':
case '0.12.0-beta':
case '0.12.1-beta':
case '0.13.0-beta':
case '0.13.1-beta':
case '0.13.2-beta':
case '0.13.3-beta':
return cbk([501, 'CleanFailedPaymentsUnsupportedOnThisLndVersion']);
default:
return cbk();
}
}],
// Delete failed payments
fetchAndDelete: ['checkWalletVersion', ({}, cbk) => {
const ids = [];
let token;
if (!!args.is_dry_run) {
args.logger.info({finding_failed_payments: true});
} else {
args.logger.info({deleting_failed_payments: true});
}
return asyncWhilst(
cbk => cbk(null, token !== false),
cbk => {
return getFailedPayments({
token,
limit: !token ? defaultPagingLimit : undefined,
lnd: args.lnd,
},
(err, res) => {
if (!!err) {
return cbk([503, 'UnexpectedErrorGettingPayFailures', {err}]);
}
// Setting token to false will signal the end of paging
token = res.next || false;
// Exit early when there
if (!res.payments.length) {
const date = new Date().toISOString();
args.logger.info({searching_for_failed_payments: date});
return cbk();
}
res.payments.forEach(({id}) => ids.push(id));
// Delete each payment
return asyncEachSeries(res.payments, ({id}, cbk) => {
// Exit early when doing a dry run
if (!!args.is_dry_run) {
return cbk();
}
return deletePayment({id, lnd: args.lnd}, err => {
// LND 0.13.3 and below do not support deleting payments
if (!!isArray(err) && err.slice().shift() === unsupported) {
return cbk([501, 'LndVersionDoesNotSupportFailDeletion']);
}
if (!!err) {
return cbk([503, 'UnexpectedErrorDeletingPayment', {err}]);
}
return cbk();
});
},
err => {
if (!!err) {
return cbk(err);
}
args.logger.info({failed_payments: ids.length});
return cbk();
});
});
},
err => {
if (!!err) {
return cbk(err);
}
// Exit early when this is a test
if (!!args.is_dry_run) {
return cbk(null, {total_failed_payments_found: ids.length});
}
return cbk(null, {total_failed_payments_deleted: ids.length});
}
);
}],
},
returnResult({reject, resolve, of: 'fetchAndDelete'}, cbk));
});
};

View file

@ -1,5 +1,11 @@
const cleanFailedPayments = require('./clean_failed_payments');
const getReceivedChart = require('./get_received_chart');
const getReport = require('./get_report');
const unlockWallet = require('./unlock_wallet');
module.exports = {getReceivedChart, getReport, unlockWallet};
module.exports = {
cleanFailedPayments,
getReceivedChart,
getReport,
unlockWallet,
};