From ebbd3aac0316a805480bdd8e3667a041b818fd28 Mon Sep 17 00:00:00 2001 From: Alexey Date: Fri, 22 May 2020 12:35:00 +0300 Subject: [PATCH] formating --- .editorconfig | 9 + .eslintrc.json | 39 ++ cli.js | 924 ++++++++++++++++++++-------------------- package-lock.json | 1018 ++++++++++++++++++++++++++++++++++++++------- package.json | 3 + 5 files changed, 1392 insertions(+), 601 deletions(-) create mode 100644 .editorconfig create mode 100644 .eslintrc.json diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..53b061a --- /dev/null +++ b/.editorconfig @@ -0,0 +1,9 @@ +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true \ No newline at end of file diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..034524f --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,39 @@ +{ + "env": { + "node": true, + "browser": true, + "es6": true, + "mocha": true + }, + "extends": "eslint:recommended", + "globals": { + "Atomics": "readonly", + "SharedArrayBuffer": "readonly" + }, + "parserOptions": { + "ecmaVersion": 2018 + }, + "rules": { + "indent": [ + "error", + 2 + ], + "linebreak-style": [ + "error", + "unix" + ], + "quotes": [ + "error", + "single" + ], + "semi": [ + "error", + "never" + ], + "object-curly-spacing": [ + "error", + "always" + ], + "require-await": "error" + } +} diff --git a/cli.js b/cli.js index 4f11e08..3b117a2 100755 --- a/cli.js +++ b/cli.js @@ -34,33 +34,33 @@ const pedersenHash = data => circomlib.babyJub.unpackPoint(circomlib.pedersenHas /** BigNumber to hex string of specified length */ function toHex(number, length = 32) { - const str = number instanceof Buffer ? number.toString('hex') : bigInt(number).toString(16) - return '0x' + str.padStart(length * 2, '0') + const str = number instanceof Buffer ? number.toString('hex') : bigInt(number).toString(16) + return '0x' + str.padStart(length * 2, '0') } /** Display ETH account balance */ async function printETHBalance({ address, name }) { - console.log(`${name} ETH balance is`, web3.utils.fromWei(await web3.eth.getBalance(address))) + console.log(`${name} ETH balance is`, web3.utils.fromWei(await web3.eth.getBalance(address))) } /** Display ERC20 account balance */ async function printERC20Balance({ address, name, tokenAddress }) { - const erc20ContractJson = require('./build/contracts/ERC20Mock.json') - erc20 = tokenAddress ? new web3.eth.Contract(erc20ContractJson.abi, tokenAddress) : erc20 - console.log(`${name} Token Balance is`, web3.utils.fromWei(await erc20.methods.balanceOf(address).call())) + const erc20ContractJson = require('./build/contracts/ERC20Mock.json') + erc20 = tokenAddress ? new web3.eth.Contract(erc20ContractJson.abi, tokenAddress) : erc20 + console.log(`${name} Token Balance is`, web3.utils.fromWei(await erc20.methods.balanceOf(address).call())) } /** * Create deposit object from secret and nullifier */ function createDeposit({ nullifier, secret }) { - const deposit = { nullifier, secret } - deposit.preimage = Buffer.concat([deposit.nullifier.leInt2Buff(31), deposit.secret.leInt2Buff(31)]) - deposit.commitment = pedersenHash(deposit.preimage) - deposit.commitmentHex = toHex(deposit.commitment) - deposit.nullifierHash = pedersenHash(deposit.nullifier.leInt2Buff(31)) - deposit.nullifierHex = toHex(deposit.nullifierHash) - return deposit + const deposit = { nullifier, secret } + deposit.preimage = Buffer.concat([deposit.nullifier.leInt2Buff(31), deposit.secret.leInt2Buff(31)]) + deposit.commitment = pedersenHash(deposit.preimage) + deposit.commitmentHex = toHex(deposit.commitment) + deposit.nullifierHash = pedersenHash(deposit.nullifier.leInt2Buff(31)) + deposit.nullifierHex = toHex(deposit.nullifierHash) + return deposit } /** @@ -69,42 +69,42 @@ function createDeposit({ nullifier, secret }) { * @param amount Deposit amount */ async function deposit({ currency, amount }) { - const deposit = createDeposit({ nullifier: rbigint(31), secret: rbigint(31) }) - const note = toHex(deposit.preimage, 62) - const noteString = `tornado-${currency}-${amount}-${netId}-${note}` - console.log(`Your note: ${noteString}`) - if (currency === 'eth') { - await printETHBalance({ address: tornado._address, name: 'Tornado' }) - await printETHBalance({ address: senderAccount, name: 'Sender account' }) - const value = isLocalRPC ? ETH_AMOUNT : fromDecimals({ amount, decimals: 18 }) - console.log('Submitting deposit transaction') - await tornado.methods.deposit(toHex(deposit.commitment)).send({ value, from: senderAccount, gas: 2e6 }) - await printETHBalance({ address: tornado._address, name: 'Tornado' }) - await printETHBalance({ address: senderAccount, name: 'Sender account' }) - } else { // a token - await printERC20Balance({ address: tornado._address, name: 'Tornado' }) - await printERC20Balance({ address: senderAccount, name: 'Sender account' }) - const decimals = isLocalRPC ? 18 : config.deployments[`netId${netId}`][currency].decimals - const tokenAmount = isLocalRPC ? TOKEN_AMOUNT : fromDecimals({ amount, decimals }) - if (isLocalRPC) { - console.log('Minting some test tokens to deposit') - await erc20.methods.mint(senderAccount, tokenAmount).send({ from: senderAccount, gas: 2e6 }) - } - - const allowance = await erc20.methods.allowance(senderAccount, tornado._address).call({ from: senderAccount }) - console.log('Current allowance is', fromWei(allowance)) - if (toBN(allowance).lt(toBN(tokenAmount))) { - console.log('Approving tokens for deposit') - await erc20.methods.approve(tornado._address, tokenAmount).send({ from: senderAccount, gas: 1e6 }) - } - - console.log('Submitting deposit transaction') - await tornado.methods.deposit(toHex(deposit.commitment)).send({ from: senderAccount, gas: 2e6 }) - await printERC20Balance({ address: tornado._address, name: 'Tornado' }) - await printERC20Balance({ address: senderAccount, name: 'Sender account' }) + const deposit = createDeposit({ nullifier: rbigint(31), secret: rbigint(31) }) + const note = toHex(deposit.preimage, 62) + const noteString = `tornado-${currency}-${amount}-${netId}-${note}` + console.log(`Your note: ${noteString}`) + if (currency === 'eth') { + await printETHBalance({ address: tornado._address, name: 'Tornado' }) + await printETHBalance({ address: senderAccount, name: 'Sender account' }) + const value = isLocalRPC ? ETH_AMOUNT : fromDecimals({ amount, decimals: 18 }) + console.log('Submitting deposit transaction') + await tornado.methods.deposit(toHex(deposit.commitment)).send({ value, from: senderAccount, gas: 2e6 }) + await printETHBalance({ address: tornado._address, name: 'Tornado' }) + await printETHBalance({ address: senderAccount, name: 'Sender account' }) + } else { // a token + await printERC20Balance({ address: tornado._address, name: 'Tornado' }) + await printERC20Balance({ address: senderAccount, name: 'Sender account' }) + const decimals = isLocalRPC ? 18 : config.deployments[`netId${netId}`][currency].decimals + const tokenAmount = isLocalRPC ? TOKEN_AMOUNT : fromDecimals({ amount, decimals }) + if (isLocalRPC) { + console.log('Minting some test tokens to deposit') + await erc20.methods.mint(senderAccount, tokenAmount).send({ from: senderAccount, gas: 2e6 }) } - return noteString + const allowance = await erc20.methods.allowance(senderAccount, tornado._address).call({ from: senderAccount }) + console.log('Current allowance is', fromWei(allowance)) + if (toBN(allowance).lt(toBN(tokenAmount))) { + console.log('Approving tokens for deposit') + await erc20.methods.approve(tornado._address, tokenAmount).send({ from: senderAccount, gas: 1e6 }) + } + + console.log('Submitting deposit transaction') + await tornado.methods.deposit(toHex(deposit.commitment)).send({ from: senderAccount, gas: 2e6 }) + await printERC20Balance({ address: tornado._address, name: 'Tornado' }) + await printERC20Balance({ address: senderAccount, name: 'Sender account' }) + } + + return noteString } /** @@ -114,28 +114,28 @@ async function deposit({ currency, amount }) { * @param deposit Deposit object */ async function generateMerkleProof(deposit) { - // Get all deposit events from smart contract and assemble merkle tree from them - console.log('Getting current state from tornado contract') - const events = await tornado.getPastEvents('Deposit', { fromBlock: 0, toBlock: 'latest' }) - const leaves = events - .sort((a, b) => a.returnValues.leafIndex - b.returnValues.leafIndex) // Sort events in chronological order - .map(e => e.returnValues.commitment) - const tree = new merkleTree(MERKLE_TREE_HEIGHT, leaves) + // Get all deposit events from smart contract and assemble merkle tree from them + console.log('Getting current state from tornado contract') + const events = await tornado.getPastEvents('Deposit', { fromBlock: 0, toBlock: 'latest' }) + const leaves = events + .sort((a, b) => a.returnValues.leafIndex - b.returnValues.leafIndex) // Sort events in chronological order + .map(e => e.returnValues.commitment) + const tree = new merkleTree(MERKLE_TREE_HEIGHT, leaves) - // Find current commitment in the tree - const depositEvent = events.find(e => e.returnValues.commitment === toHex(deposit.commitment)) - const leafIndex = depositEvent ? depositEvent.returnValues.leafIndex : -1 + // Find current commitment in the tree + const depositEvent = events.find(e => e.returnValues.commitment === toHex(deposit.commitment)) + const leafIndex = depositEvent ? depositEvent.returnValues.leafIndex : -1 - // Validate that our data is correct - const root = await tree.root() - const isValidRoot = await tornado.methods.isKnownRoot(toHex(root)).call() - const isSpent = await tornado.methods.isSpent(toHex(deposit.nullifierHash)).call() - assert(isValidRoot === true, 'Merkle tree is corrupted') - assert(isSpent === false, 'The note is already spent') - assert(leafIndex >= 0, 'The deposit is not found in the tree') + // Validate that our data is correct + const root = await tree.root() + const isValidRoot = await tornado.methods.isKnownRoot(toHex(root)).call() + const isSpent = await tornado.methods.isSpent(toHex(deposit.nullifierHash)).call() + assert(isValidRoot === true, 'Merkle tree is corrupted') + assert(isSpent === false, 'The note is already spent') + assert(leafIndex >= 0, 'The deposit is not found in the tree') - // Compute merkle proof of our commitment - return tree.path(leafIndex) + // Compute merkle proof of our commitment + return tree.path(leafIndex) } /** @@ -147,42 +147,42 @@ async function generateMerkleProof(deposit) { * @param refund Receive ether for exchanged tokens */ async function generateProof({ deposit, recipient, relayerAddress = 0, fee = 0, refund = 0 }) { - // Compute merkle proof of our commitment - const { root, path_elements, path_index } = await generateMerkleProof(deposit) + // Compute merkle proof of our commitment + const { root, path_elements, path_index } = await generateMerkleProof(deposit) - // Prepare circuit input - const input = { - // Public snark inputs - root: root, - nullifierHash: deposit.nullifierHash, - recipient: bigInt(recipient), - relayer: bigInt(relayerAddress), - fee: bigInt(fee), - refund: bigInt(refund), + // Prepare circuit input + const input = { + // Public snark inputs + root: root, + nullifierHash: deposit.nullifierHash, + recipient: bigInt(recipient), + relayer: bigInt(relayerAddress), + fee: bigInt(fee), + refund: bigInt(refund), - // Private snark inputs - nullifier: deposit.nullifier, - secret: deposit.secret, - pathElements: path_elements, - pathIndices: path_index, - } + // Private snark inputs + nullifier: deposit.nullifier, + secret: deposit.secret, + pathElements: path_elements, + pathIndices: path_index, + } - console.log('Generating SNARK proof') - console.time('Proof time') - const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key) - const { proof } = websnarkUtils.toSolidityInput(proofData) - console.timeEnd('Proof time') + console.log('Generating SNARK proof') + console.time('Proof time') + const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key) + const { proof } = websnarkUtils.toSolidityInput(proofData) + console.timeEnd('Proof time') - const args = [ - toHex(input.root), - toHex(input.nullifierHash), - toHex(input.recipient, 20), - toHex(input.relayer, 20), - toHex(input.fee), - toHex(input.refund) - ] + const args = [ + toHex(input.root), + toHex(input.nullifierHash), + toHex(input.recipient, 20), + toHex(input.relayer, 20), + toHex(input.fee), + toHex(input.refund) + ] - return { proof, args } + return { proof, args } } /** @@ -191,180 +191,180 @@ async function generateProof({ deposit, recipient, relayerAddress = 0, fee = 0, * @param recipient Recipient address */ async function withdraw({ deposit, currency, amount, recipient, relayerURL, refund = '0' }) { - if (currency === 'eth' && refund !== '0') { - throw new Error('The ETH purchase is supposted to be 0 for ETH withdrawals') + if (currency === 'eth' && refund !== '0') { + throw new Error('The ETH purchase is supposted to be 0 for ETH withdrawals') + } + refund = toWei(refund) + if (relayerURL) { + if (relayerURL.endsWith('.eth')) { + throw new Error('ENS name resolving is not supported. Please provide DNS name of the relayer. See instuctions in README.md') } - refund = toWei(refund) - if (relayerURL) { - if (relayerURL.endsWith('.eth')) { - throw new Error('ENS name resolving is not supported. Please provide DNS name of the relayer. See instuctions in README.md') - } - const relayerStatus = await axios.get(relayerURL + '/status') - const { relayerAddress, netId, gasPrices, ethPrices, relayerServiceFee } = relayerStatus.data - assert(netId === await web3.eth.net.getId() || netId === '*', 'This relay is for different network') - console.log('Relay address: ', relayerAddress) + const relayerStatus = await axios.get(relayerURL + '/status') + const { relayerAddress, netId, gasPrices, ethPrices, relayerServiceFee } = relayerStatus.data + assert(netId === await web3.eth.net.getId() || netId === '*', 'This relay is for different network') + console.log('Relay address: ', relayerAddress) - const decimals = isLocalRPC ? 18 : config.deployments[`netId${netId}`][currency].decimals - const fee = calculateFee({ gasPrices, currency, amount, refund, ethPrices, relayerServiceFee, decimals }) - if (fee.gt(fromDecimals({ amount, decimals }))) { - throw new Error('Too high refund') - } - const { proof, args } = await generateProof({ deposit, recipient, relayerAddress, fee, refund }) - - console.log('Sending withdraw transaction through relay') - try { - const relay = await axios.post(relayerURL + '/relay', { contract: tornado._address, proof, args }) - if (netId === 1 || netId === 42) { - console.log(`Transaction submitted through the relay. View transaction on etherscan https://${getCurrentNetworkName()}etherscan.io/tx/${relay.data.txHash}`) - } else { - console.log(`Transaction submitted through the relay. The transaction hash is ${relay.data.txHash}`) - } - - const receipt = await waitForTxReceipt({ txHash: relay.data.txHash }) - console.log('Transaction mined in block', receipt.blockNumber) - } catch (e) { - if (e.response) { - console.error(e.response.data.error) - } else { - console.error(e.message) - } - } - } else { // using private key - const { proof, args } = await generateProof({ deposit, recipient, refund }) - - console.log('Submitting withdraw transaction') - await tornado.methods.withdraw(proof, ...args).send({ from: senderAccount, value: refund.toString(), gas: 1e6 }) - .on('transactionHash', function (txHash) { - if (netId === 1 || netId === 42) { - console.log(`View transaction on etherscan https://${getCurrentNetworkName()}etherscan.io/tx/${txHash}`) - } else { - console.log(`The transaction hash is ${txHash}`) - } - }).on('error', function (e) { - console.error('on transactionHash error', e.message) - }) + const decimals = isLocalRPC ? 18 : config.deployments[`netId${netId}`][currency].decimals + const fee = calculateFee({ gasPrices, currency, amount, refund, ethPrices, relayerServiceFee, decimals }) + if (fee.gt(fromDecimals({ amount, decimals }))) { + throw new Error('Too high refund') } - console.log('Done') + const { proof, args } = await generateProof({ deposit, recipient, relayerAddress, fee, refund }) + + console.log('Sending withdraw transaction through relay') + try { + const relay = await axios.post(relayerURL + '/relay', { contract: tornado._address, proof, args }) + if (netId === 1 || netId === 42) { + console.log(`Transaction submitted through the relay. View transaction on etherscan https://${getCurrentNetworkName()}etherscan.io/tx/${relay.data.txHash}`) + } else { + console.log(`Transaction submitted through the relay. The transaction hash is ${relay.data.txHash}`) + } + + const receipt = await waitForTxReceipt({ txHash: relay.data.txHash }) + console.log('Transaction mined in block', receipt.blockNumber) + } catch (e) { + if (e.response) { + console.error(e.response.data.error) + } else { + console.error(e.message) + } + } + } else { // using private key + const { proof, args } = await generateProof({ deposit, recipient, refund }) + + console.log('Submitting withdraw transaction') + await tornado.methods.withdraw(proof, ...args).send({ from: senderAccount, value: refund.toString(), gas: 1e6 }) + .on('transactionHash', function (txHash) { + if (netId === 1 || netId === 42) { + console.log(`View transaction on etherscan https://${getCurrentNetworkName()}etherscan.io/tx/${txHash}`) + } else { + console.log(`The transaction hash is ${txHash}`) + } + }).on('error', function (e) { + console.error('on transactionHash error', e.message) + }) + } + console.log('Done') } function fromDecimals({ amount, decimals }) { - amount = amount.toString() - let ether = amount.toString() - const base = new BN('10').pow(new BN(decimals)) - const baseLength = base.toString(10).length - 1 || 1 + amount = amount.toString() + let ether = amount.toString() + const base = new BN('10').pow(new BN(decimals)) + const baseLength = base.toString(10).length - 1 || 1 - const negative = ether.substring(0, 1) === '-' - if (negative) { - ether = ether.substring(1) - } + const negative = ether.substring(0, 1) === '-' + if (negative) { + ether = ether.substring(1) + } - if (ether === '.') { - throw new Error('[ethjs-unit] while converting number ' + amount + ' to wei, invalid value') - } + if (ether === '.') { + throw new Error('[ethjs-unit] while converting number ' + amount + ' to wei, invalid value') + } - // Split it into a whole and fractional part - const comps = ether.split('.') - if (comps.length > 2) { - throw new Error( - '[ethjs-unit] while converting number ' + amount + ' to wei, too many decimal points' - ) - } + // Split it into a whole and fractional part + const comps = ether.split('.') + if (comps.length > 2) { + throw new Error( + '[ethjs-unit] while converting number ' + amount + ' to wei, too many decimal points' + ) + } - let whole = comps[0] - let fraction = comps[1] + let whole = comps[0] + let fraction = comps[1] - if (!whole) { - whole = '0' - } - if (!fraction) { - fraction = '0' - } - if (fraction.length > baseLength) { - throw new Error( - '[ethjs-unit] while converting number ' + amount + ' to wei, too many decimal places' - ) - } + if (!whole) { + whole = '0' + } + if (!fraction) { + fraction = '0' + } + if (fraction.length > baseLength) { + throw new Error( + '[ethjs-unit] while converting number ' + amount + ' to wei, too many decimal places' + ) + } - while (fraction.length < baseLength) { - fraction += '0' - } + while (fraction.length < baseLength) { + fraction += '0' + } - whole = new BN(whole) - fraction = new BN(fraction) - let wei = whole.mul(base).add(fraction) + whole = new BN(whole) + fraction = new BN(fraction) + let wei = whole.mul(base).add(fraction) - if (negative) { - wei = wei.mul(negative) - } + if (negative) { + wei = wei.mul(negative) + } - return new BN(wei.toString(10), 10) + return new BN(wei.toString(10), 10) } function toDecimals(value, decimals, fixed) { - const zero = new BN(0) - const negative1 = new BN(-1) - decimals = decimals || 18 - fixed = fixed || 7 + const zero = new BN(0) + const negative1 = new BN(-1) + decimals = decimals || 18 + fixed = fixed || 7 - value = new BN(value) - const negative = value.lt(zero) - const base = new BN('10').pow(new BN(decimals)) - const baseLength = base.toString(10).length - 1 || 1 + value = new BN(value) + const negative = value.lt(zero) + const base = new BN('10').pow(new BN(decimals)) + const baseLength = base.toString(10).length - 1 || 1 - if (negative) { - value = value.mul(negative1) - } + if (negative) { + value = value.mul(negative1) + } - let fraction = value.mod(base).toString(10) - while (fraction.length < baseLength) { - fraction = `0${fraction}` - } - fraction = fraction.match(/^([0-9]*[1-9]|0)(0*)/)[1] + let fraction = value.mod(base).toString(10) + while (fraction.length < baseLength) { + fraction = `0${fraction}` + } + fraction = fraction.match(/^([0-9]*[1-9]|0)(0*)/)[1] - const whole = value.div(base).toString(10) - value = `${whole}${fraction === '0' ? '' : `.${fraction}`}` + const whole = value.div(base).toString(10) + value = `${whole}${fraction === '0' ? '' : `.${fraction}`}` - if (negative) { - value = `-${value}` - } + if (negative) { + value = `-${value}` + } - if (fixed) { - value = value.slice(0, fixed) - } + if (fixed) { + value = value.slice(0, fixed) + } - return value + return value } function getCurrentNetworkName() { - switch (netId) { - case 1: - return '' - case 42: - return 'kovan.' - } + switch (netId) { + case 1: + return '' + case 42: + return 'kovan.' + } } function calculateFee({ gasPrices, currency, amount, refund, ethPrices, relayerServiceFee, decimals }) { - const total = toBN(fromDecimals({ amount, decimals })) - const fee = relayerServiceFee - const decimalsPoint = Math.floor(fee) === fee ? 0 : fee.toString().split('.')[1].length - const roundDecimal = 10 ** decimalsPoint - relayerServiceFee = total.mul(toBN(fee * roundDecimal)).div(toBN(roundDecimal * 100)) - const ethFee = toBN(toWei(gasPrices.fast.toString(), 'gwei')).mul(toBN('500000')) + const total = toBN(fromDecimals({ amount, decimals })) + const fee = relayerServiceFee + const decimalsPoint = Math.floor(fee) === fee ? 0 : fee.toString().split('.')[1].length + const roundDecimal = 10 ** decimalsPoint + relayerServiceFee = total.mul(toBN(fee * roundDecimal)).div(toBN(roundDecimal * 100)) + const ethFee = toBN(toWei(gasPrices.fast.toString(), 'gwei')).mul(toBN('500000')) - switch (currency) { - case 'eth': { - return ethFee.add(relayerServiceFee) - } - default: { - const tokenFee = ethFee - .mul(toBN(10 ** decimals)) - .div(toBN(ethPrices[currency])) - return tokenFee.add(relayerServiceFee) - } - } + switch (currency) { + case 'eth': { + return ethFee.add(relayerServiceFee) + } + default: { + const tokenFee = ethFee + .mul(toBN(10 ** decimals)) + .div(toBN(ethPrices[currency])) + return tokenFee.add(relayerServiceFee) + } + } } /** @@ -374,21 +374,21 @@ function calculateFee({ gasPrices, currency, amount, refund, ethPrices, relayerS * @param delay */ function waitForTxReceipt({ txHash, attempts = 60, delay = 1000 }) { - return new Promise((resolve, reject) => { - const checkForTx = async (txHash, retryAttempt = 0) => { - const result = await web3.eth.getTransactionReceipt(txHash) - if (!result || !result.blockNumber) { - if (retryAttempt <= attempts) { - setTimeout(() => checkForTx(txHash, retryAttempt + 1), delay) - } else { - reject(new Error('tx was not mined')) - } - } else { - resolve(result) - } + return new Promise((resolve, reject) => { + const checkForTx = async (txHash, retryAttempt = 0) => { + const result = await web3.eth.getTransactionReceipt(txHash) + if (!result || !result.blockNumber) { + if (retryAttempt <= attempts) { + setTimeout(() => checkForTx(txHash, retryAttempt + 1), delay) + } else { + reject(new Error('tx was not mined')) } - checkForTx(txHash) - }) + } else { + resolve(result) + } + } + checkForTx(txHash) + }) } /** @@ -396,242 +396,242 @@ function waitForTxReceipt({ txHash, attempts = 60, delay = 1000 }) { * @param noteString the note */ function parseNote(noteString) { - const noteRegex = /tornado-(?\w+)-(?[\d.]+)-(?\d+)-0x(?[0-9a-fA-F]{124})/g - const match = noteRegex.exec(noteString) - if (!match) { - throw new Error('The note has invalid format') - } + const noteRegex = /tornado-(?\w+)-(?[\d.]+)-(?\d+)-0x(?[0-9a-fA-F]{124})/g + const match = noteRegex.exec(noteString) + if (!match) { + throw new Error('The note has invalid format') + } - const buf = Buffer.from(match.groups.note, 'hex') - const nullifier = bigInt.leBuff2int(buf.slice(0, 31)) - const secret = bigInt.leBuff2int(buf.slice(31, 62)) - const deposit = createDeposit({ nullifier, secret }) - const netId = Number(match.groups.netId) + const buf = Buffer.from(match.groups.note, 'hex') + const nullifier = bigInt.leBuff2int(buf.slice(0, 31)) + const secret = bigInt.leBuff2int(buf.slice(31, 62)) + const deposit = createDeposit({ nullifier, secret }) + const netId = Number(match.groups.netId) - return { currency: match.groups.currency, amount: match.groups.amount, netId, deposit } + return { currency: match.groups.currency, amount: match.groups.amount, netId, deposit } } async function loadDepositData({ deposit }) { - try { - const eventWhenHappened = await tornado.getPastEvents('Deposit', { - filter: { - commitment: deposit.commitmentHex - }, - fromBlock: 0, - toBlock: 'latest' - }) - if (eventWhenHappened.length === 0) { - throw new Error('There is no related deposit, the note is invalid') - } - - const { timestamp } = eventWhenHappened[0].returnValues - const txHash = eventWhenHappened[0].transactionHash - const isSpent = await tornado.methods.isSpent(deposit.nullifierHex).call() - const receipt = await web3.eth.getTransactionReceipt(txHash) - - return { timestamp, txHash, isSpent, from: receipt.from, commitment: deposit.commitmentHex } - } catch (e) { - console.error('loadDepositData', e) + try { + const eventWhenHappened = await tornado.getPastEvents('Deposit', { + filter: { + commitment: deposit.commitmentHex + }, + fromBlock: 0, + toBlock: 'latest' + }) + if (eventWhenHappened.length === 0) { + throw new Error('There is no related deposit, the note is invalid') } - return {} + + const { timestamp } = eventWhenHappened[0].returnValues + const txHash = eventWhenHappened[0].transactionHash + const isSpent = await tornado.methods.isSpent(deposit.nullifierHex).call() + const receipt = await web3.eth.getTransactionReceipt(txHash) + + return { timestamp, txHash, isSpent, from: receipt.from, commitment: deposit.commitmentHex } + } catch (e) { + console.error('loadDepositData', e) + } + return {} } async function loadWithdrawalData({ amount, currency, deposit }) { - try { - const events = await await tornado.getPastEvents('Withdrawal', { - fromBlock: 0, - toBlock: 'latest' - }) + try { + const events = await await tornado.getPastEvents('Withdrawal', { + fromBlock: 0, + toBlock: 'latest' + }) - const withdrawEvent = events.filter((event) => { - return event.returnValues.nullifierHash === deposit.nullifierHex - })[0] + const withdrawEvent = events.filter((event) => { + return event.returnValues.nullifierHash === deposit.nullifierHex + })[0] - const fee = withdrawEvent.returnValues.fee - const decimals = config.deployments[`netId${netId}`][currency].decimals - const withdrawalAmount = toBN(fromDecimals({ amount, decimals })).sub( - toBN(fee) - ) - const { timestamp } = await web3.eth.getBlock(withdrawEvent.blockHash) - return { - amount: toDecimals(withdrawalAmount, decimals, 9), - txHash: withdrawEvent.transactionHash, - to: withdrawEvent.returnValues.to, - timestamp, - nullifier: deposit.nullifierHex, - fee: toDecimals(fee, decimals, 9) - } - } catch (e) { - console.error('loadWithdrawalData', e) + const fee = withdrawEvent.returnValues.fee + const decimals = config.deployments[`netId${netId}`][currency].decimals + const withdrawalAmount = toBN(fromDecimals({ amount, decimals })).sub( + toBN(fee) + ) + const { timestamp } = await web3.eth.getBlock(withdrawEvent.blockHash) + return { + amount: toDecimals(withdrawalAmount, decimals, 9), + txHash: withdrawEvent.transactionHash, + to: withdrawEvent.returnValues.to, + timestamp, + nullifier: deposit.nullifierHex, + fee: toDecimals(fee, decimals, 9) } + } catch (e) { + console.error('loadWithdrawalData', e) + } } /** * Init web3, contracts, and snark */ async function init({ rpc, noteNetId, currency = 'dai', amount = '100' }) { - let contractJson, erc20ContractJson, erc20tornadoJson, tornadoAddress, tokenAddress - // TODO do we need this? should it work in browser really? - if (inBrowser) { - // Initialize using injected web3 (Metamask) - // To assemble web version run `npm run browserify` - web3 = new Web3(window.web3.currentProvider, null, { transactionConfirmationBlocks: 1 }) - contractJson = await (await fetch('build/contracts/ETHTornado.json')).json() - circuit = await (await fetch('build/circuits/withdraw.json')).json() - proving_key = await (await fetch('build/circuits/withdraw_proving_key.bin')).arrayBuffer() - MERKLE_TREE_HEIGHT = 20 - ETH_AMOUNT = 1e18 - TOKEN_AMOUNT = 1e19 - senderAccount = (await web3.eth.getAccounts())[0] + let contractJson, erc20ContractJson, erc20tornadoJson, tornadoAddress, tokenAddress + // TODO do we need this? should it work in browser really? + if (inBrowser) { + // Initialize using injected web3 (Metamask) + // To assemble web version run `npm run browserify` + web3 = new Web3(window.web3.currentProvider, null, { transactionConfirmationBlocks: 1 }) + contractJson = await (await fetch('build/contracts/ETHTornado.json')).json() + circuit = await (await fetch('build/circuits/withdraw.json')).json() + proving_key = await (await fetch('build/circuits/withdraw_proving_key.bin')).arrayBuffer() + MERKLE_TREE_HEIGHT = 20 + ETH_AMOUNT = 1e18 + TOKEN_AMOUNT = 1e19 + senderAccount = (await web3.eth.getAccounts())[0] + } else { + // Initialize from local node + web3 = new Web3(rpc, null, { transactionConfirmationBlocks: 1 }) + contractJson = require('./build/contracts/ETHTornado.json') + circuit = require('./build/circuits/withdraw.json') + proving_key = fs.readFileSync('build/circuits/withdraw_proving_key.bin').buffer + MERKLE_TREE_HEIGHT = process.env.MERKLE_TREE_HEIGHT || 20 + ETH_AMOUNT = process.env.ETH_AMOUNT + TOKEN_AMOUNT = process.env.TOKEN_AMOUNT + PRIVATE_KEY = process.env.PRIVATE_KEY + if (PRIVATE_KEY) { + const account = web3.eth.accounts.privateKeyToAccount('0x' + PRIVATE_KEY) + web3.eth.accounts.wallet.add('0x' + PRIVATE_KEY) + web3.eth.defaultAccount = account.address + senderAccount = account.address } else { - // Initialize from local node - web3 = new Web3(rpc, null, { transactionConfirmationBlocks: 1 }) - contractJson = require('./build/contracts/ETHTornado.json') - circuit = require('./build/circuits/withdraw.json') - proving_key = fs.readFileSync('build/circuits/withdraw_proving_key.bin').buffer - MERKLE_TREE_HEIGHT = process.env.MERKLE_TREE_HEIGHT || 20 - ETH_AMOUNT = process.env.ETH_AMOUNT - TOKEN_AMOUNT = process.env.TOKEN_AMOUNT - PRIVATE_KEY = process.env.PRIVATE_KEY - if (PRIVATE_KEY) { - const account = web3.eth.accounts.privateKeyToAccount('0x' + PRIVATE_KEY) - web3.eth.accounts.wallet.add('0x' + PRIVATE_KEY) - web3.eth.defaultAccount = account.address - senderAccount = account.address - } else { - console.log('Warning! PRIVATE_KEY not found. Please provide PRIVATE_KEY in .env file if you deposit') - } - erc20ContractJson = require('./build/contracts/ERC20Mock.json') - erc20tornadoJson = require('./build/contracts/ERC20Tornado.json') + console.log('Warning! PRIVATE_KEY not found. Please provide PRIVATE_KEY in .env file if you deposit') } - // groth16 initialises a lot of Promises that will never be resolved, that's why we need to use process.exit to terminate the CLI - groth16 = await buildGroth16() - netId = await web3.eth.net.getId() - if (noteNetId && Number(noteNetId) !== netId) { - throw new Error('This note is for a different network. Specify the --rpc option explicitly') - } - isLocalRPC = netId > 42 + erc20ContractJson = require('./build/contracts/ERC20Mock.json') + erc20tornadoJson = require('./build/contracts/ERC20Tornado.json') + } + // groth16 initialises a lot of Promises that will never be resolved, that's why we need to use process.exit to terminate the CLI + groth16 = await buildGroth16() + netId = await web3.eth.net.getId() + if (noteNetId && Number(noteNetId) !== netId) { + throw new Error('This note is for a different network. Specify the --rpc option explicitly') + } + isLocalRPC = netId > 42 - if (isLocalRPC) { - tornadoAddress = currency === 'eth' ? contractJson.networks[netId].address : erc20tornadoJson.networks[netId].address - tokenAddress = currency !== 'eth' ? erc20ContractJson.networks[netId].address : null - senderAccount = (await web3.eth.getAccounts())[0] - } else { - try { - tornadoAddress = config.deployments[`netId${netId}`][currency].instanceAddress[amount] - if (!tornadoAddress) { - throw new Error() - } - tokenAddress = config.deployments[`netId${netId}`][currency].tokenAddress - } catch (e) { - console.error('There is no such tornado instance, check the currency and amount you provide') - process.exit(1) - } + if (isLocalRPC) { + tornadoAddress = currency === 'eth' ? contractJson.networks[netId].address : erc20tornadoJson.networks[netId].address + tokenAddress = currency !== 'eth' ? erc20ContractJson.networks[netId].address : null + senderAccount = (await web3.eth.getAccounts())[0] + } else { + try { + tornadoAddress = config.deployments[`netId${netId}`][currency].instanceAddress[amount] + if (!tornadoAddress) { + throw new Error() + } + tokenAddress = config.deployments[`netId${netId}`][currency].tokenAddress + } catch (e) { + console.error('There is no such tornado instance, check the currency and amount you provide') + process.exit(1) } - tornado = new web3.eth.Contract(contractJson.abi, tornadoAddress) - erc20 = currency !== 'eth' ? new web3.eth.Contract(erc20ContractJson.abi, tokenAddress) : {} + } + tornado = new web3.eth.Contract(contractJson.abi, tornadoAddress) + erc20 = currency !== 'eth' ? new web3.eth.Contract(erc20ContractJson.abi, tokenAddress) : {} } async function main() { - if (inBrowser) { - const instance = { currency: 'eth', amount: '0.1' } - await init(instance) - window.deposit = async () => { - await deposit(instance) - } - window.withdraw = async () => { - const noteString = prompt('Enter the note to withdraw') - const recipient = (await web3.eth.getAccounts())[0] - - const { currency, amount, netId, deposit } = parseNote(noteString) - await init({ noteNetId: netId, currency, amount }) - await withdraw({ deposit, currency, amount, recipient }) - } - } else { - program - .option('-r, --rpc ', 'The RPC, CLI should interact with', 'http://localhost:8545') - .option('-R, --relayer ', 'Withdraw via relayer') - program - .command('deposit ') - .description('Submit a deposit of specified currency and amount from default eth account and return the resulting note. The currency is one of (ETH|DAI|cDAI|USDC|cUSDC|USDT). The amount depends on currency, see config.js file or visit https://tornado.cash.') - .action(async (currency, amount) => { - currency = currency.toLowerCase() - await init({ rpc: program.rpc, currency, amount }) - await deposit({ currency, amount }) - }) - program - .command('withdraw [ETH_purchase]') - .description('Withdraw a note to a recipient account using relayer or specified private key. You can exchange some of your deposit`s tokens to ETH during the withdrawal by specifing ETH_purchase (e.g. 0.01) to pay for gas in future transactions. Also see the --relayer option.') - .action(async (noteString, recipient, refund) => { - const { currency, amount, netId, deposit } = parseNote(noteString) - await init({ rpc: program.rpc, noteNetId: netId, currency, amount }) - await withdraw({ deposit, currency, amount, recipient, refund, relayerURL: program.relayer }) - }) - program - .command('balance
[token_address]') - .description('Check ETH and ERC20 balance') - .action(async (address, tokenAddress) => { - await init({ rpc: program.rpc }) - await printETHBalance({ address, name: '' }) - if (tokenAddress) { - await printERC20Balance({ address, name: '', tokenAddress }) - } - }) - program - .command('compliance ') - .description('Shows the deposit and withdrawal of the provided note. This might be necessary to show the origin of assets held in your withdrawal address.') - .action(async (noteString) => { - const { currency, amount, netId, deposit } = parseNote(noteString) - await init({ rpc: program.rpc, noteNetId: netId, currency, amount }) - const depositInfo = await loadDepositData({ deposit }) - const depositDate = new Date(depositInfo.timestamp * 1000) - console.log('\n=============Deposit=================') - console.log('Deposit :', amount, currency) - console.log('Date :', depositDate.toLocaleDateString(), depositDate.toLocaleTimeString()) - console.log('From :', `https://${getCurrentNetworkName()}etherscan.io/address/${depositInfo.from}`) - console.log('Transaction :', `https://${getCurrentNetworkName()}etherscan.io/tx/${depositInfo.txHash}`) - console.log('Commitment :', depositInfo.commitment) - if (deposit.isSpent) { - console.log('The note was not spent') - } - - const withdrawInfo = await loadWithdrawalData({ amount, currency, deposit }) - const withdrawalDate = new Date(withdrawInfo.timestamp * 1000) - console.log('\n=============Withdrawal==============') - console.log('Withdrawal :', withdrawInfo.amount, currency) - console.log('Relayer Fee :', withdrawInfo.fee, currency) - console.log('Date :', withdrawalDate.toLocaleDateString(), withdrawalDate.toLocaleTimeString()) - console.log('To :', `https://${getCurrentNetworkName()}etherscan.io/address/${withdrawInfo.to}`) - console.log('Transaction :', `https://${getCurrentNetworkName()}etherscan.io/tx/${withdrawInfo.txHash}`) - console.log('Nullifier :', withdrawInfo.nullifier) - }) - program - .command('test') - .description('Perform an automated test. It deposits and withdraws one ETH and one ERC20 note. Uses ganache.') - .action(async () => { - console.log('Start performing ETH deposit-withdraw test') - let currency = 'eth' - let amount = '0.1' - await init({ rpc: program.rpc, currency, amount }) - let noteString = await deposit({ currency, amount }) - let parsedNote = parseNote(noteString) - await withdraw({ deposit: parsedNote.deposit, currency, amount, recipient: senderAccount, relayerURL: program.relayer }) - - console.log('\nStart performing DAI deposit-withdraw test') - currency = 'dai' - amount = '100' - await init({ rpc: program.rpc, currency, amount }) - noteString = await deposit({ currency, amount }) - ; (parsedNote = parseNote(noteString)) - await withdraw({ deposit: parsedNote.deposit, currency, amount, recipient: senderAccount, refund: '0.02', relayerURL: program.relayer }) - }) - try { - await program.parseAsync(process.argv) - process.exit(0) - } catch (e) { - console.log('Error:', e) - process.exit(1) - } + if (inBrowser) { + const instance = { currency: 'eth', amount: '0.1' } + await init(instance) + window.deposit = async () => { + await deposit(instance) } + window.withdraw = async () => { + const noteString = prompt('Enter the note to withdraw') + const recipient = (await web3.eth.getAccounts())[0] + + const { currency, amount, netId, deposit } = parseNote(noteString) + await init({ noteNetId: netId, currency, amount }) + await withdraw({ deposit, currency, amount, recipient }) + } + } else { + program + .option('-r, --rpc ', 'The RPC, CLI should interact with', 'http://localhost:8545') + .option('-R, --relayer ', 'Withdraw via relayer') + program + .command('deposit ') + .description('Submit a deposit of specified currency and amount from default eth account and return the resulting note. The currency is one of (ETH|DAI|cDAI|USDC|cUSDC|USDT). The amount depends on currency, see config.js file or visit https://tornado.cash.') + .action(async (currency, amount) => { + currency = currency.toLowerCase() + await init({ rpc: program.rpc, currency, amount }) + await deposit({ currency, amount }) + }) + program + .command('withdraw [ETH_purchase]') + .description('Withdraw a note to a recipient account using relayer or specified private key. You can exchange some of your deposit`s tokens to ETH during the withdrawal by specifing ETH_purchase (e.g. 0.01) to pay for gas in future transactions. Also see the --relayer option.') + .action(async (noteString, recipient, refund) => { + const { currency, amount, netId, deposit } = parseNote(noteString) + await init({ rpc: program.rpc, noteNetId: netId, currency, amount }) + await withdraw({ deposit, currency, amount, recipient, refund, relayerURL: program.relayer }) + }) + program + .command('balance
[token_address]') + .description('Check ETH and ERC20 balance') + .action(async (address, tokenAddress) => { + await init({ rpc: program.rpc }) + await printETHBalance({ address, name: '' }) + if (tokenAddress) { + await printERC20Balance({ address, name: '', tokenAddress }) + } + }) + program + .command('compliance ') + .description('Shows the deposit and withdrawal of the provided note. This might be necessary to show the origin of assets held in your withdrawal address.') + .action(async (noteString) => { + const { currency, amount, netId, deposit } = parseNote(noteString) + await init({ rpc: program.rpc, noteNetId: netId, currency, amount }) + const depositInfo = await loadDepositData({ deposit }) + const depositDate = new Date(depositInfo.timestamp * 1000) + console.log('\n=============Deposit=================') + console.log('Deposit :', amount, currency) + console.log('Date :', depositDate.toLocaleDateString(), depositDate.toLocaleTimeString()) + console.log('From :', `https://${getCurrentNetworkName()}etherscan.io/address/${depositInfo.from}`) + console.log('Transaction :', `https://${getCurrentNetworkName()}etherscan.io/tx/${depositInfo.txHash}`) + console.log('Commitment :', depositInfo.commitment) + if (deposit.isSpent) { + console.log('The note was not spent') + } + + const withdrawInfo = await loadWithdrawalData({ amount, currency, deposit }) + const withdrawalDate = new Date(withdrawInfo.timestamp * 1000) + console.log('\n=============Withdrawal==============') + console.log('Withdrawal :', withdrawInfo.amount, currency) + console.log('Relayer Fee :', withdrawInfo.fee, currency) + console.log('Date :', withdrawalDate.toLocaleDateString(), withdrawalDate.toLocaleTimeString()) + console.log('To :', `https://${getCurrentNetworkName()}etherscan.io/address/${withdrawInfo.to}`) + console.log('Transaction :', `https://${getCurrentNetworkName()}etherscan.io/tx/${withdrawInfo.txHash}`) + console.log('Nullifier :', withdrawInfo.nullifier) + }) + program + .command('test') + .description('Perform an automated test. It deposits and withdraws one ETH and one ERC20 note. Uses ganache.') + .action(async () => { + console.log('Start performing ETH deposit-withdraw test') + let currency = 'eth' + let amount = '0.1' + await init({ rpc: program.rpc, currency, amount }) + let noteString = await deposit({ currency, amount }) + let parsedNote = parseNote(noteString) + await withdraw({ deposit: parsedNote.deposit, currency, amount, recipient: senderAccount, relayerURL: program.relayer }) + + console.log('\nStart performing DAI deposit-withdraw test') + currency = 'dai' + amount = '100' + await init({ rpc: program.rpc, currency, amount }) + noteString = await deposit({ currency, amount }) + ; (parsedNote = parseNote(noteString)) + await withdraw({ deposit: parsedNote.deposit, currency, amount, recipient: senderAccount, refund: '0.02', relayerURL: program.relayer }) + }) + try { + await program.parseAsync(process.argv) + process.exit(0) + } catch (e) { + console.log('Error:', e) + process.exit(1) + } + } } main() diff --git a/package-lock.json b/package-lock.json index f564304..b4b0fe8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,6 +25,18 @@ "@babel/helper-validator-identifier": "^7.9.0", "chalk": "^2.0.0", "js-tokens": "^4.0.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } } }, "@ethersproject/abi": { @@ -163,6 +175,12 @@ "@types/node": "*" } }, + "@types/color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", + "dev": true + }, "@types/node": { "version": "10.17.24", "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.24.tgz", @@ -209,9 +227,10 @@ } }, "acorn": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", - "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==" + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.2.0.tgz", + "integrity": "sha512-apwXVmYVpQ34m/i71vrApRrRKCWQnZZF1+npOD0WV5xZFfwWOmKGQ2RWlfdy9vWITsenisM8M0Qeq8agcFHNiQ==", + "dev": true }, "acorn-jsx": { "version": "5.2.0", @@ -230,9 +249,21 @@ } }, "ansi-escapes": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", - "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==" + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", + "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==", + "dev": true, + "requires": { + "type-fest": "^0.11.0" + }, + "dependencies": { + "type-fest": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz", + "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==", + "dev": true + } + } }, "ansi-regex": { "version": "3.0.0", @@ -604,13 +635,55 @@ } }, "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz", + "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==", + "dev": true, "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "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==", + "dev": 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==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } }, "chardet": { @@ -681,6 +754,194 @@ "web3": "^1.0.0-beta.55" }, "dependencies": { + "acorn": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", + "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==" + }, + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==" + }, + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + }, + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", + "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "espree": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-5.0.1.tgz", + "integrity": "sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A==", + "requires": { + "acorn": "^6.0.7", + "acorn-jsx": "^5.0.0", + "eslint-visitor-keys": "^1.0.0" + } + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" + }, + "inquirer": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", + "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", + "requires": { + "ansi-escapes": "^3.2.0", + "chalk": "^2.4.2", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^2.0.0", + "lodash": "^4.17.12", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rxjs": "^6.4.0", + "string-width": "^2.1.0", + "strip-ansi": "^5.1.0", + "through": "^2.3.6" + }, + "dependencies": { + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==" + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "requires": { + "minimist": "^1.2.5" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" + }, + "regexpp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==" + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + }, "snarkjs": { "version": "git+https://github.com/peppersec/snarkjs.git#869181cfaf7526fe8972073d31655493a04326d5", "from": "git+https://github.com/peppersec/snarkjs.git#869181cfaf7526fe8972073d31655493a04326d5", @@ -691,6 +952,64 @@ "eslint": "^5.16.0", "keccak": "^2.0.0", "yargs": "^12.0.5" + }, + "dependencies": { + "eslint": { + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.16.0.tgz", + "integrity": "sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg==", + "requires": { + "@babel/code-frame": "^7.0.0", + "ajv": "^6.9.1", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^4.0.3", + "eslint-utils": "^1.3.1", + "eslint-visitor-keys": "^1.0.0", + "espree": "^5.0.1", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob": "^7.1.2", + "globals": "^11.7.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "inquirer": "^6.2.2", + "js-yaml": "^3.13.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.11", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "path-is-inside": "^1.0.2", + "progress": "^2.0.0", + "regexpp": "^2.0.1", + "semver": "^5.5.1", + "strip-ansi": "^4.0.0", + "strip-json-comments": "^2.0.1", + "table": "^5.2.3", + "text-table": "^0.2.0" + } + } + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "requires": { + "prelude-ls": "~1.1.2" } } } @@ -701,11 +1020,12 @@ "integrity": "sha512-rhjH9AG1fvabIDoGRVH587413LPjTZgmDF9fOFCbFJQV4yuocX1mHxxvXI4g3cGwbVY9wAYIoKlg1N79frJKQw==" }, "cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, "requires": { - "restore-cursor": "^2.0.0" + "restore-cursor": "^3.1.0" } }, "cli-width": { @@ -1047,9 +1367,10 @@ } }, "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true }, "encodeurl": { "version": "1.0.2", @@ -1104,89 +1425,143 @@ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, "eslint": { - "version": "5.16.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.16.0.tgz", - "integrity": "sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.0.0.tgz", + "integrity": "sha512-qY1cwdOxMONHJfGqw52UOpZDeqXy8xmD0u8CT6jIstil72jkhURC704W8CFyTPDPllz4z4lu0Ql1+07PG/XdIg==", + "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "ajv": "^6.9.1", - "chalk": "^2.1.0", - "cross-spawn": "^6.0.5", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", "debug": "^4.0.1", "doctrine": "^3.0.0", - "eslint-scope": "^4.0.3", - "eslint-utils": "^1.3.1", - "eslint-visitor-keys": "^1.0.0", - "espree": "^5.0.1", - "esquery": "^1.0.1", + "eslint-scope": "^5.0.0", + "eslint-utils": "^2.0.0", + "eslint-visitor-keys": "^1.1.0", + "espree": "^7.0.0", + "esquery": "^1.2.0", "esutils": "^2.0.2", "file-entry-cache": "^5.0.1", "functional-red-black-tree": "^1.0.1", - "glob": "^7.1.2", - "globals": "^11.7.0", + "glob-parent": "^5.0.0", + "globals": "^12.1.0", "ignore": "^4.0.6", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", - "inquirer": "^6.2.2", - "js-yaml": "^3.13.0", + "inquirer": "^7.0.0", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.3.0", - "lodash": "^4.17.11", + "levn": "^0.4.1", + "lodash": "^4.17.14", "minimatch": "^3.0.4", - "mkdirp": "^0.5.1", "natural-compare": "^1.4.0", - "optionator": "^0.8.2", - "path-is-inside": "^1.0.2", + "optionator": "^0.9.1", "progress": "^2.0.0", - "regexpp": "^2.0.1", - "semver": "^5.5.1", - "strip-ansi": "^4.0.0", - "strip-json-comments": "^2.0.1", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", "table": "^5.2.3", - "text-table": "^0.2.0" + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" }, "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "cross-spawn": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.2.tgz", + "integrity": "sha512-PD6G8QG3S4FK/XCGFbEQrDqO2AnMMsy0meR7lerlIOHAAbkuavGU/pOqprrlvfTNjvowivTeBsjebAL0NSoMxw==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, "debug": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, "requires": { "ms": "^2.1.1" } }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "requires": { - "minimist": "^1.2.5" - } - }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": 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==", + "dev": true }, "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true + }, + "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==", + "dev": 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==", + "dev": true + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } } } }, "eslint-scope": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", - "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz", + "integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==", + "dev": true, "requires": { "esrecurse": "^4.1.0", "estraverse": "^4.1.1" } }, "eslint-utils": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", - "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.0.0.tgz", + "integrity": "sha512-0HCPuJv+7Wv1bACm8y5/ECVfYdfsAm9xmVb7saeFlxjPYALefjhbYoCkBjPdPzGH8wWyTpAez82Fh3VKYEZ8OA==", + "dev": true, "requires": { "eslint-visitor-keys": "^1.1.0" } @@ -1197,13 +1572,14 @@ "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==" }, "espree": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-5.0.1.tgz", - "integrity": "sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.0.0.tgz", + "integrity": "sha512-/r2XEx5Mw4pgKdyb7GNLQNsu++asx/dltf/CI8RFi9oGHxmQFgvLbc5Op4U6i8Oaj+kdslhJtVlEZeAqH5qOTw==", + "dev": true, "requires": { - "acorn": "^6.0.7", - "acorn-jsx": "^5.0.0", - "eslint-visitor-keys": "^1.0.0" + "acorn": "^7.1.1", + "acorn-jsx": "^5.2.0", + "eslint-visitor-keys": "^1.1.0" } }, "esprima": { @@ -1465,9 +1841,10 @@ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" }, "figures": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, "requires": { "escape-string-regexp": "^1.0.5" } @@ -1632,6 +2009,15 @@ "path-is-absolute": "^1.0.0" } }, + "glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, "global": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz", @@ -1642,9 +2028,13 @@ } }, "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", + "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "dev": true, + "requires": { + "type-fest": "^0.8.1" + } }, "got": { "version": "9.6.0", @@ -1838,36 +2228,106 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "inquirer": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", - "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.1.0.tgz", + "integrity": "sha512-5fJMWEmikSYu0nv/flMc475MhGbB7TSPd/2IpFV4I4rMklboCH2rQjYY5kKiYGHqUF9gvaambupcJFFG9dvReg==", + "dev": true, "requires": { - "ansi-escapes": "^3.2.0", - "chalk": "^2.4.2", - "cli-cursor": "^2.1.0", + "ansi-escapes": "^4.2.1", + "chalk": "^3.0.0", + "cli-cursor": "^3.1.0", "cli-width": "^2.0.0", "external-editor": "^3.0.3", - "figures": "^2.0.0", - "lodash": "^4.17.12", - "mute-stream": "0.0.7", - "run-async": "^2.2.0", - "rxjs": "^6.4.0", - "string-width": "^2.1.0", - "strip-ansi": "^5.1.0", + "figures": "^3.0.0", + "lodash": "^4.17.15", + "mute-stream": "0.0.8", + "run-async": "^2.4.0", + "rxjs": "^6.5.3", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", "through": "^2.3.6" }, "dependencies": { "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": 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==", + "dev": 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==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } }, "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, "requires": { - "ansi-regex": "^4.1.0" + "ansi-regex": "^5.0.0" + } + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" } } } @@ -1882,6 +2342,12 @@ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", @@ -1892,6 +2358,15 @@ "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz", "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==" }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, "is-hex-prefixed": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", @@ -2044,12 +2519,13 @@ } }, "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" } }, "locate-path": { @@ -2261,9 +2737,10 @@ } }, "mute-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", - "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true }, "nan": { "version": "2.14.1", @@ -2369,18 +2846,12 @@ } }, "onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz", + "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==", + "dev": true, "requires": { - "mimic-fn": "^1.0.0" - }, - "dependencies": { - "mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==" - } + "mimic-fn": "^2.1.0" } }, "optimist": { @@ -2400,16 +2871,17 @@ } }, "optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" + "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" } }, "os-locale": { @@ -2555,9 +3027,10 @@ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" }, "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true }, "prepend-http": { "version": "2.0.0", @@ -2674,9 +3147,10 @@ } }, "regexpp": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", - "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==" + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", + "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", + "dev": true }, "request": { "version": "2.88.2", @@ -2736,11 +3210,12 @@ } }, "restore-cursor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, "requires": { - "onetime": "^2.0.0", + "onetime": "^5.1.0", "signal-exit": "^3.0.2" } }, @@ -2959,6 +3434,252 @@ "eslint": "^5.16.0", "keccak": "^2.0.0", "yargs": "^12.0.5" + }, + "dependencies": { + "acorn": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", + "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==" + }, + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==" + }, + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + }, + "eslint": { + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.16.0.tgz", + "integrity": "sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg==", + "requires": { + "@babel/code-frame": "^7.0.0", + "ajv": "^6.9.1", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^4.0.3", + "eslint-utils": "^1.3.1", + "eslint-visitor-keys": "^1.0.0", + "espree": "^5.0.1", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob": "^7.1.2", + "globals": "^11.7.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "inquirer": "^6.2.2", + "js-yaml": "^3.13.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.11", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "path-is-inside": "^1.0.2", + "progress": "^2.0.0", + "regexpp": "^2.0.1", + "semver": "^5.5.1", + "strip-ansi": "^4.0.0", + "strip-json-comments": "^2.0.1", + "table": "^5.2.3", + "text-table": "^0.2.0" + } + }, + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", + "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "espree": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-5.0.1.tgz", + "integrity": "sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A==", + "requires": { + "acorn": "^6.0.7", + "acorn-jsx": "^5.0.0", + "eslint-visitor-keys": "^1.0.0" + } + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" + }, + "inquirer": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", + "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", + "requires": { + "ansi-escapes": "^3.2.0", + "chalk": "^2.4.2", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^2.0.0", + "lodash": "^4.17.12", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rxjs": "^6.4.0", + "string-width": "^2.1.0", + "strip-ansi": "^5.1.0", + "through": "^2.3.6" + }, + "dependencies": { + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==" + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "requires": { + "minimist": "^1.2.5" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" + }, + "regexpp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==" + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "requires": { + "prelude-ls": "~1.1.2" + } + } } }, "sprintf-js": { @@ -3038,9 +3759,10 @@ } }, "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.0.tgz", + "integrity": "sha512-e6/d0eBu7gHtdCqFt0xJr642LdToM5/cN4Qb9DbHjVx1CP5RyeM+zH7pbecEmDv/lBqb0QH+6Uqq75rxFPkM0w==", + "dev": true }, "supports-color": { "version": "5.5.0", @@ -3130,6 +3852,11 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" + }, "string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", @@ -3240,11 +3967,12 @@ "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" }, "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, "requires": { - "prelude-ls": "~1.1.2" + "prelude-ls": "^1.2.1" } }, "type-detect": { @@ -3252,6 +3980,12 @@ "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + }, "type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", @@ -3335,6 +4069,12 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" }, + "v8-compile-cache": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz", + "integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==", + "dev": true + }, "varint": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/varint/-/varint-5.0.0.tgz", diff --git a/package.json b/package.json index 749de18..ae5df69 100644 --- a/package.json +++ b/package.json @@ -17,5 +17,8 @@ "snarkjs": "git+https://github.com/tornadocash/snarkjs.git#869181cfaf7526fe8972073d31655493a04326d5", "web3": "^1.2.8", "websnark": "git+https://github.com/tornadocash/websnark.git#4c0af6a8b65aabea3c09f377f63c44e7a58afa6d" + }, + "devDependencies": { + "eslint": "^7.0.0" } }