mirror of
https://github.com/tornadocash/tornado-cli.git
synced 2024-10-01 07:15:36 -04:00
Refactor cli.js and use Promise.all for non multicall calls
This commit is contained in:
parent
873940cbf7
commit
2ab7e7afb6
129
cli.js
129
cli.js
@ -58,6 +58,7 @@ async function useMultiCall(queryArray) {
|
|||||||
async function printETHBalance({ address, name }) {
|
async function printETHBalance({ address, name }) {
|
||||||
const checkBalance = new BigNumber(await web3.eth.getBalance(address)).div(BigNumber(10).pow(18));
|
const checkBalance = new BigNumber(await web3.eth.getBalance(address)).div(BigNumber(10).pow(18));
|
||||||
console.log(`${name} balance is`, rmDecimalBN(checkBalance), `${netSymbol}`);
|
console.log(`${name} balance is`, rmDecimalBN(checkBalance), `${netSymbol}`);
|
||||||
|
return checkBalance;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Display ERC20 account balance */
|
/** Display ERC20 account balance */
|
||||||
@ -66,18 +67,27 @@ async function printERC20Balance({ address, name, tokenAddress }) {
|
|||||||
const erc20ContractJson = require('./build/contracts/ERC20Mock.json');
|
const erc20ContractJson = require('./build/contracts/ERC20Mock.json');
|
||||||
erc20 = tokenAddress ? new web3.eth.Contract(erc20ContractJson.abi, tokenAddress) : erc20;
|
erc20 = tokenAddress ? new web3.eth.Contract(erc20ContractJson.abi, tokenAddress) : erc20;
|
||||||
if (!isTestRPC && multiCall) {
|
if (!isTestRPC && multiCall) {
|
||||||
const tokenCall = await useMultiCall([[tokenAddress, erc20.methods.balanceOf(address).encodeABI()], [tokenAddress, erc20.methods.decimals().encodeABI()], [tokenAddress, erc20.methods.name().encodeABI()], [tokenAddress, erc20.methods.symbol().encodeABI()]]);
|
const tokenCall = await useMultiCall([
|
||||||
|
[tokenAddress, erc20.methods.balanceOf(address).encodeABI()],
|
||||||
|
[tokenAddress, erc20.methods.decimals().encodeABI()],
|
||||||
|
[tokenAddress, erc20.methods.name().encodeABI()],
|
||||||
|
[tokenAddress, erc20.methods.symbol().encodeABI()]
|
||||||
|
]);
|
||||||
tokenDecimals = parseInt(tokenCall[1]);
|
tokenDecimals = parseInt(tokenCall[1]);
|
||||||
tokenBalance = new BigNumber(tokenCall[0]).div(BigNumber(10).pow(tokenDecimals));
|
tokenBalance = new BigNumber(tokenCall[0]).div(BigNumber(10).pow(tokenDecimals));
|
||||||
tokenName = web3.eth.abi.decodeParameter('string', tokenCall[2]);
|
tokenName = web3.eth.abi.decodeParameter('string', tokenCall[2]);
|
||||||
tokenSymbol = web3.eth.abi.decodeParameter('string', tokenCall[3]);
|
tokenSymbol = web3.eth.abi.decodeParameter('string', tokenCall[3]);
|
||||||
} else {
|
} else {
|
||||||
tokenDecimals = await erc20.methods.decimals().call();
|
[ tokenDecimals, tokenBalance, tokenName, tokenSymbol ] = await Promise.all([
|
||||||
tokenBalance = new BigNumber(await erc20.methods.balanceOf(address).call()).div(BigNumber(10).pow(tokenDecimals));
|
erc20.methods.decimals().call(),
|
||||||
tokenName = await erc20.methods.name().call();
|
erc20.methods.balanceOf(address).call(),
|
||||||
tokenSymbol = await erc20.methods.symbol().call();
|
erc20.methods.name().call(),
|
||||||
|
erc20.methods.symbol().call()
|
||||||
|
]);
|
||||||
|
tokenBalance = new BigNumber(tokenBalance).div(BigNumber(10).pow(tokenDecimals));
|
||||||
}
|
}
|
||||||
console.log(`${name}`, tokenName, `Balance is`, rmDecimalBN(tokenBalance), tokenSymbol);
|
console.log(`${name}`, tokenName, `Balance is`, rmDecimalBN(tokenBalance), tokenSymbol);
|
||||||
|
return tokenBalance;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function submitTransaction(signedTX) {
|
async function submitTransaction(signedTX) {
|
||||||
@ -92,8 +102,10 @@ async function submitTransaction(signedTX) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function generateTransaction(to, encodedData, value = 0) {
|
async function generateTransaction(to, encodedData, value = 0) {
|
||||||
const nonce = await web3.eth.getTransactionCount(senderAccount);
|
const [ nonce, gasPrice ] = await Promise.all([
|
||||||
let gasPrice = await fetchGasPrice();
|
web3.eth.getTransactionCount(senderAccount),
|
||||||
|
fetchGasPrice()
|
||||||
|
]);
|
||||||
let gasLimit;
|
let gasLimit;
|
||||||
|
|
||||||
async function estimateGas() {
|
async function estimateGas() {
|
||||||
@ -207,8 +219,10 @@ async function createInvoice({ currency, amount, chainId }) {
|
|||||||
const invoiceString = `tornadoInvoice-${currency}-${amount}-${chainId}-${commitmentNote}`;
|
const invoiceString = `tornadoInvoice-${currency}-${amount}-${chainId}-${commitmentNote}`;
|
||||||
console.log(`Your invoice for deposit: ${invoiceString}`);
|
console.log(`Your invoice for deposit: ${invoiceString}`);
|
||||||
|
|
||||||
await backupNote({ currency, amount, netId: chainId, note, noteString });
|
await Promise.all([
|
||||||
await backupInvoice({ currency, amount, netId: chainId, commitmentNote, invoiceString });
|
backupNote({ currency, amount, netId: chainId, note, noteString }),
|
||||||
|
backupInvoice({ currency, amount, netId: chainId, commitmentNote, invoiceString })
|
||||||
|
]);
|
||||||
|
|
||||||
return (noteString, invoiceString);
|
return (noteString, invoiceString);
|
||||||
}
|
}
|
||||||
@ -237,25 +251,30 @@ async function deposit({ currency, amount, commitmentNote }) {
|
|||||||
commitment = toHex(commitmentNote);
|
commitment = toHex(commitmentNote);
|
||||||
}
|
}
|
||||||
if (currency === netSymbol.toLowerCase()) {
|
if (currency === netSymbol.toLowerCase()) {
|
||||||
await printETHBalance({ address: tornadoContract._address, name: 'Tornado contract' });
|
await Promise.all([
|
||||||
await printETHBalance({ address: senderAccount, name: 'Sender account' });
|
printETHBalance({ address: tornadoContract._address, name: 'Tornado contract' }),
|
||||||
|
printETHBalance({ address: senderAccount, name: 'Sender account' })
|
||||||
|
]);
|
||||||
const value = isTestRPC ? ETH_AMOUNT : fromDecimals({ amount, decimals: 18 });
|
const value = isTestRPC ? ETH_AMOUNT : fromDecimals({ amount, decimals: 18 });
|
||||||
console.log('Submitting deposit transaction');
|
console.log('Submitting deposit transaction');
|
||||||
await generateTransaction(contractAddress, tornado.methods.deposit(tornadoInstance, commitment, []).encodeABI(), value);
|
await generateTransaction(contractAddress, tornado.methods.deposit(tornadoInstance, commitment, []).encodeABI(), value);
|
||||||
await printETHBalance({ address: tornadoContract._address, name: 'Tornado contract' });
|
await Promise.all([
|
||||||
await printETHBalance({ address: senderAccount, name: 'Sender account' });
|
printETHBalance({ address: tornadoContract._address, name: 'Tornado contract' }),
|
||||||
|
printETHBalance({ address: senderAccount, name: 'Sender account' })
|
||||||
|
]);
|
||||||
} else {
|
} else {
|
||||||
// a token
|
// a token
|
||||||
await printERC20Balance({ address: tornadoContract._address, name: 'Tornado contract' });
|
const [ balance1, balance2, allowance ] = await Promise.all([
|
||||||
await printERC20Balance({ address: senderAccount, name: 'Sender account' });
|
printERC20Balance({ address: tornadoContract._address, name: 'Tornado contract' }),
|
||||||
|
printERC20Balance({ address: senderAccount, name: 'Sender account' }),
|
||||||
|
erc20.methods.allowance(senderAccount, tornado._address).call({ from: senderAccount })
|
||||||
|
]);
|
||||||
const decimals = isTestRPC ? 18 : config.deployments[`netId${netId}`][currency].decimals;
|
const decimals = isTestRPC ? 18 : config.deployments[`netId${netId}`][currency].decimals;
|
||||||
const tokenAmount = isTestRPC ? TOKEN_AMOUNT : fromDecimals({ amount, decimals });
|
const tokenAmount = isTestRPC ? TOKEN_AMOUNT : fromDecimals({ amount, decimals });
|
||||||
if (isTestRPC) {
|
if (isTestRPC) {
|
||||||
console.log('Minting some test tokens to deposit');
|
console.log('Minting some test tokens to deposit');
|
||||||
await generateTransaction(erc20Address, erc20.methods.mint(senderAccount, tokenAmount).encodeABI());
|
await generateTransaction(erc20Address, erc20.methods.mint(senderAccount, tokenAmount).encodeABI());
|
||||||
}
|
}
|
||||||
|
|
||||||
const allowance = await erc20.methods.allowance(senderAccount, tornado._address).call({ from: senderAccount });
|
|
||||||
console.log('Current allowance is', fromWei(allowance));
|
console.log('Current allowance is', fromWei(allowance));
|
||||||
if (toBN(allowance).lt(toBN(tokenAmount))) {
|
if (toBN(allowance).lt(toBN(tokenAmount))) {
|
||||||
console.log('Approving tokens for deposit');
|
console.log('Approving tokens for deposit');
|
||||||
@ -264,8 +283,10 @@ async function deposit({ currency, amount, commitmentNote }) {
|
|||||||
|
|
||||||
console.log('Submitting deposit transaction');
|
console.log('Submitting deposit transaction');
|
||||||
await generateTransaction(contractAddress, tornado.methods.deposit(tornadoInstance, commitment, []).encodeABI());
|
await generateTransaction(contractAddress, tornado.methods.deposit(tornadoInstance, commitment, []).encodeABI());
|
||||||
await printERC20Balance({ address: tornadoContract._address, name: 'Tornado contract' });
|
await Promise.all([
|
||||||
await printERC20Balance({ address: senderAccount, name: 'Sender account' });
|
printERC20Balance({ address: tornadoContract._address, name: 'Tornado contract' }),
|
||||||
|
printERC20Balance({ address: senderAccount, name: 'Sender account' })
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!commitmentNote) {
|
if(!commitmentNote) {
|
||||||
@ -301,12 +322,17 @@ async function generateMerkleProof(deposit, currency, amount) {
|
|||||||
const root = tree.root();
|
const root = tree.root();
|
||||||
let isValidRoot, isSpent;
|
let isValidRoot, isSpent;
|
||||||
if (!isTestRPC && multiCall) {
|
if (!isTestRPC && multiCall) {
|
||||||
const callContract = await useMultiCall([[tornadoContract._address, tornadoContract.methods.isKnownRoot(toHex(root)).encodeABI()], [tornadoContract._address, tornadoContract.methods.isSpent(toHex(deposit.nullifierHash)).encodeABI()]])
|
const callContract = await useMultiCall([
|
||||||
|
[tornadoContract._address, tornadoContract.methods.isKnownRoot(toHex(root)).encodeABI()],
|
||||||
|
[tornadoContract._address, tornadoContract.methods.isSpent(toHex(deposit.nullifierHash)).encodeABI()]
|
||||||
|
]);
|
||||||
isValidRoot = web3.eth.abi.decodeParameter('bool', callContract[0]);
|
isValidRoot = web3.eth.abi.decodeParameter('bool', callContract[0]);
|
||||||
isSpent = web3.eth.abi.decodeParameter('bool', callContract[1]);
|
isSpent = web3.eth.abi.decodeParameter('bool', callContract[1]);
|
||||||
} else {
|
} else {
|
||||||
isValidRoot = await tornadoContract.methods.isKnownRoot(toHex(root)).call();
|
[ isValidRoot, isSpent ] = await Promise.all([
|
||||||
isSpent = await tornadoContract.methods.isSpent(toHex(deposit.nullifierHash)).call();
|
tornadoContract.methods.isKnownRoot(toHex(root)).call(),
|
||||||
|
tornadoContract.methods.isSpent(toHex(deposit.nullifierHash)).call()
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
assert(isValidRoot === true, 'Merkle tree is corrupted. Some events could be missing, please try again.');
|
assert(isValidRoot === true, 'Merkle tree is corrupted. Some events could be missing, please try again.');
|
||||||
assert(isSpent === false, 'The note is already spent');
|
assert(isSpent === false, 'The note is already spent');
|
||||||
@ -384,8 +410,8 @@ async function withdraw({ deposit, currency, amount, recipient, relayerURL, refu
|
|||||||
}
|
}
|
||||||
const relayerStatus = await axios.get(relayerURL + '/status', options);
|
const relayerStatus = await axios.get(relayerURL + '/status', options);
|
||||||
|
|
||||||
const { rewardAccount, netId, ethPrices, tornadoServiceFee } = relayerStatus.data
|
const { rewardAccount, relayerNetId, ethPrices, tornadoServiceFee } = relayerStatus.data
|
||||||
assert(netId === (await web3.eth.net.getId()) || netId === '*', 'This relay is for different network');
|
assert(relayerNetId === netId || relayerNetId === '*', 'This relay is for different network');
|
||||||
console.log('Relay address:', rewardAccount);
|
console.log('Relay address:', rewardAccount);
|
||||||
|
|
||||||
const gasPrice = await fetchGasPrice();
|
const gasPrice = await fetchGasPrice();
|
||||||
@ -460,14 +486,21 @@ async function send({ address, amount, tokenAddress }) {
|
|||||||
erc20 = new web3.eth.Contract(erc20ContractJson.abi, tokenAddress);
|
erc20 = new web3.eth.Contract(erc20ContractJson.abi, tokenAddress);
|
||||||
let tokenBalance, tokenDecimals, tokenSymbol;
|
let tokenBalance, tokenDecimals, tokenSymbol;
|
||||||
if (!isTestRPC && multiCall) {
|
if (!isTestRPC && multiCall) {
|
||||||
const callToken = await useMultiCall([[tokenAddress, erc20.methods.balanceOf(senderAccount).encodeABI()], [tokenAddress, erc20.methods.decimals().encodeABI()], [tokenAddress, erc20.methods.symbol().encodeABI()]]);
|
const callToken = await useMultiCall([
|
||||||
|
[tokenAddress, erc20.methods.balanceOf(senderAccount).encodeABI()],
|
||||||
|
[tokenAddress, erc20.methods.decimals().encodeABI()],
|
||||||
|
[tokenAddress, erc20.methods.symbol().encodeABI()]
|
||||||
|
]);
|
||||||
tokenBalance = new BigNumber(callToken[0]);
|
tokenBalance = new BigNumber(callToken[0]);
|
||||||
tokenDecimals = parseInt(callToken[1]);
|
tokenDecimals = parseInt(callToken[1]);
|
||||||
tokenSymbol = web3.eth.abi.decodeParameter('string', callToken[2]);
|
tokenSymbol = web3.eth.abi.decodeParameter('string', callToken[2]);
|
||||||
} else {
|
} else {
|
||||||
tokenBalance = new BigNumber(await erc20.methods.balanceOf(senderAccount).call());
|
[ tokenBalance, tokenDecimals, tokenSymbol ] = await Promise.all([
|
||||||
tokenDecimals = await erc20.methods.decimals().call();
|
erc20.methods.balanceOf(senderAccount).call(),
|
||||||
tokenSymbol = await erc20.methods.symbol().call();
|
erc20.methods.decimals().call(),
|
||||||
|
erc20.methods.symbol().call()
|
||||||
|
]);
|
||||||
|
tokenBalance = new BigNumber(tokenBalance);
|
||||||
}
|
}
|
||||||
const toSend = new BigNumber(amount).times(BigNumber(10).pow(tokenDecimals));
|
const toSend = new BigNumber(amount).times(BigNumber(10).pow(tokenDecimals));
|
||||||
if (tokenBalance.lt(toSend)) {
|
if (tokenBalance.lt(toSend)) {
|
||||||
@ -478,7 +511,12 @@ async function send({ address, amount, tokenAddress }) {
|
|||||||
await generateTransaction(tokenAddress, encodeTransfer);
|
await generateTransaction(tokenAddress, encodeTransfer);
|
||||||
console.log('Sent', amount, tokenSymbol, 'to', address);
|
console.log('Sent', amount, tokenSymbol, 'to', address);
|
||||||
} else {
|
} else {
|
||||||
const balance = new BigNumber(await web3.eth.getBalance(senderAccount));
|
const fetchInfo = await Promise.all([
|
||||||
|
web3.eth.getBalance(senderAccount),
|
||||||
|
fetchGasPrice()
|
||||||
|
]);
|
||||||
|
const balance = new BigNumber(fetchInfo[0]);
|
||||||
|
const gasPrice = new BigNumber(fetchInfo[1]);
|
||||||
assert(balance.toNumber() !== 0, "You have 0 balance, can't send transaction");
|
assert(balance.toNumber() !== 0, "You have 0 balance, can't send transaction");
|
||||||
if (amount) {
|
if (amount) {
|
||||||
toSend = new BigNumber(amount).times(BigNumber(10).pow(18));
|
toSend = new BigNumber(amount).times(BigNumber(10).pow(18));
|
||||||
@ -488,10 +526,9 @@ async function send({ address, amount, tokenAddress }) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log('Amount not defined, sending all available amounts');
|
console.log('Amount not defined, sending all available amounts');
|
||||||
const gasPrice = new BigNumber(await fetchGasPrice());
|
|
||||||
const gasLimit = new BigNumber(21000);
|
const gasLimit = new BigNumber(21000);
|
||||||
if (netId == 1) {
|
if (netId == 1) {
|
||||||
const priorityFee = new BigNumber(await gasPrices(3));
|
const priorityFee = new BigNumber(gasPrices(3));
|
||||||
toSend = balance.minus(gasLimit.times(gasPrice.plus(priorityFee)));
|
toSend = balance.minus(gasLimit.times(gasPrice.plus(priorityFee)));
|
||||||
} else {
|
} else {
|
||||||
toSend = balance.minus(gasLimit.times(gasPrice));
|
toSend = balance.minus(gasLimit.times(gasPrice));
|
||||||
@ -853,14 +890,6 @@ async function fetchEvents({ type, currency, amount }) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapLatestEvents() {
|
|
||||||
if (type === "deposit"){
|
|
||||||
mapDepositEvents();
|
|
||||||
} else {
|
|
||||||
mapWithdrawEvents();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function fetchWeb3Events(i) {
|
async function fetchWeb3Events(i) {
|
||||||
let j;
|
let j;
|
||||||
if (i + chunks - 1 > targetBlock) {
|
if (i + chunks - 1 > targetBlock) {
|
||||||
@ -868,10 +897,18 @@ async function fetchEvents({ type, currency, amount }) {
|
|||||||
} else {
|
} else {
|
||||||
j = i + chunks - 1;
|
j = i + chunks - 1;
|
||||||
}
|
}
|
||||||
await tornadoContract.getPastEvents(capitalizeFirstLetter(type), {
|
|
||||||
|
try {
|
||||||
|
const getPastEvents = await tornadoContract.getPastEvents(capitalizeFirstLetter(type), {
|
||||||
fromBlock: i,
|
fromBlock: i,
|
||||||
toBlock: j,
|
toBlock: j,
|
||||||
}).then(r => { fetchedEvents = fetchedEvents.concat(r); console.log("Fetched", amount, currency.toUpperCase(), type, "events to block:", j) }, err => { console.error(i + " failed fetching", type, "events from node", err); process.exit(1); }).catch(console.log);
|
});
|
||||||
|
fetchedEvents = fetchedEvents.concat(getPastEvents);
|
||||||
|
console.log("Fetched", amount, currency.toUpperCase(), type, "events to block:", j);
|
||||||
|
} catch (e) {
|
||||||
|
console.error(i + " failed fetching", type, "events from node", e);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
if (type === "deposit"){
|
if (type === "deposit"){
|
||||||
mapDepositEvents();
|
mapDepositEvents();
|
||||||
@ -1075,6 +1112,7 @@ async function fetchEvents({ type, currency, amount }) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
await fetchGraphEvents();
|
await fetchGraphEvents();
|
||||||
|
await syncEvents();
|
||||||
}
|
}
|
||||||
if (!privateRpc && subgraph && !isTestRPC) {
|
if (!privateRpc && subgraph && !isTestRPC) {
|
||||||
await syncGraphEvents();
|
await syncGraphEvents();
|
||||||
@ -1145,7 +1183,7 @@ function parseInvoice(invoiceString) {
|
|||||||
async function loadDepositData({ amount, currency, deposit }) {
|
async function loadDepositData({ amount, currency, deposit }) {
|
||||||
try {
|
try {
|
||||||
const cachedEvents = await fetchEvents({ type: 'deposit', currency, amount });
|
const cachedEvents = await fetchEvents({ type: 'deposit', currency, amount });
|
||||||
const eventWhenHappened = await cachedEvents.filter(function (event) {
|
const eventWhenHappened = cachedEvents.filter(function (event) {
|
||||||
return event.commitment === deposit.commitmentHex;
|
return event.commitment === deposit.commitmentHex;
|
||||||
})[0];
|
})[0];
|
||||||
|
|
||||||
@ -1155,8 +1193,11 @@ async function loadDepositData({ amount, currency, deposit }) {
|
|||||||
|
|
||||||
const timestamp = eventWhenHappened.timestamp;
|
const timestamp = eventWhenHappened.timestamp;
|
||||||
const txHash = eventWhenHappened.transactionHash;
|
const txHash = eventWhenHappened.transactionHash;
|
||||||
const isSpent = await tornadoContract.methods.isSpent(deposit.nullifierHex).call();
|
|
||||||
const receipt = await web3.eth.getTransactionReceipt(txHash);
|
const [ isSpent, receipt ] = await Promise.all([
|
||||||
|
tornadoContract.methods.isSpent(deposit.nullifierHex).call(),
|
||||||
|
web3.eth.getTransactionReceipt(txHash)
|
||||||
|
]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
timestamp,
|
timestamp,
|
||||||
|
Loading…
Reference in New Issue
Block a user