Merge pull request #20 from 0xAyanami/develop
Bug fixes & Minor updates
This commit is contained in:
commit
80a810e727
72
README.md
72
README.md
@ -1,13 +1,40 @@
|
|||||||
# Warning!
|
# Tornado cli
|
||||||
|
|
||||||
|
Command line tool to interact with [Tornado Cash](https://tornadocash.eth.link).
|
||||||
|
|
||||||
|
### Warning!
|
||||||
Current cli version doesn't support [Anonymity Mining](https://tornado-cash.medium.com/tornado-cash-governance-proposal-a55c5c7d0703)
|
Current cli version doesn't support [Anonymity Mining](https://tornado-cash.medium.com/tornado-cash-governance-proposal-a55c5c7d0703)
|
||||||
|
|
||||||
### Goerli, Mainnet, Binance Smart Chain
|
### How to install tornado cli
|
||||||
|
Download and install [node.js](https://nodejs.org/en/download/).
|
||||||
|
|
||||||
|
If you have git installed on your system, clone the master branch.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ git clone https://github.com/tornadocash/tornado-cli
|
||||||
|
```
|
||||||
|
|
||||||
|
Or, download the archive file from github
|
||||||
|
|
||||||
|
https://github.com/tornadocash/tornado-cli/archive/refs/heads/master.zip
|
||||||
|
|
||||||
|
After downloading or cloning the repository, you must install necessary libraries using the following command.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cd tornado-cli
|
||||||
|
$ npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
If you want to use Tor connection to conceal ip address, install [Tor Browser](https://www.torproject.org/download/) and add `--tor 9150` for `cli.js` if you connect tor with browser.
|
||||||
|
Note that you should reset your tor connection by restarting the browser every time when you deposit & withdraw otherwise you will have the same exit node used for connection.
|
||||||
|
|
||||||
|
### Goerli, Mainnet, Binance Smart Chain, Gnosis Chain, Polygon Network, Arbitrum, Avalanche
|
||||||
1. Add `PRIVATE_KEY` to `.env` file
|
1. Add `PRIVATE_KEY` to `.env` file
|
||||||
2. `./cli.js --help`
|
2. `node cli.js --help`
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
```bash
|
```bash
|
||||||
$ ./cli.js deposit ETH 0.1 --rpc https://goerli.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161 --tor 9050
|
$ node cli.js deposit ETH 0.1 --rpc https://goerli.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161 --tor 9150
|
||||||
|
|
||||||
Your note: tornado-eth-0.1-5-0xf73dd6833ccbcc046c44228c8e2aa312bf49e08389dadc7c65e6a73239867b7ef49c705c4db227e2fadd8489a494b6880bdcb6016047e019d1abec1c7652
|
Your note: tornado-eth-0.1-5-0xf73dd6833ccbcc046c44228c8e2aa312bf49e08389dadc7c65e6a73239867b7ef49c705c4db227e2fadd8489a494b6880bdcb6016047e019d1abec1c7652
|
||||||
Tornado ETH balance is 8.9
|
Tornado ETH balance is 8.9
|
||||||
@ -18,7 +45,7 @@ Sender account ETH balance is 1004873.361652048361352542
|
|||||||
```
|
```
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ ./cli.js withdraw tornado-eth-0.1-5-0xf73dd6833ccbcc046c44228c8e2aa312bf49e08389dadc7c65e6a73239867b7ef49c705c4db227e2fadd8489a494b6880bdcb6016047e019d1abec1c7652 0x8589427373D6D84E98730D7795D8f6f8731FDA16 --rpc https://goerli.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161 --relayer https://goerli-frelay.duckdns.org --tor 9050
|
$ node cli.js withdraw tornado-eth-0.1-5-0xf73dd6833ccbcc046c44228c8e2aa312bf49e08389dadc7c65e6a73239867b7ef49c705c4db227e2fadd8489a494b6880bdcb6016047e019d1abec1c7652 0x8589427373D6D84E98730D7795D8f6f8731FDA16 --rpc https://goerli.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161 --relayer https://goerli-frelay.duckdns.org --tor 9150
|
||||||
|
|
||||||
Relay address: 0x6A31736e7490AbE5D5676be059DFf064AB4aC754
|
Relay address: 0x6A31736e7490AbE5D5676be059DFf064AB4aC754
|
||||||
Getting current state from tornado contract
|
Getting current state from tornado contract
|
||||||
@ -520,6 +547,41 @@ Infura API key fetched from https://rpc.info (Same one with Metamask)
|
|||||||
"cachedUrl":"https://goerli-v2.defidevotee.xyz"
|
"cachedUrl":"https://goerli-v2.defidevotee.xyz"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"netId10":{
|
||||||
|
"rpcUrls":{
|
||||||
|
"Optimism":{
|
||||||
|
"name":"Optimism Public RPC",
|
||||||
|
"url":"https://mainnet.optimism.io"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"relayers":{
|
||||||
|
"optimism.t-relay.eth":{
|
||||||
|
"url":"optimism.t-relay.eth",
|
||||||
|
"name":"optimism.t-relay.eth",
|
||||||
|
"cachedUrl":"https://optimism.t-relay.online/"
|
||||||
|
},
|
||||||
|
"optimism.therelayer.eth":{
|
||||||
|
"url":"optimism.therelayer.eth",
|
||||||
|
"name":"optimism.therelayer.eth",
|
||||||
|
"cachedUrl":"https://optimism.therelayer.xyz/"
|
||||||
|
},
|
||||||
|
"optimism.relayer-service.eth":{
|
||||||
|
"url":"optimism.relayer-service.eth",
|
||||||
|
"name":"optimism.relayer-service.eth",
|
||||||
|
"cachedUrl":"https://optimism-relayer.hertz.zone/"
|
||||||
|
},
|
||||||
|
"optimism.torn.eth":{
|
||||||
|
"url":"optimism.torn.eth",
|
||||||
|
"name":"optimism.torn.eth",
|
||||||
|
"cachedUrl":"https://optimism.torn.cash/"
|
||||||
|
},
|
||||||
|
"optimism.relaymy.eth":{
|
||||||
|
"url":"optimism.relaymy.eth",
|
||||||
|
"name":"optimism.relaymy.eth",
|
||||||
|
"cachedUrl":"https://optimism.relaymy.xyz/"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
264
cli.js
264
cli.js
@ -71,7 +71,11 @@ async function generateTransaction(to, encodedData, value = 0) {
|
|||||||
const bumped = Math.floor(fetchedGas * 1.3)
|
const bumped = Math.floor(fetchedGas * 1.3)
|
||||||
gasLimit = web3.utils.toHex(bumped)
|
gasLimit = web3.utils.toHex(bumped)
|
||||||
}
|
}
|
||||||
await estimateGas();
|
if (encodedData) {
|
||||||
|
await estimateGas();
|
||||||
|
} else {
|
||||||
|
gasLimit = web3.utils.toHex(21000);
|
||||||
|
}
|
||||||
|
|
||||||
async function txoptions() {
|
async function txoptions() {
|
||||||
// Generate EIP-1559 transaction
|
// Generate EIP-1559 transaction
|
||||||
@ -85,6 +89,16 @@ async function generateTransaction(to, encodedData, value = 0) {
|
|||||||
gas : gasLimit,
|
gas : gasLimit,
|
||||||
data : encodedData
|
data : encodedData
|
||||||
}
|
}
|
||||||
|
} else if (netId == 137 || netId == 43114) {
|
||||||
|
tx = {
|
||||||
|
to : to,
|
||||||
|
value : value,
|
||||||
|
nonce : nonce,
|
||||||
|
maxFeePerGas : gasPrice,
|
||||||
|
maxPriorityFeePerGas : gasPrice,
|
||||||
|
gas : gasLimit,
|
||||||
|
data : encodedData
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
tx = {
|
tx = {
|
||||||
to : to,
|
to : to,
|
||||||
@ -144,7 +158,7 @@ async function deposit({ currency, amount }) {
|
|||||||
const noteString = `tornado-${currency}-${amount}-${netId}-${note}`
|
const noteString = `tornado-${currency}-${amount}-${netId}-${note}`
|
||||||
console.log(`Your note: ${noteString}`)
|
console.log(`Your note: ${noteString}`)
|
||||||
await backupNote({ currency, amount, netId, note, noteString })
|
await backupNote({ currency, amount, netId, note, noteString })
|
||||||
if (currency === 'eth' || currency === 'bnb' || currency === 'xdai' || currency === 'matic' || currency === 'avax') {
|
if (currency === netSymbol.toLowerCase()) {
|
||||||
await printETHBalance({ address: tornadoContract._address, name: 'Tornado contract', symbol: currency.toUpperCase() })
|
await printETHBalance({ address: tornadoContract._address, name: 'Tornado contract', symbol: currency.toUpperCase() })
|
||||||
await printETHBalance({ address: senderAccount, name: 'Sender account', symbol: currency.toUpperCase() })
|
await printETHBalance({ address: senderAccount, name: 'Sender account', symbol: currency.toUpperCase() })
|
||||||
const value = isLocalRPC ? ETH_AMOUNT : fromDecimals({ amount, decimals: 18 })
|
const value = isLocalRPC ? ETH_AMOUNT : fromDecimals({ amount, decimals: 18 })
|
||||||
@ -269,7 +283,7 @@ async function generateProof({ deposit, currency, amount, recipient, relayerAddr
|
|||||||
*/
|
*/
|
||||||
async function withdraw({ deposit, currency, amount, recipient, relayerURL, torPort, refund = '0' }) {
|
async function withdraw({ deposit, currency, amount, recipient, relayerURL, torPort, refund = '0' }) {
|
||||||
let options = {};
|
let options = {};
|
||||||
if (currency === 'eth' && refund !== '0') {
|
if (currency === netSymbol.toLowerCase() && refund !== '0') {
|
||||||
throw new Error('The ETH purchase is supposted to be 0 for ETH withdrawals')
|
throw new Error('The ETH purchase is supposted to be 0 for ETH withdrawals')
|
||||||
}
|
}
|
||||||
refund = toWei(refund)
|
refund = toWei(refund)
|
||||||
@ -328,7 +342,7 @@ async function withdraw({ deposit, currency, amount, recipient, relayerURL, torP
|
|||||||
|
|
||||||
// check if the address of recepient matches with the account of provided private key from environment to prevent accidental use of deposit address for withdrawal transaction.
|
// check if the address of recepient matches with the account of provided private key from environment to prevent accidental use of deposit address for withdrawal transaction.
|
||||||
const { address } = await web3.eth.accounts.privateKeyToAccount('0x' + PRIVATE_KEY)
|
const { address } = await web3.eth.accounts.privateKeyToAccount('0x' + PRIVATE_KEY)
|
||||||
assert(recipient.toLowerCase() == address.toLowerCase(), 'Withdrawal amount recepient',recipient,'mismatches with the account of provided private key from environment file',address)
|
assert(recipient.toLowerCase() == address.toLowerCase(), 'Withdrawal amount recepient mismatches with the account of provided private key from environment file')
|
||||||
|
|
||||||
const { proof, args } = await generateProof({ deposit, currency, amount, recipient, refund })
|
const { proof, args } = await generateProof({ deposit, currency, amount, recipient, refund })
|
||||||
|
|
||||||
@ -338,6 +352,53 @@ async function withdraw({ deposit, currency, amount, recipient, relayerURL, torP
|
|||||||
console.log('Done withdrawal from Tornado Cash')
|
console.log('Done withdrawal from Tornado Cash')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do an ETH / ERC20 send
|
||||||
|
* @param address Recepient address
|
||||||
|
* @param amount Amount to send
|
||||||
|
* @param tokenAddress ERC20 token address
|
||||||
|
*/
|
||||||
|
async function send({ address, amount, tokenAddress }) {
|
||||||
|
// using private key
|
||||||
|
assert(senderAccount != null, 'Error! PRIVATE_KEY not found. Please provide PRIVATE_KEY in .env file if you send')
|
||||||
|
if (tokenAddress) {
|
||||||
|
const erc20ContractJson = require('./build/contracts/ERC20Mock.json')
|
||||||
|
erc20 = new web3.eth.Contract(erc20ContractJson.abi, tokenAddress)
|
||||||
|
const balance = await erc20.methods.balanceOf(senderAccount).call()
|
||||||
|
const decimals = await erc20.methods.decimals().call()
|
||||||
|
const toSend = amount * Math.pow(10, decimals)
|
||||||
|
if (balance < toSend) {
|
||||||
|
console.error("You have",toDecimals(balance, decimals, (balance.length + decimals)).toString().replace(/\B(?<!\.\d*)(?=(\d{3})+(?!\d))/g, ","),(await erc20.methods.symbol().call()),", you can't send more than you have")
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
await generateTransaction(tokenAddress, await erc20.methods.transfer(address, toBN(toSend)).encodeABI())
|
||||||
|
console.log('Sent',amount,(await erc20.methods.symbol().call()),'to',address);
|
||||||
|
} else {
|
||||||
|
const balance = await web3.eth.getBalance(senderAccount)
|
||||||
|
if (balance == 0) {
|
||||||
|
console.error("You have 0 balance, can't send")
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
if (!amount) {
|
||||||
|
console.log('Amount not defined, sending all available amounts')
|
||||||
|
const gasPrice = await fetchGasPrice()
|
||||||
|
const gasLimit = 21000;
|
||||||
|
if (netId == 1 || netId == 5) {
|
||||||
|
const priorityFee = await gasPrices(3)
|
||||||
|
amount = (balance - (gasLimit * (parseInt(gasPrice) + parseInt(priorityFee))))
|
||||||
|
} else {
|
||||||
|
amount = (balance - (gasLimit * parseInt(gasPrice)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (balance < amount) {
|
||||||
|
console.error("You have",web3.utils.fromWei(toHex(balance)),netSymbol,", you can't send more than you have.")
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
await generateTransaction(address, null, amount)
|
||||||
|
console.log('Sent',web3.utils.fromWei(toHex(amount)),netSymbol,'to',address);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function getStatus(id, relayerURL, options) {
|
function getStatus(id, relayerURL, options) {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
async function getRelayerStatus() {
|
async function getRelayerStatus() {
|
||||||
@ -476,6 +537,8 @@ function getExplorerLink() {
|
|||||||
return 'goerli.etherscan.io'
|
return 'goerli.etherscan.io'
|
||||||
case 42:
|
case 42:
|
||||||
return 'kovan.etherscan.io'
|
return 'kovan.etherscan.io'
|
||||||
|
case 10:
|
||||||
|
return 'optimistic.etherscan.io'
|
||||||
default:
|
default:
|
||||||
return 'etherscan.io'
|
return 'etherscan.io'
|
||||||
}
|
}
|
||||||
@ -500,6 +563,8 @@ function getCurrentNetworkName() {
|
|||||||
return 'Goerli'
|
return 'Goerli'
|
||||||
case 42:
|
case 42:
|
||||||
return 'Kovan'
|
return 'Kovan'
|
||||||
|
case 137:
|
||||||
|
return 'Optimism'
|
||||||
default:
|
default:
|
||||||
return 'localRPC'
|
return 'localRPC'
|
||||||
}
|
}
|
||||||
@ -562,23 +627,7 @@ function calculateFee({ currency, gasPrice, amount, refund, ethPrices, relayerSe
|
|||||||
const expense = toBN(gasPrice).mul(toBN(5e5))
|
const expense = toBN(gasPrice).mul(toBN(5e5))
|
||||||
let desiredFee
|
let desiredFee
|
||||||
switch (currency) {
|
switch (currency) {
|
||||||
case 'eth': {
|
case netSymbol.toLowerCase(): {
|
||||||
desiredFee = expense.add(feePercent)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
case 'bnb': {
|
|
||||||
desiredFee = expense.add(feePercent)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
case 'xdai': {
|
|
||||||
desiredFee = expense.add(feePercent)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
case 'matic': {
|
|
||||||
desiredFee = expense.add(feePercent)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
case 'avax': {
|
|
||||||
desiredFee = expense.add(feePercent)
|
desiredFee = expense.add(feePercent)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -618,6 +667,21 @@ function waitForTxReceipt({ txHash, attempts = 60, delay = 1000 }) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function initJson(file) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
fs.readFile(file, 'utf8', (error, data) => {
|
||||||
|
if (error) {
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
resolve(JSON.parse(data));
|
||||||
|
} catch (error) {
|
||||||
|
resolve([]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
function loadCachedEvents({ type, currency, amount }) {
|
function loadCachedEvents({ type, currency, amount }) {
|
||||||
try {
|
try {
|
||||||
const module = require(`./cache/${netName.toLowerCase()}/${type}s_${currency}_${amount}.json`)
|
const module = require(`./cache/${netName.toLowerCase()}/${type}s_${currency}_${amount}.json`)
|
||||||
@ -640,10 +704,6 @@ function loadCachedEvents({ type, currency, amount }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function fetchEvents({ type, currency, amount}) {
|
async function fetchEvents({ type, currency, amount}) {
|
||||||
let leafIndex = -1
|
|
||||||
let events = [];
|
|
||||||
let fetchedEvents, chunks, targetBlock;
|
|
||||||
|
|
||||||
if (type === "withdraw") {
|
if (type === "withdraw") {
|
||||||
type = "withdrawal"
|
type = "withdrawal"
|
||||||
}
|
}
|
||||||
@ -651,75 +711,86 @@ async function fetchEvents({ type, currency, amount}) {
|
|||||||
const cachedEvents = loadCachedEvents({ type, currency, amount })
|
const cachedEvents = loadCachedEvents({ type, currency, amount })
|
||||||
const startBlock = cachedEvents.lastBlock + 1
|
const startBlock = cachedEvents.lastBlock + 1
|
||||||
|
|
||||||
|
console.log("Loaded cached",amount,currency.toUpperCase(),type,"events for",startBlock,"block")
|
||||||
console.log("Fetching",amount,currency.toUpperCase(),type,"events for",netName,"network")
|
console.log("Fetching",amount,currency.toUpperCase(),type,"events for",netName,"network")
|
||||||
|
|
||||||
async function fetchLatestEvents() {
|
async function syncEvents() {
|
||||||
targetBlock = await web3.eth.getBlockNumber();
|
|
||||||
chunks = 1000;
|
|
||||||
fetchedEvents = [];
|
|
||||||
for (let i=startBlock; i < targetBlock; i+=chunks) {
|
|
||||||
await tornadoContract.getPastEvents(capitalizeFirstLetter(type), {
|
|
||||||
fromBlock: i,
|
|
||||||
toBlock: i+chunks-1,
|
|
||||||
}).then(r => { fetchedEvents = fetchedEvents.concat(r); console.log("Fetched",amount,currency.toUpperCase(),type,"events from block:", i) }, err => { console.error(i + " failed fetching",type,"events from node", err) }).catch(console.log);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
await fetchLatestEvents()
|
|
||||||
|
|
||||||
async function mapDepositEvents() {
|
|
||||||
fetchedEvents = fetchedEvents.map(({ blockNumber, transactionHash, returnValues }) => {
|
|
||||||
const { commitment, leafIndex, timestamp } = returnValues
|
|
||||||
return {
|
|
||||||
blockNumber,
|
|
||||||
transactionHash,
|
|
||||||
commitment,
|
|
||||||
leafIndex: Number(leafIndex),
|
|
||||||
timestamp
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
async function mapWithdrawEvents() {
|
|
||||||
fetchedEvents = fetchedEvents.map(({ blockNumber, transactionHash, returnValues }) => {
|
|
||||||
const { nullifierHash, to, fee } = returnValues
|
|
||||||
return {
|
|
||||||
blockNumber,
|
|
||||||
transactionHash,
|
|
||||||
nullifierHash,
|
|
||||||
to,
|
|
||||||
fee
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
async function mapLatestEvents() {
|
|
||||||
console.log("Mapping",amount,currency.toUpperCase(),type,"events, please wait")
|
|
||||||
if (type === "deposit"){
|
|
||||||
await mapDepositEvents();
|
|
||||||
} else {
|
|
||||||
await mapWithdrawEvents();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
await mapLatestEvents();
|
|
||||||
|
|
||||||
console.log("Gathering cached events + collected events from node")
|
|
||||||
|
|
||||||
async function concatEvents() {
|
|
||||||
events = cachedEvents.events.concat(fetchedEvents)
|
|
||||||
}
|
|
||||||
await concatEvents();
|
|
||||||
|
|
||||||
console.log('Total events:', events.length)
|
|
||||||
|
|
||||||
async function updateCache() {
|
|
||||||
try {
|
try {
|
||||||
await fs.writeFileSync(`./cache/${netName.toLowerCase()}/${type}s_${currency}_${amount}.json`, JSON.stringify(events, null, 2), 'utf8')
|
let targetBlock = await web3.eth.getBlockNumber();
|
||||||
console.log("Cache updated for Tornado",type,amount,currency,"instance successfully")
|
let chunks = 1000;
|
||||||
} catch (e) {
|
for (let i=startBlock; i < targetBlock; i+=chunks) {
|
||||||
throw new Error('Writing cache file failed:',e)
|
let fetchedEvents = [];
|
||||||
|
async function fetchLatestEvents(i) {
|
||||||
|
await tornadoContract.getPastEvents(capitalizeFirstLetter(type), {
|
||||||
|
fromBlock: i,
|
||||||
|
toBlock: i+chunks-1,
|
||||||
|
}).then(r => { fetchedEvents = fetchedEvents.concat(r); console.log("Fetched",amount,currency.toUpperCase(),type,"events to block:", i) }, err => { console.error(i + " failed fetching",type,"events from node", err); process.exit(1); }).catch(console.log);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function mapDepositEvents() {
|
||||||
|
fetchedEvents = fetchedEvents.map(({ blockNumber, transactionHash, returnValues }) => {
|
||||||
|
const { commitment, leafIndex, timestamp } = returnValues
|
||||||
|
return {
|
||||||
|
blockNumber,
|
||||||
|
transactionHash,
|
||||||
|
commitment,
|
||||||
|
leafIndex: Number(leafIndex),
|
||||||
|
timestamp
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function mapWithdrawEvents() {
|
||||||
|
fetchedEvents = fetchedEvents.map(({ blockNumber, transactionHash, returnValues }) => {
|
||||||
|
const { nullifierHash, to, fee } = returnValues
|
||||||
|
return {
|
||||||
|
blockNumber,
|
||||||
|
transactionHash,
|
||||||
|
nullifierHash,
|
||||||
|
to,
|
||||||
|
fee
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function mapLatestEvents() {
|
||||||
|
if (type === "deposit"){
|
||||||
|
await mapDepositEvents();
|
||||||
|
} else {
|
||||||
|
await mapWithdrawEvents();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function updateCache() {
|
||||||
|
try {
|
||||||
|
const fileName = `./cache/${netName.toLowerCase()}/${type}s_${currency}_${amount}.json`
|
||||||
|
const localEvents = await initJson(fileName);
|
||||||
|
const events = localEvents.concat(fetchedEvents);
|
||||||
|
await fs.writeFileSync(fileName, JSON.stringify(events, null, 2), 'utf8')
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error('Writing cache file failed:',error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await fetchLatestEvents(i);
|
||||||
|
await mapLatestEvents();
|
||||||
|
await updateCache();
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error("Error while updating cache")
|
||||||
|
process.exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await updateCache();
|
await syncEvents();
|
||||||
|
|
||||||
|
async function loadUpdatedEvents() {
|
||||||
|
const fileName = `./cache/${netName.toLowerCase()}/${type}s_${currency}_${amount}.json`
|
||||||
|
const updatedEvents = await initJson(fileName);
|
||||||
|
const updatedBlock = updatedEvents[updatedEvents.length - 1].blockNumber
|
||||||
|
console.log("Cache updated for Tornado",type,amount,currency,"instance to block",updatedBlock,"successfully")
|
||||||
|
console.log('Total events:', updatedEvents.length)
|
||||||
|
return updatedEvents;
|
||||||
|
}
|
||||||
|
const events = await loadUpdatedEvents();
|
||||||
|
|
||||||
return events
|
return events
|
||||||
}
|
}
|
||||||
@ -846,7 +917,12 @@ async function init({ rpc, noteNetId, currency = 'dai', amount = '100', torPort,
|
|||||||
MERKLE_TREE_HEIGHT = process.env.MERKLE_TREE_HEIGHT || 20
|
MERKLE_TREE_HEIGHT = process.env.MERKLE_TREE_HEIGHT || 20
|
||||||
ETH_AMOUNT = process.env.ETH_AMOUNT
|
ETH_AMOUNT = process.env.ETH_AMOUNT
|
||||||
TOKEN_AMOUNT = process.env.TOKEN_AMOUNT
|
TOKEN_AMOUNT = process.env.TOKEN_AMOUNT
|
||||||
PRIVATE_KEY = process.env.PRIVATE_KEY
|
const privKey = process.env.PRIVATE_KEY
|
||||||
|
if (privKey.includes("0x")) {
|
||||||
|
PRIVATE_KEY = process.env.PRIVATE_KEY.substring(2)
|
||||||
|
} else {
|
||||||
|
PRIVATE_KEY = process.env.PRIVATE_KEY
|
||||||
|
}
|
||||||
if (PRIVATE_KEY) {
|
if (PRIVATE_KEY) {
|
||||||
const account = web3.eth.accounts.privateKeyToAccount('0x' + PRIVATE_KEY)
|
const account = web3.eth.accounts.privateKeyToAccount('0x' + PRIVATE_KEY)
|
||||||
web3.eth.accounts.wallet.add('0x' + PRIVATE_KEY)
|
web3.eth.accounts.wallet.add('0x' + PRIVATE_KEY)
|
||||||
@ -893,6 +969,7 @@ async function init({ rpc, noteNetId, currency = 'dai', amount = '100', torPort,
|
|||||||
process.exit(1)
|
process.exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
netSymbol = getCurrentNetworkSymbol()
|
||||||
tornado = new web3.eth.Contract(contractJson, tornadoAddress)
|
tornado = new web3.eth.Contract(contractJson, tornadoAddress)
|
||||||
tornadoContract = new web3.eth.Contract(instanceJson, tornadoInstance)
|
tornadoContract = new web3.eth.Contract(instanceJson, tornadoInstance)
|
||||||
contractAddress = tornadoAddress
|
contractAddress = tornadoAddress
|
||||||
@ -958,6 +1035,13 @@ async function main() {
|
|||||||
await printERC20Balance({ address, name: 'Account', tokenAddress })
|
await printERC20Balance({ address, name: 'Account', tokenAddress })
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
program
|
||||||
|
.command('send <address> [amount] [token_address]')
|
||||||
|
.description('Send ETH or ERC to address')
|
||||||
|
.action(async (address, amount, tokenAddress) => {
|
||||||
|
await init({ rpc: program.rpc, torPort: program.tor, balanceCheck: true })
|
||||||
|
await send({ address, amount, tokenAddress })
|
||||||
|
})
|
||||||
program
|
program
|
||||||
.command('compliance <note>')
|
.command('compliance <note>')
|
||||||
.description(
|
.description(
|
||||||
|
20
config.js
20
config.js
@ -330,5 +330,25 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
proxy: '0x0D5550d52428E7e3175bfc9550207e4ad3859b17',
|
proxy: '0x0D5550d52428E7e3175bfc9550207e4ad3859b17',
|
||||||
},
|
},
|
||||||
|
netId42161: {
|
||||||
|
'eth': {
|
||||||
|
'instanceAddress': {
|
||||||
|
'0.1': '0x84443CFd09A48AF6eF360C6976C5392aC5023a1F',
|
||||||
|
'1': '0xd47438C816c9E7f2E2888E060936a499Af9582b3',
|
||||||
|
'10': '0x330bdFADE01eE9bF63C209Ee33102DD334618e0a',
|
||||||
|
'100': '0x1E34A77868E19A6647b1f2F47B51ed72dEDE95DD'
|
||||||
|
},
|
||||||
|
'deployedBlockNumber': {
|
||||||
|
'0.1': 2243707,
|
||||||
|
'1': 2243709,
|
||||||
|
'10': 2243735,
|
||||||
|
'100': 2243749
|
||||||
|
},
|
||||||
|
'miningEnabled': false,
|
||||||
|
'symbol': 'ETH',
|
||||||
|
'decimals': 18
|
||||||
|
},
|
||||||
|
proxy: '0x0D5550d52428E7e3175bfc9550207e4ad3859b17',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user