X-Git-Url: https://git.josue.xyz/?p=crowdnode.js%2F.git;a=blobdiff_plain;f=bin%2Fcrowdnode.js;h=adb6306402070cf5a6c2f3637e55cee0db490aae;hp=b3c096f461642b7ffbe42ef5fb4eb1ce3bbe044c;hb=5dbccedf943f0f768d80a9da1bffff061a5cef3e;hpb=9d9d10f8ad4c191369fb712b6b975936cc2c0713 diff --git a/bin/crowdnode.js b/bin/crowdnode.js index b3c096f..adb6306 100755 --- a/bin/crowdnode.js +++ b/bin/crowdnode.js @@ -49,6 +49,11 @@ let keysDirRel = `~/${configdir}/keys`; let shadowPath = Path.join(HOME, `${configdir}/shadow`); let defaultWifPath = Path.join(HOME, `${configdir}/default`); +function debug() { + //@ts-ignore + console.error.apply(console, arguments); +} + function showVersion() { console.info(`${pkg.name} v${pkg.version} - ${pkg.description}`); console.info(); @@ -113,6 +118,19 @@ function showHelp() { " crowdnode http SetReferral ./privkey.wif ", ); console.info(""); + console.info("Official CrowdNode Resources"); + console.info(""); + console.info("Homepage:"); + console.info(" https://crowdnode.io/"); + console.info(""); + console.info("Terms of Service:"); + console.info(" https://crowdnode.io/terms/"); + console.info(""); + console.info("BlockChain API Guide:"); + console.info( + " https://knowledge.crowdnode.io/en/articles/5963880-blockchain-api-guide", + ); + console.info(""); } let cmds = {}; @@ -182,7 +200,7 @@ async function main() { } if ("list" === subcommand) { - await listKeys({ dashApi }, args); + await listKeys({ dashApi, defaultAddr }, args); process.exit(0); return; } @@ -206,7 +224,8 @@ async function main() { } if ("import" === subcommand) { - await importKey(null, args); + let keypath = args.shift() || ""; + await importKey({ keypath }); process.exit(0); return; } @@ -319,13 +338,20 @@ async function main() { // keeping rm for backwards compat if ("rm" === subcommand || "delete" === subcommand) { await initCrowdNode(insightBaseUrl); - await removeKey({ defaultAddr, dashApi, insightBaseUrl }, args); + let [addr, filepath] = await mustGetAddr({ defaultAddr }, args); + await removeKey({ addr, dashApi, filepath, insightBaseUrl }, args); process.exit(0); return; } if ("balance" === subcommand) { - await getBalance({ dashApi, defaultAddr }, args); + if (args.length) { + await getBalance({ dashApi, defaultAddr }, args); + process.exit(0); + return; + } + + await getAllBalances({ dashApi, defaultAddr }, args); process.exit(0); return; } @@ -393,7 +419,8 @@ async function stakeDash( let err = await Fs.access(args[0]).catch(Object); let addr; if (!err) { - addr = await importKey(null, [args[0]]); + let keypath = args.shift() || ""; + addr = await importKey({ keypath }); } else if (forceGenerate) { addr = await generateKey({ defaultKey: defaultAddr }, []); } else { @@ -449,14 +476,14 @@ async function stakeDash( if (!state.status?.accept) { if (!state.status?.signup) { - await sendSignup({ dashApi, defaultAddr: addr, insightBaseUrl }, []); + await sendSignup({ dashApi, defaultAddr: addr, insightBaseUrl }, [addr]); } - await acceptTerms({ dashApi, defaultAddr: addr, insightBaseUrl }, []); + await acceptTerms({ dashApi, defaultAddr: addr, insightBaseUrl }, [addr]); } await depositDash( { dashApi, defaultAddr: addr, insightBaseUrl, noReserve }, - args, + [addr].concat(args), ); } @@ -722,7 +749,7 @@ async function mustGetDefaultWif(defaultAddr, opts) { } if (defaultWif && !shownDefault) { shownDefault = true; - console.info(`Selected default staking key ${defaultAddr}`); + debug(`Selected default staking key ${defaultAddr}`); return defaultWif; } @@ -882,11 +909,10 @@ async function promptPassphrase() { /** * Import and Encrypt - * @param {Null} _ - * @param {Array} args + * @param {Object} opts + * @param {String} opts.keypath */ -async function importKey(_, args) { - let keypath = args.shift() || ""; +async function importKey({ keypath }) { let key = await maybeReadKeyFileRaw(keypath); if (!key?.wif) { console.error(`no key found for '${keypath}'`); @@ -1295,20 +1321,89 @@ async function setDefault(_, args) { /** * @param {Object} opts * @param {any} opts.dashApi - TODO + * @param {String} opts.defaultAddr * @param {Array} args */ -async function listKeys({ dashApi }, args) { +async function listKeys({ dashApi, defaultAddr }, args) { let wifnames = await listManagedKeynames(); + if (wifnames) { + // to print 'default staking key' message + await mustGetAddr({ defaultAddr }, args); + } + /** * @type Array<{ node: String, error: Error }> */ let warns = []; - console.info(``); - console.info(`🔑Holdings 🪧 Stakings 💸Earnings`); - console.info(``); - console.info(`Staking keys: (in ${keysDirRel}/)`); - console.info(``); + // console.error because console.debug goes to stdout, not stderr + debug(``); + debug(`Staking keys: (in ${keysDirRel}/)`); + debug(``); + + await wifnames.reduce(async function (promise, wifname) { + await promise; + + let wifpath = Path.join(keysDir, wifname); + let addr = await maybeReadKeyFile(wifpath, { wif: false }).catch(function ( + err, + ) { + warns.push({ node: wifname, error: err }); + return ""; + }); + if (!addr) { + return; + } + + console.info(`${addr}`); + }, Promise.resolve()); + debug(``); + + if (warns.length) { + console.warn(`Warnings:`); + warns.forEach(function (warn) { + console.warn(`${warn.node}: ${warn.error.message}`); + }); + console.warn(``); + } +} + +/** + * @param {Object} opts + * @param {any} opts.dashApi - TODO + * @param {String} opts.defaultAddr + * @param {Array} args + */ +async function getAllBalances({ dashApi, defaultAddr }, args) { + let wifnames = await listManagedKeynames(); + let totals = { + key: 0, + stake: 0, + dividend: 0, + keyDash: "", + stakeDash: "", + dividendDash: "", + }; + + if (wifnames.length) { + // to print 'default staking key' message + await mustGetAddr({ defaultAddr }, args); + } + + /** + * @type Array<{ node: String, error: Error }> + */ + let warns = []; + // console.error because console.debug goes to stdout, not stderr + debug(``); + debug(`Staking keys: (in ${keysDirRel}/)`); + debug(``); + console.info( + `| | 🔑 Holdings | 🪧 Stakings | 💸 Earnings |`, + ); + console.info( + `| ---------------------------------: | ------------: | ------------: | ------------: |`, + ); if (!wifnames.length) { console.info(` (none)`); } @@ -1341,7 +1436,7 @@ async function listKeys({ dashApi }, args) { } */ - process.stdout.write(`${addr}: `); + process.stdout.write(`| ${addr} |`); let balanceInfo = await dashApi.getInstantBalance(addr); let balanceDASH = toDASH(balanceInfo.balanceSat); @@ -1357,12 +1452,26 @@ async function listKeys({ dashApi }, args) { let crowdNodeDivNum = toDuff(crowdNodeBalance.TotalDividend); let crowdNodeDivDASH = toDASH(crowdNodeDivNum); process.stdout.write( - `${balanceDASH}🔑 ${crowdNodeDASH}🪧 ${crowdNodeDivDASH}💸`, + ` ${balanceDASH} | ${crowdNodeDASH} | ${crowdNodeDivDASH} |`, ); + totals.key += balanceInfo.balanceSat; + totals.dividend += crowdNodeBalance.TotalDividend; + totals.stake += crowdNodeBalance.TotalBalance; + console.info(); }, Promise.resolve()); - console.info(``); + console.info( + `| | | | |`, + ); + let total = `| Totals`; + totals.keyDash = toDASH(toDuff(totals.key.toString())); + totals.stakeDash = toDASH(toDuff(totals.stake.toString())); + totals.dividendDash = toDASH(toDuff(totals.dividend.toString())); + console.info( + `${total} | ${totals.stakeDash} | ${totals.stakeDash} | ${totals.dividendDash} |`, + ); + debug(``); if (warns.length) { console.warn(`Warnings:`); @@ -1387,12 +1496,12 @@ function isNamedLikeKey(name) { /** * @param {Object} opts * @param {any} opts.dashApi - TODO - * @param {String} opts.defaultAddr + * @param {String} opts.addr + * @param {String} opts.filepath * @param {String} opts.insightBaseUrl * @param {Array} args */ -async function removeKey({ dashApi, defaultAddr, insightBaseUrl }, args) { - let [addr, name] = await mustGetAddr({ defaultAddr }, args); +async function removeKey({ addr, dashApi, filepath, insightBaseUrl }, args) { let balanceInfo = await dashApi.getInstantBalance(addr); let balanceDash = toDash(balanceInfo.balanceSat); @@ -1433,10 +1542,10 @@ async function removeKey({ dashApi, defaultAddr, insightBaseUrl }, args) { } let wifname = await findWif(addr); - let filepath = Path.join(keysDir, wifname); - let wif = await maybeReadKeyPaths(name, { wif: true }); + let fullpath = Path.join(keysDir, wifname); + let wif = await maybeReadKeyPaths(filepath, { wif: true }); - await Fs.unlink(filepath).catch(function (err) { + await Fs.unlink(fullpath).catch(function (err) { console.error(`could not remove ${filepath}: ${err.message}`); process.exit(1); }); @@ -1453,7 +1562,7 @@ async function removeKey({ dashApi, defaultAddr, insightBaseUrl }, args) { console.info(``); } else { let newAddr = wifnames[0]; - console.info(`Selected ${newAddr} as new default staking key.`); + debug(`Selected ${newAddr} as new default staking key.`); await Fs.writeFile(defaultWifPath, addr.replace(".wif", ""), "utf8"); console.info(``); } @@ -1976,7 +2085,7 @@ function toDash(duffs) { */ function toDASH(duffs) { let dash = (duffs / DUFFS).toFixed(8); - return `Đ${dash}`.padStart(13, " "); + return `Đ` + dash.padStart(12, " "); } /**