Improve coding style for getProof func and save events using promise

This commit is contained in:
Tornado Contrib 2024-05-01 09:47:49 +00:00
parent 94b03abd19
commit e55994068c
Signed by: tornadocontrib
GPG Key ID: 60B4DF1A076C64B1
4 changed files with 140 additions and 111 deletions

110
dist/cli.js vendored

@ -189900,7 +189900,7 @@ class BaseEventsService {
}); });
const lastBlock = newEvents ? newEvents.lastBlock : allEvents[allEvents.length - 1] ? allEvents[allEvents.length - 1].blockNumber : null; const lastBlock = newEvents ? newEvents.lastBlock : allEvents[allEvents.length - 1] ? allEvents[allEvents.length - 1].blockNumber : null;
this.validateEvents({ events: allEvents, lastBlock }); this.validateEvents({ events: allEvents, lastBlock });
yield this.saveEvents({ events: allEvents, lastBlock }); this.saveEventsPromise = this.saveEvents({ events: allEvents, lastBlock });
return { return {
events: allEvents, events: allEvents,
lastBlock lastBlock
@ -189908,7 +189908,7 @@ class BaseEventsService {
}); });
} }
} }
class BaseDepositsService extends BaseEventsService { class BaseTornadoService extends BaseEventsService {
constructor({ constructor({
netId, netId,
provider, provider,
@ -190406,7 +190406,7 @@ var __async$9 = (__this, __arguments, generator) => {
step((generator = generator.apply(__this, __arguments)).next()); step((generator = generator.apply(__this, __arguments)).next());
}); });
}; };
class NodeDepositsService extends BaseDepositsService { class NodeTornadoService extends BaseTornadoService {
constructor({ constructor({
netId, netId,
provider, provider,
@ -193369,21 +193369,19 @@ function getProgramRelayer(_0) {
const relayerStatus2 = yield relayerClient.askRelayerStatus({ const relayerStatus2 = yield relayerClient.askRelayerStatus({
hostname: new URL(relayer).hostname hostname: new URL(relayer).hostname
}); });
if (relayerStatus2) { relayerClient.selectedRelayer = {
relayerClient.selectedRelayer = { netId: relayerStatus2.netId,
netId: relayerStatus2.netId, url: relayerStatus2.url,
url: relayerStatus2.url, hostname: new URL(relayerStatus2.url).hostname,
hostname: new URL(relayerStatus2.url).hostname, rewardAccount: address_getAddress(relayerStatus2.rewardAccount),
rewardAccount: address_getAddress(relayerStatus2.rewardAccount), instances: getSupportedInstances(relayerStatus2.instances),
instances: getSupportedInstances(relayerStatus2.instances), gasPrice: (_a = relayerStatus2.gasPrices) == null ? void 0 : _a.fast,
gasPrice: (_a = relayerStatus2.gasPrices) == null ? void 0 : _a.fast, ethPrices: relayerStatus2.ethPrices,
ethPrices: relayerStatus2.ethPrices, currentQueue: relayerStatus2.currentQueue,
currentQueue: relayerStatus2.currentQueue, tornadoServiceFee: relayerStatus2.tornadoServiceFee
tornadoServiceFee: relayerStatus2.tornadoServiceFee };
};
}
return { return {
validRelayers: relayerClient.selectedRelayer ? [relayerClient.selectedRelayer] : [], validRelayers: [relayerClient.selectedRelayer],
invalidRelayers: [], invalidRelayers: [],
relayerClient relayerClient
}; };
@ -193405,6 +193403,7 @@ function getProgramRelayer(_0) {
yield registryService.fetchRelayers(), yield registryService.fetchRelayers(),
subdomains subdomains
); );
yield registryService.saveEventsPromise;
const relayerStatus = relayerClient.pickWeightedRandomRelayer(validRelayers); const relayerStatus = relayerClient.pickWeightedRandomRelayer(validRelayers);
if (relayerStatus) { if (relayerStatus) {
relayerClient.selectedRelayer = relayerStatus; relayerClient.selectedRelayer = relayerStatus;
@ -193743,7 +193742,7 @@ function tornadoProgram() {
Multicall, Multicall,
offchainOracleContract ? OffchainOracle__factory.connect(offchainOracleContract, provider) : void 0 offchainOracleContract ? OffchainOracle__factory.connect(offchainOracleContract, provider) : void 0
); );
const depositsServiceConstructor = { const TornadoServiceConstructor = {
netId, netId,
provider, provider,
graphApi, graphApi,
@ -193756,10 +193755,10 @@ function tornadoProgram() {
cacheDirectory: EVENTS_DIR, cacheDirectory: EVENTS_DIR,
userDirectory: SAVED_DIR userDirectory: SAVED_DIR
}; };
const depositsService = new NodeDepositsService(program_spreadProps(program_spreadValues({}, depositsServiceConstructor), { const depositsService = new NodeTornadoService(program_spreadProps(program_spreadValues({}, TornadoServiceConstructor), {
type: "Deposit" type: "Deposit"
})); }));
const withdrawalsService = new NodeDepositsService(program_spreadProps(program_spreadValues({}, depositsServiceConstructor), { const withdrawalsService = new NodeTornadoService(program_spreadProps(program_spreadValues({}, TornadoServiceConstructor), {
type: "Withdrawal" type: "Withdrawal"
})); }));
const merkleTreeService = new MerkleTreeService({ const merkleTreeService = new MerkleTreeService({
@ -193783,6 +193782,7 @@ function tornadoProgram() {
depositTreePromise = depositTreeInitiator; depositTreePromise = depositTreeInitiator;
} }
const withdrawalEvents = (yield withdrawalsService.updateEvents()).events; const withdrawalEvents = (yield withdrawalsService.updateEvents()).events;
yield Promise.all([depositsService.saveEventsPromise, withdrawalsService.saveEventsPromise]);
const depositEvent = depositEvents.find(({ commitment }) => commitment === commitmentHex); const depositEvent = depositEvents.find(({ commitment }) => commitment === commitmentHex);
const withdrawalEvent = withdrawalEvents.find(({ nullifierHash }) => nullifierHash === nullifierHex); const withdrawalEvent = withdrawalEvents.find(({ nullifierHash }) => nullifierHash === nullifierHex);
if (!depositEvent) { if (!depositEvent) {
@ -193834,52 +193834,54 @@ function tornadoProgram() {
!isEth ? tokenPriceOracle.fetchPrices([{ tokenAddress, decimals }]).then((p) => p[0]) : BigInt(0), !isEth ? tokenPriceOracle.fetchPrices([{ tokenAddress, decimals }]).then((p) => p[0]) : BigInt(0),
provider.getFeeData() provider.getFeeData()
]); ]);
const { pathElements, pathIndices } = tree.path(depositEvent.leafIndex);
if (!walletWithdrawal && !(relayerClient == null ? void 0 : relayerClient.selectedRelayer)) { if (!walletWithdrawal && !(relayerClient == null ? void 0 : relayerClient.selectedRelayer)) {
throw new Error( throw new Error(
"No valid relayer found for the network, you can either try again, or find any relayers using the relayers command and set with --relayer option" "No valid relayer found for the network, you can either try again, or find any relayers using the relayers command and set with --relayer option"
); );
} }
const { url, rewardAccount, tornadoServiceFee } = (relayerClient == null ? void 0 : relayerClient.selectedRelayer) || {};
let gasPrice = feeData.maxFeePerGas ? feeData.maxFeePerGas + (feeData.maxPriorityFeePerGas || BigInt(0)) : feeData.gasPrice; let gasPrice = feeData.maxFeePerGas ? feeData.maxFeePerGas + (feeData.maxPriorityFeePerGas || BigInt(0)) : feeData.gasPrice;
if (netId === 56 && gasPrice < parseUnits("3.3", "gwei")) { if (netId === NetId.BSC && gasPrice < parseUnits("3.3", "gwei")) {
gasPrice = parseUnits("3.3", "gwei"); gasPrice = parseUnits("3.3", "gwei");
} }
const defaultGasLimit = instanceGasLimit ? BigInt(instanceGasLimit) : BigInt(DEFAULT_GAS_LIMIT); const defaultGasLimit = instanceGasLimit ? BigInt(instanceGasLimit) : BigInt(DEFAULT_GAS_LIMIT);
let gasLimit = defaultGasLimit; let gasLimit = defaultGasLimit;
const refundGasLimit = isFirstAmount && tokenGasLimit ? BigInt(tokenGasLimit) : void 0; const refundGasLimit = isFirstAmount && tokenGasLimit ? BigInt(tokenGasLimit) : void 0;
const ethRefund = ethPurchase ? parseEther(`${ethPurchase}`) : !isEth ? tornadoFeeOracle.defaultEthRefund(gasPrice, refundGasLimit) : BigInt(0);
if (isEth && ethRefund) {
throw new Error("Can not purchase native assets on native asset withdrawal");
}
function getProof() { function getProof() {
return program_async(this, null, function* () { return program_async(this, null, function* () {
let relayerFee2 = BigInt(0); let relayer2 = ZeroAddress;
let fee2 = BigInt(0);
let refund2 = BigInt(0);
const { url: url2, rewardAccount, tornadoServiceFee } = (relayerClient == null ? void 0 : relayerClient.selectedRelayer) || {};
if (!walletWithdrawal) { if (!walletWithdrawal) {
relayerFee2 = tornadoFeeOracle.calculateRelayerFee({ fee2 = tornadoFeeOracle.calculateRelayerFee({
gasPrice, gasPrice,
gasLimit, gasLimit,
l1Fee, l1Fee,
denomination, denomination,
ethRefund, ethRefund: refund2,
tokenPriceInWei, tokenPriceInWei,
tokenDecimals: decimals, tokenDecimals: decimals,
relayerFeePercent: tornadoServiceFee, relayerFeePercent: tornadoServiceFee,
isEth isEth
}); });
if (relayerFee2 > denomination) { relayer2 = rewardAccount;
const errMsg = `Relayer fee ${formatUnits(relayerFee2, decimals)} ${currency.toUpperCase()} exceeds the deposit amount ${amount} ${currency.toUpperCase()}.`; if (fee2 > denomination) {
const errMsg = `Relayer fee ${formatUnits(fee2, decimals)} ${currency.toUpperCase()} exceeds the deposit amount ${amount} ${currency.toUpperCase()}.`;
throw new Error(errMsg); throw new Error(errMsg);
} }
} }
const { pathElements, pathIndices } = tree.path(depositEvent.leafIndex); if (!isEth) {
refund2 = ethPurchase ? parseEther(`${ethPurchase}`) : tornadoFeeOracle.defaultEthRefund(gasPrice, refundGasLimit);
}
const { proof: proof2, args: args2 } = yield calculateSnarkProof( const { proof: proof2, args: args2 } = yield calculateSnarkProof(
{ {
root: tree.root, root: tree.root,
nullifierHex, nullifierHex,
recipient, recipient,
relayer: !walletWithdrawal ? rewardAccount : ZeroAddress, relayer: !walletWithdrawal ? rewardAccount : ZeroAddress,
fee: relayerFee2, fee: fee2,
refund: ethRefund, refund: refund2,
nullifier, nullifier,
secret, secret,
pathElements, pathElements,
@ -193889,20 +193891,24 @@ function tornadoProgram() {
provingKey provingKey
); );
return { return {
relayerFee: relayerFee2, url: url2,
relayer: relayer2,
fee: fee2,
feePercent: tornadoServiceFee,
refund: refund2,
proof: proof2, proof: proof2,
args: args2 args: args2
}; };
}); });
} }
let { relayerFee, proof, args } = yield getProof(); let { url, relayer, fee, feePercent, refund, proof, args } = yield getProof();
const withdrawOverrides = { const withdrawOverrides = {
from: !walletWithdrawal ? rewardAccount : signer == null ? void 0 : signer.address, from: !walletWithdrawal ? relayer : signer == null ? void 0 : signer.address,
value: args[5] || 0 value: args[5] || 0
}; };
gasLimit = yield TornadoProxy.withdraw.estimateGas(instanceAddress, proof, ...args, withdrawOverrides); gasLimit = yield TornadoProxy.withdraw.estimateGas(instanceAddress, proof, ...args, withdrawOverrides);
if (gasLimit > defaultGasLimit) { if (gasLimit > defaultGasLimit) {
({ relayerFee, proof, args } = yield getProof()); ({ url, relayer, fee, feePercent, refund, proof, args } = yield getProof());
gasLimit = yield TornadoProxy.withdraw.estimateGas(instanceAddress, proof, ...args, withdrawOverrides); gasLimit = yield TornadoProxy.withdraw.estimateGas(instanceAddress, proof, ...args, withdrawOverrides);
} }
const withdrawTable = new (cli_table3_default())(); const withdrawTable = new (cli_table3_default())();
@ -193914,14 +193920,14 @@ function tornadoProgram() {
["Relayer", `${url}`], ["Relayer", `${url}`],
[ [
"Relayer Fee", "Relayer Fee",
`${formatUnits(relayerFee, decimals)} ${currency.toUpperCase()} (${(Number(relayerFee) / Number(denomination) * 100).toFixed(5)}%)` `${formatUnits(fee, decimals)} ${currency.toUpperCase()} (${(Number(fee) / Number(denomination) * 100).toFixed(5)}%)`
], ],
["Relayer Fee Percent", `${tornadoServiceFee}%`], ["Relayer Fee Percent", `${feePercent}%`],
[ [
"Amount to receive", "Amount to receive",
`${Number(formatUnits(denomination - relayerFee, decimals)).toFixed(5)} ${currency.toUpperCase()}` `${Number(formatUnits(denomination - fee, decimals)).toFixed(5)} ${currency.toUpperCase()}`
], ],
[`${nativeCurrency.toUpperCase()} purchase`, `${formatEther(ethRefund)} ${nativeCurrency.toUpperCase()}`], [`${nativeCurrency.toUpperCase()} purchase`, `${formatEther(refund)} ${nativeCurrency.toUpperCase()}`],
["To", recipient], ["To", recipient],
["Nullifier", nullifierHex] ["Nullifier", nullifierHex]
); );
@ -193981,7 +193987,7 @@ function tornadoProgram() {
const provider = getProgramProvider(netId, rpc, config, program_spreadValues({}, fetchDataOptions2)); const provider = getProgramProvider(netId, rpc, config, program_spreadValues({}, fetchDataOptions2));
const graphApi = getProgramGraphAPI(options, config); const graphApi = getProgramGraphAPI(options, config);
const Tornado = Tornado__factory.connect(instanceAddress, provider); const Tornado = Tornado__factory.connect(instanceAddress, provider);
const depositsServiceConstructor = { const TornadoServiceConstructor = {
netId, netId,
provider, provider,
graphApi, graphApi,
@ -193994,10 +194000,10 @@ function tornadoProgram() {
cacheDirectory: EVENTS_DIR, cacheDirectory: EVENTS_DIR,
userDirectory: SAVED_DIR userDirectory: SAVED_DIR
}; };
const depositsService = new NodeDepositsService(program_spreadProps(program_spreadValues({}, depositsServiceConstructor), { const depositsService = new NodeTornadoService(program_spreadProps(program_spreadValues({}, TornadoServiceConstructor), {
type: "Deposit" type: "Deposit"
})); }));
const withdrawalsService = new NodeDepositsService(program_spreadProps(program_spreadValues({}, depositsServiceConstructor), { const withdrawalsService = new NodeTornadoService(program_spreadProps(program_spreadValues({}, TornadoServiceConstructor), {
type: "Withdrawal" type: "Withdrawal"
})); }));
const merkleTreeService = new MerkleTreeService({ const merkleTreeService = new MerkleTreeService({
@ -194055,6 +194061,7 @@ function tornadoProgram() {
); );
} }
console.log("\n\n" + complianceTable.toString() + "\n"); console.log("\n\n" + complianceTable.toString() + "\n");
yield Promise.all([depositsService.saveEventsPromise, withdrawalsService.saveEventsPromise]);
external_process_default().exit(0); external_process_default().exit(0);
})); }));
program.command("updateEvents").description("Sync the local cache file of tornado cash events.\n\n").argument("[netId]", "Network Chain ID to connect with (see https://chainlist.org for examples)", parseNumber).argument("[currency]", "Currency to sync events").action( program.command("updateEvents").description("Sync the local cache file of tornado cash events.\n\n").argument("[netId]", "Network Chain ID to connect with (see https://chainlist.org for examples)", parseNumber).argument("[currency]", "Currency to sync events").action(
@ -194092,6 +194099,7 @@ function tornadoProgram() {
userDirectory: SAVED_DIR userDirectory: SAVED_DIR
}); });
yield governanceService.updateEvents(); yield governanceService.updateEvents();
yield governanceService.saveEventsPromise;
} }
if (registryContract) { if (registryContract) {
const registryService = new NodeRegistryService({ const registryService = new NodeRegistryService({
@ -194106,6 +194114,7 @@ function tornadoProgram() {
userDirectory: SAVED_DIR userDirectory: SAVED_DIR
}); });
yield registryService.updateEvents(); yield registryService.updateEvents();
yield registryService.saveEventsPromise;
} }
const echoService = new NodeEchoService({ const echoService = new NodeEchoService({
netId, netId,
@ -194119,6 +194128,7 @@ function tornadoProgram() {
userDirectory: SAVED_DIR userDirectory: SAVED_DIR
}); });
yield echoService.updateEvents(); yield echoService.updateEvents();
yield echoService.saveEventsPromise;
const encryptedNotesService = new NodeEncryptedNotesService({ const encryptedNotesService = new NodeEncryptedNotesService({
netId, netId,
provider, provider,
@ -194131,6 +194141,7 @@ function tornadoProgram() {
userDirectory: SAVED_DIR userDirectory: SAVED_DIR
}); });
yield encryptedNotesService.updateEvents(); yield encryptedNotesService.updateEvents();
yield encryptedNotesService.saveEventsPromise;
const currencies = currencyOpts ? [currencyOpts.toLowerCase()] : Object.keys(tokens); const currencies = currencyOpts ? [currencyOpts.toLowerCase()] : Object.keys(tokens);
for (const currency of currencies) { for (const currency of currencies) {
const currencyConfig = tokens[currency]; const currencyConfig = tokens[currency];
@ -194138,7 +194149,7 @@ function tornadoProgram() {
for (const amount of amounts) { for (const amount of amounts) {
const instanceAddress = currencyConfig.instanceAddress[amount]; const instanceAddress = currencyConfig.instanceAddress[amount];
const Tornado = Tornado__factory.connect(instanceAddress, provider); const Tornado = Tornado__factory.connect(instanceAddress, provider);
const depositsServiceConstructor = { const TornadoServiceConstructor = {
netId, netId,
provider, provider,
graphApi, graphApi,
@ -194151,10 +194162,10 @@ function tornadoProgram() {
cacheDirectory: EVENTS_DIR, cacheDirectory: EVENTS_DIR,
userDirectory: SAVED_DIR userDirectory: SAVED_DIR
}; };
const depositsService = new NodeDepositsService(program_spreadProps(program_spreadValues({}, depositsServiceConstructor), { const depositsService = new NodeTornadoService(program_spreadProps(program_spreadValues({}, TornadoServiceConstructor), {
type: "Deposit" type: "Deposit"
})); }));
const withdrawalsService = new NodeDepositsService(program_spreadProps(program_spreadValues({}, depositsServiceConstructor), { const withdrawalsService = new NodeTornadoService(program_spreadProps(program_spreadValues({}, TornadoServiceConstructor), {
type: "Withdrawal" type: "Withdrawal"
})); }));
const merkleTreeService = new MerkleTreeService({ const merkleTreeService = new MerkleTreeService({
@ -194184,6 +194195,7 @@ function tornadoProgram() {
if (nativeCurrency === currency) { if (nativeCurrency === currency) {
yield treeCache.createTree(depositEvents, tree); yield treeCache.createTree(depositEvents, tree);
} }
yield Promise.all([depositsService.saveEventsPromise, withdrawalsService.saveEventsPromise]);
} }
} }
} }
@ -194280,6 +194292,7 @@ function tornadoProgram() {
}); });
console.log("Getting historic note accounts would take a while\n"); console.log("Getting historic note accounts would take a while\n");
const echoEvents = (yield echoService.updateEvents()).events; const echoEvents = (yield echoService.updateEvents()).events;
yield echoService.saveEventsPromise;
const userEvents = echoEvents.filter(({ address }) => address === signer.address); const userEvents = echoEvents.filter(({ address }) => address === signer.address);
const existingAccounts = newAccount.decryptAccountsWithWallet(signer, userEvents); const existingAccounts = newAccount.decryptAccountsWithWallet(signer, userEvents);
const accountsTable = new (cli_table3_default())(); const accountsTable = new (cli_table3_default())();
@ -194359,6 +194372,7 @@ function tornadoProgram() {
userDirectory: SAVED_DIR userDirectory: SAVED_DIR
}); });
const encryptedNoteEvents = (yield encryptedNotesService.updateEvents()).events; const encryptedNoteEvents = (yield encryptedNotesService.updateEvents()).events;
yield encryptedNotesService.saveEventsPromise;
const accountsTable = new (cli_table3_default())(); const accountsTable = new (cli_table3_default())();
accountsTable.push( accountsTable.push(
[{ colSpan: 2, content: `Note Accounts (${netId})`, hAlign: "center" }], [{ colSpan: 2, content: `Note Accounts (${netId})`, hAlign: "center" }],

@ -53,7 +53,7 @@
"@colors/colors": "1.5.0", "@colors/colors": "1.5.0",
"@metamask/eth-sig-util": "^7.0.1", "@metamask/eth-sig-util": "^7.0.1",
"@tornado/contracts": "1.0.0", "@tornado/contracts": "1.0.0",
"@tornado/core": "git+https://git.tornado.ws/tornadocontrib/tornado-core.git#e7412f3d986f6a89382f444b6fa26e770226643f", "@tornado/core": "git+https://git.tornado.ws/tornadocontrib/tornado-core.git#4623e386a158a01438ac2d7a8b7107cffd10242e",
"@tornado/fixed-merkle-tree": "0.7.3", "@tornado/fixed-merkle-tree": "0.7.3",
"@tornado/snarkjs": "0.1.20", "@tornado/snarkjs": "0.1.20",
"@tornado/websnark": "0.0.4", "@tornado/websnark": "0.0.4",

@ -50,7 +50,7 @@ import {
TornadoVoidSigner, TornadoVoidSigner,
tokenBalances, tokenBalances,
Deposit, Deposit,
NodeDepositsService, NodeTornadoService,
DepositsEvents, DepositsEvents,
WithdrawalsEvents, WithdrawalsEvents,
Relayer, Relayer,
@ -331,22 +331,20 @@ export async function getProgramRelayer({
hostname: new URL(relayer).hostname, hostname: new URL(relayer).hostname,
}); });
if (relayerStatus) { relayerClient.selectedRelayer = {
relayerClient.selectedRelayer = { netId: relayerStatus.netId,
netId: relayerStatus.netId, url: relayerStatus.url,
url: relayerStatus.url, hostname: new URL(relayerStatus.url).hostname,
hostname: new URL(relayerStatus.url).hostname, rewardAccount: getAddress(relayerStatus.rewardAccount),
rewardAccount: getAddress(relayerStatus.rewardAccount), instances: getSupportedInstances(relayerStatus.instances),
instances: getSupportedInstances(relayerStatus.instances), gasPrice: relayerStatus.gasPrices?.fast,
gasPrice: relayerStatus.gasPrices?.fast, ethPrices: relayerStatus.ethPrices,
ethPrices: relayerStatus.ethPrices, currentQueue: relayerStatus.currentQueue,
currentQueue: relayerStatus.currentQueue, tornadoServiceFee: relayerStatus.tornadoServiceFee,
tornadoServiceFee: relayerStatus.tornadoServiceFee, };
};
}
return { return {
validRelayers: relayerClient.selectedRelayer ? [relayerClient.selectedRelayer] : [], validRelayers: [relayerClient.selectedRelayer],
invalidRelayers: [], invalidRelayers: [],
relayerClient, relayerClient,
}; };
@ -372,6 +370,7 @@ export async function getProgramRelayer({
await registryService.fetchRelayers(), await registryService.fetchRelayers(),
subdomains, subdomains,
); );
await registryService.saveEventsPromise;
const relayerStatus = relayerClient.pickWeightedRandomRelayer(validRelayers); const relayerStatus = relayerClient.pickWeightedRandomRelayer(validRelayers);
@ -847,7 +846,7 @@ export function tornadoProgram() {
offchainOracleContract ? OffchainOracle__factory.connect(offchainOracleContract, provider) : undefined, offchainOracleContract ? OffchainOracle__factory.connect(offchainOracleContract, provider) : undefined,
); );
const depositsServiceConstructor = { const TornadoServiceConstructor = {
netId, netId,
provider, provider,
graphApi, graphApi,
@ -861,13 +860,13 @@ export function tornadoProgram() {
userDirectory: SAVED_DIR, userDirectory: SAVED_DIR,
}; };
const depositsService = new NodeDepositsService({ const depositsService = new NodeTornadoService({
...depositsServiceConstructor, ...TornadoServiceConstructor,
type: 'Deposit', type: 'Deposit',
}); });
const withdrawalsService = new NodeDepositsService({ const withdrawalsService = new NodeTornadoService({
...depositsServiceConstructor, ...TornadoServiceConstructor,
type: 'Withdrawal', type: 'Withdrawal',
}); });
@ -899,6 +898,8 @@ export function tornadoProgram() {
const withdrawalEvents = (await withdrawalsService.updateEvents()).events as WithdrawalsEvents[]; const withdrawalEvents = (await withdrawalsService.updateEvents()).events as WithdrawalsEvents[];
await Promise.all([depositsService.saveEventsPromise, withdrawalsService.saveEventsPromise]);
const depositEvent = depositEvents.find(({ commitment }) => commitment === commitmentHex); const depositEvent = depositEvents.find(({ commitment }) => commitment === commitmentHex);
const withdrawalEvent = withdrawalEvents.find(({ nullifierHash }) => nullifierHash === nullifierHex); const withdrawalEvent = withdrawalEvents.find(({ nullifierHash }) => nullifierHash === nullifierHex);
@ -965,19 +966,19 @@ export function tornadoProgram() {
provider.getFeeData(), provider.getFeeData(),
]); ]);
const { pathElements, pathIndices } = tree.path((depositEvent as DepositsEvents).leafIndex);
if (!walletWithdrawal && !relayerClient?.selectedRelayer) { if (!walletWithdrawal && !relayerClient?.selectedRelayer) {
throw new Error( throw new Error(
'No valid relayer found for the network, you can either try again, or find any relayers using the relayers command and set with --relayer option', 'No valid relayer found for the network, you can either try again, or find any relayers using the relayers command and set with --relayer option',
); );
} }
const { url, rewardAccount, tornadoServiceFee } = relayerClient?.selectedRelayer || {};
let gasPrice: bigint = feeData.maxFeePerGas let gasPrice: bigint = feeData.maxFeePerGas
? feeData.maxFeePerGas + (feeData.maxPriorityFeePerGas || BigInt(0)) ? feeData.maxFeePerGas + (feeData.maxPriorityFeePerGas || BigInt(0))
: (feeData.gasPrice as bigint); : (feeData.gasPrice as bigint);
if (netId === 56 && gasPrice < parseUnits('3.3', 'gwei')) { if (netId === NetId.BSC && gasPrice < parseUnits('3.3', 'gwei')) {
gasPrice = parseUnits('3.3', 'gwei'); gasPrice = parseUnits('3.3', 'gwei');
} }
@ -988,41 +989,41 @@ export function tornadoProgram() {
// If the denomination is small only refund small amount otherwise use the default value // If the denomination is small only refund small amount otherwise use the default value
const refundGasLimit = isFirstAmount && tokenGasLimit ? BigInt(tokenGasLimit) : undefined; const refundGasLimit = isFirstAmount && tokenGasLimit ? BigInt(tokenGasLimit) : undefined;
const ethRefund = ethPurchase
? parseEther(`${ethPurchase}`)
: !isEth
? tornadoFeeOracle.defaultEthRefund(gasPrice, refundGasLimit)
: BigInt(0);
if (isEth && ethRefund) {
throw new Error('Can not purchase native assets on native asset withdrawal');
}
async function getProof() { async function getProof() {
let relayerFee = BigInt(0); let relayer = ZeroAddress;
let fee = BigInt(0);
let refund = BigInt(0);
const { url, rewardAccount, tornadoServiceFee } = relayerClient?.selectedRelayer || {};
if (!walletWithdrawal) { if (!walletWithdrawal) {
relayerFee = tornadoFeeOracle.calculateRelayerFee({ fee = tornadoFeeOracle.calculateRelayerFee({
gasPrice, gasPrice,
gasLimit, gasLimit,
l1Fee, l1Fee,
denomination, denomination,
ethRefund, ethRefund: refund,
tokenPriceInWei, tokenPriceInWei,
tokenDecimals: decimals, tokenDecimals: decimals,
relayerFeePercent: tornadoServiceFee, relayerFeePercent: tornadoServiceFee,
isEth, isEth,
}); });
if (relayerFee > denomination) { relayer = rewardAccount as string;
if (fee > denomination) {
const errMsg = const errMsg =
`Relayer fee ${formatUnits(relayerFee, decimals)} ${currency.toUpperCase()} ` + `Relayer fee ${formatUnits(fee, decimals)} ${currency.toUpperCase()} ` +
`exceeds the deposit amount ${amount} ${currency.toUpperCase()}.`; `exceeds the deposit amount ${amount} ${currency.toUpperCase()}.`;
throw new Error(errMsg); throw new Error(errMsg);
} }
} }
const { pathElements, pathIndices } = tree.path((depositEvent as DepositsEvents).leafIndex); if (!isEth) {
refund = ethPurchase
? parseEther(`${ethPurchase}`)
: tornadoFeeOracle.defaultEthRefund(gasPrice, refundGasLimit);
}
const { proof, args } = await calculateSnarkProof( const { proof, args } = await calculateSnarkProof(
{ {
@ -1030,8 +1031,8 @@ export function tornadoProgram() {
nullifierHex, nullifierHex,
recipient, recipient,
relayer: !walletWithdrawal ? (rewardAccount as string) : ZeroAddress, relayer: !walletWithdrawal ? (rewardAccount as string) : ZeroAddress,
fee: relayerFee, fee,
refund: ethRefund, refund,
nullifier, nullifier,
secret, secret,
pathElements, pathElements,
@ -1042,23 +1043,27 @@ export function tornadoProgram() {
); );
return { return {
relayerFee, url,
relayer,
fee,
feePercent: tornadoServiceFee,
refund,
proof, proof,
args, args,
}; };
} }
let { relayerFee, proof, args } = await getProof(); let { url, relayer, fee, feePercent, refund, proof, args } = await getProof();
const withdrawOverrides = { const withdrawOverrides = {
from: !walletWithdrawal ? (rewardAccount as string) : (signer?.address as string), from: !walletWithdrawal ? relayer : (signer?.address as string),
value: args[5] || 0, value: args[5] || 0,
}; };
gasLimit = await TornadoProxy.withdraw.estimateGas(instanceAddress, proof, ...args, withdrawOverrides); gasLimit = await TornadoProxy.withdraw.estimateGas(instanceAddress, proof, ...args, withdrawOverrides);
if (gasLimit > defaultGasLimit) { if (gasLimit > defaultGasLimit) {
({ relayerFee, proof, args } = await getProof()); ({ url, relayer, fee, feePercent, refund, proof, args } = await getProof());
gasLimit = await TornadoProxy.withdraw.estimateGas(instanceAddress, proof, ...args, withdrawOverrides); gasLimit = await TornadoProxy.withdraw.estimateGas(instanceAddress, proof, ...args, withdrawOverrides);
} }
@ -1073,15 +1078,15 @@ export function tornadoProgram() {
['Relayer', `${url}`], ['Relayer', `${url}`],
[ [
'Relayer Fee', 'Relayer Fee',
`${formatUnits(relayerFee, decimals)} ${currency.toUpperCase()} ` + `${formatUnits(fee, decimals)} ${currency.toUpperCase()} ` +
`(${((Number(relayerFee) / Number(denomination)) * 100).toFixed(5)}%)`, `(${((Number(fee) / Number(denomination)) * 100).toFixed(5)}%)`,
], ],
['Relayer Fee Percent', `${tornadoServiceFee}%`], ['Relayer Fee Percent', `${feePercent}%`],
[ [
'Amount to receive', 'Amount to receive',
`${Number(formatUnits(denomination - relayerFee, decimals)).toFixed(5)} ${currency.toUpperCase()}`, `${Number(formatUnits(denomination - fee, decimals)).toFixed(5)} ${currency.toUpperCase()}`,
], ],
[`${nativeCurrency.toUpperCase()} purchase`, `${formatEther(ethRefund)} ${nativeCurrency.toUpperCase()}`], [`${nativeCurrency.toUpperCase()} purchase`, `${formatEther(refund)} ${nativeCurrency.toUpperCase()}`],
['To', recipient], ['To', recipient],
['Nullifier', nullifierHex], ['Nullifier', nullifierHex],
); );
@ -1174,7 +1179,7 @@ export function tornadoProgram() {
const Tornado = Tornado__factory.connect(instanceAddress, provider); const Tornado = Tornado__factory.connect(instanceAddress, provider);
const depositsServiceConstructor = { const TornadoServiceConstructor = {
netId, netId,
provider, provider,
graphApi, graphApi,
@ -1188,13 +1193,13 @@ export function tornadoProgram() {
userDirectory: SAVED_DIR, userDirectory: SAVED_DIR,
}; };
const depositsService = new NodeDepositsService({ const depositsService = new NodeTornadoService({
...depositsServiceConstructor, ...TornadoServiceConstructor,
type: 'Deposit', type: 'Deposit',
}); });
const withdrawalsService = new NodeDepositsService({ const withdrawalsService = new NodeTornadoService({
...depositsServiceConstructor, ...TornadoServiceConstructor,
type: 'Withdrawal', type: 'Withdrawal',
}); });
@ -1266,6 +1271,8 @@ export function tornadoProgram() {
console.log('\n\n' + complianceTable.toString() + '\n'); console.log('\n\n' + complianceTable.toString() + '\n');
await Promise.all([depositsService.saveEventsPromise, withdrawalsService.saveEventsPromise]);
process.exit(0); process.exit(0);
}); });
@ -1316,6 +1323,7 @@ export function tornadoProgram() {
}); });
await governanceService.updateEvents(); await governanceService.updateEvents();
await governanceService.saveEventsPromise;
} }
if (registryContract) { if (registryContract) {
@ -1332,6 +1340,7 @@ export function tornadoProgram() {
}); });
await registryService.updateEvents(); await registryService.updateEvents();
await registryService.saveEventsPromise;
} }
const echoService = new NodeEchoService({ const echoService = new NodeEchoService({
@ -1347,6 +1356,7 @@ export function tornadoProgram() {
}); });
await echoService.updateEvents(); await echoService.updateEvents();
await echoService.saveEventsPromise;
const encryptedNotesService = new NodeEncryptedNotesService({ const encryptedNotesService = new NodeEncryptedNotesService({
netId, netId,
@ -1361,6 +1371,7 @@ export function tornadoProgram() {
}); });
await encryptedNotesService.updateEvents(); await encryptedNotesService.updateEvents();
await encryptedNotesService.saveEventsPromise;
const currencies = currencyOpts ? [currencyOpts.toLowerCase()] : Object.keys(tokens); const currencies = currencyOpts ? [currencyOpts.toLowerCase()] : Object.keys(tokens);
@ -1374,7 +1385,7 @@ export function tornadoProgram() {
const instanceAddress = currencyConfig.instanceAddress[amount]; const instanceAddress = currencyConfig.instanceAddress[amount];
const Tornado = Tornado__factory.connect(instanceAddress, provider); const Tornado = Tornado__factory.connect(instanceAddress, provider);
const depositsServiceConstructor = { const TornadoServiceConstructor = {
netId, netId,
provider, provider,
graphApi, graphApi,
@ -1388,13 +1399,13 @@ export function tornadoProgram() {
userDirectory: SAVED_DIR, userDirectory: SAVED_DIR,
}; };
const depositsService = new NodeDepositsService({ const depositsService = new NodeTornadoService({
...depositsServiceConstructor, ...TornadoServiceConstructor,
type: 'Deposit', type: 'Deposit',
}); });
const withdrawalsService = new NodeDepositsService({ const withdrawalsService = new NodeTornadoService({
...depositsServiceConstructor, ...TornadoServiceConstructor,
type: 'Withdrawal', type: 'Withdrawal',
}); });
@ -1431,6 +1442,8 @@ export function tornadoProgram() {
if (nativeCurrency === currency) { if (nativeCurrency === currency) {
await treeCache.createTree(depositEvents, tree); await treeCache.createTree(depositEvents, tree);
} }
await Promise.all([depositsService.saveEventsPromise, withdrawalsService.saveEventsPromise]);
} }
} }
} }
@ -1565,6 +1578,7 @@ export function tornadoProgram() {
console.log('Getting historic note accounts would take a while\n'); console.log('Getting historic note accounts would take a while\n');
const echoEvents = (await echoService.updateEvents()).events; const echoEvents = (await echoService.updateEvents()).events;
await echoService.saveEventsPromise;
const userEvents = echoEvents.filter(({ address }) => address === signer.address); const userEvents = echoEvents.filter(({ address }) => address === signer.address);
@ -1675,6 +1689,7 @@ export function tornadoProgram() {
}); });
const encryptedNoteEvents = (await encryptedNotesService.updateEvents()).events; const encryptedNoteEvents = (await encryptedNotesService.updateEvents()).events;
await encryptedNotesService.saveEventsPromise;
const accountsTable = new Table(); const accountsTable = new Table();

@ -771,9 +771,9 @@
"@openzeppelin/contracts-v3" "npm:@openzeppelin/contracts@3.2.0-rc.0" "@openzeppelin/contracts-v3" "npm:@openzeppelin/contracts@3.2.0-rc.0"
ethers "^6.4.0" ethers "^6.4.0"
"@tornado/core@git+https://git.tornado.ws/tornadocontrib/tornado-core.git#e7412f3d986f6a89382f444b6fa26e770226643f": "@tornado/core@git+https://git.tornado.ws/tornadocontrib/tornado-core.git#4623e386a158a01438ac2d7a8b7107cffd10242e":
version "1.0.0" version "1.0.0"
resolved "git+https://git.tornado.ws/tornadocontrib/tornado-core.git#e7412f3d986f6a89382f444b6fa26e770226643f" resolved "git+https://git.tornado.ws/tornadocontrib/tornado-core.git#4623e386a158a01438ac2d7a8b7107cffd10242e"
dependencies: dependencies:
"@metamask/eth-sig-util" "^7.0.1" "@metamask/eth-sig-util" "^7.0.1"
"@tornado/contracts" "^1.0.0" "@tornado/contracts" "^1.0.0"