UNPKG

lightning

Version:
126 lines (99 loc) 3.7 kB
const asyncAuto = require('async/auto'); const {returnResult} = require('asyncjs-util'); const {getAutopilot} = require('./../info'); const {isLnd} = require('./../../lnd_requests'); const externalType = 'externalscore'; const {floor} = Math; const {isArray} = Array; const maxScore = 100000000; const method = 'status'; const type = 'autopilot'; const unknownScore = '2 UNKNOWN: heuristic with name externalscore not found'; const wrongLnd = '12 UNIMPLEMENTED: unknown service autopilotrpc.Autopilot'; /** Configure Autopilot settings Either candidate_nodes or is_enabled is required Candidate node scores range from 1 to 100,000,000 Permissions `info:read`, `offchain:write`, `onchain:write` are required { [candidate_nodes]: [{ public_key: <Node Public Key Hex String> score: <Score Number> }] [is_enabled]: <Enable Autopilot Bool> lnd: <Authenticated LND Object> } @returns via cbk or Promise */ module.exports = (args, cbk) => { return new Promise((resolve, reject) => { return asyncAuto({ // Check arguments validate: cbk => { if (!isArray(args.candidate_nodes) && args.is_enabled === undefined) { return cbk([400, 'ExpectedNodesOrEnabledSettingToAdjustAutopilot']); } if (!isLnd({method, type, lnd: args.lnd})) { return cbk([400, 'ExpectedAutopilotEnabledLndToSetAutopilot']); } const nodes = args.candidate_nodes || []; if (!!nodes.find(n => !n.public_key)) { return cbk([400, 'ExpectedAllCandidateNodesToHavePublicKeys']); } if (!!nodes.find(({score}) => !floor(score))) { return cbk([400, 'ExpectedAllCandidateNodesToHaveScore']); } if (!!nodes.find(({score}) => score > maxScore)) { return cbk([400, 'ExpectedCandidateNodesToHaveValidScores']); } return cbk(); }, // Get existing status getStatus: ['validate', ({}, cbk) => getAutopilot({lnd: args.lnd}, cbk)], // Adjust candidate nodes setNodes: ['validate', ({}, cbk) => { // Exit early when there are no adjustments to candidate nodes if (!args.candidate_nodes || !args.candidate_nodes.length) { return cbk(); } const heuristic = externalType; const scores = {}; const nodes = args.candidate_nodes.map(node => ({ public_key: node.public_key, score: node.score / maxScore, })); nodes.forEach(n => scores[n.public_key] = n.score); return args.lnd.autopilot.setScores({ heuristic, scores, }, (err, res) => { if (!!err && err.message === unknownScore) { return cbk([400, 'ExternalScoreHeuristicNotEnabled']); } if (!!err) { return cbk([503, 'FailedToSetAutopilotCandidateScores', {err}]); } return cbk(); }); }], // Modify the autopilot status setStatus: ['getStatus', 'setNodes', ({getStatus}, cbk) => { const enable = args.is_enabled; // Exit early when autopilot status does not need to be set if (enable === undefined || getStatus.is_enabled === enable) { return cbk(); } return args.lnd.autopilot.modifyStatus({enable}, err => { if (!!err && err.message === wrongLnd) { return cbk([400, 'ExpectedAuthenticatedLndToSetAutopilotStatus']); } if (!!err) { return cbk([503, 'UnexpectedErrorSettingAutopilotStatus', {err}]); } return cbk(); }); }], }, returnResult({reject, resolve}, cbk)); }); };