mirror of
https://github.com/tornadocash/tornado-cli.git
synced 2024-12-25 15:49:33 -05:00
Merge branch 'master' into fixTorando
This commit is contained in:
commit
4dbdd42252
7
.prettierrc
Normal file
7
.prettierrc
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"singleQuote": true,
|
||||||
|
"trailingComma": "none",
|
||||||
|
"bracketSpacing": true,
|
||||||
|
"semi": false,
|
||||||
|
"printWidth": 130
|
||||||
|
}
|
35
README.md
35
README.md
@ -7,24 +7,25 @@ Current cli version doesn't support [Anonymity Mining](https://tornado-cash.medi
|
|||||||
|
|
||||||
Example:
|
Example:
|
||||||
```bash
|
```bash
|
||||||
./cli.js deposit ETH 0.1 --rpc https://kovan.infura.io/v3/27a9649f826b4e31a83e07ae09a87448
|
$ ./cli.js deposit ETH 0.1 --rpc https://kovan.infura.io/v3/27a9649f826b4e31a83e07ae09a87448
|
||||||
|
|
||||||
|
Your note: tornado-eth-0.1-42-0xf73dd6833ccbcc046c44228c8e2aa312bf49e08389dadc7c65e6a73239867b7ef49c705c4db227e2fadd8489a494b6880bdcb6016047e019d1abec1c7652
|
||||||
|
Tornado ETH balance is 8.9
|
||||||
|
Sender account ETH balance is 1004873.470619891361352542
|
||||||
|
Submitting deposit transaction
|
||||||
|
Tornado ETH balance is 9
|
||||||
|
Sender account ETH balance is 1004873.361652048361352542
|
||||||
```
|
```
|
||||||
> Your note: tornado-eth-0.1-42-0xf73dd6833ccbcc046c44228c8e2aa312bf49e08389dadc7c65e6a73239867b7ef49c705c4db227e2fadd8489a494b6880bdcb6016047e019d1abec1c7652
|
|
||||||
> Tornado ETH balance is 8.9
|
|
||||||
> Sender account ETH balance is 1004873.470619891361352542
|
|
||||||
> Submitting deposit transaction
|
|
||||||
> Tornado ETH balance is 9
|
|
||||||
> Sender account ETH balance is 1004873.361652048361352542
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./cli.js withdraw tornado-eth-0.1-42-0xf73dd6833ccbcc046c44228c8e2aa312bf49e08389dadc7c65e6a73239867b7ef49c705c4db227e2fadd8489a494b6880bdcb6016047e019d1abec1c7652 0x8589427373D6D84E98730D7795D8f6f8731FDA16 --rpc https://kovan.infura.io/v3/27a9649f826b4e31a83e07ae09a87448 --relayer https://kovan-frelay.duckdns.org
|
$ ./cli.js withdraw tornado-eth-0.1-42-0xf73dd6833ccbcc046c44228c8e2aa312bf49e08389dadc7c65e6a73239867b7ef49c705c4db227e2fadd8489a494b6880bdcb6016047e019d1abec1c7652 0x8589427373D6D84E98730D7795D8f6f8731FDA16 --rpc https://kovan.infura.io/v3/27a9649f826b4e31a83e07ae09a87448 --relayer https://kovan-frelay.duckdns.org
|
||||||
```
|
|
||||||
|
|
||||||
> Relay address: 0x6A31736e7490AbE5D5676be059DFf064AB4aC754
|
Relay address: 0x6A31736e7490AbE5D5676be059DFf064AB4aC754
|
||||||
> Getting current state from tornado contract
|
Getting current state from tornado contract
|
||||||
> Generating SNARK proof
|
Generating SNARK proof
|
||||||
> Proof time: 9117.051ms
|
Proof time: 9117.051ms
|
||||||
> Sending withdraw transaction through relay
|
Sending withdraw transaction through relay
|
||||||
> Transaction submitted through the relay. View transaction on etherscan https://kovan.etherscan.io/tx/0xcb21ae8cad723818c6bc7273e83e00c8393fcdbe74802ce5d562acad691a2a7b
|
Transaction submitted through the relay. View transaction on etherscan https://kovan.etherscan.io/tx/0xcb21ae8cad723818c6bc7273e83e00c8393fcdbe74802ce5d562acad691a2a7b
|
||||||
> Transaction mined in block 17036120
|
Transaction mined in block 17036120
|
||||||
> Done
|
Done
|
||||||
|
```
|
||||||
|
169
cli.js
169
cli.js
@ -23,14 +23,14 @@ let web3, tornado, mixerContract, tornadoInstance, circuit, proving_key, groth16
|
|||||||
let MERKLE_TREE_HEIGHT, ETH_AMOUNT, TOKEN_AMOUNT, PRIVATE_KEY
|
let MERKLE_TREE_HEIGHT, ETH_AMOUNT, TOKEN_AMOUNT, PRIVATE_KEY
|
||||||
|
|
||||||
/** Whether we are in a browser or node.js */
|
/** Whether we are in a browser or node.js */
|
||||||
const inBrowser = (typeof window !== 'undefined')
|
const inBrowser = typeof window !== 'undefined'
|
||||||
let isLocalRPC = false
|
let isLocalRPC = false
|
||||||
|
|
||||||
/** Generate random number of specified byte length */
|
/** Generate random number of specified byte length */
|
||||||
const rbigint = nbytes => snarkjs.bigInt.leBuff2int(crypto.randomBytes(nbytes))
|
const rbigint = (nbytes) => snarkjs.bigInt.leBuff2int(crypto.randomBytes(nbytes))
|
||||||
|
|
||||||
/** Compute pedersen hash */
|
/** Compute pedersen hash */
|
||||||
const pedersenHash = data => circomlib.babyJub.unpackPoint(circomlib.pedersenHash.hash(data))[0]
|
const pedersenHash = (data) => circomlib.babyJub.unpackPoint(circomlib.pedersenHash.hash(data))[0]
|
||||||
|
|
||||||
/** BigNumber to hex string of specified length */
|
/** BigNumber to hex string of specified length */
|
||||||
function toHex(number, length = 32) {
|
function toHex(number, length = 32) {
|
||||||
@ -69,7 +69,10 @@ function createDeposit({ nullifier, secret }) {
|
|||||||
* @param amount Deposit amount
|
* @param amount Deposit amount
|
||||||
*/
|
*/
|
||||||
async function deposit({ currency, amount }) {
|
async function deposit({ currency, amount }) {
|
||||||
const deposit = createDeposit({ nullifier: rbigint(31), secret: rbigint(31) })
|
const deposit = createDeposit({
|
||||||
|
nullifier: rbigint(31),
|
||||||
|
secret: rbigint(31)
|
||||||
|
})
|
||||||
const note = toHex(deposit.preimage, 62)
|
const note = toHex(deposit.preimage, 62)
|
||||||
const noteString = `tornado-${currency}-${amount}-${netId}-${note}`
|
const noteString = `tornado-${currency}-${amount}-${netId}-${note}`
|
||||||
console.log(`Your note: ${noteString}`)
|
console.log(`Your note: ${noteString}`)
|
||||||
@ -81,7 +84,8 @@ async function deposit({ currency, amount }) {
|
|||||||
await tornado.methods.deposit(tornadoInstance, toHex(deposit.commitment), []).send({ value, from: senderAccount, gas: 2e6 })
|
await tornado.methods.deposit(tornadoInstance, toHex(deposit.commitment), []).send({ value, from: senderAccount, gas: 2e6 })
|
||||||
await printETHBalance({ address: tornado._address, name: 'Tornado' })
|
await printETHBalance({ address: tornado._address, name: 'Tornado' })
|
||||||
await printETHBalance({ address: senderAccount, name: 'Sender account' })
|
await printETHBalance({ address: senderAccount, name: 'Sender account' })
|
||||||
} else { // a token
|
} else {
|
||||||
|
// a token
|
||||||
await printERC20Balance({ address: tornado._address, name: 'Tornado' })
|
await printERC20Balance({ address: tornado._address, name: 'Tornado' })
|
||||||
await printERC20Balance({ address: senderAccount, name: 'Sender account' })
|
await printERC20Balance({ address: senderAccount, name: 'Sender account' })
|
||||||
const decimals = isLocalRPC ? 18 : config.deployments[`netId${netId}`][currency].decimals
|
const decimals = isLocalRPC ? 18 : config.deployments[`netId${netId}`][currency].decimals
|
||||||
@ -116,6 +120,7 @@ async function deposit({ currency, amount }) {
|
|||||||
async function generateMerkleProof(deposit, amount) {
|
async function generateMerkleProof(deposit, amount) {
|
||||||
let leafIndex = -1
|
let leafIndex = -1
|
||||||
// Get all deposit events from smart contract and assemble merkle tree from them
|
// Get all deposit events from smart contract and assemble merkle tree from them
|
||||||
|
|
||||||
const cachedEvents = loadCachedEvents({ type: 'Deposit', amount })
|
const cachedEvents = loadCachedEvents({ type: 'Deposit', amount })
|
||||||
|
|
||||||
const startBlock = cachedEvents.lastBlock
|
const startBlock = cachedEvents.lastBlock
|
||||||
@ -189,7 +194,7 @@ async function generateProof({ deposit, amount, recipient, relayerAddress = 0, f
|
|||||||
nullifier: deposit.nullifier,
|
nullifier: deposit.nullifier,
|
||||||
secret: deposit.secret,
|
secret: deposit.secret,
|
||||||
pathElements: path_elements,
|
pathElements: path_elements,
|
||||||
pathIndices: path_index,
|
pathIndices: path_index
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Generating SNARK proof')
|
console.log('Generating SNARK proof')
|
||||||
@ -227,13 +232,21 @@ async function withdraw({ deposit, currency, amount, recipient, relayerURL, refu
|
|||||||
const relayerStatus = await axios.get(relayerURL + '/status')
|
const relayerStatus = await axios.get(relayerURL + '/status')
|
||||||
|
|
||||||
const { rewardAccount, netId, ethPrices, tornadoServiceFee } = relayerStatus.data
|
const { rewardAccount, netId, ethPrices, tornadoServiceFee } = relayerStatus.data
|
||||||
assert(netId === await web3.eth.net.getId() || netId === '*', 'This relay is for different network')
|
assert(netId === (await web3.eth.net.getId()) || netId === '*', 'This relay is for different network')
|
||||||
console.log('Relay address: ', rewardAccount)
|
console.log('Relay address: ', rewardAccount)
|
||||||
|
|
||||||
const gasPrice = await fetchGasPrice()
|
const gasPrice = await fetchGasPrice()
|
||||||
|
|
||||||
const decimals = isLocalRPC ? 18 : config.deployments[`netId${netId}`][currency].decimals
|
const decimals = isLocalRPC ? 18 : config.deployments[`netId${netId}`][currency].decimals
|
||||||
const fee = calculateFee({ currency, gasPrice, amount, refund, ethPrices, relayerServiceFee: tornadoServiceFee, decimals })
|
const fee = calculateFee({
|
||||||
|
currency,
|
||||||
|
gasPrice,
|
||||||
|
amount,
|
||||||
|
refund,
|
||||||
|
ethPrices,
|
||||||
|
relayerServiceFee: tornadoServiceFee,
|
||||||
|
decimals
|
||||||
|
})
|
||||||
if (fee.gt(fromDecimals({ amount, decimals }))) {
|
if (fee.gt(fromDecimals({ amount, decimals }))) {
|
||||||
throw new Error('Too high refund')
|
throw new Error('Too high refund')
|
||||||
}
|
}
|
||||||
@ -242,7 +255,11 @@ async function withdraw({ deposit, currency, amount, recipient, relayerURL, refu
|
|||||||
|
|
||||||
console.log('Sending withdraw transaction through relay')
|
console.log('Sending withdraw transaction through relay')
|
||||||
try {
|
try {
|
||||||
const response = await axios.post(relayerURL + '/v1/tornadoWithdraw', { contract: tornadoInstance, proof, args })
|
const response = await axios.post(relayerURL + '/v1/tornadoWithdraw', {
|
||||||
|
contract: tornadoInstance,
|
||||||
|
proof,
|
||||||
|
args
|
||||||
|
})
|
||||||
|
|
||||||
const { id } = response.data
|
const { id } = response.data
|
||||||
|
|
||||||
@ -255,25 +272,29 @@ async function withdraw({ deposit, currency, amount, recipient, relayerURL, refu
|
|||||||
console.error(e.message)
|
console.error(e.message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else { // using private key
|
} else {
|
||||||
|
// using private key
|
||||||
const { proof, args } = await generateProof({ deposit, recipient, refund })
|
const { proof, args } = await generateProof({ deposit, recipient, refund })
|
||||||
|
|
||||||
console.log('Submitting withdraw transaction')
|
console.log('Submitting withdraw transaction')
|
||||||
await tornado.methods.withdraw(tornadoInstance, proof, ...args).send({ from: senderAccount, value: refund.toString(), gas: 1e6 })
|
await tornado.methods
|
||||||
|
.withdraw(tornadoInstance, proof, ...args)
|
||||||
|
.send({ from: senderAccount, value: refund.toString(), gas: 1e6 })
|
||||||
.on('transactionHash', function (txHash) {
|
.on('transactionHash', function (txHash) {
|
||||||
if (netId === 1 || netId === 42) {
|
if (netId === 1 || netId === 42) {
|
||||||
console.log(`View transaction on etherscan https://${getCurrentNetworkName()}etherscan.io/tx/${txHash}`)
|
console.log(`View transaction on etherscan https://${getCurrentNetworkName()}etherscan.io/tx/${txHash}`)
|
||||||
} else {
|
} else {
|
||||||
console.log(`The transaction hash is ${txHash}`)
|
console.log(`The transaction hash is ${txHash}`)
|
||||||
}
|
}
|
||||||
}).on('error', function (e) {
|
})
|
||||||
|
.on('error', function (e) {
|
||||||
console.error('on transactionHash error', e.message)
|
console.error('on transactionHash error', e.message)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
console.log('Done')
|
console.log('Done')
|
||||||
}
|
}
|
||||||
|
|
||||||
function getStatus (id, relayerURL) {
|
function getStatus(id, relayerURL) {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
async function getRelayerStatus() {
|
async function getRelayerStatus() {
|
||||||
const responseStatus = await axios.get(relayerURL + '/v1/jobs/' + id)
|
const responseStatus = await axios.get(relayerURL + '/v1/jobs/' + id)
|
||||||
@ -289,7 +310,9 @@ function getStatus (id, relayerURL) {
|
|||||||
|
|
||||||
if (status === 'CONFIRMED') {
|
if (status === 'CONFIRMED') {
|
||||||
const receipt = await waitForTxReceipt({ txHash })
|
const receipt = await waitForTxReceipt({ txHash })
|
||||||
console.log(`Transaction submitted through the relay. View transaction on etherscan https://${getCurrentNetworkName()}etherscan.io/tx/${txHash}`)
|
console.log(
|
||||||
|
`Transaction submitted through the relay. View transaction on etherscan https://${getCurrentNetworkName()}etherscan.io/tx/${txHash}`
|
||||||
|
)
|
||||||
console.log('Transaction mined in block', receipt.blockNumber)
|
console.log('Transaction mined in block', receipt.blockNumber)
|
||||||
resolve(status)
|
resolve(status)
|
||||||
}
|
}
|
||||||
@ -322,9 +345,7 @@ function fromDecimals({ amount, decimals }) {
|
|||||||
// Split it into a whole and fractional part
|
// Split it into a whole and fractional part
|
||||||
const comps = ether.split('.')
|
const comps = ether.split('.')
|
||||||
if (comps.length > 2) {
|
if (comps.length > 2) {
|
||||||
throw new Error(
|
throw new Error('[ethjs-unit] while converting number ' + amount + ' to wei, too many decimal points')
|
||||||
'[ethjs-unit] while converting number ' + amount + ' to wei, too many decimal points'
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let whole = comps[0]
|
let whole = comps[0]
|
||||||
@ -337,9 +358,7 @@ function fromDecimals({ amount, decimals }) {
|
|||||||
fraction = '0'
|
fraction = '0'
|
||||||
}
|
}
|
||||||
if (fraction.length > baseLength) {
|
if (fraction.length > baseLength) {
|
||||||
throw new Error(
|
throw new Error('[ethjs-unit] while converting number ' + amount + ' to wei, too many decimal places')
|
||||||
'[ethjs-unit] while converting number ' + amount + ' to wei, too many decimal places'
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while (fraction.length < baseLength) {
|
while (fraction.length < baseLength) {
|
||||||
@ -394,14 +413,13 @@ function toDecimals(value, decimals, fixed) {
|
|||||||
|
|
||||||
function getCurrentNetworkName() {
|
function getCurrentNetworkName() {
|
||||||
switch (netId) {
|
switch (netId) {
|
||||||
case 1:
|
case 1:
|
||||||
return ''
|
return ''
|
||||||
case 5:
|
case 5:
|
||||||
return 'goerli.'
|
return 'goerli.'
|
||||||
case 42:
|
case 42:
|
||||||
return 'kovan.'
|
return 'kovan.'
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function gasPrices(value = 80) {
|
function gasPrices(value = 80) {
|
||||||
@ -423,26 +441,26 @@ async function fetchGasPrice() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function calculateFee({ currency, gasPrice, amount, refund, ethPrices, relayerServiceFee, decimals }) {
|
function calculateFee({ currency, gasPrice, amount, refund, ethPrices, relayerServiceFee, decimals }) {
|
||||||
const decimalsPoint = Math.floor(relayerServiceFee) === Number(relayerServiceFee) ?
|
const decimalsPoint =
|
||||||
0 :
|
Math.floor(relayerServiceFee) === Number(relayerServiceFee) ? 0 : relayerServiceFee.toString().split('.')[1].length
|
||||||
relayerServiceFee.toString().split('.')[1].length
|
|
||||||
const roundDecimal = 10 ** decimalsPoint
|
const roundDecimal = 10 ** decimalsPoint
|
||||||
const total = toBN(fromDecimals({ amount, decimals }))
|
const total = toBN(fromDecimals({ amount, decimals }))
|
||||||
const feePercent = total.mul(toBN(relayerServiceFee * roundDecimal)).div(toBN(roundDecimal * 100))
|
const feePercent = total.mul(toBN(relayerServiceFee * roundDecimal)).div(toBN(roundDecimal * 100))
|
||||||
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 'eth': {
|
||||||
desiredFee = expense.add(feePercent)
|
desiredFee = expense.add(feePercent)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
desiredFee = expense.add(toBN(refund))
|
desiredFee = expense
|
||||||
.mul(toBN(10 ** decimals))
|
.add(toBN(refund))
|
||||||
.div(toBN(ethPrices[currency]))
|
.mul(toBN(10 ** decimals))
|
||||||
desiredFee = desiredFee.add(feePercent)
|
.div(toBN(ethPrices[currency]))
|
||||||
break
|
desiredFee = desiredFee.add(feePercent)
|
||||||
}
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return desiredFee
|
return desiredFee
|
||||||
}
|
}
|
||||||
@ -512,7 +530,12 @@ function parseNote(noteString) {
|
|||||||
const deposit = createDeposit({ nullifier, secret })
|
const deposit = createDeposit({ nullifier, secret })
|
||||||
const netId = Number(match.groups.netId)
|
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 }) {
|
async function loadDepositData({ deposit }) {
|
||||||
@ -533,7 +556,13 @@ async function loadDepositData({ deposit }) {
|
|||||||
const isSpent = await tornado.methods.isSpent(deposit.nullifierHex).call()
|
const isSpent = await tornado.methods.isSpent(deposit.nullifierHex).call()
|
||||||
const receipt = await web3.eth.getTransactionReceipt(txHash)
|
const receipt = await web3.eth.getTransactionReceipt(txHash)
|
||||||
|
|
||||||
return { timestamp, txHash, isSpent, from: receipt.from, commitment: deposit.commitmentHex }
|
return {
|
||||||
|
timestamp,
|
||||||
|
txHash,
|
||||||
|
isSpent,
|
||||||
|
from: receipt.from,
|
||||||
|
commitment: deposit.commitmentHex
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('loadDepositData', e)
|
console.error('loadDepositData', e)
|
||||||
}
|
}
|
||||||
@ -569,9 +598,7 @@ async function loadWithdrawalData({ amount, currency, deposit }) {
|
|||||||
|
|
||||||
const fee = withdrawEvent.fee
|
const fee = withdrawEvent.fee
|
||||||
const decimals = config.deployments[`netId${netId}`][currency].decimals
|
const decimals = config.deployments[`netId${netId}`][currency].decimals
|
||||||
const withdrawalAmount = toBN(fromDecimals({ amount, decimals })).sub(
|
const withdrawalAmount = toBN(fromDecimals({ amount, decimals })).sub(toBN(fee))
|
||||||
toBN(fee)
|
|
||||||
)
|
|
||||||
const { timestamp } = await web3.eth.getBlock(withdrawEvent.blockHash)
|
const { timestamp } = await web3.eth.getBlock(withdrawEvent.blockHash)
|
||||||
return {
|
return {
|
||||||
amount: toDecimals(withdrawalAmount, decimals, 9),
|
amount: toDecimals(withdrawalAmount, decimals, 9),
|
||||||
@ -595,7 +622,9 @@ async function init({ rpc, noteNetId, currency = 'dai', amount = '100' }) {
|
|||||||
if (inBrowser) {
|
if (inBrowser) {
|
||||||
// Initialize using injected web3 (Metamask)
|
// Initialize using injected web3 (Metamask)
|
||||||
// To assemble web version run `npm run browserify`
|
// To assemble web version run `npm run browserify`
|
||||||
web3 = new Web3(window.web3.currentProvider, null, { transactionConfirmationBlocks: 1 })
|
web3 = new Web3(window.web3.currentProvider, null, {
|
||||||
|
transactionConfirmationBlocks: 1
|
||||||
|
})
|
||||||
contractJson = await (await fetch('build/contracts/TornadoProxy.abi.json')).json()
|
contractJson = await (await fetch('build/contracts/TornadoProxy.abi.json')).json()
|
||||||
mixerJson = await (await fetch('build/contracts/Mixer.abi.json')).json()
|
mixerJson = await (await fetch('build/contracts/Mixer.abi.json')).json()
|
||||||
circuit = await (await fetch('build/circuits/tornado.json')).json()
|
circuit = await (await fetch('build/circuits/tornado.json')).json()
|
||||||
@ -678,7 +707,9 @@ async function main() {
|
|||||||
.option('-R, --relayer <URL>', 'Withdraw via relayer')
|
.option('-R, --relayer <URL>', 'Withdraw via relayer')
|
||||||
program
|
program
|
||||||
.command('deposit <currency> <amount>')
|
.command('deposit <currency> <amount>')
|
||||||
.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.')
|
.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) => {
|
.action(async (currency, amount) => {
|
||||||
currency = currency.toLowerCase()
|
currency = currency.toLowerCase()
|
||||||
await init({ rpc: program.rpc, currency, amount })
|
await init({ rpc: program.rpc, currency, amount })
|
||||||
@ -686,11 +717,20 @@ async function main() {
|
|||||||
})
|
})
|
||||||
program
|
program
|
||||||
.command('withdraw <note> <recipient> [ETH_purchase]')
|
.command('withdraw <note> <recipient> [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.')
|
.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) => {
|
.action(async (noteString, recipient, refund) => {
|
||||||
const { currency, amount, netId, deposit } = parseNote(noteString)
|
const { currency, amount, netId, deposit } = parseNote(noteString)
|
||||||
await init({ rpc: program.rpc, noteNetId: netId, currency, amount })
|
await init({ rpc: program.rpc, noteNetId: netId, currency, amount })
|
||||||
await withdraw({ deposit, currency, amount, recipient, refund, relayerURL: program.relayer })
|
await withdraw({
|
||||||
|
deposit,
|
||||||
|
currency,
|
||||||
|
amount,
|
||||||
|
recipient,
|
||||||
|
refund,
|
||||||
|
relayerURL: program.relayer
|
||||||
|
})
|
||||||
})
|
})
|
||||||
program
|
program
|
||||||
.command('balance <address> [token_address]')
|
.command('balance <address> [token_address]')
|
||||||
@ -704,7 +744,9 @@ async function main() {
|
|||||||
})
|
})
|
||||||
program
|
program
|
||||||
.command('compliance <note>')
|
.command('compliance <note>')
|
||||||
.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.')
|
.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) => {
|
.action(async (noteString) => {
|
||||||
const { currency, amount, netId, deposit } = parseNote(noteString)
|
const { currency, amount, netId, deposit } = parseNote(noteString)
|
||||||
await init({ rpc: program.rpc, noteNetId: netId, currency, amount })
|
await init({ rpc: program.rpc, noteNetId: netId, currency, amount })
|
||||||
@ -720,7 +762,11 @@ async function main() {
|
|||||||
console.log('The note was not spent')
|
console.log('The note was not spent')
|
||||||
}
|
}
|
||||||
|
|
||||||
const withdrawInfo = await loadWithdrawalData({ amount, currency, deposit })
|
const withdrawInfo = await loadWithdrawalData({
|
||||||
|
amount,
|
||||||
|
currency,
|
||||||
|
deposit
|
||||||
|
})
|
||||||
const withdrawalDate = new Date(withdrawInfo.timestamp * 1000)
|
const withdrawalDate = new Date(withdrawInfo.timestamp * 1000)
|
||||||
console.log('\n=============Withdrawal==============')
|
console.log('\n=============Withdrawal==============')
|
||||||
console.log('Withdrawal :', withdrawInfo.amount, currency)
|
console.log('Withdrawal :', withdrawInfo.amount, currency)
|
||||||
@ -740,15 +786,28 @@ async function main() {
|
|||||||
await init({ rpc: program.rpc, currency, amount })
|
await init({ rpc: program.rpc, currency, amount })
|
||||||
let noteString = await deposit({ currency, amount })
|
let noteString = await deposit({ currency, amount })
|
||||||
let parsedNote = parseNote(noteString)
|
let parsedNote = parseNote(noteString)
|
||||||
await withdraw({ deposit: parsedNote.deposit, currency, amount, recipient: senderAccount, relayerURL: program.relayer })
|
await withdraw({
|
||||||
|
deposit: parsedNote.deposit,
|
||||||
|
currency,
|
||||||
|
amount,
|
||||||
|
recipient: senderAccount,
|
||||||
|
relayerURL: program.relayer
|
||||||
|
})
|
||||||
|
|
||||||
console.log('\nStart performing DAI deposit-withdraw test')
|
console.log('\nStart performing DAI deposit-withdraw test')
|
||||||
currency = 'dai'
|
currency = 'dai'
|
||||||
amount = '100'
|
amount = '100'
|
||||||
await init({ rpc: program.rpc, currency, amount })
|
await init({ rpc: program.rpc, currency, amount })
|
||||||
noteString = await deposit({ currency, amount })
|
noteString = await deposit({ currency, amount })
|
||||||
; (parsedNote = parseNote(noteString))
|
parsedNote = parseNote(noteString)
|
||||||
await withdraw({ deposit: parsedNote.deposit, currency, amount, recipient: senderAccount, refund: '0.02', relayerURL: program.relayer })
|
await withdraw({
|
||||||
|
deposit: parsedNote.deposit,
|
||||||
|
currency,
|
||||||
|
amount,
|
||||||
|
recipient: senderAccount,
|
||||||
|
refund: '0.02',
|
||||||
|
relayerURL: program.relayer
|
||||||
|
})
|
||||||
})
|
})
|
||||||
try {
|
try {
|
||||||
await program.parseAsync(process.argv)
|
await program.parseAsync(process.argv)
|
||||||
|
Loading…
Reference in New Issue
Block a user