diff --git a/README.md b/README.md
index 1c4d866..45ba3c2 100644
--- a/README.md
+++ b/README.md
@@ -36,11 +36,10 @@ npm install --save crowdnode@v1
## CrowdNode Browser SDK
```html
-
-
+
+
-
```
@@ -124,7 +123,7 @@ APIs, but which you could learn from in [crowdnode-cli](/bin/crowdnode.js).
```js
CrowdNode.offset = 20000;
-CrowdNode.duffs = 100000000;
+CrowdNode.satoshis = 100000000;
CrowdNode.depositMinimum = 100000;
CrowdNode.requests = {
@@ -188,8 +187,8 @@ await CrowdNode.accept(wif, hotwallet);
* }
*/
-// amount given in DUFFs
-await CrowdNode.deposit(wif, hotwallet, (amount = 0));
+// satoshis (a.k.a. duffs) is the base unit of DASH
+await CrowdNode.deposit(wif, hotwallet, (satoshis = 0));
/** @type SocketPayment
* {
* "address": "Xj00000000000000000000000000000000",
@@ -282,7 +281,7 @@ await CrowdNode.http.VotingOpen(pub);
| Term | Description |
| ------------- | ------------------------------------------------------------- |
| addr | your Dash address (Base58Check-encoded Pay-to-PubKey Address) |
-| amount | the integer value of "Duffs" (Đ/100000000) |
+| satoshis | the base unit of DASH (a.k.a. "Duffs") Đ/100000000 |
| permil | 1/1000, 1‰, or 0.1% - between 1 and 1000 (0.1% to 100.0%) |
| ./privkey.wif | the file path to your staking key in WIF (Base58Check) format |
diff --git a/bin/_qr-node.js b/bin/_qr-node.js
index 4d374a1..d614616 100644
--- a/bin/_qr-node.js
+++ b/bin/_qr-node.js
@@ -16,3 +16,5 @@ async function save(filepath, data, opts) {
//@ts-ignore
Qr.save = save;
+
+module.exports = Qr;
diff --git a/bin/crowdnode.js b/bin/crowdnode.js
index 8bd792c..341f140 100755
--- a/bin/crowdnode.js
+++ b/bin/crowdnode.js
@@ -16,24 +16,24 @@ let Path = require("path");
let Cipher = require("./_cipher.js");
let CrowdNode = require("../crowdnode.js");
let Dash = require("../dashapi.js");
-let Insight = require("dashsight");
+let Dashsight = require("dashsight");
let Prompt = require("./_prompt.js");
let Qr = require("./_qr-node.js");
let Ws = require("dashsight/ws");
-let Dashcore = require("@dashevo/dashcore-lib");
+let Dashcore = require("../dashcore-lit.js");
const DONE = "✅";
const TODO = "ℹ️";
const NO_SHADOW = "NONE";
-const DUFFS = 100000000;
+const SATOSHIS = 100000000;
let shownDefault = false;
let qrWidth = 2 + 33 + 2;
// Sign Up Fees:
// 0.00236608 // required for signup
// 0.00002000 // TX fee estimate
-// 0.00238608 // minimum recommended amount
+// 0.00238608 // minimum recommended DASH
// Target:
// 0.01000000
let signupOnly = CrowdNode.requests.signupForApi + CrowdNode.requests.offset;
@@ -137,6 +137,14 @@ function showHelp() {
let cmds = {};
+let dashsightBaseUrl =
+ process.env.DASHSIGHT_BASE_URL ||
+ "https://dashsight.dashincubator.dev/insight-api";
+let dashsocketBaseUrl =
+ process.env.DASHSOCKET_BASE_URL || "https://insight.dash.org/socket.io";
+let insightBaseUrl =
+ process.env.INSIGHT_BASE_URL || "https://insight.dash.org/insight-api";
+
async function main() {
/*jshint maxcomplexity:40 */
/*jshint maxstatements:500 */
@@ -180,17 +188,18 @@ async function main() {
);
defaultAddr = defaultAddr.trim();
- let insightBaseUrl =
- process.env.INSIGHT_BASE_URL || "https://insight.dash.org";
- let insightApi = Insight.create({ baseUrl: insightBaseUrl });
- let dashApi = Dash.create({ insightApi: insightApi });
+ let dashsightApi = Dashsight.create({
+ dashsightBaseUrl: dashsightBaseUrl,
+ dashsocketBaseUrl: dashsocketBaseUrl,
+ insightBaseUrl: insightBaseUrl,
+ });
+ let dashApi = Dash.create({ insightApi: dashsightApi });
if ("stake" === subcommand) {
await stakeDash(
{
dashApi,
- insightApi,
- insightBaseUrl,
+ insightApi: dashsightApi,
defaultAddr,
forceGenerate,
noReserve,
@@ -290,7 +299,12 @@ async function main() {
// helper for debugging
if ("transfer" === subcommand) {
await transferBalance(
- { dashApi, defaultAddr, forceConfirm, insightBaseUrl, insightApi },
+ {
+ dashApi,
+ defaultAddr,
+ forceConfirm,
+ insightApi: dashsightApi,
+ },
args,
);
process.exit(0);
@@ -308,7 +322,7 @@ async function main() {
let [addr] = await mustGetAddr({ defaultAddr }, args);
- await initCrowdNode(insightBaseUrl);
+ await initCrowdNode();
// ex: http (, ...)
args.unshift(addr);
let hasRpc = rpc in CrowdNode.http;
@@ -339,7 +353,7 @@ async function main() {
// keeping rm for backwards compat
if ("rm" === subcommand || "delete" === subcommand) {
- await initCrowdNode(insightBaseUrl);
+ await initCrowdNode();
let [addr, filepath] = await mustGetAddr({ defaultAddr }, args);
await removeKey({ addr, dashApi, filepath, insightBaseUrl }, args);
process.exit(0);
@@ -377,10 +391,7 @@ async function main() {
}
if ("deposit" === subcommand) {
- await depositDash(
- { dashApi, defaultAddr, insightBaseUrl, noReserve },
- args,
- );
+ await depositDash({ dashApi, defaultAddr, noReserve }, args);
process.exit(0);
return;
}
@@ -416,14 +427,7 @@ async function main() {
* @param {Array} args
*/
async function stakeDash(
- {
- dashApi,
- defaultAddr,
- forceGenerate,
- insightApi,
- insightBaseUrl,
- noReserve,
- },
+ { dashApi, defaultAddr, forceGenerate, insightApi, noReserve },
args,
) {
let err = await Fs.access(args[0]).catch(Object);
@@ -446,6 +450,8 @@ async function stakeDash(
console.info("Checking CrowdNode account... ");
await CrowdNode.init({
baseUrl: "https://app.crowdnode.io",
+ dashsightBaseUrl,
+ dashsocketBaseUrl,
insightBaseUrl,
});
let hotwallet = CrowdNode.main.hotwallet;
@@ -466,21 +472,20 @@ async function stakeDash(
extra += acceptDeposit;
}
- let desiredAmountDash = args.shift() || "0.5";
- let effectiveDuff = toDuff(desiredAmountDash);
- effectiveDuff += extra;
+ let desiredDashAmount = args.shift() || "0.5";
+ let effectiveSats = toDuff(desiredDashAmount);
+ effectiveSats += extra;
let balanceInfo = await dashApi.getInstantBalance(addr);
- effectiveDuff -= balanceInfo.balanceSat;
+ effectiveSats -= balanceInfo.balanceSat;
- if (effectiveDuff > 0) {
- effectiveDuff = roundDuff(effectiveDuff, 3);
- let effectiveDash = toDash(effectiveDuff);
+ if (effectiveSats > 0) {
+ effectiveSats = roundDuff(effectiveSats, 3);
+ let effectiveDash = toDash(effectiveSats);
await plainLoadAddr({
addr,
effectiveDash,
- effectiveDuff,
- insightBaseUrl,
+ effectiveSats,
});
}
@@ -492,7 +497,7 @@ async function stakeDash(
}
await depositDash(
- { dashApi, defaultAddr: addr, insightBaseUrl, noReserve },
+ { dashApi, defaultAddr: addr, noReserve },
[addr].concat(args),
);
@@ -514,16 +519,15 @@ async function initKeystore({ defaultAddr }) {
return defaultAddr || wifnames[0];
}
-/**
- * @param {String} insightBaseUrl
- */
-async function initCrowdNode(insightBaseUrl) {
- if (CrowdNode.main.hotwallet) {
+async function initCrowdNode() {
+ if (CrowdNode._initialized) {
return;
}
process.stdout.write("Checking CrowdNode API... ");
await CrowdNode.init({
baseUrl: "https://app.crowdnode.io",
+ dashsightBaseUrl,
+ dashsocketBaseUrl,
insightBaseUrl,
});
console.info(`(hotwallet ${CrowdNode.main.hotwallet})`);
@@ -659,7 +663,7 @@ async function mustGetAddr({ defaultAddr }, args) {
return [addr, name];
}
//let pk = new Dashcore.PrivateKey(wif);
- //let addr = pk.toAddress().toString();
+ //let addr = (await pk.toAddress()).toString();
return [addr, name];
}
@@ -792,8 +796,8 @@ async function generateKey({ defaultKey, plainText }, args) {
//@ts-ignore - TODO submit JSDoc PR for Dashcore
let pk = new Dashcore.PrivateKey();
- let addr = pk.toAddress().toString();
- let plainWif = pk.toWIF();
+ let addr = (await pk.toAddress()).toString();
+ let plainWif = await pk.toWIF();
let wif = plainWif;
if (!plainText) {
@@ -1255,7 +1259,7 @@ async function maybeReadKeyFileRaw(filepath, opts) {
}
let pk = new Dashcore.PrivateKey(privKey);
- let pub = pk.toAddress().toString();
+ let pub = (await pk.toAddress()).toString();
return {
addr: pub,
@@ -1322,7 +1326,7 @@ async function setDefault(_, args) {
let filepath = Path.join(keysDir, keyname);
let wif = await maybeReadKeyFile(filepath);
let pk = new Dashcore.PrivateKey(wif);
- let pub = pk.toAddress().toString();
+ let pub = (await pk.toAddress()).toString();
console.info("set", defaultWifPath, pub);
await Fs.writeFile(defaultWifPath, pub, "utf8");
@@ -1435,7 +1439,7 @@ async function getAllBalances({ dashApi, defaultAddr }, args) {
/*
let pk = new Dashcore.PrivateKey(wif);
- let pub = pk.toAddress().toString();
+ let pub = (await pk.toAddress()).toString();
if (`${pub}.wif` !== wifname) {
// sanity check
warns.push({
@@ -1529,7 +1533,7 @@ async function removeKey({ addr, dashApi, filepath, insightBaseUrl }, args) {
return;
}
- await initCrowdNode(insightBaseUrl);
+ await initCrowdNode();
let crowdNodeBalance = await CrowdNode.http.GetBalance(addr);
if (!crowdNodeBalance) {
// may be janky if not registered
@@ -1621,18 +1625,18 @@ async function listManagedKeynames() {
async function loadAddr({ defaultAddr, insightBaseUrl }, args) {
let [addr] = await mustGetAddr({ defaultAddr }, args);
- let desiredAmountDash = parseFloat(args.shift() || "0");
- let desiredAmountDuff = Math.round(desiredAmountDash * DUFFS);
+ let desiredDashAmount = parseFloat(args.shift() || "0");
+ let desiredSatoshis = Math.round(desiredDashAmount * SATOSHIS);
- let effectiveDuff = desiredAmountDuff;
+ let effectiveSats = desiredSatoshis;
let effectiveDash = "";
- if (!effectiveDuff) {
- effectiveDuff = CrowdNode.stakeMinimum + signupTotal + feeEstimate;
- effectiveDuff = roundDuff(effectiveDuff, 3);
- effectiveDash = toDash(effectiveDuff);
+ if (!effectiveSats) {
+ effectiveSats = CrowdNode.stakeMinimum + signupTotal + feeEstimate;
+ effectiveSats = roundDuff(effectiveSats, 3);
+ effectiveDash = toDash(effectiveSats);
}
- await plainLoadAddr({ addr, effectiveDash, effectiveDuff, insightBaseUrl });
+ await plainLoadAddr({ addr, effectiveDash, effectiveSats, insightBaseUrl });
return;
}
@@ -1640,33 +1644,28 @@ async function loadAddr({ defaultAddr, insightBaseUrl }, args) {
/**
* 1000 to Round to the nearest mDash
* ex: 0.50238108 => 0.50300000
- * @param {Number} effectiveDuff
+ * @param {Number} effectiveSats
* @param {Number} numDigits
*/
-function roundDuff(effectiveDuff, numDigits) {
+function roundDuff(effectiveSats, numDigits) {
let n = Math.pow(10, numDigits);
- let effectiveDash = toDash(effectiveDuff);
- effectiveDuff = toDuff(
+ let effectiveDash = toDash(effectiveSats);
+ effectiveSats = toDuff(
(Math.ceil(parseFloat(effectiveDash) * n) / n).toString(),
);
- return effectiveDuff;
+ return effectiveSats;
}
/**
* @param {Object} opts
* @param {String} opts.addr
* @param {String} opts.effectiveDash
- * @param {Number} opts.effectiveDuff
+ * @param {Number} opts.effectiveSats
* @param {String} opts.insightBaseUrl
*/
-async function plainLoadAddr({
- addr,
- effectiveDash,
- effectiveDuff,
- insightBaseUrl,
-}) {
+async function plainLoadAddr({ addr, effectiveDash, effectiveSats }) {
console.info(``);
- showQr(addr, effectiveDuff);
+ showQr(addr, effectiveSats);
console.info(``);
console.info(
`Send Đ${effectiveDash} to your staking key via the QR above, or its address:`,
@@ -1678,7 +1677,7 @@ async function plainLoadAddr({
console.info(``);
console.info(`(waiting...)`);
console.info(``);
- let payment = await Ws.waitForVout(insightBaseUrl, addr, 0);
+ let payment = await Ws.waitForVout(dashsocketBaseUrl, addr, 0);
console.info(`Received ${payment.satoshis}`);
}
@@ -1707,7 +1706,7 @@ async function getBalance({ dashApi, defaultAddr }, args) {
*/
// ex: node ./bin/crowdnode.js transfer Xxxxx 'pub' 0.01
async function transferBalance(
- { dashApi, defaultAddr, forceConfirm, insightBaseUrl, insightApi },
+ { dashApi, defaultAddr, forceConfirm, insightApi },
args,
) {
/** @type Array */
@@ -1719,16 +1718,16 @@ async function transferBalance(
//
// Ex:
// crowdnode transfer {source} {dest}
- // crowdnode transfer {source} {dest} {amount}
- // crowdnode transfer {dest} {amount}
+ // crowdnode transfer {source} {dest} {dash-amount}
+ // crowdnode transfer {dest} {dash-amount}
// crowdnode transfer {dest}
//
- // To disambiguate, we check if the second argument is an amount.
+ // To disambiguate, we check if the second argument is a dash-amount.
if (3 === args.length) {
getAddrArgs = args;
} else if (2 === args.length) {
- let maybeAmount = parseFloat(args[1]);
- let isAddr = isNaN(maybeAmount);
+ let maybeDashAmount = parseFloat(args[1]);
+ let isAddr = isNaN(maybeDashAmount);
if (isAddr) {
getAddrArgs = args;
}
@@ -1738,17 +1737,17 @@ async function transferBalance(
let keyname = args.shift() || "";
let newAddr = await wifFileToAddr(keyname);
let dashAmount = parseFloat(args.shift() || "0");
- let duffAmount = Math.round(dashAmount * DUFFS);
+ let satoshis = Math.round(dashAmount * SATOSHIS);
let tx;
- if (duffAmount) {
- tx = await dashApi.createPayment(wif, newAddr, duffAmount);
+ if (satoshis) {
+ tx = await dashApi.createPayment(wif, newAddr, satoshis);
} else {
tx = await dashApi.createBalanceTransfer(wif, newAddr);
}
- if (duffAmount) {
- let dashAmountStr = toDash(duffAmount);
+ if (satoshis) {
+ let dashAmountStr = toDash(satoshis);
console.info(
- `Transferring ${duffAmount} (Đ${dashAmountStr}) to ${newAddr}...`,
+ `Transferring ${satoshis} (Đ${dashAmountStr}) to ${newAddr}...`,
);
} else {
console.info(`Transferring balance to ${newAddr}...`);
@@ -1764,7 +1763,7 @@ async function transferBalance(
}
process.exit(1);
}, 30 * 1000);
- await Ws.waitForVout(insightBaseUrl, newAddr, 0);
+ await Ws.waitForVout(dashsocketBaseUrl, newAddr, 0);
console.info(`Accepted!`);
return;
}
@@ -1778,7 +1777,7 @@ async function transferBalance(
*/
async function getStatus({ dashApi, defaultAddr, insightBaseUrl }, args) {
let [addr] = await mustGetAddr({ defaultAddr }, args);
- await initCrowdNode(insightBaseUrl);
+ await initCrowdNode();
let hotwallet = CrowdNode.main.hotwallet;
let state = await getCrowdNodeStatus({ addr, hotwallet });
@@ -1816,7 +1815,7 @@ async function getStatus({ dashApi, defaultAddr, insightBaseUrl }, args) {
*/
async function sendSignup({ dashApi, defaultAddr, insightBaseUrl }, args) {
let [addr, name] = await mustGetAddr({ defaultAddr }, args);
- await initCrowdNode(insightBaseUrl);
+ await initCrowdNode();
let hotwallet = CrowdNode.main.hotwallet;
let state = await getCrowdNodeStatus({ addr, hotwallet });
let balanceInfo = await dashApi.getInstantBalance(addr);
@@ -1831,7 +1830,7 @@ async function sendSignup({ dashApi, defaultAddr, insightBaseUrl }, args) {
let hasEnough = balanceInfo.balanceSat > signupOnly + feeEstimate;
if (!hasEnough) {
- await collectSignupFees(insightBaseUrl, addr);
+ await collectSignupFees(addr);
}
let wif = await maybeReadKeyPaths(name, { wif: true });
@@ -1853,7 +1852,7 @@ async function sendSignup({ dashApi, defaultAddr, insightBaseUrl }, args) {
async function acceptTerms({ dashApi, defaultAddr, insightBaseUrl }, args) {
let [addr, name] = await mustGetAddr({ defaultAddr }, args);
- await initCrowdNode(insightBaseUrl);
+ await initCrowdNode();
let hotwallet = CrowdNode.main.hotwallet;
let state = await getCrowdNodeStatus({ addr, hotwallet });
let balanceInfo = await dashApi.getInstantBalance(addr);
@@ -1875,7 +1874,7 @@ async function acceptTerms({ dashApi, defaultAddr, insightBaseUrl }, args) {
}
let hasEnough = balanceInfo.balanceSat > acceptOnly + feeEstimate;
if (!hasEnough) {
- await collectSignupFees(insightBaseUrl, addr);
+ await collectSignupFees(addr);
}
let wif = await maybeReadKeyPaths(name, { wif: true });
@@ -1895,12 +1894,9 @@ async function acceptTerms({ dashApi, defaultAddr, insightBaseUrl }, args) {
* @param {Boolean} opts.noReserve
* @param {Array} args
*/
-async function depositDash(
- { dashApi, defaultAddr, insightBaseUrl, noReserve },
- args,
-) {
+async function depositDash({ dashApi, defaultAddr, noReserve }, args) {
let [addr, name] = await mustGetAddr({ defaultAddr }, args);
- await initCrowdNode(insightBaseUrl);
+ await initCrowdNode();
let hotwallet = CrowdNode.main.hotwallet;
let state = await getCrowdNodeStatus({ addr, hotwallet });
let balanceInfo = await dashApi.getInstantBalance(addr);
@@ -1926,20 +1922,20 @@ async function depositDash(
// deposit what the user asks, or all that we have,
// or all that the user deposits - but at least 2x the reserve
- let desiredAmountDash = parseFloat(args.shift() || "0");
- let desiredAmountDuff = Math.round(desiredAmountDash * DUFFS);
- let effectiveAmount = desiredAmountDuff;
- if (!effectiveAmount) {
- effectiveAmount = balanceInfo.balanceSat - reserve;
+ let desiredDashAmount = parseFloat(args.shift() || "0");
+ let desiredSatoshis = Math.round(desiredDashAmount * SATOSHIS);
+ let effectiveSats = desiredSatoshis;
+ if (!effectiveSats) {
+ effectiveSats = balanceInfo.balanceSat - reserve;
}
- let needed = Math.max(reserve * 2, effectiveAmount + reserve);
+ let needed = Math.max(reserve * 2, effectiveSats + reserve);
if (balanceInfo.balanceSat < needed) {
let ask = 0;
- if (desiredAmountDuff) {
- ask = desiredAmountDuff + reserve + -balanceInfo.balanceSat;
+ if (desiredSatoshis) {
+ ask = desiredSatoshis + reserve + -balanceInfo.balanceSat;
}
- await collectDeposit(insightBaseUrl, addr, ask);
+ await collectDeposit(addr, ask);
balanceInfo = await dashApi.getInstantBalance(addr);
if (balanceInfo.balanceSat < needed) {
let balanceDash = toDash(balanceInfo.balanceSat);
@@ -1950,18 +1946,16 @@ async function depositDash(
return;
}
}
- if (!desiredAmountDuff) {
- effectiveAmount = balanceInfo.balanceSat - reserve;
+ if (!desiredSatoshis) {
+ effectiveSats = balanceInfo.balanceSat - reserve;
}
- let effectiveDash = toDash(effectiveAmount);
- console.info(
- `Initiating deposit of ${effectiveAmount} (Đ${effectiveDash})...`,
- );
+ let effectiveDash = toDash(effectiveSats);
+ console.info(`Initiating deposit of ${effectiveSats} (Đ${effectiveDash})...`);
let wif = await maybeReadKeyPaths(name, { wif: true });
- await CrowdNode.deposit(wif, hotwallet, effectiveAmount);
+ await CrowdNode.deposit(wif, hotwallet, effectiveSats);
state.deposit = DONE;
console.info(` ${state.deposit} DepositReceived`);
return;
@@ -1976,7 +1970,7 @@ async function depositDash(
*/
async function withdrawDash({ dashApi, defaultAddr, insightBaseUrl }, args) {
let [addr] = await mustGetAddr({ defaultAddr }, args);
- await initCrowdNode(insightBaseUrl);
+ await initCrowdNode();
let hotwallet = CrowdNode.main.hotwallet;
let state = await getCrowdNodeStatus({ addr, hotwallet });
@@ -2008,7 +2002,7 @@ async function withdrawDash({ dashApi, defaultAddr, insightBaseUrl }, args) {
let filepath = Path.join(keysDir, wifname);
let wif = await maybeReadKeyFile(filepath);
let paid = await CrowdNode.withdraw(wif, hotwallet, permil);
- //let paidFloat = (paid.satoshis / DUFFS).toFixed(8);
+ //let paidFloat = (paid.satoshis / SATOSHIS).toFixed(8);
//let paidInt = paid.satoshis.toString().padStart(9, "0");
console.info(`API Response: ${paid.api}`);
return;
@@ -2042,15 +2036,14 @@ async function wifFileToAddr(name) {
}
let pk = new Dashcore.PrivateKey(privKey);
- let pub = pk.toPublicKey().toAddress().toString();
+ let pub = (await pk.toPublicKey().toAddress()).toString();
return pub;
}
/**
- * @param {String} insightBaseUrl
* @param {String} addr
*/
-async function collectSignupFees(insightBaseUrl, addr) {
+async function collectSignupFees(addr) {
console.info(``);
showQr(addr);
@@ -2068,23 +2061,23 @@ async function collectSignupFees(insightBaseUrl, addr) {
console.info("");
console.info("(waiting...)");
console.info("");
- let payment = await Ws.waitForVout(insightBaseUrl, addr, 0);
+ let payment = await Ws.waitForVout(dashsocketBaseUrl, addr, 0);
console.info(`Received ${payment.satoshis}`);
}
/**
* @param {String} insightBaseUrl
* @param {String} addr
- * @param {Number} duffAmount
+ * @param {Number} satoshis
*/
-async function collectDeposit(insightBaseUrl, addr, duffAmount) {
+async function collectDeposit(addr, satoshis) {
console.info(``);
- showQr(addr, duffAmount);
+ showQr(addr, satoshis);
let depositMsg = `Please send what you wish to deposit to ${addr}`;
- if (duffAmount) {
- let dashAmount = toDash(duffAmount);
- depositMsg = `Please deposit ${duffAmount} (Đ${dashAmount}) to ${addr}`;
+ if (satoshis) {
+ let dashAmount = toDash(satoshis);
+ depositMsg = `Please deposit ${satoshis} (Đ${dashAmount}) to ${addr}`;
}
let msgPad = Math.ceil((qrWidth - depositMsg.length) / 2);
@@ -2097,7 +2090,7 @@ async function collectDeposit(insightBaseUrl, addr, duffAmount) {
console.info("");
console.info("(waiting...)");
console.info("");
- let payment = await Ws.waitForVout(insightBaseUrl, addr, 0);
+ let payment = await Ws.waitForVout(dashsocketBaseUrl, addr, 0);
console.info(`Received ${payment.satoshis}`);
}
@@ -2116,14 +2109,14 @@ function emptyStringOnErrEnoent(err) {
* @param {Number} duffs - ex: 00000000
*/
function toDash(duffs) {
- return (duffs / DUFFS).toFixed(8);
+ return (duffs / SATOSHIS).toFixed(8);
}
/**
* @param {Number} duffs - ex: 00000000
*/
function toDASH(duffs) {
- let dash = (duffs / DUFFS).toFixed(8);
+ let dash = (duffs / SATOSHIS).toFixed(8);
return `Đ` + dash.padStart(12, " ");
}
@@ -2131,7 +2124,7 @@ function toDASH(duffs) {
* @param {String} dash - ex: 0.00000000
*/
function toDuff(dash) {
- return Math.round(parseFloat(dash) * DUFFS);
+ return Math.round(parseFloat(dash) * SATOSHIS);
}
// Run
diff --git a/bin/crowdnode.js.bak b/bin/crowdnode.js.bak
deleted file mode 100755
index e59b950..0000000
--- a/bin/crowdnode.js.bak
+++ /dev/null
@@ -1,2360 +0,0 @@
-#!/usr/bin/env node
-"use strict";
-/*jshint maxcomplexity:25 */
-
-require("dotenv").config({ path: ".env" });
-require("dotenv").config({ path: ".env.secret" });
-
-let HOME = process.env.HOME || "";
-
-//@ts-ignore
-let pkg = require("../package.json");
-
-let Fs = require("fs").promises;
-let Path = require("path");
-
-let Cipher = require("./_cipher.js");
-let CrowdNode = require("../lib/crowdnode.js");
-let Dash = require("../lib/dash.js");
-let Insight = require("../lib/insight.js");
-let Prompt = require("./_prompt.js");
-let Qr = require("../lib/qr.js");
-let Ws = require("../lib/ws.js");
-
-let Dashcore = require("@dashevo/dashcore-lib");
-
-const DONE = "✅";
-const TODO = "ℹ️";
-const NO_SHADOW = "NONE";
-const DUFFS = 100000000;
-
-let shownDefault = false;
-let qrWidth = 2 + 33 + 2;
-// Sign Up Fees:
-// 0.00236608 // required for signup
-// 0.00002000 // TX fee estimate
-// 0.00238608 // minimum recommended amount
-// Target:
-// 0.01000000
-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 paths = {};
-let configdir = `.config/crowdnode`;
-let keysDir = Path.join(HOME, `${configdir}/keys`);
-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();
-}
-
-function showHelp() {
- showVersion();
-
- console.info("Quick Start:");
- // technically this also has [--no-reserve]
- console.info(" crowdnode stake [addr-or-import-key | --create-new]");
-
- console.info("");
- console.info("Usage:");
- console.info(" crowdnode help");
- console.info(" crowdnode version");
- console.info("");
- console.info(" crowdnode status [keyfile-or-addr]");
- console.info(" crowdnode signup [keyfile-or-addr]");
- console.info(" crowdnode accept [keyfile-or-addr]");
- console.info(
- " crowdnode deposit [keyfile-or-addr] [dash-amount] [--no-reserve]",
- );
- console.info(
- " crowdnode withdraw [keyfile-or-addr] # 1.0-100.0 (steps by 0.1)",
- );
- console.info("");
-
- console.info("Helpful Extras:");
- console.info(" crowdnode balance [keyfile-or-addr]"); // addr
- console.info(" crowdnode load [keyfile-or-addr] [dash-amount]"); // addr
- console.info(
- " crowdnode transfer [dash-amount]",
- ); // custom
- console.info("");
-
- console.info("Key Management & Encryption:");
- console.info(" crowdnode init");
- 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 ");
- console.info(" crowdnode import ");
- //console.info(" crowdnode import <(dash-cli dumpprivkey )"); // TODO
- //console.info(" crowdnode export "); // TODO
- console.info(" crowdnode passphrase # set or change passphrase");
- console.info(" crowdnode decrypt"); // TODO allow decrypting one-by-one?
- console.info(" crowdnode delete ");
- console.info("");
-
- console.info("CrowdNode HTTP RPC:");
- console.info(" crowdnode http FundsOpen ");
- console.info(" crowdnode http VotingOpen ");
- console.info(" crowdnode http GetFunds ");
- console.info(" crowdnode http GetFundsFrom ");
- console.info(" crowdnode http GetBalance ");
- console.info(" crowdnode http GetMessages ");
- console.info(" crowdnode http IsAddressInUse ");
- // TODO create signature rather than requiring it
- console.info(" crowdnode http SetEmail ./privkey.wif ");
- console.info(" crowdnode http Vote ./privkey.wif ");
- console.info(" ");
- console.info(
- " 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 = {};
-
-async function main() {
- /*jshint maxcomplexity:40 */
- /*jshint maxstatements:500 */
-
- // Usage:
- // crowdnode [flags] [options]
- // Example:
- // crowdnode withdraw ./Xxxxpubaddr.wif 100.0
-
- let args = process.argv.slice(2);
-
- // flags
- let forceGenerate = removeItem(args, "--create-new");
- let forceConfirm = removeItem(args, "--unconfirmed");
- let plainText = removeItem(args, "--plain-text");
- let noReserve = removeItem(args, "--no-reserve");
-
- let subcommand = args.shift();
-
- if (!subcommand || ["--help", "-h", "help"].includes(subcommand)) {
- showHelp();
- process.exit(0);
- return;
- }
-
- if (["--version", "-V", "version"].includes(subcommand)) {
- showVersion();
- process.exit(0);
- return;
- }
-
- //
- //
- // find addr by name or by file or by string
- await Fs.mkdir(keysDir, {
- recursive: true,
- });
-
- let defaultAddr = await Fs.readFile(defaultWifPath, "utf8").catch(
- emptyStringOnErrEnoent,
- );
- defaultAddr = defaultAddr.trim();
-
- let insightBaseUrl =
- process.env.INSIGHT_BASE_URL || "https://insight.dash.org";
- let insightApi = Insight.create({ baseUrl: insightBaseUrl });
- let dashApi = Dash.create({ insightApi: insightApi });
-
- if ("stake" === subcommand) {
- await stakeDash(
- {
- dashApi,
- insightApi,
- insightBaseUrl,
- defaultAddr,
- forceGenerate,
- noReserve,
- },
- args,
- );
- process.exit(0);
- return;
- }
-
- if ("list" === subcommand) {
- await listKeys({ dashApi, defaultAddr }, args);
- process.exit(0);
- return;
- }
-
- if ("init" === subcommand) {
- await initKeystore({ defaultAddr });
- process.exit(0);
- return;
- }
-
- if ("generate" === subcommand) {
- await generateKey({ defaultKey: defaultAddr, plainText }, args);
- process.exit(0);
- return;
- }
-
- if ("passphrase" === subcommand) {
- await setPassphrase({}, args);
- process.exit(0);
- return;
- }
-
- if ("import" === subcommand) {
- let keypath = args.shift() || "";
- await importKey({ keypath });
- process.exit(0);
- return;
- }
-
- if ("encrypt" === subcommand) {
- let addr = args.shift() || "";
- if (!addr) {
- await encryptAll(null);
- process.exit(0);
- return;
- }
-
- let keypath = await findWif(addr);
- if (!keypath) {
- console.error(`no managed key matches '${addr}'`);
- process.exit(1);
- return;
- }
- let key = await maybeReadKeyFileRaw(keypath);
- if (!key) {
- throw new Error("impossible error");
- }
- await encryptAll([key]);
- process.exit(0);
- return;
- }
-
- if ("decrypt" === subcommand) {
- let addr = args.shift() || "";
- if (!addr) {
- await decryptAll(null);
- await Fs.writeFile(shadowPath, NO_SHADOW, "utf8").catch(
- emptyStringOnErrEnoent,
- );
- process.exit(0);
- return;
- }
- let keypath = await findWif(addr);
- if (!keypath) {
- console.error(`no managed key matches '${addr}'`);
- process.exit(1);
- return;
- }
- let key = await maybeReadKeyFileRaw(keypath);
- if (!key) {
- throw new Error("impossible error");
- }
- await decryptAll([key]);
- process.exit(0);
- return;
- }
-
- // use or select or default... ?
- if ("use" === subcommand) {
- await setDefault(null, args);
- process.exit(0);
- return;
- }
-
- // helper for debugging
- if ("transfer" === subcommand) {
- await transferBalance(
- { dashApi, defaultAddr, forceConfirm, insightBaseUrl, insightApi },
- args,
- );
- process.exit(0);
- return;
- }
-
- let rpc = "";
- if ("http" === subcommand) {
- rpc = args.shift() || "";
- if (!rpc) {
- showHelp();
- process.exit(1);
- return;
- }
-
- let [addr] = await mustGetAddr({ defaultAddr }, args);
-
- await initCrowdNode(insightBaseUrl);
- // ex: http (, ...)
- args.unshift(addr);
- let hasRpc = rpc in CrowdNode.http;
- if (!hasRpc) {
- console.error(`Unrecognized rpc command ${rpc}`);
- console.error();
- showHelp();
- process.exit(1);
- }
- //@ts-ignore - TODO use `switch` or make Record Type
- let result = await CrowdNode.http[rpc].apply(null, args);
- console.info(``);
- console.info(`${rpc} ${addr}:`);
- if ("string" === typeof result) {
- console.info(result);
- } else {
- console.info(JSON.stringify(result, null, 2));
- }
- process.exit(0);
- return;
- }
-
- if ("load" === subcommand) {
- await loadAddr({ defaultAddr, insightBaseUrl }, args);
- process.exit(0);
- return;
- }
-
- // keeping rm for backwards compat
- if ("rm" === subcommand || "delete" === subcommand) {
- await initCrowdNode(insightBaseUrl);
- let [addr, filepath] = await mustGetAddr({ defaultAddr }, args);
- await removeKey({ addr, dashApi, filepath, insightBaseUrl }, args);
- process.exit(0);
- return;
- }
-
- if ("balance" === subcommand) {
- if (args.length) {
- await getBalance({ dashApi, defaultAddr }, args);
- process.exit(0);
- return;
- }
-
- await getAllBalances({ dashApi, defaultAddr }, args);
- process.exit(0);
- return;
- }
-
- if ("status" === subcommand) {
- await getStatus({ dashApi, defaultAddr, insightBaseUrl }, args);
- process.exit(0);
- return;
- }
-
- if ("signup" === subcommand) {
- await sendSignup({ dashApi, defaultAddr, insightBaseUrl }, args);
- process.exit(0);
- return;
- }
-
- if ("accept" === subcommand) {
- await acceptTerms({ dashApi, defaultAddr, insightBaseUrl }, args);
- process.exit(0);
- return;
- }
-
- if ("deposit" === subcommand) {
- await depositDash(
- { dashApi, defaultAddr, insightBaseUrl, noReserve },
- args,
- );
- process.exit(0);
- return;
- }
-
- // The misspelling 'withdrawal' is kept as part of compatibility < v1.7
- if ("withdrawal" === subcommand) {
- console.warn(
- `[Deprecation Notice] 'crowdnode withdrawal' is a misspelling of 'crowdnode withdraw'`,
- );
- subcommand = "withdraw";
- }
-
- if ("withdraw" === subcommand) {
- await withdrawDash({ dashApi, defaultAddr, insightBaseUrl }, args);
- process.exit(0);
- return;
- }
-
- console.error(`Unrecognized subcommand ${subcommand}`);
- console.error();
- showHelp();
- process.exit(1);
-}
-
-/**
- * @param {String} insightBaseUrl
- * @param {String} addr
- */
-async function collectSignupFees(insightBaseUrl, addr) {
- console.info(``);
- showQr(addr);
-
- 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);
-
- console.info();
- console.info(" ".repeat(msgPad) + signupMsg);
- console.info(" ".repeat(subMsgPad) + subMsg);
- console.info();
-
- console.info("");
- console.info("(waiting...)");
- console.info("");
- let payment = await Ws.waitForVout(insightBaseUrl, addr, 0);
- console.info(`Received ${payment.satoshis}`);
-}
-
-/**
- * @param {String} insightBaseUrl
- * @param {String} addr
- * @param {Number} duffAmount
- */
-async function collectDeposit(insightBaseUrl, addr, duffAmount) {
- console.info(``);
- showQr(addr, duffAmount);
-
- let depositMsg = `Please send what you wish to deposit to ${addr}`;
- if (duffAmount) {
- let dashAmount = toDash(duffAmount);
- depositMsg = `Please deposit ${duffAmount} (Đ${dashAmount}) to ${addr}`;
- }
-
- let msgPad = Math.ceil((qrWidth - depositMsg.length) / 2);
- msgPad = Math.max(0, msgPad);
-
- console.info();
- console.info(" ".repeat(msgPad) + depositMsg);
- console.info();
-
- console.info("");
- console.info("(waiting...)");
- console.info("");
- let payment = await Ws.waitForVout(insightBaseUrl, addr, 0);
- console.info(`Received ${payment.satoshis}`);
-}
-
-/**
- * @param {Object} opts
- * @param {any} opts.dashApi - TODO
- * @param {String} opts.defaultAddr
- * @param {String} opts.insightBaseUrl
- * @param {Array} args
- */
-async function getStatus({ dashApi, defaultAddr, insightBaseUrl }, args) {
- let [addr] = await mustGetAddr({ defaultAddr }, args);
- await initCrowdNode(insightBaseUrl);
- let hotwallet = CrowdNode.main.hotwallet;
- let state = await getCrowdNodeStatus({ addr, hotwallet });
-
- console.info();
- console.info(`API Actions Complete for ${addr}:`);
- console.info(` ${state.signup} SignUpForApi`);
- console.info(` ${state.accept} AcceptTerms`);
- console.info(` ${state.deposit} DepositReceived`);
- console.info();
- let crowdNodeBalance = await CrowdNode.http.GetBalance(addr);
- // may be unregistered / undefined
- /*
- * {
- * '@odata.context': 'https://app.crowdnode.io/odata/$metadata#Edm.String',
- * value: 'Address not found.'
- * }
- */
- if (!crowdNodeBalance.TotalBalance) {
- crowdNodeBalance.TotalBalance = 0;
- }
- let crowdNodeDuff = toDuff(crowdNodeBalance.TotalBalance);
- console.info(
- `CrowdNode Stake: ${crowdNodeDuff} (Đ${crowdNodeBalance.TotalBalance})`,
- );
- console.info();
- return;
-}
-
-/**
- * @param {Object} opts
- * @param {any} opts.dashApi - TODO
- * @param {String} opts.defaultAddr
- * @param {String} opts.insightBaseUrl
- * @param {Array} args
- */
-async function sendSignup({ dashApi, defaultAddr, insightBaseUrl }, args) {
- let [addr, name] = await mustGetAddr({ defaultAddr }, args);
- await initCrowdNode(insightBaseUrl);
- let hotwallet = CrowdNode.main.hotwallet;
- let state = await getCrowdNodeStatus({ addr, hotwallet });
- let balanceInfo = await checkBalance({ addr, dashApi });
-
- if (state.status?.signup) {
- console.info(`${addr} is already signed up. Here's the account status:`);
- console.info(` ${state.signup} SignUpForApi`);
- console.info(` ${state.accept} AcceptTerms`);
- console.info(` ${state.deposit} DepositReceived`);
- return;
- }
-
- let hasEnough = balanceInfo.balanceSat > signupOnly + feeEstimate;
- if (!hasEnough) {
- await collectSignupFees(insightBaseUrl, addr);
- }
-
- let wif = await maybeReadKeyPaths(name, { wif: true });
-
- console.info("Requesting account...");
- await CrowdNode.signup(wif, hotwallet);
- state.signup = DONE;
- console.info(` ${state.signup} SignUpForApi`);
- return;
-}
-
-/**
- * @param {Object} opts
- * @param {any} opts.dashApi - TODO
- * @param {String} opts.defaultAddr
- * @param {String} opts.insightBaseUrl
- * @param {Array} args
- */
-async function acceptTerms({ dashApi, defaultAddr, insightBaseUrl }, args) {
- let [addr, name] = await mustGetAddr({ defaultAddr }, args);
-
- await initCrowdNode(insightBaseUrl);
- let hotwallet = CrowdNode.main.hotwallet;
- let state = await getCrowdNodeStatus({ addr, hotwallet });
- let balanceInfo = await dashApi.getInstantBalance(addr);
-
- if (!state.status?.signup) {
- console.info(`${addr} is not signed up yet. Here's the account status:`);
- console.info(` ${state.signup} SignUpForApi`);
- console.info(` ${state.accept} AcceptTerms`);
- process.exit(1);
- return;
- }
-
- if (state.status?.accept) {
- console.info(`${addr} is already signed up. Here's the account status:`);
- console.info(` ${state.signup} SignUpForApi`);
- console.info(` ${state.accept} AcceptTerms`);
- console.info(` ${state.deposit} DepositReceived`);
- return;
- }
- let hasEnough = balanceInfo.balanceSat > acceptOnly + feeEstimate;
- if (!hasEnough) {
- await collectSignupFees(insightBaseUrl, addr);
- }
-
- let wif = await maybeReadKeyPaths(name, { wif: true });
-
- console.info("Accepting terms...");
- await CrowdNode.accept(wif, hotwallet);
- state.accept = DONE;
- console.info(` ${state.accept} AcceptTerms`);
- return;
-}
-
-/**
- * @param {Object} opts
- * @param {any} opts.dashApi - TODO
- * @param {String} opts.defaultAddr
- * @param {String} opts.insightBaseUrl
- * @param {Boolean} opts.noReserve
- * @param {Array} args
- */
-async function depositDash(
- { dashApi, defaultAddr, insightBaseUrl, noReserve },
- args,
-) {
- let [addr, name] = await mustGetAddr({ defaultAddr }, args);
- await initCrowdNode(insightBaseUrl);
- let hotwallet = CrowdNode.main.hotwallet;
- let state = await getCrowdNodeStatus({ addr, hotwallet });
- let balanceInfo = await dashApi.getInstantBalance(addr);
-
- if (!state.status?.accept) {
- console.error(`no account for address ${addr}`);
- process.exit(1);
- return;
- }
-
- // this would allow for at least 2 withdrawals costing (21000 + 1000)
- let reserve = 50000;
- let reserveDash = toDash(reserve);
- if (!noReserve) {
- console.info(
- `reserving ${reserve} (Đ${reserveDash}) for withdrawals (--no-reserve to disable)`,
- );
- } else {
- reserve = 0;
- }
-
- // TODO if unconfirmed, check utxos instead
-
- // deposit what the user asks, or all that we have,
- // or all that the user deposits - but at least 2x the reserve
- let desiredAmountDash = parseFloat(args.shift() || "0");
- let desiredAmountDuff = Math.round(desiredAmountDash * DUFFS);
- let effectiveAmount = desiredAmountDuff;
- if (!effectiveAmount) {
- effectiveAmount = balanceInfo.balanceSat - reserve;
- }
- let needed = Math.max(reserve * 2, effectiveAmount + reserve);
-
- if (balanceInfo.balanceSat < needed) {
- let ask = 0;
- if (desiredAmountDuff) {
- ask = desiredAmountDuff + reserve + -balanceInfo.balanceSat;
- }
- await collectDeposit(insightBaseUrl, addr, ask);
- balanceInfo = await dashApi.getInstantBalance(addr);
- if (balanceInfo.balanceSat < needed) {
- let balanceDash = toDash(balanceInfo.balanceSat);
- console.error(
- `Balance is still too small: ${balanceInfo.balanceSat} (Đ${balanceDash})`,
- );
- process.exit(1);
- return;
- }
- }
- if (!desiredAmountDuff) {
- effectiveAmount = balanceInfo.balanceSat - reserve;
- }
-
- let effectiveDash = toDash(effectiveAmount);
- console.info(
- `Initiating deposit of ${effectiveAmount} (Đ${effectiveDash})...`,
- );
-
- let wif = await maybeReadKeyPaths(name, { wif: true });
-
- await CrowdNode.deposit(wif, hotwallet, effectiveAmount);
- state.deposit = DONE;
- console.info(` ${state.deposit} DepositReceived`);
- return;
-}
-
-/**
- * @param {Object} opts
- * @param {any} opts.dashApi - TODO
- * @param {String} opts.defaultAddr
- * @param {Boolean} opts.forceGenerate
- * @param {String} opts.insightBaseUrl
- * @param {any} opts.insightApi
- * @param {Boolean} opts.noReserve
- * @param {Array} args
- */
-async function stakeDash(
- {
- dashApi,
- defaultAddr,
- forceGenerate,
- insightApi,
- insightBaseUrl,
- noReserve,
- },
- args,
-) {
- let err = await Fs.access(args[0]).catch(Object);
- let addr;
- if (!err) {
- let keypath = args.shift() || "";
- addr = await importKey({ keypath });
- } else if (forceGenerate) {
- addr = await generateKey({ defaultKey: defaultAddr }, []);
- } else {
- addr = await initKeystore({ defaultAddr });
- }
-
- if (!addr) {
- let [_addr] = await mustGetAddr({ defaultAddr }, args);
- addr = _addr;
- }
-
- let extra = feeEstimate;
- console.info("Checking CrowdNode account... ");
- await CrowdNode.init({
- baseUrl: "https://app.crowdnode.io",
- insightBaseUrl,
- });
- let hotwallet = CrowdNode.main.hotwallet;
- let state = await getCrowdNodeStatus({ addr, hotwallet });
-
- if (!state.status?.accept) {
- if (!state.status?.signup) {
- let signUpDeposit = signupOnly + feeEstimate;
- console.info(
- ` ${TODO} SignUpForApi deposit is ${signupOnly} (+ tx fee)`,
- );
- extra += signUpDeposit;
- } else {
- console.info(` ${DONE} SignUpForApi complete`);
- }
- let acceptDeposit = acceptOnly + feeEstimate;
- console.info(` ${TODO} AcceptTerms deposit is ${acceptOnly} (+ tx fee)`);
- extra += acceptDeposit;
- }
-
- let desiredAmountDash = args.shift() || "0.5";
- let effectiveDuff = toDuff(desiredAmountDash);
- effectiveDuff += extra;
-
- let balanceInfo = await dashApi.getInstantBalance(addr);
- effectiveDuff -= balanceInfo.balanceSat;
-
- if (effectiveDuff > 0) {
- effectiveDuff = roundDuff(effectiveDuff, 3);
- let effectiveDash = toDash(effectiveDuff);
- await plainLoadAddr({
- addr,
- effectiveDash,
- effectiveDuff,
- insightBaseUrl,
- });
- }
-
- if (!state.status?.accept) {
- if (!state.status?.signup) {
- await sendSignup({ dashApi, defaultAddr: addr, insightBaseUrl }, [addr]);
- }
- await acceptTerms({ dashApi, defaultAddr: addr, insightBaseUrl }, [addr]);
- }
-
- await depositDash(
- { dashApi, defaultAddr: addr, insightBaseUrl, noReserve },
- [addr].concat(args),
- );
-
- await checkBalance({ addr, dashApi });
-}
-
-/**
- * @param {Object} opts
- * @param {any} opts.dashApi - TODO
- * @param {String} opts.defaultAddr
- * @param {String} opts.insightBaseUrl
- * @param {Array} args
- */
-async function withdrawalDash({ dashApi, defaultAddr, insightBaseUrl }, args) {
- let [addr] = await mustGetAddr({ defaultAddr }, args);
- await initCrowdNode(insightBaseUrl);
- let hotwallet = CrowdNode.main.hotwallet;
- let state = await getCrowdNodeStatus({ addr, hotwallet });
-
- if (!state.status?.accept) {
- console.error(`no account for address ${addr}`);
- process.exit(1);
- return;
- }
-
- 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);
-
- 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 wifname = await findWif(addr);
- let filepath = Path.join(keysDir, wifname);
- let wif = await maybeReadKeyFile(filepath);
- let paid = await CrowdNode.withdrawal(wif, hotwallet, permil);
- //let paidFloat = (paid.satoshis / DUFFS).toFixed(8);
- //let paidInt = paid.satoshis.toString().padStart(9, "0");
- console.info(`API Response: ${paid.api}`);
- return;
-}
-
-/**
- * @param {String} insightBaseUrl
- */
-async function initCrowdNode(insightBaseUrl) {
- if (CrowdNode.main.hotwallet) {
- return;
- }
- process.stdout.write("Checking CrowdNode API... ");
- await CrowdNode.init({
- baseUrl: "https://app.crowdnode.io",
- insightBaseUrl,
- });
- console.info(`(hotwallet ${CrowdNode.main.hotwallet})`);
-}
-
-/**
- * @param {Object} opts
- * @param {String} opts.addr
- * @param {String} opts.hotwallet
- */
-async function getCrowdNodeStatus({ addr, hotwallet }) {
- let state = {
- signup: TODO,
- accept: TODO,
- deposit: TODO,
- status: {
- signup: 0,
- accept: 0,
- deposit: 0,
- },
- };
-
- //@ts-ignore - TODO why warnings?
- let status = await CrowdNode.status(addr, hotwallet);
- if (status) {
- state.status = status;
- }
- if (state.status?.signup) {
- state.signup = DONE;
- }
- if (state.status?.accept) {
- state.accept = DONE;
- }
- if (state.status?.deposit) {
- state.deposit = DONE;
- }
- return state;
-}
-
-/**
- * @param {Null} _
- * @param {Array} args
- */
-async function setDefault(_, args) {
- let addr = args.shift() || "";
-
- let keyname = await findWif(addr);
- if (!keyname) {
- console.error(`no key matches '${addr}'`);
- process.exit(1);
- return;
- }
-
- let filepath = Path.join(keysDir, keyname);
- let wif = await maybeReadKeyFile(filepath);
- let pk = new Dashcore.PrivateKey(wif);
- let pub = pk.toAddress().toString();
-
- console.info("set", defaultWifPath, pub);
- await Fs.writeFile(defaultWifPath, pub, "utf8");
-}
-
-/**
- * @param {String} defaultAddr
- * @param {Object} [opts]
- * @param {Boolean} opts.wif
- */
-async function mustGetDefaultWif(defaultAddr, opts) {
- let defaultWif = "";
- if (defaultAddr) {
- let keyfile = Path.join(keysDir, `${defaultAddr}.wif`);
- let raw = await maybeReadKeyFileRaw(keyfile, opts);
- // misnomering wif here a bit
- defaultWif = raw?.wif || raw?.addr || "";
- }
- if (defaultWif && !shownDefault) {
- shownDefault = true;
- debug(`Selected default staking key ${defaultAddr}`);
- return defaultWif;
- }
-
- console.error();
- console.error(`Error: no default staking key selected.`);
- console.error();
- console.error(`Select a different address:`);
- console.error(` crowdnode list`);
- console.error(` crowdnode use `);
- console.error(``);
- console.error(`Or create a new staking key:`);
- console.error(` crowdnode generate`);
- console.error();
- process.exit(1);
- return "";
-}
-
-
-
-/**
- * @param {String} addr - Base58Check pubKeyHash address
- * @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=${dashAmount}`;
- }
-
- let dashQr = Qr.ascii(dashUri, { indent: 4, size: "mini" });
- let addrPad = Math.max(0, Math.ceil((qrWidth - dashUri.length) / 2));
-
- console.info(dashQr);
- console.info();
- console.info(" ".repeat(addrPad) + dashUri);
-}
-
-/**
- * @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)`);
- }
- 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;
- }
-
- /*
- let pk = new Dashcore.PrivateKey(wif);
- let pub = pk.toAddress().toString();
- if (`${pub}.wif` !== wifname) {
- // sanity check
- warns.push({
- node: wifname,
- error: new Error(
- `computed pubkey '${pub}' of WIF does not match filename '${wifname}'`,
- ),
- });
- return;
- }
- */
-
- process.stdout.write(`| ${addr} |`);
-
- let balanceInfo = await dashApi.getInstantBalance(addr);
- let balanceDASH = toDASH(balanceInfo.balanceSat);
-
- let crowdNodeBalance = await CrowdNode.http.GetBalance(addr);
- if (!crowdNodeBalance.TotalBalance) {
- crowdNodeBalance.TotalBalance = 0;
- crowdNodeBalance.TotalDividend = 0;
- }
- let crowdNodeDuffNum = toDuff(crowdNodeBalance.TotalBalance);
- let crowdNodeDASH = toDASH(crowdNodeDuffNum);
-
- let crowdNodeDivNum = toDuff(crowdNodeBalance.TotalDividend);
- let crowdNodeDivDASH = toDASH(crowdNodeDivNum);
- process.stdout.write(
- ` ${balanceDASH} | ${crowdNodeDASH} | ${crowdNodeDivDASH} |`,
- );
-
- totals.key += balanceInfo.balanceSat;
- totals.dividend += crowdNodeBalance.TotalDividend;
- totals.stake += crowdNodeBalance.TotalBalance;
-
- console.info();
- }, Promise.resolve());
- 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:`);
- warns.forEach(function (warn) {
- console.warn(`${warn.node}: ${warn.error.message}`);
- });
- console.warn(``);
- }
-}
-
-
-
-/**
- * @param {Object} opts
- * @param {String} opts.defaultAddr
- * @param {any} opts.dashApi - TODO
- * @param {Array} args
- */
-async function getBalance({ dashApi, defaultAddr }, args) {
- let [addr] = await mustGetAddr({ defaultAddr }, args);
- await checkBalance({ addr, dashApi });
- //let balanceInfo = await checkBalance({ addr, dashApi });
- //console.info(balanceInfo);
- return;
-}
-
-/**
- * @param {Object} opts
- * @param {any} opts.dashApi - TODO
- * @param {String} opts.defaultAddr
- * @param {Boolean} opts.forceConfirm
- * @param {String} opts.insightBaseUrl
- * @param {any} opts.insightApi
- * @param {Array} args
- */
-// ex: node ./bin/crowdnode.js transfer ./priv.wif 'pub' 0.01
-async function transferBalance(
- { dashApi, defaultAddr, forceConfirm, insightBaseUrl, insightApi },
- args,
-) {
- let wif = await mustGetWif({ defaultAddr }, args);
-
- let keyname = args.shift() || "";
- let newAddr = await wifFileToAddr(keyname);
- let dashAmount = parseFloat(args.shift() || "0");
- let duffAmount = Math.round(dashAmount * DUFFS);
- let tx;
- if (duffAmount) {
- tx = await dashApi.createPayment(wif, newAddr, duffAmount);
- } else {
- tx = await dashApi.createBalanceTransfer(wif, newAddr);
- }
- if (duffAmount) {
- let dashAmountStr = toDash(duffAmount);
- console.info(
- `Transferring ${duffAmount} (Đ${dashAmountStr}) to ${newAddr}...`,
- );
- } else {
- console.info(`Transferring balance to ${newAddr}...`);
- }
- await insightApi.instantSend(tx);
- console.info(`Queued...`);
- setTimeout(function () {
- // TODO take a cleaner approach
- // (waitForVout needs a reasonable timeout)
- console.error(`Error: Transfer did not complete.`);
- if (forceConfirm) {
- console.error(`(using --unconfirmed may lead to rejected double spends)`);
- }
- process.exit(1);
- }, 30 * 1000);
- await Ws.waitForVout(insightBaseUrl, newAddr, 0);
- console.info(`Accepted!`);
- return;
-}
-
-<<<<<<< Updated upstream
- // State 1: not initialized, what does the user want?
- if (needsInit) {
- for (;;) {
- let no;
- if (!_force) {
- no = await Prompt.prompt(
- "Would you like to encrypt your keys with a passphrase? [Y/n]: ",
- );
- }
-=======
-/**
- * @param {Object} opts
- * @param {String} opts.addr
- * @param {any} opts.dashApi - TODO
- */
-async function checkBalance({ addr, dashApi }) {
- // deposit if balance is over 100,000 (0.00100000)
- console.info("Checking balance... ");
- let balanceInfo = await dashApi.getInstantBalance(addr);
- let balanceDASH = toDASH(balanceInfo.balanceSat);
->>>>>>> Stashed changes
-
- let crowdNodeBalance = await CrowdNode.http.GetBalance(addr);
- if (!crowdNodeBalance.TotalBalance) {
- crowdNodeBalance.TotalBalance = 0;
- crowdNodeBalance.TotalDividend = 0;
- }
-
- let crowdNodeDuffNum = toDuff(crowdNodeBalance.TotalBalance);
- let crowdNodeDASH = toDASH(crowdNodeDuffNum);
-
- let crowdNodeDivNum = toDuff(crowdNodeBalance.TotalDividend);
- let crowdNodeDASHDiv = toDASH(crowdNodeDivNum);
-
- console.info(`Key: ${balanceDASH}`);
- console.info(`CrowdNode: ${crowdNodeDASH}`);
- console.info(`Dividends: ${crowdNodeDASHDiv}`);
- console.info();
- /*
- let balanceInfo = await insightApi.getBalance(pub);
- if (balanceInfo.unconfirmedBalanceSat || balanceInfo.unconfirmedAppearances) {
- if (!forceConfirm) {
- console.error(
- `Error: This address has pending transactions. Please try again in 1-2 minutes or use --unconfirmed.`,
- );
- console.error(balanceInfo);
- if ("status" !== subcommand) {
- process.exit(1);
- return;
- }
- }
- }
- */
- return balanceInfo;
-}
-
-/**
- * @param {Object} opts
- * @param {String} opts.defaultAddr
- * @param {Array} args
- * @returns {Promise<[String, String]>}
- */
-async function mustGetAddr({ defaultAddr }, args) {
- let name = args.shift() ?? "";
- if (34 === name.length) {
- // looks like addr already
- // TODO make function for addr-lookin' check
- return [name, name];
- }
-
- let addr = await maybeReadKeyPaths(name, { wif: false });
- if (addr) {
- if (34 === addr.length) {
- return [addr, name];
- }
- //let pk = new Dashcore.PrivateKey(wif);
- //let addr = pk.toAddress().toString();
- return [addr, name];
- }
-
- let isNum = !isNaN(parseFloat(name));
- if (isNum) {
- args.unshift(name);
- name = "";
- }
-
- if (name) {
- console.error();
- console.error(`could not read '${name}' in ./ or match in ${keysDirRel}/.`);
- console.error();
- process.exit(1);
- return ["", name];
- }
-
- addr = await mustGetDefaultWif(defaultAddr, { wif: false });
-
- // TODO we don't need defaultAddr, right? because it could be old?
- return [addr, addr];
-}
-
-/**
- * @param {Object} opts
- * @param {String} opts.defaultAddr
- * @param {Array} args
- */
-async function mustGetWif({ defaultAddr }, args) {
- let name = args.shift() ?? "";
-
- let wif = await maybeReadKeyPaths(name, { wif: true });
- if (wif) {
- return wif;
- }
-
- let isNum = !isNaN(parseFloat(name));
- if (isNum) {
- args.unshift(name);
- name = "";
- }
-
- if (name) {
- console.error();
- console.error(
- `'${name}' does not match a staking key in ./ or ${keysDirRel}/`,
- );
- console.error();
- process.exit(1);
- return "";
- }
-
- wif = await mustGetDefaultWif(defaultAddr);
-
- return wif;
-}
-
-/**
- * @param {Object} opts
- * @param {String} opts.defaultAddr
- */
-async function initKeystore({ defaultAddr }) {
- // if we have no keys, make one
- let wifnames = await listManagedKeynames();
- if (!wifnames.length) {
- return await generateKey({ defaultKey: defaultAddr }, []);
- }
- // if we have no passphrase, ask about it
- await initPassphrase();
- return defaultAddr || wifnames[0];
-}
-
-/**
- * @param {String} name
- * @param {Object} opts
- * @param {Boolean} opts.wif
- * @returns {Promise} - wif
- */
-async function maybeReadKeyPaths(name, opts) {
- let privKey = "";
-
- // prefix match in .../keys/
- let wifname = await findWif(name);
- if (!wifname) {
- return "";
- }
-
- if (false === opts.wif) {
- return wifname.slice(0, -".wif".length);
- }
-
- let filepath = Path.join(keysDir, wifname);
- privKey = await maybeReadKeyFile(filepath);
- if (!privKey) {
- // local in ./
- privKey = await maybeReadKeyFile(name);
- }
-
- return privKey;
-}
-
-// Subcommands
-
-/**
- * @param {Object} psuedoState
- * @param {String} psuedoState.defaultKey - addr name of default key
- * @param {Boolean} [psuedoState.plainText] - don't encrypt
- * @param {Array} args
- */
-async function generateKey({ defaultKey, plainText }, args) {
- let name = args.shift();
- //@ts-ignore - TODO submit JSDoc PR for Dashcore
- let pk = new Dashcore.PrivateKey();
-
- let addr = pk.toAddress().toString();
- let plainWif = pk.toWIF();
-
- let wif = plainWif;
- if (!plainText) {
- wif = await maybeEncrypt(plainWif);
- }
-
- let filename = `~/${configdir}/keys/${addr}.wif`;
- let filepath = Path.join(`${keysDir}/${addr}.wif`);
- let note = "";
- if (name) {
- filename = name;
- filepath = name;
- note = `\n(for pubkey address ${addr})`;
- let err = await Fs.access(filepath).catch(Object);
- if (!err) {
- // TODO
- console.info(`'${filepath}' already exists (will not overwrite)`);
- process.exit(0);
- return;
- }
- }
-
- await Fs.writeFile(filepath, wif, "utf8");
- if (!name && !defaultKey) {
- await Fs.writeFile(defaultWifPath, addr, "utf8");
- }
-
- console.info(``);
- console.info(`Generated ${filename} ${note}`);
- console.info(``);
- return addr;
-}
-
-async function initPassphrase() {
- let needsInit = false;
- let shadow = await Fs.readFile(shadowPath, "utf8").catch(
- emptyStringOnErrEnoent,
- );
- if (!shadow) {
- needsInit = true;
- }
- if (needsInit) {
- await cmds.getPassphrase({}, []);
- }
-}
-
-/**
- * @param {Object} state
- * @param {Boolean} [state._askPreviousPassphrase] - don't ask for passphrase again
- * @param {Array} args
- */
-async function setPassphrase({ _askPreviousPassphrase }, args) {
- let result = {
- passphrase: "",
- changed: false,
- };
- let date = getFsDateString();
-
- // get the old passphrase
- if (false !== _askPreviousPassphrase) {
- // TODO should contain the shadow?
- await cmds.getPassphrase({ _rotatePassphrase: true }, []);
- }
-
- // get the new passphrase
- let newPassphrase = await promptPassphrase();
- let curShadow = await Fs.readFile(shadowPath, "utf8").catch(
- emptyStringOnErrEnoent,
- );
-
- let newShadow = await Cipher.shadowPassphrase(newPassphrase);
- await Fs.writeFile(shadowPath, newShadow, "utf8");
-
- let rawKeys = await readAllKeys();
- let encAddrs = rawKeys
- .map(function (raw) {
- if (raw.encrypted) {
- return raw.addr;
- }
- })
- .filter(Boolean);
-
- // backup all currently encrypted files
- //@ts-ignore
- if (encAddrs.length) {
- let filepath = Path.join(HOME, `${configdir}/keys.${date}.bak`);
- console.info(``);
- console.info(`Backing up previous (encrypted) keys:`);
- encAddrs.unshift(`SHADOW:${curShadow}`);
- await Fs.writeFile(filepath, encAddrs.join("\n") + "\n", "utf8");
- console.info(` ~/${configdir}/keys.${date}.bak`);
- console.info(``);
- }
- cmds._setPassphrase(newPassphrase);
-
- await encryptAll(rawKeys, { rotateKey: true });
-
- result.passphrase = newPassphrase;
- result.changed = true;
- return result;
-}
-
-async function promptPassphrase() {
- let newPassphrase;
- for (;;) {
- newPassphrase = await Prompt.prompt("Enter (new) passphrase: ", {
- mask: true,
- });
- newPassphrase = newPassphrase.trim();
-
- let _newPassphrase = await Prompt.prompt("Enter passphrase again: ", {
- mask: true,
- });
- _newPassphrase = _newPassphrase.trim();
-
- let match = Cipher.secureCompare(newPassphrase, _newPassphrase);
- if (match) {
- break;
- }
-
- console.error("passphrases do not match");
- }
- return newPassphrase;
-}
-
-/**
- * Import and Encrypt
- * @param {Object} opts
- * @param {String} opts.keypath
- */
-async function importKey({ keypath }) {
- 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(``);
-
- return key.addr;
-}
-
-/**
- * @param {Object} opts
- * @param {Boolean} [opts._rotatePassphrase]
- * @param {Boolean} [opts._force]
- * @param {Array} args
- */
-cmds.getPassphrase = async function ({ _rotatePassphrase, _force }, args) {
- let result = {
- passphrase: "",
- changed: false,
- };
- /*
- if (!_rotatePassphrase) {
- let cachedphrase = cmds._getPassphrase();
- if (cachedphrase) {
- return cachedphrase;
- }
- }
- */
-
- // 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)
- // 3. encrypted shadow file (initialized, requires passphrase)
- let needsInit = false;
- let shadow = await Fs.readFile(shadowPath, "utf8").catch(
- emptyStringOnErrEnoent,
- );
- if (!shadow) {
- needsInit = true;
- } else if (NO_SHADOW === shadow && _force) {
- needsInit = true;
- }
-
- // State 1: not initialized, what does the user want?
- if (needsInit) {
- for (;;) {
- let no;
- if (!_force) {
- no = await Prompt.prompt(
- "Would you like to set an encryption passphrase? [Y/n]: ",
- );
- }
-
- // Set a passphrase and create shadow file
- if (!no || ["yes", "y"].includes(no.toLowerCase())) {
- result = await setPassphrase({ _askPreviousPassphrase: false }, args);
- cmds._setPassphrase(result.passphrase);
- return result;
- }
-
- // ask user again
- if (!["no", "n"].includes(no.toLowerCase())) {
- continue;
- }
-
- // No passphrase, create a NONE shadow file
- await Fs.writeFile(shadowPath, NO_SHADOW, "utf8");
- return result;
- }
-<<<<<<< Updated upstream
- let crowdNodeDuffNum = toDuff(crowdNodeBalance.TotalBalance);
- let crowdNodeDASH = toDASH(crowdNodeDuffNum);
-
- let crowdNodeDivNum = toDuff(crowdNodeBalance.TotalDividend);
- let crowdNodeDivDASH = toDASH(crowdNodeDivNum);
- process.stdout.write(
- ` ${balanceDASH} | ${crowdNodeDASH} | ${crowdNodeDivDASH} |`,
- );
-
- totals.key += balanceInfo.balanceSat;
- totals.dividend += crowdNodeBalance.TotalDividend;
- totals.stake += crowdNodeBalance.TotalBalance;
-
- console.info();
- }, Promise.resolve());
- 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.keyDash} | ${totals.stakeDash} | ${totals.dividendDash} |`,
- );
- debug(``);
-
- if (warns.length) {
- console.warn(`Warnings:`);
- warns.forEach(function (warn) {
- console.warn(`${warn.node}: ${warn.error.message}`);
- });
- console.warn(``);
- }
-}
-
-/**
- * @param {String} name - ex: Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.wif.enc
- */
-function isNamedLikeKey(name) {
- // TODO distinguish with .enc extension?
- let hasGoodLength = 34 + 4 === name.length || 34 + 4 + 4 === name.length;
- let knownExt = name.endsWith(".wif") || name.endsWith(".wif.enc");
- let isTmp = name.startsWith(".") || name.startsWith("_");
- return hasGoodLength && knownExt && !isTmp;
-}
-
-/**
- * @param {Object} opts
- * @param {any} opts.dashApi - TODO
- * @param {String} opts.addr
- * @param {String} opts.filepath
- * @param {String} opts.insightBaseUrl
- * @param {Array} args
- */
-async function removeKey({ addr, dashApi, filepath, insightBaseUrl }, args) {
- let balanceInfo = await dashApi.getInstantBalance(addr);
-
- let balanceDash = toDash(balanceInfo.balanceSat);
- if (balanceInfo.balanceSat) {
- console.error(``);
- console.error(`Error: ${addr}`);
- console.error(
- ` still has a balance of ${balanceInfo.balanceSat} (Đ${balanceDash})`,
- );
- console.error(` (transfer to another address before deleting)`);
- console.error(``);
- process.exit(1);
- return;
- }
-
- await initCrowdNode(insightBaseUrl);
- let crowdNodeBalance = await CrowdNode.http.GetBalance(addr);
- if (!crowdNodeBalance) {
- // may be janky if not registered
- crowdNodeBalance = {};
- }
- if (!crowdNodeBalance.TotalBalance) {
- crowdNodeBalance.TotalBalance = 0;
- }
- let crowdNodeDash = toDash(crowdNodeBalance.TotalBalance);
- if (crowdNodeBalance.TotalBalance) {
- console.error(``);
- console.error(`Error: ${addr}`);
- console.error(
- ` still staking ${crowdNodeBalance.TotalBalance} (Đ${crowdNodeDash}) on CrowdNode`,
- );
- console.error(
- ` (withdraw 100.0 and transfer to another address before deleting)`,
- );
- console.error(``);
- process.exit(1);
- return;
- }
-
- let wifname = await findWif(addr);
- let fullpath = Path.join(keysDir, wifname);
- let wif = await maybeReadKeyPaths(filepath, { wif: true });
-
- await Fs.unlink(fullpath).catch(function (err) {
- console.error(`could not remove ${filepath}: ${err.message}`);
- process.exit(1);
- });
-
- let wifnames = await listManagedKeynames();
- console.info(``);
- console.info(`No balances found. Removing ${filepath}.`);
- console.info(``);
- console.info(`Backup (just in case):`);
- console.info(` ${wif}`);
- console.info(``);
- if (!wifnames.length) {
- console.info(`No keys left.`);
- console.info(``);
- } else {
- let newAddr = wifnames[0];
- debug(`Selected ${newAddr} as new default staking key.`);
- await Fs.writeFile(defaultWifPath, addr.replace(".wif", ""), "utf8");
- console.info(``);
-=======
->>>>>>> Stashed changes
- }
-
- // State 2: shadow already initialized to empty
- // (user doesn't want a passphrase)
- if (!shadow) {
- cmds._setPassphrase("");
- return result;
- }
-
- // State 3: passphrase & shadow already in use
- for (;;) {
- let prompt = `Enter passphrase: `;
- if (_rotatePassphrase) {
- prompt = `Enter (current) passphrase: `;
- }
- result.passphrase = await Prompt.prompt(prompt, {
- mask: true,
- });
- result.passphrase = result.passphrase.trim();
- if (!result.passphrase || "q" === result.passphrase) {
- console.error("cancel: no passphrase");
- process.exit(1);
- return result;
- }
-
- let match = await Cipher.checkPassphrase(result.passphrase, shadow);
- if (match) {
- cmds._setPassphrase(result.passphrase);
- console.info(``);
- return result;
- }
-
- console.error("incorrect passphrase");
- }
-
- throw new Error("SANITY FAIL: unreachable return");
-};
-
-cmds._getPassphrase = function () {
- return "";
-};
-
-/**
- * @param {String} passphrase
- */
-cmds._setPassphrase = function (passphrase) {
- // Look Ma! A private variable!
- cmds._getPassphrase = function () {
- return passphrase;
- };
-};
-
-/**
- * Encrypt ALL-the-things!
- * @param {Object} [opts]
- * @param {Boolean} opts.rotateKey
- * @param {Array?} rawKeys
- */
-async function encryptAll(rawKeys, opts) {
- if (!rawKeys) {
- rawKeys = await readAllKeys();
- }
- let date = getFsDateString();
-
- let passphrase = cmds._getPassphrase();
- if (!passphrase) {
- let result = await cmds.getPassphrase({ _force: true }, []);
- if (result.changed) {
- // encryptAll was already called on rotation
- return;
- }
- passphrase = result.passphrase;
- }
-
- console.info(`Encrypting...`);
- console.info(``);
- await rawKeys.reduce(async function (promise, key) {
- await promise;
-
- if (key.encrypted && !opts?.rotateKey) {
- console.info(`🙈 ${key.addr} [already encrypted]`);
- return;
- }
- let encWif = await maybeEncrypt(key.wif, { force: true });
- await safeSave(
- Path.join(keysDir, `${key.addr}.wif`),
- encWif,
- Path.join(keysDir, `${key.addr}.${date}.bak`),
- );
- console.info(`🔑 ${key.addr}`);
- }, Promise.resolve());
- console.info(``);
- console.info(`Done 🔐`);
- console.info(``);
-}
-
-/**
- * @param {String} encWif
- */
-async function decrypt(encWif) {
- let passphrase = cmds._getPassphrase();
- if (!passphrase) {
- let result = await cmds.getPassphrase({}, []);
- passphrase = result.passphrase;
- // we don't return just in case they're setting a passphrase to
- // decrypt a previously encrypted file (i.e. for recovery from elsewhere)
- }
- let key128 = await Cipher.deriveKey(passphrase);
- let cipher = Cipher.create(key128);
-
- return cipher.decrypt(encWif);
-}
-
-/**
- * Decrypt ALL-the-things!
- * @param {Array?} rawKeys
- */
-async function decryptAll(rawKeys) {
- if (!rawKeys) {
- rawKeys = await readAllKeys();
- }
- let date = getFsDateString();
-
- console.info(``);
- console.info(`Decrypting...`);
- console.info(``);
-<<<<<<< Updated upstream
- console.info(
- `Send Đ${effectiveDash} to your staking key via the QR above, or its address:`,
- );
- console.info(`${addr}`);
- console.info(
- `(this key will be used to fund and control your CrowdNode account)`,
- );
-=======
- await rawKeys.reduce(async function (promise, key) {
- await promise;
-
- if (!key.encrypted) {
- console.info(`📖 ${key.addr} [already decrypted]`);
- return;
- }
- await safeSave(
- Path.join(keysDir, `${key.addr}.wif`),
- key.wif,
- Path.join(keysDir, `${key.addr}.${date}.bak`),
- );
- console.info(`🔓 ${key.addr}`);
- }, Promise.resolve());
->>>>>>> Stashed changes
- console.info(``);
- console.info(`Done ${DONE}`);
- console.info(``);
-}
-
-function getFsDateString() {
- // YYYY-MM-DD_hh-mm_ss
- let date = new Date()
- .toISOString()
- .replace(/:/g, ".")
- .replace(/T/, "_")
- .replace(/\.\d{3}.*/, "");
- return date;
-}
-
-/**
- * @param {String} filepath
- * @param {String} wif
- * @param {String} bakpath
- */
-async function safeSave(filepath, wif, bakpath) {
- let tmpPath = `${bakpath}.tmp`;
- await Fs.writeFile(tmpPath, wif, "utf8");
- let err = await Fs.access(filepath).catch(Object);
- if (!err) {
- await Fs.rename(filepath, bakpath);
- }
- await Fs.rename(tmpPath, filepath);
- if (!err) {
- await Fs.unlink(bakpath);
- }
-}
-
-/**
- * @typedef {Object} RawKey
- * @property {String} addr
- * @property {Boolean} encrypted
- * @property {String} wif
- */
-<<<<<<< Updated upstream
-// ex: node ./bin/crowdnode.js transfer Xxxxx 'pub' 0.01
-async function transferBalance(
- { dashApi, defaultAddr, forceConfirm, insightBaseUrl, insightApi },
- args,
-) {
- /** @type Array */
- let getAddrArgs = [];
-
- // There are two cases in which we could have only 2 arguments,
- // and the first argument could be an address inside or outside
- // of the wallet.
- //
- // Ex:
- // crowdnode transfer {source} {dest}
- // crowdnode transfer {source} {dest} {amount}
- // crowdnode transfer {dest} {amount}
- // crowdnode transfer {dest}
- //
- // To disambiguate, we check if the second argument is an amount.
- if (3 === args.length) {
- getAddrArgs = args;
- } else if (2 === args.length) {
- let maybeAmount = parseFloat(args[1]);
- let isAddr = isNaN(maybeAmount);
- if (isAddr) {
- getAddrArgs = args;
- }
- }
- let wif = await mustGetWif({ defaultAddr }, getAddrArgs);
-=======
->>>>>>> Stashed changes
-
-/**
- * @throws
- */
-async function readAllKeys() {
- let wifnames = await listManagedKeynames();
-
- /** @type Array */
- let keys = [];
- await wifnames.reduce(async function (promise, wifname) {
- await promise;
-
- let keypath = Path.join(keysDir, wifname);
- let key = await maybeReadKeyFileRaw(keypath);
- if (!key?.wif) {
- return;
- }
-
- if (`${key.addr}.wif` !== wifname) {
- throw new Error(
- `computed pubkey '${key.addr}' of WIF does not match filename '${keypath}'`,
- );
- }
-
- keys.push(key);
- }, Promise.resolve());
-
- return keys;
-}
-
-/**
- * @param {String} filepath
- * @param {Object} [opts]
- * @param {Boolean} opts.wif
- * @returns {Promise}
- */
-async function maybeReadKeyFile(filepath, opts) {
- let key = await maybeReadKeyFileRaw(filepath, opts);
- if (false === opts?.wif) {
- return key?.addr || "";
- }
- return key?.wif || "";
-}
-
-/**
- * @param {String} filepath
- * @param {Object} [opts]
- * @param {Boolean} opts.wif
- * @returns {Promise}
- */
-<<<<<<< Updated upstream
-async function sendSignup({ dashApi, defaultAddr, insightBaseUrl }, args) {
- let [addr, name] = await mustGetAddr({ defaultAddr }, args);
- await initCrowdNode(insightBaseUrl);
- let hotwallet = CrowdNode.main.hotwallet;
- let state = await getCrowdNodeStatus({ addr, hotwallet });
- let balanceInfo = await dashApi.getInstantBalance(addr);
-
- if (state.status?.signup) {
- console.info(`${addr} is already signed up. Here's the account status:`);
- console.info(` ${state.signup} SignUpForApi`);
- console.info(` ${state.accept} AcceptTerms`);
- console.info(` ${state.deposit} DepositReceived`);
- return;
-=======
-async function maybeReadKeyFileRaw(filepath, opts) {
- let privKey = await Fs.readFile(filepath, "utf8").catch(
- emptyStringOnErrEnoent,
- );
- privKey = privKey.trim();
- if (!privKey) {
- return null;
->>>>>>> Stashed changes
- }
-
- let encrypted = false;
- if (privKey.includes(":")) {
- encrypted = true;
- try {
- if (false !== opts?.wif) {
- privKey = await decrypt(privKey);
- }
- } catch (err) {
- //@ts-ignore
- console.error(err.message);
- console.error(`passphrase does not match for key ${filepath}`);
- process.exit(1);
- }
- }
- if (false === opts?.wif) {
- return {
- addr: Path.basename(filepath, ".wif"),
- encrypted: encrypted,
- wif: "",
- };
- }
-
- let pk = new Dashcore.PrivateKey(privKey);
- let pub = pk.toAddress().toString();
-
- return {
- addr: pub,
- encrypted: encrypted,
- wif: privKey,
- };
-}
-
-// tuple example {Promise<[String, Boolean]>}
-/**
- * @param {Object} [opts]
- * @param {Boolean} [opts.force]
- * @param {String} plainWif
- */
-async function maybeEncrypt(plainWif, opts) {
- let passphrase = cmds._getPassphrase();
- if (!passphrase) {
- let result = await cmds.getPassphrase({}, []);
- passphrase = result.passphrase;
- }
- if (!passphrase) {
- if (opts?.force) {
- throw new Error(`no passphrase with which to encrypt file`);
- }
- return plainWif;
- }
-
- let key128 = await Cipher.deriveKey(passphrase);
- let cipher = Cipher.create(key128);
- return cipher.encrypt(plainWif);
-}
-
-// TODO option to specify config dir
-
-/**
- * @param {Object} opts
- * @param {any} opts.dashApi - TODO
- * @param {String} opts.defaultAddr
- * @param {Array} 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.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 {String} name - ex: Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.wif.enc
- */
-function isNamedLikeKey(name) {
- // TODO distinguish with .enc extension?
- let hasGoodLength = 34 + 4 === name.length || 34 + 4 + 4 === name.length;
- let knownExt = name.endsWith(".wif") || name.endsWith(".wif.enc");
- let isTmp = name.startsWith(".") || name.startsWith("_");
- return hasGoodLength && knownExt && !isTmp;
-}
-
-/**
- * @param {Object} opts
- * @param {any} opts.dashApi - TODO
- * @param {String} opts.addr
- * @param {String} opts.filepath
- * @param {String} opts.insightBaseUrl
- * @param {Array} args
- */
-async function removeKey({ addr, dashApi, filepath, insightBaseUrl }, args) {
- let balanceInfo = await dashApi.getInstantBalance(addr);
-
- let balanceDash = toDash(balanceInfo.balanceSat);
- if (balanceInfo.balanceSat) {
- console.error(``);
- console.error(`Error: ${addr}`);
- console.error(
- ` still has a balance of ${balanceInfo.balanceSat} (Đ${balanceDash})`,
- );
- console.error(` (transfer to another address before deleting)`);
- console.error(``);
- process.exit(1);
- return;
- }
-
- await initCrowdNode(insightBaseUrl);
- let crowdNodeBalance = await CrowdNode.http.GetBalance(addr);
- if (!crowdNodeBalance) {
- // may be janky if not registered
- crowdNodeBalance = {};
- }
- if (!crowdNodeBalance.TotalBalance) {
- crowdNodeBalance.TotalBalance = 0;
- }
- let crowdNodeDash = toDash(crowdNodeBalance.TotalBalance);
- if (crowdNodeBalance.TotalBalance) {
- console.error(``);
- console.error(`Error: ${addr}`);
- console.error(
- ` still staking ${crowdNodeBalance.TotalBalance} (Đ${crowdNodeDash}) on CrowdNode`,
- );
- console.error(
- ` (withdrawal 100.0 and transfer to another address before deleting)`,
- );
- console.error(``);
- process.exit(1);
- return;
- }
-
-<<<<<<< Updated upstream
- // this would allow for at least 2 withdraws costing (21000 + 1000)
- let reserve = 50000;
- let reserveDash = toDash(reserve);
- if (!noReserve) {
- console.info(
- `reserving ${reserve} (Đ${reserveDash}) for withdraws (--no-reserve to disable)`,
- );
-=======
- let wifname = await findWif(addr);
- let fullpath = Path.join(keysDir, wifname);
- let wif = await maybeReadKeyPaths(filepath, { wif: true });
-
- await Fs.unlink(fullpath).catch(function (err) {
- console.error(`could not remove ${filepath}: ${err.message}`);
- process.exit(1);
- });
-
- let wifnames = await listManagedKeynames();
- console.info(``);
- console.info(`No balances found. Removing ${filepath}.`);
- console.info(``);
- console.info(`Backup (just in case):`);
- console.info(` ${wif}`);
- console.info(``);
- if (!wifnames.length) {
- console.info(`No keys left.`);
- console.info(``);
->>>>>>> Stashed changes
- } else {
- let newAddr = wifnames[0];
- debug(`Selected ${newAddr} as new default staking key.`);
- await Fs.writeFile(defaultWifPath, addr.replace(".wif", ""), "utf8");
- console.info(``);
- }
-}
-
-/**
- * @param {String} pre
- */
-async function findWif(pre) {
- if (!pre) {
- return "";
- }
-
- let names = await listManagedKeynames();
- names = names.filter(function (name) {
- return name.startsWith(pre);
- });
-
- if (!names.length) {
- return "";
- }
-
- if (names.length > 1) {
- console.error(`'${pre}' is ambiguous:`, names.join(", "));
- process.exit(1);
- return "";
- }
-
- return names[0];
-}
-
-async function listManagedKeynames() {
- let nodes = await Fs.readdir(keysDir);
-
- return nodes.filter(isNamedLikeKey);
-}
-
-/**
- * @param {Object} opts
- * @param {String} opts.defaultAddr
- * @param {String} opts.insightBaseUrl
- * @param {Array} args
- */
-<<<<<<< Updated upstream
-async function withdrawDash({ dashApi, defaultAddr, insightBaseUrl }, args) {
-=======
-async function loadAddr({ defaultAddr, insightBaseUrl }, args) {
->>>>>>> Stashed changes
- let [addr] = await mustGetAddr({ defaultAddr }, args);
-
-<<<<<<< Updated upstream
- if (!state.status?.accept) {
- console.error(`no account for address ${addr}`);
- process.exit(1);
- return;
- }
-
- 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: withdraw percent must be between 0.1 and 100.0");
- process.exit(1);
- }
- let percent = parseFloat(percentStr);
-
- let permil = Math.round(percent * 10);
- if (permil <= 0 || permil > 1000) {
- console.error("Error: withdraw percent must be between 0.1 and 100.0");
- process.exit(1);
- }
-
- let realPercentStr = (permil / 10).toFixed(1);
- console.info(`Initiating withdraw of ${realPercentStr}%...`);
-
- let wifname = await findWif(addr);
- let filepath = Path.join(keysDir, wifname);
- let wif = await maybeReadKeyFile(filepath);
- let paid = await CrowdNode.withdraw(wif, hotwallet, permil);
- //let paidFloat = (paid.satoshis / DUFFS).toFixed(8);
- //let paidInt = paid.satoshis.toString().padStart(9, "0");
- console.info(`API Response: ${paid.api}`);
-=======
- let desiredAmountDash = parseFloat(args.shift() || "0");
- let desiredAmountDuff = Math.round(desiredAmountDash * DUFFS);
-
- let effectiveDuff = desiredAmountDuff;
- let effectiveDash = "";
- if (!effectiveDuff) {
- effectiveDuff = CrowdNode.stakeMinimum + signupTotal + feeEstimate;
- effectiveDuff = roundDuff(effectiveDuff, 3);
- effectiveDash = toDash(effectiveDuff);
- }
-
- await plainLoadAddr({ addr, effectiveDash, effectiveDuff, insightBaseUrl });
-
->>>>>>> Stashed changes
- return;
-}
-
-/**
- * @param {Object} opts
- * @param {String} opts.addr
- * @param {String} opts.effectiveDash
- * @param {Number} opts.effectiveDuff
- * @param {String} opts.insightBaseUrl
- */
-async function plainLoadAddr({
- addr,
- effectiveDash,
- effectiveDuff,
- insightBaseUrl,
-}) {
- console.info(``);
- showQr(addr, 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(insightBaseUrl, addr, 0);
- console.info(`Received ${payment.satoshis}`);
-}
-
-// Helpers
-
-/**
- * Convert prefix, addr, keyname, or filepath to pub addr
- * @param {String} name
- * @throws
- */
-async function wifFileToAddr(name) {
- if (34 === name.length) {
- // actually payment addr
- return name;
- }
-
- let privKey = "";
-
- let wifname = await findWif(name);
- if (wifname) {
- let filepath = Path.join(keysDir, wifname);
- privKey = await maybeReadKeyFile(filepath);
- }
- if (!privKey) {
- privKey = await maybeReadKeyFile(name);
- }
- if (!privKey) {
- throw new Error("bad file path or address");
- }
-
- let pk = new Dashcore.PrivateKey(privKey);
- let pub = pk.toPublicKey().toAddress().toString();
- return pub;
-}
-
-/**
- * @param {Error & { code: String }} err
- * @throws
- */
-function emptyStringOnErrEnoent(err) {
- if ("ENOENT" !== err.code) {
- throw err;
- }
- return "";
-}
-
-/**
- * @param {Number} duffs - ex: 00000000
- */
-function toDash(duffs) {
- return (duffs / DUFFS).toFixed(8);
-}
-
-/**
- * @param {Number} duffs - ex: 00000000
- */
-function toDASH(duffs) {
- let dash = (duffs / DUFFS).toFixed(8);
- return `Đ` + dash.padStart(12, " ");
-}
-
-/**
- * @param {String} dash - ex: 0.00000000
- */
-function toDuff(dash) {
- return Math.round(parseFloat(dash) * DUFFS);
-}
-
-/**
- * 1000 to Round to the nearest mDash
- * ex: 0.50238108 => 0.50300000
- * @param {Number} effectiveDuff
- * @param {Number} numDigits
- */
-function roundDuff(effectiveDuff, numDigits) {
- let n = Math.pow(10, numDigits);
- let effectiveDash = toDash(effectiveDuff);
- effectiveDuff = toDuff(
- (Math.ceil(parseFloat(effectiveDash) * n) / n).toString(),
- );
- return effectiveDuff;
-}
-
-/**
- * @param {Array} arr
- * @param {any} item
- */
-function removeItem(arr, item) {
- let index = arr.indexOf(item);
- if (index >= 0) {
- return arr.splice(index, 1)[0];
- }
- return null;
-}
-
-// Run
-
-main().catch(function (err) {
- console.error("Fail:");
- console.error(err.stack || err);
- process.exit(1);
-});
diff --git a/cli b/cli
index 949d278..ef8a233 160000
--- a/cli
+++ b/cli
@@ -1 +1 @@
-Subproject commit 949d278e580d7f43b703e988e9edbe34fdf441b6
+Subproject commit ef8a233106b074893ea569525cf3aaf4a987dc61
diff --git a/crowdnode.js b/crowdnode.js
index 65b1d0f..b2bc8cd 100644
--- a/crowdnode.js
+++ b/crowdnode.js
@@ -9,16 +9,21 @@
let CrowdNode = {};
exports.CrowdNode = CrowdNode;
- const DUFFS = 100000000;
+ const SATOSHIS = 100000000;
let Dash = exports.DashApi || require("./dashapi.js");
- let Dashcore = exports.dashcore || require("./lib/dashcore.js");
- let Insight = exports.DashSight || require("dashsight");
+ let Dashcore = exports.dashcore || require("./dashcore-lit.js");
+ let DashSight = exports.DashSight || require("dashsight");
let Ws = exports.DashSocket || require("dashsight/ws");
- CrowdNode._insightBaseUrl = "";
+ CrowdNode._initialized = false;
+ CrowdNode._dashsocketBaseUrl = "";
// TODO don't require these shims
- CrowdNode._insightApi = Insight.create({ baseUrl: "" });
+ CrowdNode._insightApi = DashSight.create({
+ dashsightBaseUrl: "",
+ dashsocketBaseUrl: "",
+ insightBaseUrl: "",
+ });
CrowdNode._dashApi = Dash.create({ insightApi: CrowdNode._insightApi });
CrowdNode.main = {
@@ -40,8 +45,9 @@
CrowdNode.offset = 20000;
CrowdNode.duffs = 100000000;
+ CrowdNode.satoshis = 100000000;
CrowdNode.depositMinimum = 100000;
- CrowdNode.stakeMinimum = toDuff(0.5);
+ CrowdNode.stakeMinimum = toSatoshis(0.5);
/**
* @type {Record}
@@ -83,19 +89,38 @@
/**
* @param {Object} opts
* @param {String} opts.baseUrl
- * @param {String} opts.insightBaseUrl
+ * @param {String} opts.dashsightBaseUrl - typically ends with /insight-api
+ * @param {String} opts.dashsocketBaseUrl - typically ends with /socket.io
+ * @param {String} opts.insightBaseUrl - typically ends with /insight-api
*/
- CrowdNode.init = async function ({ baseUrl, insightBaseUrl }) {
+ CrowdNode.init = async function ({
+ baseUrl,
+ dashsightBaseUrl,
+ dashsocketBaseUrl,
+ insightBaseUrl,
+ }) {
// TODO use API
// See https://github.com/dashhive/crowdnode.js/issues/3
CrowdNode._baseUrl = baseUrl;
- CrowdNode._insightBaseUrl = insightBaseUrl;
- CrowdNode._insightApi = Insight.create({
- baseUrl: insightBaseUrl,
+ if ("https://insight.dash.org" === insightBaseUrl) {
+ insightBaseUrl = "https://insight.dash.org/insight-api";
+ if (!dashsocketBaseUrl) {
+ dashsocketBaseUrl = "https://insight.dash.org/socket.io";
+ }
+ if (!dashsightBaseUrl) {
+ dashsightBaseUrl = "https://dashsight.dashincubator.dev/insight-api";
+ }
+ }
+ CrowdNode._dashsocketBaseUrl = dashsocketBaseUrl;
+ CrowdNode._insightApi = DashSight.create({
+ dashsightBaseUrl: dashsightBaseUrl,
+ dashsocketBaseUrl: dashsocketBaseUrl,
+ insightBaseUrl: insightBaseUrl,
});
CrowdNode._dashApi = Dash.create({ insightApi: CrowdNode._insightApi });
+ CrowdNode._initialized = true;
};
/**
@@ -127,8 +152,8 @@
if (vout.scriptPubKey.addresses[0] !== signupAddr) {
return;
}
- let amount = Math.round(parseFloat(vout.value) * DUFFS);
- let msg = amount - CrowdNode.offset;
+ let sats = Math.round(parseFloat(vout.value) * SATOSHIS);
+ let msg = sats - CrowdNode.offset;
if (CrowdNode.responses.DepositReceived === msg) {
status.deposit = tx.time;
@@ -165,7 +190,7 @@
// Send Request Message
let pk = new Dashcore.PrivateKey(wif);
let msg = CrowdNode.offset + CrowdNode.requests.signupForApi;
- let changeAddr = pk.toPublicKey().toAddress().toString();
+ let changeAddr = (await pk.toPublicKey().toAddress()).toString();
let tx = await CrowdNode._dashApi.createPayment(
wif,
hotwallet,
@@ -175,7 +200,11 @@
await CrowdNode._insightApi.instantSend(tx.serialize());
let reply = CrowdNode.offset + CrowdNode.responses.PleaseAcceptTerms;
- return await Ws.waitForVout(CrowdNode._insightBaseUrl, changeAddr, reply);
+ return await Ws.waitForVout(
+ CrowdNode._dashsocketBaseUrl,
+ changeAddr,
+ reply,
+ );
};
/**
@@ -186,7 +215,7 @@
// Send Request Message
let pk = new Dashcore.PrivateKey(wif);
let msg = CrowdNode.offset + CrowdNode.requests.acceptTerms;
- let changeAddr = pk.toPublicKey().toAddress().toString();
+ let changeAddr = (await pk.toPublicKey().toAddress()).toString();
let tx = await CrowdNode._dashApi.createPayment(
wif,
hotwallet,
@@ -197,31 +226,35 @@
let reply =
CrowdNode.offset + CrowdNode.responses.WelcomeToCrowdNodeBlockChainAPI;
- return await Ws.waitForVout(CrowdNode._insightBaseUrl, changeAddr, reply);
+ return await Ws.waitForVout(
+ CrowdNode._dashsocketBaseUrl,
+ changeAddr,
+ reply,
+ );
};
/**
* @param {String} wif
* @param {String} hotwallet
- * @param {Number} amount - Duffs (1/100000000 Dash)
+ * @param {Number} satoshis - base unit of 1/100000000 Dash
*/
- CrowdNode.deposit = async function (wif, hotwallet, amount) {
+ CrowdNode.deposit = async function (wif, hotwallet, satoshis) {
// Send Request Message
let pk = new Dashcore.PrivateKey(wif);
- let changeAddr = pk.toPublicKey().toAddress().toString();
+ let changeAddr = (await pk.toPublicKey().toAddress()).toString();
// TODO reserve a balance
let tx;
- if (amount) {
- if (amount < CrowdNode.depositMinimum) {
+ if (satoshis) {
+ if (satoshis < CrowdNode.depositMinimum) {
throw new Error(
- `cannot deposit '${amount}': less than minimum of '${CrowdNode.depositMinimum}'`,
+ `cannot deposit '${satoshis}': less than minimum of '${CrowdNode.depositMinimum}'`,
);
}
tx = await CrowdNode._dashApi.createPayment(
wif,
hotwallet,
- amount,
+ satoshis,
changeAddr,
);
} else {
@@ -230,7 +263,11 @@
await CrowdNode._insightApi.instantSend(tx.serialize());
let reply = CrowdNode.offset + CrowdNode.responses.DepositReceived;
- return await Ws.waitForVout(CrowdNode._insightBaseUrl, changeAddr, reply);
+ return await Ws.waitForVout(
+ CrowdNode._dashsocketBaseUrl,
+ changeAddr,
+ reply,
+ );
};
/**
@@ -248,7 +285,7 @@
// Send Request Message
let pk = new Dashcore.PrivateKey(wif);
let msg = CrowdNode.offset + permil;
- let changeAddr = pk.toPublicKey().toAddress().toString();
+ let changeAddr = (await pk.toPublicKey().toAddress()).toString();
let tx = await CrowdNode._dashApi.createPayment(
wif,
hotwallet,
@@ -266,7 +303,7 @@
satoshis: 0,
txlock: false,
};
- return await Ws.listen(CrowdNode._insightBaseUrl, findResponse);
+ return await Ws.listen(CrowdNode._dashsocketBaseUrl, findResponse);
/**
* @param {String} evname
@@ -293,12 +330,12 @@
return false;
}
- let duffs = vout[addr];
- let msg = duffs - CrowdNode.offset;
+ let sats = vout[addr];
+ let msg = sats - CrowdNode.offset;
let api = CrowdNode._responses[msg];
if (!api) {
// the withdraw often happens before the queued message
- console.warn(` => received '${duffs}' (${evname})`);
+ console.warn(` => received '${sats}' (${evname})`);
return false;
}
@@ -307,7 +344,7 @@
api: api.toString(),
at: now,
txid: data.txid,
- satoshis: duffs,
+ satoshis: sats,
txlock: data.txlock,
};
@@ -399,7 +436,7 @@
}
// Workaround for https://github.com/dashhive/crowdnode-cli/issues/19
- // (we could also `b = Math.round(Math.floor(b * DUFFS) / DUFFS)`)
+ // (we could also `b = Math.round(Math.floor(b * SATOSHIS) / SATOSHIS)`)
balanceInfo.TotalBalance = parseFloat(balanceInfo.TotalBalance.toFixed(8));
balanceInfo.TotalActiveBalance = parseFloat(
balanceInfo.TotalActiveBalance.toFixed(8),
@@ -497,10 +534,10 @@
/**
* @param {String|Number} dash
*/
- function toDuff(dash) {
+ function toSatoshis(dash) {
//@ts-ignore
let dashF = parseFloat(dash);
- return Math.round(dashF * DUFFS);
+ return Math.round(dashF * SATOSHIS);
}
if ("undefined" !== typeof module) {
diff --git a/dashapi.js b/dashapi.js
index e247f9b..0505b44 100644
--- a/dashapi.js
+++ b/dashapi.js
@@ -5,13 +5,13 @@
//@ts-ignore
exports.DashApi = Dash;
- const DUFFS = 100000000;
- const DUST = 10000;
+ const SATOSHIS = 100000000;
const FEE = 1000;
//@ts-ignore
- let Dashcore = exports.dashcore || require("./lib/dashcore.js");
+ let Dashcore = exports.dashcore || require("./dashcore-lit.js");
let Transaction = Dashcore.Transaction;
+ let PrivateKey = Dashcore.PrivateKey;
Dash.create = function ({
//@ts-ignore TODO
@@ -32,7 +32,7 @@
}, 0);
// because 0.1 + 0.2 = 0.30000000000000004,
// but we would only want 0.30000000
- let floatBalance = parseFloat((balance / DUFFS).toFixed(8));
+ let floatBalance = parseFloat((balance / SATOSHIS).toFixed(8));
return {
addrStr: address,
@@ -51,8 +51,8 @@
* @param {String} pub
*/
dashApi.createBalanceTransfer = async function (privKey, pub) {
- let pk = new Dashcore.PrivateKey(privKey);
- let changeAddr = pk.toPublicKey().toAddress().toString();
+ let pk = new PrivateKey(privKey);
+ let changeAddr = (await pk.toPublicKey().toAddress()).toString();
let body = await insightApi.getUtxos(changeAddr);
let utxos = await getUtxos(body);
@@ -65,7 +65,7 @@
//@ts-ignore - allows single value or array
.from(utxos);
tmpTx.to(pub, balance - 1000);
- tmpTx.sign(pk);
+ await tmpTx.sign(pk);
// TODO getsmartfeeestimate??
// fee = 1duff/byte (2 chars hex is 1 byte)
@@ -78,7 +78,7 @@
.from(utxos);
tx.to(pub, balance - fee);
tx.fee(fee);
- tx.sign(pk);
+ await tx.sign(pk);
return tx;
};
@@ -86,25 +86,25 @@
/**
* Send with change back
* @param {String} privKey
- * @param {(String|import('@dashevo/dashcore-lib').Address)} payAddr
- * @param {Number} amount
- * @param {(String|import('@dashevo/dashcore-lib').Address)} [changeAddr]
+ * @param {String} payAddr
+ * @param {Number} satoshis - base unit of DASH (a.k.a. "duffs")
+ * @param {String} [changeAddr]
*/
dashApi.createPayment = async function (
privKey,
payAddr,
- amount,
+ satoshis,
changeAddr,
) {
- let pk = new Dashcore.PrivateKey(privKey);
- let utxoAddr = pk.toPublicKey().toAddress().toString();
+ let pk = new PrivateKey(privKey);
+ let utxoAddr = (await pk.toPublicKey().toAddress()).toString();
if (!changeAddr) {
changeAddr = utxoAddr;
}
// TODO make more accurate?
let feePreEstimate = 1000;
- let utxos = await getOptimalUtxos(utxoAddr, amount + feePreEstimate);
+ let utxos = await getOptimalUtxos(utxoAddr, satoshis + feePreEstimate);
let balance = getBalance(utxos);
if (!utxos.length) {
@@ -112,18 +112,18 @@
}
// (estimate) don't send dust back as change
- if (balance - amount <= DUST + FEE) {
- amount = balance;
+ if (balance - satoshis <= Transaction.DUST_AMOUNT + FEE) {
+ satoshis = balance;
}
//@ts-ignore - no input required, actually
let tmpTx = new Transaction()
//@ts-ignore - allows single value or array
.from(utxos);
- tmpTx.to(payAddr, amount);
+ tmpTx.to(payAddr, satoshis);
//@ts-ignore - the JSDoc is wrong in dashcore-lib/lib/transaction/transaction.js
tmpTx.change(changeAddr);
- tmpTx.sign(pk);
+ await tmpTx.sign(pk);
// TODO getsmartfeeestimate??
// fee = 1duff/byte (2 chars hex is 1 byte)
@@ -132,19 +132,19 @@
let fee = 10 + tmpTx.toString().length / 2;
// (adjusted) don't send dust back as change
- if (balance + -amount + -fee <= DUST) {
- amount = balance - fee;
+ if (balance + -satoshis + -fee <= Transaction.DUST_AMOUNT) {
+ satoshis = balance - fee;
}
//@ts-ignore - no input required, actually
let tx = new Transaction()
//@ts-ignore - allows single value or array
.from(utxos);
- tx.to(payAddr, amount);
+ tx.to(payAddr, satoshis);
tx.fee(fee);
//@ts-ignore - see above
tx.change(changeAddr);
- tx.sign(pk);
+ await tx.sign(pk);
return tx;
};
@@ -152,16 +152,16 @@
// TODO make more optimal
/**
* @param {String} utxoAddr
- * @param {Number} fullAmount - including fee estimate
+ * @param {Number} totalSatoshis - including fee estimate
*/
- async function getOptimalUtxos(utxoAddr, fullAmount) {
+ async function getOptimalUtxos(utxoAddr, totalSatoshis) {
// get smallest coin larger than transaction
// if that would create dust, donate it as tx fee
let body = await insightApi.getUtxos(utxoAddr);
let utxos = await getUtxos(body);
let balance = getBalance(utxos);
- if (balance < fullAmount) {
+ if (balance < totalSatoshis) {
return [];
}
@@ -176,7 +176,7 @@
// try to get just one
utxos.every(function (utxo) {
- if (utxo.satoshis > fullAmount) {
+ if (utxo.satoshis > totalSatoshis) {
included[0] = utxo;
total = utxo.satoshis;
return true;
@@ -191,7 +191,7 @@
utxos.some(function (utxo) {
included.push(utxo);
total += utxo.satoshis;
- return total >= fullAmount;
+ return total >= totalSatoshis;
});
return included;
}
@@ -207,6 +207,7 @@
/**
* @param {Array} body
+ * @returns {Promise>}
*/
async function getUtxos(body) {
/** @type Array */
@@ -232,7 +233,7 @@
return false;
}
- let satoshis = Math.round(parseFloat(vout.value) * DUFFS);
+ let satoshis = Math.round(parseFloat(vout.value) * SATOSHIS);
if (utxo.satoshis !== satoshis) {
return false;
}
@@ -243,6 +244,7 @@
data.vout.some(findAndSetUtxoIndex);
+ // TODO test without txid
utxos.push({
txId: utxo.txid,
outputIndex: utxoIndex,
diff --git a/dashcore-lit.js b/dashcore-lit.js
new file mode 100644
index 0000000..8a291ac
--- /dev/null
+++ b/dashcore-lit.js
@@ -0,0 +1,489 @@
+(function (exports) {
+ "use strict";
+
+ let Dashcore = {};
+ //@ts-ignore
+ exports.dashcore = Dashcore;
+
+ let Base58Check = require("@dashincubator/base58check").Base58Check;
+ //@ts-ignore
+ let BlockTx = exports.BlockTx || require("@dashincubator/blocktx");
+ //@ts-ignore
+ let Crypto = exports.crypto || require("./shims/crypto-node.js");
+ let RIPEMD160 = require("@dashincubator/ripemd160");
+ let Secp256k1 = require("@dashincubator/secp256k1");
+
+ let b58c = Base58Check.create({
+ pubKeyHashVersion: "4c",
+ privateKeyVersion: "cc",
+ });
+
+ let dashTx = BlockTx.create({
+ version: 3,
+ /**
+ * @param {String} addr
+ * @returns {String}
+ */
+ addrToPubKeyHash: function (addr) {
+ let b58c = Base58Check.create({
+ pubKeyHashVersion: "4c",
+ privateKeyVersion: "cc",
+ });
+
+ // XXX bad idea?
+ // using .decode to avoid the async of .verify
+ let parts = b58c.decode(addr);
+ return parts.pubKeyHash;
+ },
+ });
+
+ function Transaction() {
+ //@ts-ignore
+ return Dashcore.Transaction.create.apply(null, arguments);
+ }
+ Dashcore.Transaction = Transaction;
+
+ // 193 + BlockTx.OUTPUT_SIZE;
+ Transaction.DUST_AMOUNT = 5460;
+
+ Transaction.create = function () {
+ let changeAddr = "";
+ let fee = 0;
+ let txInfo = {
+ /** @type {Array} */
+ inputs: [],
+ locktime: 0,
+ /** @type {Array} */
+ outputs: [],
+ version: 3,
+ };
+ /** @type {import('@dashincubator/blocktx').TxInfoSigned} */
+ let txSigned;
+
+ let coreTx = {};
+
+ /**
+ * @param {Array} utxos
+ */
+ coreTx.from = function (utxos) {
+ if (!Array.isArray(utxos)) {
+ utxos = [utxos];
+ }
+ txInfo.inputs = txInfo.inputs.concat(utxos);
+ return coreTx;
+ };
+
+ /**
+ * @param {Array} payments
+ * @param {Number} satoshis - base unit of DASH (a.k.a. "duffs")
+ */
+ coreTx.to = function (payments, satoshis) {
+ if (!Array.isArray(payments)) {
+ payments = [
+ {
+ address: payments,
+ satoshis: satoshis,
+ },
+ ];
+ }
+ txInfo.outputs = txInfo.outputs.concat(payments);
+ return coreTx;
+ };
+
+ /**
+ * @param {Number} targetFee
+ */
+ coreTx.fee = function (targetFee) {
+ fee = targetFee;
+
+ return coreTx;
+ };
+
+ /**
+ * @param {String} address
+ */
+ coreTx.change = function (address) {
+ changeAddr = address;
+
+ return coreTx;
+ };
+
+ /**
+ * @param {Array} keys
+ */
+ coreTx.sign = async function (keys) {
+ if (!Array.isArray(keys)) {
+ keys = [keys];
+ }
+
+ let _txInfo = Object.assign({}, txInfo);
+ let changeOutput = await coreTx._calculateFee();
+ if (changeOutput) {
+ _txInfo.outputs.push(changeOutput);
+ }
+ let _keys = await coreTx._mapKeysToUtxos(_txInfo, keys);
+ console.log(_keys.length, _txInfo.inputs.length);
+ txSigned = await dashTx.hashAndSignAll(_txInfo, _keys);
+ };
+
+ coreTx._calculateFee = async function () {
+ let sats = txInfo.inputs.reduce(function (total, utxo) {
+ return total + utxo.satoshis;
+ }, 0);
+ let paid = txInfo.outputs.reduce(function (total, payment) {
+ return total + payment.satoshis;
+ }, 0);
+
+ let [minFee, maxFee] = BlockTx.estimates(txInfo);
+ let feeSpread = maxFee - minFee;
+ let halfSpread = Math.ceil(feeSpread / 2);
+ if (!fee) {
+ fee = maxFee;
+ }
+ if (fee < minFee) {
+ throw new Error(
+ `your fees are too powerful: increase fee to at least ${minFee} (absolute possible minimum) + ${halfSpread} (to account for possible byte padding) + ${BlockTx.OUTPUT_SIZE} (if you expect change back)`,
+ );
+ }
+
+ let myMaxFee = Math.max(fee, maxFee);
+ let change = sats + -paid + -myMaxFee;
+ if (change <= Transaction.DUST_AMOUNT) {
+ change = 0;
+ }
+
+ let changeFee = 0;
+ /** @type {import('@dashincubator/blocktx').TxOutput?} */
+ let changeOutput = null;
+ if (change) {
+ if (!changeAddr) {
+ let bigFee = fee + change;
+ throw new Error(
+ `you must provide 'change(addr)' to collect '${change}' sats or increase 'fee' to '${bigFee}'`,
+ );
+ }
+ changeFee = BlockTx.OUTPUT_SIZE;
+ change -= changeFee;
+ changeOutput = {
+ address: changeAddr,
+ satoshis: change,
+ };
+ }
+
+ let total = paid + myMaxFee;
+ if (total > sats) {
+ let debt = sats - total;
+ throw new Error(
+ `your spending is too powerful: ${debt} = ${sats} (inputs) + -${paid} (outputs) + -${myMaxFee} (fee) + -${changeFee} (change fee)`,
+ );
+ }
+
+ return changeOutput;
+ };
+
+ /**
+ * @param {import('@dashincubator/blocktx').TxInfo} _txInfo
+ * @param {Array} keys
+ */
+ coreTx._mapKeysToUtxos = async function (_txInfo, keys) {
+ /** @type {Array} */
+ let utxoKeys = [];
+ /** @type {Object.} */
+ let keysMap = {};
+ for (let key of keys) {
+ let privInst = PrivateKeyFactory.create(key);
+ let privBuf = privInst._toUint8Array();
+ let pubInst = await privInst.toPublicKey();
+ let addrInst = await pubInst.toAddress();
+ console.log("DEBUG", addrInst._address, addrInst._pubKeyHash);
+ keysMap[addrInst._address] = privBuf;
+ keysMap[addrInst._pubKeyHash] = privBuf;
+ }
+ for (let input of _txInfo.inputs) {
+ let index = input.address || input.pubKeyHash || "";
+ let privBuf = keysMap[index];
+ if (!privBuf) {
+ let outStr = JSON.stringify(input);
+ throw new Error(`missing private key for input: ${outStr}`);
+ }
+ utxoKeys.push(privBuf);
+ }
+
+ return utxoKeys;
+ };
+
+ coreTx.toString = function () {
+ // TODO produce raw tx if not signed
+ return txSigned.transaction;
+ };
+
+ coreTx.serialize = function () {
+ // TODO run checks on fees and change and stuff
+ return txSigned.transaction;
+ };
+
+ return coreTx;
+ };
+
+ /**
+ * @typedef Address
+ * @prop {String} _address
+ * @prop {String} _pubKeyHash
+ * @prop {ToString} toString
+ */
+
+ /**
+ * @typedef PrivateKey
+ * @prop {ToAddress} toAddress
+ * @prop {ToPublicKey} toPublicKey
+ * @prop {ToUint8Array} _toUint8Array
+ */
+
+ /**
+ * @typedef {String|Uint8Array|ArrayBuffer|Buffer|PrivateKey} PrivateKeyish
+ */
+
+ /**
+ * @typedef PublicKey
+ * @prop {ToAddress} toAddress
+ * @prop {ToUint8Array} _toUint8Array
+ */
+
+ /**
+ * @callback ToAddress
+ * @returns {Promise} - Payment Address (Public) instance object
+ */
+
+ /**
+ * @callback ToPublicKey
+ * @returns {PublicKey}
+ */
+
+ /**
+ * @callback ToString
+ * @returns {String} - payAddr (Public)
+ */
+
+ /**
+ * @callback ToUint8Array
+ * @returns {Uint8Array} - key bytes
+ */
+
+ /**
+ * @callback ToWIF
+ * @returns {Promise} - wif (Private)
+ */
+
+ /**
+ * @param {String|Uint8Array|ArrayBuffer|Buffer} wifHexOrBuf
+ * @returns {PrivateKey}
+ */
+ function PrivateKeyFactory(wifHexOrBuf) {
+ return PrivateKeyFactory.create(wifHexOrBuf);
+ }
+ Dashcore.PrivateKey = PrivateKeyFactory;
+
+ /**
+ * @param {String|Uint8Array|ArrayBuffer|Buffer} wifHexOrBuf
+ * @returns {PrivateKey}
+ */
+ PrivateKeyFactory.create = function (wifHexOrBuf) {
+ let pk = {};
+ /** @type {Uint8Array} */
+ let privBuf;
+ if (!wifHexOrBuf) {
+ privBuf = Secp256k1.utils.randomPrivateKey();
+ }
+ privBuf = PrivateKeyFactory.from(wifHexOrBuf);
+
+ /** @type ToWIF */
+ pk.toWIF = async function () {
+ let wif = await privateKeyToWif(privBuf);
+ return wif;
+ };
+
+ /** @type ToAddress */
+ pk.toAddress = async function () {
+ return await pk.toPublicKey().toAddress();
+ };
+
+ pk.toPublicKey = function () {
+ let pubBuf = BlockTx.utils.toPublicKey(privBuf);
+ let pub = PublicKeyFactory.create(pubBuf);
+ return pub;
+ };
+
+ pk._toUint8Array = function () {
+ return privBuf;
+ };
+
+ return pk;
+ };
+
+ /**
+ * @param {any} pk
+ * @returns {pk is PrivateKey}
+ */
+ PrivateKeyFactory.isPrivateKey = function (pk) {
+ return "function" === typeof pk._toUint8Array;
+ };
+
+ /**
+ * @param {PrivateKeyish} wifHexOrBuf
+ * @returns {Uint8Array}
+ */
+ PrivateKeyFactory.from = function (wifHexOrBuf) {
+ let isPrivateKeyInst = PrivateKeyFactory.isPrivateKey(wifHexOrBuf);
+ if (isPrivateKeyInst) {
+ //@ts-ignore
+ return wifHexOrBuf._toUint8Array();
+ }
+
+ if ("string" === typeof wifHexOrBuf) {
+ if (64 === wifHexOrBuf.length) {
+ return BlockTx.utils.hexToU8(wifHexOrBuf);
+ }
+ if (52 === wifHexOrBuf.length) {
+ return wifToPrivateKey(wifHexOrBuf);
+ }
+ throw new Error(
+ "cannot create private key from non-hex, non-wif strings",
+ );
+ }
+
+ //@ts-ignore
+ if (wifHexOrBuf?.buffer) {
+ //@ts-ignore
+ return new Uint8Array(wifHexOrBuf.buffer);
+ }
+ //@ts-ignore
+ if (wifHexOrBuf.byteLength) {
+ //@ts-ignore
+ return new Uint8Array(wifHexOrBuf);
+ }
+ throw new Error(
+ "cannot create private key from non-string, non-buffer type",
+ );
+ };
+
+ /**
+ * @param {String|Uint8Array|ArrayBuffer|Buffer} hexOrBuf
+ * @returns {PublicKey}
+ */
+ function PublicKeyFactory(hexOrBuf) {
+ return PublicKeyFactory.create(hexOrBuf);
+ }
+ Dashcore.PublicKey = PublicKeyFactory;
+
+ /**
+ * @param {String|Uint8Array|ArrayBuffer|Buffer} hexOrBuf
+ * @returns {PublicKey}
+ */
+ PublicKeyFactory.create = function (hexOrBuf) {
+ let pubBuf = PublicKeyFactory.from(hexOrBuf);
+
+ let pub = {};
+ pub._pubKeyHash = "";
+ pub._address = "";
+ pub._buffer = pubBuf;
+
+ /** @type ToAddress */
+ pub.toAddress = async function () {
+ pub._pubKeyHash = await hashPublicKey(pubBuf);
+ pub._address = await pubKeyHashToAddr(pub._pubKeyHash);
+ return {
+ _pubKeyHash: pub._pubKeyHash,
+ _address: pub._address,
+ toString: function () {
+ return pub._address;
+ },
+ };
+ };
+ pub._toUint8Array = function () {
+ return pub._buffer;
+ };
+
+ return pub;
+ };
+
+ /**
+ * @param {String|Uint8Array|ArrayBuffer|Buffer} hexOrBuf
+ * @returns {Uint8Array}
+ */
+ PublicKeyFactory.from = function (hexOrBuf) {
+ if ("string" === typeof hexOrBuf) {
+ if (64 === hexOrBuf.length) {
+ return BlockTx.utils.hexToU8(hexOrBuf);
+ }
+ throw new Error("cannot create public key from non-hex strings");
+ }
+
+ //@ts-ignore
+ if (hexOrBuf?.buffer) {
+ //@ts-ignore
+ return new Uint8Array(hexOrBuf.buffer);
+ }
+ if (hexOrBuf.byteLength) {
+ return new Uint8Array(hexOrBuf);
+ }
+ throw new Error(
+ "cannot create public key from non-string, non-buffer type",
+ );
+ };
+
+ /**
+ * @param {Uint8Array} pubBuf
+ * @return {Promise} - hex sha256 ripemd160 pubKeyHash
+ */
+ async function hashPublicKey(pubBuf) {
+ let sha = await Crypto.subtle.digest("SHA-256", pubBuf);
+ let shaU8 = new Uint8Array(sha);
+ let ripemd = RIPEMD160.create();
+ let hash = ripemd.update(shaU8);
+ let pkh = hash.digest("hex");
+ // extra .toString() for tsc
+ return pkh.toString();
+ }
+
+ /**
+ * @param {Uint8Array} privBuf - Private Key as Uint8Array
+ * @returns {Promise} wif - Base58Check-encoded private key
+ */
+ async function privateKeyToWif(privBuf) {
+ let privHex = BlockTx.utils.u8ToHex(privBuf);
+ let decoded = {
+ privateKey: privHex,
+ };
+
+ let wif = await b58c.encode(decoded);
+ return wif;
+ }
+
+ /**
+ * @param {String} pubKeyHash - pkh hex
+ * @returns {Promise} addr - Base58Check-encoded payment address
+ */
+ async function pubKeyHashToAddr(pubKeyHash) {
+ let addr = await b58c.encode({
+ version: "4c",
+ pubKeyHash: pubKeyHash,
+ });
+ return addr;
+ }
+
+ /**
+ * @param {String} wif
+ * @returns {Uint8Array}
+ */
+ function wifToPrivateKey(wif) {
+ //let parts = await b58c.verify(wif);
+ // TODO verifySync
+ let parts = b58c.decode(wif);
+ let privBuf = Buffer.from(parts.privateKey, "hex");
+ return privBuf;
+ }
+
+ if ("undefined" !== typeof module) {
+ module.exports = Dashcore;
+ }
+})(("undefined" !== typeof module && module.exports) || window);
diff --git a/lib/browser-dashcore.js b/lib/browser-dashcore.js
deleted file mode 100644
index eb176c4..0000000
--- a/lib/browser-dashcore.js
+++ /dev/null
@@ -1,3 +0,0 @@
-"use strict";
-
-module.exports = require("@dashevo/dashcore-lib/dist/dashcore-lib.min.js");
diff --git a/lib/dashcore.js b/lib/dashcore.js
deleted file mode 100644
index ef7e9e7..0000000
--- a/lib/dashcore.js
+++ /dev/null
@@ -1,3 +0,0 @@
-"use strict";
-
-module.exports = require("@dashevo/dashcore-lib");
diff --git a/package-lock.json b/package-lock.json
index 1345182..7f787bd 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,291 +1,68 @@
{
"name": "crowdnode",
- "version": "1.7.0",
+ "version": "1.8.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "crowdnode",
- "version": "1.7.0",
+ "version": "1.8.0",
"license": "SEE LICENSE IN LICENSE",
"dependencies": {
- "@dashevo/dashcore-lib": "^0.19.41",
- "dashsight": "^1.1.1"
+ "@dashincubator/base58check": "^1.3.1",
+ "@dashincubator/blocktx": "^0.9.0-2",
+ "@dashincubator/ripemd160": "^2.3.0",
+ "@dashincubator/secp256k1": "^1.7.1-1",
+ "dashsight": "^1.3.0-0"
},
"bin": {
"crowdnode": "bin/crowdnode.js"
},
- "devDependencies": {},
"optionalDependencies": {
- "@root/request": "^1.9.1",
+ "@root/request": "^1.9.2",
"dotenv": "^16.0.1",
"qrcode-svg": "^1.1.0",
"tough-cookie": "^4.0.0",
"ws": "^8.8.0"
}
},
- "node_modules/@dashevo/dashcore-lib": {
- "version": "0.19.41",
- "resolved": "https://registry.npmjs.org/@dashevo/dashcore-lib/-/dashcore-lib-0.19.41.tgz",
- "integrity": "sha512-xsbDcV9P3WOa1s4X6pVbLXKD7xuuB5YqsW1GjE1iyeN+hXXKUJzky5txKt8e9ZEQF7Qd/L/enWupcdHRYhgsqg==",
- "dependencies": {
- "@dashevo/x11-hash-js": "^1.0.2",
- "@types/node": "^12.12.47",
- "bloom-filter": "^0.2.0",
- "bls-signatures": "^0.2.5",
- "bn.js": "^4.12.0",
- "bs58": "=4.0.1",
- "elliptic": "^6.5.4",
- "eslint-config-prettier": "^8.3.0",
- "inherits": "=2.0.1",
- "lodash": "^4.17.20",
- "ripemd160": "^2.0.2",
- "unorm": "^1.6.0"
- }
- },
- "node_modules/@dashevo/x11-hash-js": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/@dashevo/x11-hash-js/-/x11-hash-js-1.0.2.tgz",
- "integrity": "sha512-3vvnZweBca4URBXHF+FTrM4sdTpp3IMt73G1zUKQEdYm/kJkIKN94qpFai7YZDl87k64RCH+ckRZk6ruQPz5KQ=="
- },
- "node_modules/@eslint/eslintrc": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.0.tgz",
- "integrity": "sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==",
- "peer": true,
- "dependencies": {
- "ajv": "^6.12.4",
- "debug": "^4.3.2",
- "espree": "^9.3.2",
- "globals": "^13.15.0",
- "ignore": "^5.2.0",
- "import-fresh": "^3.2.1",
- "js-yaml": "^4.1.0",
- "minimatch": "^3.1.2",
- "strip-json-comments": "^3.1.1"
- },
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- }
- },
- "node_modules/@humanwhocodes/config-array": {
- "version": "0.9.5",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz",
- "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==",
- "peer": true,
- "dependencies": {
- "@humanwhocodes/object-schema": "^1.2.1",
- "debug": "^4.1.1",
- "minimatch": "^3.0.4"
- },
- "engines": {
- "node": ">=10.10.0"
- }
- },
- "node_modules/@humanwhocodes/object-schema": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz",
- "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
- "peer": true
- },
- "node_modules/@root/request": {
- "version": "1.9.1",
- "resolved": "https://registry.npmjs.org/@root/request/-/request-1.9.1.tgz",
- "integrity": "sha512-ROVgS5qgTvXDCI9XoJawJCB+QfC9jF7t3pFWmdUibjHqPt+2wV7pYSgth65qb65bK3qDIv9xXYF5FBECKhe8Iw=="
- },
- "node_modules/@types/node": {
- "version": "12.20.55",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz",
- "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ=="
- },
- "node_modules/acorn": {
- "version": "8.7.1",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz",
- "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==",
- "peer": true,
+ "node_modules/@dashincubator/base58check": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/@dashincubator/base58check/-/base58check-1.3.1.tgz",
+ "integrity": "sha512-v2vYOwsTmbfaADJUg+0Vsw61/P5XtdDnjZtImDIC5DePIA/2lT9V+00nR5GsKfwc40WQ02tFlN+xoFt9cx+P7A==",
"bin": {
- "acorn": "bin/acorn"
- },
- "engines": {
- "node": ">=0.4.0"
- }
- },
- "node_modules/acorn-jsx": {
- "version": "5.3.2",
- "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
- "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
- "peer": true,
- "peerDependencies": {
- "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
- }
- },
- "node_modules/ajv": {
- "version": "6.12.6",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
- "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
- "peer": true,
- "dependencies": {
- "fast-deep-equal": "^3.1.1",
- "fast-json-stable-stringify": "^2.0.0",
- "json-schema-traverse": "^0.4.1",
- "uri-js": "^4.2.2"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/epoberezkin"
- }
- },
- "node_modules/ansi-regex": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "peer": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/ansi-styles": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
- "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
- "peer": true,
- "dependencies": {
- "color-convert": "^2.0.1"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
- "node_modules/argparse": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
- "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
- "peer": true
- },
- "node_modules/balanced-match": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
- "peer": true
- },
- "node_modules/base-x": {
- "version": "3.0.9",
- "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz",
- "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==",
- "dependencies": {
- "safe-buffer": "^5.0.1"
+ "base58check": "bin/base58check.js"
}
},
- "node_modules/bloom-filter": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/bloom-filter/-/bloom-filter-0.2.0.tgz",
- "integrity": "sha512-RMG2RpnKczVzRsEYSPaT5rKsyj0w5/wpQRjaW4vOMe1WyUDQpoqxjNc10uROEjdhu63ytRt6aFRPXFePi/Rd7A=="
- },
- "node_modules/bls-signatures": {
- "version": "0.2.5",
- "resolved": "https://registry.npmjs.org/bls-signatures/-/bls-signatures-0.2.5.tgz",
- "integrity": "sha512-5TzQNCtR4zWE4lM08EOMIT8l3b4h8g5LNKu50fUYP1PnupaLGSLklAcTto4lnH7VXpyhsar+74L9wNJII4E/4Q=="
- },
- "node_modules/bn.js": {
- "version": "4.12.0",
- "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
- "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA=="
- },
- "node_modules/brace-expansion": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
- "peer": true,
- "dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "node_modules/brorand": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
- "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w=="
- },
- "node_modules/bs58": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz",
- "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==",
- "dependencies": {
- "base-x": "^3.0.2"
- }
- },
- "node_modules/callsites": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
- "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
- "peer": true,
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/chalk": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
- "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
- "peer": true,
- "dependencies": {
- "ansi-styles": "^4.1.0",
- "supports-color": "^7.1.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/chalk?sponsor=1"
- }
- },
- "node_modules/color-convert": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
- "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
- "peer": true,
- "dependencies": {
- "color-name": "~1.1.4"
- },
- "engines": {
- "node": ">=7.0.0"
+ "node_modules/@dashincubator/blocktx": {
+ "version": "0.9.0-2",
+ "resolved": "https://registry.npmjs.org/@dashincubator/blocktx/-/blocktx-0.9.0-2.tgz",
+ "integrity": "sha512-g6IQxx/nuwsl3Dxzq61bE/UM8t/qQOnnnpF6BzPReHFd4XudQvQ+WcMXRJbrCQWj4yoR5SOCCBZ6IG7As3aVOg==",
+ "bin": {
+ "blocktx-inspect": "bin/inspect.js"
}
},
- "node_modules/color-name": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
- "peer": true
+ "node_modules/@dashincubator/ripemd160": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/@dashincubator/ripemd160/-/ripemd160-2.3.0.tgz",
+ "integrity": "sha512-SfaUhvXti0Ut6ZhlAwurrRAG56phxqWozj72Hixx/v3LSQj1/wjkgTuDaexil672CzLD+RRWoPgp41BSM+DJJA=="
},
- "node_modules/concat-map": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
- "peer": true
+ "node_modules/@dashincubator/secp256k1": {
+ "version": "1.7.1-1",
+ "resolved": "https://registry.npmjs.org/@dashincubator/secp256k1/-/secp256k1-1.7.1-1.tgz",
+ "integrity": "sha512-zkCfHPiIBWkSHojMEVBGNi9y9vX0NHGxkwO5zdZVlhbiqpWGOPbFRbUIwbEFdlnx4tS2x8w8InNzl36qVYWsGg=="
},
- "node_modules/cross-spawn": {
- "version": "7.0.3",
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
- "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
- "peer": true,
- "dependencies": {
- "path-key": "^3.1.0",
- "shebang-command": "^2.0.0",
- "which": "^2.0.1"
- },
- "engines": {
- "node": ">= 8"
- }
+ "node_modules/@root/request": {
+ "version": "1.9.2",
+ "resolved": "https://registry.npmjs.org/@root/request/-/request-1.9.2.tgz",
+ "integrity": "sha512-wVaL9yVV9oDR9UNbPZa20qgY+4Ch6YN8JUkaE4el/uuS5dmhD8Lusm/ku8qJVNtmQA56XLzEDCRS6/vfpiHK2A=="
},
"node_modules/dashsight": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/dashsight/-/dashsight-1.1.1.tgz",
- "integrity": "sha512-fcNGAxbFlqh2p3Al0Jq+byexPK0HrQMYGzpvgINVs1DI+bQLgI1tjgbpNJf8l7uu5LVmDBq8tjVKoH+hCSzPPA==",
+ "version": "1.3.0-0",
+ "resolved": "https://registry.npmjs.org/dashsight/-/dashsight-1.3.0-0.tgz",
+ "integrity": "sha512-KR2Vj6Ts94FLRFr0A3xqa4PAf3R9njrN5k7IHzbzDZjohb+cG3+11e48W0Dvt6CQGC4+yToRnUvlrBmGdpU5TQ==",
"dependencies": {
- "@root/request": "^1.9.1"
+ "@root/request": "^1.9.2"
},
"bin": {
"dashsight-balance": "bin/balance.js",
@@ -298,41 +75,6 @@
"dotenv": "^16.0.1"
}
},
- "node_modules/debug": {
- "version": "4.3.4",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
- "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
- "peer": true,
- "dependencies": {
- "ms": "2.1.2"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
- "node_modules/deep-is": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
- "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
- "peer": true
- },
- "node_modules/doctrine": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
- "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
- "peer": true,
- "dependencies": {
- "esutils": "^2.0.2"
- },
- "engines": {
- "node": ">=6.0.0"
- }
- },
"node_modules/dotenv": {
"version": "16.0.1",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.1.tgz",
@@ -342,587 +84,6 @@
"node": ">=12"
}
},
- "node_modules/elliptic": {
- "version": "6.5.4",
- "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz",
- "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==",
- "dependencies": {
- "bn.js": "^4.11.9",
- "brorand": "^1.1.0",
- "hash.js": "^1.0.0",
- "hmac-drbg": "^1.0.1",
- "inherits": "^2.0.4",
- "minimalistic-assert": "^1.0.1",
- "minimalistic-crypto-utils": "^1.0.1"
- }
- },
- "node_modules/elliptic/node_modules/inherits": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
- },
- "node_modules/escape-string-regexp": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
- "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
- "peer": true,
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/eslint": {
- "version": "8.17.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.17.0.tgz",
- "integrity": "sha512-gq0m0BTJfci60Fz4nczYxNAlED+sMcihltndR8t9t1evnU/azx53x3t2UHXC/uRjcbvRw/XctpaNygSTcQD+Iw==",
- "peer": true,
- "dependencies": {
- "@eslint/eslintrc": "^1.3.0",
- "@humanwhocodes/config-array": "^0.9.2",
- "ajv": "^6.10.0",
- "chalk": "^4.0.0",
- "cross-spawn": "^7.0.2",
- "debug": "^4.3.2",
- "doctrine": "^3.0.0",
- "escape-string-regexp": "^4.0.0",
- "eslint-scope": "^7.1.1",
- "eslint-utils": "^3.0.0",
- "eslint-visitor-keys": "^3.3.0",
- "espree": "^9.3.2",
- "esquery": "^1.4.0",
- "esutils": "^2.0.2",
- "fast-deep-equal": "^3.1.3",
- "file-entry-cache": "^6.0.1",
- "functional-red-black-tree": "^1.0.1",
- "glob-parent": "^6.0.1",
- "globals": "^13.15.0",
- "ignore": "^5.2.0",
- "import-fresh": "^3.0.0",
- "imurmurhash": "^0.1.4",
- "is-glob": "^4.0.0",
- "js-yaml": "^4.1.0",
- "json-stable-stringify-without-jsonify": "^1.0.1",
- "levn": "^0.4.1",
- "lodash.merge": "^4.6.2",
- "minimatch": "^3.1.2",
- "natural-compare": "^1.4.0",
- "optionator": "^0.9.1",
- "regexpp": "^3.2.0",
- "strip-ansi": "^6.0.1",
- "strip-json-comments": "^3.1.0",
- "text-table": "^0.2.0",
- "v8-compile-cache": "^2.0.3"
- },
- "bin": {
- "eslint": "bin/eslint.js"
- },
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
- }
- },
- "node_modules/eslint-config-prettier": {
- "version": "8.5.0",
- "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz",
- "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==",
- "bin": {
- "eslint-config-prettier": "bin/cli.js"
- },
- "peerDependencies": {
- "eslint": ">=7.0.0"
- }
- },
- "node_modules/eslint-scope": {
- "version": "7.1.1",
- "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz",
- "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==",
- "peer": true,
- "dependencies": {
- "esrecurse": "^4.3.0",
- "estraverse": "^5.2.0"
- },
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- }
- },
- "node_modules/eslint-utils": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz",
- "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==",
- "peer": true,
- "dependencies": {
- "eslint-visitor-keys": "^2.0.0"
- },
- "engines": {
- "node": "^10.0.0 || ^12.0.0 || >= 14.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/mysticatea"
- },
- "peerDependencies": {
- "eslint": ">=5"
- }
- },
- "node_modules/eslint-utils/node_modules/eslint-visitor-keys": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz",
- "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==",
- "peer": true,
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/eslint-visitor-keys": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz",
- "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==",
- "peer": true,
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- }
- },
- "node_modules/espree": {
- "version": "9.3.2",
- "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.2.tgz",
- "integrity": "sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA==",
- "peer": true,
- "dependencies": {
- "acorn": "^8.7.1",
- "acorn-jsx": "^5.3.2",
- "eslint-visitor-keys": "^3.3.0"
- },
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- }
- },
- "node_modules/esquery": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz",
- "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==",
- "peer": true,
- "dependencies": {
- "estraverse": "^5.1.0"
- },
- "engines": {
- "node": ">=0.10"
- }
- },
- "node_modules/esrecurse": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
- "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
- "peer": true,
- "dependencies": {
- "estraverse": "^5.2.0"
- },
- "engines": {
- "node": ">=4.0"
- }
- },
- "node_modules/estraverse": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
- "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
- "peer": true,
- "engines": {
- "node": ">=4.0"
- }
- },
- "node_modules/esutils": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
- "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
- "peer": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/fast-deep-equal": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
- "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
- "peer": true
- },
- "node_modules/fast-json-stable-stringify": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
- "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
- "peer": true
- },
- "node_modules/fast-levenshtein": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
- "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
- "peer": true
- },
- "node_modules/file-entry-cache": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
- "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
- "peer": true,
- "dependencies": {
- "flat-cache": "^3.0.4"
- },
- "engines": {
- "node": "^10.12.0 || >=12.0.0"
- }
- },
- "node_modules/flat-cache": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
- "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==",
- "peer": true,
- "dependencies": {
- "flatted": "^3.1.0",
- "rimraf": "^3.0.2"
- },
- "engines": {
- "node": "^10.12.0 || >=12.0.0"
- }
- },
- "node_modules/flatted": {
- "version": "3.2.5",
- "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz",
- "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==",
- "peer": true
- },
- "node_modules/fs.realpath": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
- "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
- "peer": true
- },
- "node_modules/functional-red-black-tree": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
- "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==",
- "peer": true
- },
- "node_modules/glob": {
- "version": "7.2.3",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
- "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
- "peer": true,
- "dependencies": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^3.1.1",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
- },
- "engines": {
- "node": "*"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/glob-parent": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
- "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
- "peer": true,
- "dependencies": {
- "is-glob": "^4.0.3"
- },
- "engines": {
- "node": ">=10.13.0"
- }
- },
- "node_modules/globals": {
- "version": "13.15.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-13.15.0.tgz",
- "integrity": "sha512-bpzcOlgDhMG070Av0Vy5Owklpv1I6+j96GhUI7Rh7IzDCKLzboflLrrfqMu8NquDbiR4EOQk7XzJwqVJxicxog==",
- "peer": true,
- "dependencies": {
- "type-fest": "^0.20.2"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/has-flag": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
- "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
- "peer": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/hash-base": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz",
- "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==",
- "dependencies": {
- "inherits": "^2.0.4",
- "readable-stream": "^3.6.0",
- "safe-buffer": "^5.2.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/hash-base/node_modules/inherits": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
- },
- "node_modules/hash.js": {
- "version": "1.1.7",
- "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz",
- "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==",
- "dependencies": {
- "inherits": "^2.0.3",
- "minimalistic-assert": "^1.0.1"
- }
- },
- "node_modules/hash.js/node_modules/inherits": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
- },
- "node_modules/hmac-drbg": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
- "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==",
- "dependencies": {
- "hash.js": "^1.0.3",
- "minimalistic-assert": "^1.0.0",
- "minimalistic-crypto-utils": "^1.0.1"
- }
- },
- "node_modules/ignore": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
- "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==",
- "peer": true,
- "engines": {
- "node": ">= 4"
- }
- },
- "node_modules/import-fresh": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
- "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
- "peer": true,
- "dependencies": {
- "parent-module": "^1.0.0",
- "resolve-from": "^4.0.0"
- },
- "engines": {
- "node": ">=6"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/imurmurhash": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
- "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
- "peer": true,
- "engines": {
- "node": ">=0.8.19"
- }
- },
- "node_modules/inflight": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
- "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
- "peer": true,
- "dependencies": {
- "once": "^1.3.0",
- "wrappy": "1"
- }
- },
- "node_modules/inherits": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
- "integrity": "sha512-8nWq2nLTAwd02jTqJExUYFSD/fKq6VH9Y/oG2accc/kdI0V98Bag8d5a4gi3XHz73rDWa2PvTtvcWYquKqSENA=="
- },
- "node_modules/is-extglob": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
- "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
- "peer": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/is-glob": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
- "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
- "peer": true,
- "dependencies": {
- "is-extglob": "^2.1.1"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/isexe": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
- "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
- "peer": true
- },
- "node_modules/js-yaml": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
- "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
- "peer": true,
- "dependencies": {
- "argparse": "^2.0.1"
- },
- "bin": {
- "js-yaml": "bin/js-yaml.js"
- }
- },
- "node_modules/json-schema-traverse": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
- "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
- "peer": true
- },
- "node_modules/json-stable-stringify-without-jsonify": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
- "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
- "peer": true
- },
- "node_modules/levn": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
- "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
- "peer": true,
- "dependencies": {
- "prelude-ls": "^1.2.1",
- "type-check": "~0.4.0"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/lodash": {
- "version": "4.17.21",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
- "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
- },
- "node_modules/lodash.merge": {
- "version": "4.6.2",
- "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
- "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
- "peer": true
- },
- "node_modules/minimalistic-assert": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
- "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A=="
- },
- "node_modules/minimalistic-crypto-utils": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz",
- "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg=="
- },
- "node_modules/minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
- "peer": true,
- "dependencies": {
- "brace-expansion": "^1.1.7"
- },
- "engines": {
- "node": "*"
- }
- },
- "node_modules/ms": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
- "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
- "peer": true
- },
- "node_modules/natural-compare": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
- "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
- "peer": true
- },
- "node_modules/once": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
- "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
- "peer": true,
- "dependencies": {
- "wrappy": "1"
- }
- },
- "node_modules/optionator": {
- "version": "0.9.1",
- "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
- "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==",
- "peer": true,
- "dependencies": {
- "deep-is": "^0.1.3",
- "fast-levenshtein": "^2.0.6",
- "levn": "^0.4.1",
- "prelude-ls": "^1.2.1",
- "type-check": "^0.4.0",
- "word-wrap": "^1.2.3"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/parent-module": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
- "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
- "peer": true,
- "dependencies": {
- "callsites": "^3.0.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/path-is-absolute": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
- "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
- "peer": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/path-key": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
- "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
- "peer": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/prelude-ls": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
- "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
- "peer": true,
- "engines": {
- "node": ">= 0.8.0"
- }
- },
"node_modules/psl": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
@@ -933,171 +94,19 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/qrcode-svg": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/qrcode-svg/-/qrcode-svg-1.1.0.tgz",
- "integrity": "sha512-XyQCIXux1zEIA3NPb0AeR8UMYvXZzWEhgdBgBjH9gO7M48H9uoHzviNz8pXw3UzrAcxRRRn9gxHewAVK7bn9qw==",
"optional": true,
- "bin": {
- "qrcode-svg": "bin/qrcode-svg.js"
- }
- },
- "node_modules/readable-stream": {
- "version": "3.6.0",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
- "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
- "dependencies": {
- "inherits": "^2.0.3",
- "string_decoder": "^1.1.1",
- "util-deprecate": "^1.0.1"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/readable-stream/node_modules/inherits": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
- },
- "node_modules/regexpp": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz",
- "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==",
- "peer": true,
"engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/mysticatea"
- }
- },
- "node_modules/resolve-from": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
- "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
- "peer": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/rimraf": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
- "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
- "peer": true,
- "dependencies": {
- "glob": "^7.1.3"
- },
- "bin": {
- "rimraf": "bin.js"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/ripemd160": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz",
- "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==",
- "dependencies": {
- "hash-base": "^3.0.0",
- "inherits": "^2.0.1"
- }
- },
- "node_modules/safe-buffer": {
- "version": "5.2.1",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
- "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ]
- },
- "node_modules/shebang-command": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
- "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
- "peer": true,
- "dependencies": {
- "shebang-regex": "^3.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/shebang-regex": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
- "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
- "peer": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/string_decoder": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
- "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
- "dependencies": {
- "safe-buffer": "~5.2.0"
- }
- },
- "node_modules/strip-ansi": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "peer": true,
- "dependencies": {
- "ansi-regex": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/strip-json-comments": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
- "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
- "peer": true,
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/supports-color": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
- "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
- "peer": true,
- "dependencies": {
- "has-flag": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
+ "node": ">=6"
}
},
- "node_modules/text-table": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
- "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
- "peer": true
+ "node_modules/qrcode-svg": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/qrcode-svg/-/qrcode-svg-1.1.0.tgz",
+ "integrity": "sha512-XyQCIXux1zEIA3NPb0AeR8UMYvXZzWEhgdBgBjH9gO7M48H9uoHzviNz8pXw3UzrAcxRRRn9gxHewAVK7bn9qw==",
+ "optional": true,
+ "bin": {
+ "qrcode-svg": "bin/qrcode-svg.js"
+ }
},
"node_modules/tough-cookie": {
"version": "4.0.0",
@@ -1113,30 +122,6 @@
"node": ">=6"
}
},
- "node_modules/type-check": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
- "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
- "peer": true,
- "dependencies": {
- "prelude-ls": "^1.2.1"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/type-fest": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
- "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
- "peer": true,
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/universalify": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
@@ -1146,64 +131,6 @@
"node": ">= 4.0.0"
}
},
- "node_modules/unorm": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/unorm/-/unorm-1.6.0.tgz",
- "integrity": "sha512-b2/KCUlYZUeA7JFUuRJZPUtr4gZvBh7tavtv4fvk4+KV9pfGiR6CQAQAWl49ZpR3ts2dk4FYkP7EIgDJoiOLDA==",
- "engines": {
- "node": ">= 0.4.0"
- }
- },
- "node_modules/uri-js": {
- "version": "4.4.1",
- "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
- "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
- "peer": true,
- "dependencies": {
- "punycode": "^2.1.0"
- }
- },
- "node_modules/util-deprecate": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
- },
- "node_modules/v8-compile-cache": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz",
- "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==",
- "peer": true
- },
- "node_modules/which": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
- "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
- "peer": true,
- "dependencies": {
- "isexe": "^2.0.0"
- },
- "bin": {
- "node-which": "bin/node-which"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/word-wrap": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
- "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
- "peer": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/wrappy": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
- "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
- "peer": true
- },
"node_modules/ws": {
"version": "8.8.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.8.0.tgz",
@@ -1227,726 +154,46 @@
}
},
"dependencies": {
- "@dashevo/dashcore-lib": {
- "version": "0.19.41",
- "resolved": "https://registry.npmjs.org/@dashevo/dashcore-lib/-/dashcore-lib-0.19.41.tgz",
- "integrity": "sha512-xsbDcV9P3WOa1s4X6pVbLXKD7xuuB5YqsW1GjE1iyeN+hXXKUJzky5txKt8e9ZEQF7Qd/L/enWupcdHRYhgsqg==",
- "requires": {
- "@dashevo/x11-hash-js": "^1.0.2",
- "@types/node": "^12.12.47",
- "bloom-filter": "^0.2.0",
- "bls-signatures": "^0.2.5",
- "bn.js": "^4.12.0",
- "bs58": "=4.0.1",
- "elliptic": "^6.5.4",
- "eslint-config-prettier": "^8.3.0",
- "inherits": "=2.0.1",
- "lodash": "^4.17.20",
- "ripemd160": "^2.0.2",
- "unorm": "^1.6.0"
- }
- },
- "@dashevo/x11-hash-js": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/@dashevo/x11-hash-js/-/x11-hash-js-1.0.2.tgz",
- "integrity": "sha512-3vvnZweBca4URBXHF+FTrM4sdTpp3IMt73G1zUKQEdYm/kJkIKN94qpFai7YZDl87k64RCH+ckRZk6ruQPz5KQ=="
+ "@dashincubator/base58check": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/@dashincubator/base58check/-/base58check-1.3.1.tgz",
+ "integrity": "sha512-v2vYOwsTmbfaADJUg+0Vsw61/P5XtdDnjZtImDIC5DePIA/2lT9V+00nR5GsKfwc40WQ02tFlN+xoFt9cx+P7A=="
},
- "@eslint/eslintrc": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.0.tgz",
- "integrity": "sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==",
- "peer": true,
- "requires": {
- "ajv": "^6.12.4",
- "debug": "^4.3.2",
- "espree": "^9.3.2",
- "globals": "^13.15.0",
- "ignore": "^5.2.0",
- "import-fresh": "^3.2.1",
- "js-yaml": "^4.1.0",
- "minimatch": "^3.1.2",
- "strip-json-comments": "^3.1.1"
- }
+ "@dashincubator/blocktx": {
+ "version": "0.9.0-2",
+ "resolved": "https://registry.npmjs.org/@dashincubator/blocktx/-/blocktx-0.9.0-2.tgz",
+ "integrity": "sha512-g6IQxx/nuwsl3Dxzq61bE/UM8t/qQOnnnpF6BzPReHFd4XudQvQ+WcMXRJbrCQWj4yoR5SOCCBZ6IG7As3aVOg=="
},
- "@humanwhocodes/config-array": {
- "version": "0.9.5",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz",
- "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==",
- "peer": true,
- "requires": {
- "@humanwhocodes/object-schema": "^1.2.1",
- "debug": "^4.1.1",
- "minimatch": "^3.0.4"
- }
+ "@dashincubator/ripemd160": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/@dashincubator/ripemd160/-/ripemd160-2.3.0.tgz",
+ "integrity": "sha512-SfaUhvXti0Ut6ZhlAwurrRAG56phxqWozj72Hixx/v3LSQj1/wjkgTuDaexil672CzLD+RRWoPgp41BSM+DJJA=="
},
- "@humanwhocodes/object-schema": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz",
- "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
- "peer": true
+ "@dashincubator/secp256k1": {
+ "version": "1.7.1-1",
+ "resolved": "https://registry.npmjs.org/@dashincubator/secp256k1/-/secp256k1-1.7.1-1.tgz",
+ "integrity": "sha512-zkCfHPiIBWkSHojMEVBGNi9y9vX0NHGxkwO5zdZVlhbiqpWGOPbFRbUIwbEFdlnx4tS2x8w8InNzl36qVYWsGg=="
},
"@root/request": {
- "version": "1.9.1",
- "resolved": "https://registry.npmjs.org/@root/request/-/request-1.9.1.tgz",
- "integrity": "sha512-ROVgS5qgTvXDCI9XoJawJCB+QfC9jF7t3pFWmdUibjHqPt+2wV7pYSgth65qb65bK3qDIv9xXYF5FBECKhe8Iw=="
- },
- "@types/node": {
- "version": "12.20.55",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz",
- "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ=="
- },
- "acorn": {
- "version": "8.7.1",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz",
- "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==",
- "peer": true
- },
- "acorn-jsx": {
- "version": "5.3.2",
- "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
- "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
- "peer": true,
- "requires": {}
- },
- "ajv": {
- "version": "6.12.6",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
- "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
- "peer": true,
- "requires": {
- "fast-deep-equal": "^3.1.1",
- "fast-json-stable-stringify": "^2.0.0",
- "json-schema-traverse": "^0.4.1",
- "uri-js": "^4.2.2"
- }
- },
- "ansi-regex": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "peer": true
- },
- "ansi-styles": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
- "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
- "peer": true,
- "requires": {
- "color-convert": "^2.0.1"
- }
- },
- "argparse": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
- "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
- "peer": true
- },
- "balanced-match": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
- "peer": true
- },
- "base-x": {
- "version": "3.0.9",
- "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz",
- "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==",
- "requires": {
- "safe-buffer": "^5.0.1"
- }
- },
- "bloom-filter": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/bloom-filter/-/bloom-filter-0.2.0.tgz",
- "integrity": "sha512-RMG2RpnKczVzRsEYSPaT5rKsyj0w5/wpQRjaW4vOMe1WyUDQpoqxjNc10uROEjdhu63ytRt6aFRPXFePi/Rd7A=="
- },
- "bls-signatures": {
- "version": "0.2.5",
- "resolved": "https://registry.npmjs.org/bls-signatures/-/bls-signatures-0.2.5.tgz",
- "integrity": "sha512-5TzQNCtR4zWE4lM08EOMIT8l3b4h8g5LNKu50fUYP1PnupaLGSLklAcTto4lnH7VXpyhsar+74L9wNJII4E/4Q=="
- },
- "bn.js": {
- "version": "4.12.0",
- "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
- "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA=="
- },
- "brace-expansion": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
- "peer": true,
- "requires": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "brorand": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
- "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w=="
- },
- "bs58": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz",
- "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==",
- "requires": {
- "base-x": "^3.0.2"
- }
- },
- "callsites": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
- "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
- "peer": true
- },
- "chalk": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
- "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
- "peer": true,
- "requires": {
- "ansi-styles": "^4.1.0",
- "supports-color": "^7.1.0"
- }
- },
- "color-convert": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
- "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
- "peer": true,
- "requires": {
- "color-name": "~1.1.4"
- }
- },
- "color-name": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
- "peer": true
- },
- "concat-map": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
- "peer": true
- },
- "cross-spawn": {
- "version": "7.0.3",
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
- "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
- "peer": true,
- "requires": {
- "path-key": "^3.1.0",
- "shebang-command": "^2.0.0",
- "which": "^2.0.1"
- }
+ "version": "1.9.2",
+ "resolved": "https://registry.npmjs.org/@root/request/-/request-1.9.2.tgz",
+ "integrity": "sha512-wVaL9yVV9oDR9UNbPZa20qgY+4Ch6YN8JUkaE4el/uuS5dmhD8Lusm/ku8qJVNtmQA56XLzEDCRS6/vfpiHK2A=="
},
"dashsight": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/dashsight/-/dashsight-1.1.1.tgz",
- "integrity": "sha512-fcNGAxbFlqh2p3Al0Jq+byexPK0HrQMYGzpvgINVs1DI+bQLgI1tjgbpNJf8l7uu5LVmDBq8tjVKoH+hCSzPPA==",
+ "version": "1.3.0-0",
+ "resolved": "https://registry.npmjs.org/dashsight/-/dashsight-1.3.0-0.tgz",
+ "integrity": "sha512-KR2Vj6Ts94FLRFr0A3xqa4PAf3R9njrN5k7IHzbzDZjohb+cG3+11e48W0Dvt6CQGC4+yToRnUvlrBmGdpU5TQ==",
"requires": {
- "@root/request": "^1.9.1",
+ "@root/request": "^1.9.2",
"dotenv": "^16.0.1"
}
},
- "debug": {
- "version": "4.3.4",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
- "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
- "peer": true,
- "requires": {
- "ms": "2.1.2"
- }
- },
- "deep-is": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
- "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
- "peer": true
- },
- "doctrine": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
- "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
- "peer": true,
- "requires": {
- "esutils": "^2.0.2"
- }
- },
"dotenv": {
"version": "16.0.1",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.1.tgz",
"integrity": "sha512-1K6hR6wtk2FviQ4kEiSjFiH5rpzEVi8WW0x96aztHVMhEspNpc4DVOUTEHtEva5VThQ8IaBX1Pe4gSzpVVUsKQ==",
"optional": true
},
- "elliptic": {
- "version": "6.5.4",
- "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz",
- "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==",
- "requires": {
- "bn.js": "^4.11.9",
- "brorand": "^1.1.0",
- "hash.js": "^1.0.0",
- "hmac-drbg": "^1.0.1",
- "inherits": "^2.0.4",
- "minimalistic-assert": "^1.0.1",
- "minimalistic-crypto-utils": "^1.0.1"
- },
- "dependencies": {
- "inherits": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
- }
- }
- },
- "escape-string-regexp": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
- "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
- "peer": true
- },
- "eslint": {
- "version": "8.17.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.17.0.tgz",
- "integrity": "sha512-gq0m0BTJfci60Fz4nczYxNAlED+sMcihltndR8t9t1evnU/azx53x3t2UHXC/uRjcbvRw/XctpaNygSTcQD+Iw==",
- "peer": true,
- "requires": {
- "@eslint/eslintrc": "^1.3.0",
- "@humanwhocodes/config-array": "^0.9.2",
- "ajv": "^6.10.0",
- "chalk": "^4.0.0",
- "cross-spawn": "^7.0.2",
- "debug": "^4.3.2",
- "doctrine": "^3.0.0",
- "escape-string-regexp": "^4.0.0",
- "eslint-scope": "^7.1.1",
- "eslint-utils": "^3.0.0",
- "eslint-visitor-keys": "^3.3.0",
- "espree": "^9.3.2",
- "esquery": "^1.4.0",
- "esutils": "^2.0.2",
- "fast-deep-equal": "^3.1.3",
- "file-entry-cache": "^6.0.1",
- "functional-red-black-tree": "^1.0.1",
- "glob-parent": "^6.0.1",
- "globals": "^13.15.0",
- "ignore": "^5.2.0",
- "import-fresh": "^3.0.0",
- "imurmurhash": "^0.1.4",
- "is-glob": "^4.0.0",
- "js-yaml": "^4.1.0",
- "json-stable-stringify-without-jsonify": "^1.0.1",
- "levn": "^0.4.1",
- "lodash.merge": "^4.6.2",
- "minimatch": "^3.1.2",
- "natural-compare": "^1.4.0",
- "optionator": "^0.9.1",
- "regexpp": "^3.2.0",
- "strip-ansi": "^6.0.1",
- "strip-json-comments": "^3.1.0",
- "text-table": "^0.2.0",
- "v8-compile-cache": "^2.0.3"
- }
- },
- "eslint-config-prettier": {
- "version": "8.5.0",
- "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz",
- "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==",
- "requires": {}
- },
- "eslint-scope": {
- "version": "7.1.1",
- "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz",
- "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==",
- "peer": true,
- "requires": {
- "esrecurse": "^4.3.0",
- "estraverse": "^5.2.0"
- }
- },
- "eslint-utils": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz",
- "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==",
- "peer": true,
- "requires": {
- "eslint-visitor-keys": "^2.0.0"
- },
- "dependencies": {
- "eslint-visitor-keys": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz",
- "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==",
- "peer": true
- }
- }
- },
- "eslint-visitor-keys": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz",
- "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==",
- "peer": true
- },
- "espree": {
- "version": "9.3.2",
- "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.2.tgz",
- "integrity": "sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA==",
- "peer": true,
- "requires": {
- "acorn": "^8.7.1",
- "acorn-jsx": "^5.3.2",
- "eslint-visitor-keys": "^3.3.0"
- }
- },
- "esquery": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz",
- "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==",
- "peer": true,
- "requires": {
- "estraverse": "^5.1.0"
- }
- },
- "esrecurse": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
- "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
- "peer": true,
- "requires": {
- "estraverse": "^5.2.0"
- }
- },
- "estraverse": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
- "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
- "peer": true
- },
- "esutils": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
- "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
- "peer": true
- },
- "fast-deep-equal": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
- "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
- "peer": true
- },
- "fast-json-stable-stringify": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
- "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
- "peer": true
- },
- "fast-levenshtein": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
- "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
- "peer": true
- },
- "file-entry-cache": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
- "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
- "peer": true,
- "requires": {
- "flat-cache": "^3.0.4"
- }
- },
- "flat-cache": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
- "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==",
- "peer": true,
- "requires": {
- "flatted": "^3.1.0",
- "rimraf": "^3.0.2"
- }
- },
- "flatted": {
- "version": "3.2.5",
- "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz",
- "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==",
- "peer": true
- },
- "fs.realpath": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
- "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
- "peer": true
- },
- "functional-red-black-tree": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
- "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==",
- "peer": true
- },
- "glob": {
- "version": "7.2.3",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
- "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
- "peer": true,
- "requires": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^3.1.1",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
- }
- },
- "glob-parent": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
- "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
- "peer": true,
- "requires": {
- "is-glob": "^4.0.3"
- }
- },
- "globals": {
- "version": "13.15.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-13.15.0.tgz",
- "integrity": "sha512-bpzcOlgDhMG070Av0Vy5Owklpv1I6+j96GhUI7Rh7IzDCKLzboflLrrfqMu8NquDbiR4EOQk7XzJwqVJxicxog==",
- "peer": true,
- "requires": {
- "type-fest": "^0.20.2"
- }
- },
- "has-flag": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
- "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
- "peer": true
- },
- "hash-base": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz",
- "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==",
- "requires": {
- "inherits": "^2.0.4",
- "readable-stream": "^3.6.0",
- "safe-buffer": "^5.2.0"
- },
- "dependencies": {
- "inherits": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
- }
- }
- },
- "hash.js": {
- "version": "1.1.7",
- "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz",
- "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==",
- "requires": {
- "inherits": "^2.0.3",
- "minimalistic-assert": "^1.0.1"
- },
- "dependencies": {
- "inherits": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
- }
- }
- },
- "hmac-drbg": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
- "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==",
- "requires": {
- "hash.js": "^1.0.3",
- "minimalistic-assert": "^1.0.0",
- "minimalistic-crypto-utils": "^1.0.1"
- }
- },
- "ignore": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
- "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==",
- "peer": true
- },
- "import-fresh": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
- "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
- "peer": true,
- "requires": {
- "parent-module": "^1.0.0",
- "resolve-from": "^4.0.0"
- }
- },
- "imurmurhash": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
- "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
- "peer": true
- },
- "inflight": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
- "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
- "peer": true,
- "requires": {
- "once": "^1.3.0",
- "wrappy": "1"
- }
- },
- "inherits": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
- "integrity": "sha512-8nWq2nLTAwd02jTqJExUYFSD/fKq6VH9Y/oG2accc/kdI0V98Bag8d5a4gi3XHz73rDWa2PvTtvcWYquKqSENA=="
- },
- "is-extglob": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
- "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
- "peer": true
- },
- "is-glob": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
- "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
- "peer": true,
- "requires": {
- "is-extglob": "^2.1.1"
- }
- },
- "isexe": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
- "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
- "peer": true
- },
- "js-yaml": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
- "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
- "peer": true,
- "requires": {
- "argparse": "^2.0.1"
- }
- },
- "json-schema-traverse": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
- "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
- "peer": true
- },
- "json-stable-stringify-without-jsonify": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
- "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
- "peer": true
- },
- "levn": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
- "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
- "peer": true,
- "requires": {
- "prelude-ls": "^1.2.1",
- "type-check": "~0.4.0"
- }
- },
- "lodash": {
- "version": "4.17.21",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
- "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
- },
- "lodash.merge": {
- "version": "4.6.2",
- "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
- "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
- "peer": true
- },
- "minimalistic-assert": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
- "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A=="
- },
- "minimalistic-crypto-utils": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz",
- "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg=="
- },
- "minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
- "peer": true,
- "requires": {
- "brace-expansion": "^1.1.7"
- }
- },
- "ms": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
- "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
- "peer": true
- },
- "natural-compare": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
- "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
- "peer": true
- },
- "once": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
- "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
- "peer": true,
- "requires": {
- "wrappy": "1"
- }
- },
- "optionator": {
- "version": "0.9.1",
- "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
- "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==",
- "peer": true,
- "requires": {
- "deep-is": "^0.1.3",
- "fast-levenshtein": "^2.0.6",
- "levn": "^0.4.1",
- "prelude-ls": "^1.2.1",
- "type-check": "^0.4.0",
- "word-wrap": "^1.2.3"
- }
- },
- "parent-module": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
- "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
- "peer": true,
- "requires": {
- "callsites": "^3.0.0"
- }
- },
- "path-is-absolute": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
- "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
- "peer": true
- },
- "path-key": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
- "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
- "peer": true
- },
- "prelude-ls": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
- "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
- "peer": true
- },
"psl": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
@@ -1956,7 +203,8 @@
"punycode": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
- "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
+ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
+ "optional": true
},
"qrcode-svg": {
"version": "1.1.0",
@@ -1964,111 +212,6 @@
"integrity": "sha512-XyQCIXux1zEIA3NPb0AeR8UMYvXZzWEhgdBgBjH9gO7M48H9uoHzviNz8pXw3UzrAcxRRRn9gxHewAVK7bn9qw==",
"optional": true
},
- "readable-stream": {
- "version": "3.6.0",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
- "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
- "requires": {
- "inherits": "^2.0.3",
- "string_decoder": "^1.1.1",
- "util-deprecate": "^1.0.1"
- },
- "dependencies": {
- "inherits": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
- }
- }
- },
- "regexpp": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz",
- "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==",
- "peer": true
- },
- "resolve-from": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
- "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
- "peer": true
- },
- "rimraf": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
- "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
- "peer": true,
- "requires": {
- "glob": "^7.1.3"
- }
- },
- "ripemd160": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz",
- "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==",
- "requires": {
- "hash-base": "^3.0.0",
- "inherits": "^2.0.1"
- }
- },
- "safe-buffer": {
- "version": "5.2.1",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
- "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
- },
- "shebang-command": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
- "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
- "peer": true,
- "requires": {
- "shebang-regex": "^3.0.0"
- }
- },
- "shebang-regex": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
- "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
- "peer": true
- },
- "string_decoder": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
- "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
- "requires": {
- "safe-buffer": "~5.2.0"
- }
- },
- "strip-ansi": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "peer": true,
- "requires": {
- "ansi-regex": "^5.0.1"
- }
- },
- "strip-json-comments": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
- "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
- "peer": true
- },
- "supports-color": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
- "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
- "peer": true,
- "requires": {
- "has-flag": "^4.0.0"
- }
- },
- "text-table": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
- "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
- "peer": true
- },
"tough-cookie": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz",
@@ -2080,73 +223,12 @@
"universalify": "^0.1.2"
}
},
- "type-check": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
- "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
- "peer": true,
- "requires": {
- "prelude-ls": "^1.2.1"
- }
- },
- "type-fest": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
- "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
- "peer": true
- },
"universalify": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
"integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
"optional": true
},
- "unorm": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/unorm/-/unorm-1.6.0.tgz",
- "integrity": "sha512-b2/KCUlYZUeA7JFUuRJZPUtr4gZvBh7tavtv4fvk4+KV9pfGiR6CQAQAWl49ZpR3ts2dk4FYkP7EIgDJoiOLDA=="
- },
- "uri-js": {
- "version": "4.4.1",
- "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
- "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
- "peer": true,
- "requires": {
- "punycode": "^2.1.0"
- }
- },
- "util-deprecate": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
- },
- "v8-compile-cache": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz",
- "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==",
- "peer": true
- },
- "which": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
- "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
- "peer": true,
- "requires": {
- "isexe": "^2.0.0"
- }
- },
- "word-wrap": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
- "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
- "peer": true
- },
- "wrappy": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
- "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
- "peer": true
- },
"ws": {
"version": "8.8.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.8.0.tgz",
diff --git a/package.json b/package.json
index 7146cde..b9c2a31 100644
--- a/package.json
+++ b/package.json
@@ -1,11 +1,14 @@
{
"name": "crowdnode",
- "version": "1.7.0",
+ "version": "1.8.0",
"description": "Manage your stake in Đash with the CrowdNode Blockchain API",
"main": "./index.js",
"browser": {
- "./lib/request.js": "./lib/request-browser.js",
- "./lib/dashcore.js": "./lib/browser-dashcore.js"
+ "index.js": "crowdnode.js",
+ "./lib/dashcore.js": "./lib/browser-dashcore.js",
+ "./lib/request.js": "./shims/request-browser.js",
+ "./shims/crypto-node.js": "./shims/crypto-browser.js",
+ "crypto": false
},
"bin": {
"crowdnode": "./bin/crowdnode.js"
@@ -39,11 +42,14 @@
},
"homepage": "https://github.com/dashhive/crowdnode.js#readme",
"dependencies": {
- "@dashevo/dashcore-lib": "^0.19.41",
- "dashsight": "^1.1.1"
+ "@dashincubator/base58check": "^1.3.1",
+ "@dashincubator/blocktx": "^0.9.0-2",
+ "@dashincubator/ripemd160": "^2.3.0",
+ "@dashincubator/secp256k1": "^1.7.1-1",
+ "dashsight": "^1.3.0-0"
},
"optionalDependencies": {
- "@root/request": "^1.9.1",
+ "@root/request": "^1.9.2",
"dotenv": "^16.0.1",
"qrcode-svg": "^1.1.0",
"tough-cookie": "^4.0.0",
diff --git a/shims/crypto-node.js b/shims/crypto-node.js
new file mode 100644
index 0000000..c6d31e9
--- /dev/null
+++ b/shims/crypto-node.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = require("node:crypto");
diff --git a/lib/browser-request.js b/shims/request-browser.js
similarity index 100%
rename from lib/browser-request.js
rename to shims/request-browser.js
diff --git a/types.js b/types.js
index 3e40fd8..db1c9ac 100644
--- a/types.js
+++ b/types.js
@@ -67,7 +67,7 @@
* @typedef {Object} InsightSocketEventData
* @property {String} txid - hex
* @property {Number} valueOut - float
- * @property {Array>} vout - addr and duffs
+ * @property {Array>} vout - addr and satoshis
* @property {Boolean} isRBF
* @property {Boolean} txlock
*