Tornado CLI 1.0.4-alpha

* removed broken rpc endpoints

* use local cache for relayers

* updated dependencies

* use codeberg.org to fetch dependencies
This commit is contained in:
Tornado Contrib 2024-09-21 04:04:45 +00:00
parent 44f50a51d3
commit 3e1e6b43af
Signed by: tornadocontrib
GPG Key ID: 60B4DF1A076C64B1
12 changed files with 30031 additions and 31181 deletions

1
.npmrc

@ -1 +0,0 @@
@tornado:registry=https://git.tornado.ws/api/packages/tornado-packages/npm/

58388
dist/cli.js vendored

File diff suppressed because one or more lines are too long

4
dist/program.d.ts vendored

@ -1,7 +1,7 @@
import 'dotenv/config'; import 'dotenv/config';
import { Command } from 'commander'; import { Command } from 'commander';
import { JsonRpcProvider, Provider, TransactionLike, Wallet, VoidSigner } from 'ethers'; import { JsonRpcProvider, Provider, TransactionLike, Wallet, VoidSigner } from 'ethers';
import { getProviderOptions, TornadoWallet, TornadoVoidSigner, Relayer, RelayerInfo, RelayerError, RelayerClient, fetchDataOptions, NetIdType, Config } from '@tornado/core'; import { getProviderOptions, TornadoWallet, TornadoVoidSigner, RelayerInfo, RelayerError, RelayerClient, fetchDataOptions, NetIdType, Config } from '@tornado/core';
export type commonProgramOptions = { export type commonProgramOptions = {
rpc?: string; rpc?: string;
ethRpc?: string; ethRpc?: string;
@ -40,7 +40,7 @@ export declare function getProgramRelayer({ options, fetchDataOptions, netId, }:
fetchDataOptions?: fetchDataOptions; fetchDataOptions?: fetchDataOptions;
netId: NetIdType; netId: NetIdType;
}): Promise<{ }): Promise<{
validRelayers?: RelayerInfo[] | Relayer[]; validRelayers?: RelayerInfo[];
invalidRelayers?: RelayerError[]; invalidRelayers?: RelayerError[];
relayerClient?: RelayerClient; relayerClient?: RelayerClient;
}>; }>;

