X-Git-Url: https://git.josue.xyz/?a=blobdiff_plain;f=bin%2Fcrowdnode.js;h=60a251f451d7b43f6f92fff2446e9f4ac995acd2;hb=3561bf72d0e69d7a84e8b2d5915344b5c21cb9b4;hp=e0165a57816568255b02aa6dc318de4cc29e85f8;hpb=ce14ba4beb779a4a026bbe0e1c869583ca5e572a;p=crowdnode.js%2F.git diff --git a/bin/crowdnode.js b/bin/crowdnode.js index e0165a5..60a251f 100755 --- a/bin/crowdnode.js +++ b/bin/crowdnode.js @@ -25,18 +25,16 @@ let qrWidth = 2 + 67 + 2; // 0.00238608 // minimum recommended amount // Target: // 0.01000000 -let signupFees = - CrowdNode.requests.signupForApi + - CrowdNode.requests.acceptTerms + - 2 * CrowdNode.requests.offset; -let feeEstimate = 2 * 1000; +let signupOnly = CrowdNode.requests.signupForApi + CrowdNode.requests.offset; +let acceptOnly = CrowdNode.requests.acceptTerms + CrowdNode.requests.offset; +let signupFees = signupOnly + acceptOnly; +let feeEstimate = 500; +let signupTotal = signupFees + 2 * feeEstimate; -let signupTotal = signupFees + feeEstimate; - -function showQr(signupAddr, amount = 0) { +function showQr(signupAddr, duffs = 0) { let signupUri = `dash://${signupAddr}`; - if (amount) { - signupUri += `?amount=${amount}`; + if (duffs) { + signupUri += `?amount=${duffs}`; } let signupQr = Qr.ascii(signupUri, { indent: 4 }); @@ -60,16 +58,20 @@ function showHelp() { console.info(" crowdnode status ./privkey.wif"); console.info(" crowdnode signup ./privkey.wif"); console.info(" crowdnode accept ./privkey.wif"); - console.info(" crowdnode deposit ./privkey.wif [amount] [--no-reserve]"); console.info( - " crowdnode withdrawal ./privkey.wif # 1-1000 (1.0-100.0%)", + " crowdnode deposit ./privkey.wif [dash-amount] [--no-reserve]", + ); + console.info( + " crowdnode withdrawal ./privkey.wif # 1.0-100.0 (steps by 0.1)", ); console.info(""); console.info("Helpful Extras:"); console.info(" crowdnode generate [./privkey.wif]"); console.info(" crowdnode balance ./privkey.wif"); - console.info(" crowdnode transfer ./source.wif "); + console.info( + " crowdnode transfer ./source.wif [dash-amount]", + ); console.info(""); console.info("CrowdNode HTTP RPC:"); @@ -102,7 +104,7 @@ async function main() { // Usage: // crowdnode [flags] [options] // Example: - // crowdnode withdrawal --unconfirmed ./Xxxxpubaddr.wif 1000 + // crowdnode withdrawal ./Xxxxpubaddr.wif 100.0 let args = process.argv.slice(2); @@ -129,12 +131,22 @@ async function main() { return; } + let insightBaseUrl = + process.env.INSIGHT_BASE_URL || "https://insight.dash.org"; + let insightApi = Insight.create({ baseUrl: insightBaseUrl }); + let dashApi = Dash.create({ insightApi: insightApi }); + + process.stdout.write("Checking CrowdNode API... "); + await CrowdNode.init({ + baseUrl: "https://app.crowdnode.io", + insightBaseUrl, + insightApi: insightApi, + }); + console.info(`hotwallet is ${CrowdNode.main.hotwallet}`); + let rpc = ""; if ("http" === subcommand) { rpc = args.shift(); - } - - if ("http" === subcommand) { let keyfile = args.shift(); let pub = await wifFileToAddr(keyfile); @@ -174,18 +186,14 @@ async function main() { process.exit(1); } - let insightBaseUrl = - process.env.INSIGHT_BASE_URL || "https://insight.dash.org"; - let insightApi = Insight.create({ baseUrl: insightBaseUrl }); - let dashApi = Dash.create({ insightApi: insightApi }); - let pk = new Dashcore.PrivateKey(privKey); let pub = pk.toPublicKey().toAddress().toString(); // 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) { @@ -206,7 +214,7 @@ async function main() { balanceInfo: balanceInfo, dashApi: dashApi, forceConfirm: forceConfirm, - hotwallet: "", + hotwallet: CrowdNode.main.hotwallet, insightBaseUrl: insightBaseUrl, insightApi: insightApi, noReserve: noReserve, @@ -236,15 +244,6 @@ async function main() { return; } - process.stdout.write("Checking CrowdNode API... "); - await CrowdNode.init({ - baseUrl: "https://app.crowdnode.io", - insightBaseUrl, - insightApi: insightApi, - }); - state.hotwallet = CrowdNode.main.hotwallet; - console.info(`hotwallet is ${state.hotwallet}`); - state.status = await CrowdNode.status(pub, state.hotwallet); if (state.status?.signup) { state.signup = "✅"; @@ -302,30 +301,32 @@ 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(``); - console.info(`Generated ${filepath} ${note}`); - }); + 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); } @@ -335,17 +336,22 @@ async function balance(args, state) { return; } +// ex: node ./bin/crowdnode.js transfer ./priv.wif 'pub' 0.01 async function transfer(args, state) { let newAddr = await wifFileToAddr(process.argv[4]); - let amount = parseInt(process.argv[5] || 0, 10); + let dashAmount = parseFloat(process.argv[5] || 0); + let duffAmount = Math.round(dashAmount * DUFFS); let tx; - if (amount) { - tx = await state.dashApi.createPayment(state.privKey, newAddr, amount); + if (duffAmount) { + tx = await state.dashApi.createPayment(state.privKey, newAddr, duffAmount); } else { tx = await state.dashApi.createBalanceTransfer(state.privKey, newAddr); } - if (amount) { - console.info(`Transferring ${amount} to ${newAddr}...`); + if (duffAmount) { + let dashAmountStr = toDash(duffAmount); + console.info( + `Transferring ${duffAmount} (Đ${dashAmountStr}) to ${newAddr}...`, + ); } else { console.info(`Transferring balance to ${newAddr}...`); } @@ -373,6 +379,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; } @@ -389,15 +403,15 @@ async function signup(args, state) { return; } - let hasEnough = state.balanceInfo.balanceSat > signupTotal; + let hasEnough = state.balanceInfo.balanceSat > signupOnly + feeEstimate; if (!hasEnough) { await collectSignupFees(state.insightBaseUrl, state.pub); } console.info("Requesting account..."); await CrowdNode.signup(state.privKey, state.hotwallet); state.signup = "✅"; - console.info(` ${signup} SignUpForApi`); - console.info(` ${accept} AcceptTerms`); + console.info(` ${state.signup} SignUpForApi`); + console.info(` ${state.accept} AcceptTerms`); process.exit(0); return; } @@ -413,7 +427,7 @@ async function accept(args, state) { process.exit(0); return; } - let hasEnough = state.balanceInfo.balanceSat > signupTotal; + let hasEnough = state.balanceInfo.balanceSat > acceptOnly + feeEstimate; if (!hasEnough) { await collectSignupFees(state.insightBaseUrl, state.pub); } @@ -436,10 +450,10 @@ async function deposit(args, state) { // this would allow for at least 2 withdrawals costing (21000 + 1000) let reserve = 50000; - let reserveDash = (reserve / DUFFS).toFixed(8); + let reserveDash = toDash(reserve); if (!state.noReserve) { console.info( - `reserving ${reserve} (${reserveDash}) for withdrawals (--no-reserve to disable)`, + `reserving ${reserve} (Đ${reserveDash}) for withdrawals (--no-reserve to disable)`, ); } else { reserve = 0; @@ -449,8 +463,9 @@ async function deposit(args, state) { // deposit what the user asks, or all that we have, // or all that the user deposits - but at least 2x the reserve - let desiredAmount = parseInt(args.shift() || 0, 10); - let effectiveAmount = desiredAmount; + let desiredAmountDash = parseFloat(args.shift() || 0); + let desiredAmountDuff = Math.round(desiredAmountDash * DUFFS); + let effectiveAmount = desiredAmountDuff; if (!effectiveAmount) { effectiveAmount = state.balanceInfo.balanceSat - reserve; } @@ -458,25 +473,28 @@ async function deposit(args, state) { if (state.balanceInfo.balanceSat < needed) { let ask = 0; - if (desiredAmount) { - ask = desiredAmount + reserve + -state.balanceInfo.balanceSat; + if (desiredAmountDuff) { + ask = desiredAmountDuff + reserve + -state.balanceInfo.balanceSat; } await collectDeposit(state.insightBaseUrl, state.pub, ask); state.balanceInfo = await state.dashApi.getInstantBalance(state.pub); if (state.balanceInfo.balanceSat < needed) { + let balanceDash = toDash(state.balanceInfo.balanceSat); console.error( - `Balance is still too small: ${state.balanceInfo.balanceSat}`, + `Balance is still too small: ${state.balanceInfo.balanceSat} (Đ${balanceDash})`, ); process.exit(1); return; } } - if (!desiredAmount) { + if (!desiredAmountDuff) { effectiveAmount = state.balanceInfo.balanceSat - reserve; } - console.info(`(holding ${reserve} in reserve for API calls)`); - console.info(`Initiating deposit of ${effectiveAmount}...`); + let effectiveDash = toDash(effectiveAmount); + console.info( + `Initiating deposit of ${effectiveAmount} (Đ${effectiveDash})...`, + ); await CrowdNode.deposit(state.privKey, state.hotwallet, effectiveAmount); state.deposit = "✅"; console.info(` ${state.deposit} DepositReceived`); @@ -491,10 +509,25 @@ async function withdrawal(args, state) { return; } - let amount = parseInt(args.shift() || 1000, 10); + let percentStr = args.shift() || "100.0"; + // pass: .1 0.1, 1, 1.0, 10, 10.0, 100, 100.0 + // fail: 1000, 10.00 + if (!/^1?\d?\d?(\.\d)?$/.test(percentStr)) { + console.error("Error: withdrawal percent must be between 0.1 and 100.0"); + process.exit(1); + } + let percent = parseFloat(percentStr); - console.info("Initiating withdrawal..."); - let paid = await CrowdNode.withdrawal(state.privKey, state.hotwallet, amount); + let permil = Math.round(percent * 10); + if (permil <= 0 || permil > 1000) { + console.error("Error: withdrawal percent must be between 0.1 and 100.0"); + process.exit(1); + } + + let realPercentStr = (permil / 10).toFixed(1); + console.info(`Initiating withdrawal of ${realPercentStr}...`); + + let paid = await CrowdNode.withdrawal(state.privKey, state.hotwallet, permil); //let paidFloat = (paid.satoshis / DUFFS).toFixed(8); //let paidInt = paid.satoshis.toString().padStart(9, "0"); console.info(`API Response: ${paid.api}`); @@ -537,8 +570,8 @@ async function wifFileToAddr(keyfile) { async function collectSignupFees(insightBaseUrl, pub) { showQr(pub); - let signupTotalDash = (signupTotal / DUFFS).toFixed(8); - let signupMsg = `Please send >= ${signupTotal} (${signupTotalDash}) to Sign Up to CrowdNode`; + 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)"; let subMsgPad = Math.ceil((qrWidth - subMsg.length) / 2); @@ -555,13 +588,13 @@ async function collectSignupFees(insightBaseUrl, pub) { console.info(`Received ${payment.satoshis}`); } -async function collectDeposit(insightBaseUrl, pub, amount) { - showQr(pub, amount); +async function collectDeposit(insightBaseUrl, pub, duffAmount) { + showQr(pub, duffAmount); let depositMsg = `Please send what you wish to deposit to ${pub}`; - if (amount) { - let depositDash = (amount / DUFFS).toFixed(8); - depositMsg = `Please deposit ${amount} (${depositDash}) to ${pub}`; + if (duffAmount) { + let depositDash = toDash(duffAmount); + depositMsg = `Please deposit ${duffAmount} (Đ${depositDash}) to ${pub}`; } let msgPad = Math.ceil((qrWidth - depositMsg.length) / 2); @@ -578,6 +611,14 @@ async function collectDeposit(insightBaseUrl, pub, amount) { console.info(`Received ${payment.satoshis}`); } +function toDash(duffs) { + return (duffs / DUFFS).toFixed(8); +} + +function toDuff(dash) { + return Math.round(parseFloat(dash) * DUFFS); +} + // Run main().catch(function (err) {