feat(cli): add load subcommand
[crowdnode.js/.git] / bin / crowdnode.js
index 81720cff6911fff7129732dbe957d333fd4b4ad2..ddeafe28c646533806d1631da25c5d594d246001 100755 (executable)
@@ -68,6 +68,7 @@ function showHelp() {
 
   console.info("Helpful Extras:");
   console.info("    crowdnode generate [./privkey.wif]");
+  console.info("    crowdnode load [./privkey.wif]");
   console.info("    crowdnode balance ./privkey.wif");
   console.info(
     "    crowdnode transfer ./source.wif <key-file-or-pub-addr> [dash-amount]",
@@ -136,6 +137,18 @@ async function main() {
   let insightApi = Insight.create({ baseUrl: insightBaseUrl });
   let dashApi = Dash.create({ insightApi: insightApi });
 
+  if ("load" === subcommand) {
+    await load(
+      {
+        dashApi: dashApi,
+        insightBaseUrl: insightBaseUrl,
+        insightApi: insightApi,
+      },
+      args,
+    );
+    return;
+  }
+
   process.stdout.write("Checking CrowdNode API... ");
   await CrowdNode.init({
     baseUrl: "https://app.crowdnode.io",
@@ -192,7 +205,8 @@ async function main() {
   // deposit if balance is over 100,000 (0.00100000)
   process.stdout.write("Checking balance... ");
   let balanceInfo = await dashApi.getInstantBalance(pub);
-  console.info(`${balanceInfo.balanceSat} (Đ${balanceInfo.balance})`);
+  let balanceDash = toDash(balanceInfo.balanceSat);
+  console.info(`${balanceInfo.balanceSat} (Đ${balanceDash})`);
   /*
   let balanceInfo = await insightApi.getBalance(pub);
   if (balanceInfo.unconfirmedBalanceSat || balanceInfo.unconfirmedAppearances) {
@@ -300,30 +314,83 @@ async function generate(name) {
     note = `\n(for pubkey address ${pub})`;
   }
 
+  let testDash = 0.01;
+  let testDuff = toDuff(testDash);
+
   let err = await Fs.access(filepath).catch(Object);
   if (!err) {
     // TODO show QR anyway
     //wif = await Fs.readFile(filepath, 'utf8')
-    //showQr(pub, 0.01);
+    //showQr(pub, testDuff);
     console.info(`'${filepath}' already exists (will not overwrite)`);
     process.exit(0);
     return;
   }
 
-  await Fs.writeFile(filepath, wif, "utf8").then(function () {
-    console.info(``);
-    console.info(
-      `Use the QR Code below to load a test deposit of Đ0.01 onto your staking key.`,
-    );
-    console.info(``);
-    showQr(pub, 0.01);
-    console.info(``);
-    console.info(
-      `Use the QR Code above to load a test deposit of Đ0.01 onto your staking key.`,
-    );
-    console.info(``);
+  await Fs.writeFile(filepath, wif, "utf8");
+  console.info(``);
+  console.info(
+    `Use the QR Code below to load a test deposit of Đ${testDash} onto your staking key.`,
+  );
+  console.info(``);
+  showQr(pub, testDuff);
+  console.info(``);
+  console.info(
+    `Use the QR Code above to load a test deposit of Đ${testDash} onto your staking key.`,
+  );
+  console.info(``);
+  console.info(`Generated ${filepath} ${note}`);
+  process.exit(0);
+}
+
+async function load(psuedoState, args) {
+  let name = args.shift();
+
+  // TODO factor out the common bits from generate?
+  let pk = new Dashcore.PrivateKey();
+
+  let pub = pk.toAddress().toString();
+  let wif = pk.toWIF();
+
+  let filepath = `./${pub}.wif`;
+  let note = "";
+  if (name) {
+    filepath = name;
+    note = `\n(for pubkey address ${pub})`;
+  }
+
+  let err = await Fs.access(filepath).catch(Object);
+  if (!err) {
+    console.info(`'${filepath}' already exists (will not overwrite)`);
+  } else {
+    await Fs.writeFile(filepath, wif, "utf8");
     console.info(`Generated ${filepath} ${note}`);
-  });
+  }
+
+  let desiredAmountDash = parseFloat(args.shift() || 0);
+  let desiredAmountDuff = Math.round(desiredAmountDash * DUFFS);
+  let effectiveDuff = desiredAmountDuff;
+  let effectiveDash = "";
+  if (!effectiveDuff) {
+    effectiveDuff = CrowdNode.stakeMinimum + signupTotal + feeEstimate;
+    effectiveDash = toDash(effectiveDuff);
+    // Round to the nearest mDash
+    // ex: 0.50238108 => 0.50300000
+    effectiveDuff = toDuff(Math.ceil(effectiveDash * 1000) / 1000);
+    effectiveDash = toDash(effectiveDuff);
+  }
+
+  console.info(``);
+  showQr(pub, effectiveDuff);
+  console.info(``);
+  console.info(
+    `Use the QR Code above to load ${effectiveDuff} (Đ${effectiveDash}) onto your staking key.`,
+  );
+  console.info(``);
+  console.info(`(waiting...)`);
+  console.info(``);
+  let payment = await Ws.waitForVout(psuedoState.insightBaseUrl, pub, 0);
+  console.info(`Received ${payment.satoshis}`);
   process.exit(0);
 }
 
@@ -345,8 +412,9 @@ async function transfer(args, state) {
     tx = await state.dashApi.createBalanceTransfer(state.privKey, newAddr);
   }
   if (duffAmount) {
+    let dashAmountStr = toDash(duffAmount);
     console.info(
-      `Transferring ${duffAmount} (Đ${dashAmount}) to ${newAddr}...`,
+      `Transferring ${duffAmount} (Đ${dashAmountStr}) to ${newAddr}...`,
     );
   } else {
     console.info(`Transferring balance to ${newAddr}...`);
@@ -375,6 +443,14 @@ async function status(args, state) {
   console.info(`    ${state.accept} AcceptTerms`);
   console.info(`    ${state.deposit} DepositReceived`);
   console.info();
+  let pk = new Dashcore.PrivateKey(state.privKey);
+  let pub = pk.toPublicKey().toAddress().toString();
+  let crowdNodeBalance = await CrowdNode.http.GetBalance(pub);
+  let crowdNodeDash = toDash(crowdNodeBalance.TotalBalance);
+  console.info(
+    `CrowdNode Stake: ${crowdNodeBalance.TotalBalance} (Đ${crowdNodeDash})`,
+  );
+  console.info();
   process.exit(0);
   return;
 }
@@ -479,9 +555,6 @@ async function deposit(args, state) {
     effectiveAmount = state.balanceInfo.balanceSat - reserve;
   }
 
-  console.info(
-    `(holding ${reserve} (Đ${reserveDash}) in reserve for API calls)`,
-  );
   let effectiveDash = toDash(effectiveAmount);
   console.info(
     `Initiating deposit of ${effectiveAmount} (Đ${effectiveDash})...`,
@@ -559,9 +632,10 @@ async function wifFileToAddr(keyfile) {
 }
 
 async function collectSignupFees(insightBaseUrl, pub) {
+  console.info(``);
   showQr(pub);
 
-  let signupTotalDash = (signupTotal / DUFFS).toFixed(8);
+  let signupTotalDash = toDash(signupTotal);
   let signupMsg = `Please send >= ${signupTotal} (Đ${signupTotalDash}) to Sign Up to CrowdNode`;
   let msgPad = Math.ceil((qrWidth - signupMsg.length) / 2);
   let subMsg = "(plus whatever you'd like to deposit)";
@@ -580,6 +654,7 @@ async function collectSignupFees(insightBaseUrl, pub) {
 }
 
 async function collectDeposit(insightBaseUrl, pub, duffAmount) {
+  console.info(``);
   showQr(pub, duffAmount);
 
   let depositMsg = `Please send what you wish to deposit to ${pub}`;
@@ -606,6 +681,10 @@ function toDash(duffs) {
   return (duffs / DUFFS).toFixed(8);
 }
 
+function toDuff(dash) {
+  return Math.round(parseFloat(dash) * DUFFS);
+}
+
 // Run
 
 main().catch(function (err) {