@ -1,6 +1,5 @@
/// <reference types="node" />
import { AsyncZippable, Unzipped } from 'fflate'; import { AsyncZippable, Unzipped } from 'fflate';
import { BaseEvents, MinimalEvents } from '@tornado/core'; import { BaseEvents, CachedEvents, MinimalEvents } from '@tornado/core';
export declare function existsAsync(fileOrDir: string): Promise<boolean>; export declare function existsAsync(fileOrDir: string): Promise<boolean>;
/** /**
* Supports legacy gz format for legacy UI * Supports legacy gz format for legacy UI
@ -31,4 +30,4 @@ export declare function loadCachedEvents<T extends MinimalEvents>({ name, cacheD
name: string; name: string;
cacheDirectory: string; cacheDirectory: string;
deployedBlock: number; deployedBlock: number;
}): Promise<BaseEvents<T>>; }): Promise<CachedEvents<T>>;

@ -1,4 +1,4 @@
import { BatchBlockOnProgress, BatchEventOnProgress, BaseTornadoService, BaseEncryptedNotesService, BaseGovernanceService, BaseRegistryService, BaseTornadoServiceConstructor, BaseEncryptedNotesServiceConstructor, BaseGovernanceServiceConstructor, BaseRegistryServiceConstructor, BaseEchoServiceConstructor, BaseEchoService } from '@tornado/core'; import { BatchBlockOnProgress, BatchEventOnProgress, BaseTornadoService, BaseEncryptedNotesService, BaseGovernanceService, BaseRegistryService, BaseTornadoServiceConstructor, BaseEncryptedNotesServiceConstructor, BaseGovernanceServiceConstructor, BaseRegistryServiceConstructor, BaseEchoServiceConstructor, BaseEchoService, CachedRelayers } from '@tornado/core';
import type { BaseEvents, DepositsEvents, WithdrawalsEvents, EncryptedNotesEvents, RegistersEvents, AllGovernanceEvents, EchoEvents } from '@tornado/core'; import type { BaseEvents, DepositsEvents, WithdrawalsEvents, EncryptedNotesEvents, RegistersEvents, AllGovernanceEvents, EchoEvents } from '@tornado/core';
export type NodeTornadoServiceConstructor = BaseTornadoServiceConstructor & { export type NodeTornadoServiceConstructor = BaseTornadoServiceConstructor & {
cacheDirectory?: string; cacheDirectory?: string;
@ -13,7 +13,7 @@ export declare class NodeTornadoService extends BaseTornadoService {
updateBlockProgress({ currentIndex, totalIndex }: Parameters<BatchBlockOnProgress>[0]): void; updateBlockProgress({ currentIndex, totalIndex }: Parameters<BatchBlockOnProgress>[0]): void;
updateGraphProgress({ type, fromBlock, toBlock, count }: Parameters<BatchEventOnProgress>[0]): void; updateGraphProgress({ type, fromBlock, toBlock, count }: Parameters<BatchEventOnProgress>[0]): void;
getEventsFromDB(): Promise<BaseEvents<DepositsEvents | WithdrawalsEvents>>; getEventsFromDB(): Promise<BaseEvents<DepositsEvents | WithdrawalsEvents>>;
getEventsFromCache(): Promise<BaseEvents<DepositsEvents | WithdrawalsEvents>>; getEventsFromCache(): Promise<import("@tornado/core").CachedEvents<DepositsEvents | WithdrawalsEvents>>;
saveEvents({ events, lastBlock }: BaseEvents<DepositsEvents | WithdrawalsEvents>): Promise<void>; saveEvents({ events, lastBlock }: BaseEvents<DepositsEvents | WithdrawalsEvents>): Promise<void>;
} }
export type NodeEchoServiceConstructor = BaseEchoServiceConstructor & { export type NodeEchoServiceConstructor = BaseEchoServiceConstructor & {
@ -27,7 +27,7 @@ export declare class NodeEchoService extends BaseEchoService {
updateEventProgress({ type, fromBlock, toBlock, count }: Parameters<BatchEventOnProgress>[0]): void; updateEventProgress({ type, fromBlock, toBlock, count }: Parameters<BatchEventOnProgress>[0]): void;
updateGraphProgress({ type, fromBlock, toBlock, count }: Parameters<BatchEventOnProgress>[0]): void; updateGraphProgress({ type, fromBlock, toBlock, count }: Parameters<BatchEventOnProgress>[0]): void;
getEventsFromDB(): Promise<BaseEvents<EchoEvents>>; getEventsFromDB(): Promise<BaseEvents<EchoEvents>>;
getEventsFromCache(): Promise<BaseEvents<EchoEvents>>; getEventsFromCache(): Promise<import("@tornado/core").CachedEvents<EchoEvents>>;
saveEvents({ events, lastBlock }: BaseEvents<EchoEvents>): Promise<void>; saveEvents({ events, lastBlock }: BaseEvents<EchoEvents>): Promise<void>;
} }
export type NodeEncryptedNotesServiceConstructor = BaseEncryptedNotesServiceConstructor & { export type NodeEncryptedNotesServiceConstructor = BaseEncryptedNotesServiceConstructor & {
@ -41,7 +41,7 @@ export declare class NodeEncryptedNotesService extends BaseEncryptedNotesService
updateEventProgress({ type, fromBlock, toBlock, count }: Parameters<BatchEventOnProgress>[0]): void; updateEventProgress({ type, fromBlock, toBlock, count }: Parameters<BatchEventOnProgress>[0]): void;
updateGraphProgress({ type, fromBlock, toBlock, count }: Parameters<BatchEventOnProgress>[0]): void; updateGraphProgress({ type, fromBlock, toBlock, count }: Parameters<BatchEventOnProgress>[0]): void;
getEventsFromDB(): Promise<BaseEvents<EncryptedNotesEvents>>; getEventsFromDB(): Promise<BaseEvents<EncryptedNotesEvents>>;
getEventsFromCache(): Promise<BaseEvents<EncryptedNotesEvents>>; getEventsFromCache(): Promise<import("@tornado/core").CachedEvents<EncryptedNotesEvents>>;
saveEvents({ events, lastBlock }: BaseEvents<EncryptedNotesEvents>): Promise<void>; saveEvents({ events, lastBlock }: BaseEvents<EncryptedNotesEvents>): Promise<void>;
} }
export type NodeGovernanceServiceConstructor = BaseGovernanceServiceConstructor & { export type NodeGovernanceServiceConstructor = BaseGovernanceServiceConstructor & {
@ -56,7 +56,7 @@ export declare class NodeGovernanceService extends BaseGovernanceService {
updateGraphProgress({ type, fromBlock, toBlock, count }: Parameters<BatchEventOnProgress>[0]): void; updateGraphProgress({ type, fromBlock, toBlock, count }: Parameters<BatchEventOnProgress>[0]): void;
updateTransactionProgress({ currentIndex, totalIndex }: Parameters<BatchBlockOnProgress>[0]): void; updateTransactionProgress({ currentIndex, totalIndex }: Parameters<BatchBlockOnProgress>[0]): void;
getEventsFromDB(): Promise<BaseEvents<AllGovernanceEvents>>; getEventsFromDB(): Promise<BaseEvents<AllGovernanceEvents>>;
getEventsFromCache(): Promise<BaseEvents<AllGovernanceEvents>>; getEventsFromCache(): Promise<import("@tornado/core").CachedEvents<AllGovernanceEvents>>;
saveEvents({ events, lastBlock }: BaseEvents<AllGovernanceEvents>): Promise<void>; saveEvents({ events, lastBlock }: BaseEvents<AllGovernanceEvents>): Promise<void>;
} }
export type NodeRegistryServiceConstructor = BaseRegistryServiceConstructor & { export type NodeRegistryServiceConstructor = BaseRegistryServiceConstructor & {
@ -66,10 +66,13 @@ export type NodeRegistryServiceConstructor = BaseRegistryServiceConstructor & {
export declare class NodeRegistryService extends BaseRegistryService { export declare class NodeRegistryService extends BaseRegistryService {
cacheDirectory?: string; cacheDirectory?: string;
userDirectory?: string; userDirectory?: string;
constructor({ netId, provider, graphApi, subgraphName, RelayerRegistry, deployedBlock, fetchDataOptions, cacheDirectory, userDirectory, }: NodeRegistryServiceConstructor); constructor({ netId, provider, graphApi, subgraphName, RelayerRegistry, Aggregator, relayerEnsSubdomains, deployedBlock, fetchDataOptions, cacheDirectory, userDirectory, }: NodeRegistryServiceConstructor);
updateEventProgress({ type, fromBlock, toBlock, count }: Parameters<BatchEventOnProgress>[0]): void; updateEventProgress({ type, fromBlock, toBlock, count }: Parameters<BatchEventOnProgress>[0]): void;
updateGraphProgress({ type, fromBlock, toBlock, count }: Parameters<BatchEventOnProgress>[0]): void; updateGraphProgress({ type, fromBlock, toBlock, count }: Parameters<BatchEventOnProgress>[0]): void;
getEventsFromDB(): Promise<BaseEvents<RegistersEvents>>; getEventsFromDB(): Promise<BaseEvents<RegistersEvents>>;
getEventsFromCache(): Promise<BaseEvents<RegistersEvents>>; getEventsFromCache(): Promise<import("@tornado/core").CachedEvents<RegistersEvents>>;
saveEvents({ events, lastBlock }: BaseEvents<RegistersEvents>): Promise<void>; saveEvents({ events, lastBlock }: BaseEvents<RegistersEvents>): Promise<void>;
getRelayersFromDB(): Promise<CachedRelayers>;
getRelayersFromCache(): Promise<CachedRelayers>;
saveRelayers({ timestamp, relayers }: CachedRelayers): Promise<void>;
} }

@ -1,6 +1,6 @@
{ {
"name": "@tornado/cli", "name": "@tornado/cli",
"version": "1.0.3-alpha", "version": "1.0.4-alpha",
"description": "Modern Toolsets for Privacy Pools on Ethereum", "description": "Modern Toolsets for Privacy Pools on Ethereum",
"main": "./dist/cli.js", "main": "./dist/cli.js",
"types": "./dist/cli.d.ts", "types": "./dist/cli.d.ts",
@ -51,38 +51,21 @@
"optionalDependencies": {}, "optionalDependencies": {},
"devDependencies": { "devDependencies": {
"@colors/colors": "1.5.0", "@colors/colors": "1.5.0",
"@metamask/eth-sig-util": "^7.0.1", "@tornado/core": "git+https://codeberg.org/tornadocash/tornado-core.git#ef56beb29b3dc8808167acefe2bd23c2680643b2",
"@tornado/contracts": "1.0.0",
"@tornado/core": "git+https://git.tornado.ws/tornadocontrib/tornado-core.git#84b6ed368e75ec2957999bd86677797412da6f5f",
"@tornado/fixed-merkle-tree": "0.7.3",
"@tornado/snarkjs": "0.1.20",
"@tornado/websnark": "0.0.4",
"@typechain/ethers-v6": "^0.5.1", "@typechain/ethers-v6": "^0.5.1",
"@types/bn.js": "^5.1.5",
"@types/circomlibjs": "^0.1.6",
"@types/figlet": "^1.5.8", "@types/figlet": "^1.5.8",
"@types/node": "^20.12.5", "@typescript-eslint/eslint-plugin": "^8.6.0",
"@types/node-fetch": "^2.6.11", "@typescript-eslint/parser": "^8.6.0",
"@typescript-eslint/eslint-plugin": "^7.6.0",
"@typescript-eslint/parser": "^7.6.0",
"ajv": "^8.12.0",
"bloomfilter.js": "^1.0.2", "bloomfilter.js": "^1.0.2",
"bn.js": "^5.2.1",
"circomlibjs": "0.1.7",
"cli-table3": "^0.6.4", "cli-table3": "^0.6.4",
"commander": "^12.0.0", "commander": "^12.0.0",
"cross-fetch": "^4.0.0",
"dotenv": "^16.4.5", "dotenv": "^16.4.5",
"esbuild": "^0.20.2", "esbuild-loader": "^4.2.2",
"esbuild-loader": "^4.1.0", "eslint": "8.57.0",
"eslint": "^8.57.0",
"eslint-config-prettier": "^9.1.0", "eslint-config-prettier": "^9.1.0",
"eslint-import-resolver-typescript": "^3.6.1", "eslint-import-resolver-typescript": "^3.6.3",
"eslint-plugin-import": "^2.29.1", "eslint-plugin-import": "^2.30.0",
"eslint-plugin-prettier": "^5.1.3", "eslint-plugin-prettier": "^5.2.1",
"ethers": "^6.12.0",
"ffjavascript": "0.2.48",
"fflate": "^0.8.2",
"figlet": "^1.7.0", "figlet": "^1.7.0",
"http-proxy-agent": "^7.0.2", "http-proxy-agent": "^7.0.2",
"https-proxy-agent": "^7.0.4", "https-proxy-agent": "^7.0.4",
@ -92,8 +75,8 @@
"ts-node": "^10.9.2", "ts-node": "^10.9.2",
"tsc": "^2.0.4", "tsc": "^2.0.4",
"typechain": "^8.3.2", "typechain": "^8.3.2",
"typescript": "^5.4.4", "typescript": "^5.6.2",
"webpack": "^5.91.0", "webpack": "^5.94.0",
"webpack-cli": "^5.1.4" "webpack-cli": "^5.1.4"
} }
} }

@ -45,14 +45,13 @@ import {
tokenBalances, tokenBalances,
Deposit, Deposit,
DepositsEvents, DepositsEvents,
WithdrawalsEvents,
Relayer,
RelayerInfo, RelayerInfo,
RelayerError, RelayerError,
RelayerClient,
WithdrawalsEvents,
TornadoFeeOracle, TornadoFeeOracle,
TokenPriceOracle, TokenPriceOracle,
calculateSnarkProof, calculateSnarkProof,
RelayerClient,
MerkleTreeService, MerkleTreeService,
multicall, multicall,
Invoice, Invoice,
@ -61,7 +60,6 @@ import {
NetId, NetId,
NetIdType, NetIdType,
getInstanceByAddress, getInstanceByAddress,
getSubdomains,
getConfig, getConfig,
Config, Config,
enabledChains, enabledChains,
@ -69,6 +67,7 @@ import {
NoteAccount, NoteAccount,
getSupportedInstances, getSupportedInstances,
initGroth16, initGroth16,
getRelayerEnsSubdomains,
} from '@tornado/core'; } from '@tornado/core';
import * as packageJson from '../package.json'; import * as packageJson from '../package.json';
import { import {
@ -230,11 +229,17 @@ export function getProgramGraphAPI(options: commonProgramOptions, config: Config
return ''; return '';
} }
if (!options.graph) { if (options.graph) {
return Object.values(config.subgraphs)[0].url; return options.graph;
} }
return options.graph; const predefinedUrl = Object.values(config.subgraphs)?.[0]?.url;
if (predefinedUrl) {
return predefinedUrl;
}
return '';
} }
export function getProgramProvider( export function getProgramProvider(
@ -279,7 +284,7 @@ export async function getProgramRelayer({
fetchDataOptions?: fetchDataOptions; fetchDataOptions?: fetchDataOptions;
netId: NetIdType; netId: NetIdType;
}): Promise<{ }): Promise<{
validRelayers?: RelayerInfo[] | Relayer[]; validRelayers?: RelayerInfo[];
invalidRelayers?: RelayerError[]; invalidRelayers?: RelayerError[];
relayerClient?: RelayerClient; relayerClient?: RelayerClient;
}> { }> {
@ -289,8 +294,6 @@ export async function getProgramRelayer({
const ethConfig = getConfig(RELAYER_NETWORK); const ethConfig = getConfig(RELAYER_NETWORK);
const subdomains = getSubdomains();
const { const {
aggregatorContract, aggregatorContract,
registryContract, registryContract,
@ -310,12 +313,16 @@ export async function getProgramRelayer({
ethConfig, ethConfig,
); );
const relayerEnsSubdomains = getRelayerEnsSubdomains();
const registryService = new NodeRegistryService({ const registryService = new NodeRegistryService({
netId: RELAYER_NETWORK, netId: RELAYER_NETWORK,
provider, provider,
graphApi, graphApi,
subgraphName: registrySubgraph, subgraphName: registrySubgraph,
RelayerRegistry: RelayerRegistry__factory.connect(registryContract as string, provider), RelayerRegistry: RelayerRegistry__factory.connect(registryContract as string, provider),
Aggregator: Aggregator__factory.connect(aggregatorContract as string, provider),
relayerEnsSubdomains,
deployedBlock: REGISTRY_BLOCK, deployedBlock: REGISTRY_BLOCK,
fetchDataOptions, fetchDataOptions,
cacheDirectory: EVENTS_DIR, cacheDirectory: EVENTS_DIR,
@ -325,56 +332,56 @@ export async function getProgramRelayer({
const relayerClient = new RelayerClient({ const relayerClient = new RelayerClient({
netId, netId,
config: netConfig, config: netConfig,
Aggregator: Aggregator__factory.connect(aggregatorContract as string, provider),
fetchDataOptions, fetchDataOptions,
}); });
if (relayer) { // If user provided relayer is a full working URL
if (!relayer.endsWith('.eth')) { if (relayer && relayer.startsWith('http')) {
const relayerStatus = await relayerClient.askRelayerStatus({ const relayerStatus = await relayerClient.askRelayerStatus({
hostname: new URL(relayer).hostname, hostname: new URL(relayer).hostname,
}); });
relayerClient.selectedRelayer = { relayerClient.selectedRelayer = {
netId: relayerStatus.netId, ensName: new URL(relayer).hostname,
url: relayerStatus.url, relayerAddress: getAddress(relayerStatus.rewardAccount),
hostname: new URL(relayerStatus.url).hostname, netId: relayerStatus.netId,
rewardAccount: getAddress(relayerStatus.rewardAccount), url: relayerStatus.url,
instances: getSupportedInstances(relayerStatus.instances), hostname: new URL(relayerStatus.url).hostname,
gasPrice: relayerStatus.gasPrices?.fast, rewardAccount: getAddress(relayerStatus.rewardAccount),
ethPrices: relayerStatus.ethPrices, instances: getSupportedInstances(relayerStatus.instances),
currentQueue: relayerStatus.currentQueue, gasPrice: relayerStatus.gasPrices?.fast,
tornadoServiceFee: relayerStatus.tornadoServiceFee, ethPrices: relayerStatus.ethPrices,
}; currentQueue: relayerStatus.currentQueue,
tornadoServiceFee: relayerStatus.tornadoServiceFee,
};
return { return {
validRelayers: [relayerClient.selectedRelayer], validRelayers: [relayerClient.selectedRelayer],
invalidRelayers: [], invalidRelayers: [],
relayerClient, relayerClient,
}; };
} else {
const { validRelayers } = await relayerClient.getValidRelayers([{ ensName: relayer }], subdomains, true);
const relayerStatus = validRelayers[0];
if (relayerStatus) {
relayerClient.selectedRelayer = relayerStatus;
}
return {
validRelayers,
invalidRelayers: [],
relayerClient,
};
}
} }
console.log('\nGetting valid relayers from registry, would take some time\n'); console.log('\nGetting valid relayers from registry, would take some time\n');
const { validRelayers, invalidRelayers } = await relayerClient.getValidRelayers( const { validRelayers, invalidRelayers } = await relayerClient.getValidRelayers(
await registryService.fetchRelayers(), (await registryService.updateRelayers()).relayers,
subdomains,
); );
await registryService.saveEventsPromise;
// If user has provided either a hostname or ensname of known registered relayer
const foundRelayer = relayer
? validRelayers.find((r) => r.hostname.includes(relayer) || r.ensName.includes(relayer))
: undefined;
if (foundRelayer) {
relayerClient.selectedRelayer = foundRelayer;
return {
validRelayers: [foundRelayer],
invalidRelayers: [],
relayerClient,
};
}
const relayerStatus = relayerClient.pickWeightedRandomRelayer(validRelayers); const relayerStatus = relayerClient.pickWeightedRandomRelayer(validRelayers);
@ -902,8 +909,6 @@ 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);
@ -1275,8 +1280,6 @@ 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);
}); });
@ -1303,6 +1306,7 @@ export function tornadoProgram() {
routerContract, routerContract,
echoContract, echoContract,
registryContract, registryContract,
aggregatorContract,
governanceContract, governanceContract,
deployedBlock, deployedBlock,
constants: { GOVERNANCE_BLOCK, REGISTRY_BLOCK, NOTE_ACCOUNT_BLOCK, ENCRYPTED_NOTES_BLOCK }, constants: { GOVERNANCE_BLOCK, REGISTRY_BLOCK, NOTE_ACCOUNT_BLOCK, ENCRYPTED_NOTES_BLOCK },
@ -1327,24 +1331,26 @@ export function tornadoProgram() {
}); });
await governanceService.updateEvents(); await governanceService.updateEvents();
await governanceService.saveEventsPromise;
} }
if (registryContract) { if (registryContract && aggregatorContract) {
const relayerEnsSubdomains = getRelayerEnsSubdomains();
const registryService = new NodeRegistryService({ const registryService = new NodeRegistryService({
netId, netId,
provider, provider,
graphApi, graphApi,
subgraphName: registrySubgraph, subgraphName: registrySubgraph,
RelayerRegistry: RelayerRegistry__factory.connect(registryContract, provider), RelayerRegistry: RelayerRegistry__factory.connect(registryContract, provider),
Aggregator: Aggregator__factory.connect(aggregatorContract, provider),
relayerEnsSubdomains,
deployedBlock: REGISTRY_BLOCK, deployedBlock: REGISTRY_BLOCK,
fetchDataOptions, fetchDataOptions,
cacheDirectory: EVENTS_DIR, cacheDirectory: EVENTS_DIR,
userDirectory: SAVED_DIR, userDirectory: SAVED_DIR,
}); });
await registryService.updateEvents(); await registryService.updateRelayers();
await registryService.saveEventsPromise;
} }
const echoService = new NodeEchoService({ const echoService = new NodeEchoService({
@ -1360,7 +1366,6 @@ export function tornadoProgram() {
}); });
await echoService.updateEvents(); await echoService.updateEvents();
await echoService.saveEventsPromise;
const encryptedNotesService = new NodeEncryptedNotesService({ const encryptedNotesService = new NodeEncryptedNotesService({
netId, netId,
@ -1375,7 +1380,6 @@ 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);
@ -1446,8 +1450,6 @@ 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]);
} }
} }
} }
@ -1492,7 +1494,7 @@ export function tornadoProgram() {
netId, netId,
url, url,
ensName, ensName,
stakeBalance ? `${Number(formatEther(stakeBalance)).toFixed(5)} TORN` : '', stakeBalance ? `${Number(stakeBalance).toFixed(5)} TORN` : '',
relayerAddress, relayerAddress,
rewardAccount, rewardAccount,
currentQueue, currentQueue,
@ -1582,7 +1584,6 @@ 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);
@ -1693,7 +1694,6 @@ 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();

@ -2,7 +2,7 @@ import path from 'path';
import { deflate, constants } from 'zlib'; import { deflate, constants } from 'zlib';
import { stat, mkdir, readFile, writeFile } from 'fs/promises'; import { stat, mkdir, readFile, writeFile } from 'fs/promises';
import { zip, unzip, AsyncZippable, Unzipped } from 'fflate'; import { zip, unzip, AsyncZippable, Unzipped } from 'fflate';
import { BaseEvents, MinimalEvents } from '@tornado/core'; import { BaseEvents, CachedEvents, MinimalEvents } from '@tornado/core';
export async function existsAsync(fileOrDir: string): Promise<boolean> { export async function existsAsync(fileOrDir: string): Promise<boolean> {
try { try {
@ -161,7 +161,7 @@ export async function loadCachedEvents<T extends MinimalEvents>({
name: string; name: string;
cacheDirectory: string; cacheDirectory: string;
deployedBlock: number; deployedBlock: number;
}): Promise<BaseEvents<T>> { }): Promise<CachedEvents<T>> {
try { try {
const module = await download({ cacheDirectory, name }); const module = await download({ cacheDirectory, name });
@ -173,12 +173,14 @@ export async function loadCachedEvents<T extends MinimalEvents>({
return { return {
events, events,
lastBlock, lastBlock,
fromCache: true,
}; };
} }
return { return {
events: [], events: [],
lastBlock: deployedBlock, lastBlock: deployedBlock,
fromCache: true,
}; };
} catch (err) { } catch (err) {
console.log('Method loadCachedEvents has error'); console.log('Method loadCachedEvents has error');
@ -186,6 +188,7 @@ export async function loadCachedEvents<T extends MinimalEvents>({
return { return {
events: [], events: [],
lastBlock: deployedBlock, lastBlock: deployedBlock,
fromCache: true,
}; };
} }
} }

@ -1,3 +1,5 @@
import path from 'path';
import { readFile } from 'fs/promises';
import Table from 'cli-table3'; import Table from 'cli-table3';
import moment from 'moment'; import moment from 'moment';
import { import {
@ -14,6 +16,7 @@ import {
BaseEchoServiceConstructor, BaseEchoServiceConstructor,
BaseEchoService, BaseEchoService,
DEPOSIT, DEPOSIT,
CachedRelayers,
} from '@tornado/core'; } from '@tornado/core';
import type { import type {
BaseEvents, BaseEvents,
@ -24,7 +27,7 @@ import type {
AllGovernanceEvents, AllGovernanceEvents,
EchoEvents, EchoEvents,
} from '@tornado/core'; } from '@tornado/core';
import { saveUserFile, loadSavedEvents, loadCachedEvents, saveLegacyFile } from './data'; import { saveUserFile, loadSavedEvents, loadCachedEvents, saveLegacyFile, existsAsync } from './data';
export type NodeTornadoServiceConstructor = BaseTornadoServiceConstructor & { export type NodeTornadoServiceConstructor = BaseTornadoServiceConstructor & {
cacheDirectory?: string; cacheDirectory?: string;
@ -142,6 +145,7 @@ export class NodeTornadoService extends BaseTornadoService {
return { return {
events: [], events: [],
lastBlock: this.deployedBlock, lastBlock: this.deployedBlock,
fromCache: true,
}; };
} }
@ -314,6 +318,7 @@ export class NodeEchoService extends BaseEchoService {
return { return {
events: [], events: [],
lastBlock: this.deployedBlock, lastBlock: this.deployedBlock,
fromCache: true,
}; };
} }
@ -459,6 +464,7 @@ export class NodeEncryptedNotesService extends BaseEncryptedNotesService {
return { return {
events: [], events: [],
lastBlock: this.deployedBlock, lastBlock: this.deployedBlock,
fromCache: true,
}; };
} }
@ -622,6 +628,7 @@ export class NodeGovernanceService extends BaseGovernanceService {
return { return {
events: [], events: [],
lastBlock: this.deployedBlock, lastBlock: this.deployedBlock,
fromCache: true,
}; };
} }
@ -689,6 +696,8 @@ export class NodeRegistryService extends BaseRegistryService {
graphApi, graphApi,
subgraphName, subgraphName,
RelayerRegistry, RelayerRegistry,
Aggregator,
relayerEnsSubdomains,
deployedBlock, deployedBlock,
fetchDataOptions, fetchDataOptions,
cacheDirectory, cacheDirectory,
@ -700,6 +709,8 @@ export class NodeRegistryService extends BaseRegistryService {
graphApi, graphApi,
subgraphName, subgraphName,
RelayerRegistry, RelayerRegistry,
Aggregator,
relayerEnsSubdomains,
deployedBlock, deployedBlock,
fetchDataOptions, fetchDataOptions,
}); });
@ -767,6 +778,7 @@ export class NodeRegistryService extends BaseRegistryService {
return { return {
events: [], events: [],
lastBlock: this.deployedBlock, lastBlock: this.deployedBlock,
fromCache: true,
}; };
} }
@ -817,4 +829,73 @@ export class NodeRegistryService extends BaseRegistryService {
}); });
} }
} }
async getRelayersFromDB(): Promise<CachedRelayers> {
const filePath = path.join(this.userDirectory || '', 'relayers.json');
if (!this.userDirectory || !(await existsAsync(filePath))) {
return {
timestamp: 0,
relayers: [],
};
}
try {
const { timestamp, relayers } = JSON.parse(await readFile(filePath, { encoding: 'utf8' }));
return {
timestamp,
relayers,
};
} catch (err) {
console.log('Method getRelayersFromDB has error');
console.log(err);
return {
timestamp: 0,
relayers: [],
};
}
}
async getRelayersFromCache(): Promise<CachedRelayers> {
const filePath = path.join(this.cacheDirectory || '', 'relayers.json');
if (!this.cacheDirectory || !(await existsAsync(filePath))) {
return {
timestamp: 0,
relayers: [],
fromCache: true,
};
}
try {
const { timestamp, relayers } = JSON.parse(await readFile(filePath, { encoding: 'utf8' }));
return {
timestamp,
relayers,
fromCache: true,
};
} catch (err) {
console.log('Method getRelayersFromDB has error');
console.log(err);
return {
timestamp: 0,
relayers: [],
fromCache: true,
};
}
}
async saveRelayers({ timestamp, relayers }: CachedRelayers) {
if (this.userDirectory) {
await saveUserFile({
fileName: 'relayers.json',
userDirectory: this.userDirectory,
dataString: JSON.stringify({ timestamp, relayers }, null, 2) + '\n',
});
}
}
} }

357
static/events/relayers.json Normal file

@ -0,0 +1,357 @@
{
"timestamp": 1726890359,
"relayers": [
{
"ensName": "okrelayer.eth",
"relayerAddress": "0x0e9D9a828247F5eed7f6D31D213A39805De52441",
"isRegistered": true,
"owner": "0x0e9D9a828247F5eed7f6D31D213A39805De52441",
"stakeBalance": "4666.679387946529032297",
"hostnames": {
"1": "okrelayer.xyz",
"56": "binance.okrelayer.xyz",
"137": "polygon.okrelayer.xyz",
"42161": "arb.okrelayer.xyz"
}
},
{
"ensName": "quick-relayer.eth",
"relayerAddress": "0x187541D7D312F742040f270d0221B4Fe577934B0",
"isRegistered": true,
"owner": "0x187541D7D312F742040f270d0221B4Fe577934B0",
"stakeBalance": "2931.033250737658918569",
"hostnames": {
"1": "quick-relayer.xyz"
}
},
{
"ensName": "safety-relayer.eth",
"relayerAddress": "0xF1F4F76c9969eFbFB5C9A90a6E44c0E3696D3EF8",
"isRegistered": true,
"owner": "0xF1F4F76c9969eFbFB5C9A90a6E44c0E3696D3EF8",
"stakeBalance": "500.879215977529089999",
"hostnames": {
"1": "a-relayer.top",
"56": "bsc.a-relayer.top",
"137": "polygon.a-relayer.top"
}
},
{
"ensName": "k-relayer.eth",
"relayerAddress": "0xC49415493eB3Ec64a0F13D8AA5056f1CfC4ce35c",
"isRegistered": true,
"owner": "0xC49415493eB3Ec64a0F13D8AA5056f1CfC4ce35c",
"stakeBalance": "2194.529689989084430299",
"hostnames": {
"1": "black-hardy.com",
"56": "bsc.black-hardy.com"
}
},
{
"ensName": "relayer007.eth",
"relayerAddress": "0xa0109274F53609f6Be97ec5f3052C659AB80f012",
"isRegistered": true,
"owner": "0xa0109274F53609f6Be97ec5f3052C659AB80f012",
"stakeBalance": "4989.637826137906607638",
"hostnames": {
"1": "torn.relayersdao.finance",
"56": "bsc.relayersdao.finance",
"137": "matic.relayersdao.finance"
}
},
{
"ensName": "reltor.eth",
"relayerAddress": "0x4750BCfcC340AA4B31be7e71fa072716d28c29C5",
"isRegistered": true,
"owner": "0x4750BCfcC340AA4B31be7e71fa072716d28c29C5",
"stakeBalance": "19999.983956326624881327",
"hostnames": {
"1": "eth.reltor.su",
"56": "binance.reltor.su",
"137": "polygon.reltor.su"
}
},
{
"ensName": "best-relay.eth",
"relayerAddress": "0xe5A4c70113b90566BC5f80a3866935d0d52F990E",
"isRegistered": true,
"owner": "0xe5A4c70113b90566BC5f80a3866935d0d52F990E",
"stakeBalance": "2002.0",
"hostnames": {
"1": "best-relay.gato-miaouw.xyz",
"56": "bsc.gato-miaouw.xyz"
}
},
{
"ensName": "crelayer.eth",
"relayerAddress": "0x180c58B7305152357142b33Eea94cBB152058B61",
"isRegistered": true,
"owner": "0x180c58B7305152357142b33Eea94cBB152058B61",
"stakeBalance": "1460.389956347917729137",
"hostnames": {
"1": "eth.crelayer.xyz",
"56": "bsc.crelayer.xyz"
}
},
{
"ensName": "torn-city.eth",
"relayerAddress": "0xd04e9f0945DEA8373D882C730e2c93a74B591796",
"isRegistered": true,
"owner": "0xd04e9f0945DEA8373D882C730e2c93a74B591796",
"stakeBalance": "6715.49550101901162633",
"hostnames": {
"1": "torn-city.com",
"56": "bsc.torn-city.com"
}
},
{
"ensName": "torrelayer.eth",
"relayerAddress": "0x2Ee39Ff05643bC7cc9ed31B71e142429044A425C",
"isRegistered": true,
"owner": "0x2Ee39Ff05643bC7cc9ed31B71e142429044A425C",
"stakeBalance": "3734.220945056618867324",
"hostnames": {
"1": "tornima.xyz",
"56": "binance.tornima.xyz"
}
},
{
"ensName": "tornxdo.eth",
"relayerAddress": "0xB399aa4c2F1678f72529Cd125F82cEA2c2a823eD",
"isRegistered": true,
"owner": "0xB399aa4c2F1678f72529Cd125F82cEA2c2a823eD",
"stakeBalance": "983.310689667160962345",
"hostnames": {
"1": "tornado.evmjunkie.xyz"
}
},
{
"ensName": "0xgm777.eth",
"relayerAddress": "0x94596B6A626392F5D972D6CC4D929a42c2f0008c",
"isRegistered": true,
"owner": "0x94596B6A626392F5D972D6CC4D929a42c2f0008c",
"stakeBalance": "1979.261700994868938309",
"hostnames": {
"1": "main.gm777.xyz",
"56": "bsc.gm777.xyz",
"42161": "arb.gm777.xyz"
}
},
{
"ensName": "relayer-secure.eth",
"relayerAddress": "0xCEdac436cEA98E93F471331eCC693fF41D730921",
"isRegistered": true,
"owner": "0xCEdac436cEA98E93F471331eCC693fF41D730921",
"stakeBalance": "548.198082306127582623",
"hostnames": {
"1": "relsecc-mainnet.moon-relayer.app"
}
},
{
"ensName": "default-relayer.eth",
"relayerAddress": "0x5555555731006f71f121144534Ca7C8799F66AA3",
"isRegistered": true,
"owner": "0x5555555731006f71f121144534Ca7C8799F66AA3",
"stakeBalance": "5011.216884015043970278",
"hostnames": {
"1": "eth.default-relayer.com",
"56": "bsc.default-relayer.com"
}
},
{
"ensName": "t-relayer.eth",
"relayerAddress": "0x000000Cd6521Ed1a65FAe0678eA15aF4EEAD74fe",
"isRegistered": true,
"owner": "0x000000Cd6521Ed1a65FAe0678eA15aF4EEAD74fe",
"stakeBalance": "6079.008889316501226288",
"hostnames": {
"1": "eth.t-relayer.com",
"56": "bsc.t-relayer.com"
}
},
{
"ensName": "secure-relay.eth",
"relayerAddress": "0x1036AF02bCDb2e3A4db2d3D40b29e5054EDc79BA",
"isRegistered": true,
"owner": "0x1036AF02bCDb2e3A4db2d3D40b29e5054EDc79BA",
"stakeBalance": "6751.661507930994067422",
"hostnames": {
"1": "torn-relayer.duckdns.org"
}
},
{
"ensName": "torntorn.eth",
"relayerAddress": "0x1247749d7E28D357B4279110af0802603AC526cE",
"isRegistered": true,
"owner": "0x1247749d7E28D357B4279110af0802603AC526cE",
"stakeBalance": "5535.435044583932530913",
"hostnames": {
"1": "eth.fsdhreu39jfk.com",
"56": "bsc.fsdhreu39jfk.com",
"100": "gnosis.tornad0.com",
"137": "polygon.tornad0.com"
}
},
{
"ensName": "bitah.eth",
"relayerAddress": "0x7E3893725d4e238B4c8c83375bBAd024a66Ffa42",
"isRegistered": true,
"owner": "0x7E3893725d4e238B4c8c83375bBAd024a66Ffa42",
"stakeBalance": "503.237718892072788154",
"hostnames": {
"1": "tornado.bitah.link",
"56": "bsc-tornado.bitah.link",
"137": "polygon-tornado.bitah.link"
}
},
{
"ensName": "shadow-out.eth",
"relayerAddress": "0x9Ee26a4bFd731E8e742B65bF955814EADdd7F151",
"isRegistered": true,
"owner": "0x9Ee26a4bFd731E8e742B65bF955814EADdd7F151",
"stakeBalance": "3571.639136672079169166",
"hostnames": {
"1": "livetobecomeavillain",
"56": "justarandomdude",
"100": "everythingisburning"
}
},
{
"ensName": "torn-eth.eth",
"relayerAddress": "0x42FecB4137aFF76E0E85702ff4F339DbFe6D859E",
"isRegistered": true,
"owner": "0x42FecB4137aFF76E0E85702ff4F339DbFe6D859E",
"stakeBalance": "978.62598484549460861",
"hostnames": {
"1": "mainnet-tornado.50swap.com"
}
},
{
"ensName": "0xproxy.eth",
"relayerAddress": "0x08657a1f4C1F06d657F31767831421EE7FaDf549",
"isRegistered": true,
"owner": "0x08657a1f4C1F06d657F31767831421EE7FaDf549",
"stakeBalance": "705.605817336537209483",
"hostnames": {
"1": "mainnet.0x0relayer.xyz",
"56": "bsc.0x0relayer.xyz",
"137": "polygon.0x0relayer.xyz"
}
},
{
"ensName": "wetez.eth",
"relayerAddress": "0xe6184DA55174Cc0263a17eA2fc24E48511766505",
"isRegistered": true,
"owner": "0xe6184DA55174Cc0263a17eA2fc24E48511766505",
"stakeBalance": "567.980734786905511868",
"hostnames": {
"1": "tornado-1.wetez.io"
}
},
{
"ensName": "0xtorn.eth",
"relayerAddress": "0x9Ffbd3f9eE795A4fDa880ED553A2A4BD6D45CE5B",
"isRegistered": true,
"owner": "0x9Ffbd3f9eE795A4fDa880ED553A2A4BD6D45CE5B",
"stakeBalance": "4627.036617270139345308",
"hostnames": {
"1": "mainnet.al1n.cc",
"56": "bsc-tornado.al1n.cc"
}
},
{
"ensName": "reslayer.eth",
"relayerAddress": "0x7Ba6781620c91676B070D319E7E894BFd4A9eC81",
"isRegistered": true,
"owner": "0x7Ba6781620c91676B070D319E7E894BFd4A9eC81",
"stakeBalance": "879.305690438201312145",
"hostnames": {
"1": "mainnet-tornado.reslayer.xyz",
"56": "bsc-tornado.reslayer.xyz",
"100": "gnosis-tornado.reslayer.xyz",
"137": "polygon-tornado.reslayer.xyz",
"42161": "arbitrum-tornado.reslayer.xyz",
"43114": "avalanche-tornado.reslayer.xyz"
}
},
{
"ensName": "em3tornado.eth",
"relayerAddress": "0x3a1d526D09b7E59Fd88De4726f68A8246dDC2742",
"isRegistered": true,
"owner": "0x3a1d526D09b7E59Fd88De4726f68A8246dDC2742",
"stakeBalance": "16864.242955629118561145",
"hostnames": {
"1": "em3torn.com",
"10": "optimism.em3torn.com",
"56": "bsc.em3torn.com",
"137": "polygon.em3torn.com",
"42161": "arbitrum.em3torn.com",
"43114": "avax.em3torn.com"
}
},
{
"ensName": "on-sale.eth",
"relayerAddress": "0x63606C4011e97a73BCd844Cde6a38D45a728BC0E",
"isRegistered": true,
"owner": "0x63606C4011e97a73BCd844Cde6a38D45a728BC0E",
"stakeBalance": "4476.543684932880020592",
"hostnames": {
"1": "mainnet-tornado.appleworld.club",
"56": "bsc-tornado.appleworld.club"
}
},
{
"ensName": "relayernews.eth",
"relayerAddress": "0x6289C8a70EE2Ed6914834CaEa431F9a82c7eAf70",
"isRegistered": true,
"owner": "0x6289C8a70EE2Ed6914834CaEa431F9a82c7eAf70",
"stakeBalance": "1661.181918638614466424",
"hostnames": {
"1": "mainnet-tornado.relayernews.xyz",
"56": "bsc-tornado.relayernews.xyz"
}
},
{
"ensName": "lowcost.eth",
"relayerAddress": "0x28907F21F43B419F34226d6f10aCbCf1832b1D4d",
"isRegistered": true,
"owner": "0x28907F21F43B419F34226d6f10aCbCf1832b1D4d",
"stakeBalance": "500.279638085962965981",
"hostnames": {
"1": "mainnet-tornado.low-fee.xyz",
"56": "bsc-tornado.low-fee.xyz",
"137": "polygon-tornado.low-fee.xyz",
"43114": "avalanche-tornado.low-fee.xyz"
}
},
{
"ensName": "cheap-relayer.eth",
"relayerAddress": "0x076D4E32C6A5D888fC4658281539c94E778C796d",
"isRegistered": true,
"owner": "0x076D4E32C6A5D888fC4658281539c94E778C796d",
"stakeBalance": "500.878420081833044818",
"hostnames": {
"1": "mainnet-tornado.cheap-relayer.xyz",
"56": "bsc-tornado.cheap-relayer.xyz",
"137": "polygon-tornado.cheap-relayer.xyz",
"43114": "avalanche-tornado.cheap-relayer.xyz"
}
},
{
"ensName": "therelayer.eth",
"relayerAddress": "0xA0F0287683E820FF4211e67C03cf46a87431f4E1",
"isRegistered": true,
"owner": "0xA0F0287683E820FF4211e67C03cf46a87431f4E1",
"stakeBalance": "1335.888771359625809238",
"hostnames": {
"1": "mainnet.therelayer.xyz",
"10": "optimism.therelayer.xyz",
"56": "bsc.therelayer.xyz",
"100": "xdai.therelayer.xyz",
"137": "polygon.therelayer.xyz",
"42161": "arbitrum.therelayer.xyz",
"43114": "avalanche.therelayer.xyz"
}
}
]
}

@ -1,4 +1,3 @@
const esbuild = require('esbuild');
const path = require('path'); const path = require('path');
const { BannerPlugin } = require('webpack'); const { BannerPlugin } = require('webpack');
@ -8,7 +7,6 @@ const esbuildLoader = {
options: { options: {
loader: 'ts', loader: 'ts',
target: 'es2016', target: 'es2016',
implementation: esbuild
} }
} }

1313
yarn.lock

File diff suppressed because it is too large Load Diff