Added Governance Commands

This commit is contained in:
Tornado Contrib 2024-10-20 11:33:13 +00:00
parent 4512834388
commit 1217d411c2
Signed by: tornadocontrib
GPG Key ID: 60B4DF1A076C64B1
10 changed files with 9125 additions and 6002 deletions

13904
dist/cli.js vendored

File diff suppressed because one or more lines are too long

10
dist/program.d.ts vendored

@ -1,13 +1,10 @@
import 'dotenv/config';
import { Command } from 'commander';
import { JsonRpcProvider, Provider, TransactionLike, Wallet, VoidSigner } from 'ethers';
import { getProviderOptions, TornadoWallet, TornadoVoidSigner, RelayerInfo, RelayerError, RelayerClient, fetchDataOptions, NetIdType, Config, TovarishClient, TovarishInfo } from '@tornado/core';
export type commonProgramOptions = {
import { getProviderOptions, TornadoWallet, TornadoVoidSigner, RelayerInfo, RelayerError, RelayerClient, fetchDataOptions, NetIdType, TovarishClient, TovarishInfo } from '@tornado/core';
export interface commonProgramOptions {
rpc?: string;
ethRpc?: string;
graph?: string;
ethGraph?: string;
disableGraph?: boolean;
disableTovarish?: boolean;
accountKey?: string;
relayer?: string;
@ -20,7 +17,7 @@ export type commonProgramOptions = {
privateKey?: string;
nonInteractive?: boolean;
localRpc?: boolean;
};
}
export declare function promptConfirmation(nonInteractive?: boolean): Promise<void>;
export declare function getIPAddress(fetchDataOptions: fetchDataOptions): Promise<{
ip: any;
@ -30,7 +27,6 @@ export declare function getProgramOptions(options: commonProgramOptions): Promis
options: commonProgramOptions;
fetchDataOptions: fetchDataOptions;
}>;
export declare function getProgramGraphAPI(options: commonProgramOptions, config: Config): string;
export declare function getProgramProvider(rpcUrl: string | undefined, providerOptions: getProviderOptions): Promise<JsonRpcProvider>;
export declare function getProgramSigner({ options, provider, }: {
options: commonProgramOptions;

@ -1,9 +1,11 @@
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, MerkleTreeService } from '@tornado/core';
import { TreeCache } from './treeCache';
export type NodeTornadoServiceConstructor = BaseTornadoServiceConstructor & {
export type NodeServiceConstructor = {
cacheDirectory: string;
userDirectory: string;
};
export type NodeTornadoServiceConstructor = BaseTornadoServiceConstructor & NodeServiceConstructor & {
nativeCurrency: string;
merkleTreeService?: MerkleTreeService;
treeCache?: TreeCache;
@ -14,7 +16,7 @@ export declare class NodeTornadoService extends BaseTornadoService {
nativeCurrency: string;
merkleTreeService?: MerkleTreeService;
treeCache?: TreeCache;
constructor({ netId, provider, graphApi, subgraphName, Tornado, type, amount, currency, deployedBlock, fetchDataOptions, tovarishClient, cacheDirectory, userDirectory, nativeCurrency, merkleTreeService, treeCache, }: NodeTornadoServiceConstructor);
constructor(serviceConstructor: NodeTornadoServiceConstructor);
updateEventProgress({ type, fromBlock, toBlock, count }: Parameters<BatchEventOnProgress>[0]): void;
updateTransactionProgress({ currentIndex, totalIndex }: Parameters<BatchBlockOnProgress>[0]): void;
updateBlockProgress({ currentIndex, totalIndex }: Parameters<BatchBlockOnProgress>[0]): void;
@ -23,42 +25,33 @@ export declare class NodeTornadoService extends BaseTornadoService {
getEventsFromCache(): Promise<import("@tornado/core").CachedEvents<DepositsEvents | WithdrawalsEvents>>;
saveEvents({ events, lastBlock }: BaseEvents<DepositsEvents | WithdrawalsEvents>): Promise<void>;
}
export type NodeEchoServiceConstructor = BaseEchoServiceConstructor & {
cacheDirectory: string;
userDirectory: string;
};
export type NodeEchoServiceConstructor = BaseEchoServiceConstructor & NodeServiceConstructor;
export declare class NodeEchoService extends BaseEchoService {
cacheDirectory: string;
userDirectory: string;
constructor({ netId, provider, graphApi, subgraphName, Echoer, deployedBlock, fetchDataOptions, tovarishClient, cacheDirectory, userDirectory, }: NodeEchoServiceConstructor);
constructor(serviceConstructor: NodeEchoServiceConstructor);
updateEventProgress({ type, fromBlock, toBlock, count }: Parameters<BatchEventOnProgress>[0]): void;
updateGraphProgress({ type, fromBlock, toBlock, count }: Parameters<BatchEventOnProgress>[0]): void;
getEventsFromDB(): Promise<BaseEvents<EchoEvents>>;
getEventsFromCache(): Promise<import("@tornado/core").CachedEvents<EchoEvents>>;
saveEvents({ events, lastBlock }: BaseEvents<EchoEvents>): Promise<void>;
}
export type NodeEncryptedNotesServiceConstructor = BaseEncryptedNotesServiceConstructor & {
cacheDirectory: string;
userDirectory: string;
};
export type NodeEncryptedNotesServiceConstructor = BaseEncryptedNotesServiceConstructor & NodeServiceConstructor;
export declare class NodeEncryptedNotesService extends BaseEncryptedNotesService {
cacheDirectory: string;
userDirectory: string;
constructor({ netId, provider, graphApi, subgraphName, Router, deployedBlock, fetchDataOptions, tovarishClient, cacheDirectory, userDirectory, }: NodeEncryptedNotesServiceConstructor);
constructor(serviceConstructor: NodeEncryptedNotesServiceConstructor);
updateEventProgress({ type, fromBlock, toBlock, count }: Parameters<BatchEventOnProgress>[0]): void;
updateGraphProgress({ type, fromBlock, toBlock, count }: Parameters<BatchEventOnProgress>[0]): void;
getEventsFromDB(): Promise<BaseEvents<EncryptedNotesEvents>>;
getEventsFromCache(): Promise<import("@tornado/core").CachedEvents<EncryptedNotesEvents>>;
saveEvents({ events, lastBlock }: BaseEvents<EncryptedNotesEvents>): Promise<void>;
}
export type NodeGovernanceServiceConstructor = BaseGovernanceServiceConstructor & {
cacheDirectory: string;
userDirectory: string;
};
export type NodeGovernanceServiceConstructor = BaseGovernanceServiceConstructor & NodeServiceConstructor;
export declare class NodeGovernanceService extends BaseGovernanceService {
cacheDirectory: string;
userDirectory: string;
constructor({ netId, provider, graphApi, subgraphName, Governance, deployedBlock, fetchDataOptions, tovarishClient, cacheDirectory, userDirectory, }: NodeGovernanceServiceConstructor);
constructor(serviceConstructor: NodeGovernanceServiceConstructor);
updateEventProgress({ type, fromBlock, toBlock, count }: Parameters<BatchEventOnProgress>[0]): void;
updateGraphProgress({ type, fromBlock, toBlock, count }: Parameters<BatchEventOnProgress>[0]): void;
updateTransactionProgress({ currentIndex, totalIndex }: Parameters<BatchBlockOnProgress>[0]): void;
@ -66,14 +59,11 @@ export declare class NodeGovernanceService extends BaseGovernanceService {
getEventsFromCache(): Promise<import("@tornado/core").CachedEvents<AllGovernanceEvents>>;
saveEvents({ events, lastBlock }: BaseEvents<AllGovernanceEvents>): Promise<void>;
}
export type NodeRegistryServiceConstructor = BaseRegistryServiceConstructor & {
cacheDirectory: string;
userDirectory: string;
};
export type NodeRegistryServiceConstructor = BaseRegistryServiceConstructor & NodeServiceConstructor;
export declare class NodeRegistryService extends BaseRegistryService {
cacheDirectory: string;
userDirectory: string;
constructor({ netId, provider, graphApi, subgraphName, RelayerRegistry, Aggregator, relayerEnsSubdomains, deployedBlock, fetchDataOptions, tovarishClient, cacheDirectory, userDirectory, }: NodeRegistryServiceConstructor);
constructor(serviceConstructor: NodeRegistryServiceConstructor);
updateEventProgress({ type, fromBlock, toBlock, count }: Parameters<BatchEventOnProgress>[0]): void;
updateGraphProgress({ type, fromBlock, toBlock, count }: Parameters<BatchEventOnProgress>[0]): void;
getEventsFromDB(): Promise<BaseEvents<RegistersEvents>>;

@ -51,11 +51,11 @@
"optionalDependencies": {},
"devDependencies": {
"@colors/colors": "^1.6.0",
"@tornado/core": "git+https://git.tornado.ws/tornadocontrib/tornado-core.git#4f0aaea790ff26bb8902bbf60f101ec240704685",
"@tornado/core": "git+https://git.tornado.ws/tornadocontrib/tornado-core.git#ddf306a835a0907eed1a2a7aab4ed41e34fd9037",
"@typechain/ethers-v6": "^0.5.1",
"@types/figlet": "^1.7.0",
"@typescript-eslint/eslint-plugin": "^8.8.1",
"@typescript-eslint/parser": "^8.8.1",
"@typescript-eslint/eslint-plugin": "^8.9.0",
"@typescript-eslint/parser": "^8.9.0",
"bloomfilter.js": "^1.0.2",
"cli-table3": "^0.6.4",
"commander": "^12.0.0",

@ -70,6 +70,8 @@ import {
getActiveTokens,
TovarishClient,
TovarishInfo,
ReverseRecords__factory,
numberFormatter,
} from '@tornado/core';
import * as packageJson from '../package.json';
import {
@ -116,12 +118,9 @@ interface packageJson {
description: string;
}
export type commonProgramOptions = {
export interface commonProgramOptions {
rpc?: string;
ethRpc?: string;
graph?: string;
ethGraph?: string;
disableGraph?: boolean;
disableTovarish?: boolean;
accountKey?: string;
relayer?: string;
@ -134,7 +133,7 @@ export type commonProgramOptions = {
privateKey?: string;
nonInteractive?: boolean;
localRpc?: boolean;
};
}
export async function promptConfirmation(nonInteractive?: boolean) {
if (nonInteractive) {
@ -175,9 +174,6 @@ export async function getProgramOptions(options: commonProgramOptions): Promise<
options = {
rpc: options.rpc || (process.env.RPC_URL ? parseUrl(process.env.RPC_URL) : undefined),
ethRpc: options.ethRpc || (process.env.ETHRPC_URL ? parseUrl(process.env.ETHRPC_URL) : undefined),
graph: options.graph || (process.env.GRAPH_URL ? parseUrl(process.env.GRAPH_URL) : undefined),
ethGraph: options.ethGraph || (process.env.ETHGRAPH_URL ? parseUrl(process.env.ETHGRAPH_URL) : undefined),
disableGraph: Boolean(options.disableGraph) || (process.env.DISABLE_GRAPH === 'true' ? true : undefined),
disableTovarish: Boolean(options.disableTovarish) || (process.env.DISABLE_TOVARISH === 'true' ? true : undefined),
accountKey: options.accountKey || (process.env.ACCOUNT_KEY ? parseRecoveryKey(process.env.ACCOUNT_KEY) : undefined),
relayer: options.relayer || (process.env.RELAYER ? parseRelayer(process.env.RELAYER) : undefined),
@ -225,24 +221,6 @@ export async function getProgramOptions(options: commonProgramOptions): Promise<
};
}
export function getProgramGraphAPI(options: commonProgramOptions, config: Config): string {
if (options.disableGraph) {
return '';
}
if (options.graph) {
return options.graph;
}
const predefinedUrl = Object.values(config.subgraphs)?.[0]?.url;
if (predefinedUrl) {
return predefinedUrl;
}
return '';
}
export function getProgramProvider(rpcUrl: string = '', providerOptions: getProviderOptions): Promise<JsonRpcProvider> {
const { netId } = providerOptions;
@ -288,7 +266,7 @@ export async function getProgramRelayer({
invalidRelayers: RelayerError[];
relayerClient: RelayerClient;
}> {
const { ethRpc, ethGraph, relayer, disableGraph } = options;
const { ethRpc, relayer } = options;
const netConfig = getConfig(netId);
@ -297,7 +275,6 @@ export async function getProgramRelayer({
const {
aggregatorContract,
registryContract,
registrySubgraph,
constants: { REGISTRY_BLOCK },
} = ethConfig;
@ -306,19 +283,9 @@ export async function getProgramRelayer({
...fetchDataOptions,
});
const graphApi = getProgramGraphAPI(
{
disableGraph,
graph: ethGraph,
},
ethConfig,
);
const registryService = new NodeRegistryService({
netId: RELAYER_NETWORK,
provider,
graphApi,
subgraphName: registrySubgraph,
RelayerRegistry: RelayerRegistry__factory.connect(registryContract as string, provider),
Aggregator: Aggregator__factory.connect(aggregatorContract as string, provider),
relayerEnsSubdomains: getRelayerEnsSubdomains(),
@ -408,7 +375,7 @@ export async function getTovarishRelayer({
invalidRelayers: RelayerError[];
relayerClient: TovarishClient;
}> {
const { ethRpc, ethGraph, relayer, disableGraph } = options;
const { ethRpc, relayer } = options;
const netConfig = getConfig(netId);
@ -417,7 +384,6 @@ export async function getTovarishRelayer({
const {
aggregatorContract,
registryContract,
registrySubgraph,
constants: { REGISTRY_BLOCK },
} = ethConfig;
@ -426,19 +392,9 @@ export async function getTovarishRelayer({
...fetchDataOptions,
});
const graphApi = getProgramGraphAPI(
{
disableGraph,
graph: ethGraph,
},
ethConfig,
);
const registryService = new NodeRegistryService({
netId: RELAYER_NETWORK,
provider,
graphApi,
subgraphName: registrySubgraph,
RelayerRegistry: RelayerRegistry__factory.connect(registryContract as string, provider),
Aggregator: Aggregator__factory.connect(aggregatorContract as string, provider),
relayerEnsSubdomains: getRelayerEnsSubdomains(),
@ -932,7 +888,6 @@ export function tornadoProgram() {
const config = getConfig(netId);
const {
tornadoSubgraph,
deployedBlock,
nativeCurrency,
multicallContract,
@ -974,8 +929,8 @@ export function tornadoProgram() {
const tovarishClient = relayerClient.tovarish ? (relayerClient as TovarishClient) : undefined;
if (tovarishClient) {
console.log(`\nConnected with Tovarish Relayer ${tovarishClient.selectedRelayer?.url}\n`);
if (tovarishClient?.selectedRelayer) {
console.log(`\nConnected with Tovarish Relayer ${tovarishClient.selectedRelayer.url}\n`);
}
if (!walletWithdrawal && !relayerClient?.selectedRelayer) {
@ -994,8 +949,6 @@ export function tornadoProgram() {
throw new Error('Wallet withdrawal is configured however could not find any wallets');
}
const graphApi = getProgramGraphAPI(options, config);
const Tornado = Tornado__factory.connect(instanceAddress, provider);
const TornadoProxy = TornadoRouter__factory.connect(routerContract, !walletWithdrawal ? provider : signer);
const Multicall = Multicall__factory.connect(multicallContract, provider);
@ -1016,8 +969,6 @@ export function tornadoProgram() {
const TornadoServiceConstructor = {
netId,
provider,
graphApi,
subgraphName: tornadoSubgraph,
Tornado,
amount,
currency,
@ -1107,9 +1058,7 @@ export function tornadoProgram() {
readFile(KEY_PATH).then((b) => new Uint8Array(b).buffer),
tornadoFeeOracle.gasPrice(),
tornadoFeeOracle.fetchL1OptimismFee(),
!isEth
? tokenPriceOracle.fetchPrices([{ tokenAddress: tokenAddress as string, decimals }]).then((p) => p[0])
: BigInt(0),
!isEth ? tokenPriceOracle.fetchPrice(tokenAddress as string, decimals) : BigInt(0),
]);
const { pathElements, pathIndices } = tree.path((depositEvent as DepositsEvents).leafIndex);
@ -1209,7 +1158,7 @@ export function tornadoProgram() {
? tornadoFeeOracle.calculateTokenAmount(txFee, tokenPriceInWei, decimals)
: BigInt(0);
const txFeeString = !isEth
? `( ${Number(formatUnits(txFeeInToken, decimals)).toFixed(5)} ${currency.toUpperCase()} worth )` +
? `( ${Number(formatUnits(txFeeInToken, decimals)).toFixed(5)} ${currency.toUpperCase()} worth ) ` +
`( ${((Number(formatUnits(txFeeInToken, decimals)) / Number(amount)) * 100).toFixed(5)}% )`
: `( ${((Number(formatUnits(txFee, decimals)) / Number(amount)) * 100).toFixed(5)}% )`;
@ -1311,7 +1260,6 @@ export function tornadoProgram() {
const config = getConfig(netId);
const {
tornadoSubgraph,
deployedBlock,
nativeCurrency,
tokens: { [currency]: currencyConfig },
@ -1327,14 +1275,12 @@ export function tornadoProgram() {
...fetchDataOptions,
});
const graphApi = getProgramGraphAPI(options, config);
const tovarishClient = !disableTovarish
? (await getTovarishRelayer({ options, fetchDataOptions, netId })).relayerClient
: undefined;
if (tovarishClient) {
console.log(`\nConnected with Tovarish Relayer ${tovarishClient.selectedRelayer?.url}\n`);
if (tovarishClient?.selectedRelayer) {
console.log(`\nConnected with Tovarish Relayer ${tovarishClient.selectedRelayer.url}\n`);
}
const Tornado = Tornado__factory.connect(instanceAddress, provider);
@ -1342,8 +1288,6 @@ export function tornadoProgram() {
const TornadoServiceConstructor = {
netId,
provider,
graphApi,
subgraphName: tornadoSubgraph,
Tornado,
amount,
currency,
@ -1439,14 +1383,12 @@ export function tornadoProgram() {
for (const netId of networks) {
const config = getConfig(netId);
const {
tornadoSubgraph,
registrySubgraph,
governanceSubgraph,
tokens,
nativeCurrency,
routerContract,
echoContract,
registryContract,
reverseRecordsContract,
aggregatorContract,
governanceContract,
deployedBlock,
@ -1457,23 +1399,22 @@ export function tornadoProgram() {
netId,
...fetchDataOptions,
});
const graphApi = getProgramGraphAPI(options, config);
const tovarishClient = !disableTovarish
? (await getTovarishRelayer({ options, fetchDataOptions, netId })).relayerClient
: undefined;
if (tovarishClient) {
console.log(`\nConnected with Tovarish Relayer ${tovarishClient.selectedRelayer?.url}\n`);
if (tovarishClient?.selectedRelayer) {
console.log(`\nConnected with Tovarish Relayer ${tovarishClient.selectedRelayer.url}\n`);
}
if (netId === RELAYER_NETWORK && governanceContract) {
if (netId === RELAYER_NETWORK && governanceContract && aggregatorContract && reverseRecordsContract) {
const governanceService = new NodeGovernanceService({
netId,
provider,
graphApi,
subgraphName: governanceSubgraph,
Governance: Governance__factory.connect(governanceContract, provider),
Aggregator: Aggregator__factory.connect(aggregatorContract, provider),
ReverseRecords: ReverseRecords__factory.connect(reverseRecordsContract, provider),
deployedBlock: GOVERNANCE_BLOCK,
fetchDataOptions,
tovarishClient,
@ -1488,8 +1429,6 @@ export function tornadoProgram() {
const registryService = new NodeRegistryService({
netId,
provider,
graphApi,
subgraphName: registrySubgraph,
RelayerRegistry: RelayerRegistry__factory.connect(registryContract, provider),
Aggregator: Aggregator__factory.connect(aggregatorContract, provider),
relayerEnsSubdomains: getRelayerEnsSubdomains(),
@ -1507,8 +1446,6 @@ export function tornadoProgram() {
const echoService = new NodeEchoService({
netId,
provider,
graphApi,
subgraphName: tornadoSubgraph,
Echoer: Echoer__factory.connect(echoContract, provider),
deployedBlock: NOTE_ACCOUNT_BLOCK,
fetchDataOptions,
@ -1522,8 +1459,6 @@ export function tornadoProgram() {
const encryptedNotesService = new NodeEncryptedNotesService({
netId,
provider,
graphApi,
subgraphName: tornadoSubgraph,
Router: TornadoRouter__factory.connect(routerContract, provider),
deployedBlock: ENCRYPTED_NOTES_BLOCK,
fetchDataOptions,
@ -1548,8 +1483,6 @@ export function tornadoProgram() {
const TornadoServiceConstructor = {
netId,
provider,
graphApi,
subgraphName: tornadoSubgraph,
Tornado,
amount,
currency,
@ -1680,7 +1613,6 @@ export function tornadoProgram() {
const {
echoContract,
tornadoSubgraph,
constants: { ['NOTE_ACCOUNT_BLOCK']: deployedBlock },
} = config;
@ -1694,8 +1626,6 @@ export function tornadoProgram() {
provider,
});
const graphApi = getProgramGraphAPI(options, config);
if (!signer || signer instanceof VoidSigner) {
throw new Error(
'No wallet found, make your you have supplied a valid mnemonic or private key before using this command',
@ -1706,8 +1636,8 @@ export function tornadoProgram() {
? (await getTovarishRelayer({ options, fetchDataOptions, netId })).relayerClient
: undefined;
if (tovarishClient) {
console.log(`\nConnected with Tovarish Relayer ${tovarishClient.selectedRelayer?.url}\n`);
if (tovarishClient?.selectedRelayer) {
console.log(`\nConnected with Tovarish Relayer ${tovarishClient.selectedRelayer.url}\n`);
}
/**
@ -1725,8 +1655,6 @@ export function tornadoProgram() {
const echoService = new NodeEchoService({
netId,
provider,
graphApi,
subgraphName: tornadoSubgraph,
Echoer,
deployedBlock,
fetchDataOptions,
@ -1811,7 +1739,6 @@ export function tornadoProgram() {
const {
routerContract,
echoContract,
tornadoSubgraph,
constants: { ENCRYPTED_NOTES_BLOCK },
} = config;
@ -1820,8 +1747,6 @@ export function tornadoProgram() {
...fetchDataOptions,
});
const graphApi = getProgramGraphAPI(options, config);
if (!accountKey) {
throw new Error(
'No account key find! Please supply correct account key from either UI or find one with createAccount command',
@ -1832,8 +1757,8 @@ export function tornadoProgram() {
? (await getTovarishRelayer({ options, fetchDataOptions, netId })).relayerClient
: undefined;
if (tovarishClient) {
console.log(`\nConnected with Tovarish Relayer ${tovarishClient.selectedRelayer?.url}\n`);
if (tovarishClient?.selectedRelayer) {
console.log(`\nConnected with Tovarish Relayer ${tovarishClient.selectedRelayer.url}\n`);
}
const Echoer = Echoer__factory.connect(echoContract, provider);
@ -1847,8 +1772,6 @@ export function tornadoProgram() {
const encryptedNotesService = new NodeEncryptedNotesService({
netId,
provider,
graphApi,
subgraphName: tornadoSubgraph,
Router: TornadoRouter__factory.connect(routerContract, provider),
deployedBlock: ENCRYPTED_NOTES_BLOCK,
fetchDataOptions,
@ -2139,20 +2062,228 @@ export function tornadoProgram() {
process.exit(0);
});
program
.command('proposals')
.description('Get list or detail about TORN proposal')
.argument('[proposalId]', 'Proposal ID')
.action(async (proposalId: number, cmdOptions: commonProgramOptions) => {
const { options, fetchDataOptions } = await getProgramOptions(cmdOptions);
const { rpc, disableTovarish } = options;
const netId = RELAYER_NETWORK;
const provider = await getProgramProvider(rpc, {
netId,
...fetchDataOptions,
});
const config = getConfig(netId);
const {
governanceContract,
aggregatorContract,
reverseRecordsContract,
constants: { GOVERNANCE_BLOCK },
} = config;
const tovarishClient = !disableTovarish
? (await getTovarishRelayer({ options, fetchDataOptions, netId })).relayerClient
: undefined;
if (tovarishClient?.selectedRelayer) {
console.log(`\nConnected with Tovarish Relayer ${tovarishClient.selectedRelayer.url}\n`);
}
const governanceService = new NodeGovernanceService({
netId,
provider,
Governance: Governance__factory.connect(governanceContract as string, provider),
Aggregator: Aggregator__factory.connect(aggregatorContract as string, provider),
ReverseRecords: ReverseRecords__factory.connect(reverseRecordsContract as string, provider),
deployedBlock: GOVERNANCE_BLOCK,
fetchDataOptions,
tovarishClient,
cacheDirectory: EVENTS_DIR,
userDirectory: SAVED_DIR,
});
const proposals = await governanceService.getAllProposals();
const proposal = proposals.find((p) => p.id === Number(proposalId));
if (!proposal) {
const recentProposals = proposals.reverse().slice(0, 20);
const proposalTable = new Table();
proposalTable.push(
[{ colSpan: 9, content: 'Last 20 Proposals', hAlign: 'center' }],
['ID', 'Title', 'Proposer', 'Start Time', 'End Time', 'Quorum', 'For Votes', 'Against Votes', 'State'],
...recentProposals.map(
({ id, title, proposer, proposerName, startTime, endTime, quorum, forVotes, againstVotes, state }) => {
return [
id,
title,
proposerName || proposer.slice(0, 20),
moment.unix(startTime).format('DD/MM/YYYY'),
moment.unix(endTime).format('DD/MM/YYYY'),
quorum,
numberFormatter(formatEther(forVotes)) + ' TORN',
numberFormatter(formatEther(againstVotes)) + ' TORN',
state,
];
},
),
);
console.log(proposalTable.toString());
process.exit(0);
}
proposalId = Number(proposalId);
const {
transactionHash,
proposer,
proposerName,
target,
startTime,
endTime,
description,
title,
forVotes,
againstVotes,
executed,
extended,
quorum,
state,
} = proposal;
const allVotes = forVotes + againstVotes;
const proposalTable = new Table();
proposalTable.push(
[{ colSpan: 2, content: `Proposal ${proposalId}`, hAlign: 'center' }],
['Title', title],
['Description', description],
['Proposer', proposerName || proposer],
['Proposal Address', target],
['Proposal TX', transactionHash],
['Start Time', String(moment.unix(startTime).toDate())],
['End Time', String(moment.unix(endTime).toDate())],
['For', numberFormatter(formatEther(forVotes)) + ' TORN'],
['Against', numberFormatter(formatEther(againstVotes)) + ' TORN'],
['Quorum', quorum],
['State', state],
['Extended', extended],
['Executed', executed],
);
console.log(proposalTable.toString());
const votes = await governanceService.getVotes(proposalId);
const votersSet = new Set();
const uniqueVotes = votes
.reverse()
.filter((v) => {
if (!votersSet.has(v.voter)) {
votersSet.add(v.voter);
return true;
}
return false;
})
.sort((a, b) => Number(b.votes) - Number(a.votes));
const commentTable = new Table();
commentTable.push(
[{ colSpan: 5, content: 'Votes', hAlign: 'center' }],
['Support', 'Votes', 'Voter', 'Delegate', 'Percent'],
...uniqueVotes.map(({ support, votes, voter, voterName, from, fromName }) => {
const supportStr = support ? 'For' : 'Against';
const votesStr = numberFormatter(formatEther(votes)) + ' TORN';
const delegate = voter !== from ? fromName || from.slice(0, 20) : '';
const percentage = ((Number(votes) / Number(allVotes)) * 100).toFixed(2) + '%';
return [supportStr, votesStr, voterName || voter.slice(0, 20), delegate, percentage];
}),
);
console.log(commentTable.toString());
process.exit(0);
});
program
.command('delegates')
.description('Get list of delegates to address or ens')
.argument('<address>', 'Address or ENS name to lookup for delegation')
.action(async (address: string, cmdOptions: commonProgramOptions) => {
const { options, fetchDataOptions } = await getProgramOptions(cmdOptions);
const { rpc, disableTovarish } = options;
const netId = RELAYER_NETWORK;
const provider = await getProgramProvider(rpc, {
netId,
...fetchDataOptions,
});
const config = getConfig(netId);
const {
governanceContract,
aggregatorContract,
reverseRecordsContract,
constants: { GOVERNANCE_BLOCK },
} = config;
const tovarishClient = !disableTovarish
? (await getTovarishRelayer({ options, fetchDataOptions, netId })).relayerClient
: undefined;
if (tovarishClient?.selectedRelayer) {
console.log(`\nConnected with Tovarish Relayer ${tovarishClient.selectedRelayer.url}\n`);
}
const account = address.endsWith('.eth') ? await provider._getAddress(address) : getAddress(address);
const governanceService = new NodeGovernanceService({
netId,
provider,
Governance: Governance__factory.connect(governanceContract as string, provider),
Aggregator: Aggregator__factory.connect(aggregatorContract as string, provider),
ReverseRecords: ReverseRecords__factory.connect(reverseRecordsContract as string, provider),
deployedBlock: GOVERNANCE_BLOCK,
fetchDataOptions,
tovarishClient,
cacheDirectory: EVENTS_DIR,
userDirectory: SAVED_DIR,
});
const { uniq, uniqNames, balances, balance } = await governanceService.getDelegatedBalance(account);
const delegateTable = new Table();
delegateTable.push(
[{ colSpan: 2, content: 'Delegates', hAlign: 'center' }],
['Account', account.toLowerCase() !== address.toLowerCase() ? `${address} (${account})` : address],
['Delegated Balance', formatEther(balance) + ' TORN'],
...uniq.map((acc, index) => {
return [uniqNames[acc] || acc, formatEther(balances[index]) + ' TORN'];
}),
);
console.log(delegateTable.toString());
process.exit(0);
});
// common options
program.commands.forEach((cmd) => {
cmd.option('-r, --rpc <RPC_URL>', 'The RPC that CLI should interact with', parseUrl);
cmd.option('-e, --eth-rpc <ETHRPC_URL>', 'The Ethereum Mainnet RPC that CLI should interact with', parseUrl);
cmd.option('-g, --graph <GRAPH_URL>', 'The Subgraph API that CLI should interact with', parseUrl);
cmd.option(
'-G, --eth-graph <ETHGRAPH_URL>',
'The Ethereum Mainnet Subgraph API that CLI should interact with',
parseUrl,
);
cmd.option(
'-d, --disable-graph',
'Disable Graph API - Does not enable Subgraph API and use only local RPC as an event source',
);
cmd.option(
'-a, --account-key <ACCOUNT_KEY>',
'Account key generated from UI or the createAccount to store encrypted notes on-chain',

@ -15,7 +15,6 @@ import {
BaseRegistryServiceConstructor,
BaseEchoServiceConstructor,
BaseEchoService,
DEPOSIT,
CachedRelayers,
toFixedHex,
} from '@tornado/core';
@ -28,18 +27,97 @@ import type {
AllGovernanceEvents,
EchoEvents,
MerkleTreeService,
BaseEventsService,
MinimalEvents,
} from '@tornado/core';
import { TreeCache } from './treeCache';
import { saveUserFile, loadSavedEvents, loadCachedEvents, saveLegacyFile, existsAsync } from './data';
import { saveUserFile, loadSavedEvents, loadCachedEvents, existsAsync } from './data';
export type NodeTornadoServiceConstructor = BaseTornadoServiceConstructor & {
async function getEventsFromDB<T extends MinimalEvents>(service: BaseEventsService<T> & { userDirectory: string }) {
if (!service.userDirectory) {
console.log(`Updating ${service.getInstanceName()} events\n`);
console.log(`savedEvents count - ${0}`);
console.log(`savedEvents lastBlock - ${service.deployedBlock}\n`);
return {
events: [],
lastBlock: 0,
};
}
const savedEvents = await loadSavedEvents<T>({
name: service.getInstanceName(),
userDirectory: service.userDirectory,
});
console.log(`Updating ${service.getInstanceName()} events\n`);
console.log(`savedEvents count - ${savedEvents.events.length}`);
console.log(`savedEvents lastBlock - ${savedEvents.lastBlock}\n`);
return savedEvents;
}
async function getEventsFromCache<T extends MinimalEvents>(service: BaseEventsService<T> & { cacheDirectory: string }) {
if (!service.cacheDirectory) {
console.log(`cachedEvents count - ${0}`);
console.log(`cachedEvents lastBlock - ${service.deployedBlock}\n`);
return {
events: [],
lastBlock: service.deployedBlock,
fromCache: true,
};
}
const cachedEvents = await loadCachedEvents<T>({
name: service.getInstanceName(),
cacheDirectory: service.cacheDirectory,
deployedBlock: service.deployedBlock,
});
console.log(`cachedEvents count - ${cachedEvents.events.length}`);
console.log(`cachedEvents lastBlock - ${cachedEvents.lastBlock}\n`);
return cachedEvents;
}
async function saveEvents<T extends MinimalEvents>(
service: BaseEventsService<T> & { userDirectory: string },
{ events, lastBlock }: BaseEvents<T>,
eventTable?: Table.Table,
) {
const instanceName = service.getInstanceName();
console.log('\ntotalEvents count - ', events.length);
console.log(
`totalEvents lastBlock - ${events[events.length - 1] ? events[events.length - 1].blockNumber : lastBlock}\n`,
);
if (eventTable) {
console.log(eventTable.toString() + '\n');
}
if (service.userDirectory) {
await saveUserFile({
fileName: instanceName + '.json',
userDirectory: service.userDirectory,
dataString: JSON.stringify(events, null, 2) + '\n',
});
}
}
export type NodeServiceConstructor = {
cacheDirectory: string;
userDirectory: string;
nativeCurrency: string;
merkleTreeService?: MerkleTreeService;
treeCache?: TreeCache;
};
export type NodeTornadoServiceConstructor = BaseTornadoServiceConstructor &
NodeServiceConstructor & {
nativeCurrency: string;
merkleTreeService?: MerkleTreeService;
treeCache?: TreeCache;
};
export class NodeTornadoService extends BaseTornadoService {
cacheDirectory: string;
userDirectory: string;
@ -48,37 +126,10 @@ export class NodeTornadoService extends BaseTornadoService {
merkleTreeService?: MerkleTreeService;
treeCache?: TreeCache;
constructor({
netId,
provider,
graphApi,
subgraphName,
Tornado,
type,
amount,
currency,
deployedBlock,
fetchDataOptions,
tovarishClient,
cacheDirectory,
userDirectory,
nativeCurrency,
merkleTreeService,
treeCache,
}: NodeTornadoServiceConstructor) {
super({
netId,
provider,
graphApi,
subgraphName,
Tornado,
type,
amount,
currency,
deployedBlock,
fetchDataOptions,
tovarishClient,
});
constructor(serviceConstructor: NodeTornadoServiceConstructor) {
super(serviceConstructor);
const { cacheDirectory, userDirectory, nativeCurrency, merkleTreeService, treeCache } = serviceConstructor;
this.cacheDirectory = cacheDirectory;
this.userDirectory = userDirectory;
@ -127,65 +178,23 @@ export class NodeTornadoService extends BaseTornadoService {
}
async getEventsFromDB() {
if (!this.userDirectory) {
console.log(
'Updating events for',
this.amount,
this.currency.toUpperCase(),
`${this.getType().toLowerCase()}s\n`,
);
console.log(`savedEvents count - ${0}`);
console.log(`savedEvents lastBlock - ${this.deployedBlock}\n`);
return {
events: [],
lastBlock: 0,
};
}
const savedEvents = await loadSavedEvents<DepositsEvents | WithdrawalsEvents>({
name: this.getInstanceName(),
userDirectory: this.userDirectory,
});
console.log('Updating events for', this.amount, this.currency.toUpperCase(), `${this.getType().toLowerCase()}s\n`);
console.log(`savedEvents count - ${savedEvents.events.length}`);
console.log(`savedEvents lastBlock - ${savedEvents.lastBlock}\n`);
return savedEvents;
return await getEventsFromDB<DepositsEvents | WithdrawalsEvents>(this);
}
async getEventsFromCache() {
if (!this.cacheDirectory) {
console.log(`cachedEvents count - ${0}`);
console.log(`cachedEvents lastBlock - ${this.deployedBlock}\n`);
return {
events: [],
lastBlock: this.deployedBlock,
fromCache: true,
};
}
const cachedEvents = await loadCachedEvents<DepositsEvents | WithdrawalsEvents>({
name: this.getInstanceName(),
cacheDirectory: this.cacheDirectory,
deployedBlock: this.deployedBlock,
});
console.log(`cachedEvents count - ${cachedEvents.events.length}`);
console.log(`cachedEvents lastBlock - ${cachedEvents.lastBlock}\n`);
return cachedEvents;
return await getEventsFromCache<DepositsEvents | WithdrawalsEvents>(this);
}
async saveEvents({ events, lastBlock }: BaseEvents<DepositsEvents | WithdrawalsEvents>) {
const instanceName = this.getInstanceName();
if (this.userDirectory && this.merkleTreeService) {
const tree = await this.merkleTreeService.verifyTree(events as DepositsEvents[]);
console.log('\ntotalEvents count - ', events.length);
console.log(
`totalEvents lastBlock - ${events[events.length - 1] ? events[events.length - 1].blockNumber : lastBlock}\n`,
);
if (this.currency === this.nativeCurrency && this.treeCache) {
await this.treeCache.createTree(events as DepositsEvents[], tree);
console.log(`${this.getInstanceName()}: Updated tree cache with root ${toFixedHex(BigInt(tree.root))}\n`);
}
}
const eventTable = new Table();
@ -205,85 +214,20 @@ export class NodeTornadoService extends BaseTornadoService {
}),
);
console.log(eventTable.toString() + '\n');
if (this.userDirectory) {
if (this.merkleTreeService) {
const tree = await this.merkleTreeService.verifyTree(events as DepositsEvents[]);
if (this.currency === this.nativeCurrency && this.treeCache) {
await this.treeCache.createTree(events as DepositsEvents[], tree);
console.log(`${this.getInstanceName()}: Updated tree cache with root ${toFixedHex(BigInt(tree.root))}\n`);
}
}
await saveUserFile({
fileName: instanceName + '.json',
userDirectory: this.userDirectory,
dataString: JSON.stringify(events, null, 2) + '\n',
});
if (this.getType().toLowerCase() === DEPOSIT) {
const legacyEvents = (events as DepositsEvents[]).map(
({ blockNumber, transactionHash, commitment, leafIndex, timestamp }) => ({
blockNumber,
transactionHash,
commitment,
leafIndex,
timestamp: String(timestamp),
}),
);
await saveLegacyFile({
fileName: instanceName + '.json',
userDirectory: this.userDirectory,
dataString: JSON.stringify(legacyEvents, null, 2) + '\n',
});
} else {
const legacyEvents = events as WithdrawalsEvents[];
await saveLegacyFile({
fileName: instanceName + '.json',
userDirectory: this.userDirectory,
dataString: JSON.stringify(legacyEvents, null, 2) + '\n',
});
}
}
await saveEvents<DepositsEvents | WithdrawalsEvents>(this, { events, lastBlock }, eventTable);
}
}
export type NodeEchoServiceConstructor = BaseEchoServiceConstructor & {
cacheDirectory: string;
userDirectory: string;
};
export type NodeEchoServiceConstructor = BaseEchoServiceConstructor & NodeServiceConstructor;
export class NodeEchoService extends BaseEchoService {
cacheDirectory: string;
userDirectory: string;
constructor({
netId,
provider,
graphApi,
subgraphName,
Echoer,
deployedBlock,
fetchDataOptions,
tovarishClient,
cacheDirectory,
userDirectory,
}: NodeEchoServiceConstructor) {
super({
netId,
provider,
graphApi,
subgraphName,
Echoer,
deployedBlock,
fetchDataOptions,
tovarishClient,
});
constructor(serviceConstructor: NodeEchoServiceConstructor) {
super(serviceConstructor);
const { cacheDirectory, userDirectory } = serviceConstructor;
this.cacheDirectory = cacheDirectory;
this.userDirectory = userDirectory;
@ -316,61 +260,14 @@ export class NodeEchoService extends BaseEchoService {
}
async getEventsFromDB() {
if (!this.userDirectory) {
console.log(`Updating events for ${this.netId} chain echo events\n`);
console.log(`savedEvents count - ${0}`);
console.log(`savedEvents lastBlock - ${this.deployedBlock}\n`);
return {
events: [],
lastBlock: 0,
};
}
const savedEvents = await loadSavedEvents<EchoEvents>({
name: this.getInstanceName(),
userDirectory: this.userDirectory,
});
console.log(`Updating events for ${this.netId} chain echo events\n`);
console.log(`savedEvents count - ${savedEvents.events.length}`);
console.log(`savedEvents lastBlock - ${savedEvents.lastBlock}\n`);
return savedEvents;
return await getEventsFromDB<EchoEvents>(this);
}
async getEventsFromCache() {
if (!this.cacheDirectory) {
console.log(`cachedEvents count - ${0}`);
console.log(`cachedEvents lastBlock - ${this.deployedBlock}\n`);
return {
events: [],
lastBlock: this.deployedBlock,
fromCache: true,
};
}
const cachedEvents = await loadCachedEvents<EchoEvents>({
name: this.getInstanceName(),
cacheDirectory: this.cacheDirectory,
deployedBlock: this.deployedBlock,
});
console.log(`cachedEvents count - ${cachedEvents.events.length}`);
console.log(`cachedEvents lastBlock - ${cachedEvents.lastBlock}\n`);
return cachedEvents;
return await getEventsFromCache<EchoEvents>(this);
}
async saveEvents({ events, lastBlock }: BaseEvents<EchoEvents>) {
const instanceName = this.getInstanceName();
console.log('\ntotalEvents count - ', events.length);
console.log(
`totalEvents lastBlock - ${events[events.length - 1] ? events[events.length - 1].blockNumber : lastBlock}\n`,
);
const eventTable = new Table();
eventTable.push(
@ -388,49 +285,20 @@ export class NodeEchoService extends BaseEchoService {
}),
);
console.log(eventTable.toString() + '\n');
if (this.userDirectory) {
await saveUserFile({
fileName: instanceName + '.json',
userDirectory: this.userDirectory,
dataString: JSON.stringify(events, null, 2) + '\n',
});
}
await saveEvents<EchoEvents>(this, { events, lastBlock }, eventTable);
}
}
export type NodeEncryptedNotesServiceConstructor = BaseEncryptedNotesServiceConstructor & {
cacheDirectory: string;
userDirectory: string;
};
export type NodeEncryptedNotesServiceConstructor = BaseEncryptedNotesServiceConstructor & NodeServiceConstructor;
export class NodeEncryptedNotesService extends BaseEncryptedNotesService {
cacheDirectory: string;
userDirectory: string;
constructor({
netId,
provider,
graphApi,
subgraphName,
Router,
deployedBlock,
fetchDataOptions,
tovarishClient,
cacheDirectory,
userDirectory,
}: NodeEncryptedNotesServiceConstructor) {
super({
netId,
provider,
graphApi,
subgraphName,
Router,
deployedBlock,
fetchDataOptions,
tovarishClient,
});
constructor(serviceConstructor: NodeEncryptedNotesServiceConstructor) {
super(serviceConstructor);
const { cacheDirectory, userDirectory } = serviceConstructor;
this.cacheDirectory = cacheDirectory;
this.userDirectory = userDirectory;
@ -463,61 +331,14 @@ export class NodeEncryptedNotesService extends BaseEncryptedNotesService {
}
async getEventsFromDB() {
if (!this.userDirectory) {
console.log(`Updating events for ${this.netId} chain encrypted events\n`);
console.log(`savedEvents count - ${0}`);
console.log(`savedEvents lastBlock - ${this.deployedBlock}\n`);
return {
events: [],
lastBlock: 0,
};
}
const savedEvents = await loadSavedEvents<EncryptedNotesEvents>({
name: this.getInstanceName(),
userDirectory: this.userDirectory,
});
console.log(`Updating events for ${this.netId} chain encrypted events\n`);
console.log(`savedEvents count - ${savedEvents.events.length}`);
console.log(`savedEvents lastBlock - ${savedEvents.lastBlock}\n`);
return savedEvents;
return await getEventsFromDB<EncryptedNotesEvents>(this);
}
async getEventsFromCache() {
if (!this.cacheDirectory) {
console.log(`cachedEvents count - ${0}`);
console.log(`cachedEvents lastBlock - ${this.deployedBlock}\n`);
return {
events: [],
lastBlock: this.deployedBlock,
fromCache: true,
};
}
const cachedEvents = await loadCachedEvents<EncryptedNotesEvents>({
name: this.getInstanceName(),
cacheDirectory: this.cacheDirectory,
deployedBlock: this.deployedBlock,
});
console.log(`cachedEvents count - ${cachedEvents.events.length}`);
console.log(`cachedEvents lastBlock - ${cachedEvents.lastBlock}\n`);
return cachedEvents;
return await getEventsFromCache<EncryptedNotesEvents>(this);
}
async saveEvents({ events, lastBlock }: BaseEvents<EncryptedNotesEvents>) {
const instanceName = this.getInstanceName();
console.log('\ntotalEvents count - ', events.length);
console.log(
`totalEvents lastBlock - ${events[events.length - 1] ? events[events.length - 1].blockNumber : lastBlock}\n`,
);
const eventTable = new Table();
eventTable.push(
@ -535,61 +356,20 @@ export class NodeEncryptedNotesService extends BaseEncryptedNotesService {
}),
);
console.log(eventTable.toString() + '\n');
if (this.userDirectory) {
await saveUserFile({
fileName: instanceName + '.json',
userDirectory: this.userDirectory,
dataString: JSON.stringify(events, null, 2) + '\n',
});
const legacyEvents = events.map(({ transactionHash, blockNumber, encryptedNote }) => ({
txHash: transactionHash,
blockNumber,
encryptedNote,
}));
await saveLegacyFile({
fileName: instanceName + '.json',
userDirectory: this.userDirectory,
dataString: JSON.stringify(legacyEvents, null, 2) + '\n',
});
}
await saveEvents<EncryptedNotesEvents>(this, { events, lastBlock }, eventTable);
}
}
export type NodeGovernanceServiceConstructor = BaseGovernanceServiceConstructor & {
cacheDirectory: string;
userDirectory: string;
};
export type NodeGovernanceServiceConstructor = BaseGovernanceServiceConstructor & NodeServiceConstructor;
export class NodeGovernanceService extends BaseGovernanceService {
cacheDirectory: string;
userDirectory: string;
constructor({
netId,
provider,
graphApi,
subgraphName,
Governance,
deployedBlock,
fetchDataOptions,
tovarishClient,
cacheDirectory,
userDirectory,
}: NodeGovernanceServiceConstructor) {
super({
netId,
provider,
graphApi,
subgraphName,
Governance,
deployedBlock,
fetchDataOptions,
tovarishClient,
});
constructor(serviceConstructor: NodeGovernanceServiceConstructor) {
super(serviceConstructor);
const { cacheDirectory, userDirectory } = serviceConstructor;
this.cacheDirectory = cacheDirectory;
this.userDirectory = userDirectory;
@ -628,61 +408,14 @@ export class NodeGovernanceService extends BaseGovernanceService {
}
async getEventsFromDB() {
if (!this.userDirectory) {
console.log(`Updating events for ${this.netId} chain governance events\n`);
console.log(`savedEvents count - ${0}`);
console.log(`savedEvents lastBlock - ${this.deployedBlock}\n`);
return {
events: [],
lastBlock: 0,
};
}
const savedEvents = await loadSavedEvents<AllGovernanceEvents>({
name: this.getInstanceName(),
userDirectory: this.userDirectory,
});
console.log(`Updating events for ${this.netId} chain governance events\n`);
console.log(`savedEvents count - ${savedEvents.events.length}`);
console.log(`savedEvents lastBlock - ${savedEvents.lastBlock}\n`);
return savedEvents;
return await getEventsFromDB<AllGovernanceEvents>(this);
}
async getEventsFromCache() {
if (!this.cacheDirectory) {
console.log(`cachedEvents count - ${0}`);
console.log(`cachedEvents lastBlock - ${this.deployedBlock}\n`);
return {
events: [],
lastBlock: this.deployedBlock,
fromCache: true,
};
}
const cachedEvents = await loadCachedEvents<AllGovernanceEvents>({
name: this.getInstanceName(),
cacheDirectory: this.cacheDirectory,
deployedBlock: this.deployedBlock,
});
console.log(`cachedEvents count - ${cachedEvents.events.length}`);
console.log(`cachedEvents lastBlock - ${cachedEvents.lastBlock}\n`);
return cachedEvents;
return await getEventsFromCache<AllGovernanceEvents>(this);
}
async saveEvents({ events, lastBlock }: BaseEvents<AllGovernanceEvents>) {
const instanceName = this.getInstanceName();
console.log('\ntotalEvents count - ', events.length);
console.log(
`totalEvents lastBlock - ${events[events.length - 1] ? events[events.length - 1].blockNumber : lastBlock}\n`,
);
const eventTable = new Table();
eventTable.push(
@ -700,53 +433,20 @@ export class NodeGovernanceService extends BaseGovernanceService {
}),
);
console.log(eventTable.toString() + '\n');
if (this.userDirectory) {
await saveUserFile({
fileName: instanceName + '.json',
userDirectory: this.userDirectory,
dataString: JSON.stringify(events, null, 2) + '\n',
});
}
await saveEvents<AllGovernanceEvents>(this, { events, lastBlock }, eventTable);
}
}
export type NodeRegistryServiceConstructor = BaseRegistryServiceConstructor & {
cacheDirectory: string;
userDirectory: string;
};
export type NodeRegistryServiceConstructor = BaseRegistryServiceConstructor & NodeServiceConstructor;
export class NodeRegistryService extends BaseRegistryService {
cacheDirectory: string;
userDirectory: string;
constructor({
netId,
provider,
graphApi,
subgraphName,
RelayerRegistry,
Aggregator,
relayerEnsSubdomains,
deployedBlock,
fetchDataOptions,
tovarishClient,
cacheDirectory,
userDirectory,
}: NodeRegistryServiceConstructor) {
super({
netId,
provider,
graphApi,
subgraphName,
RelayerRegistry,
Aggregator,
relayerEnsSubdomains,
deployedBlock,
fetchDataOptions,
tovarishClient,
});
constructor(serviceConstructor: NodeRegistryServiceConstructor) {
super(serviceConstructor);
const { cacheDirectory, userDirectory } = serviceConstructor;
this.cacheDirectory = cacheDirectory;
this.userDirectory = userDirectory;
@ -779,61 +479,14 @@ export class NodeRegistryService extends BaseRegistryService {
}
async getEventsFromDB() {
if (!this.userDirectory) {
console.log(`Updating events for ${this.netId} chain registry events\n`);
console.log(`savedEvents count - ${0}`);
console.log(`savedEvents lastBlock - ${this.deployedBlock}\n`);
return {
events: [],
lastBlock: 0,
};
}
const savedEvents = await loadSavedEvents<RegistersEvents>({
name: this.getInstanceName(),
userDirectory: this.userDirectory,
});
console.log(`Updating events for ${this.netId} chain registry events\n`);
console.log(`savedEvents count - ${savedEvents.events.length}`);
console.log(`savedEvents lastBlock - ${savedEvents.lastBlock}\n`);
return savedEvents;
return await getEventsFromDB<RegistersEvents>(this);
}
async getEventsFromCache() {
if (!this.cacheDirectory) {
console.log(`cachedEvents count - ${0}`);
console.log(`cachedEvents lastBlock - ${this.deployedBlock}\n`);
return {
events: [],
lastBlock: this.deployedBlock,
fromCache: true,
};
}
const cachedEvents = await loadCachedEvents<RegistersEvents>({
name: this.getInstanceName(),
cacheDirectory: this.cacheDirectory,
deployedBlock: this.deployedBlock,
});
console.log(`cachedEvents count - ${cachedEvents.events.length}`);
console.log(`cachedEvents lastBlock - ${cachedEvents.lastBlock}\n`);
return cachedEvents;
return await getEventsFromCache<RegistersEvents>(this);
}
async saveEvents({ events, lastBlock }: BaseEvents<RegistersEvents>) {
const instanceName = this.getInstanceName();
console.log('\ntotalEvents count - ', events.length);
console.log(
`totalEvents lastBlock - ${events[events.length - 1] ? events[events.length - 1].blockNumber : lastBlock}\n`,
);
const eventTable = new Table();
eventTable.push(
@ -851,15 +504,7 @@ export class NodeRegistryService extends BaseRegistryService {
}),
);
console.log(eventTable.toString() + '\n');
if (this.userDirectory) {
await saveUserFile({
fileName: instanceName + '.json',
userDirectory: this.userDirectory,
dataString: JSON.stringify(events, null, 2) + '\n',
});
}
await saveEvents<RegistersEvents>(this, { events, lastBlock }, eventTable);
}
async getRelayersFromDB(): Promise<CachedRelayers> {

@ -22,7 +22,6 @@
"ensName": "therelayer.eth",
"relayerAddress": "0xA0F0287683E820FF4211e67C03cf46a87431f4E1",
"isRegistered": true,
"owner": "0xA0F0287683E820FF4211e67C03cf46a87431f4E1",
"stakeBalance": "1335.888771359625809238",
"hostnames": {
"1": "mainnet.therelayer.xyz",
@ -38,7 +37,6 @@
"ensName": "cheap-relayer.eth",
"relayerAddress": "0x076D4E32C6A5D888fC4658281539c94E778C796d",
"isRegistered": true,
"owner": "0x076D4E32C6A5D888fC4658281539c94E778C796d",
"stakeBalance": "500.878420081833044818",
"hostnames": {
"1": "mainnet-tornado.cheap-relayer.xyz",
@ -51,7 +49,6 @@
"ensName": "lowcost.eth",
"relayerAddress": "0x28907F21F43B419F34226d6f10aCbCf1832b1D4d",
"isRegistered": true,
"owner": "0x28907F21F43B419F34226d6f10aCbCf1832b1D4d",
"stakeBalance": "500.279638085962965981",
"hostnames": {
"1": "mainnet-tornado.low-fee.xyz",
@ -64,7 +61,6 @@
"ensName": "relayernews.eth",
"relayerAddress": "0x6289C8a70EE2Ed6914834CaEa431F9a82c7eAf70",
"isRegistered": true,
"owner": "0x6289C8a70EE2Ed6914834CaEa431F9a82c7eAf70",
"stakeBalance": "1661.181918638614466424",
"hostnames": {
"1": "mainnet-tornado.relayernews.xyz",
@ -75,7 +71,6 @@
"ensName": "on-sale.eth",
"relayerAddress": "0x63606C4011e97a73BCd844Cde6a38D45a728BC0E",
"isRegistered": true,
"owner": "0x63606C4011e97a73BCd844Cde6a38D45a728BC0E",
"stakeBalance": "4476.543684932880020592",
"hostnames": {
"1": "mainnet-tornado.appleworld.club",
@ -86,7 +81,6 @@
"ensName": "em3tornado.eth",
"relayerAddress": "0x3a1d526D09b7E59Fd88De4726f68A8246dDC2742",
"isRegistered": true,
"owner": "0x3a1d526D09b7E59Fd88De4726f68A8246dDC2742",
"stakeBalance": "16864.242955629118561145",
"hostnames": {
"1": "em3torn.com",
@ -101,7 +95,6 @@
"ensName": "reslayer.eth",
"relayerAddress": "0x7Ba6781620c91676B070D319E7E894BFd4A9eC81",
"isRegistered": true,
"owner": "0x7Ba6781620c91676B070D319E7E894BFd4A9eC81",
"stakeBalance": "879.305690438201312145",
"hostnames": {
"1": "mainnet-tornado.reslayer.xyz",
@ -116,7 +109,6 @@
"ensName": "0xtorn.eth",
"relayerAddress": "0x9Ffbd3f9eE795A4fDa880ED553A2A4BD6D45CE5B",
"isRegistered": true,
"owner": "0x9Ffbd3f9eE795A4fDa880ED553A2A4BD6D45CE5B",
"stakeBalance": "4627.036617270139345308",
"hostnames": {
"1": "mainnet.al1n.cc",
@ -127,7 +119,6 @@
"ensName": "wetez.eth",
"relayerAddress": "0xe6184DA55174Cc0263a17eA2fc24E48511766505",
"isRegistered": true,
"owner": "0xe6184DA55174Cc0263a17eA2fc24E48511766505",
"stakeBalance": "567.980734786905511868",
"hostnames": {
"1": "tornado-1.wetez.io"
@ -137,7 +128,6 @@
"ensName": "0xproxy.eth",
"relayerAddress": "0x08657a1f4C1F06d657F31767831421EE7FaDf549",
"isRegistered": true,
"owner": "0x08657a1f4C1F06d657F31767831421EE7FaDf549",
"stakeBalance": "705.605817336537209483",
"hostnames": {
"1": "mainnet.0x0relayer.xyz",
@ -149,7 +139,6 @@
"ensName": "torn-eth.eth",
"relayerAddress": "0x42FecB4137aFF76E0E85702ff4F339DbFe6D859E",
"isRegistered": true,
"owner": "0x42FecB4137aFF76E0E85702ff4F339DbFe6D859E",
"stakeBalance": "978.62598484549460861",
"hostnames": {
"1": "mainnet-tornado.50swap.com"
@ -159,7 +148,6 @@
"ensName": "shadow-out.eth",
"relayerAddress": "0x9Ee26a4bFd731E8e742B65bF955814EADdd7F151",
"isRegistered": true,
"owner": "0x9Ee26a4bFd731E8e742B65bF955814EADdd7F151",
"stakeBalance": "3571.639136672079169166",
"hostnames": {
"1": "livetobecomeavillain",
@ -171,7 +159,6 @@
"ensName": "bitah.eth",
"relayerAddress": "0x7E3893725d4e238B4c8c83375bBAd024a66Ffa42",
"isRegistered": true,
"owner": "0x7E3893725d4e238B4c8c83375bBAd024a66Ffa42",
"stakeBalance": "503.237718892072788154",
"hostnames": {
"1": "tornado.bitah.link",
@ -183,7 +170,6 @@
"ensName": "torntorn.eth",
"relayerAddress": "0x1247749d7E28D357B4279110af0802603AC526cE",
"isRegistered": true,
"owner": "0x1247749d7E28D357B4279110af0802603AC526cE",
"stakeBalance": "5535.435044583932530913",
"hostnames": {
"1": "eth.fsdhreu39jfk.com",
@ -196,7 +182,6 @@
"ensName": "secure-relay.eth",
"relayerAddress": "0x1036AF02bCDb2e3A4db2d3D40b29e5054EDc79BA",
"isRegistered": true,
"owner": "0x1036AF02bCDb2e3A4db2d3D40b29e5054EDc79BA",
"stakeBalance": "6751.661507930994067422",
"hostnames": {
"1": "torn-relayer.duckdns.org"
@ -206,8 +191,7 @@
"ensName": "relayer007.eth",
"relayerAddress": "0xa0109274F53609f6Be97ec5f3052C659AB80f012",
"isRegistered": true,
"owner": "0xa0109274F53609f6Be97ec5f3052C659AB80f012",
"stakeBalance": "2075.677151387681021207",
"stakeBalance": "764.494558928255909552",
"hostnames": {
"1": "torn.relayersdao.finance",
"56": "bsc.relayersdao.finance",
@ -218,8 +202,7 @@
"ensName": "reltor.eth",
"relayerAddress": "0x4750BCfcC340AA4B31be7e71fa072716d28c29C5",
"isRegistered": true,
"owner": "0x4750BCfcC340AA4B31be7e71fa072716d28c29C5",
"stakeBalance": "17078.896444585792890283",
"stakeBalance": "17277.123317072861115346",
"hostnames": {
"1": "eth.reltor.su",
"56": "binance.reltor.su",
@ -230,8 +213,7 @@
"ensName": "t-relayer.eth",
"relayerAddress": "0x000000Cd6521Ed1a65FAe0678eA15aF4EEAD74fe",
"isRegistered": true,
"owner": "0x000000Cd6521Ed1a65FAe0678eA15aF4EEAD74fe",
"stakeBalance": "9393.81613250700489948",
"stakeBalance": "10559.144467425443459818",
"hostnames": {
"1": "eth.t-relayer.com",
"56": "bsc.t-relayer.com"
@ -241,8 +223,7 @@
"ensName": "default-relayer.eth",
"relayerAddress": "0x5555555731006f71f121144534Ca7C8799F66AA3",
"isRegistered": true,
"owner": "0x5555555731006f71f121144534Ca7C8799F66AA3",
"stakeBalance": "12244.203047120053584442",
"stakeBalance": "11444.187984222270256832",
"hostnames": {
"1": "eth.default-relayer.com",
"56": "bsc.default-relayer.com"
@ -252,7 +233,6 @@
"ensName": "relayer-secure.eth",
"relayerAddress": "0xCEdac436cEA98E93F471331eCC693fF41D730921",
"isRegistered": true,
"owner": "0xCEdac436cEA98E93F471331eCC693fF41D730921",
"stakeBalance": "548.198082306127582623",
"hostnames": {
"1": "relsecc-mainnet.moon-relayer.app"
@ -262,8 +242,7 @@
"ensName": "0xgm777.eth",
"relayerAddress": "0x94596B6A626392F5D972D6CC4D929a42c2f0008c",
"isRegistered": true,
"owner": "0x94596B6A626392F5D972D6CC4D929a42c2f0008c",
"stakeBalance": "1649.22629774180421325",
"stakeBalance": "2842.234800942323658403",
"hostnames": {
"1": "main.gm777.xyz",
"56": "bsc.gm777.xyz",
@ -274,8 +253,7 @@
"ensName": "k-relayer.eth",
"relayerAddress": "0xC49415493eB3Ec64a0F13D8AA5056f1CfC4ce35c",
"isRegistered": true,
"owner": "0xC49415493eB3Ec64a0F13D8AA5056f1CfC4ce35c",
"stakeBalance": "2392.026618435010858225",
"stakeBalance": "7511.750002576918870401",
"hostnames": {
"1": "black-hardy.com",
"56": "bsc.black-hardy.com"
@ -285,7 +263,6 @@
"ensName": "tornxdo.eth",
"relayerAddress": "0xB399aa4c2F1678f72529Cd125F82cEA2c2a823eD",
"isRegistered": true,
"owner": "0xB399aa4c2F1678f72529Cd125F82cEA2c2a823eD",
"stakeBalance": "983.310689667160962345",
"hostnames": {
"1": "tornado.evmjunkie.xyz"
@ -295,8 +272,7 @@
"ensName": "torrelayer.eth",
"relayerAddress": "0x2Ee39Ff05643bC7cc9ed31B71e142429044A425C",
"isRegistered": true,
"owner": "0x2Ee39Ff05643bC7cc9ed31B71e142429044A425C",
"stakeBalance": "4150.327987173762878437",
"stakeBalance": "4027.950194967008042155",
"hostnames": {
"1": "tornima.xyz",
"56": "binance.tornima.xyz"
@ -306,8 +282,7 @@
"ensName": "torn-city.eth",
"relayerAddress": "0xd04e9f0945DEA8373D882C730e2c93a74B591796",
"isRegistered": true,
"owner": "0xd04e9f0945DEA8373D882C730e2c93a74B591796",
"stakeBalance": "6636.564618899564311691",
"stakeBalance": "5690.913065974717568893",
"hostnames": {
"1": "torn-city.com",
"56": "bsc.torn-city.com"
@ -317,7 +292,6 @@
"ensName": "crelayer.eth",
"relayerAddress": "0x180c58B7305152357142b33Eea94cBB152058B61",
"isRegistered": true,
"owner": "0x180c58B7305152357142b33Eea94cBB152058B61",
"stakeBalance": "1460.389956347917729137",
"hostnames": {
"1": "eth.crelayer.xyz",
@ -328,7 +302,6 @@
"ensName": "best-relay.eth",
"relayerAddress": "0xe5A4c70113b90566BC5f80a3866935d0d52F990E",
"isRegistered": true,
"owner": "0xe5A4c70113b90566BC5f80a3866935d0d52F990E",
"stakeBalance": "2002.0",
"hostnames": {
"1": "best-relay.gato-miaouw.xyz",
@ -339,7 +312,6 @@
"ensName": "safety-relayer.eth",
"relayerAddress": "0xF1F4F76c9969eFbFB5C9A90a6E44c0E3696D3EF8",
"isRegistered": true,
"owner": "0xF1F4F76c9969eFbFB5C9A90a6E44c0E3696D3EF8",
"stakeBalance": "500.879215977529089999",
"hostnames": {
"1": "a-relayer.top",
@ -351,7 +323,6 @@
"ensName": "quick-relayer.eth",
"relayerAddress": "0x187541D7D312F742040f270d0221B4Fe577934B0",
"isRegistered": true,
"owner": "0x187541D7D312F742040f270d0221B4Fe577934B0",
"stakeBalance": "2931.033250737658918569",
"hostnames": {
"1": "quick-relayer.xyz"
@ -361,8 +332,7 @@
"ensName": "okrelayer.eth",
"relayerAddress": "0x0e9D9a828247F5eed7f6D31D213A39805De52441",
"isRegistered": true,
"owner": "0x0e9D9a828247F5eed7f6D31D213A39805De52441",
"stakeBalance": "4668.726167448982243314",
"stakeBalance": "5024.542182980585875232",
"hostnames": {
"1": "okrelayer.xyz",
"56": "binance.okrelayer.xyz",
@ -374,8 +344,7 @@
"ensName": "s-relayer.eth",
"relayerAddress": "0xc6398b4e8B60720051ed33f5C5a692f9785f5580",
"isRegistered": true,
"owner": "0xc6398b4e8B60720051ed33f5C5a692f9785f5580",
"stakeBalance": "5000.0",
"stakeBalance": "3945.162714534474821251",
"hostnames": {
"1": "s-relayer.xyz"
}

@ -15,7 +15,7 @@
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
/* Language and Environment */
"target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
"target": "es2022", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
// "jsx": "preserve", /* Specify what JSX code is generated. */
// "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */

@ -6,7 +6,7 @@ const esbuildLoader = {
loader: 'esbuild-loader',
options: {
loader: 'ts',
target: 'es2016',
target: 'es2022',
}
}

152
yarn.lock

@ -777,21 +777,20 @@
"@noble/hashes" "~1.4.0"
"@scure/base" "~1.1.6"
"@tornado/contracts@^1.0.1":
version "1.0.1"
resolved "https://git.tornado.ws/api/packages/tornado-packages/npm/%40tornado%2Fcontracts/-/1.0.1/contracts-1.0.1.tgz#4ce0bb721c602155f087bc5526afb22b2dd05b31"
integrity sha512-5PHi2y/WybAF4uMjLenOEtqmaJ+sHkGYJJ9bHlOPlzbKooVzqVPpESKg1MEjofSpTLGG8XZAKEsXedyHX7+6qw==
"@tornado/contracts@git+https://git.tornado.ws/tornadocontrib/tornado-contracts.git#ece511f424dc811c3aec149a4bf0e3731c0598a4":
version "1.0.2"
resolved "git+https://git.tornado.ws/tornadocontrib/tornado-contracts.git#ece511f424dc811c3aec149a4bf0e3731c0598a4"
dependencies:
"@openzeppelin/contracts" "5.0.2"
"@openzeppelin/contracts-v3" "npm:@openzeppelin/contracts@3.2.0-rc.0"
ethers "^6.4.0"
ethers "^6.13.4"
"@tornado/core@git+https://git.tornado.ws/tornadocontrib/tornado-core.git#4f0aaea790ff26bb8902bbf60f101ec240704685":
"@tornado/core@git+https://git.tornado.ws/tornadocontrib/tornado-core.git#ddf306a835a0907eed1a2a7aab4ed41e34fd9037":
version "1.0.19"
resolved "git+https://git.tornado.ws/tornadocontrib/tornado-core.git#4f0aaea790ff26bb8902bbf60f101ec240704685"
resolved "git+https://git.tornado.ws/tornadocontrib/tornado-core.git#ddf306a835a0907eed1a2a7aab4ed41e34fd9037"
dependencies:
"@metamask/eth-sig-util" "^7.0.3"
"@tornado/contracts" "^1.0.1"
"@tornado/contracts" "git+https://git.tornado.ws/tornadocontrib/tornado-contracts.git#ece511f424dc811c3aec149a4bf0e3731c0598a4"
"@tornado/fixed-merkle-tree" "^0.7.3"
"@tornado/snarkjs" "^0.1.20"
"@tornado/websnark" "^0.0.4"
@ -799,7 +798,7 @@
bn.js "^5.2.1"
circomlibjs "0.1.7"
cross-fetch "^4.0.0"
ethers "^6.13.3"
ethers "^6.13.4"
ffjavascript "0.2.48"
fflate "^0.8.2"
idb "^8.0.0"
@ -896,72 +895,74 @@
dependencies:
undici-types "~6.19.2"
"@types/node@18.15.13":
version "18.15.13"
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.15.13.tgz#f64277c341150c979e42b00e4ac289290c9df469"
integrity sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==
"@types/node@22.7.5":
version "22.7.5"
resolved "https://registry.yarnpkg.com/@types/node/-/node-22.7.5.tgz#cfde981727a7ab3611a481510b473ae54442b92b"
integrity sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==
dependencies:
undici-types "~6.19.2"
"@types/prettier@^2.1.1":
version "2.7.3"
resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.3.tgz#3e51a17e291d01d17d3fc61422015a933af7a08f"
integrity sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==
"@typescript-eslint/eslint-plugin@^8.8.1":
version "8.8.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.8.1.tgz#9364b756d4d78bcbdf6fd3e9345e6924c68ad371"
integrity sha512-xfvdgA8AP/vxHgtgU310+WBnLB4uJQ9XdyP17RebG26rLtDrQJV3ZYrcopX91GrHmMoH8bdSwMRh2a//TiJ1jQ==
"@typescript-eslint/eslint-plugin@^8.9.0":
version "8.9.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.9.0.tgz#bf0b25305b0bf014b4b194a6919103d7ac2a7907"
integrity sha512-Y1n621OCy4m7/vTXNlCbMVp87zSd7NH0L9cXD8aIpOaNlzeWxIK4+Q19A68gSmTNRZn92UjocVUWDthGxtqHFg==
dependencies:
"@eslint-community/regexpp" "^4.10.0"
"@typescript-eslint/scope-manager" "8.8.1"
"@typescript-eslint/type-utils" "8.8.1"
"@typescript-eslint/utils" "8.8.1"
"@typescript-eslint/visitor-keys" "8.8.1"
"@typescript-eslint/scope-manager" "8.9.0"
"@typescript-eslint/type-utils" "8.9.0"
"@typescript-eslint/utils" "8.9.0"
"@typescript-eslint/visitor-keys" "8.9.0"
graphemer "^1.4.0"
ignore "^5.3.1"
natural-compare "^1.4.0"
ts-api-utils "^1.3.0"
"@typescript-eslint/parser@^8.8.1":
version "8.8.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.8.1.tgz#5952ba2a83bd52024b872f3fdc8ed2d3636073b8"
integrity sha512-hQUVn2Lij2NAxVFEdvIGxT9gP1tq2yM83m+by3whWFsWC+1y8pxxxHUFE1UqDu2VsGi2i6RLcv4QvouM84U+ow==
"@typescript-eslint/parser@^8.9.0":
version "8.9.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.9.0.tgz#0cecda6def8aef95d7c7098359c0fda5a362d6ad"
integrity sha512-U+BLn2rqTTHnc4FL3FJjxaXptTxmf9sNftJK62XLz4+GxG3hLHm/SUNaaXP5Y4uTiuYoL5YLy4JBCJe3+t8awQ==
dependencies:
"@typescript-eslint/scope-manager" "8.8.1"
"@typescript-eslint/types" "8.8.1"
"@typescript-eslint/typescript-estree" "8.8.1"
"@typescript-eslint/visitor-keys" "8.8.1"
"@typescript-eslint/scope-manager" "8.9.0"
"@typescript-eslint/types" "8.9.0"
"@typescript-eslint/typescript-estree" "8.9.0"
"@typescript-eslint/visitor-keys" "8.9.0"
debug "^4.3.4"
"@typescript-eslint/scope-manager@8.8.1":
version "8.8.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.8.1.tgz#b4bea1c0785aaebfe3c4ab059edaea1c4977e7ff"
integrity sha512-X4JdU+66Mazev/J0gfXlcC/dV6JI37h+93W9BRYXrSn0hrE64IoWgVkO9MSJgEzoWkxONgaQpICWg8vAN74wlA==
"@typescript-eslint/scope-manager@8.9.0":
version "8.9.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.9.0.tgz#c98fef0c4a82a484e6a1eb610a55b154d14d46f3"
integrity sha512-bZu9bUud9ym1cabmOYH9S6TnbWRzpklVmwqICeOulTCZ9ue2/pczWzQvt/cGj2r2o1RdKoZbuEMalJJSYw3pHQ==
dependencies:
"@typescript-eslint/types" "8.8.1"
"@typescript-eslint/visitor-keys" "8.8.1"
"@typescript-eslint/types" "8.9.0"
"@typescript-eslint/visitor-keys" "8.9.0"
"@typescript-eslint/type-utils@8.8.1":
version "8.8.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.8.1.tgz#31f59ec46e93a02b409fb4d406a368a59fad306e"
integrity sha512-qSVnpcbLP8CALORf0za+vjLYj1Wp8HSoiI8zYU5tHxRVj30702Z1Yw4cLwfNKhTPWp5+P+k1pjmD5Zd1nhxiZA==
"@typescript-eslint/type-utils@8.9.0":
version "8.9.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.9.0.tgz#aa86da3e4555fe7c8b42ab75e13561c4b5a8dfeb"
integrity sha512-JD+/pCqlKqAk5961vxCluK+clkppHY07IbV3vett97KOV+8C6l+CPEPwpUuiMwgbOz/qrN3Ke4zzjqbT+ls+1Q==
dependencies:
"@typescript-eslint/typescript-estree" "8.8.1"
"@typescript-eslint/utils" "8.8.1"
"@typescript-eslint/typescript-estree" "8.9.0"
"@typescript-eslint/utils" "8.9.0"
debug "^4.3.4"
ts-api-utils "^1.3.0"
"@typescript-eslint/types@8.8.1":
version "8.8.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.8.1.tgz#ebe85e0fa4a8e32a24a56adadf060103bef13bd1"
integrity sha512-WCcTP4SDXzMd23N27u66zTKMuEevH4uzU8C9jf0RO4E04yVHgQgW+r+TeVTNnO1KIfrL8ebgVVYYMMO3+jC55Q==
"@typescript-eslint/types@8.9.0":
version "8.9.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.9.0.tgz#b733af07fb340b32e962c6c63b1062aec2dc0fe6"
integrity sha512-SjgkvdYyt1FAPhU9c6FiYCXrldwYYlIQLkuc+LfAhCna6ggp96ACncdtlbn8FmnG72tUkXclrDExOpEYf1nfJQ==
"@typescript-eslint/typescript-estree@8.8.1":
version "8.8.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.8.1.tgz#34649f4e28d32ee49152193bc7dedc0e78e5d1ec"
integrity sha512-A5d1R9p+X+1js4JogdNilDuuq+EHZdsH9MjTVxXOdVFfTJXunKJR/v+fNNyO4TnoOn5HqobzfRlc70NC6HTcdg==
"@typescript-eslint/typescript-estree@8.9.0":
version "8.9.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.9.0.tgz#1714f167e9063062dc0df49c1d25afcbc7a96199"
integrity sha512-9iJYTgKLDG6+iqegehc5+EqE6sqaee7kb8vWpmHZ86EqwDjmlqNNHeqDVqb9duh+BY6WCNHfIGvuVU3Tf9Db0g==
dependencies:
"@typescript-eslint/types" "8.8.1"
"@typescript-eslint/visitor-keys" "8.8.1"
"@typescript-eslint/types" "8.9.0"
"@typescript-eslint/visitor-keys" "8.9.0"
debug "^4.3.4"
fast-glob "^3.3.2"
is-glob "^4.0.3"
@ -969,22 +970,22 @@
semver "^7.6.0"
ts-api-utils "^1.3.0"
"@typescript-eslint/utils@8.8.1":
version "8.8.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.8.1.tgz#9e29480fbfa264c26946253daa72181f9f053c9d"
integrity sha512-/QkNJDbV0bdL7H7d0/y0qBbV2HTtf0TIyjSDTvvmQEzeVx8jEImEbLuOA4EsvE8gIgqMitns0ifb5uQhMj8d9w==
"@typescript-eslint/utils@8.9.0":
version "8.9.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.9.0.tgz#748bbe3ea5bee526d9786d9405cf1b0df081c299"
integrity sha512-PKgMmaSo/Yg/F7kIZvrgrWa1+Vwn036CdNUvYFEkYbPwOH4i8xvkaRlu148W3vtheWK9ckKRIz7PBP5oUlkrvQ==
dependencies:
"@eslint-community/eslint-utils" "^4.4.0"
"@typescript-eslint/scope-manager" "8.8.1"
"@typescript-eslint/types" "8.8.1"
"@typescript-eslint/typescript-estree" "8.8.1"
"@typescript-eslint/scope-manager" "8.9.0"
"@typescript-eslint/types" "8.9.0"
"@typescript-eslint/typescript-estree" "8.9.0"
"@typescript-eslint/visitor-keys@8.8.1":
version "8.8.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.8.1.tgz#0fb1280f381149fc345dfde29f7542ff4e587fc5"
integrity sha512-0/TdC3aeRAsW7MDvYRwEc1Uwm0TIBfzjPFgg60UU2Haj5qsCs9cc3zNgY71edqE3LbWfF/WoZQd3lJoDXFQpag==
"@typescript-eslint/visitor-keys@8.9.0":
version "8.9.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.9.0.tgz#5f11f4d9db913f37da42776893ffe0dd1ae78f78"
integrity sha512-Ht4y38ubk4L5/U8xKUBfKNYGmvKvA1CANoxiTRMM+tOLk3lbF3DvzZCxJCRSE+2GdCMSh6zq9VZJc3asc1XuAA==
dependencies:
"@typescript-eslint/types" "8.8.1"
"@typescript-eslint/types" "8.9.0"
eslint-visitor-keys "^3.4.3"
"@ungap/structured-clone@^1.2.0":
@ -2326,17 +2327,17 @@ ethers@^5.5.1:
"@ethersproject/web" "5.7.1"
"@ethersproject/wordlists" "5.7.0"
ethers@^6.13.3, ethers@^6.4.0:
version "6.13.3"
resolved "https://registry.yarnpkg.com/ethers/-/ethers-6.13.3.tgz#b87afdadb91cc8df5f56b9c59c96e5b206f4a600"
integrity sha512-/DzbZOLVtoO4fKvvQwpEucHAQgIwBGWuRvBdwE/lMXgXvvHHTSkn7XqAQ2b+gjJzZDJjWA9OD05bVceVOsBHbg==
ethers@^6.13.4:
version "6.13.4"
resolved "https://registry.yarnpkg.com/ethers/-/ethers-6.13.4.tgz#bd3e1c3dc1e7dc8ce10f9ffb4ee40967a651b53c"
integrity sha512-21YtnZVg4/zKkCQPjrDj38B1r4nQvTZLopUGMLQ1ePU2zV/joCfDC3t3iKQjWRzjjjbzR+mdAIoikeBRNkdllA==
dependencies:
"@adraffy/ens-normalize" "1.10.1"
"@noble/curves" "1.2.0"
"@noble/hashes" "1.3.2"
"@types/node" "18.15.13"
"@types/node" "22.7.5"
aes-js "4.0.0-beta.5"
tslib "2.4.0"
tslib "2.7.0"
ws "8.17.1"
events@^3.2.0:
@ -4331,21 +4332,16 @@ tsconfig-paths@^3.15.0:
minimist "^1.2.6"
strip-bom "^3.0.0"
tslib@2.4.0:
version "2.4.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3"
integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==
tslib@2.7.0, tslib@^2.6.2:
version "2.7.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.7.0.tgz#d9b40c5c40ab59e8738f297df3087bf1a2690c01"
integrity sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==
tslib@^1.9.0:
version "1.14.1"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
tslib@^2.6.2:
version "2.7.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.7.0.tgz#d9b40c5c40ab59e8738f297df3087bf1a2690c01"
integrity sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==
tweetnacl@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596"