fix: use correct prompt for existing passhprases
[crowdnode.js/.git] / bin / crowdnode.js
index 2cf8cdfaf269a9dc74b4f50be7449d4ee633fa9d..f3b1d88a4f6fc7db31cfe9e9aab9ab19e687c0de 100755 (executable)
@@ -74,7 +74,7 @@ function showHelp() {
   console.info("");
 
   console.info("Key Management & Encryption:");
-  console.info("    crowdnode generate [./privkey.wif]");
+  console.info("    crowdnode generate [--plain-text] [./privkey.wif]");
   console.info("    crowdnode encrypt"); // TODO allow encrypting one-by-one?
   console.info("    crowdnode list");
   console.info("    crowdnode use <addr>");
@@ -119,6 +119,7 @@ async function main() {
 
   // flags
   let forceConfirm = removeItem(args, "--unconfirmed");
+  let plainText = removeItem(args, "--plain-text");
   let noReserve = removeItem(args, "--no-reserve");
 
   let subcommand = args.shift();
@@ -158,7 +159,7 @@ async function main() {
   }
 
   if ("generate" === subcommand) {
-    await generateKey({ defaultKey: defaultAddr }, args);
+    await generateKey({ defaultKey: defaultAddr, plainText }, args);
     return;
   }
 
@@ -330,12 +331,13 @@ async function initCrowdNode(insightBaseUrl) {
  * @param {Number} duffs - 1/100000000 of a DASH
  */
 function showQr(addr, duffs = 0) {
+  let dashAmount = toDash(duffs);
   let dashUri = `dash://${addr}`;
   if (duffs) {
-    dashUri += `?amount=${duffs}`;
+    dashUri += `?amount=${dashAmount}`;
   }
 
-  let dashQr = Qr.ascii(dashUri, { indent: 4 });
+  let dashQr = Qr.ascii(dashUri, { indent: 4, size: "mini" });
   let addrPad = Math.ceil((qrWidth - dashUri.length) / 2);
 
   console.info(dashQr);
@@ -559,9 +561,10 @@ async function mustGetDefaultWif(defaultAddr, opts) {
 /**
  * @param {Object} psuedoState
  * @param {String} psuedoState.defaultKey - addr name of default key
+ * @param {Boolean} psuedoState.plainText - don't encrypt
  * @param {Array<String>} args
  */
-async function generateKey({ defaultKey }, args) {
+async function generateKey({ defaultKey, plainText }, args) {
   let name = args.shift();
   //@ts-ignore - TODO submit JSDoc PR for Dashcore
   let pk = new Dashcore.PrivateKey();
@@ -569,7 +572,10 @@ async function generateKey({ defaultKey }, args) {
   let addr = pk.toAddress().toString();
   let plainWif = pk.toWIF();
 
-  let wif = await maybeEncrypt(plainWif);
+  let wif = plainWif;
+  if (!plainText) {
+    wif = await maybeEncrypt(plainWif);
+  }
 
   let filename = `~/${configdir}/keys/${addr}.wif`;
   let filepath = Path.join(`${keysDir}/${addr}.wif`);
@@ -608,7 +614,7 @@ async function setPassphrase({ _askPreviousPassphrase }, args) {
 
   // get the old passphrase
   if (false !== _askPreviousPassphrase) {
-    await cmds.getPassphrase(null, []);
+    await cmds.getPassphrase({ _rotatePassphrase: true }, []);
   }
 
   // get the new passphrase
@@ -696,6 +702,37 @@ async function importKey(_, args) {
   console.info(``);
 }
 
+/**
+ * Import and Encrypt
+ * @param {Null} _
+ * @param {Array<String>} args
+ */
+async function importKey(_, args) {
+  let keypath = args.shift() || "";
+  let key = await maybeReadKeyFileRaw(keypath);
+  if (!key?.wif) {
+    console.error(`no key found for '${keypath}'`);
+    process.exit(1);
+    return;
+  }
+
+  let encWif = await maybeEncrypt(key.wif);
+  let icon = "💾";
+  if (encWif.includes(":")) {
+    icon = "🔐";
+  }
+  let date = getFsDateString();
+
+  await safeSave(
+    Path.join(keysDir, `${key.addr}.wif`),
+    encWif,
+    Path.join(keysDir, `${key.addr}.${date}.bak`),
+  );
+
+  console.info(`${icon} Imported ${keysDirRel}/${key.addr}.wif`);
+  console.info(``);
+}
+
 /**
  * Encrypt ALL-the-things!
  * @param {Object} [opts]
@@ -791,10 +828,11 @@ async function safeSave(filepath, wif, bakpath) {
 }
 
 /**
- * @param {Null} psuedoState
+ * @param {Object} opts
+ * @param {Boolean} [opts._rotatePassphrase]
  * @param {Array<String>} args
  */
-cmds.getPassphrase = async function (psuedoState, args) {
+cmds.getPassphrase = async function ({ _rotatePassphrase }, args) {
   // Three possible states:
   //   1. no shadow file yet (ask to set one)
   //   2. empty shadow file (initialized, but not set - don't ask to set one)
@@ -845,7 +883,11 @@ cmds.getPassphrase = async function (psuedoState, args) {
 
   // State 3: passphrase & shadow already in use
   for (;;) {
-    let passphrase = await Prompt.prompt("Enter (current) passphrase: ", {
+    let prompt = `Enter passphrase: `;
+    if (_rotatePassphrase) {
+      prompt = `Enter (current) passphrase: `;
+    }
+    let passphrase = await Prompt.prompt(prompt, {
       mask: true,
     });
     passphrase = passphrase.trim();
@@ -985,7 +1027,7 @@ async function maybeReadKeyFileRaw(filepath, opts) {
 async function decrypt(encWif) {
   let passphrase = cmds._getPassphrase();
   if (!passphrase) {
-    passphrase = await cmds.getPassphrase(null, []);
+    passphrase = await cmds.getPassphrase({}, []);
   }
   let key128 = await Cipher.deriveKey(passphrase);
   let cipher = Cipher.create(key128);
@@ -999,7 +1041,7 @@ async function decrypt(encWif) {
 async function maybeEncrypt(plainWif) {
   let passphrase = cmds._getPassphrase();
   if (!passphrase) {
-    passphrase = await cmds.getPassphrase(null, []);
+    passphrase = await cmds.getPassphrase({}, []);
   }
   if (!passphrase) {
     return plainWif;