UNPKG

lightning

Version:
219 lines (180 loc) 7.25 kB
const asyncAuto = require('async/auto'); const {returnResult} = require('asyncjs-util'); const {isLnd} = require('./../../lnd_requests'); const {isArray} = Array; const method = 'policy'; const type = 'tower_client'; const unimplementedError = '12 UNIMPLEMENTED: unknown service wtclientrpc.WatchtowerClient'; /** Get a list of connected watchtowers and watchtower info Includes previously connected watchtowers Requires LND built with `wtclientrpc` build tag Requires `offchain:read` permission `is_anchor` flag is not supported on LND 0.11.1 and below `is_taproot` flag is not supported on LND 0.17.5 and below { [is_anchor]: <Get Anchor Type Tower Info Bool> [is_taproot]: <Get Taproot Type Tower Info Bool> lnd: <Authenticated LND API Object> } @returns via cbk or Promise { max_session_update_count: <Maximum Updates Per Session Number> sweep_tokens_per_vbyte: <Sweep Tokens per Virtual Byte Number> backups_count: <Total Backups Made Count Number> failed_backups_count: <Total Backup Failures Count Number> finished_sessions_count: <Finished Updated Sessions Count Number> pending_backups_count: <As Yet Unacknowledged Backup Requests Count Number> sessions_count: <Total Backup Sessions Starts Count Number> towers: [{ is_active: <Tower Can Be Used For New Sessions Bool> public_key: <Identity Public Key Hex String> sessions: [{ backups_count: <Total Successful Backups Made Count Number> max_backups_count: <Backups Limit Number> pending_backups_count: <Backups Pending Acknowledgement Count Number> sweep_tokens_per_vbyte: <Fee Rate in Tokens Per Virtual Byte Number> }] sockets: [<Tower Network Address IP:Port String>] }] } */ module.exports = (args, cbk) => { return new Promise((resolve, reject) => { return asyncAuto({ // Check arguments validate: cbk => { if (!isLnd({method, type, lnd: args.lnd})) { return cbk([400, 'ExpectedAuthenticatedLndToGetWatchtowerInfo']); } return cbk(); }, // Get stats getStats: ['validate', ({}, cbk) => { return args.lnd[type].stats({}, (err, res) => { if (!!err && err.message === unimplementedError) { return cbk([503, 'ExpectedWatchtowerClientLndToGetStats']); } if (!!err) { return cbk([503, 'UnexpectedErrorGettingWatchtowerStats', {err}]); } if (!res) { return cbk([503, 'ExpectedResultForWatchtowerStats']); } if (res.num_backups === undefined) { return cbk([503, 'ExpectedBackupsCountInWatchtowerStats']); } if (res.num_failed_backups === undefined) { return cbk([503, 'ExpectedFailedBackupsCountInWatchtowerStats']); } if (res.num_pending_backups === undefined) { return cbk([503, 'ExpectedPendingBackupsCountInWatchtowerStats']); } if (res.num_sessions_acquired === undefined) { return cbk([503, 'ExpectedSessionsCountInWatchtowerStats']); } if (res.num_sessions_exhausted === undefined) { return cbk([503, 'ExpectedExhaustedSessionsCountInTowerStats']); } return cbk(null, { backups_count: res.num_backups, failed_backups_count: res.num_failed_backups, finished_sessions_count: res.num_sessions_exhausted, pending_backups_count: res.num_pending_backups, sessions_count: res.num_sessions_acquired, }); }); }], // Get towers getTowers: ['validate', ({}, cbk) => { return args.lnd[type].listTowers({ include_sessions: true, }, (err, res) => { if (!!err && err.message === unimplementedError) { return cbk([503, 'ExpectedWatchtowerClientLndToGetTowers']); } if (!!err) { return cbk([503, 'UnexpectedErrorGettingWatchtowersList', {err}]); } if (!res) { return cbk([503, 'ExpectedResultForWatchtowerListing']); } if (!isArray(res.towers)) { return cbk([503, 'ExpectedArrayOfTowersForWatchtowerListing']); } if (!!res.towers.find(n => !Buffer.isBuffer(n.pubkey))) { return cbk([503, 'ExpectedPublicKeyForWatchtower']); } if (!!res.towers.find(n => !isArray(n.addresses))) { return cbk([503, 'ExpectedAddressesForWatchtower']); } const towers = res.towers.map(tower => ({ is_active: tower.active_session_candidate, public_key: tower.pubkey.toString('hex'), sessions: (tower.sessions || []).map(session => ({ backups_count: session.num_backups, max_backups_count: session.max_backups, pending_backups_count: session.num_pending_backups, sweep_tokens_per_vbyte: session.sweep_sat_per_vbyte, })), sockets: tower.addresses, })); return cbk(null, {towers}); }); }], // Determine the policy type policyType: ['validate', ({}, cbk) => { if (!!args.is_anchor) { return cbk(null, 'ANCHOR'); } if (!!args.is_taproot) { return cbk(null, 'TAPROOT'); } return cbk(null, 'LEGACY'); }], // Get policy getPolicy: ['policyType', ({policyType}, cbk) => { return args.lnd[type].policy({policy_type: policyType}, (err, res) => { if (!!err && err.message === unimplementedError) { return cbk([503, 'ExpectedWatchtowerClientLndToGetPolicy']); } if (!!err) { return cbk([503, 'UnexpectedErrorGettingWatchtowerPolicy', {err}]); } if (!res) { return cbk([503, 'ExpectedResultForWatchtowerPolicy']); } if (res.max_updates === undefined) { return cbk([503, 'ExpectedMaxUpdateCountInWatchtowerPolicyInfo']); } if (res.sweep_sat_per_vbyte === undefined) { return cbk([503, 'ExpectedSweepSatsPerByteInWatchtowerPolicy']); } return cbk(null, { max_session_update_count: res.max_updates, sweep_tokens_per_vbyte: res.sweep_sat_per_vbyte, }); }); }], // Connected watchtowers watchtowers: [ 'getPolicy', 'getStats', 'getTowers', ({getPolicy, getStats, getTowers}, cbk) => { return cbk(null, { backups_count: getStats.backups_count, failed_backups_count: getStats.failed_backups_count, finished_sessions_count: getStats.finished_sessions_count, max_session_update_count: getPolicy.max_session_update_count, pending_backups_count: getStats.pending_backups_count, sessions_count: getStats.sessions_count, sweep_tokens_per_vbyte: getPolicy.sweep_tokens_per_vbyte, towers: getTowers.towers, }); }], }, returnResult({reject, resolve, of: 'watchtowers'}, cbk)); }); };